2 * Marvell 88e6xxx Ethernet switch PHY and PPU support
4 * Copyright (c) 2008 Marvell Semiconductor
6 * Copyright (c) 2017 Andrew Lunn <andrew@lunn.ch>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
14 #include <linux/mdio.h>
15 #include <linux/module.h>
18 #include "mv88e6xxx.h"
21 int mv88e6165_phy_read(struct mv88e6xxx_chip
*chip
, struct mii_bus
*bus
,
22 int addr
, int reg
, u16
*val
)
24 return mv88e6xxx_read(chip
, addr
, reg
, val
);
27 int mv88e6165_phy_write(struct mv88e6xxx_chip
*chip
, struct mii_bus
*bus
,
28 int addr
, int reg
, u16 val
)
30 return mv88e6xxx_write(chip
, addr
, reg
, val
);
33 int mv88e6xxx_phy_read(struct mv88e6xxx_chip
*chip
, int phy
, int reg
, u16
*val
)
35 int addr
= phy
; /* PHY devices addresses start at 0x0 */
38 bus
= mv88e6xxx_default_mdio_bus(chip
);
42 if (!chip
->info
->ops
->phy_read
)
45 return chip
->info
->ops
->phy_read(chip
, bus
, addr
, reg
, val
);
48 int mv88e6xxx_phy_write(struct mv88e6xxx_chip
*chip
, int phy
, int reg
, u16 val
)
50 int addr
= phy
; /* PHY devices addresses start at 0x0 */
53 bus
= mv88e6xxx_default_mdio_bus(chip
);
57 if (!chip
->info
->ops
->phy_write
)
60 return chip
->info
->ops
->phy_write(chip
, bus
, addr
, reg
, val
);
63 static int mv88e6xxx_phy_page_get(struct mv88e6xxx_chip
*chip
, int phy
, u8 page
)
65 return mv88e6xxx_phy_write(chip
, phy
, PHY_PAGE
, page
);
68 static void mv88e6xxx_phy_page_put(struct mv88e6xxx_chip
*chip
, int phy
)
72 /* Restore PHY page Copper 0x0 for access via the registered
75 err
= mv88e6xxx_phy_write(chip
, phy
, PHY_PAGE
, PHY_PAGE_COPPER
);
78 "failed to restore PHY %d page Copper (%d)\n",
83 int mv88e6xxx_phy_page_read(struct mv88e6xxx_chip
*chip
, int phy
,
84 u8 page
, int reg
, u16
*val
)
88 /* There is no paging for registers 22 */
92 err
= mv88e6xxx_phy_page_get(chip
, phy
, page
);
94 err
= mv88e6xxx_phy_read(chip
, phy
, reg
, val
);
95 mv88e6xxx_phy_page_put(chip
, phy
);
101 int mv88e6xxx_phy_page_write(struct mv88e6xxx_chip
*chip
, int phy
,
102 u8 page
, int reg
, u16 val
)
106 /* There is no paging for registers 22 */
110 err
= mv88e6xxx_phy_page_get(chip
, phy
, page
);
112 err
= mv88e6xxx_phy_write(chip
, phy
, PHY_PAGE
, page
);
113 mv88e6xxx_phy_page_put(chip
, phy
);
119 static int mv88e6xxx_phy_ppu_disable(struct mv88e6xxx_chip
*chip
)
121 if (!chip
->info
->ops
->ppu_disable
)
124 return chip
->info
->ops
->ppu_disable(chip
);
127 static int mv88e6xxx_phy_ppu_enable(struct mv88e6xxx_chip
*chip
)
129 if (!chip
->info
->ops
->ppu_enable
)
132 return chip
->info
->ops
->ppu_enable(chip
);
135 static void mv88e6xxx_phy_ppu_reenable_work(struct work_struct
*ugly
)
137 struct mv88e6xxx_chip
*chip
;
139 chip
= container_of(ugly
, struct mv88e6xxx_chip
, ppu_work
);
141 mutex_lock(&chip
->reg_lock
);
143 if (mutex_trylock(&chip
->ppu_mutex
)) {
144 if (mv88e6xxx_phy_ppu_enable(chip
) == 0)
145 chip
->ppu_disabled
= 0;
146 mutex_unlock(&chip
->ppu_mutex
);
149 mutex_unlock(&chip
->reg_lock
);
152 static void mv88e6xxx_phy_ppu_reenable_timer(unsigned long _ps
)
154 struct mv88e6xxx_chip
*chip
= (void *)_ps
;
156 schedule_work(&chip
->ppu_work
);
159 static int mv88e6xxx_phy_ppu_access_get(struct mv88e6xxx_chip
*chip
)
163 mutex_lock(&chip
->ppu_mutex
);
165 /* If the PHY polling unit is enabled, disable it so that
166 * we can access the PHY registers. If it was already
167 * disabled, cancel the timer that is going to re-enable
170 if (!chip
->ppu_disabled
) {
171 ret
= mv88e6xxx_phy_ppu_disable(chip
);
173 mutex_unlock(&chip
->ppu_mutex
);
176 chip
->ppu_disabled
= 1;
178 del_timer(&chip
->ppu_timer
);
185 static void mv88e6xxx_phy_ppu_access_put(struct mv88e6xxx_chip
*chip
)
187 /* Schedule a timer to re-enable the PHY polling unit. */
188 mod_timer(&chip
->ppu_timer
, jiffies
+ msecs_to_jiffies(10));
189 mutex_unlock(&chip
->ppu_mutex
);
192 static void mv88e6xxx_phy_ppu_state_init(struct mv88e6xxx_chip
*chip
)
194 mutex_init(&chip
->ppu_mutex
);
195 INIT_WORK(&chip
->ppu_work
, mv88e6xxx_phy_ppu_reenable_work
);
196 setup_timer(&chip
->ppu_timer
, mv88e6xxx_phy_ppu_reenable_timer
,
197 (unsigned long)chip
);
200 static void mv88e6xxx_phy_ppu_state_destroy(struct mv88e6xxx_chip
*chip
)
202 del_timer_sync(&chip
->ppu_timer
);
205 int mv88e6185_phy_ppu_read(struct mv88e6xxx_chip
*chip
, struct mii_bus
*bus
,
206 int addr
, int reg
, u16
*val
)
210 err
= mv88e6xxx_phy_ppu_access_get(chip
);
212 err
= mv88e6xxx_read(chip
, addr
, reg
, val
);
213 mv88e6xxx_phy_ppu_access_put(chip
);
219 int mv88e6185_phy_ppu_write(struct mv88e6xxx_chip
*chip
, struct mii_bus
*bus
,
220 int addr
, int reg
, u16 val
)
224 err
= mv88e6xxx_phy_ppu_access_get(chip
);
226 err
= mv88e6xxx_write(chip
, addr
, reg
, val
);
227 mv88e6xxx_phy_ppu_access_put(chip
);
233 void mv88e6xxx_phy_init(struct mv88e6xxx_chip
*chip
)
235 if (chip
->info
->ops
->ppu_enable
&& chip
->info
->ops
->ppu_disable
)
236 mv88e6xxx_phy_ppu_state_init(chip
);
239 void mv88e6xxx_phy_destroy(struct mv88e6xxx_chip
*chip
)
241 if (chip
->info
->ops
->ppu_enable
&& chip
->info
->ops
->ppu_disable
)
242 mv88e6xxx_phy_ppu_state_destroy(chip
);
245 int mv88e6xxx_phy_setup(struct mv88e6xxx_chip
*chip
)
247 return mv88e6xxx_phy_ppu_enable(chip
);