1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Marvell 88e6xxx Ethernet switch PHY and PPU support
5 * Copyright (c) 2008 Marvell Semiconductor
7 * Copyright (c) 2017 Andrew Lunn <andrew@lunn.ch>
10 #include <linux/mdio.h>
11 #include <linux/module.h>
16 int mv88e6165_phy_read(struct mv88e6xxx_chip
*chip
, struct mii_bus
*bus
,
17 int addr
, int reg
, u16
*val
)
19 return mv88e6xxx_read(chip
, addr
, reg
, val
);
22 int mv88e6165_phy_write(struct mv88e6xxx_chip
*chip
, struct mii_bus
*bus
,
23 int addr
, int reg
, u16 val
)
25 return mv88e6xxx_write(chip
, addr
, reg
, val
);
28 int mv88e6xxx_phy_read(struct mv88e6xxx_chip
*chip
, int phy
, int reg
, u16
*val
)
30 int addr
= phy
; /* PHY devices addresses start at 0x0 */
33 bus
= mv88e6xxx_default_mdio_bus(chip
);
37 if (!chip
->info
->ops
->phy_read
)
40 return chip
->info
->ops
->phy_read(chip
, bus
, addr
, reg
, val
);
43 int mv88e6xxx_phy_write(struct mv88e6xxx_chip
*chip
, int phy
, int reg
, u16 val
)
45 int addr
= phy
; /* PHY devices addresses start at 0x0 */
48 bus
= mv88e6xxx_default_mdio_bus(chip
);
52 if (!chip
->info
->ops
->phy_write
)
55 return chip
->info
->ops
->phy_write(chip
, bus
, addr
, reg
, val
);
58 int mv88e6xxx_phy_read_c45(struct mv88e6xxx_chip
*chip
, int phy
, int devad
,
61 int addr
= phy
; /* PHY devices addresses start at 0x0 */
64 bus
= mv88e6xxx_default_mdio_bus(chip
);
68 if (!chip
->info
->ops
->phy_read_c45
)
71 return chip
->info
->ops
->phy_read_c45(chip
, bus
, addr
, devad
, reg
, val
);
74 int mv88e6xxx_phy_write_c45(struct mv88e6xxx_chip
*chip
, int phy
, int devad
,
77 int addr
= phy
; /* PHY devices addresses start at 0x0 */
80 bus
= mv88e6xxx_default_mdio_bus(chip
);
84 if (!chip
->info
->ops
->phy_write_c45
)
87 return chip
->info
->ops
->phy_write_c45(chip
, bus
, addr
, devad
, reg
, val
);
90 static int mv88e6xxx_phy_page_get(struct mv88e6xxx_chip
*chip
, int phy
, u8 page
)
92 return mv88e6xxx_phy_write(chip
, phy
, MV88E6XXX_PHY_PAGE
, page
);
95 static void mv88e6xxx_phy_page_put(struct mv88e6xxx_chip
*chip
, int phy
)
99 /* Restore PHY page Copper 0x0 for access via the registered
102 err
= mv88e6xxx_phy_write(chip
, phy
, MV88E6XXX_PHY_PAGE
,
103 MV88E6XXX_PHY_PAGE_COPPER
);
106 "failed to restore PHY %d page Copper (%d)\n",
111 int mv88e6xxx_phy_page_read(struct mv88e6xxx_chip
*chip
, int phy
,
112 u8 page
, int reg
, u16
*val
)
116 /* There is no paging for registers 22 */
117 if (reg
== MV88E6XXX_PHY_PAGE
)
120 err
= mv88e6xxx_phy_page_get(chip
, phy
, page
);
122 err
= mv88e6xxx_phy_read(chip
, phy
, reg
, val
);
123 mv88e6xxx_phy_page_put(chip
, phy
);
129 int mv88e6xxx_phy_page_write(struct mv88e6xxx_chip
*chip
, int phy
,
130 u8 page
, int reg
, u16 val
)
134 /* There is no paging for registers 22 */
135 if (reg
== MV88E6XXX_PHY_PAGE
)
138 err
= mv88e6xxx_phy_page_get(chip
, phy
, page
);
140 err
= mv88e6xxx_phy_write(chip
, phy
, MV88E6XXX_PHY_PAGE
, page
);
142 err
= mv88e6xxx_phy_write(chip
, phy
, reg
, val
);
144 mv88e6xxx_phy_page_put(chip
, phy
);
150 static int mv88e6xxx_phy_ppu_disable(struct mv88e6xxx_chip
*chip
)
152 if (!chip
->info
->ops
->ppu_disable
)
155 return chip
->info
->ops
->ppu_disable(chip
);
158 static int mv88e6xxx_phy_ppu_enable(struct mv88e6xxx_chip
*chip
)
160 if (!chip
->info
->ops
->ppu_enable
)
163 return chip
->info
->ops
->ppu_enable(chip
);
166 static void mv88e6xxx_phy_ppu_reenable_work(struct work_struct
*ugly
)
168 struct mv88e6xxx_chip
*chip
;
170 chip
= container_of(ugly
, struct mv88e6xxx_chip
, ppu_work
);
172 mv88e6xxx_reg_lock(chip
);
174 if (mutex_trylock(&chip
->ppu_mutex
)) {
175 if (mv88e6xxx_phy_ppu_enable(chip
) == 0)
176 chip
->ppu_disabled
= 0;
177 mutex_unlock(&chip
->ppu_mutex
);
180 mv88e6xxx_reg_unlock(chip
);
183 static void mv88e6xxx_phy_ppu_reenable_timer(struct timer_list
*t
)
185 struct mv88e6xxx_chip
*chip
= from_timer(chip
, t
, ppu_timer
);
187 schedule_work(&chip
->ppu_work
);
190 static int mv88e6xxx_phy_ppu_access_get(struct mv88e6xxx_chip
*chip
)
194 mutex_lock(&chip
->ppu_mutex
);
196 /* If the PHY polling unit is enabled, disable it so that
197 * we can access the PHY registers. If it was already
198 * disabled, cancel the timer that is going to re-enable
201 if (!chip
->ppu_disabled
) {
202 ret
= mv88e6xxx_phy_ppu_disable(chip
);
204 mutex_unlock(&chip
->ppu_mutex
);
207 chip
->ppu_disabled
= 1;
209 del_timer(&chip
->ppu_timer
);
216 static void mv88e6xxx_phy_ppu_access_put(struct mv88e6xxx_chip
*chip
)
218 /* Schedule a timer to re-enable the PHY polling unit. */
219 mod_timer(&chip
->ppu_timer
, jiffies
+ msecs_to_jiffies(10));
220 mutex_unlock(&chip
->ppu_mutex
);
223 static void mv88e6xxx_phy_ppu_state_init(struct mv88e6xxx_chip
*chip
)
225 mutex_init(&chip
->ppu_mutex
);
226 INIT_WORK(&chip
->ppu_work
, mv88e6xxx_phy_ppu_reenable_work
);
227 timer_setup(&chip
->ppu_timer
, mv88e6xxx_phy_ppu_reenable_timer
, 0);
230 static void mv88e6xxx_phy_ppu_state_destroy(struct mv88e6xxx_chip
*chip
)
232 del_timer_sync(&chip
->ppu_timer
);
235 int mv88e6185_phy_ppu_read(struct mv88e6xxx_chip
*chip
, struct mii_bus
*bus
,
236 int addr
, int reg
, u16
*val
)
240 err
= mv88e6xxx_phy_ppu_access_get(chip
);
242 err
= mv88e6xxx_read(chip
, addr
, reg
, val
);
243 mv88e6xxx_phy_ppu_access_put(chip
);
249 int mv88e6185_phy_ppu_write(struct mv88e6xxx_chip
*chip
, struct mii_bus
*bus
,
250 int addr
, int reg
, u16 val
)
254 err
= mv88e6xxx_phy_ppu_access_get(chip
);
256 err
= mv88e6xxx_write(chip
, addr
, reg
, val
);
257 mv88e6xxx_phy_ppu_access_put(chip
);
263 void mv88e6xxx_phy_init(struct mv88e6xxx_chip
*chip
)
265 if (chip
->info
->ops
->ppu_enable
&& chip
->info
->ops
->ppu_disable
)
266 mv88e6xxx_phy_ppu_state_init(chip
);
269 void mv88e6xxx_phy_destroy(struct mv88e6xxx_chip
*chip
)
271 if (chip
->info
->ops
->ppu_enable
&& chip
->info
->ops
->ppu_disable
)
272 mv88e6xxx_phy_ppu_state_destroy(chip
);
275 int mv88e6xxx_phy_setup(struct mv88e6xxx_chip
*chip
)
277 return mv88e6xxx_phy_ppu_enable(chip
);