2 * Atheros AR71xx built-in ethernet mac driver
4 * Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org>
5 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
7 * Based on Atheros' AG7100 driver
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published
11 * by the Free Software Foundation.
16 #define AG71XX_MII_RETRY 1000
17 #define AG71XX_MII_DELAY 5
19 static inline void ag71xx_mii_ctrl_wr(struct ag71xx *ag, u32 value)
21 __raw_writel(value, ag->mii_ctrl);
24 static inline u32 ag71xx_mii_ctrl_rr(struct ag71xx *ag)
26 return __raw_readl(ag->mii_ctrl);
29 void ag71xx_mii_ctrl_set_if(struct ag71xx *ag, unsigned int mii_if)
33 t = ag71xx_mii_ctrl_rr(ag);
36 ag71xx_mii_ctrl_wr(ag, t);
39 void ag71xx_mii_ctrl_set_speed(struct ag71xx *ag, unsigned int speed)
43 t = ag71xx_mii_ctrl_rr(ag);
45 t |= (speed & 0x3) << 4;
46 ag71xx_mii_ctrl_wr(ag, t);
49 static int ag71xx_mii_read(struct ag71xx *ag, int addr, int reg)
54 ag71xx_wr(ag, AG71XX_REG_MII_CMD, MII_CMD_WRITE);
55 ag71xx_wr(ag, AG71XX_REG_MII_ADDR,
56 ((addr & 0xff) << MII_ADDR_S) | (reg & 0xff));
57 ag71xx_wr(ag, AG71XX_REG_MII_CMD, MII_CMD_READ);
60 while (ag71xx_rr(ag, AG71XX_REG_MII_IND) & MII_IND_BUSY) {
62 printk(KERN_ERR "%s: mii_read timed out\n",
67 udelay(AG71XX_MII_DELAY);
70 ret = ag71xx_rr(ag, AG71XX_REG_MII_STATUS) & 0xffff;
71 ag71xx_wr(ag, AG71XX_REG_MII_CMD, MII_CMD_WRITE);
73 DBG("mii_read: addr=%04x, reg=%04x, value=%04x\n", addr, reg, ret);
79 static void ag71xx_mii_write(struct ag71xx *ag, int addr, int reg, u16 val)
83 DBG("mii_write: addr=%04x, reg=%04x, value=%04x\n", addr, reg, val);
85 ag71xx_wr(ag, AG71XX_REG_MII_ADDR,
86 ((addr & 0xff) << MII_ADDR_S) | (reg & 0xff));
87 ag71xx_wr(ag, AG71XX_REG_MII_CTRL, val);
90 while (ag71xx_rr(ag, AG71XX_REG_MII_IND) & MII_IND_BUSY) {
92 printk(KERN_ERR "%s: mii_write timed out\n",
96 udelay(AG71XX_MII_DELAY);
100 int ag71xx_mii_peek(struct ag71xx *ag)
106 for (i = 0; i < PHY_MAX_ADDR; i++) {
107 u16 bmsr, id1, id2, bmcr, advert, lpa;
109 bmsr = ag71xx_mii_read(ag, i, MII_BMSR);
110 bmcr = ag71xx_mii_read(ag, i, MII_BMCR);
111 id1 = ag71xx_mii_read(ag, i, MII_PHYSID1);
112 id2 = ag71xx_mii_read(ag, i, MII_PHYSID2);
113 advert = ag71xx_mii_read(ag, i, MII_ADVERTISE);
114 lpa = ag71xx_mii_read(ag, i, MII_LPA);
115 DBG("%s: phy%02d bmsr=%04x, bmcr=%04x, "
116 "id=%04x.%04x, advertise=%04x, lpa=%04x\n",
118 bmsr, bmcr, id1, id2, advert, lpa);
120 if ((bmsr | bmcr | id1 | id2 | advert | lpa) != 0)
127 #define PLL_SEC_CONFIG 0x18050004
128 #define PLL_ETH0_INT_CLOCK 0x18050010
129 #define PLL_ETH1_INT_CLOCK 0x18050014
130 #define PLL_ETH_EXT_CLOCK 0x18050018
132 #define ag7100_pll_shift(_ag) (((_ag)->pdev->id) ? 19 : 17)
133 #define ag7100_pll_offset(_ag) (((_ag)->pdev->id) ? PLL_ETH1_INT_CLOCK \
134 : PLL_ETH0_INT_CLOCK)
136 static void ag71xx_set_pll(struct ag71xx *ag, u32 pll_val)
138 void __iomem *pll_reg = ioremap_nocache(ag7100_pll_offset(ag), 4);
139 void __iomem *pll_cfg = ioremap_nocache(PLL_SEC_CONFIG, 4);
143 s = ag7100_pll_shift(ag);
145 t = __raw_readl(pll_cfg);
148 __raw_writel(t, pll_cfg);
151 __raw_writel(pll_val, pll_reg);
154 __raw_writel(t, pll_cfg);
158 __raw_writel(t, pll_cfg);
160 DBG("%s: pll_reg %#x: %#x\n", ag->dev->name,
161 (unsigned int)pll_reg, __raw_readl(pll_reg));
167 static unsigned char *ag71xx_speed_str(struct ag71xx *ag)
182 #define PLL_VAL_1000 0x00110000
183 #define PLL_VAL_100 0x00001099
184 #define PLL_VAL_10 0x00991099
186 #define PLL_VAL_1000 0x01111000
187 #define PLL_VAL_100 0x09991000
188 #define PLL_VAL_10 0x09991999
191 void ag71xx_link_update(struct ag71xx *ag)
200 netif_carrier_off(ag->dev);
201 printk(KERN_INFO "%s: link down\n", ag->dev->name);
205 cfg2 = ag71xx_rr(ag, AG71XX_REG_MAC_CFG2);
206 cfg2 &= ~(MAC_CFG2_IF_1000 | MAC_CFG2_IF_10_100 | MAC_CFG2_FDX);
207 cfg2 |= (ag->duplex) ? MAC_CFG2_FDX : 0;
209 ifctl = ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL);
210 ifctl &= ~(MAC_IFCTL_SPEED);
212 fifo5 = ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5);
213 fifo5 &= ~FIFO_CFG5_BYTE_PER_CLK;
217 mii_speed = MII_CTRL_SPEED_1000;
218 cfg2 |= MAC_CFG2_IF_1000;
220 fifo5 |= FIFO_CFG5_BYTE_PER_CLK;
223 mii_speed = MII_CTRL_SPEED_100;
224 cfg2 |= MAC_CFG2_IF_10_100;
225 ifctl |= MAC_IFCTL_SPEED;
229 mii_speed = MII_CTRL_SPEED_10;
230 cfg2 |= MAC_CFG2_IF_10_100;
238 ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, 0x008001ff);
239 ag71xx_set_pll(ag, pll);
240 ag71xx_mii_ctrl_set_speed(ag, mii_speed);
242 ag71xx_wr(ag, AG71XX_REG_MAC_CFG2, cfg2);
243 ag71xx_wr(ag, AG71XX_REG_FIFO_CFG5, fifo5);
244 ag71xx_wr(ag, AG71XX_REG_MAC_IFCTL, ifctl);
246 netif_carrier_on(ag->dev);
247 printk(KERN_INFO "%s: link up (%sMbps/%s duplex)\n",
249 ag71xx_speed_str(ag),
250 (DUPLEX_FULL == ag->duplex) ? "Full" : "Half");
252 DBG("%s: fifo1=%#x, fifo2=%#x, fifo3=%#x, fifo4=%#x, fifo5=%#x\n",
254 ag71xx_rr(ag, AG71XX_REG_FIFO_CFG1),
255 ag71xx_rr(ag, AG71XX_REG_FIFO_CFG2),
256 ag71xx_rr(ag, AG71XX_REG_FIFO_CFG3),
257 ag71xx_rr(ag, AG71XX_REG_FIFO_CFG4),
258 ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5));
260 DBG("%s: mac_cfg2=%#x, ifctl=%#x, mii_ctrl=%#x\n",
262 ag71xx_rr(ag, AG71XX_REG_MAC_CFG2),
263 ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL),
264 ag71xx_mii_ctrl_rr(ag));
267 static void ag71xx_link_adjust(struct net_device *dev)
269 struct ag71xx *ag = netdev_priv(dev);
270 struct phy_device *phydev = ag->phy_dev;
272 int status_change = 0;
274 spin_lock_irqsave(&ag->lock, flags);
277 if (ag->duplex != phydev->duplex
278 || ag->speed != phydev->speed) {
283 if (phydev->link != ag->link) {
290 ag->link = phydev->link;
291 ag->duplex = phydev->duplex;
292 ag->speed = phydev->speed;
295 ag71xx_link_update(ag);
297 spin_unlock_irqrestore(&ag->lock, flags);
300 static int ag71xx_mdio_read(struct mii_bus *bus, int addr, int reg)
302 struct ag71xx *ag = bus->priv;
304 return ag71xx_mii_read(ag, addr, reg);
307 static int ag71xx_mdio_write(struct mii_bus *bus, int addr, int reg, u16 val)
309 struct ag71xx *ag = bus->priv;
311 ag71xx_mii_write(ag, addr, reg, val);
315 static int ag71xx_mdio_reset(struct mii_bus *bus)
321 static int ag71xx_mdio_probe(struct ag71xx *ag)
323 struct net_device *dev = ag->dev;
324 struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag);
325 struct phy_device *phydev = NULL;
329 for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
330 if (!(pdata->phy_mask & (1 << phy_addr)))
333 if (ag->mii_bus.phy_map[phy_addr] == NULL)
336 DBG("%s: PHY found at %s, uid=%08x\n",
338 ag->mii_bus.phy_map[phy_addr]->dev.bus_id,
339 ag->mii_bus.phy_map[phy_addr]->phy_id);
342 phydev = ag->mii_bus.phy_map[phy_addr];
349 printk(KERN_ERR "%s: no PHY found\n", dev->name);
352 ag->phy_dev = phy_connect(dev, phydev->dev.bus_id,
353 &ag71xx_link_adjust, 0, pdata->phy_if_mode);
355 if (IS_ERR(ag->phy_dev)) {
356 printk(KERN_ERR "%s: could not connect to PHY at %s\n",
357 dev->name, phydev->dev.bus_id);
358 return PTR_ERR(ag->phy_dev);
361 /* mask with MAC supported features */
362 phydev->supported &= (SUPPORTED_10baseT_Half
363 | SUPPORTED_10baseT_Full
364 | SUPPORTED_100baseT_Half
365 | SUPPORTED_100baseT_Full
370 phydev->advertising = phydev->supported;
372 printk(KERN_DEBUG "%s: connected to PHY at %s "
373 "[uid=%08x, driver=%s]\n",
374 dev->name, phydev->dev.bus_id,
375 phydev->phy_id, phydev->drv->name);
383 printk(KERN_DEBUG "%s: connected to multiple PHYs (%d)\n",
384 dev->name, phy_count);
391 int ag71xx_mdio_init(struct ag71xx *ag, int id)
396 ag->mii_bus.name = "ag71xx_mii";
397 ag->mii_bus.read = ag71xx_mdio_read;
398 ag->mii_bus.write = ag71xx_mdio_write;
399 ag->mii_bus.reset = ag71xx_mdio_reset;
401 ag->mii_bus.priv = ag;
402 ag->mii_bus.dev = &ag->dev->dev;
404 ag->mii_bus.irq = kmalloc(sizeof(*ag->mii_bus.irq) * PHY_MAX_ADDR,
406 if (!ag->mii_bus.irq) {
411 for (i = 0; i < PHY_MAX_ADDR; i++)
412 ag->mii_bus.irq[i] = PHY_POLL;
414 err = mdiobus_register(&ag->mii_bus);
418 err = ag71xx_mdio_probe(ag);
420 goto err_unregister_bus;
425 mdiobus_unregister(&ag->mii_bus);
427 kfree(ag->mii_bus.irq);
432 void ag71xx_mdio_cleanup(struct ag71xx *ag)
434 mdiobus_unregister(&ag->mii_bus);
435 kfree(ag->mii_bus.irq);