Home | History | Annotate | Line # | Download | only in starfive
      1 /* $NetBSD: jh71x0_eth.c,v 1.1 2024/10/26 15:49:43 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: jh71x0_eth.c,v 1.1 2024/10/26 15:49:43 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 #include <dev/fdt/syscon.h>
     47 
     48 #include <dev/mii/miivar.h>
     49 
     50 //#include <prop/proplib.h>
     51 
     52 #include <riscv/starfive/jh71x0_eth.h>
     53 
     54 
     55 /* Register definitions */
     56 
     57 #define	STARFIVE_GMAC_PHY_INFT_RGMII		0x1
     58 #define	STARFIVE_GMAC_PHY_INFT_RMII		0x4
     59 #define	STARFIVE_GMAC_PHY_INFT_MASK		__BITS(2, 0)
     60 
     61 #define JH7100_SYSMAIN_REGISTER49_DLYCHAIN	0xc8
     62 
     63 static void
     64 jh71x0_eth_set_phy_rgmii_id(struct jh71x0_eth_softc *jh_sc)
     65 {
     66 	const uint32_t reg = jh_sc->sc_phy_syscon_reg;
     67 	const uint32_t shift = jh_sc->sc_phy_syscon_shift;
     68 
     69 	syscon_lock(jh_sc->sc_syscon);
     70 	uint32_t val = syscon_read_4(jh_sc->sc_syscon, reg);
     71 	val &= ~(STARFIVE_GMAC_PHY_INFT_MASK << shift);
     72 	val |= STARFIVE_GMAC_PHY_INFT_RGMII << shift;
     73 	syscon_write_4(jh_sc->sc_syscon, reg, val);
     74 
     75 	if (jh_sc->sc_type == JH71X0ETH_GMAC) {
     76 		syscon_write_4(jh_sc->sc_syscon,
     77 		    JH7100_SYSMAIN_REGISTER49_DLYCHAIN, 4);
     78 	}
     79 
     80 	syscon_unlock(jh_sc->sc_syscon);
     81 }
     82 
     83 
     84 int
     85 jh71x0_eth_attach(struct jh71x0_eth_softc *jh_sc, struct fdt_attach_args *faa,
     86     bus_space_handle_t *bshp)
     87 {
     88 	const int phandle = faa->faa_phandle;
     89 	int phandle_phy;
     90 	bus_addr_t addr;
     91 	bus_size_t size;
     92 	int error;
     93 	int n;
     94 
     95 	error = fdtbus_get_reg(phandle, 0, &addr, &size);
     96 	if (error) {
     97 		aprint_error(": couldn't get registers\n");
     98 		return ENXIO;
     99 	}
    100 
    101 	int len;
    102 	const u_int * const syscon_data =
    103 	    fdtbus_get_prop(phandle, "starfive,syscon", &len);
    104 	if (syscon_data == NULL) {
    105 		aprint_error(": couldn't get 'starfive,syscon' property\n");
    106 		return ENXIO;
    107 	}
    108 	if (len != 3 * sizeof(uint32_t)) {
    109 		aprint_error(": incorrect syscon data (len = %u)\n",
    110 		    len);
    111 		return ENXIO;
    112 	}
    113 
    114 	const int syscon_phandle =
    115 	    fdtbus_get_phandle_from_native(be32dec(&syscon_data[0]));
    116 
    117 	jh_sc->sc_syscon = fdtbus_syscon_lookup(syscon_phandle);
    118 	if (jh_sc->sc_syscon == NULL) {
    119 		aprint_error(": couldn't get syscon\n");
    120 		return ENXIO;
    121 	}
    122 
    123 	jh_sc->sc_phy_syscon_reg = be32dec(&syscon_data[1]);
    124 	jh_sc->sc_phy_syscon_shift = be32dec(&syscon_data[2]);
    125 
    126 	if (bus_space_map(faa->faa_bst, addr, size, 0, bshp) != 0) {
    127 		aprint_error(": couldn't map registers\n");
    128 		return ENXIO;
    129 	}
    130 
    131 	/* enable clocks */
    132 	struct clk *clk;
    133 	fdtbus_clock_assign(phandle);
    134 	for (n = 0; (clk = fdtbus_clock_get_index(phandle, n)) != NULL; n++) {
    135 		if (clk_enable(clk) != 0) {
    136 			aprint_error(": couldn't enable clock #%d\n", n);
    137 			return ENXIO;
    138 		}
    139 	}
    140 	/* de-assert resets */
    141 	struct fdtbus_reset *rst;
    142 	for (n = 0; (rst = fdtbus_reset_get_index(phandle, n)) != NULL; n++) {
    143 		if (fdtbus_reset_deassert(rst) != 0) {
    144 			aprint_error(": couldn't de-assert reset #%d\n", n);
    145 			return ENXIO;
    146 		}
    147 	}
    148 
    149 	const char *phy_mode = fdtbus_get_string(phandle, "phy-mode");
    150 	if (phy_mode == NULL)
    151 		phy_mode = "rgmii-id";	/* default: RGMII */
    152 
    153 	phandle_phy = fdtbus_get_phandle(phandle, "phy-handle");
    154 	if (phandle_phy > 0) {
    155 		of_getprop_uint32(phandle_phy, "reg", &jh_sc->sc_phy);
    156 	}
    157 	jh_sc->sc_phandle_phy = phandle_phy;
    158 
    159 	if (strncmp(phy_mode, "rgmii-id", 8) == 0) {
    160 		jh71x0_eth_set_phy_rgmii_id(jh_sc);
    161 	} else {
    162 		aprint_error(": unsupported phy-mode '%s'\n", phy_mode);
    163 		return ENXIO;
    164 	}
    165 
    166 	if (!of_hasprop(phandle, "starfive,tx-use-rgmii-clk")) {
    167 		jh_sc->sc_clk_tx = fdtbus_clock_get(phandle, "tx");
    168 	}
    169 
    170 	const uint8_t *macaddr = fdtbus_get_prop(phandle, "local-mac-address",
    171 	   &len);
    172 	if (macaddr != NULL && len == ETHER_ADDR_LEN) {
    173 		prop_dictionary_t prop = device_properties(jh_sc->sc_dev);
    174 		prop_dictionary_set_data(prop, "mac-address", macaddr, len);
    175 	}
    176 
    177 	return 0;
    178 }
    179 
    180