11
11
#include <linux/of_mdio.h>
12
12
#include <linux/phy.h>
13
13
#include <linux/platform_device.h>
14
+ #include <linux/clk.h>
14
15
15
16
#define MDIO_MODE_REG 0x40
16
17
#define MDIO_ADDR_REG 0x44
31
32
#define IPQ4019_MDIO_TIMEOUT 10000
32
33
#define IPQ4019_MDIO_SLEEP 10
33
34
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
+
34
40
struct ipq4019_mdio_data {
35
41
void __iomem * membase ;
42
+ void __iomem * eth_ldo_rdy ;
43
+ struct clk * mdio_clk ;
36
44
};
37
45
38
46
static 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,
171
179
return 0 ;
172
180
}
173
181
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
+
174
206
static int ipq4019_mdio_probe (struct platform_device * pdev )
175
207
{
176
208
struct ipq4019_mdio_data * priv ;
177
209
struct mii_bus * bus ;
210
+ struct resource * res ;
178
211
int ret ;
179
212
180
213
bus = devm_mdiobus_alloc_size (& pdev -> dev , sizeof (* priv ));
@@ -187,9 +220,19 @@ static int ipq4019_mdio_probe(struct platform_device *pdev)
187
220
if (IS_ERR (priv -> membase ))
188
221
return PTR_ERR (priv -> membase );
189
222
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
+
190
232
bus -> name = "ipq4019_mdio" ;
191
233
bus -> read = ipq4019_mdio_read ;
192
234
bus -> write = ipq4019_mdio_write ;
235
+ bus -> reset = ipq_mdio_reset ;
193
236
bus -> parent = & pdev -> dev ;
194
237
snprintf (bus -> id , MII_BUS_ID_SIZE , "%s%d" , pdev -> name , pdev -> id );
195
238
0 commit comments