Home | History | Annotate | Line # | Download | only in starfive
      1  1.1  skrll /* $NetBSD: jh71x0_eth.c,v 1.1 2024/10/26 15:49:43 skrll Exp $ */
      2  1.1  skrll 
      3  1.1  skrll /*-
      4  1.1  skrll  * Copyright (c) 2024 The NetBSD Foundation, Inc.
      5  1.1  skrll  * All rights reserved.
      6  1.1  skrll  *
      7  1.1  skrll  * This code is derived from software contributed to The NetBSD Foundation
      8  1.1  skrll  * by Nick Hudson
      9  1.1  skrll  *
     10  1.1  skrll  * Redistribution and use in source and binary forms, with or without
     11  1.1  skrll  * modification, are permitted provided that the following conditions
     12  1.1  skrll  * are met:
     13  1.1  skrll  * 1. Redistributions of source code must retain the above copyright
     14  1.1  skrll  *    notice, this list of conditions and the following disclaimer.
     15  1.1  skrll  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1  skrll  *    notice, this list of conditions and the following disclaimer in the
     17  1.1  skrll  *    documentation and/or other materials provided with the distribution.
     18  1.1  skrll  *
     19  1.1  skrll  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  1.1  skrll  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  1.1  skrll  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  1.1  skrll  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  1.1  skrll  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  1.1  skrll  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  1.1  skrll  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  1.1  skrll  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  1.1  skrll  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  1.1  skrll  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  1.1  skrll  * POSSIBILITY OF SUCH DAMAGE.
     30  1.1  skrll  */
     31  1.1  skrll 
     32  1.1  skrll #include <sys/cdefs.h>
     33  1.1  skrll __KERNEL_RCSID(0, "$NetBSD: jh71x0_eth.c,v 1.1 2024/10/26 15:49:43 skrll Exp $");
     34  1.1  skrll 
     35  1.1  skrll #include <sys/param.h>
     36  1.1  skrll 
     37  1.1  skrll #include <sys/param.h>
     38  1.1  skrll #include <sys/bus.h>
     39  1.1  skrll #include <sys/device.h>
     40  1.1  skrll #include <sys/rndsource.h>
     41  1.1  skrll 
     42  1.1  skrll #include <net/if_ether.h>
     43  1.1  skrll #include <net/if_media.h>
     44  1.1  skrll 
     45  1.1  skrll #include <dev/fdt/fdtvar.h>
     46  1.1  skrll #include <dev/fdt/syscon.h>
     47  1.1  skrll 
     48  1.1  skrll #include <dev/mii/miivar.h>
     49  1.1  skrll 
     50  1.1  skrll //#include <prop/proplib.h>
     51  1.1  skrll 
     52  1.1  skrll #include <riscv/starfive/jh71x0_eth.h>
     53  1.1  skrll 
     54  1.1  skrll 
     55  1.1  skrll /* Register definitions */
     56  1.1  skrll 
     57  1.1  skrll #define	STARFIVE_GMAC_PHY_INFT_RGMII		0x1
     58  1.1  skrll #define	STARFIVE_GMAC_PHY_INFT_RMII		0x4
     59  1.1  skrll #define	STARFIVE_GMAC_PHY_INFT_MASK		__BITS(2, 0)
     60  1.1  skrll 
     61  1.1  skrll #define JH7100_SYSMAIN_REGISTER49_DLYCHAIN	0xc8
     62  1.1  skrll 
     63  1.1  skrll static void
     64  1.1  skrll jh71x0_eth_set_phy_rgmii_id(struct jh71x0_eth_softc *jh_sc)
     65  1.1  skrll {
     66  1.1  skrll 	const uint32_t reg = jh_sc->sc_phy_syscon_reg;
     67  1.1  skrll 	const uint32_t shift = jh_sc->sc_phy_syscon_shift;
     68  1.1  skrll 
     69  1.1  skrll 	syscon_lock(jh_sc->sc_syscon);
     70  1.1  skrll 	uint32_t val = syscon_read_4(jh_sc->sc_syscon, reg);
     71  1.1  skrll 	val &= ~(STARFIVE_GMAC_PHY_INFT_MASK << shift);
     72  1.1  skrll 	val |= STARFIVE_GMAC_PHY_INFT_RGMII << shift;
     73  1.1  skrll 	syscon_write_4(jh_sc->sc_syscon, reg, val);
     74  1.1  skrll 
     75  1.1  skrll 	if (jh_sc->sc_type == JH71X0ETH_GMAC) {
     76  1.1  skrll 		syscon_write_4(jh_sc->sc_syscon,
     77  1.1  skrll 		    JH7100_SYSMAIN_REGISTER49_DLYCHAIN, 4);
     78  1.1  skrll 	}
     79  1.1  skrll 
     80  1.1  skrll 	syscon_unlock(jh_sc->sc_syscon);
     81  1.1  skrll }
     82  1.1  skrll 
     83  1.1  skrll 
     84  1.1  skrll int
     85  1.1  skrll jh71x0_eth_attach(struct jh71x0_eth_softc *jh_sc, struct fdt_attach_args *faa,
     86  1.1  skrll     bus_space_handle_t *bshp)
     87  1.1  skrll {
     88  1.1  skrll 	const int phandle = faa->faa_phandle;
     89  1.1  skrll 	int phandle_phy;
     90  1.1  skrll 	bus_addr_t addr;
     91  1.1  skrll 	bus_size_t size;
     92  1.1  skrll 	int error;
     93  1.1  skrll 	int n;
     94  1.1  skrll 
     95  1.1  skrll 	error = fdtbus_get_reg(phandle, 0, &addr, &size);
     96  1.1  skrll 	if (error) {
     97  1.1  skrll 		aprint_error(": couldn't get registers\n");
     98  1.1  skrll 		return ENXIO;
     99  1.1  skrll 	}
    100  1.1  skrll 
    101  1.1  skrll 	int len;
    102  1.1  skrll 	const u_int * const syscon_data =
    103  1.1  skrll 	    fdtbus_get_prop(phandle, "starfive,syscon", &len);
    104  1.1  skrll 	if (syscon_data == NULL) {
    105  1.1  skrll 		aprint_error(": couldn't get 'starfive,syscon' property\n");
    106  1.1  skrll 		return ENXIO;
    107  1.1  skrll 	}
    108  1.1  skrll 	if (len != 3 * sizeof(uint32_t)) {
    109  1.1  skrll 		aprint_error(": incorrect syscon data (len = %u)\n",
    110  1.1  skrll 		    len);
    111  1.1  skrll 		return ENXIO;
    112  1.1  skrll 	}
    113  1.1  skrll 
    114  1.1  skrll 	const int syscon_phandle =
    115  1.1  skrll 	    fdtbus_get_phandle_from_native(be32dec(&syscon_data[0]));
    116  1.1  skrll 
    117  1.1  skrll 	jh_sc->sc_syscon = fdtbus_syscon_lookup(syscon_phandle);
    118  1.1  skrll 	if (jh_sc->sc_syscon == NULL) {
    119  1.1  skrll 		aprint_error(": couldn't get syscon\n");
    120  1.1  skrll 		return ENXIO;
    121  1.1  skrll 	}
    122  1.1  skrll 
    123  1.1  skrll 	jh_sc->sc_phy_syscon_reg = be32dec(&syscon_data[1]);
    124  1.1  skrll 	jh_sc->sc_phy_syscon_shift = be32dec(&syscon_data[2]);
    125  1.1  skrll 
    126  1.1  skrll 	if (bus_space_map(faa->faa_bst, addr, size, 0, bshp) != 0) {
    127  1.1  skrll 		aprint_error(": couldn't map registers\n");
    128  1.1  skrll 		return ENXIO;
    129  1.1  skrll 	}
    130  1.1  skrll 
    131  1.1  skrll 	/* enable clocks */
    132  1.1  skrll 	struct clk *clk;
    133  1.1  skrll 	fdtbus_clock_assign(phandle);
    134  1.1  skrll 	for (n = 0; (clk = fdtbus_clock_get_index(phandle, n)) != NULL; n++) {
    135  1.1  skrll 		if (clk_enable(clk) != 0) {
    136  1.1  skrll 			aprint_error(": couldn't enable clock #%d\n", n);
    137  1.1  skrll 			return ENXIO;
    138  1.1  skrll 		}
    139  1.1  skrll 	}
    140  1.1  skrll 	/* de-assert resets */
    141  1.1  skrll 	struct fdtbus_reset *rst;
    142  1.1  skrll 	for (n = 0; (rst = fdtbus_reset_get_index(phandle, n)) != NULL; n++) {
    143  1.1  skrll 		if (fdtbus_reset_deassert(rst) != 0) {
    144  1.1  skrll 			aprint_error(": couldn't de-assert reset #%d\n", n);
    145  1.1  skrll 			return ENXIO;
    146  1.1  skrll 		}
    147  1.1  skrll 	}
    148  1.1  skrll 
    149  1.1  skrll 	const char *phy_mode = fdtbus_get_string(phandle, "phy-mode");
    150  1.1  skrll 	if (phy_mode == NULL)
    151  1.1  skrll 		phy_mode = "rgmii-id";	/* default: RGMII */
    152  1.1  skrll 
    153  1.1  skrll 	phandle_phy = fdtbus_get_phandle(phandle, "phy-handle");
    154  1.1  skrll 	if (phandle_phy > 0) {
    155  1.1  skrll 		of_getprop_uint32(phandle_phy, "reg", &jh_sc->sc_phy);
    156  1.1  skrll 	}
    157  1.1  skrll 	jh_sc->sc_phandle_phy = phandle_phy;
    158  1.1  skrll 
    159  1.1  skrll 	if (strncmp(phy_mode, "rgmii-id", 8) == 0) {
    160  1.1  skrll 		jh71x0_eth_set_phy_rgmii_id(jh_sc);
    161  1.1  skrll 	} else {
    162  1.1  skrll 		aprint_error(": unsupported phy-mode '%s'\n", phy_mode);
    163  1.1  skrll 		return ENXIO;
    164  1.1  skrll 	}
    165  1.1  skrll 
    166  1.1  skrll 	if (!of_hasprop(phandle, "starfive,tx-use-rgmii-clk")) {
    167  1.1  skrll 		jh_sc->sc_clk_tx = fdtbus_clock_get(phandle, "tx");
    168  1.1  skrll 	}
    169  1.1  skrll 
    170  1.1  skrll 	const uint8_t *macaddr = fdtbus_get_prop(phandle, "local-mac-address",
    171  1.1  skrll 	   &len);
    172  1.1  skrll 	if (macaddr != NULL && len == ETHER_ADDR_LEN) {
    173  1.1  skrll 		prop_dictionary_t prop = device_properties(jh_sc->sc_dev);
    174  1.1  skrll 		prop_dictionary_set_data(prop, "mac-address", macaddr, len);
    175  1.1  skrll 	}
    176  1.1  skrll 
    177  1.1  skrll 	return 0;
    178  1.1  skrll }
    179  1.1  skrll 
    180