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>
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)
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
33 enum mvmdio_bus_type {
40 enum mvmdio_bus_type type;
43 static int mvmdio_smi_read(struct udevice *dev, int addr,
46 struct mvmdio_priv *priv = dev_get_priv(dev);
50 if (devad != MDIO_DEVAD_NONE)
53 ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_SMI_BUSY,
54 false, CONFIG_SYS_HZ, false);
58 writel(((addr << MVMDIO_SMI_PHY_ADDR_SHIFT) |
59 (reg << MVMDIO_SMI_PHY_REG_SHIFT) |
60 MVMDIO_SMI_READ_OPERATION),
63 ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_SMI_BUSY,
64 false, CONFIG_SYS_HZ, false);
68 val = readl(priv->mdio_base);
69 if (!(val & MVMDIO_SMI_READ_VALID)) {
70 pr_err("SMI bus read not valid\n");
74 return val & GENMASK(15, 0);
77 static int mvmdio_smi_write(struct udevice *dev, int addr, int devad,
80 struct mvmdio_priv *priv = dev_get_priv(dev);
83 if (devad != MDIO_DEVAD_NONE)
86 ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_SMI_BUSY,
87 false, CONFIG_SYS_HZ, false);
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)),
100 static int mvmdio_xsmi_read(struct udevice *dev, int addr,
103 struct mvmdio_priv *priv = dev_get_priv(dev);
106 if (devad == MDIO_DEVAD_NONE)
109 ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_XSMI_BUSY,
110 false, CONFIG_SYS_HZ, false);
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);
120 ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_XSMI_BUSY,
121 false, CONFIG_SYS_HZ, false);
125 if (!(readl(priv->mdio_base + MVMDIO_XSMI_MGNT_REG) &
126 MVMDIO_XSMI_READ_VALID)) {
127 pr_err("XSMI bus read not valid\n");
131 return readl(priv->mdio_base + MVMDIO_XSMI_MGNT_REG) & GENMASK(15, 0);
134 static int mvmdio_xsmi_write(struct udevice *dev, int addr, int devad,
137 struct mvmdio_priv *priv = dev_get_priv(dev);
140 if (devad == MDIO_DEVAD_NONE)
143 ret = wait_for_bit_le32(priv->mdio_base, MVMDIO_XSMI_BUSY,
144 false, CONFIG_SYS_HZ, false);
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);
157 static int mvmdio_read(struct udevice *dev, int addr, int devad, int reg)
159 struct mvmdio_priv *priv = dev_get_priv(dev);
162 switch (priv->type) {
164 err = mvmdio_smi_read(dev, addr, devad, reg);
167 err = mvmdio_xsmi_read(dev, addr, devad, reg);
174 static int mvmdio_write(struct udevice *dev, int addr, int devad, int reg,
177 struct mvmdio_priv *priv = dev_get_priv(dev);
180 switch (priv->type) {
182 err = mvmdio_smi_write(dev, addr, devad, reg, value);
185 err = mvmdio_xsmi_write(dev, addr, devad, reg, value);
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
197 static int mvmdio_bind(struct udevice *dev)
199 if (ofnode_valid(dev->node))
200 device_set_name(dev, ofnode_get_name(dev->node));
205 /* Get device base address and type, either C22 SMII or C45 XSMI */
206 static int mvmdio_probe(struct udevice *dev)
208 struct mvmdio_priv *priv = dev_get_priv(dev);
210 priv->mdio_base = (void *)dev_read_addr(dev);
211 priv->type = (enum mvmdio_bus_type)dev_get_driver_data(dev);
216 static const struct mdio_ops mvmdio_ops = {
218 .write = mvmdio_write,
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 },
227 U_BOOT_DRIVER(mvmdio) = {
230 .of_match = mvmdio_ids,
232 .probe = mvmdio_probe,
234 .priv_auto_alloc_size = sizeof(struct mvmdio_priv),