1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2018-2022 Marvell International Ltd. 4 */ 5 6#include <dm.h> 7#include <fdt_support.h> 8#include <log.h> 9#include <miiphy.h> 10#include <net.h> 11#include <linux/delay.h> 12 13#include <mach/cvmx-regs.h> 14#include <mach/cvmx-csr.h> 15#include <mach/octeon-model.h> 16#include <mach/octeon-feature.h> 17#include <mach/cvmx-smix-defs.h> 18#include <mach/cvmx-config.h> 19#include <mach/cvmx-helper.h> 20#include <mach/cvmx-helper-board.h> 21#include <mach/cvmx-mdio.h> 22 23#define CVMX_SMI_DRV_CTL 0x0001180000001828ull 24#define DEFAULT_MDIO_SPEED 2500000 /** 2.5 MHz default speed */ 25 26/** 27 * cvmx_smi_drv_ctl 28 * 29 * Enables the SMI interface. 30 * 31 */ 32union cvmx_smi_drv_ctl { 33 u64 u64; 34 struct cvmx_smi_drv_ctl_s { 35 u64 reserved_14_63 : 50; 36 u64 pctl : 6; 37 u64 reserved_6_7 : 2; 38 u64 nctl : 6; 39 } s; 40}; 41 42struct octeon_mdiobus { 43 struct mii_dev *mii_dev; 44 /** 45 * The local bus is in the lower 8 bits, followed by the remote bus in 46 * the top 8 bits. Bit 16 will be set if the bus is non-local. 47 */ 48 u32 bus_id; 49 50 int node; /** Node number */ 51 int speed; /** Bus speed, normally 2.5 MHz */ 52 int fdt_node; /** Node in FDT */ 53 bool local; /** true if local MDIO bus */ 54}; 55 56static int octeon_mdio_read(struct udevice *mdio_dev, int phy_addr, 57 int dev_addr, int reg_addr) 58{ 59 struct octeon_mdiobus *p = dev_get_priv(mdio_dev); 60 struct mii_dev *dev = p->mii_dev; 61 int value; 62 63 debug("%s(0x%p(%s): bus_id=%d phy_addr=%d, 0x%x, 0x%x) - ", __func__, 64 dev, dev->name, p->bus_id, phy_addr, dev_addr, reg_addr); 65 if (IS_ENABLED(CONFIG_PHYLIB_10G) && dev_addr != MDIO_DEVAD_NONE) { 66 debug("clause 45 mode\n"); 67 value = cvmx_mdio_45_read(p->bus_id & 0xff, phy_addr, dev_addr, 68 reg_addr); 69 } else { 70 value = cvmx_mdio_read(p->bus_id & 0xff, phy_addr, reg_addr); 71 } 72 73 debug("Return value: 0x%x\n", value); 74 return value; 75} 76 77static int octeon_mdio_write(struct udevice *mdio_dev, int phy_addr, 78 int dev_addr, int reg_addr, u16 value) 79{ 80 struct octeon_mdiobus *p = dev_get_priv(mdio_dev); 81 struct mii_dev *dev = p->mii_dev; 82 83 debug("%s(0x%p(%s): bus_id=%d phy_addr=%d, 0x%x, 0x%x, 0x%x)\n", 84 __func__, dev, dev->name, p->bus_id, phy_addr, dev_addr, reg_addr, 85 value); 86 87 if (IS_ENABLED(CONFIG_PHYLIB_10G) && dev_addr != MDIO_DEVAD_NONE) { 88 debug("clause 45 mode\n"); 89 return cvmx_mdio_45_write(p->bus_id & 0xff, phy_addr, dev_addr, 90 reg_addr, value); 91 } 92 93 return cvmx_mdio_write(p->bus_id & 0xff, phy_addr, reg_addr, value); 94} 95 96/** 97 * Converts a MDIO register address to a bus number 98 * 99 * @param reg_addr MDIO base register address 100 * 101 * @return MDIO bus number or -1 if invalid address 102 */ 103int octeon_mdio_reg_addr_to_bus(u64 reg_addr) 104{ 105 int bus_base; 106 int bus; 107 108 /* Adjust the bus number based on the node number */ 109 bus_base = cvmx_csr_addr_to_node(reg_addr) * 4; 110 reg_addr = cvmx_csr_addr_strip_node(reg_addr); 111 112 switch (reg_addr) { 113 case 0x1180000001800: 114 case 0x1180000003800: /* 68XX/78XX address */ 115 bus = 0; 116 break; 117 case 0x1180000001900: 118 case 0x1180000003880: 119 bus = 1; 120 break; 121 case 0x1180000003900: 122 bus = 2; 123 break; 124 case 0x1180000003980: 125 bus = 3; 126 break; 127 default: 128 printf("%s: Unknown register address 0x%llx\n", __func__, 129 reg_addr); 130 return -1; 131 } 132 bus += bus_base; 133 debug("%s: address 0x%llx is bus %d\n", __func__, reg_addr, bus); 134 return bus; 135} 136 137static int octeon_mdio_probe(struct udevice *dev) 138{ 139 struct octeon_mdiobus *p = dev_get_priv(dev); 140 union cvmx_smi_drv_ctl drv_ctl; 141 cvmx_smix_clk_t smi_clk; 142 u64 mdio_addr; 143 int bus; 144 u64 sclock; 145 u32 sample_dly; 146 u64 denom; 147 148 mdio_addr = dev_read_addr(dev); 149 debug("%s: Translated address: 0x%llx\n", __func__, mdio_addr); 150 bus = octeon_mdio_reg_addr_to_bus(mdio_addr); 151 p->bus_id = bus; 152 debug("%s: bus: %d\n", __func__, bus); 153 154 drv_ctl.u64 = csr_rd(CVMX_SMI_DRV_CTL); 155 drv_ctl.s.pctl = dev_read_u32_default(dev, "cavium,pctl-drive-strength", 156 drv_ctl.s.pctl); 157 drv_ctl.s.nctl = dev_read_u32_default(dev, "cavium,nctl-drive-strength", 158 drv_ctl.s.nctl); 159 debug("%s: Set MDIO PCTL drive strength to 0x%x and NCTL drive strength to 0x%x\n", 160 __func__, drv_ctl.s.pctl, drv_ctl.s.nctl); 161 csr_wr(CVMX_SMI_DRV_CTL, drv_ctl.u64); 162 163 /* Set the bus speed, default is 2.5MHz */ 164 p->speed = dev_read_u32_default(dev, "cavium,max-speed", 165 DEFAULT_MDIO_SPEED); 166 sclock = gd->bus_clk; 167 smi_clk.u64 = csr_rd(CVMX_SMIX_CLK(bus & 3)); 168 smi_clk.s.phase = sclock / (p->speed * 2); 169 170 /* Allow sample delay to be specified */ 171 sample_dly = dev_read_u32_default(dev, "cavium,sample-delay", 0); 172 /* Only change the sample delay if it is set, otherwise use 173 * the default value of 2. 174 */ 175 if (sample_dly) { 176 u32 sample; 177 178 denom = (sclock * 1000ULL) / sample_dly; 179 debug("%s: sclock: %llu, sample_dly: %u ps, denom: %llu\n", 180 __func__, sclock, sample_dly, denom); 181 sample = (sclock + denom - 1) / denom; 182 debug("%s: sample: %u\n", __func__, smi_clk.s.sample); 183 if (sample < 2) { 184 printf("%s: warning: cavium,sample-delay %u ps is too small in device tree for %s\n", 185 __func__, sample_dly, dev->name); 186 sample = 2; 187 } 188 if (sample > (2 * smi_clk.s.phase - 3)) { 189 printf("%s: warning: cavium,sample-delay %u ps is too large in device tree for %s\n", 190 __func__, sample_dly, dev->name); 191 sample = 2 * smi_clk.s.phase - 3; 192 } 193 smi_clk.s.sample = sample & 0xf; 194 smi_clk.s.sample_hi = (sample >> 4) & 0xf; 195 debug("%s(%s): sample delay: %u ps (%d clocks)\n", __func__, 196 dev->name, sample_dly, smi_clk.s.sample); 197 } 198 csr_wr(CVMX_SMIX_CLK(bus & 3), smi_clk.u64); 199 200 debug("mdio clock phase: %d clocks\n", smi_clk.s.phase); 201 csr_wr(CVMX_SMIX_CLK(bus & 3), smi_clk.u64); 202 debug("Enabling SMI interface %s\n", dev->name); 203 csr_wr(CVMX_SMIX_EN(bus & 3), 1); 204 205 /* Muxed MDIO bus support removed for now! */ 206 return 0; 207} 208 209static const struct mdio_ops octeon_mdio_ops = { 210 .read = octeon_mdio_read, 211 .write = octeon_mdio_write, 212}; 213 214static const struct udevice_id octeon_mdio_ids[] = { 215 { .compatible = "cavium,octeon-3860-mdio" }, 216 {} 217}; 218 219U_BOOT_DRIVER(octeon_mdio) = { 220 .name = "octeon_mdio", 221 .id = UCLASS_MDIO, 222 .of_match = octeon_mdio_ids, 223 .probe = octeon_mdio_probe, 224 .ops = &octeon_mdio_ops, 225 .priv_auto = sizeof(struct octeon_mdiobus), 226}; 227