OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [net/] [phy/] [marvell.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * drivers/net/phy/marvell.c
3
 *
4
 * Driver for Marvell PHYs
5
 *
6
 * Author: Andy Fleming
7
 *
8
 * Copyright (c) 2004 Freescale Semiconductor, Inc.
9
 *
10
 * This program is free software; you can redistribute  it and/or modify it
11
 * under  the terms of  the GNU General  Public License as published by the
12
 * Free Software Foundation;  either version 2 of the  License, or (at your
13
 * option) any later version.
14
 *
15
 */
16
#include <linux/kernel.h>
17
#include <linux/string.h>
18
#include <linux/errno.h>
19
#include <linux/unistd.h>
20
#include <linux/slab.h>
21
#include <linux/interrupt.h>
22
#include <linux/init.h>
23
#include <linux/delay.h>
24
#include <linux/netdevice.h>
25
#include <linux/etherdevice.h>
26
#include <linux/skbuff.h>
27
#include <linux/spinlock.h>
28
#include <linux/mm.h>
29
#include <linux/module.h>
30
#include <linux/mii.h>
31
#include <linux/ethtool.h>
32
#include <linux/phy.h>
33
 
34
#include <asm/io.h>
35
#include <asm/irq.h>
36
#include <asm/uaccess.h>
37
 
38
#define MII_M1011_IEVENT                0x13
39
#define MII_M1011_IEVENT_CLEAR          0x0000
40
 
41
#define MII_M1011_IMASK                 0x12
42
#define MII_M1011_IMASK_INIT            0x6400
43
#define MII_M1011_IMASK_CLEAR           0x0000
44
 
45
#define MII_M1011_PHY_SCR               0x10
46
#define MII_M1011_PHY_SCR_AUTO_CROSS    0x0060
47
 
48
#define MII_M1145_PHY_EXT_CR            0x14
49
#define MII_M1145_RGMII_RX_DELAY        0x0080
50
#define MII_M1145_RGMII_TX_DELAY        0x0002
51
 
52
#define M1145_DEV_FLAGS_RESISTANCE      0x00000001
53
 
54
#define MII_M1111_PHY_LED_CONTROL       0x18
55
#define MII_M1111_PHY_LED_DIRECT        0x4100
56
#define MII_M1111_PHY_LED_COMBINE       0x411c
57
#define MII_M1111_PHY_EXT_CR            0x14
58
#define MII_M1111_RX_DELAY              0x80
59
#define MII_M1111_TX_DELAY              0x2
60
#define MII_M1111_PHY_EXT_SR            0x1b
61
#define MII_M1111_HWCFG_MODE_MASK       0xf
62
#define MII_M1111_HWCFG_MODE_RGMII      0xb
63
#define MII_M1111_HWCFG_MODE_SGMII_NO_CLK       0x4
64
 
65
MODULE_DESCRIPTION("Marvell PHY driver");
66
MODULE_AUTHOR("Andy Fleming");
67
MODULE_LICENSE("GPL");
68
 
69
static int marvell_ack_interrupt(struct phy_device *phydev)
70
{
71
        int err;
72
 
73
        /* Clear the interrupts by reading the reg */
74
        err = phy_read(phydev, MII_M1011_IEVENT);
75
 
76
        if (err < 0)
77
                return err;
78
 
79
        return 0;
80
}
81
 
82
static int marvell_config_intr(struct phy_device *phydev)
83
{
84
        int err;
85
 
86
        if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
87
                err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
88
        else
89
                err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
90
 
91
        return err;
92
}
93
 
94
static int marvell_config_aneg(struct phy_device *phydev)
95
{
96
        int err;
97
 
98
        /* The Marvell PHY has an errata which requires
99
         * that certain registers get written in order
100
         * to restart autonegotiation */
101
        err = phy_write(phydev, MII_BMCR, BMCR_RESET);
102
 
103
        if (err < 0)
104
                return err;
105
 
106
        err = phy_write(phydev, 0x1d, 0x1f);
107
        if (err < 0)
108
                return err;
109
 
110
        err = phy_write(phydev, 0x1e, 0x200c);
111
        if (err < 0)
112
                return err;
113
 
114
        err = phy_write(phydev, 0x1d, 0x5);
115
        if (err < 0)
116
                return err;
117
 
118
        err = phy_write(phydev, 0x1e, 0);
119
        if (err < 0)
120
                return err;
121
 
122
        err = phy_write(phydev, 0x1e, 0x100);
123
        if (err < 0)
124
                return err;
125
 
126
        err = phy_write(phydev, MII_M1011_PHY_SCR,
127
                        MII_M1011_PHY_SCR_AUTO_CROSS);
128
        if (err < 0)
129
                return err;
130
 
131
        err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL,
132
                        MII_M1111_PHY_LED_DIRECT);
133
        if (err < 0)
134
                return err;
135
 
136
        err = genphy_config_aneg(phydev);
137
 
138
        return err;
139
}
140
 
141
static int m88e1111_config_init(struct phy_device *phydev)
142
{
143
        int err;
144
 
145
        if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
146
            (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
147
            (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
148
            (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
149
                int temp;
150
 
151
                temp = phy_read(phydev, MII_M1111_PHY_EXT_CR);
152
                if (temp < 0)
153
                        return temp;
154
 
155
                if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
156
                        temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY);
157
                } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
158
                        temp &= ~MII_M1111_TX_DELAY;
159
                        temp |= MII_M1111_RX_DELAY;
160
                } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
161
                        temp &= ~MII_M1111_RX_DELAY;
162
                        temp |= MII_M1111_TX_DELAY;
163
                }
164
 
165
                err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp);
166
                if (err < 0)
167
                        return err;
168
 
169
                temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
170
                if (temp < 0)
171
                        return temp;
172
 
173
                temp &= ~(MII_M1111_HWCFG_MODE_MASK);
174
                temp |= MII_M1111_HWCFG_MODE_RGMII;
175
 
176
                err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
177
                if (err < 0)
178
                        return err;
179
        }
180
 
181
        if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
182
                int temp;
183
 
184
                temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
185
                if (temp < 0)
186
                        return temp;
187
 
188
                temp &= ~(MII_M1111_HWCFG_MODE_MASK);
189
                temp |= MII_M1111_HWCFG_MODE_SGMII_NO_CLK;
190
 
191
                err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
192
                if (err < 0)
193
                        return err;
194
        }
195
 
196
        err = phy_write(phydev, MII_BMCR, BMCR_RESET);
197
        if (err < 0)
198
                return err;
199
 
200
        return 0;
201
}
202
 
203
static int m88e1145_config_init(struct phy_device *phydev)
204
{
205
        int err;
206
 
207
        /* Take care of errata E0 & E1 */
208
        err = phy_write(phydev, 0x1d, 0x001b);
209
        if (err < 0)
210
                return err;
211
 
212
        err = phy_write(phydev, 0x1e, 0x418f);
213
        if (err < 0)
214
                return err;
215
 
216
        err = phy_write(phydev, 0x1d, 0x0016);
217
        if (err < 0)
218
                return err;
219
 
220
        err = phy_write(phydev, 0x1e, 0xa2da);
221
        if (err < 0)
222
                return err;
223
 
224
        if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
225
                int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR);
226
                if (temp < 0)
227
                        return temp;
228
 
229
                temp |= (MII_M1145_RGMII_RX_DELAY | MII_M1145_RGMII_TX_DELAY);
230
 
231
                err = phy_write(phydev, MII_M1145_PHY_EXT_CR, temp);
232
                if (err < 0)
233
                        return err;
234
 
235
                if (phydev->dev_flags & M1145_DEV_FLAGS_RESISTANCE) {
236
                        err = phy_write(phydev, 0x1d, 0x0012);
237
                        if (err < 0)
238
                                return err;
239
 
240
                        temp = phy_read(phydev, 0x1e);
241
                        if (temp < 0)
242
                                return temp;
243
 
244
                        temp &= 0xf03f;
245
                        temp |= 2 << 9; /* 36 ohm */
246
                        temp |= 2 << 6; /* 39 ohm */
247
 
248
                        err = phy_write(phydev, 0x1e, temp);
249
                        if (err < 0)
250
                                return err;
251
 
252
                        err = phy_write(phydev, 0x1d, 0x3);
253
                        if (err < 0)
254
                                return err;
255
 
256
                        err = phy_write(phydev, 0x1e, 0x8000);
257
                        if (err < 0)
258
                                return err;
259
                }
260
        }
261
 
262
        return 0;
263
}
264
 
265
static struct phy_driver marvell_drivers[] = {
266
        {
267
                .phy_id = 0x01410c60,
268
                .phy_id_mask = 0xfffffff0,
269
                .name = "Marvell 88E1101",
270
                .features = PHY_GBIT_FEATURES,
271
                .flags = PHY_HAS_INTERRUPT,
272
                .config_aneg = &marvell_config_aneg,
273
                .read_status = &genphy_read_status,
274
                .ack_interrupt = &marvell_ack_interrupt,
275
                .config_intr = &marvell_config_intr,
276
                .driver = { .owner = THIS_MODULE },
277
        },
278
        {
279
                .phy_id = 0x01410c90,
280
                .phy_id_mask = 0xfffffff0,
281
                .name = "Marvell 88E1112",
282
                .features = PHY_GBIT_FEATURES,
283
                .flags = PHY_HAS_INTERRUPT,
284
                .config_init = &m88e1111_config_init,
285
                .config_aneg = &marvell_config_aneg,
286
                .read_status = &genphy_read_status,
287
                .ack_interrupt = &marvell_ack_interrupt,
288
                .config_intr = &marvell_config_intr,
289
                .driver = { .owner = THIS_MODULE },
290
        },
291
        {
292
                .phy_id = 0x01410cc0,
293
                .phy_id_mask = 0xfffffff0,
294
                .name = "Marvell 88E1111",
295
                .features = PHY_GBIT_FEATURES,
296
                .flags = PHY_HAS_INTERRUPT,
297
                .config_init = &m88e1111_config_init,
298
                .config_aneg = &marvell_config_aneg,
299
                .read_status = &genphy_read_status,
300
                .ack_interrupt = &marvell_ack_interrupt,
301
                .config_intr = &marvell_config_intr,
302
                .driver = { .owner = THIS_MODULE },
303
        },
304
        {
305
                .phy_id = 0x01410cd0,
306
                .phy_id_mask = 0xfffffff0,
307
                .name = "Marvell 88E1145",
308
                .features = PHY_GBIT_FEATURES,
309
                .flags = PHY_HAS_INTERRUPT,
310
                .config_init = &m88e1145_config_init,
311
                .config_aneg = &marvell_config_aneg,
312
                .read_status = &genphy_read_status,
313
                .ack_interrupt = &marvell_ack_interrupt,
314
                .config_intr = &marvell_config_intr,
315
                .driver = { .owner = THIS_MODULE },
316
        },
317
        {
318
                .phy_id = 0x01410e30,
319
                .phy_id_mask = 0xfffffff0,
320
                .name = "Marvell 88E1240",
321
                .features = PHY_GBIT_FEATURES,
322
                .flags = PHY_HAS_INTERRUPT,
323
                .config_init = &m88e1111_config_init,
324
                .config_aneg = &marvell_config_aneg,
325
                .read_status = &genphy_read_status,
326
                .ack_interrupt = &marvell_ack_interrupt,
327
                .config_intr = &marvell_config_intr,
328
                .driver = { .owner = THIS_MODULE },
329
        },
330
};
331
 
332
static int __init marvell_init(void)
333
{
334
        int ret;
335
        int i;
336
 
337
        for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) {
338
                ret = phy_driver_register(&marvell_drivers[i]);
339
 
340
                if (ret) {
341
                        while (i-- > 0)
342
                                phy_driver_unregister(&marvell_drivers[i]);
343
                        return ret;
344
                }
345
        }
346
 
347
        return 0;
348
}
349
 
350
static void __exit marvell_exit(void)
351
{
352
        int i;
353
 
354
        for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++)
355
                phy_driver_unregister(&marvell_drivers[i]);
356
}
357
 
358
module_init(marvell_init);
359
module_exit(marvell_exit);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.