1 /* $NetBSD: jh7110_eqos.c,v 1.2 2024/11/17 06:56:58 skrll Exp $ */ 2 3 /*- 4 * Copyright (c) 2024 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Nick Hudson 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: jh7110_eqos.c,v 1.2 2024/11/17 06:56:58 skrll Exp $"); 34 35 #include <sys/param.h> 36 37 #include <sys/param.h> 38 #include <sys/bus.h> 39 #include <sys/device.h> 40 #include <sys/rndsource.h> 41 42 #include <net/if_ether.h> 43 #include <net/if_media.h> 44 45 #include <dev/fdt/fdtvar.h> 46 47 #include <dev/mii/miivar.h> 48 49 #include <dev/ic/dwc_eqos_var.h> 50 51 #include <prop/proplib.h> 52 53 #include <riscv/starfive/jh71x0_eth.h> 54 55 struct jh7110_eqos_softc { 56 struct eqos_softc sc_eqos; 57 struct jh71x0_eth_softc sc_jh71x0eth; 58 }; 59 60 static void 61 jh7110_parse_phyprops(struct jh7110_eqos_softc *jh_sc, int phandle) 62 { 63 struct eqos_softc * const sc = &jh_sc->sc_eqos; 64 prop_dictionary_t dict = device_properties(sc->sc_dev); 65 66 if (of_hasprop(phandle, "motorcomm,tx-clk-adj-enabled")) { 67 prop_dictionary_set_bool(dict, "motorcomm,tx-clk-adj-enabled", 68 true); 69 } 70 if (of_hasprop(phandle, "motorcomm,tx-clk-100-inverted")) { 71 prop_dictionary_set_bool(dict, "motorcomm,tx-clk-100-inverted", 72 true); 73 } 74 if (of_hasprop(phandle, "motorcomm,tx-clk-1000-inverted")) { 75 prop_dictionary_set_bool(dict, "motorcomm,tx-clk-1000-inverted", 76 true); 77 } 78 79 uint32_t val; 80 if (of_getprop_uint32(phandle, 81 "motorcomm,rx-clk-drv-microamp", &val) == 0) { 82 prop_dictionary_set_uint32(dict, 83 "motorcomm,rx-clk-drv-microamp", val); 84 } 85 if (of_getprop_uint32(phandle, 86 "motorcomm,rx-data-drv-microamp", &val) == 0) { 87 prop_dictionary_set_uint32(dict, 88 "motorcomm,rx-data-drv-microamp", val); 89 } 90 if (of_getprop_uint32(phandle, 91 "rx-internal-delay-ps", &val) == 0) { 92 prop_dictionary_set_uint32(dict, 93 "rx-internal-delay-ps", val); 94 } 95 if (of_getprop_uint32(phandle, 96 "tx-internal-delay-ps", &val) == 0) { 97 prop_dictionary_set_uint32(dict, 98 "tx-internal-delay-ps", val); 99 } 100 } 101 102 /* Compat string(s) */ 103 static const struct device_compatible_entry compat_data[] = { 104 { .compat = "starfive,jh7110-dwmac" }, 105 DEVICE_COMPAT_EOL 106 }; 107 108 static int 109 jh7110_eqos_match(device_t parent, cfdata_t cf, void *aux) 110 { 111 struct fdt_attach_args * const faa = aux; 112 113 return of_compatible_match(faa->faa_phandle, compat_data); 114 } 115 116 static void 117 jh7110_eqos_attach(device_t parent, device_t self, void *aux) 118 { 119 struct jh7110_eqos_softc * const sc = device_private(self); 120 struct jh71x0_eth_softc * const jheth_sc = &sc->sc_jh71x0eth; 121 struct eqos_softc * const eqos_sc = &sc->sc_eqos; 122 struct fdt_attach_args * const faa = aux; 123 const int phandle = faa->faa_phandle; 124 char intrstr[128]; 125 int error; 126 127 sc->sc_eqos.sc_dev = self; 128 sc->sc_eqos.sc_bst = faa->faa_bst; 129 sc->sc_eqos.sc_dmat = faa->faa_dmat; 130 sc->sc_jh71x0eth.sc_dev = self; 131 sc->sc_jh71x0eth.sc_phy = MII_PHY_ANY; 132 sc->sc_jh71x0eth.sc_type = JH71X0ETH_EQOS; 133 134 error = jh71x0_eth_attach(jheth_sc, faa, &sc->sc_eqos.sc_bsh); 135 if (error) 136 return; 137 138 jh7110_parse_phyprops(sc, sc->sc_jh71x0eth.sc_phandle_phy); 139 140 // aprint_naive("\n"); 141 // aprint_normal(": Gigabit Ethernet Controller\n"); 142 143 #define CSR_RATE_RGMII 125000000 /* default */ 144 eqos_sc->sc_csr_clock = CSR_RATE_RGMII; 145 error = eqos_attach(eqos_sc); 146 if (error) 147 return; 148 if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) { 149 aprint_error(": failed to decode interrupt\n"); 150 return; 151 } 152 void *ih = fdtbus_intr_establish_xname(phandle, 0, IPL_NET, 153 FDT_INTR_MPSAFE, eqos_intr, eqos_sc, device_xname(self)); 154 if (ih == NULL) { 155 aprint_error_dev(self, "failed to establish interrupt on %s\n", 156 intrstr); 157 // XXXNH unwind 158 return; 159 } 160 aprint_normal_dev(self, "interrupting on %s\n", intrstr); 161 } 162 163 CFATTACH_DECL_NEW(jh7110_eqos, sizeof(struct jh7110_eqos_softc), 164 jh7110_eqos_match, jh7110_eqos_attach, NULL, NULL); 165