2 * QorIQ 10G MDIO Controller
4 * Copyright 2012 Freescale Semiconductor, Inc.
6 * Authors: Andy Fleming <afleming@freescale.com>
7 * Timur Tabi <timur@freescale.com>
9 * This file is licensed under the terms of the GNU General Public License
10 * version 2. This program is licensed "as is" without any warranty of any
11 * kind, whether express or implied.
14 #include <linux/kernel.h>
15 #include <linux/slab.h>
16 #include <linux/interrupt.h>
17 #include <linux/module.h>
18 #include <linux/phy.h>
19 #include <linux/mdio.h>
20 #include <linux/of_address.h>
21 #include <linux/of_platform.h>
22 #include <linux/of_mdio.h>
24 /* Number of microseconds to wait for a register to respond */
27 struct tgec_mdio_controller
{
29 __be32 mdio_stat
; /* MDIO configuration and status */
30 __be32 mdio_ctl
; /* MDIO control */
31 __be32 mdio_data
; /* MDIO data */
32 __be32 mdio_addr
; /* MDIO address */
35 #define MDIO_STAT_ENC BIT(6)
36 #define MDIO_STAT_CLKDIV(x) (((x>>1) & 0xff) << 8)
37 #define MDIO_STAT_BSY BIT(0)
38 #define MDIO_STAT_RD_ER BIT(1)
39 #define MDIO_CTL_DEV_ADDR(x) (x & 0x1f)
40 #define MDIO_CTL_PORT_ADDR(x) ((x & 0x1f) << 5)
41 #define MDIO_CTL_PRE_DIS BIT(10)
42 #define MDIO_CTL_SCAN_EN BIT(11)
43 #define MDIO_CTL_POST_INC BIT(14)
44 #define MDIO_CTL_READ BIT(15)
46 #define MDIO_DATA(x) (x & 0xffff)
47 #define MDIO_DATA_BSY BIT(31)
49 struct mdio_fsl_priv
{
50 struct tgec_mdio_controller __iomem
*mdio_base
;
51 bool is_little_endian
;
54 static u32
xgmac_read32(void __iomem
*regs
,
55 bool is_little_endian
)
58 return ioread32(regs
);
60 return ioread32be(regs
);
63 static void xgmac_write32(u32 value
,
65 bool is_little_endian
)
68 iowrite32(value
, regs
);
70 iowrite32be(value
, regs
);
74 * Wait until the MDIO bus is free
76 static int xgmac_wait_until_free(struct device
*dev
,
77 struct tgec_mdio_controller __iomem
*regs
,
78 bool is_little_endian
)
82 /* Wait till the bus is free */
84 while ((xgmac_read32(®s
->mdio_stat
, is_little_endian
) &
85 MDIO_STAT_BSY
) && timeout
) {
91 dev_err(dev
, "timeout waiting for bus to be free\n");
99 * Wait till the MDIO read or write operation is complete
101 static int xgmac_wait_until_done(struct device
*dev
,
102 struct tgec_mdio_controller __iomem
*regs
,
103 bool is_little_endian
)
105 unsigned int timeout
;
107 /* Wait till the MDIO write is complete */
109 while ((xgmac_read32(®s
->mdio_stat
, is_little_endian
) &
110 MDIO_STAT_BSY
) && timeout
) {
116 dev_err(dev
, "timeout waiting for operation to complete\n");
124 * Write value to the PHY for this device to the register at regnum,waiting
125 * until the write is done before it returns. All PHY configuration has to be
126 * done through the TSEC1 MIIM regs.
128 static int xgmac_mdio_write(struct mii_bus
*bus
, int phy_id
, int regnum
, u16 value
)
130 struct mdio_fsl_priv
*priv
= (struct mdio_fsl_priv
*)bus
->priv
;
131 struct tgec_mdio_controller __iomem
*regs
= priv
->mdio_base
;
133 u32 mdio_ctl
, mdio_stat
;
135 bool endian
= priv
->is_little_endian
;
137 mdio_stat
= xgmac_read32(®s
->mdio_stat
, endian
);
138 if (regnum
& MII_ADDR_C45
) {
139 /* Clause 45 (ie 10G) */
140 dev_addr
= (regnum
>> 16) & 0x1f;
141 mdio_stat
|= MDIO_STAT_ENC
;
143 /* Clause 22 (ie 1G) */
144 dev_addr
= regnum
& 0x1f;
145 mdio_stat
&= ~MDIO_STAT_ENC
;
148 xgmac_write32(mdio_stat
, ®s
->mdio_stat
, endian
);
150 ret
= xgmac_wait_until_free(&bus
->dev
, regs
, endian
);
154 /* Set the port and dev addr */
155 mdio_ctl
= MDIO_CTL_PORT_ADDR(phy_id
) | MDIO_CTL_DEV_ADDR(dev_addr
);
156 xgmac_write32(mdio_ctl
, ®s
->mdio_ctl
, endian
);
158 /* Set the register address */
159 if (regnum
& MII_ADDR_C45
) {
160 xgmac_write32(regnum
& 0xffff, ®s
->mdio_addr
, endian
);
162 ret
= xgmac_wait_until_free(&bus
->dev
, regs
, endian
);
167 /* Write the value to the register */
168 xgmac_write32(MDIO_DATA(value
), ®s
->mdio_data
, endian
);
170 ret
= xgmac_wait_until_done(&bus
->dev
, regs
, endian
);
178 * Reads from register regnum in the PHY for device dev, returning the value.
179 * Clears miimcom first. All PHY configuration has to be done through the
182 static int xgmac_mdio_read(struct mii_bus
*bus
, int phy_id
, int regnum
)
184 struct mdio_fsl_priv
*priv
= (struct mdio_fsl_priv
*)bus
->priv
;
185 struct tgec_mdio_controller __iomem
*regs
= priv
->mdio_base
;
191 bool endian
= priv
->is_little_endian
;
193 mdio_stat
= xgmac_read32(®s
->mdio_stat
, endian
);
194 if (regnum
& MII_ADDR_C45
) {
195 dev_addr
= (regnum
>> 16) & 0x1f;
196 mdio_stat
|= MDIO_STAT_ENC
;
198 dev_addr
= regnum
& 0x1f;
199 mdio_stat
&= ~MDIO_STAT_ENC
;
202 xgmac_write32(mdio_stat
, ®s
->mdio_stat
, endian
);
204 ret
= xgmac_wait_until_free(&bus
->dev
, regs
, endian
);
208 /* Set the Port and Device Addrs */
209 mdio_ctl
= MDIO_CTL_PORT_ADDR(phy_id
) | MDIO_CTL_DEV_ADDR(dev_addr
);
210 xgmac_write32(mdio_ctl
, ®s
->mdio_ctl
, endian
);
212 /* Set the register address */
213 if (regnum
& MII_ADDR_C45
) {
214 xgmac_write32(regnum
& 0xffff, ®s
->mdio_addr
, endian
);
216 ret
= xgmac_wait_until_free(&bus
->dev
, regs
, endian
);
221 /* Initiate the read */
222 xgmac_write32(mdio_ctl
| MDIO_CTL_READ
, ®s
->mdio_ctl
, endian
);
224 ret
= xgmac_wait_until_done(&bus
->dev
, regs
, endian
);
228 /* Return all Fs if nothing was there */
229 if (xgmac_read32(®s
->mdio_stat
, endian
) & MDIO_STAT_RD_ER
) {
231 "Error while reading PHY%d reg at %d.%hhu\n",
232 phy_id
, dev_addr
, regnum
);
236 value
= xgmac_read32(®s
->mdio_data
, endian
) & 0xffff;
237 dev_dbg(&bus
->dev
, "read %04x\n", value
);
242 static int xgmac_mdio_probe(struct platform_device
*pdev
)
244 struct device_node
*np
= pdev
->dev
.of_node
;
247 struct mdio_fsl_priv
*priv
;
250 ret
= of_address_to_resource(np
, 0, &res
);
252 dev_err(&pdev
->dev
, "could not obtain address\n");
256 bus
= mdiobus_alloc_size(sizeof(struct mdio_fsl_priv
));
260 bus
->name
= "Freescale XGMAC MDIO Bus";
261 bus
->read
= xgmac_mdio_read
;
262 bus
->write
= xgmac_mdio_write
;
263 bus
->parent
= &pdev
->dev
;
264 snprintf(bus
->id
, MII_BUS_ID_SIZE
, "%llx", (unsigned long long)res
.start
);
266 /* Set the PHY base address */
268 priv
->mdio_base
= of_iomap(np
, 0);
269 if (!priv
->mdio_base
) {
274 priv
->is_little_endian
= of_property_read_bool(pdev
->dev
.of_node
,
277 ret
= of_mdiobus_register(bus
, np
);
279 dev_err(&pdev
->dev
, "cannot register MDIO bus\n");
280 goto err_registration
;
283 platform_set_drvdata(pdev
, bus
);
288 iounmap(priv
->mdio_base
);
296 static int xgmac_mdio_remove(struct platform_device
*pdev
)
298 struct mii_bus
*bus
= platform_get_drvdata(pdev
);
300 mdiobus_unregister(bus
);
307 static const struct of_device_id xgmac_mdio_match
[] = {
309 .compatible
= "fsl,fman-xmdio",
312 .compatible
= "fsl,fman-memac-mdio",
316 MODULE_DEVICE_TABLE(of
, xgmac_mdio_match
);
318 static struct platform_driver xgmac_mdio_driver
= {
320 .name
= "fsl-fman_xmdio",
321 .of_match_table
= xgmac_mdio_match
,
323 .probe
= xgmac_mdio_probe
,
324 .remove
= xgmac_mdio_remove
,
327 module_platform_driver(xgmac_mdio_driver
);
329 MODULE_DESCRIPTION("Freescale QorIQ 10G MDIO Controller");
330 MODULE_LICENSE("GPL v2");