"Das U-Boot" Source Tree
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: add Microsemi/Microchip MDIO driver

Add Microsemi/Microchip MDIO driver for interfaces found in their network
switches.

Driver is based on the Linux version.

Signed-off-by: Robert Marko <robert.marko@sartura.hr>
Acked-by: Jerome Forissier <jerome@forissier.org>

authored by

Robert Marko and committed by
Jerome Forissier
dfc39f9c c832cd3b

+145
+8
drivers/net/Kconfig
··· 1069 1069 This driver supports the MDIO bus of Aspeed AST2600 SOC. The driver 1070 1070 currently supports Clause 22. 1071 1071 1072 + config MDIO_MSCC_MIIM 1073 + bool "Microsemi MIIM interface support" 1074 + depends on DM_MDIO 1075 + select REGMAP 1076 + help 1077 + This driver supports MDIO interface found in Microsemi and Microchip 1078 + network switches. 1079 + 1072 1080 config MDIO_MUX_MMIOREG 1073 1081 bool "MDIO MUX accessed as a MMIO register access" 1074 1082 depends on DM_MDIO_MUX
+1
drivers/net/Makefile
··· 62 62 obj-$(CONFIG_MACB) += macb.o 63 63 obj-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o 64 64 obj-$(CONFIG_MDIO_IPQ4019) += mdio-ipq4019.o 65 + obj-$(CONFIG_MDIO_MSCC_MIIM) += mdio-mscc-miim.o 65 66 obj-$(CONFIG_MDIO_GPIO_BITBANG) += mdio_gpio.o 66 67 obj-$(CONFIG_MDIO_MT7531_MMIO) += mdio-mt7531-mmio.o 67 68 obj-$(CONFIG_MDIO_MUX_I2CREG) += mdio_mux_i2creg.o
+136
drivers/net/mdio-mscc-miim.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + 3 + #include <asm/io.h> 4 + #include <dm.h> 5 + #include <time.h> 6 + #include <regmap.h> 7 + #include <miiphy.h> 8 + #include <linux/bitfield.h> 9 + 10 + #define MSCC_MIIM_REG_STATUS 0x0 11 + #define MSCC_MIIM_STATUS_STAT_PENDING BIT(2) 12 + #define MSCC_MIIM_STATUS_STAT_BUSY BIT(3) 13 + #define MSCC_MIIM_REG_CMD 0x8 14 + #define MSCC_MIIM_CMD_OPR_WRITE BIT(1) 15 + #define MSCC_MIIM_CMD_OPR_READ BIT(2) 16 + #define MSCC_MIIM_CMD_WRDATA_SHIFT 4 17 + #define MSCC_MIIM_CMD_REGAD_SHIFT 20 18 + #define MSCC_MIIM_CMD_PHYAD_SHIFT 25 19 + #define MSCC_MIIM_CMD_VLD BIT(31) 20 + #define MSCC_MIIM_REG_DATA 0xC 21 + #define MSCC_MIIM_DATA_ERROR (BIT(16) | BIT(17)) 22 + #define MSCC_MIIM_DATA_MASK GENMASK(15, 0) 23 + #define MSCC_MIIM_REG_CFG 0x10 24 + #define MSCC_MIIM_CFG_PRESCALE_MASK GENMASK(7, 0) 25 + /* 01 = Clause 22, 00 = Clause 45 */ 26 + #define MSCC_MIIM_CFG_ST_CFG_MASK GENMASK(10, 9) 27 + #define MSCC_MIIM_C22 1 28 + #define MSCC_MIIM_C45 0 29 + 30 + #define MSCC_MDIO_TIMEOUT 10000 31 + #define MSCC_MDIO_SLEEP 50 32 + 33 + struct mscc_mdio_priv { 34 + struct regmap *map; 35 + }; 36 + 37 + static int mscc_mdio_wait_busy(struct mscc_mdio_priv *priv) 38 + { 39 + u32 busy; 40 + 41 + return regmap_read_poll_timeout(priv->map, MSCC_MIIM_REG_STATUS, busy, 42 + (busy & MSCC_MIIM_STATUS_STAT_BUSY) == 0, 43 + MSCC_MDIO_SLEEP, 44 + MSCC_MDIO_TIMEOUT); 45 + } 46 + 47 + static int mscc_mdio_read(struct udevice *dev, int addr, int devad, int reg) 48 + { 49 + struct mscc_mdio_priv *priv = dev_get_priv(dev); 50 + u32 val; 51 + int ret; 52 + 53 + if (mscc_mdio_wait_busy(priv)) 54 + return -ETIMEDOUT; 55 + 56 + ret = regmap_write(priv->map, MSCC_MIIM_REG_CMD, 57 + MSCC_MIIM_CMD_VLD | 58 + (addr << MSCC_MIIM_CMD_PHYAD_SHIFT) | 59 + (reg << MSCC_MIIM_CMD_REGAD_SHIFT) | 60 + MSCC_MIIM_CMD_OPR_READ); 61 + if (ret) 62 + return ret; 63 + 64 + if (mscc_mdio_wait_busy(priv)) 65 + return -ETIMEDOUT; 66 + 67 + regmap_read(priv->map, MSCC_MIIM_REG_DATA, &val); 68 + if (val & MSCC_MIIM_DATA_ERROR) 69 + return -EIO; 70 + 71 + return FIELD_GET(MSCC_MIIM_DATA_MASK, val); 72 + } 73 + 74 + int mscc_mdio_write(struct udevice *dev, int addr, int devad, int reg, u16 val) 75 + { 76 + struct mscc_mdio_priv *priv = dev_get_priv(dev); 77 + int ret; 78 + 79 + if (mscc_mdio_wait_busy(priv)) 80 + return -ETIMEDOUT; 81 + 82 + ret = regmap_write(priv->map, MSCC_MIIM_REG_CMD, 83 + MSCC_MIIM_CMD_VLD | 84 + (addr << MSCC_MIIM_CMD_PHYAD_SHIFT) | 85 + (reg << MSCC_MIIM_CMD_REGAD_SHIFT) | 86 + (val << MSCC_MIIM_CMD_WRDATA_SHIFT) | 87 + MSCC_MIIM_CMD_OPR_WRITE); 88 + 89 + return ret; 90 + } 91 + 92 + static const struct mdio_ops mscc_mdio_ops = { 93 + .read = mscc_mdio_read, 94 + .write = mscc_mdio_write, 95 + }; 96 + 97 + static int mscc_mdio_bind(struct udevice *dev) 98 + { 99 + if (ofnode_valid(dev_ofnode(dev))) 100 + device_set_name(dev, ofnode_get_name(dev_ofnode(dev))); 101 + 102 + return 0; 103 + } 104 + 105 + static int mscc_mdio_probe(struct udevice *dev) 106 + { 107 + struct mscc_mdio_priv *priv = dev_get_priv(dev); 108 + int ret; 109 + 110 + ret = regmap_init_mem(dev_ofnode(dev), &priv->map); 111 + if (ret) 112 + return -EINVAL; 113 + 114 + /* Enter Clause 22 mode */ 115 + ret = regmap_update_bits(priv->map, MSCC_MIIM_REG_CFG, 116 + MSCC_MIIM_CFG_ST_CFG_MASK, 117 + FIELD_PREP(MSCC_MIIM_CFG_ST_CFG_MASK, 118 + MSCC_MIIM_C22)); 119 + 120 + return ret; 121 + } 122 + 123 + static const struct udevice_id mscc_mdio_ids[] = { 124 + { .compatible = "mscc,ocelot-miim", }, 125 + { } 126 + }; 127 + 128 + U_BOOT_DRIVER(mscc_mdio) = { 129 + .name = "mscc_mdio", 130 + .id = UCLASS_MDIO, 131 + .of_match = mscc_mdio_ids, 132 + .bind = mscc_mdio_bind, 133 + .probe = mscc_mdio_probe, 134 + .ops = &mscc_mdio_ops, 135 + .priv_auto = sizeof(struct mscc_mdio_priv), 136 + };