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