~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/net/phy/marvell.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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/interrupt.h>
 
21
#include <linux/init.h>
 
22
#include <linux/delay.h>
 
23
#include <linux/netdevice.h>
 
24
#include <linux/etherdevice.h>
 
25
#include <linux/skbuff.h>
 
26
#include <linux/spinlock.h>
 
27
#include <linux/mm.h>
 
28
#include <linux/module.h>
 
29
#include <linux/mii.h>
 
30
#include <linux/ethtool.h>
 
31
#include <linux/phy.h>
 
32
#include <linux/marvell_phy.h>
 
33
#include <linux/of.h>
 
34
 
 
35
#include <asm/io.h>
 
36
#include <asm/irq.h>
 
37
#include <asm/uaccess.h>
 
38
 
 
39
#define MII_MARVELL_PHY_PAGE            22
 
40
 
 
41
#define MII_M1011_IEVENT                0x13
 
42
#define MII_M1011_IEVENT_CLEAR          0x0000
 
43
 
 
44
#define MII_M1011_IMASK                 0x12
 
45
#define MII_M1011_IMASK_INIT            0x6400
 
46
#define MII_M1011_IMASK_CLEAR           0x0000
 
47
 
 
48
#define MII_M1011_PHY_SCR               0x10
 
49
#define MII_M1011_PHY_SCR_AUTO_CROSS    0x0060
 
50
 
 
51
#define MII_M1145_PHY_EXT_CR            0x14
 
52
#define MII_M1145_RGMII_RX_DELAY        0x0080
 
53
#define MII_M1145_RGMII_TX_DELAY        0x0002
 
54
 
 
55
#define MII_M1111_PHY_LED_CONTROL       0x18
 
56
#define MII_M1111_PHY_LED_DIRECT        0x4100
 
57
#define MII_M1111_PHY_LED_COMBINE       0x411c
 
58
#define MII_M1111_PHY_EXT_CR            0x14
 
59
#define MII_M1111_RX_DELAY              0x80
 
60
#define MII_M1111_TX_DELAY              0x2
 
61
#define MII_M1111_PHY_EXT_SR            0x1b
 
62
 
 
63
#define MII_M1111_HWCFG_MODE_MASK               0xf
 
64
#define MII_M1111_HWCFG_MODE_COPPER_RGMII       0xb
 
65
#define MII_M1111_HWCFG_MODE_FIBER_RGMII        0x3
 
66
#define MII_M1111_HWCFG_MODE_SGMII_NO_CLK       0x4
 
67
#define MII_M1111_HWCFG_MODE_COPPER_RTBI        0x9
 
68
#define MII_M1111_HWCFG_FIBER_COPPER_AUTO       0x8000
 
69
#define MII_M1111_HWCFG_FIBER_COPPER_RES        0x2000
 
70
 
 
71
#define MII_M1111_COPPER                0
 
72
#define MII_M1111_FIBER                 1
 
73
 
 
74
#define MII_88E1121_PHY_MSCR_PAGE       2
 
75
#define MII_88E1121_PHY_MSCR_REG        21
 
76
#define MII_88E1121_PHY_MSCR_RX_DELAY   BIT(5)
 
77
#define MII_88E1121_PHY_MSCR_TX_DELAY   BIT(4)
 
78
#define MII_88E1121_PHY_MSCR_DELAY_MASK (~(0x3 << 4))
 
79
 
 
80
#define MII_88E1318S_PHY_MSCR1_REG      16
 
81
#define MII_88E1318S_PHY_MSCR1_PAD_ODD  BIT(6)
 
82
 
 
83
#define MII_88E1121_PHY_LED_CTRL        16
 
84
#define MII_88E1121_PHY_LED_PAGE        3
 
85
#define MII_88E1121_PHY_LED_DEF         0x0030
 
86
 
 
87
#define MII_M1011_PHY_STATUS            0x11
 
88
#define MII_M1011_PHY_STATUS_1000       0x8000
 
89
#define MII_M1011_PHY_STATUS_100        0x4000
 
90
#define MII_M1011_PHY_STATUS_SPD_MASK   0xc000
 
91
#define MII_M1011_PHY_STATUS_FULLDUPLEX 0x2000
 
92
#define MII_M1011_PHY_STATUS_RESOLVED   0x0800
 
93
#define MII_M1011_PHY_STATUS_LINK       0x0400
 
94
 
 
95
 
 
96
MODULE_DESCRIPTION("Marvell PHY driver");
 
97
MODULE_AUTHOR("Andy Fleming");
 
98
MODULE_LICENSE("GPL");
 
99
 
 
100
static int marvell_ack_interrupt(struct phy_device *phydev)
 
101
{
 
102
        int err;
 
103
 
 
104
        /* Clear the interrupts by reading the reg */
 
105
        err = phy_read(phydev, MII_M1011_IEVENT);
 
106
 
 
107
        if (err < 0)
 
108
                return err;
 
109
 
 
110
        return 0;
 
111
}
 
112
 
 
113
static int marvell_config_intr(struct phy_device *phydev)
 
114
{
 
115
        int err;
 
116
 
 
117
        if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
 
118
                err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
 
119
        else
 
120
                err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
 
121
 
 
122
        return err;
 
123
}
 
124
 
 
125
static int marvell_config_aneg(struct phy_device *phydev)
 
126
{
 
127
        int err;
 
128
 
 
129
        /* The Marvell PHY has an errata which requires
 
130
         * that certain registers get written in order
 
131
         * to restart autonegotiation */
 
132
        err = phy_write(phydev, MII_BMCR, BMCR_RESET);
 
133
 
 
134
        if (err < 0)
 
135
                return err;
 
136
 
 
137
        err = phy_write(phydev, 0x1d, 0x1f);
 
138
        if (err < 0)
 
139
                return err;
 
140
 
 
141
        err = phy_write(phydev, 0x1e, 0x200c);
 
142
        if (err < 0)
 
143
                return err;
 
144
 
 
145
        err = phy_write(phydev, 0x1d, 0x5);
 
146
        if (err < 0)
 
147
                return err;
 
148
 
 
149
        err = phy_write(phydev, 0x1e, 0);
 
150
        if (err < 0)
 
151
                return err;
 
152
 
 
153
        err = phy_write(phydev, 0x1e, 0x100);
 
154
        if (err < 0)
 
155
                return err;
 
156
 
 
157
        err = phy_write(phydev, MII_M1011_PHY_SCR,
 
158
                        MII_M1011_PHY_SCR_AUTO_CROSS);
 
159
        if (err < 0)
 
160
                return err;
 
161
 
 
162
        err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL,
 
163
                        MII_M1111_PHY_LED_DIRECT);
 
164
        if (err < 0)
 
165
                return err;
 
166
 
 
167
        err = genphy_config_aneg(phydev);
 
168
        if (err < 0)
 
169
                return err;
 
170
 
 
171
        if (phydev->autoneg != AUTONEG_ENABLE) {
 
172
                int bmcr;
 
173
 
 
174
                /*
 
175
                 * A write to speed/duplex bits (that is performed by
 
176
                 * genphy_config_aneg() call above) must be followed by
 
177
                 * a software reset. Otherwise, the write has no effect.
 
178
                 */
 
179
                bmcr = phy_read(phydev, MII_BMCR);
 
180
                if (bmcr < 0)
 
181
                        return bmcr;
 
182
 
 
183
                err = phy_write(phydev, MII_BMCR, bmcr | BMCR_RESET);
 
184
                if (err < 0)
 
185
                        return err;
 
186
        }
 
187
 
 
188
        return 0;
 
189
}
 
190
 
 
191
#ifdef CONFIG_OF_MDIO
 
192
/*
 
193
 * Set and/or override some configuration registers based on the
 
194
 * marvell,reg-init property stored in the of_node for the phydev.
 
195
 *
 
196
 * marvell,reg-init = <reg-page reg mask value>,...;
 
197
 *
 
198
 * There may be one or more sets of <reg-page reg mask value>:
 
199
 *
 
200
 * reg-page: which register bank to use.
 
201
 * reg: the register.
 
202
 * mask: if non-zero, ANDed with existing register value.
 
203
 * value: ORed with the masked value and written to the regiser.
 
204
 *
 
205
 */
 
206
static int marvell_of_reg_init(struct phy_device *phydev)
 
207
{
 
208
        const __be32 *paddr;
 
209
        int len, i, saved_page, current_page, page_changed, ret;
 
210
 
 
211
        if (!phydev->dev.of_node)
 
212
                return 0;
 
213
 
 
214
        paddr = of_get_property(phydev->dev.of_node, "marvell,reg-init", &len);
 
215
        if (!paddr || len < (4 * sizeof(*paddr)))
 
216
                return 0;
 
217
 
 
218
        saved_page = phy_read(phydev, MII_MARVELL_PHY_PAGE);
 
219
        if (saved_page < 0)
 
220
                return saved_page;
 
221
        page_changed = 0;
 
222
        current_page = saved_page;
 
223
 
 
224
        ret = 0;
 
225
        len /= sizeof(*paddr);
 
226
        for (i = 0; i < len - 3; i += 4) {
 
227
                u16 reg_page = be32_to_cpup(paddr + i);
 
228
                u16 reg = be32_to_cpup(paddr + i + 1);
 
229
                u16 mask = be32_to_cpup(paddr + i + 2);
 
230
                u16 val_bits = be32_to_cpup(paddr + i + 3);
 
231
                int val;
 
232
 
 
233
                if (reg_page != current_page) {
 
234
                        current_page = reg_page;
 
235
                        page_changed = 1;
 
236
                        ret = phy_write(phydev, MII_MARVELL_PHY_PAGE, reg_page);
 
237
                        if (ret < 0)
 
238
                                goto err;
 
239
                }
 
240
 
 
241
                val = 0;
 
242
                if (mask) {
 
243
                        val = phy_read(phydev, reg);
 
244
                        if (val < 0) {
 
245
                                ret = val;
 
246
                                goto err;
 
247
                        }
 
248
                        val &= mask;
 
249
                }
 
250
                val |= val_bits;
 
251
 
 
252
                ret = phy_write(phydev, reg, val);
 
253
                if (ret < 0)
 
254
                        goto err;
 
255
 
 
256
        }
 
257
err:
 
258
        if (page_changed) {
 
259
                i = phy_write(phydev, MII_MARVELL_PHY_PAGE, saved_page);
 
260
                if (ret == 0)
 
261
                        ret = i;
 
262
        }
 
263
        return ret;
 
264
}
 
265
#else
 
266
static int marvell_of_reg_init(struct phy_device *phydev)
 
267
{
 
268
        return 0;
 
269
}
 
270
#endif /* CONFIG_OF_MDIO */
 
271
 
 
272
static int m88e1121_config_aneg(struct phy_device *phydev)
 
273
{
 
274
        int err, oldpage, mscr;
 
275
 
 
276
        oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE);
 
277
 
 
278
        err = phy_write(phydev, MII_MARVELL_PHY_PAGE,
 
279
                        MII_88E1121_PHY_MSCR_PAGE);
 
280
        if (err < 0)
 
281
                return err;
 
282
 
 
283
        if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
 
284
            (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
 
285
            (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
 
286
            (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
 
287
 
 
288
                mscr = phy_read(phydev, MII_88E1121_PHY_MSCR_REG) &
 
289
                        MII_88E1121_PHY_MSCR_DELAY_MASK;
 
290
 
 
291
                if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
 
292
                        mscr |= (MII_88E1121_PHY_MSCR_RX_DELAY |
 
293
                                 MII_88E1121_PHY_MSCR_TX_DELAY);
 
294
                else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
 
295
                        mscr |= MII_88E1121_PHY_MSCR_RX_DELAY;
 
296
                else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
 
297
                        mscr |= MII_88E1121_PHY_MSCR_TX_DELAY;
 
298
 
 
299
                err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr);
 
300
                if (err < 0)
 
301
                        return err;
 
302
        }
 
303
 
 
304
        phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage);
 
305
 
 
306
        err = phy_write(phydev, MII_BMCR, BMCR_RESET);
 
307
        if (err < 0)
 
308
                return err;
 
309
 
 
310
        err = phy_write(phydev, MII_M1011_PHY_SCR,
 
311
                        MII_M1011_PHY_SCR_AUTO_CROSS);
 
312
        if (err < 0)
 
313
                return err;
 
314
 
 
315
        oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE);
 
316
 
 
317
        phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_88E1121_PHY_LED_PAGE);
 
318
        phy_write(phydev, MII_88E1121_PHY_LED_CTRL, MII_88E1121_PHY_LED_DEF);
 
319
        phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage);
 
320
 
 
321
        err = genphy_config_aneg(phydev);
 
322
 
 
323
        return err;
 
324
}
 
325
 
 
326
static int m88e1318_config_aneg(struct phy_device *phydev)
 
327
{
 
328
        int err, oldpage, mscr;
 
329
 
 
330
        oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE);
 
331
 
 
332
        err = phy_write(phydev, MII_MARVELL_PHY_PAGE,
 
333
                        MII_88E1121_PHY_MSCR_PAGE);
 
334
        if (err < 0)
 
335
                return err;
 
336
 
 
337
        mscr = phy_read(phydev, MII_88E1318S_PHY_MSCR1_REG);
 
338
        mscr |= MII_88E1318S_PHY_MSCR1_PAD_ODD;
 
339
 
 
340
        err = phy_write(phydev, MII_88E1318S_PHY_MSCR1_REG, mscr);
 
341
        if (err < 0)
 
342
                return err;
 
343
 
 
344
        err = phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage);
 
345
        if (err < 0)
 
346
                return err;
 
347
 
 
348
        return m88e1121_config_aneg(phydev);
 
349
}
 
350
 
 
351
static int m88e1111_config_init(struct phy_device *phydev)
 
352
{
 
353
        int err;
 
354
        int temp;
 
355
 
 
356
        /* Enable Fiber/Copper auto selection */
 
357
        temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
 
358
        temp &= ~MII_M1111_HWCFG_FIBER_COPPER_AUTO;
 
359
        phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
 
360
 
 
361
        temp = phy_read(phydev, MII_BMCR);
 
362
        temp |= BMCR_RESET;
 
363
        phy_write(phydev, MII_BMCR, temp);
 
364
 
 
365
        if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
 
366
            (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
 
367
            (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
 
368
            (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
 
369
 
 
370
                temp = phy_read(phydev, MII_M1111_PHY_EXT_CR);
 
371
                if (temp < 0)
 
372
                        return temp;
 
373
 
 
374
                if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
 
375
                        temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY);
 
376
                } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
 
377
                        temp &= ~MII_M1111_TX_DELAY;
 
378
                        temp |= MII_M1111_RX_DELAY;
 
379
                } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
 
380
                        temp &= ~MII_M1111_RX_DELAY;
 
381
                        temp |= MII_M1111_TX_DELAY;
 
382
                }
 
383
 
 
384
                err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp);
 
385
                if (err < 0)
 
386
                        return err;
 
387
 
 
388
                temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
 
389
                if (temp < 0)
 
390
                        return temp;
 
391
 
 
392
                temp &= ~(MII_M1111_HWCFG_MODE_MASK);
 
393
 
 
394
                if (temp & MII_M1111_HWCFG_FIBER_COPPER_RES)
 
395
                        temp |= MII_M1111_HWCFG_MODE_FIBER_RGMII;
 
396
                else
 
397
                        temp |= MII_M1111_HWCFG_MODE_COPPER_RGMII;
 
398
 
 
399
                err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
 
400
                if (err < 0)
 
401
                        return err;
 
402
        }
 
403
 
 
404
        if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
 
405
                temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
 
406
                if (temp < 0)
 
407
                        return temp;
 
408
 
 
409
                temp &= ~(MII_M1111_HWCFG_MODE_MASK);
 
410
                temp |= MII_M1111_HWCFG_MODE_SGMII_NO_CLK;
 
411
                temp |= MII_M1111_HWCFG_FIBER_COPPER_AUTO;
 
412
 
 
413
                err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
 
414
                if (err < 0)
 
415
                        return err;
 
416
        }
 
417
 
 
418
        if (phydev->interface == PHY_INTERFACE_MODE_RTBI) {
 
419
                temp = phy_read(phydev, MII_M1111_PHY_EXT_CR);
 
420
                if (temp < 0)
 
421
                        return temp;
 
422
                temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY);
 
423
                err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp);
 
424
                if (err < 0)
 
425
                        return err;
 
426
 
 
427
                temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
 
428
                if (temp < 0)
 
429
                        return temp;
 
430
                temp &= ~(MII_M1111_HWCFG_MODE_MASK | MII_M1111_HWCFG_FIBER_COPPER_RES);
 
431
                temp |= 0x7 | MII_M1111_HWCFG_FIBER_COPPER_AUTO;
 
432
                err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
 
433
                if (err < 0)
 
434
                        return err;
 
435
 
 
436
                /* soft reset */
 
437
                err = phy_write(phydev, MII_BMCR, BMCR_RESET);
 
438
                if (err < 0)
 
439
                        return err;
 
440
                do
 
441
                        temp = phy_read(phydev, MII_BMCR);
 
442
                while (temp & BMCR_RESET);
 
443
 
 
444
                temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
 
445
                if (temp < 0)
 
446
                        return temp;
 
447
                temp &= ~(MII_M1111_HWCFG_MODE_MASK | MII_M1111_HWCFG_FIBER_COPPER_RES);
 
448
                temp |= MII_M1111_HWCFG_MODE_COPPER_RTBI | MII_M1111_HWCFG_FIBER_COPPER_AUTO;
 
449
                err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
 
450
                if (err < 0)
 
451
                        return err;
 
452
        }
 
453
 
 
454
        err = marvell_of_reg_init(phydev);
 
455
        if (err < 0)
 
456
                return err;
 
457
 
 
458
        err = phy_write(phydev, MII_BMCR, BMCR_RESET);
 
459
        if (err < 0)
 
460
                return err;
 
461
 
 
462
        return 0;
 
463
}
 
464
 
 
465
static int m88e1118_config_aneg(struct phy_device *phydev)
 
466
{
 
467
        int err;
 
468
 
 
469
        err = phy_write(phydev, MII_BMCR, BMCR_RESET);
 
470
        if (err < 0)
 
471
                return err;
 
472
 
 
473
        err = phy_write(phydev, MII_M1011_PHY_SCR,
 
474
                        MII_M1011_PHY_SCR_AUTO_CROSS);
 
475
        if (err < 0)
 
476
                return err;
 
477
 
 
478
        err = genphy_config_aneg(phydev);
 
479
        return 0;
 
480
}
 
481
 
 
482
static int m88e1118_config_init(struct phy_device *phydev)
 
483
{
 
484
        int err;
 
485
 
 
486
        /* Change address */
 
487
        err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0002);
 
488
        if (err < 0)
 
489
                return err;
 
490
 
 
491
        /* Enable 1000 Mbit */
 
492
        err = phy_write(phydev, 0x15, 0x1070);
 
493
        if (err < 0)
 
494
                return err;
 
495
 
 
496
        /* Change address */
 
497
        err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0003);
 
498
        if (err < 0)
 
499
                return err;
 
500
 
 
501
        /* Adjust LED Control */
 
502
        if (phydev->dev_flags & MARVELL_PHY_M1118_DNS323_LEDS)
 
503
                err = phy_write(phydev, 0x10, 0x1100);
 
504
        else
 
505
                err = phy_write(phydev, 0x10, 0x021e);
 
506
        if (err < 0)
 
507
                return err;
 
508
 
 
509
        err = marvell_of_reg_init(phydev);
 
510
        if (err < 0)
 
511
                return err;
 
512
 
 
513
        /* Reset address */
 
514
        err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0);
 
515
        if (err < 0)
 
516
                return err;
 
517
 
 
518
        err = phy_write(phydev, MII_BMCR, BMCR_RESET);
 
519
        if (err < 0)
 
520
                return err;
 
521
 
 
522
        return 0;
 
523
}
 
524
 
 
525
static int m88e1149_config_init(struct phy_device *phydev)
 
526
{
 
527
        int err;
 
528
 
 
529
        /* Change address */
 
530
        err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0002);
 
531
        if (err < 0)
 
532
                return err;
 
533
 
 
534
        /* Enable 1000 Mbit */
 
535
        err = phy_write(phydev, 0x15, 0x1048);
 
536
        if (err < 0)
 
537
                return err;
 
538
 
 
539
        err = marvell_of_reg_init(phydev);
 
540
        if (err < 0)
 
541
                return err;
 
542
 
 
543
        /* Reset address */
 
544
        err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0);
 
545
        if (err < 0)
 
546
                return err;
 
547
 
 
548
        err = phy_write(phydev, MII_BMCR, BMCR_RESET);
 
549
        if (err < 0)
 
550
                return err;
 
551
 
 
552
        return 0;
 
553
}
 
554
 
 
555
static int m88e1145_config_init(struct phy_device *phydev)
 
556
{
 
557
        int err;
 
558
 
 
559
        /* Take care of errata E0 & E1 */
 
560
        err = phy_write(phydev, 0x1d, 0x001b);
 
561
        if (err < 0)
 
562
                return err;
 
563
 
 
564
        err = phy_write(phydev, 0x1e, 0x418f);
 
565
        if (err < 0)
 
566
                return err;
 
567
 
 
568
        err = phy_write(phydev, 0x1d, 0x0016);
 
569
        if (err < 0)
 
570
                return err;
 
571
 
 
572
        err = phy_write(phydev, 0x1e, 0xa2da);
 
573
        if (err < 0)
 
574
                return err;
 
575
 
 
576
        if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
 
577
                int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR);
 
578
                if (temp < 0)
 
579
                        return temp;
 
580
 
 
581
                temp |= (MII_M1145_RGMII_RX_DELAY | MII_M1145_RGMII_TX_DELAY);
 
582
 
 
583
                err = phy_write(phydev, MII_M1145_PHY_EXT_CR, temp);
 
584
                if (err < 0)
 
585
                        return err;
 
586
 
 
587
                if (phydev->dev_flags & MARVELL_PHY_M1145_FLAGS_RESISTANCE) {
 
588
                        err = phy_write(phydev, 0x1d, 0x0012);
 
589
                        if (err < 0)
 
590
                                return err;
 
591
 
 
592
                        temp = phy_read(phydev, 0x1e);
 
593
                        if (temp < 0)
 
594
                                return temp;
 
595
 
 
596
                        temp &= 0xf03f;
 
597
                        temp |= 2 << 9; /* 36 ohm */
 
598
                        temp |= 2 << 6; /* 39 ohm */
 
599
 
 
600
                        err = phy_write(phydev, 0x1e, temp);
 
601
                        if (err < 0)
 
602
                                return err;
 
603
 
 
604
                        err = phy_write(phydev, 0x1d, 0x3);
 
605
                        if (err < 0)
 
606
                                return err;
 
607
 
 
608
                        err = phy_write(phydev, 0x1e, 0x8000);
 
609
                        if (err < 0)
 
610
                                return err;
 
611
                }
 
612
        }
 
613
 
 
614
        err = marvell_of_reg_init(phydev);
 
615
        if (err < 0)
 
616
                return err;
 
617
 
 
618
        return 0;
 
619
}
 
620
 
 
621
/* marvell_read_status
 
622
 *
 
623
 * Generic status code does not detect Fiber correctly!
 
624
 * Description:
 
625
 *   Check the link, then figure out the current state
 
626
 *   by comparing what we advertise with what the link partner
 
627
 *   advertises.  Start by checking the gigabit possibilities,
 
628
 *   then move on to 10/100.
 
629
 */
 
630
static int marvell_read_status(struct phy_device *phydev)
 
631
{
 
632
        int adv;
 
633
        int err;
 
634
        int lpa;
 
635
        int status = 0;
 
636
 
 
637
        /* Update the link, but return if there
 
638
         * was an error */
 
639
        err = genphy_update_link(phydev);
 
640
        if (err)
 
641
                return err;
 
642
 
 
643
        if (AUTONEG_ENABLE == phydev->autoneg) {
 
644
                status = phy_read(phydev, MII_M1011_PHY_STATUS);
 
645
                if (status < 0)
 
646
                        return status;
 
647
 
 
648
                lpa = phy_read(phydev, MII_LPA);
 
649
                if (lpa < 0)
 
650
                        return lpa;
 
651
 
 
652
                adv = phy_read(phydev, MII_ADVERTISE);
 
653
                if (adv < 0)
 
654
                        return adv;
 
655
 
 
656
                lpa &= adv;
 
657
 
 
658
                if (status & MII_M1011_PHY_STATUS_FULLDUPLEX)
 
659
                        phydev->duplex = DUPLEX_FULL;
 
660
                else
 
661
                        phydev->duplex = DUPLEX_HALF;
 
662
 
 
663
                status = status & MII_M1011_PHY_STATUS_SPD_MASK;
 
664
                phydev->pause = phydev->asym_pause = 0;
 
665
 
 
666
                switch (status) {
 
667
                case MII_M1011_PHY_STATUS_1000:
 
668
                        phydev->speed = SPEED_1000;
 
669
                        break;
 
670
 
 
671
                case MII_M1011_PHY_STATUS_100:
 
672
                        phydev->speed = SPEED_100;
 
673
                        break;
 
674
 
 
675
                default:
 
676
                        phydev->speed = SPEED_10;
 
677
                        break;
 
678
                }
 
679
 
 
680
                if (phydev->duplex == DUPLEX_FULL) {
 
681
                        phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0;
 
682
                        phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0;
 
683
                }
 
684
        } else {
 
685
                int bmcr = phy_read(phydev, MII_BMCR);
 
686
 
 
687
                if (bmcr < 0)
 
688
                        return bmcr;
 
689
 
 
690
                if (bmcr & BMCR_FULLDPLX)
 
691
                        phydev->duplex = DUPLEX_FULL;
 
692
                else
 
693
                        phydev->duplex = DUPLEX_HALF;
 
694
 
 
695
                if (bmcr & BMCR_SPEED1000)
 
696
                        phydev->speed = SPEED_1000;
 
697
                else if (bmcr & BMCR_SPEED100)
 
698
                        phydev->speed = SPEED_100;
 
699
                else
 
700
                        phydev->speed = SPEED_10;
 
701
 
 
702
                phydev->pause = phydev->asym_pause = 0;
 
703
        }
 
704
 
 
705
        return 0;
 
706
}
 
707
 
 
708
static int m88e1121_did_interrupt(struct phy_device *phydev)
 
709
{
 
710
        int imask;
 
711
 
 
712
        imask = phy_read(phydev, MII_M1011_IEVENT);
 
713
 
 
714
        if (imask & MII_M1011_IMASK_INIT)
 
715
                return 1;
 
716
 
 
717
        return 0;
 
718
}
 
719
 
 
720
static struct phy_driver marvell_drivers[] = {
 
721
        {
 
722
                .phy_id = MARVELL_PHY_ID_88E1101,
 
723
                .phy_id_mask = MARVELL_PHY_ID_MASK,
 
724
                .name = "Marvell 88E1101",
 
725
                .features = PHY_GBIT_FEATURES,
 
726
                .flags = PHY_HAS_INTERRUPT,
 
727
                .config_aneg = &marvell_config_aneg,
 
728
                .read_status = &genphy_read_status,
 
729
                .ack_interrupt = &marvell_ack_interrupt,
 
730
                .config_intr = &marvell_config_intr,
 
731
                .driver = { .owner = THIS_MODULE },
 
732
        },
 
733
        {
 
734
                .phy_id = MARVELL_PHY_ID_88E1112,
 
735
                .phy_id_mask = MARVELL_PHY_ID_MASK,
 
736
                .name = "Marvell 88E1112",
 
737
                .features = PHY_GBIT_FEATURES,
 
738
                .flags = PHY_HAS_INTERRUPT,
 
739
                .config_init = &m88e1111_config_init,
 
740
                .config_aneg = &marvell_config_aneg,
 
741
                .read_status = &genphy_read_status,
 
742
                .ack_interrupt = &marvell_ack_interrupt,
 
743
                .config_intr = &marvell_config_intr,
 
744
                .driver = { .owner = THIS_MODULE },
 
745
        },
 
746
        {
 
747
                .phy_id = MARVELL_PHY_ID_88E1111,
 
748
                .phy_id_mask = MARVELL_PHY_ID_MASK,
 
749
                .name = "Marvell 88E1111",
 
750
                .features = PHY_GBIT_FEATURES,
 
751
                .flags = PHY_HAS_INTERRUPT,
 
752
                .config_init = &m88e1111_config_init,
 
753
                .config_aneg = &marvell_config_aneg,
 
754
                .read_status = &marvell_read_status,
 
755
                .ack_interrupt = &marvell_ack_interrupt,
 
756
                .config_intr = &marvell_config_intr,
 
757
                .driver = { .owner = THIS_MODULE },
 
758
        },
 
759
        {
 
760
                .phy_id = MARVELL_PHY_ID_88E1118,
 
761
                .phy_id_mask = MARVELL_PHY_ID_MASK,
 
762
                .name = "Marvell 88E1118",
 
763
                .features = PHY_GBIT_FEATURES,
 
764
                .flags = PHY_HAS_INTERRUPT,
 
765
                .config_init = &m88e1118_config_init,
 
766
                .config_aneg = &m88e1118_config_aneg,
 
767
                .read_status = &genphy_read_status,
 
768
                .ack_interrupt = &marvell_ack_interrupt,
 
769
                .config_intr = &marvell_config_intr,
 
770
                .driver = {.owner = THIS_MODULE,},
 
771
        },
 
772
        {
 
773
                .phy_id = MARVELL_PHY_ID_88E1121R,
 
774
                .phy_id_mask = MARVELL_PHY_ID_MASK,
 
775
                .name = "Marvell 88E1121R",
 
776
                .features = PHY_GBIT_FEATURES,
 
777
                .flags = PHY_HAS_INTERRUPT,
 
778
                .config_aneg = &m88e1121_config_aneg,
 
779
                .read_status = &marvell_read_status,
 
780
                .ack_interrupt = &marvell_ack_interrupt,
 
781
                .config_intr = &marvell_config_intr,
 
782
                .did_interrupt = &m88e1121_did_interrupt,
 
783
                .driver = { .owner = THIS_MODULE },
 
784
        },
 
785
        {
 
786
                .phy_id = MARVELL_PHY_ID_88E1318S,
 
787
                .phy_id_mask = MARVELL_PHY_ID_MASK,
 
788
                .name = "Marvell 88E1318S",
 
789
                .features = PHY_GBIT_FEATURES,
 
790
                .flags = PHY_HAS_INTERRUPT,
 
791
                .config_aneg = &m88e1318_config_aneg,
 
792
                .read_status = &marvell_read_status,
 
793
                .ack_interrupt = &marvell_ack_interrupt,
 
794
                .config_intr = &marvell_config_intr,
 
795
                .did_interrupt = &m88e1121_did_interrupt,
 
796
                .driver = { .owner = THIS_MODULE },
 
797
        },
 
798
        {
 
799
                .phy_id = MARVELL_PHY_ID_88E1145,
 
800
                .phy_id_mask = MARVELL_PHY_ID_MASK,
 
801
                .name = "Marvell 88E1145",
 
802
                .features = PHY_GBIT_FEATURES,
 
803
                .flags = PHY_HAS_INTERRUPT,
 
804
                .config_init = &m88e1145_config_init,
 
805
                .config_aneg = &marvell_config_aneg,
 
806
                .read_status = &genphy_read_status,
 
807
                .ack_interrupt = &marvell_ack_interrupt,
 
808
                .config_intr = &marvell_config_intr,
 
809
                .driver = { .owner = THIS_MODULE },
 
810
        },
 
811
        {
 
812
                .phy_id = MARVELL_PHY_ID_88E1149R,
 
813
                .phy_id_mask = MARVELL_PHY_ID_MASK,
 
814
                .name = "Marvell 88E1149R",
 
815
                .features = PHY_GBIT_FEATURES,
 
816
                .flags = PHY_HAS_INTERRUPT,
 
817
                .config_init = &m88e1149_config_init,
 
818
                .config_aneg = &m88e1118_config_aneg,
 
819
                .read_status = &genphy_read_status,
 
820
                .ack_interrupt = &marvell_ack_interrupt,
 
821
                .config_intr = &marvell_config_intr,
 
822
                .driver = { .owner = THIS_MODULE },
 
823
        },
 
824
        {
 
825
                .phy_id = MARVELL_PHY_ID_88E1240,
 
826
                .phy_id_mask = MARVELL_PHY_ID_MASK,
 
827
                .name = "Marvell 88E1240",
 
828
                .features = PHY_GBIT_FEATURES,
 
829
                .flags = PHY_HAS_INTERRUPT,
 
830
                .config_init = &m88e1111_config_init,
 
831
                .config_aneg = &marvell_config_aneg,
 
832
                .read_status = &genphy_read_status,
 
833
                .ack_interrupt = &marvell_ack_interrupt,
 
834
                .config_intr = &marvell_config_intr,
 
835
                .driver = { .owner = THIS_MODULE },
 
836
        },
 
837
};
 
838
 
 
839
static int __init marvell_init(void)
 
840
{
 
841
        int ret;
 
842
        int i;
 
843
 
 
844
        for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) {
 
845
                ret = phy_driver_register(&marvell_drivers[i]);
 
846
 
 
847
                if (ret) {
 
848
                        while (i-- > 0)
 
849
                                phy_driver_unregister(&marvell_drivers[i]);
 
850
                        return ret;
 
851
                }
 
852
        }
 
853
 
 
854
        return 0;
 
855
}
 
856
 
 
857
static void __exit marvell_exit(void)
 
858
{
 
859
        int i;
 
860
 
 
861
        for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++)
 
862
                phy_driver_unregister(&marvell_drivers[i]);
 
863
}
 
864
 
 
865
module_init(marvell_init);
 
866
module_exit(marvell_exit);
 
867
 
 
868
static struct mdio_device_id __maybe_unused marvell_tbl[] = {
 
869
        { 0x01410c60, 0xfffffff0 },
 
870
        { 0x01410c90, 0xfffffff0 },
 
871
        { 0x01410cc0, 0xfffffff0 },
 
872
        { 0x01410e10, 0xfffffff0 },
 
873
        { 0x01410cb0, 0xfffffff0 },
 
874
        { 0x01410cd0, 0xfffffff0 },
 
875
        { 0x01410e50, 0xfffffff0 },
 
876
        { 0x01410e30, 0xfffffff0 },
 
877
        { 0x01410e90, 0xfffffff0 },
 
878
        { }
 
879
};
 
880
 
 
881
MODULE_DEVICE_TABLE(mdio, marvell_tbl);