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