summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Tomsich <philipp.tomsich@theobroma-systems.com>2016-04-06 18:04:57 +0200
committerKlaus Goger <klaus.goger@theobroma-systems.com>2016-09-18 13:45:14 +0200
commit5da39118172811a2fe32a4eeaee7193f8cb413ed (patch)
tree5f942d4c7778b3de6f1e03da1338ac6811ff0010
parent6ed4d8a8686a0e8da9806a42dc90f1f0b7a0c160 (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.dtsi66
-rw-r--r--arch/arm/include/asm/arch-sunxi/clock_sun9i.h20
-rw-r--r--arch/arm/include/asm/arch-sunxi/cpu_sun9i.h1
-rw-r--r--arch/arm/include/asm/arch-sunxi/gpio.h1
-rw-r--r--board/sunxi/gmac.c32
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