2 * Atheros AR71xx built-in ethernet mac driver
4 * Copyright (C) 2008-2010 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.
14 #include <linux/clk.h>
15 #include <linux/of_mdio.h>
18 #define AG71XX_MDIO_RETRY 1000
19 #define AG71XX_MDIO_DELAY 5
23 static int ag71xx_mdio_wait_busy(struct ag71xx
*ag
)
27 for (i
= 0; i
< AG71XX_MDIO_RETRY
; i
++) {
30 udelay(AG71XX_MDIO_DELAY
);
32 regmap_read(ag
->mii_regmap
, AG71XX_REG_MII_IND
, &busy
);
36 udelay(AG71XX_MDIO_DELAY
);
39 pr_err("%s: MDIO operation timed out\n", ag
->mii_bus
->name
);
44 int ag71xx_mdio_mii_read(struct mii_bus
*bus
, int addr
, int reg
)
46 struct ag71xx
*ag
= bus
->priv
;
50 err
= ag71xx_mdio_wait_busy(ag
);
54 regmap_write(ag
->mii_regmap
, AG71XX_REG_MII_CMD
, MII_CMD_WRITE
);
55 regmap_write(ag
->mii_regmap
, AG71XX_REG_MII_ADDR
,
56 ((addr
& 0xff) << MII_ADDR_SHIFT
) | (reg
& 0xff));
57 regmap_write(ag
->mii_regmap
, AG71XX_REG_MII_CMD
, MII_CMD_READ
);
59 err
= ag71xx_mdio_wait_busy(ag
);
63 regmap_read(ag
->mii_regmap
, AG71XX_REG_MII_STATUS
, &ret
);
65 regmap_write(ag
->mii_regmap
, AG71XX_REG_MII_CMD
, MII_CMD_WRITE
);
67 DBG("mii_read: addr=%04x, reg=%04x, value=%04x\n", addr
, reg
, ret
);
72 int ag71xx_mdio_mii_write(struct mii_bus
*bus
, int addr
, int reg
, u16 val
)
74 struct ag71xx
*ag
= bus
->priv
;
76 DBG("mii_write: addr=%04x, reg=%04x, value=%04x\n", addr
, reg
, val
);
78 regmap_write(ag
->mii_regmap
, AG71XX_REG_MII_ADDR
,
79 ((addr
& 0xff) << MII_ADDR_SHIFT
) | (reg
& 0xff));
80 regmap_write(ag
->mii_regmap
, AG71XX_REG_MII_CTRL
, val
);
82 ag71xx_mdio_wait_busy(ag
);
87 static int ar934x_mdio_clock_div(unsigned int rate
)
89 if (rate
== 100 * 1000 * 1000)
90 return 6; /* 100 MHz clock divided by 20 => 5 MHz */
91 else if (rate
== 25 * 1000 * 1000)
92 return 0; /* 25 MHz clock divided by 4 => 6.25 MHz */
94 return 3; /* 40 MHz clock divided by 8 => 5 MHz */
97 static int ag71xx_mdio_reset(struct mii_bus
*bus
)
99 struct device_node
*np
= bus
->dev
.of_node
;
100 struct ag71xx
*ag
= bus
->priv
;
101 struct device_node
*np_ag
= ag
->pdev
->dev
.of_node
;
105 builtin_switch
= of_property_read_bool(np
, "builtin-switch");
107 if (of_device_is_compatible(np_ag
, "qca,ar7240-eth"))
108 t
= MII_CFG_CLK_DIV_6
;
109 else if (of_device_is_compatible(np_ag
, "qca,ar9340-eth"))
110 t
= MII_CFG_CLK_DIV_58
;
111 else if (builtin_switch
)
112 t
= MII_CFG_CLK_DIV_10
;
114 t
= MII_CFG_CLK_DIV_28
;
116 if (builtin_switch
&& of_device_is_compatible(np_ag
, "qca,ar9340-eth")) {
117 struct clk
*ref_clk
= of_clk_get(np
, 0);
120 if (WARN_ON_ONCE(!ref_clk
))
121 clock_rate
= 40 * 1000 * 1000;
123 clock_rate
= clk_get_rate(ref_clk
);
125 t
= ar934x_mdio_clock_div(clock_rate
);
129 regmap_write(ag
->mii_regmap
, AG71XX_REG_MII_CFG
, t
| MII_CFG_RESET
);
132 regmap_write(ag
->mii_regmap
, AG71XX_REG_MII_CFG
, t
);
138 int ag71xx_mdio_init(struct ag71xx
*ag
)
140 struct device
*parent
= &ag
->pdev
->dev
;
141 struct device_node
*np
;
142 struct mii_bus
*mii_bus
;
146 np
= of_get_child_by_name(parent
->of_node
, "mdio-bus");
150 if (!of_device_is_available(np
)) {
155 ag
->mii_regmap
= syscon_regmap_lookup_by_phandle(np
, "regmap");
159 mii_bus
= devm_mdiobus_alloc(parent
);
165 ag
->mdio_reset
= of_reset_control_get_exclusive(np
, "mdio");
166 builtin_switch
= of_property_read_bool(np
, "builtin-switch");
168 mii_bus
->name
= "mdio";
169 if (builtin_switch
) {
170 mii_bus
->read
= ar7240sw_phy_read
;
171 mii_bus
->write
= ar7240sw_phy_write
;
173 mii_bus
->read
= ag71xx_mdio_mii_read
;
174 mii_bus
->write
= ag71xx_mdio_mii_write
;
176 mii_bus
->reset
= ag71xx_mdio_reset
;
178 mii_bus
->parent
= parent
;
179 snprintf(mii_bus
->id
, MII_BUS_ID_SIZE
, "%s.%d", np
->name
, bus_count
++);
181 if (!builtin_switch
&&
182 of_property_read_u32(np
, "phy-mask", &mii_bus
->phy_mask
))
183 mii_bus
->phy_mask
= 0;
185 for (i
= 0; i
< PHY_MAX_ADDR
; i
++)
186 mii_bus
->irq
[i
] = PHY_POLL
;
188 if (!IS_ERR(ag
->mdio_reset
)) {
189 reset_control_assert(ag
->mdio_reset
);
191 reset_control_deassert(ag
->mdio_reset
);
195 err
= of_mdiobus_register(mii_bus
, np
);
199 ag
->mii_bus
= mii_bus
;
202 ag71xx_ar7240_init(ag
, np
);
211 void ag71xx_mdio_cleanup(struct ag71xx
*ag
)
216 ag71xx_ar7240_cleanup(ag
);
217 mdiobus_unregister(ag
->mii_bus
);