1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2022 Soren Schmidt <sos@deepcore.dk> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $Id: eqos_fdt.c 1049 2022-12-03 14:25:46Z sos $ 29 */ 30 31 #include "opt_platform.h" 32 33 #include <sys/param.h> 34 #include <sys/bus.h> 35 #include <sys/kernel.h> 36 #include <sys/module.h> 37 #include <sys/systm.h> 38 #include <sys/endian.h> 39 #include <sys/hash.h> 40 #include <sys/gpio.h> 41 #include <sys/rman.h> 42 #include <sys/socket.h> 43 #include <machine/bus.h> 44 45 #include <net/if.h> 46 #include <net/if_media.h> 47 #include <dev/mii/mii.h> 48 #include <dev/mii/miivar.h> 49 50 #include <dev/ofw/ofw_bus.h> 51 #include <dev/ofw/ofw_bus_subr.h> 52 53 #include <dev/extres/clk/clk.h> 54 #include <dev/extres/hwreset/hwreset.h> 55 #include <dev/extres/regulator/regulator.h> 56 #include <dev/extres/syscon/syscon.h> 57 58 #include <dev/eqos/if_eqos_var.h> 59 60 #include "if_eqos_if.h" 61 #include "syscon_if.h" 62 #include "gpio_if.h" 63 #include "rk_otp_if.h" 64 65 #define RK356XGMAC0 0xfe2a0000 66 #define RK356XGMAC1 0xfe010000 67 #define RK3588GMAC0 0xfe1b0000 68 #define RK3588GMAC1 0xfe1c0000 69 70 #define EQOS_GRF_GMAC0 0x0380 71 #define EQOS_GRF_GMAC1 0x0388 72 #define EQOS_CON0_OFFSET 0 73 #define EQOS_CON1_OFFSET 4 74 75 #define EQOS_GMAC_PHY_INTF_SEL_RGMII 0x00fc0010 76 #define EQOS_GMAC_PHY_INTF_SEL_RMII 0x00fc0040 77 #define EQOS_GMAC_RXCLK_DLY_ENABLE 0x00020002 78 #define EQOS_GMAC_RXCLK_DLY_DISABLE 0x00020000 79 #define EQOS_GMAC_TXCLK_DLY_ENABLE 0x00010001 80 #define EQOS_GMAC_TXCLK_DLY_DISABLE 0x00010000 81 #define EQOS_GMAC_CLK_RX_DL_CFG(val) (0x7f000000 | val << 8) 82 #define EQOS_GMAC_CLK_TX_DL_CFG(val) (0x007f0000 | val) 83 84 #define WR4(sc, o, v) bus_write_4(sc->res[EQOS_RES_MEM], (o), (v)) 85 86 static const struct ofw_compat_data compat_data[] = { 87 {"snps,dwmac-4.20a", 1}, 88 { NULL, 0 } 89 }; 90 91 92 static int 93 eqos_phy_reset(device_t dev) 94 { 95 pcell_t gpio_prop[4]; 96 pcell_t delay_prop[3]; 97 phandle_t node, gpio_node; 98 device_t gpio; 99 uint32_t pin, flags; 100 uint32_t pin_value; 101 102 node = ofw_bus_get_node(dev); 103 if (OF_getencprop(node, "snps,reset-gpio", 104 gpio_prop, sizeof(gpio_prop)) <= 0) 105 return (0); 106 107 if (OF_getencprop(node, "snps,reset-delays-us", 108 delay_prop, sizeof(delay_prop)) <= 0) { 109 device_printf(dev, 110 "Wrong property for snps,reset-delays-us"); 111 return (ENXIO); 112 } 113 114 gpio_node = OF_node_from_xref(gpio_prop[0]); 115 if ((gpio = OF_device_from_xref(gpio_prop[0])) == NULL) { 116 device_printf(dev, 117 "Can't find gpio controller for phy reset\n"); 118 return (ENXIO); 119 } 120 121 if (GPIO_MAP_GPIOS(gpio, node, gpio_node, 122 nitems(gpio_prop) - 1, 123 gpio_prop + 1, &pin, &flags) != 0) { 124 device_printf(dev, "Can't map gpio for phy reset\n"); 125 return (ENXIO); 126 } 127 128 pin_value = GPIO_PIN_LOW; 129 if (OF_hasprop(node, "snps,reset-active-low")) 130 pin_value = GPIO_PIN_HIGH; 131 132 GPIO_PIN_SETFLAGS(gpio, pin, GPIO_PIN_OUTPUT); 133 GPIO_PIN_SET(gpio, pin, pin_value); 134 DELAY(delay_prop[0]); 135 GPIO_PIN_SET(gpio, pin, !pin_value); 136 DELAY(delay_prop[1]); 137 GPIO_PIN_SET(gpio, pin, pin_value); 138 DELAY(delay_prop[2]); 139 140 return (0); 141 } 142 143 static int 144 eqos_fdt_init(device_t dev) 145 { 146 struct eqos_softc *sc = device_get_softc(dev); 147 phandle_t node = ofw_bus_get_node(dev); 148 hwreset_t eqos_reset; 149 regulator_t eqos_supply; 150 uint32_t rx_delay, tx_delay; 151 uint8_t buffer[16]; 152 clk_t stmmaceth, mac_clk_rx, mac_clk_tx, aclk_mac, pclk_mac; 153 uint64_t freq; 154 int error; 155 156 if (OF_hasprop(node, "rockchip,grf") && 157 syscon_get_by_ofw_property(dev, node, "rockchip,grf", &sc->grf)) { 158 device_printf(dev, "cannot get grf driver handle\n"); 159 return (ENXIO); 160 } 161 162 /* figure out if gmac0 or gmac1 offset */ 163 switch (rman_get_start(sc->res[EQOS_RES_MEM])) { 164 case RK356XGMAC0: /* RK356X gmac0 */ 165 sc->grf_offset = EQOS_GRF_GMAC0; 166 break; 167 case RK356XGMAC1: /* RK356X gmac1 */ 168 sc->grf_offset = EQOS_GRF_GMAC1; 169 break; 170 case RK3588GMAC0: /* RK3588 gmac0 */ 171 case RK3588GMAC1: /* RK3588 gmac1 */ 172 default: 173 device_printf(dev, "Unknown eqos address\n"); 174 return (ENXIO); 175 } 176 177 if (hwreset_get_by_ofw_idx(dev, node, 0, &eqos_reset)) { 178 device_printf(dev, "cannot get reset\n"); 179 return (ENXIO); 180 } 181 hwreset_assert(eqos_reset); 182 183 error = clk_set_assigned(dev, ofw_bus_get_node(dev)); 184 if (error != 0) { 185 device_printf(dev, "clk_set_assigned failed\n"); 186 return (error); 187 } 188 189 if (clk_get_by_ofw_name(dev, 0, "stmmaceth", &stmmaceth) == 0) { 190 error = clk_enable(stmmaceth); 191 if (error != 0) { 192 device_printf(dev, "could not enable main clock\n"); 193 return (error); 194 } 195 if (bootverbose) { 196 clk_get_freq(stmmaceth, &freq); 197 device_printf(dev, "MAC clock(%s) freq: %jd\n", 198 clk_get_name(stmmaceth), (intmax_t)freq); 199 } 200 } 201 else { 202 device_printf(dev, "could not find clock stmmaceth\n"); 203 } 204 205 if (clk_get_by_ofw_name(dev, 0, "mac_clk_rx", &mac_clk_rx) != 0) { 206 device_printf(dev, "could not get mac_clk_rx clock\n"); 207 mac_clk_rx = NULL; 208 } 209 210 if (clk_get_by_ofw_name(dev, 0, "mac_clk_tx", &mac_clk_tx) != 0) { 211 device_printf(dev, "could not get mac_clk_tx clock\n"); 212 mac_clk_tx = NULL; 213 } 214 215 if (clk_get_by_ofw_name(dev, 0, "aclk_mac", &aclk_mac) != 0) { 216 device_printf(dev, "could not get aclk_mac clock\n"); 217 aclk_mac = NULL; 218 } 219 220 if (clk_get_by_ofw_name(dev, 0, "pclk_mac", &pclk_mac) != 0) { 221 device_printf(dev, "could not get pclk_mac clock\n"); 222 pclk_mac = NULL; 223 } 224 225 if (aclk_mac) 226 clk_enable(aclk_mac); 227 if (pclk_mac) 228 clk_enable(pclk_mac); 229 if (mac_clk_tx) 230 clk_enable(mac_clk_tx); 231 232 sc->csr_clock = 125000000; 233 sc->csr_clock_range = GMAC_MAC_MDIO_ADDRESS_CR_100_150; 234 235 if (OF_getencprop(node, "tx_delay", &tx_delay, sizeof(tx_delay)) <= 0) 236 tx_delay = 0x30; 237 if (OF_getencprop(node, "rx_delay", &rx_delay, sizeof(rx_delay)) <= 0) 238 rx_delay = 0x10; 239 240 SYSCON_WRITE_4(sc->grf, sc->grf_offset + EQOS_CON0_OFFSET, 241 EQOS_GMAC_CLK_RX_DL_CFG(rx_delay) | 242 EQOS_GMAC_CLK_TX_DL_CFG(tx_delay)); 243 SYSCON_WRITE_4(sc->grf, sc->grf_offset + EQOS_CON1_OFFSET, 244 EQOS_GMAC_PHY_INTF_SEL_RGMII | 245 EQOS_GMAC_RXCLK_DLY_ENABLE | 246 EQOS_GMAC_TXCLK_DLY_ENABLE); 247 248 if (!regulator_get_by_ofw_property(dev, 0, "phy-supply", 249 &eqos_supply)) { 250 if (regulator_enable(eqos_supply)) 251 device_printf(dev, "cannot enable 'phy' regulator\n"); 252 } 253 else 254 device_printf(dev, "no phy-supply property\n"); 255 256 if (eqos_phy_reset(dev)) 257 return (ENXIO); 258 259 if (eqos_reset) 260 hwreset_deassert(eqos_reset); 261 262 /* set the MAC address if we have OTP data handy */ 263 if (!RK_OTP_READ(dev, buffer, 0, sizeof(buffer))) { 264 uint32_t mac; 265 266 mac = hash32_buf(buffer, sizeof(buffer), HASHINIT); 267 WR4(sc, GMAC_MAC_ADDRESS0_LOW, 268 htobe32((mac & 0xffffff00) | 0x22)); 269 270 mac = hash32_buf(buffer, sizeof(buffer), mac); 271 WR4(sc, GMAC_MAC_ADDRESS0_HIGH, 272 htobe16((mac & 0x0000ffff) + (device_get_unit(dev) << 8))); 273 } 274 275 return (0); 276 } 277 278 static int 279 eqos_fdt_probe(device_t dev) 280 { 281 282 if (!ofw_bus_status_okay(dev)) 283 return (ENXIO); 284 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) 285 return (ENXIO); 286 287 device_set_desc(dev, "DesignWare EQOS Gigabit ethernet"); 288 289 return (BUS_PROBE_DEFAULT); 290 } 291 292 293 static device_method_t eqos_fdt_methods[] = { 294 /* Device interface */ 295 DEVMETHOD(device_probe, eqos_fdt_probe), 296 297 /* EQOS interface */ 298 DEVMETHOD(if_eqos_init, eqos_fdt_init), 299 300 DEVMETHOD_END 301 }; 302 303 DEFINE_CLASS_1(eqos, eqos_fdt_driver, eqos_fdt_methods, 304 sizeof(struct eqos_softc), eqos_driver); 305 DRIVER_MODULE(eqos, simplebus, eqos_fdt_driver, 0, 0); 306 MODULE_DEPEND(eqos, ether, 1, 1, 1); 307 MODULE_DEPEND(eqos, miibus, 1, 1, 1); 308