Thu Nov 30 21:36:11 2017 UTC ()
Add support for new emac bindings


(jmcneill)
diff -r1.9 -r1.10 src/sys/arch/arm/sunxi/sunxi_emac.c

cvs diff -r1.9 -r1.10 src/sys/arch/arm/sunxi/sunxi_emac.c (expand / switch to unified diff)

--- src/sys/arch/arm/sunxi/sunxi_emac.c 2017/11/16 03:07:17 1.9
+++ src/sys/arch/arm/sunxi/sunxi_emac.c 2017/11/30 21:36:11 1.10
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: sunxi_emac.c,v 1.9 2017/11/16 03:07:17 ozaki-r Exp $ */ 1/* $NetBSD: sunxi_emac.c,v 1.10 2017/11/30 21:36:11 jmcneill Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2016-2017 Jared McNeill <jmcneill@invisible.ca> 4 * Copyright (c) 2016-2017 Jared McNeill <jmcneill@invisible.ca>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -23,27 +23,27 @@ @@ -23,27 +23,27 @@
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * 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 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29/* 29/*
30 * Allwinner Gigabit Ethernet MAC (EMAC) controller 30 * Allwinner Gigabit Ethernet MAC (EMAC) controller
31 */ 31 */
32 32
33#include "opt_net_mpsafe.h" 33#include "opt_net_mpsafe.h"
34 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36__KERNEL_RCSID(0, "$NetBSD: sunxi_emac.c,v 1.9 2017/11/16 03:07:17 ozaki-r Exp $"); 36__KERNEL_RCSID(0, "$NetBSD: sunxi_emac.c,v 1.10 2017/11/30 21:36:11 jmcneill Exp $");
37 37
38#include <sys/param.h> 38#include <sys/param.h>
39#include <sys/bus.h> 39#include <sys/bus.h>
40#include <sys/device.h> 40#include <sys/device.h>
41#include <sys/intr.h> 41#include <sys/intr.h>
42#include <sys/systm.h> 42#include <sys/systm.h>
43#include <sys/kernel.h> 43#include <sys/kernel.h>
44#include <sys/mutex.h> 44#include <sys/mutex.h>
45#include <sys/callout.h> 45#include <sys/callout.h>
46#include <sys/gpio.h> 46#include <sys/gpio.h>
47#include <sys/cprng.h> 47#include <sys/cprng.h>
48 48
49#include <net/if.h> 49#include <net/if.h>
@@ -87,43 +87,44 @@ __KERNEL_RCSID(0, "$NetBSD: sunxi_emac.c @@ -87,43 +87,44 @@ __KERNEL_RCSID(0, "$NetBSD: sunxi_emac.c
87#define RX_NEXT(n) (((n) + 1) & (RX_DESC_COUNT - 1)) 87#define RX_NEXT(n) (((n) + 1) & (RX_DESC_COUNT - 1))
88 88
89#define TX_MAX_SEGS 128 89#define TX_MAX_SEGS 128
90 90
91#define SOFT_RST_RETRY 1000 91#define SOFT_RST_RETRY 1000
92#define MII_BUSY_RETRY 1000 92#define MII_BUSY_RETRY 1000
93#define MDIO_FREQ 2500000 93#define MDIO_FREQ 2500000
94 94
95#define BURST_LEN_DEFAULT 8 95#define BURST_LEN_DEFAULT 8
96#define RX_TX_PRI_DEFAULT 0 96#define RX_TX_PRI_DEFAULT 0
97#define PAUSE_TIME_DEFAULT 0x400 97#define PAUSE_TIME_DEFAULT 0x400
98 98
99/* syscon EMAC clock register */ 99/* syscon EMAC clock register */
100#define EMAC_CLK_EPHY_ADDR (0x1f << 20) /* H3 */ 100#define EMAC_CLK_REG 0x30
101#define EMAC_CLK_EPHY_ADDR_SHIFT 20 101#define EMAC_CLK_EPHY_ADDR (0x1f << 20) /* H3 */
102#define EMAC_CLK_EPHY_LED_POL (1 << 17) /* H3 */ 102#define EMAC_CLK_EPHY_ADDR_SHIFT 20
103#define EMAC_CLK_EPHY_SHUTDOWN (1 << 16) /* H3 */ 103#define EMAC_CLK_EPHY_LED_POL (1 << 17) /* H3 */
104#define EMAC_CLK_EPHY_SELECT (1 << 15) /* H3 */ 104#define EMAC_CLK_EPHY_SHUTDOWN (1 << 16) /* H3 */
105#define EMAC_CLK_RMII_EN (1 << 13) 105#define EMAC_CLK_EPHY_SELECT (1 << 15) /* H3 */
106#define EMAC_CLK_ETXDC (0x7 << 10) 106#define EMAC_CLK_RMII_EN (1 << 13)
107#define EMAC_CLK_ETXDC_SHIFT 10 107#define EMAC_CLK_ETXDC (0x7 << 10)
108#define EMAC_CLK_ERXDC (0x1f << 5) 108#define EMAC_CLK_ETXDC_SHIFT 10
109#define EMAC_CLK_ERXDC_SHIFT 5 109#define EMAC_CLK_ERXDC (0x1f << 5)
110#define EMAC_CLK_PIT (0x1 << 2) 110#define EMAC_CLK_ERXDC_SHIFT 5
111#define EMAC_CLK_PIT_MII (0 << 2) 111#define EMAC_CLK_PIT (0x1 << 2)
112#define EMAC_CLK_PIT_RGMII (1 << 2) 112#define EMAC_CLK_PIT_MII (0 << 2)
113#define EMAC_CLK_SRC (0x3 << 0) 113#define EMAC_CLK_PIT_RGMII (1 << 2)
114#define EMAC_CLK_SRC_MII (0 << 0) 114#define EMAC_CLK_SRC (0x3 << 0)
115#define EMAC_CLK_SRC_EXT_RGMII (1 << 0) 115#define EMAC_CLK_SRC_MII (0 << 0)
116#define EMAC_CLK_SRC_RGMII (2 << 0) 116#define EMAC_CLK_SRC_EXT_RGMII (1 << 0)
 117#define EMAC_CLK_SRC_RGMII (2 << 0)
117 118
118/* Burst length of RX and TX DMA transfers */ 119/* Burst length of RX and TX DMA transfers */
119static int sunxi_emac_burst_len = BURST_LEN_DEFAULT; 120static int sunxi_emac_burst_len = BURST_LEN_DEFAULT;
120 121
121/* RX / TX DMA priority. If 1, RX DMA has priority over TX DMA. */ 122/* RX / TX DMA priority. If 1, RX DMA has priority over TX DMA. */
122static int sunxi_emac_rx_tx_pri = RX_TX_PRI_DEFAULT; 123static int sunxi_emac_rx_tx_pri = RX_TX_PRI_DEFAULT;
123 124
124/* Pause time field in the transmitted control frame */ 125/* Pause time field in the transmitted control frame */
125static int sunxi_emac_pause_time = PAUSE_TIME_DEFAULT; 126static int sunxi_emac_pause_time = PAUSE_TIME_DEFAULT;
126 127
127enum sunxi_emac_type { 128enum sunxi_emac_type {
128 EMAC_A83T = 1, 129 EMAC_A83T = 1,
129 EMAC_H3, 130 EMAC_H3,
@@ -879,26 +880,47 @@ sunxi_emac_ioctl(struct ifnet *ifp, u_lo @@ -879,26 +880,47 @@ sunxi_emac_ioctl(struct ifnet *ifp, u_lo
879 sunxi_emac_setup_rxfilter(sc); 880 sunxi_emac_setup_rxfilter(sc);
880 EMAC_UNLOCK(sc); 881 EMAC_UNLOCK(sc);
881 } 882 }
882 break; 883 break;
883 } 884 }
884 885
885#ifndef EMAC_MPSAFE 886#ifndef EMAC_MPSAFE
886 splx(s); 887 splx(s);
887#endif 888#endif
888 889
889 return error; 890 return error;
890} 891}
891 892
 893static bool
 894sunxi_emac_has_internal_phy(struct sunxi_emac_softc *sc)
 895{
 896 const char * mdio_internal_compat[] = {
 897 "allwinner,sun8i-h3-mdio-internal",
 898 NULL
 899 };
 900 int phy;
 901
 902 /* Non-standard property, for compatible with old dts files */
 903 if (of_hasprop(sc->phandle, "allwinner,use-internal-phy"))
 904 return true;
 905
 906 phy = fdtbus_get_phandle(sc->phandle, "phy-handle");
 907 if (phy == -1)
 908 return false;
 909
 910 /* For internal PHY, check compatible string of parent node */
 911 return of_compatible(OF_parent(phy), mdio_internal_compat) >= 0;
 912}
 913
892static int 914static int
893sunxi_emac_setup_phy(struct sunxi_emac_softc *sc) 915sunxi_emac_setup_phy(struct sunxi_emac_softc *sc)
894{ 916{
895 uint32_t reg, tx_delay, rx_delay; 917 uint32_t reg, tx_delay, rx_delay;
896 const char *phy_type; 918 const char *phy_type;
897 919
898 phy_type = fdtbus_get_string(sc->phandle, "phy-mode"); 920 phy_type = fdtbus_get_string(sc->phandle, "phy-mode");
899 if (phy_type == NULL) 921 if (phy_type == NULL)
900 return 0; 922 return 0;
901 923
902 aprint_debug_dev(sc->dev, "PHY type: %s\n", phy_type); 924 aprint_debug_dev(sc->dev, "PHY type: %s\n", phy_type);
903 925
904 reg = SYSCONRD4(sc, 0); 926 reg = SYSCONRD4(sc, 0);
@@ -911,27 +933,27 @@ sunxi_emac_setup_phy(struct sunxi_emac_s @@ -911,27 +933,27 @@ sunxi_emac_setup_phy(struct sunxi_emac_s
911 else 933 else
912 reg |= EMAC_CLK_PIT_MII | EMAC_CLK_SRC_MII; 934 reg |= EMAC_CLK_PIT_MII | EMAC_CLK_SRC_MII;
913 935
914 if (of_getprop_uint32(sc->phandle, "tx-delay", &tx_delay) == 0) { 936 if (of_getprop_uint32(sc->phandle, "tx-delay", &tx_delay) == 0) {
915 reg &= ~EMAC_CLK_ETXDC; 937 reg &= ~EMAC_CLK_ETXDC;
916 reg |= (tx_delay << EMAC_CLK_ETXDC_SHIFT); 938 reg |= (tx_delay << EMAC_CLK_ETXDC_SHIFT);
917 } 939 }
918 if (of_getprop_uint32(sc->phandle, "rx-delay", &rx_delay) == 0) { 940 if (of_getprop_uint32(sc->phandle, "rx-delay", &rx_delay) == 0) {
919 reg &= ~EMAC_CLK_ERXDC; 941 reg &= ~EMAC_CLK_ERXDC;
920 reg |= (rx_delay << EMAC_CLK_ERXDC_SHIFT); 942 reg |= (rx_delay << EMAC_CLK_ERXDC_SHIFT);
921 } 943 }
922 944
923 if (sc->type == EMAC_H3) { 945 if (sc->type == EMAC_H3) {
924 if (of_hasprop(sc->phandle, "allwinner,use-internal-phy")) { 946 if (sunxi_emac_has_internal_phy(sc)) {
925 reg |= EMAC_CLK_EPHY_SELECT; 947 reg |= EMAC_CLK_EPHY_SELECT;
926 reg &= ~EMAC_CLK_EPHY_SHUTDOWN; 948 reg &= ~EMAC_CLK_EPHY_SHUTDOWN;
927 if (of_hasprop(sc->phandle, 949 if (of_hasprop(sc->phandle,
928 "allwinner,leds-active-low")) 950 "allwinner,leds-active-low"))
929 reg |= EMAC_CLK_EPHY_LED_POL; 951 reg |= EMAC_CLK_EPHY_LED_POL;
930 else 952 else
931 reg &= ~EMAC_CLK_EPHY_LED_POL; 953 reg &= ~EMAC_CLK_EPHY_LED_POL;
932 954
933 /* Set internal PHY addr to 1 */ 955 /* Set internal PHY addr to 1 */
934 reg &= ~EMAC_CLK_EPHY_ADDR; 956 reg &= ~EMAC_CLK_EPHY_ADDR;
935 reg |= (1 << EMAC_CLK_EPHY_ADDR_SHIFT); 957 reg |= (1 << EMAC_CLK_EPHY_ADDR_SHIFT);
936 } else { 958 } else {
937 reg &= ~EMAC_CLK_EPHY_SELECT; 959 reg &= ~EMAC_CLK_EPHY_SELECT;
@@ -1252,35 +1274,51 @@ sunxi_emac_setup_dma(struct sunxi_emac_s @@ -1252,35 +1274,51 @@ sunxi_emac_setup_dma(struct sunxi_emac_s
1252 1274
1253 /* Write transmit and receive descriptor base address registers */ 1275 /* Write transmit and receive descriptor base address registers */
1254 WR4(sc, EMAC_TX_DMA_LIST, sc->tx.desc_ring_paddr); 1276 WR4(sc, EMAC_TX_DMA_LIST, sc->tx.desc_ring_paddr);
1255 WR4(sc, EMAC_RX_DMA_LIST, sc->rx.desc_ring_paddr); 1277 WR4(sc, EMAC_RX_DMA_LIST, sc->rx.desc_ring_paddr);
1256 1278
1257 return 0; 1279 return 0;
1258} 1280}
1259 1281
1260static int 1282static int
1261sunxi_emac_get_resources(struct sunxi_emac_softc *sc) 1283sunxi_emac_get_resources(struct sunxi_emac_softc *sc)
1262{ 1284{
1263 const int phandle = sc->phandle; 1285 const int phandle = sc->phandle;
1264 bus_addr_t addr, size; 1286 bus_addr_t addr, size;
1265 u_int n; 
1266 1287
1267 /* Map registers */ 1288 /* Map EMAC registers */
1268 for (n = 0; n < _RES_NITEMS; n++) { 1289 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0)
1269 if (fdtbus_get_reg(phandle, n, &addr, &size) != 0) 1290 return ENXIO;
 1291 if (bus_space_map(sc->bst, addr, size, 0, &sc->bsh[_RES_EMAC]) != 0)
 1292 return ENXIO;
 1293
 1294 /* Map SYSCON registers */
 1295 if (of_hasprop(phandle, "syscon")) {
 1296 const int syscon_phandle = fdtbus_get_phandle(phandle,
 1297 "syscon");
 1298 if (syscon_phandle == -1)
 1299 return ENXIO;
 1300 if (fdtbus_get_reg(syscon_phandle, 0, &addr, &size) != 0)
1270 return ENXIO; 1301 return ENXIO;
1271 if (bus_space_map(sc->bst, addr, size, 0, &sc->bsh[n]) != 0) 1302 if (size < EMAC_CLK_REG + 4)
 1303 return ENXIO;
 1304 addr += EMAC_CLK_REG;
 1305 size -= EMAC_CLK_REG;
 1306 } else {
 1307 if (fdtbus_get_reg(phandle, 1, &addr, &size) != 0)
1272 return ENXIO; 1308 return ENXIO;
1273 } 1309 }
 1310 if (bus_space_map(sc->bst, addr, size, 0, &sc->bsh[_RES_SYSCON]) != 0)
 1311 return ENXIO;
1274 1312
1275 /* Get clocks and resets. "ahb" is required, "ephy" is optional. */ 1313 /* Get clocks and resets. "ahb" is required, "ephy" is optional. */
1276 1314
1277 if ((sc->clk_ahb = fdtbus_clock_get(phandle, "ahb")) == NULL) 1315 if ((sc->clk_ahb = fdtbus_clock_get(phandle, "ahb")) == NULL)
1278 return ENXIO; 1316 return ENXIO;
1279 sc->clk_ephy = fdtbus_clock_get(phandle, "ephy"); 1317 sc->clk_ephy = fdtbus_clock_get(phandle, "ephy");
1280 1318
1281 if ((sc->rst_ahb = fdtbus_reset_get(phandle, "ahb")) == NULL) 1319 if ((sc->rst_ahb = fdtbus_reset_get(phandle, "ahb")) == NULL)
1282 return ENXIO; 1320 return ENXIO;
1283 sc->rst_ephy = fdtbus_reset_get(phandle, "ephy"); 1321 sc->rst_ephy = fdtbus_reset_get(phandle, "ephy");
1284 1322
1285 /* Regulator is optional */ 1323 /* Regulator is optional */
1286 sc->reg_phy = fdtbus_regulator_acquire(phandle, "phy-supply"); 1324 sc->reg_phy = fdtbus_regulator_acquire(phandle, "phy-supply");