1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2018 Marvell International Ltd.
4 * Author: Ken Ma<make@marvell.com>
9 #include <dm/device-internal.h>
15 #include <linux/bitops.h>
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)
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
34 enum mvmdio_bus_type {
41 enum mvmdio_bus_type type;
44 static int mvmdio_smi_read(struct udevice *dev, int addr,
47 struct mvmdio_priv *priv = dev_get_priv(dev);
51 if (devad != MDIO_DEVAD_NONE)
54 ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_SMI_BUSY,
55 false, CONFIG_SYS_HZ, false);
59 writel(((addr << MVMDIO_SMI_PHY_ADDR_SHIFT) |
60 (reg << MVMDIO_SMI_PHY_REG_SHIFT) |
61 MVMDIO_SMI_READ_OPERATION),
64 ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_SMI_BUSY,
65 false, CONFIG_SYS_HZ, false);
69 val = readl(priv->mdio_base);
70 if (!(val & MVMDIO_SMI_READ_VALID)) {
71 pr_err("SMI bus read not valid\n");
75 return val & GENMASK(15, 0);
78 static int mvmdio_smi_write(struct udevice *dev, int addr, int devad,
81 struct mvmdio_priv *priv = dev_get_priv(dev);
84 if (devad != MDIO_DEVAD_NONE)
87 ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_SMI_BUSY,
88 false, CONFIG_SYS_HZ, false);
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)),
101 static int mvmdio_xsmi_read(struct udevice *dev, int addr,
104 struct mvmdio_priv *priv = dev_get_priv(dev);
107 if (devad == MDIO_DEVAD_NONE)
110 ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_XSMI_BUSY,
111 false, CONFIG_SYS_HZ, false);
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);
121 ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_XSMI_BUSY,
122 false, CONFIG_SYS_HZ, false);
126 if (!(readl(priv->mdio_base + MVMDIO_XSMI_MGNT_REG) &
127 MVMDIO_XSMI_READ_VALID)) {
128 pr_err("XSMI bus read not valid\n");
132 return readl(priv->mdio_base + MVMDIO_XSMI_MGNT_REG) & GENMASK(15, 0);
135 static int mvmdio_xsmi_write(struct udevice *dev, int addr, int devad,
138 struct mvmdio_priv *priv = dev_get_priv(dev);
141 if (devad == MDIO_DEVAD_NONE)
144 ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_XSMI_BUSY,
145 false, CONFIG_SYS_HZ, false);
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);
158 static int mvmdio_read(struct udevice *dev, int addr, int devad, int reg)
160 struct mvmdio_priv *priv = dev_get_priv(dev);
163 switch (priv->type) {
165 err = mvmdio_smi_read(dev, addr, devad, reg);
168 err = mvmdio_xsmi_read(dev, addr, devad, reg);
175 static int mvmdio_write(struct udevice *dev, int addr, int devad, int reg,
178 struct mvmdio_priv *priv = dev_get_priv(dev);
181 switch (priv->type) {
183 err = mvmdio_smi_write(dev, addr, devad, reg, value);
186 err = mvmdio_xsmi_write(dev, addr, devad, reg, value);
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
198 static int mvmdio_bind(struct udevice *dev)
200 if (ofnode_valid(dev_ofnode(dev)))
201 device_set_name(dev, ofnode_get_name(dev_ofnode(dev)));
206 /* Get device base address and type, either C22 SMII or C45 XSMI */
207 static int mvmdio_probe(struct udevice *dev)
209 struct mvmdio_priv *priv = dev_get_priv(dev);
211 priv->mdio_base = (void *)dev_read_addr(dev);
212 priv->type = (enum mvmdio_bus_type)dev_get_driver_data(dev);
217 static const struct mdio_ops mvmdio_ops = {
219 .write = mvmdio_write,
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 },
228 U_BOOT_DRIVER(mvmdio) = {
231 .of_match = mvmdio_ids,
233 .probe = mvmdio_probe,
235 .priv_auto = sizeof(struct mvmdio_priv),