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