1111#include <linux/of_mdio.h>
1212#include <linux/phy.h>
1313#include <linux/platform_device.h>
14+ #include <linux/clk.h>
1415
1516#define MDIO_MODE_REG 0x40
1617#define MDIO_ADDR_REG 0x44
3132#define IPQ4019_MDIO_TIMEOUT 10000
3233#define IPQ4019_MDIO_SLEEP 10
3334
35+ /* MDIO clock source frequency is fixed to 100M */
36+ #define IPQ_MDIO_CLK_RATE 100000000
37+
38+ #define IPQ_PHY_SET_DELAY_US 100000
39+
3440struct ipq4019_mdio_data {
3541 void __iomem * membase ;
42+ void __iomem * eth_ldo_rdy ;
43+ struct clk * mdio_clk ;
3644};
3745
3846static int ipq4019_mdio_wait_busy (struct mii_bus * bus )
@@ -171,10 +179,35 @@ static int ipq4019_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
171179 return 0 ;
172180}
173181
182+ static int ipq_mdio_reset (struct mii_bus * bus )
183+ {
184+ struct ipq4019_mdio_data * priv = bus -> priv ;
185+ u32 val ;
186+ int ret ;
187+
188+ /* To indicate CMN_PLL that ethernet_ldo has been ready if platform resource 1
189+ * is specified in the device tree.
190+ */
191+ if (priv -> eth_ldo_rdy ) {
192+ val = readl (priv -> eth_ldo_rdy );
193+ val |= BIT (0 );
194+ writel (val , priv -> eth_ldo_rdy );
195+ fsleep (IPQ_PHY_SET_DELAY_US );
196+ }
197+
198+ /* Configure MDIO clock source frequency if clock is specified in the device tree */
199+ ret = clk_set_rate (priv -> mdio_clk , IPQ_MDIO_CLK_RATE );
200+ if (ret )
201+ return ret ;
202+
203+ return clk_prepare_enable (priv -> mdio_clk );
204+ }
205+
174206static int ipq4019_mdio_probe (struct platform_device * pdev )
175207{
176208 struct ipq4019_mdio_data * priv ;
177209 struct mii_bus * bus ;
210+ struct resource * res ;
178211 int ret ;
179212
180213 bus = devm_mdiobus_alloc_size (& pdev -> dev , sizeof (* priv ));
@@ -187,9 +220,19 @@ static int ipq4019_mdio_probe(struct platform_device *pdev)
187220 if (IS_ERR (priv -> membase ))
188221 return PTR_ERR (priv -> membase );
189222
223+ priv -> mdio_clk = devm_clk_get_optional (& pdev -> dev , "gcc_mdio_ahb_clk" );
224+ if (IS_ERR (priv -> mdio_clk ))
225+ return PTR_ERR (priv -> mdio_clk );
226+
227+ /* The platform resource is provided on the chipset IPQ5018 */
228+ res = platform_get_resource (pdev , IORESOURCE_MEM , 1 );
229+ if (res )
230+ priv -> eth_ldo_rdy = devm_ioremap_resource (& pdev -> dev , res );
231+
190232 bus -> name = "ipq4019_mdio" ;
191233 bus -> read = ipq4019_mdio_read ;
192234 bus -> write = ipq4019_mdio_write ;
235+ bus -> reset = ipq_mdio_reset ;
193236 bus -> parent = & pdev -> dev ;
194237 snprintf (bus -> id , MII_BUS_ID_SIZE , "%s%d" , pdev -> name , pdev -> id );
195238
0 commit comments