jh71x0_eth.c revision 1.1 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