Merge tag 'rpi-next-2019.10' of https://github.com/mbgg/u-boot
[platform/kernel/u-boot.git] / drivers / net / mvmdio.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2018 Marvell International Ltd.
4  * Author: Ken Ma<make@marvell.com>
5  */
6
7 #include <common.h>
8 #include <dm.h>
9 #include <dm/device-internal.h>
10 #include <dm/lists.h>
11 #include <miiphy.h>
12 #include <phy.h>
13 #include <asm/io.h>
14 #include <wait_bit.h>
15
16 #define MVMDIO_SMI_DATA_SHIFT           0
17 #define MVMDIO_SMI_PHY_ADDR_SHIFT       16
18 #define MVMDIO_SMI_PHY_REG_SHIFT        21
19 #define MVMDIO_SMI_READ_OPERATION       BIT(26)
20 #define MVMDIO_SMI_WRITE_OPERATION      0
21 #define MVMDIO_SMI_READ_VALID           BIT(27)
22 #define MVMDIO_SMI_BUSY                 BIT(28)
23
24 #define MVMDIO_XSMI_MGNT_REG            0x0
25 #define MVMDIO_XSMI_PHYADDR_SHIFT       16
26 #define MVMDIO_XSMI_DEVADDR_SHIFT       21
27 #define MVMDIO_XSMI_WRITE_OPERATION     (0x5 << 26)
28 #define MVMDIO_XSMI_READ_OPERATION      (0x7 << 26)
29 #define MVMDIO_XSMI_READ_VALID          BIT(29)
30 #define MVMDIO_XSMI_BUSY                BIT(30)
31 #define MVMDIO_XSMI_ADDR_REG            0x8
32
33 enum mvmdio_bus_type {
34         BUS_TYPE_SMI,
35         BUS_TYPE_XSMI
36 };
37
38 struct mvmdio_priv {
39         void *mdio_base;
40         enum mvmdio_bus_type type;
41 };
42
43 static int mvmdio_smi_read(struct udevice *dev, int addr,
44                            int devad, int reg)
45 {
46         struct mvmdio_priv *priv = dev_get_priv(dev);
47         u32 val;
48         int ret;
49
50         if (devad != MDIO_DEVAD_NONE)
51                 return -EOPNOTSUPP;
52
53         ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_SMI_BUSY,
54                                 false, CONFIG_SYS_HZ, false);
55         if (ret < 0)
56                 return ret;
57
58         writel(((addr << MVMDIO_SMI_PHY_ADDR_SHIFT) |
59                 (reg << MVMDIO_SMI_PHY_REG_SHIFT)  |
60                 MVMDIO_SMI_READ_OPERATION),
61                priv->mdio_base);
62
63         ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_SMI_BUSY,
64                                 false, CONFIG_SYS_HZ, false);
65         if (ret < 0)
66                 return ret;
67
68         val = readl(priv->mdio_base);
69         if (!(val & MVMDIO_SMI_READ_VALID)) {
70                 pr_err("SMI bus read not valid\n");
71                 return -ENODEV;
72         }
73
74         return val & GENMASK(15, 0);
75 }
76
77 static int mvmdio_smi_write(struct udevice *dev, int addr, int devad,
78                             int reg, u16 value)
79 {
80         struct mvmdio_priv *priv = dev_get_priv(dev);
81         int ret;
82
83         if (devad != MDIO_DEVAD_NONE)
84                 return -EOPNOTSUPP;
85
86         ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_SMI_BUSY,
87                                 false, CONFIG_SYS_HZ, false);
88         if (ret < 0)
89                 return ret;
90
91         writel(((addr << MVMDIO_SMI_PHY_ADDR_SHIFT) |
92                 (reg << MVMDIO_SMI_PHY_REG_SHIFT)  |
93                 MVMDIO_SMI_WRITE_OPERATION            |
94                 (value << MVMDIO_SMI_DATA_SHIFT)),
95                priv->mdio_base);
96
97         return 0;
98 }
99
100 static int mvmdio_xsmi_read(struct udevice *dev, int addr,
101                             int devad, int reg)
102 {
103         struct mvmdio_priv *priv = dev_get_priv(dev);
104         int ret;
105
106         if (devad == MDIO_DEVAD_NONE)
107                 return -EOPNOTSUPP;
108
109         ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_XSMI_BUSY,
110                                 false, CONFIG_SYS_HZ, false);
111         if (ret < 0)
112                 return ret;
113
114         writel(reg & GENMASK(15, 0), priv->mdio_base + MVMDIO_XSMI_ADDR_REG);
115         writel(((addr << MVMDIO_XSMI_PHYADDR_SHIFT) |
116                 (devad << MVMDIO_XSMI_DEVADDR_SHIFT) |
117                 MVMDIO_XSMI_READ_OPERATION),
118                priv->mdio_base + MVMDIO_XSMI_MGNT_REG);
119
120         ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_XSMI_BUSY,
121                                 false, CONFIG_SYS_HZ, false);
122         if (ret < 0)
123                 return ret;
124
125         if (!(readl(priv->mdio_base + MVMDIO_XSMI_MGNT_REG) &
126               MVMDIO_XSMI_READ_VALID)) {
127                 pr_err("XSMI bus read not valid\n");
128                 return -ENODEV;
129         }
130
131         return readl(priv->mdio_base + MVMDIO_XSMI_MGNT_REG) & GENMASK(15, 0);
132 }
133
134 static int mvmdio_xsmi_write(struct udevice *dev, int addr, int devad,
135                              int reg, u16 value)
136 {
137         struct mvmdio_priv *priv = dev_get_priv(dev);
138         int ret;
139
140         if (devad == MDIO_DEVAD_NONE)
141                 return -EOPNOTSUPP;
142
143         ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_XSMI_BUSY,
144                                 false, CONFIG_SYS_HZ, false);
145         if (ret < 0)
146                 return ret;
147
148         writel(reg & GENMASK(15, 0), priv->mdio_base + MVMDIO_XSMI_ADDR_REG);
149         writel(((addr << MVMDIO_XSMI_PHYADDR_SHIFT) |
150                 (devad << MVMDIO_XSMI_DEVADDR_SHIFT) |
151                 MVMDIO_XSMI_WRITE_OPERATION | value),
152                priv->mdio_base + MVMDIO_XSMI_MGNT_REG);
153
154         return 0;
155 }
156
157 static int mvmdio_read(struct udevice *dev, int addr, int devad, int reg)
158 {
159         struct mvmdio_priv *priv = dev_get_priv(dev);
160         int err = -ENOTSUPP;
161
162         switch (priv->type) {
163         case BUS_TYPE_SMI:
164                 err = mvmdio_smi_read(dev, addr, devad, reg);
165                 break;
166         case BUS_TYPE_XSMI:
167                 err = mvmdio_xsmi_read(dev, addr, devad, reg);
168                 break;
169         }
170
171         return err;
172 }
173
174 static int mvmdio_write(struct udevice *dev, int addr, int devad, int reg,
175                         u16 value)
176 {
177         struct mvmdio_priv *priv = dev_get_priv(dev);
178         int err = -ENOTSUPP;
179
180         switch (priv->type) {
181         case BUS_TYPE_SMI:
182                 err = mvmdio_smi_write(dev, addr, devad, reg, value);
183                 break;
184         case BUS_TYPE_XSMI:
185                 err = mvmdio_xsmi_write(dev, addr, devad, reg, value);
186                 break;
187         }
188
189         return err;
190 }
191
192 /*
193  * Name the device, we use the device tree node name.
194  * This can be overwritten by MDIO class code if device-name property is
195  * present.
196  */
197 static int mvmdio_bind(struct udevice *dev)
198 {
199         if (ofnode_valid(dev->node))
200                 device_set_name(dev, ofnode_get_name(dev->node));
201
202         return 0;
203 }
204
205 /* Get device base address and type, either C22 SMII or C45 XSMI */
206 static int mvmdio_probe(struct udevice *dev)
207 {
208         struct mvmdio_priv *priv = dev_get_priv(dev);
209
210         priv->mdio_base = (void *)dev_read_addr(dev);
211         priv->type = (enum mvmdio_bus_type)dev_get_driver_data(dev);
212
213         return 0;
214 }
215
216 static const struct mdio_ops mvmdio_ops = {
217         .read = mvmdio_read,
218         .write = mvmdio_write,
219 };
220
221 static const struct udevice_id mvmdio_ids[] = {
222         { .compatible = "marvell,orion-mdio", .data = BUS_TYPE_SMI },
223         { .compatible = "marvell,xmdio", .data = BUS_TYPE_XSMI },
224         { }
225 };
226
227 U_BOOT_DRIVER(mvmdio) = {
228         .name                   = "mvmdio",
229         .id                     = UCLASS_MDIO,
230         .of_match               = mvmdio_ids,
231         .bind                   = mvmdio_bind,
232         .probe                  = mvmdio_probe,
233         .ops                    = &mvmdio_ops,
234         .priv_auto_alloc_size   = sizeof(struct mvmdio_priv),
235 };
236