diff options
author | Philipp Tomsich <philipp.tomsich@theobroma-systems.com> | 2016-04-06 18:04:57 +0200 |
---|---|---|
committer | Klaus Goger <klaus.goger@theobroma-systems.com> | 2016-09-18 13:45:14 +0200 |
commit | 5da39118172811a2fe32a4eeaee7193f8cb413ed (patch) | |
tree | 5f942d4c7778b3de6f1e03da1338ac6811ff0010 | |
parent | 6ed4d8a8686a0e8da9806a42dc90f1f0b7a0c160 (diff) |
sunxi: Support GbE controller (GMAC) for sun9i (A80)
* board/sunxi/gmac.c(eth_init_board): Add support for configuring
sun9i (A80) for Ethernet support in RGMII mode.
* arch/arm/include/asm/arch-sunxi/gpio.h (SUN9I_GPA_GMAC): Define.
* arch/arm/include/asm/arch-sunxi/clock_sun9i.h: Add Ethernet support
for sun9i (A80), defining struct sunxi_sysctl_reg (which contains
the GMAC clock control on sun9i) and AHB_{GATE,RESET}_OFFSET_GMAC
* arch/arm/include/asm/arch-sunxi/cpu_sun9i.h(SUNXI_SYSCTL_BASE):
Define.
* arch/arm/dts/sun9i-a80.dtsi: add device-tree support for GMAC on
sun9i (A80).
-rw-r--r-- | arch/arm/dts/sun9i-a80.dtsi | 66 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-sunxi/clock_sun9i.h | 20 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-sunxi/cpu_sun9i.h | 1 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-sunxi/gpio.h | 1 | ||||
-rw-r--r-- | board/sunxi/gmac.c | 32 |
5 files changed, 115 insertions, 5 deletions
diff --git a/arch/arm/dts/sun9i-a80.dtsi b/arch/arm/dts/sun9i-a80.dtsi index f68b3242b3..f9e277015c 100644 --- a/arch/arm/dts/sun9i-a80.dtsi +++ b/arch/arm/dts/sun9i-a80.dtsi @@ -51,6 +51,10 @@ / { interrupt-parent = <&gic>; + aliases { + ethernet0 = &gmac; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -438,6 +442,37 @@ clocks = <&osc32k>, <&osc24M>; clock-output-names = "r_ir"; }; + + /* + * The following two are dummy clocks, placeholders + * used in the gmac_tx clock. The gmac driver will + * choose one parent depending on the PHY interface + * mode, using clk_set_rate auto-reparenting. + * + * The actual TX clock rate is not controlled by the + * gmac_tx clock. + */ + mii_phy_tx_clk: clk@1 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <25000000>; + clock-output-names = "mii_phy_tx"; + }; + + gmac_int_tx_clk: clk@2 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <125000000>; + clock-output-names = "gmac_int_tx"; + }; + + gmac_tx_clk: clk@00800030 { + #clock-cells = <0>; + compatible = "allwinner,sun9i-a80-gmac-clk"; + reg = <0x00800030 0x4>; + clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>; + clock-output-names = "gmac_tx"; + }; }; soc { @@ -652,6 +687,23 @@ reg = <0x060005b4 0x4>; }; + gmac: ethernet@00830000 { + compatible = "allwinner,sun7i-a20-gmac"; + reg = <0x00830000 0x1054>; + interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "macirq"; + clocks = <&ahb1_gates 17>, <&gmac_tx_clk>; + clock-names = "stmmaceth", "allwinner_gmac_tx"; + resets = <&ahb1_resets 17>; + reset-names = "stmmaceth"; + snps,pbl = <2>; + snps,fixed-burst; + snps,force_sf_dma_mode; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + timer@06000c00 { compatible = "allwinner,sun4i-a10-timer"; reg = <0x06000c00 0xa0>; @@ -724,6 +776,20 @@ allwinner,drive = <SUN4I_PINCTRL_10_MA>; allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; }; + + gmac_pins_rgmii_a: gmac_rgmii@0 { + allwinner,pins = "PA0", "PA1", "PA2", "PA3", + "PA9", "PA10", + "PA12", "PA13", "PA19", + "PA20", "PA25", "PA26", "PA27"; + allwinner,function = "gmac"; + /* + * data lines in RGMII mode use DDR mode + * and need a higher signal drive strength + */ + allwinner,drive = <SUN4I_PINCTRL_40_MA>; + allwinner,pull = <SUN4I_PINCTRL_NO_PULL>; + }; }; uart0: serial@07000000 { diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun9i.h b/arch/arm/include/asm/arch-sunxi/clock_sun9i.h index 810313c5c3..1e73d7dd6a 100644 --- a/arch/arm/include/asm/arch-sunxi/clock_sun9i.h +++ b/arch/arm/include/asm/arch-sunxi/clock_sun9i.h @@ -96,6 +96,15 @@ struct sunxi_ccm_reg { u32 apb1_reset_cfg; /* 0x5b4 Bus Software Reset Register 4 */ }; +struct sunxi_sysctl_reg { + u8 reserved1[0x24]; /* 0x00 */ + u32 version; /* 0x24 system version (and boot select) */ + u8 reserved2[0x8]; /* 0x28 */ + u32 gmac_clk_cfg; /* 0x30 GMAC clock control */ + u8 reserved3[0x4]; /* 0x34 */ + u32 disp_mux_cfg; /* 0x38 display MUX control */ +}; + /* pll4_periph0_cfg */ #define PLL4_CFG_DEFAULT 0x90002800 /* 960 MHz */ @@ -116,6 +125,7 @@ struct sunxi_ccm_reg { #define CCM_MMC_CTRL_ENABLE (1 << 31) /* ahb_gate0 fields */ +#define AHB_GATE_OFFSET_GMAC 17 #define AHB_GATE_OFFSET_MCTL 14 /* On sun9i all sdc-s share their ahb gate, so ignore (x) */ @@ -132,6 +142,7 @@ struct sunxi_ccm_reg { #define APB1_GATE_TWI_MASK (0xf << APB1_GATE_TWI_SHIFT) /* ahb_reset0_cfg fields */ +#define AHB_RESET_OFFSET_GMAC 17 #define AHB_RESET_OFFSET_MCTL 14 /* On sun9i all sdc-s share their ahb reset, so ignore (x) */ @@ -143,6 +154,15 @@ struct sunxi_ccm_reg { #define APB1_RESET_TWI_SHIFT 0 #define APB1_RESET_TWI_MASK (0xf << APB1_RESET_TWI_SHIFT) +/* gmac_clk_cfg (in SYSCTL) fields ... these need to be misnamed as CCM_GMAC_CTRL + so we can reuse the same code as for sun6i in board/sunxi/gmac.c */ +#define CCM_GMAC_CTRL_TX_CLK_SRC_MII 0x0 +#define CCM_GMAC_CTRL_TX_CLK_SRC_EXT_RGMII 0x1 +#define CCM_GMAC_CTRL_TX_CLK_SRC_INT_RGMII 0x2 +#define CCM_GMAC_CTRL_GPIT_MII (0x0 << 2) +#define CCM_GMAC_CTRL_GPIT_RGMII (0x1 << 2) +#define CCM_GMAC_CTRL_RX_CLK_DELAY(x) ((x) << 5) +#define CCM_GMAC_CTRL_TX_CLK_DELAY(x) ((x) << 10) #ifndef __ASSEMBLY__ unsigned int clock_get_pll4_periph0(void); diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h index 8ace4e7cb0..ec37bb9afb 100644 --- a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h +++ b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h @@ -47,6 +47,7 @@ #define SUNXI_DRAM_PHY1_BASE (REGS_AHB0_BASE + 0x66000) /* AHB1 Module */ +#define SUNXI_SYSCTL_BASE (REGS_AHB1_BASE + 0x000000) #define SUNXI_DMA_BASE (REGS_AHB1_BASE + 0x002000) #define SUNXI_USBOTG_BASE (REGS_AHB1_BASE + 0x100000) #define SUNXI_USBEHCI0_BASE (REGS_AHB1_BASE + 0x200000) diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h index 98c00d84aa..46ca759255 100644 --- a/arch/arm/include/asm/arch-sunxi/gpio.h +++ b/arch/arm/include/asm/arch-sunxi/gpio.h @@ -145,6 +145,7 @@ enum sunxi_gpio_number { #define SUNXI_GPA_EMAC 2 #define SUN6I_GPA_GMAC 2 #define SUN7I_GPA_GMAC 5 +#define SUN9I_GPA_GMAC 2 #define SUN6I_GPA_SDC2 5 #define SUN6I_GPA_SDC3 4 #define SUN8I_H3_GPA_UART0 2 diff --git a/board/sunxi/gmac.c b/board/sunxi/gmac.c index 69eb8ff2d9..976eefd8d3 100644 --- a/board/sunxi/gmac.c +++ b/board/sunxi/gmac.c @@ -11,9 +11,19 @@ void eth_init_board(void) int pin; struct sunxi_ccm_reg *const ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; +#ifdef CONFIG_MACH_SUN9I + struct sunxi_sysctl_reg *const gethclk = + (struct sunxi_sysctl_reg *)SUNXI_SYSCTL_BASE; +#else + struct sunxi_ccm_reg *const gethclk = + (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; +#endif /* Set up clock gating */ -#ifdef CONFIG_SUNXI_GEN_SUN6I +#if defined(CONFIG_MACH_SUN9I) + setbits_le32(&ccm->ahb_reset1_cfg, 0x1 << AHB_RESET_OFFSET_GMAC); + setbits_le32(&ccm->ahb_gate1, 0x1 << AHB_GATE_OFFSET_GMAC); +#elif defined(CONFIG_SUNXI_GEN_SUN6I) setbits_le32(&ccm->ahb_reset0_cfg, 0x1 << AHB_RESET_OFFSET_GMAC); setbits_le32(&ccm->ahb_gate0, 0x1 << AHB_GATE_OFFSET_GMAC); #else @@ -22,16 +32,28 @@ void eth_init_board(void) /* Set MII clock */ #ifdef CONFIG_RGMII - setbits_le32(&ccm->gmac_clk_cfg, CCM_GMAC_CTRL_TX_CLK_SRC_INT_RGMII | + setbits_le32(&gethclk->gmac_clk_cfg, CCM_GMAC_CTRL_TX_CLK_SRC_INT_RGMII | CCM_GMAC_CTRL_GPIT_RGMII); - setbits_le32(&ccm->gmac_clk_cfg, + setbits_le32(&gethclk->gmac_clk_cfg, CCM_GMAC_CTRL_TX_CLK_DELAY(CONFIG_GMAC_TX_DELAY)); #else - setbits_le32(&ccm->gmac_clk_cfg, CCM_GMAC_CTRL_TX_CLK_SRC_MII | + setbits_le32(&gethclk->gmac_clk_cfg, CCM_GMAC_CTRL_TX_CLK_SRC_MII | CCM_GMAC_CTRL_GPIT_MII); #endif -#ifndef CONFIG_MACH_SUN6I +#if defined(CONFIG_MACH_SUN9I) + /* Configure pin mux settings for GMAC. This is a temporary kludge + until we support reading the configuration from the device tree. */ + for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(18); pin++) { +#ifdef CONFIG_RGMII + /* skip unused pins in RGMII mode */ + if (pin == SUNXI_GPA(6) || pin == SUNXI_GPA(11) || pin == SUNXI_GPA(14)) + continue; +#endif + sunxi_gpio_set_cfgpin(pin, SUN9I_GPA_GMAC); + sunxi_gpio_set_drv(pin, 3); + } +#elif !defined(CONFIG_MACH_SUN6I) /* Configure pin mux settings for GMAC */ for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(16); pin++) { #ifdef CONFIG_RGMII |