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_mdio
*am
)
27 for (i
= 0; i
< AG71XX_MDIO_RETRY
; i
++) {
30 udelay(AG71XX_MDIO_DELAY
);
32 regmap_read(am
->mii_regmap
, AG71XX_REG_MII_IND
, &busy
);
36 udelay(AG71XX_MDIO_DELAY
);
39 pr_err("%s: MDIO operation timed out\n", am
->mii_bus
->name
);
44 static int ag71xx_mdio_mii_read(struct mii_bus
*bus
, int addr
, int reg
)
46 struct ag71xx_mdio
*am
= bus
->priv
;
50 err
= ag71xx_mdio_wait_busy(am
);
54 regmap_write(am
->mii_regmap
, AG71XX_REG_MII_CMD
, MII_CMD_WRITE
);
55 regmap_write(am
->mii_regmap
, AG71XX_REG_MII_ADDR
,
56 ((addr
& 0xff) << MII_ADDR_SHIFT
) | (reg
& 0xff));
57 regmap_write(am
->mii_regmap
, AG71XX_REG_MII_CMD
, MII_CMD_READ
);
59 err
= ag71xx_mdio_wait_busy(am
);
63 regmap_read(am
->mii_regmap
, AG71XX_REG_MII_STATUS
, &ret
);
65 regmap_write(am
->mii_regmap
, AG71XX_REG_MII_CMD
, MII_CMD_WRITE
);
67 DBG("mii_read: addr=%04x, reg=%04x, value=%04x\n", addr
, reg
, ret
);
72 static int ag71xx_mdio_mii_write(struct mii_bus
*bus
, int addr
, int reg
, u16 val
)
74 struct ag71xx_mdio
*am
= bus
->priv
;
76 DBG("mii_write: addr=%04x, reg=%04x, value=%04x\n", addr
, reg
, val
);
78 regmap_write(am
->mii_regmap
, AG71XX_REG_MII_ADDR
,
79 ((addr
& 0xff) << MII_ADDR_SHIFT
) | (reg
& 0xff));
80 regmap_write(am
->mii_regmap
, AG71XX_REG_MII_CTRL
, val
);
82 ag71xx_mdio_wait_busy(am
);
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_mdio
*am
= bus
->priv
;
104 builtin_switch
= of_property_read_bool(np
, "builtin-switch");
106 if (of_device_is_compatible(np
, "qca,ar7240-mdio"))
107 t
= MII_CFG_CLK_DIV_6
;
108 else if (of_device_is_compatible(np
, "qca,ar9340-mdio"))
109 t
= MII_CFG_CLK_DIV_58
;
110 else if (builtin_switch
)
111 t
= MII_CFG_CLK_DIV_10
;
113 t
= MII_CFG_CLK_DIV_28
;
115 if (builtin_switch
&& of_device_is_compatible(np
, "qca,ar9340-mdio")) {
116 struct clk
*ref_clk
= of_clk_get(np
, 0);
119 if (WARN_ON_ONCE(!ref_clk
))
120 clock_rate
= 40 * 1000 * 1000;
122 clock_rate
= clk_get_rate(ref_clk
);
124 t
= ar934x_mdio_clock_div(clock_rate
);
128 regmap_write(am
->mii_regmap
, AG71XX_REG_MII_CFG
, t
| MII_CFG_RESET
);
131 regmap_write(am
->mii_regmap
, AG71XX_REG_MII_CFG
, t
);
137 static int ag71xx_mdio_probe(struct platform_device
*pdev
)
139 struct device
*amdev
= &pdev
->dev
;
140 struct device_node
*np
= pdev
->dev
.of_node
;
141 struct ag71xx_mdio
*am
;
142 struct mii_bus
*mii_bus
;
146 am
= devm_kzalloc(amdev
, sizeof(*am
), GFP_KERNEL
);
150 am
->mii_regmap
= syscon_regmap_lookup_by_phandle(np
, "regmap");
154 mii_bus
= devm_mdiobus_alloc(amdev
);
158 am
->mdio_reset
= of_reset_control_get_exclusive(np
, "mdio");
159 builtin_switch
= of_property_read_bool(np
, "builtin-switch");
161 mii_bus
->name
= "ag71xx_mdio";
162 mii_bus
->read
= ag71xx_mdio_mii_read
;
163 mii_bus
->write
= ag71xx_mdio_mii_write
;
164 mii_bus
->reset
= ag71xx_mdio_reset
;
166 mii_bus
->parent
= amdev
;
167 snprintf(mii_bus
->id
, MII_BUS_ID_SIZE
, "%s.%d", np
->name
, bus_count
++);
169 if (!builtin_switch
&&
170 of_property_read_u32(np
, "phy-mask", &mii_bus
->phy_mask
))
171 mii_bus
->phy_mask
= 0;
173 for (i
= 0; i
< PHY_MAX_ADDR
; i
++)
174 mii_bus
->irq
[i
] = PHY_POLL
;
176 if (!IS_ERR(am
->mdio_reset
)) {
177 reset_control_assert(am
->mdio_reset
);
179 reset_control_deassert(am
->mdio_reset
);
183 err
= of_mdiobus_register(mii_bus
, np
);
187 am
->mii_bus
= mii_bus
;
188 platform_set_drvdata(pdev
, am
);
193 static int ag71xx_mdio_remove(struct platform_device
*pdev
)
195 struct ag71xx_mdio
*am
= platform_get_drvdata(pdev
);
197 mdiobus_unregister(am
->mii_bus
);
201 static const struct of_device_id ag71xx_mdio_match
[] = {
202 { .compatible
= "qca,ar7240-mdio" },
203 { .compatible
= "qca,ar9340-mdio" },
204 { .compatible
= "qca,ath79-mdio" },
208 static struct platform_driver ag71xx_mdio_driver
= {
209 .probe
= ag71xx_mdio_probe
,
210 .remove
= ag71xx_mdio_remove
,
212 .name
= "ag71xx-mdio",
213 .of_match_table
= ag71xx_mdio_match
,
217 module_platform_driver(ag71xx_mdio_driver
);
218 MODULE_LICENSE("GPL");