Merge branch 'master' of https://gitlab.denx.de/u-boot/custodians/u-boot-sunxi
[platform/kernel/u-boot.git] / drivers / net / ti / cpsw_mdio.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * CPSW MDIO generic driver for TI AMxx/K2x/EMAC devices.
4  *
5  * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
6  */
7
8 #include <common.h>
9 #include <asm/io.h>
10 #include <miiphy.h>
11 #include <wait_bit.h>
12
13 struct cpsw_mdio_regs {
14         u32     version;
15         u32     control;
16 #define CONTROL_IDLE            BIT(31)
17 #define CONTROL_ENABLE          BIT(30)
18 #define CONTROL_FAULT           BIT(19)
19 #define CONTROL_FAULT_ENABLE    BIT(18)
20 #define CONTROL_DIV_MASK        GENMASK(15, 0)
21
22         u32     alive;
23         u32     link;
24         u32     linkintraw;
25         u32     linkintmasked;
26         u32     __reserved_0[2];
27         u32     userintraw;
28         u32     userintmasked;
29         u32     userintmaskset;
30         u32     userintmaskclr;
31         u32     __reserved_1[20];
32
33         struct {
34                 u32             access;
35                 u32             physel;
36 #define USERACCESS_GO           BIT(31)
37 #define USERACCESS_WRITE        BIT(30)
38 #define USERACCESS_ACK          BIT(29)
39 #define USERACCESS_READ         (0)
40 #define USERACCESS_PHY_REG_SHIFT        (21)
41 #define USERACCESS_PHY_ADDR_SHIFT       (16)
42 #define USERACCESS_DATA         GENMASK(15, 0)
43         } user[0];
44 };
45
46 #define CPSW_MDIO_DIV_DEF       0xff
47 #define PHY_REG_MASK            0x1f
48 #define PHY_ID_MASK             0x1f
49
50 /*
51  * This timeout definition is a worst-case ultra defensive measure against
52  * unexpected controller lock ups.  Ideally, we should never ever hit this
53  * scenario in practice.
54  */
55 #define CPSW_MDIO_TIMEOUT            100 /* msecs */
56
57 struct cpsw_mdio {
58         struct cpsw_mdio_regs *regs;
59         struct mii_dev *bus;
60         int div;
61 };
62
63 /* wait until hardware is ready for another user access */
64 static int cpsw_mdio_wait_for_user_access(struct cpsw_mdio *mdio)
65 {
66         return wait_for_bit_le32(&mdio->regs->user[0].access,
67                                  USERACCESS_GO, false,
68                                  CPSW_MDIO_TIMEOUT, false);
69 }
70
71 static int cpsw_mdio_read(struct mii_dev *bus, int phy_id,
72                           int dev_addr, int phy_reg)
73 {
74         struct cpsw_mdio *mdio = bus->priv;
75         int data, ret;
76         u32 reg;
77
78         if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
79                 return -EINVAL;
80
81         ret = cpsw_mdio_wait_for_user_access(mdio);
82         if (ret)
83                 return ret;
84         reg = (USERACCESS_GO | USERACCESS_READ |
85                (phy_reg << USERACCESS_PHY_REG_SHIFT) |
86                (phy_id << USERACCESS_PHY_ADDR_SHIFT));
87         writel(reg, &mdio->regs->user[0].access);
88         ret = cpsw_mdio_wait_for_user_access(mdio);
89         if (ret)
90                 return ret;
91
92         reg = readl(&mdio->regs->user[0].access);
93         data = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -1;
94         return data;
95 }
96
97 static int cpsw_mdio_write(struct mii_dev *bus, int phy_id, int dev_addr,
98                            int phy_reg, u16 data)
99 {
100         struct cpsw_mdio *mdio = bus->priv;
101         u32 reg;
102         int ret;
103
104         if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
105                 return -EINVAL;
106
107         ret = cpsw_mdio_wait_for_user_access(mdio);
108         if (ret)
109                 return ret;
110         reg = (USERACCESS_GO | USERACCESS_WRITE |
111                (phy_reg << USERACCESS_PHY_REG_SHIFT) |
112                (phy_id << USERACCESS_PHY_ADDR_SHIFT) |
113                (data & USERACCESS_DATA));
114         writel(reg, &mdio->regs->user[0].access);
115
116         return cpsw_mdio_wait_for_user_access(mdio);
117 }
118
119 u32 cpsw_mdio_get_alive(struct mii_dev *bus)
120 {
121         struct cpsw_mdio *mdio = bus->priv;
122         u32 val;
123
124         val = readl(&mdio->regs->control);
125         return val & GENMASK(15, 0);
126 }
127
128 struct mii_dev *cpsw_mdio_init(const char *name, phys_addr_t mdio_base,
129                                u32 bus_freq, int fck_freq)
130 {
131         struct cpsw_mdio *cpsw_mdio;
132         int ret;
133
134         cpsw_mdio = calloc(1, sizeof(*cpsw_mdio));
135         if (!cpsw_mdio) {
136                 debug("failed to alloc cpsw_mdio\n");
137                 return NULL;
138         }
139
140         cpsw_mdio->bus = mdio_alloc();
141         if (!cpsw_mdio->bus) {
142                 debug("failed to alloc mii bus\n");
143                 free(cpsw_mdio);
144                 return NULL;
145         }
146
147         cpsw_mdio->regs = (struct cpsw_mdio_regs *)(uintptr_t)mdio_base;
148
149         if (!bus_freq || !fck_freq)
150                 cpsw_mdio->div = CPSW_MDIO_DIV_DEF;
151         else
152                 cpsw_mdio->div = (fck_freq / bus_freq) - 1;
153         cpsw_mdio->div &= CONTROL_DIV_MASK;
154
155         /* set enable and clock divider */
156         writel(cpsw_mdio->div | CONTROL_ENABLE | CONTROL_FAULT |
157                CONTROL_FAULT_ENABLE, &cpsw_mdio->regs->control);
158         wait_for_bit_le32(&cpsw_mdio->regs->control,
159                           CONTROL_IDLE, false, CPSW_MDIO_TIMEOUT, true);
160
161         /*
162          * wait for scan logic to settle:
163          * the scan time consists of (a) a large fixed component, and (b) a
164          * small component that varies with the mii bus frequency.  These
165          * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x
166          * silicon.  Since the effect of (b) was found to be largely
167          * negligible, we keep things simple here.
168          */
169         mdelay(1);
170
171         cpsw_mdio->bus->read = cpsw_mdio_read;
172         cpsw_mdio->bus->write = cpsw_mdio_write;
173         cpsw_mdio->bus->priv = cpsw_mdio;
174         snprintf(cpsw_mdio->bus->name, sizeof(cpsw_mdio->bus->name), name);
175
176         ret = mdio_register(cpsw_mdio->bus);
177         if (ret < 0) {
178                 debug("failed to register mii bus\n");
179                 goto free_bus;
180         }
181
182         return cpsw_mdio->bus;
183
184 free_bus:
185         mdio_free(cpsw_mdio->bus);
186         free(cpsw_mdio);
187         return NULL;
188 }
189
190 void cpsw_mdio_free(struct mii_dev *bus)
191 {
192         struct cpsw_mdio *mdio = bus->priv;
193         u32 reg;
194
195         /* disable mdio */
196         reg = readl(&mdio->regs->control);
197         reg &= ~CONTROL_ENABLE;
198         writel(reg, &mdio->regs->control);
199
200         mdio_unregister(bus);
201         mdio_free(bus);
202         free(mdio);
203 }