From 525d187afb418a4deef8916844f5f7744da402a8 Mon Sep 17 00:00:00 2001 From: Michael Haas Date: Fri, 25 Mar 2016 18:22:50 +0100 Subject: net: phy: Optionally force master mode for RTL PHY This patch introduces CONFIG_RTL8211X_PHY_FORCE_MASTER. If this define is set, RTL8211x PHYs (except for the RTL8211F) will have their 1000BASE-T master/slave autonegotiation disabled and forced to master mode. This is helpful for PHYs like the RTL8211C which produce unstable links in slave mode. Such problems have been found on the A20-Olimex-SOM-EVB and A20-OLinuXino-Lime2. There is no proper way to identify affected PHYs in software as the RTL8211C shares its UID with the RTL8211B. Thus, this fix requires the introduction of an #ifdef. CC: fradav@gmail.com CC: merker@debian.org CC: hdegoede@redhat.com CC: ijc@hellion.org.uk CC: joe.hershberger@ni.com Signed-off-by: Michael Haas Tested-by: Karsten Merker Acked-by: Joe Hershberger Signed-off-by: Hans de Goede --- drivers/net/Kconfig | 21 +++++++++++++++++++++ drivers/net/phy/realtek.c | 13 ++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 2a229b89996..e0008fd1a46 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -13,6 +13,27 @@ config PHYLIB help Enable Ethernet PHY (physical media interface) support. +config RTL8211X_PHY_FORCE_MASTER + bool "Ethernet PHY RTL8211x: force 1000BASE-T master mode" + depends on PHYLIB + help + Force master mode for 1000BASE-T on RTl8211x PHYs (except for RTL8211F). + This can work around link stability and data corruption issues on gigabit + links which can occur in slave mode on certain PHYs, e.g. on the + RTL8211C(L). + + Please note that two directly connected devices (i.e. via crossover cable) + will not be able to establish a link between each other if they both force + master mode. Multiple devices forcing master mode when connected by a + network switch do not pose a problem as the switch configures its affected + ports into slave mode. + + This option only affects gigabit links. If you must establish a direct + connection between two devices which both force master mode, try forcing + the link speed to 100MBit/s. + + If unsure, say N. + menuconfig NETDEVICES bool "Network device support" depends on NET diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index 259a87fcc59..359ec5048e1 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -12,6 +12,10 @@ #define PHY_AUTONEGOTIATE_TIMEOUT 5000 +/* RTL8211x 1000BASE-T Control Register */ +#define MIIM_RTL8211x_CTRL1000T_MSCE (1 << 12); +#define MIIM_RTL8211X_CTRL1000T_MASTER (1 << 11); + /* RTL8211x PHY Status Register */ #define MIIM_RTL8211x_PHY_STATUS 0x11 #define MIIM_RTL8211x_PHYSTAT_SPEED 0xc000 @@ -53,7 +57,14 @@ static int rtl8211x_config(struct phy_device *phydev) */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_INER, MIIM_RTL8211x_PHY_INTR_DIS); - +#ifdef CONFIG_RTL8211X_PHY_FORCE_MASTER + unsigned int reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_CTRL1000); + /* force manual master/slave configuration */ + reg |= MIIM_RTL8211x_CTRL1000T_MSCE; + /* force master mode */ + reg |= MIIM_RTL8211X_CTRL1000T_MASTER; + phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, reg); +#endif /* read interrupt status just to clear it */ phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_INER); -- cgit v1.3.1 From 96fccb175fc3241768ce83fee47158ab506e9d8b Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 30 Mar 2016 00:26:55 +0800 Subject: musb: sunxi: Add support for A83T Like the Allwinner A33 SoC, the A83T is missing the config register from the musb USB DRD hardware block. Use a known working value for it. Signed-off-by: Chen-Yu Tsai Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/usb/musb-new/musb_regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/musb-new/musb_regs.h b/drivers/usb/musb-new/musb_regs.h index 4dc9abbe02c..0f18dd7f7ee 100644 --- a/drivers/usb/musb-new/musb_regs.h +++ b/drivers/usb/musb-new/musb_regs.h @@ -434,7 +434,7 @@ static inline u8 musb_read_ulpi_buscontrol(void __iomem *mbase) static inline u8 musb_read_configdata(void __iomem *mbase) { -#ifdef CONFIG_MACH_SUN8I_A33 +#if defined CONFIG_MACH_SUN8I_A33 || defined CONFIG_MACH_SUN8I_A83T /* allwinner saves a reg, and we need to hardcode this */ return 0xde; #else -- cgit v1.3.1 From 81a8aa3a3969b3ec50ee27addcc4eaa0cb37aa94 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 30 Mar 2016 00:26:56 +0800 Subject: sunxi: axp: Generalize register macros for VBUS drive GPIO VBUS drive is supported on AXP221 and later PMICs. Rework the macros so we can support this on later PMICs without too much work. Signed-off-by: Chen-Yu Tsai Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/gpio/axp_gpio.c | 25 ++++++++++++++----------- include/axp221.h | 8 ++++---- 2 files changed, 18 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/axp_gpio.c b/drivers/gpio/axp_gpio.c index bd2ac892d08..ec00827f8f8 100644 --- a/drivers/gpio/axp_gpio.c +++ b/drivers/gpio/axp_gpio.c @@ -59,10 +59,11 @@ static int axp_gpio_direction_output(struct udevice *dev, unsigned pin, u8 reg; switch (pin) { -#ifdef CONFIG_AXP221_POWER /* Only available on axp221/axp223 */ +#ifdef AXP_MISC_CTRL_N_VBUSEN_FUNC + /* Only available on later PMICs */ case SUNXI_GPIO_AXP0_VBUS_ENABLE: - ret = pmic_bus_clrbits(AXP221_MISC_CTRL, - AXP221_MISC_CTRL_N_VBUSEN_FUNC); + ret = pmic_bus_clrbits(AXP_MISC_CTRL, + AXP_MISC_CTRL_N_VBUSEN_FUNC); if (ret) return ret; @@ -90,10 +91,11 @@ static int axp_gpio_get_value(struct udevice *dev, unsigned pin) mask = AXP_POWER_STATUS_VBUS_PRESENT; break; #endif -#ifdef CONFIG_AXP221_POWER /* Only available on axp221/axp223 */ +#ifdef AXP_MISC_CTRL_N_VBUSEN_FUNC + /* Only available on later PMICs */ case SUNXI_GPIO_AXP0_VBUS_ENABLE: - ret = pmic_bus_read(AXP221_VBUS_IPSOUT, &val); - mask = AXP221_VBUS_IPSOUT_DRIVEBUS; + ret = pmic_bus_read(AXP_VBUS_IPSOUT, &val); + mask = AXP_VBUS_IPSOUT_DRIVEBUS; break; #endif default: @@ -115,14 +117,15 @@ static int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val) u8 reg; switch (pin) { -#ifdef CONFIG_AXP221_POWER /* Only available on axp221/axp223 */ +#ifdef AXP_MISC_CTRL_N_VBUSEN_FUNC + /* Only available on later PMICs */ case SUNXI_GPIO_AXP0_VBUS_ENABLE: if (val) - return pmic_bus_setbits(AXP221_VBUS_IPSOUT, - AXP221_VBUS_IPSOUT_DRIVEBUS); + return pmic_bus_setbits(AXP_VBUS_IPSOUT, + AXP_VBUS_IPSOUT_DRIVEBUS); else - return pmic_bus_clrbits(AXP221_VBUS_IPSOUT, - AXP221_VBUS_IPSOUT_DRIVEBUS); + return pmic_bus_clrbits(AXP_VBUS_IPSOUT, + AXP_VBUS_IPSOUT_DRIVEBUS); #endif default: reg = axp_get_gpio_ctrl_reg(pin); diff --git a/include/axp221.h b/include/axp221.h index 04cd8c2be48..b4b64b0e870 100644 --- a/include/axp221.h +++ b/include/axp221.h @@ -43,12 +43,8 @@ #define AXP221_ALDO1_CTRL 0x28 #define AXP221_ALDO2_CTRL 0x29 #define AXP221_ALDO3_CTRL 0x2a -#define AXP221_VBUS_IPSOUT 0x30 -#define AXP221_VBUS_IPSOUT_DRIVEBUS (1 << 2) #define AXP221_SHUTDOWN 0x32 #define AXP221_SHUTDOWN_POWEROFF (1 << 7) -#define AXP221_MISC_CTRL 0x8f -#define AXP221_MISC_CTRL_N_VBUSEN_FUNC (1 << 4) #define AXP221_PAGE 0xff /* Page 1 addresses */ @@ -57,6 +53,10 @@ /* For axp_gpio.c */ #define AXP_POWER_STATUS 0x00 #define AXP_POWER_STATUS_VBUS_PRESENT (1 << 5) +#define AXP_VBUS_IPSOUT 0x30 +#define AXP_VBUS_IPSOUT_DRIVEBUS (1 << 2) +#define AXP_MISC_CTRL 0x8f +#define AXP_MISC_CTRL_N_VBUSEN_FUNC (1 << 4) #define AXP_GPIO0_CTRL 0x90 #define AXP_GPIO1_CTRL 0x92 #define AXP_GPIO_CTRL_OUTPUT_LOW 0x00 /* Drive pin low */ -- cgit v1.3.1 From 4c6a9ca103f953b6e5e6dfcd56fb558e61ca3c05 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 30 Mar 2016 00:26:47 +0800 Subject: power: axp818: Fix DCDC5 default voltage DCDC5 is designed to supply VCC-DRAM, which is normally 1.5V for DDR3, 1.35V for DDR3L, and 1.2V for LPDDR3. Also remove CONFIG_AXP_DCDC5_VOLT from h8_homlet_v2_defconfig. Signed-off-by: Chen-Yu Tsai Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- configs/h8_homlet_v2_defconfig | 1 - drivers/power/Kconfig | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/configs/h8_homlet_v2_defconfig b/configs/h8_homlet_v2_defconfig index 4742aaf6935..1f492ab3521 100644 --- a/configs/h8_homlet_v2_defconfig +++ b/configs/h8_homlet_v2_defconfig @@ -12,4 +12,3 @@ CONFIG_SPL=y # CONFIG_CMD_FLASH is not set # CONFIG_CMD_FPGA is not set CONFIG_AXP_DCDC1_VOLT=3000 -CONFIG_AXP_DCDC5_VOLT=1500 diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index adc64552e74..548fe2617da 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -118,13 +118,12 @@ config AXP_DCDC4_VOLT config AXP_DCDC5_VOLT int "axp pmic dcdc5 voltage" depends on AXP221_POWER || AXP818_POWER - default 1800 if AXP818_POWER default 1500 if MACH_SUN6I || MACH_SUN8I ---help--- Set the voltage (mV) to program the axp pmic dcdc5 at, set to 0 to disable dcdc5. On A23 / A31 / A33 / A83T boards dcdc5 is VCC-DRAM and should be 1.5V, - 1.8V for A83T. + 1.35V if DDR3L is used. config AXP_ALDO1_VOLT int "axp pmic (a)ldo1 voltage" -- cgit v1.3.1 From 38491d9c6515eafd97d881cab0420652f07d92a5 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 30 Mar 2016 00:26:48 +0800 Subject: power: axp818: Add support for FLDOs The FLDOs on AXP818 PMIC normally provide power to CPUS and USB HSIC PHY on the A83T/H8. Signed-off-by: Chen-Yu Tsai Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- board/sunxi/board.c | 6 ++++++ drivers/power/Kconfig | 27 +++++++++++++++++++++++++++ drivers/power/axp818.c | 34 ++++++++++++++++++++++++++++++++++ include/axp818.h | 1 + include/axp_pmic.h | 1 + 5 files changed, 69 insertions(+) (limited to 'drivers') diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 2d5335f9531..2271c895c20 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -486,6 +486,12 @@ void sunxi_board_init(void) power_failed |= axp_set_eldo(2, CONFIG_AXP_ELDO2_VOLT); power_failed |= axp_set_eldo(3, CONFIG_AXP_ELDO3_VOLT); #endif + +#ifdef CONFIG_AXP818_POWER + power_failed |= axp_set_fldo(1, CONFIG_AXP_FLDO1_VOLT); + power_failed |= axp_set_fldo(2, CONFIG_AXP_FLDO2_VOLT); + power_failed |= axp_set_fldo(3, CONFIG_AXP_FLDO3_VOLT); +#endif #endif printf("DRAM:"); ramsize = sunxi_dram_init(); diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 548fe2617da..937b9aa246b 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -238,6 +238,33 @@ config AXP_ELDO3_VOLT 1.2V for the SSD2828 chip (converter of parallel LCD interface into MIPI DSI). +config AXP_FLDO1_VOLT + int "axp pmic fldo1 voltage" + depends on AXP818_POWER + default 0 if MACH_SUN8I_A83T + ---help--- + Set the voltage (mV) to program the axp pmic fldo1 at, set to 0 to + disable fldo1. + On A83T / H8 boards fldo1 is VCC-HSIC and should be 1.2V if HSIC is + used. + +config AXP_FLDO2_VOLT + int "axp pmic eldo2 voltage" + depends on AXP818_POWER + default 900 if MACH_SUN8I_A83T + ---help--- + Set the voltage (mV) to program the axp pmic fldo2 at, set to 0 to + disable fldo2. + On A83T / H8 boards fldo2 is VCC-CPUS and should be 0.9V. + +config AXP_FLDO3_VOLT + int "axp pmic fldo3 voltage" + depends on AXP818_POWER + default 0 + ---help--- + Set the voltage (mV) to program the axp pmic fldo3 at, set to 0 to + disable fldo3. + config SY8106A_VOUT1_VOLT int "SY8106A pmic VOUT1 voltage" depends on SY8106A_POWER diff --git a/drivers/power/axp818.c b/drivers/power/axp818.c index e885d029840..3ac05ffefe0 100644 --- a/drivers/power/axp818.c +++ b/drivers/power/axp818.c @@ -191,6 +191,40 @@ int axp_set_eldo(int eldo_num, unsigned int mvolt) AXP818_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1)); } +int axp_set_fldo(int fldo_num, unsigned int mvolt) +{ + int ret; + u8 cfg; + + if (fldo_num < 1 || fldo_num > 3) + return -EINVAL; + + if (mvolt == 0) + return pmic_bus_clrbits(AXP818_OUTPUT_CTRL3, + AXP818_OUTPUT_CTRL3_FLDO1_EN << (fldo_num - 1)); + + if (fldo_num < 3) { + cfg = axp818_mvolt_to_cfg(mvolt, 700, 1450, 50); + ret = pmic_bus_write(AXP818_FLDO1_CTRL + (fldo_num - 1), cfg); + } else { + /* + * Special case for FLDO3, which is DCDC5 / 2 or FLDOIN / 2 + * Since FLDOIN is unknown, test against DCDC5. + */ + if (mvolt * 2 == CONFIG_AXP_DCDC5_VOLT) + ret = pmic_bus_clrbits(AXP818_FLDO2_3_CTRL, + AXP818_FLDO2_3_CTRL_FLDO3_VOL); + else + ret = pmic_bus_setbits(AXP818_FLDO2_3_CTRL, + AXP818_FLDO2_3_CTRL_FLDO3_VOL); + } + if (ret) + return ret; + + return pmic_bus_setbits(AXP818_OUTPUT_CTRL3, + AXP818_OUTPUT_CTRL3_FLDO1_EN << (fldo_num - 1)); +} + int axp_init(void) { u8 axp_chip_id; diff --git a/include/axp818.h b/include/axp818.h index b24c790383c..5630eed04d8 100644 --- a/include/axp818.h +++ b/include/axp818.h @@ -41,6 +41,7 @@ #define AXP818_ELDO3_CTRL 0x1b #define AXP818_FLDO1_CTRL 0x1c #define AXP818_FLDO2_3_CTRL 0x1d +#define AXP818_FLDO2_3_CTRL_FLDO3_VOL (1 << 4) #define AXP818_DCDC1_CTRL 0x20 #define AXP818_DCDC2_CTRL 0x21 #define AXP818_DCDC3_CTRL 0x22 diff --git a/include/axp_pmic.h b/include/axp_pmic.h index 0f146835091..b203cc88ddb 100644 --- a/include/axp_pmic.h +++ b/include/axp_pmic.h @@ -31,6 +31,7 @@ int axp_set_aldo3(unsigned int mvolt); int axp_set_aldo4(unsigned int mvolt); int axp_set_dldo(int dldo_num, unsigned int mvolt); int axp_set_eldo(int eldo_num, unsigned int mvolt); +int axp_set_fldo(int fldo_num, unsigned int mvolt); int axp_init(void); int axp_get_sid(unsigned int *sid); -- cgit v1.3.1 From 3655f287b6eb9f9dfd35d9229bd0d53fa400877d Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 30 Mar 2016 00:26:53 +0800 Subject: sunxi: ehci: Add A83T compatible We have a separate compatible for almost each SoC. Add one for the A83T. Signed-off-by: Chen-Yu Tsai Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/usb/host/ehci-sunxi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c index 677a5d3b07f..d5eb4921696 100644 --- a/drivers/usb/host/ehci-sunxi.c +++ b/drivers/usb/host/ehci-sunxi.c @@ -91,6 +91,7 @@ static const struct udevice_id ehci_usb_ids[] = { { .compatible = "allwinner,sun6i-a31-ehci", }, { .compatible = "allwinner,sun7i-a20-ehci", }, { .compatible = "allwinner,sun8i-a23-ehci", }, + { .compatible = "allwinner,sun8i-a83t-ehci", }, { .compatible = "allwinner,sun8i-h3-ehci", }, { .compatible = "allwinner,sun9i-a80-ehci", }, { } -- cgit v1.3.1 From 045ae7e3393fc940b183b3f2ea9c9edd62d9e810 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 30 Mar 2016 00:26:54 +0800 Subject: sunxi: ohci: Add A83T compatible We have a separate compatible for almost each SoC. Add one for the A83T. Signed-off-by: Chen-Yu Tsai Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/usb/host/ohci-sunxi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-sunxi.c b/drivers/usb/host/ohci-sunxi.c index d4fb95abe1e..6f3f4cec16a 100644 --- a/drivers/usb/host/ohci-sunxi.c +++ b/drivers/usb/host/ohci-sunxi.c @@ -94,6 +94,7 @@ static const struct udevice_id ohci_usb_ids[] = { { .compatible = "allwinner,sun6i-a31-ohci", }, { .compatible = "allwinner,sun7i-a20-ohci", }, { .compatible = "allwinner,sun8i-a23-ohci", }, + { .compatible = "allwinner,sun8i-a83t-ohci", }, { .compatible = "allwinner,sun8i-h3-ohci", }, { .compatible = "allwinner,sun9i-a80-ohci", }, { } -- cgit v1.3.1 From 0ea5a04fbcd72ebb37eb4b3f744374fdf551d3b7 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 29 Mar 2016 17:29:09 +0200 Subject: sunxi: Explicitly cast u32 pointer conversions Some parts of the sunxi code cast explicitly between u32 values and pointers. This is not a problem in practice, because all 64bit SoCs today only use the lower 32 bits for their phyical address space. But we need to make sure that the compiler is sure this is not an accident as well. Signed-off-by: Alexander Graf Acked-by: Hans de Goede Signed-off-by: Hans de Goede --- arch/arm/mach-sunxi/cpu_info.c | 2 +- arch/arm/mach-sunxi/dram_helpers.c | 4 ++-- arch/arm/mach-sunxi/usb_phy.c | 2 +- drivers/mmc/sunxi_mmc.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-sunxi/cpu_info.c b/arch/arm/mach-sunxi/cpu_info.c index c0eabdf91d3..b885ea1f0a0 100644 --- a/arch/arm/mach-sunxi/cpu_info.c +++ b/arch/arm/mach-sunxi/cpu_info.c @@ -105,7 +105,7 @@ int sunxi_get_sid(unsigned int *sid) int i; for (i = 0; i< 4; i++) - sid[i] = readl(SUNXI_SID_BASE + 4 * i); + sid[i] = readl((ulong)SUNXI_SID_BASE + 4 * i); return 0; #else diff --git a/arch/arm/mach-sunxi/dram_helpers.c b/arch/arm/mach-sunxi/dram_helpers.c index 9a94e1b6795..50318d2eb6b 100644 --- a/arch/arm/mach-sunxi/dram_helpers.c +++ b/arch/arm/mach-sunxi/dram_helpers.c @@ -30,8 +30,8 @@ bool mctl_mem_matches(u32 offset) { /* Try to write different values to RAM at two addresses */ writel(0, CONFIG_SYS_SDRAM_BASE); - writel(0xaa55aa55, CONFIG_SYS_SDRAM_BASE + offset); + writel(0xaa55aa55, (ulong)CONFIG_SYS_SDRAM_BASE + offset); /* Check if the same value is actually observed when reading back */ return readl(CONFIG_SYS_SDRAM_BASE) == - readl(CONFIG_SYS_SDRAM_BASE + offset); + readl((ulong)CONFIG_SYS_SDRAM_BASE + offset); } diff --git a/arch/arm/mach-sunxi/usb_phy.c b/arch/arm/mach-sunxi/usb_phy.c index fa375f1d16d..b258ce4443c 100644 --- a/arch/arm/mach-sunxi/usb_phy.c +++ b/arch/arm/mach-sunxi/usb_phy.c @@ -52,7 +52,7 @@ static struct sunxi_usb_phy { int id; int init_count; int power_on_count; - int base; + ulong base; } sunxi_usb_phy[] = { { .usb_rst_mask = CCM_USB_CTRL_PHY0_RST | CCM_USB_CTRL_PHY0_CLK, diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index 7b33094d848..44d1a768c18 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -339,7 +339,7 @@ static int sunxi_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, cmdval |= SUNXI_MMC_CMD_CHK_RESPONSE_CRC; if (data) { - if ((u32) data->dest & 0x3) { + if ((u32)(long)data->dest & 0x3) { error = -1; goto out; } -- cgit v1.3.1 From d96ebc468d0dff6eb6f069bba03b3f0e33aa22de Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Tue, 29 Mar 2016 17:29:10 +0200 Subject: sunxi: Add support for Allwinner A64 SoCs The Allwinner A64 SoC is used in the Pine64. This patch adds all bits necessary to compile U-Boot for it running in AArch64 mode. Unfortunately SPL is not ready yet due to legal problems, so we need to boot using the binary boot0 for now. Signed-off-by: Siarhei Siamashka [agraf: remove SPL code, move to AArch64] Signed-off-by: Alexander Graf Acked-by: Hans de Goede Signed-off-by: Hans de Goede --- arch/arm/dts/a64.dtsi | 564 ++++++++++++++++++++++++++ arch/arm/include/asm/arch-sunxi/clock.h | 3 +- arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 8 +- arch/arm/include/asm/arch-sunxi/gpio.h | 1 + arch/arm/include/asm/arch-sunxi/spl.h | 5 +- arch/arm/mach-sunxi/Makefile | 1 + arch/arm/mach-sunxi/board.c | 30 +- arch/arm/mach-sunxi/cpu_info.c | 2 + board/sunxi/Kconfig | 9 +- board/sunxi/board.c | 35 +- drivers/mmc/sunxi_mmc.c | 4 + drivers/power/Kconfig | 2 +- include/configs/sun50i.h | 25 ++ include/configs/sun6i.h | 1 - include/configs/sun7i.h | 1 - include/configs/sun8i.h | 2 - include/configs/sunxi-common.h | 21 +- 17 files changed, 694 insertions(+), 20 deletions(-) create mode 100644 arch/arm/dts/a64.dtsi create mode 100644 include/configs/sun50i.h (limited to 'drivers') diff --git a/arch/arm/dts/a64.dtsi b/arch/arm/dts/a64.dtsi new file mode 100644 index 00000000000..f3ad00024a7 --- /dev/null +++ b/arch/arm/dts/a64.dtsi @@ -0,0 +1,564 @@ +/* + * Copyright (C) 2016 ARM Ltd. + * based on the Allwinner H3 dtsi: + * Copyright (C) 2015 Jens Kuske + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +/ { + compatible = "allwinner,a64"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + aliases { + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + serial3 = &uart3; + serial4 = &uart4; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <0>; + enable-method = "psci"; + }; + + cpu@1 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <1>; + enable-method = "psci"; + }; + + cpu@2 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <2>; + enable-method = "psci"; + }; + + cpu@3 { + compatible = "arm,cortex-a53", "arm,armv8"; + device_type = "cpu"; + reg = <3>; + enable-method = "psci"; + }; + }; + + psci { + compatible = "arm,psci-0.2", "arm,psci"; + method = "smc"; + cpu_suspend = <0xc4000001>; + cpu_off = <0x84000002>; + cpu_on = <0xc4000003>; + }; + + memory { + device_type = "memory"; + reg = <0x40000000 0>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + clocks { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + osc24M: osc24M_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "osc24M"; + }; + + osc32k: osc32k_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + clock-output-names = "osc32k"; + }; + + pll1: clk@01c20000 { + #clock-cells = <0>; + compatible = "allwinner,sun8i-a23-pll1-clk"; + reg = <0x01c20000 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll1"; + }; + + pll6: clk@01c20028 { + #clock-cells = <1>; + compatible = "allwinner,sun6i-a31-pll6-clk"; + reg = <0x01c20028 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll6", "pll6x2"; + }; + + pll6d2: pll6d2_clk { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <2>; + clock-mult = <1>; + clocks = <&pll6 0>; + clock-output-names = "pll6d2"; + }; + + /* dummy clock until pll6 can be reused */ + pll8: pll8_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <1>; + clock-output-names = "pll8"; + }; + + cpu: cpu_clk@01c20050 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-cpu-clk"; + reg = <0x01c20050 0x4>; + clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll1>; + clock-output-names = "cpu"; + }; + + axi: axi_clk@01c20050 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-axi-clk"; + reg = <0x01c20050 0x4>; + clocks = <&cpu>; + clock-output-names = "axi"; + }; + + ahb1: ahb1_clk@01c20054 { + #clock-cells = <0>; + compatible = "allwinner,sun6i-a31-ahb1-clk"; + reg = <0x01c20054 0x4>; + clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>; + clock-output-names = "ahb1"; + }; + + ahb2: ahb2_clk@01c2005c { + #clock-cells = <0>; + compatible = "allwinner,sun8i-h3-ahb2-clk"; + reg = <0x01c2005c 0x4>; + clocks = <&ahb1>, <&pll6d2>; + clock-output-names = "ahb2"; + }; + + apb1: apb1_clk@01c20054 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-apb0-clk"; + reg = <0x01c20054 0x4>; + clocks = <&ahb1>; + clock-output-names = "apb1"; + }; + + apb2: apb2_clk@01c20058 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-apb1-clk"; + reg = <0x01c20058 0x4>; + clocks = <&osc32k>, <&osc24M>, <&pll6 1>, <&pll6 1>; + clock-output-names = "apb2"; + }; + + bus_gates: clk@01c20060 { + #clock-cells = <1>; + compatible = "allwinner,a64-bus-gates-clk", + "allwinner,sun8i-h3-bus-gates-clk"; + reg = <0x01c20060 0x14>; + clocks = <&ahb1>, <&ahb2>, <&apb1>, <&apb2>; + clock-names = "ahb1", "ahb2", "apb1", "apb2"; + clock-indices = <1>, + <5>, <6>, <8>, + <9>, <10>, <13>, + <14>, <17>, <18>, + <19>, <20>, + <21>, <23>, + <24>, <25>, + <28>, <29>, + <32>, <35>, + <36>, <37>, + <40>, <43>, + <44>, <52>, <53>, + <54>, <64>, + <65>, <69>, <72>, + <76>, <77>, <78>, + <96>, <97>, <98>, + <101>, + <112>, <113>, + <114>, <115>, + <116>, <135>; + clock-output-names = "bus_mipidsi", + "bus_ce", "bus_dma", "bus_mmc0", + "bus_mmc1", "bus_mmc2", "bus_nand", + "bus_sdram", "bus_gmac", "bus_ts", + "bus_hstimer", "bus_spi0", + "bus_spi1", "bus_otg", + "bus_otg_ehci0", "bus_ehci0", + "bus_otg_ohci0", "bus_ohci0", + "bus_ve", "bus_lcd0", + "bus_lcd1", "bus_deint", + "bus_csi", "bus_hdmi", + "bus_de", "bus_gpu", "bus_msgbox", + "bus_spinlock", "bus_codec", + "bus_spdif", "bus_pio", "bus_ths", + "bus_i2s0", "bus_i2s1", "bus_i2s2", + "bus_i2c0", "bus_i2c1", "bus_i2c2", + "bus_scr", + "bus_uart0", "bus_uart1", + "bus_uart2", "bus_uart3", + "bus_uart4", "bus_dbg"; + }; + + mmc0_clk: clk@01c20088 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-a10-mmc-clk"; + reg = <0x01c20088 0x4>; + clocks = <&osc24M>, <&pll6 0>, <&pll8>; + clock-output-names = "mmc0", + "mmc0_output", + "mmc0_sample"; + }; + + mmc1_clk: clk@01c2008c { + #clock-cells = <1>; + compatible = "allwinner,sun4i-a10-mmc-clk"; + reg = <0x01c2008c 0x4>; + clocks = <&osc24M>, <&pll6 0>, <&pll8>; + clock-output-names = "mmc1", + "mmc1_output", + "mmc1_sample"; + }; + + mmc2_clk: clk@01c20090 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-a10-mmc-clk"; + reg = <0x01c20090 0x4>; + clocks = <&osc24M>, <&pll6 0>, <&pll8>; + clock-output-names = "mmc2", + "mmc2_output", + "mmc2_sample"; + }; + }; + + regulators { + reg_vcc3v3: vcc3v3 { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + mmc0: mmc@01c0f000 { + compatible = "allwinner,sun5i-a13-mmc"; + reg = <0x01c0f000 0x1000>; + clocks = <&bus_gates 8>, + <&mmc0_clk 0>, + <&mmc0_clk 1>, + <&mmc0_clk 2>; + clock-names = "ahb", + "mmc", + "output", + "sample"; + resets = <&ahb_rst 8>; + reset-names = "ahb"; + interrupts = ; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + mmc1: mmc@01c10000 { + compatible = "allwinner,sun5i-a13-mmc"; + reg = <0x01c10000 0x1000>; + clocks = <&bus_gates 9>, + <&mmc1_clk 0>, + <&mmc1_clk 1>, + <&mmc1_clk 2>; + clock-names = "ahb", + "mmc", + "output", + "sample"; + resets = <&ahb_rst 9>; + reset-names = "ahb"; + interrupts = ; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + mmc2: mmc@01c11000 { + compatible = "allwinner,sun5i-a13-mmc"; + reg = <0x01c11000 0x1000>; + clocks = <&bus_gates 10>, + <&mmc2_clk 0>, + <&mmc2_clk 1>, + <&mmc2_clk 2>; + clock-names = "ahb", + "mmc", + "output", + "sample"; + resets = <&ahb_rst 10>; + reset-names = "ahb"; + interrupts = ; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + pio: pinctrl@01c20800 { + compatible = "allwinner,a64-pinctrl"; + reg = <0x01c20800 0x400>; + interrupts = , + , + ; + clocks = <&bus_gates 69>; + gpio-controller; + #gpio-cells = <3>; + interrupt-controller; + #interrupt-cells = <2>; + + uart0_pins_a: uart0@0 { + allwinner,pins = "PB8", "PB9"; + allwinner,function = "uart0"; + allwinner,drive = ; + allwinner,pull = ; + }; + + uart0_pins_b: uart0@1 { + allwinner,pins = "PF2", "PF3"; + allwinner,function = "uart0"; + allwinner,drive = ; + allwinner,pull = ; + }; + + uart1_pins: uart1@0 { + allwinner,pins = "PG6", "PG7", "PG8", "PG9"; + allwinner,function = "uart1"; + allwinner,drive = ; + allwinner,pull = ; + }; + + uart2_pins: uart2@0 { + allwinner,pins = "PB0", "PB1", "PB2", "PB3"; + allwinner,function = "uart2"; + allwinner,drive = ; + allwinner,pull = ; + }; + + uart3_pins_a: uart3@0 { + allwinner,pins = "PD0", "PD1"; + allwinner,function = "uart3"; + allwinner,drive = ; + allwinner,pull = ; + }; + + uart3_pins_b: uart3@1 { + allwinner,pins = "PH4", "PH5", "PH6", "PH7"; + allwinner,function = "uart3"; + allwinner,drive = ; + allwinner,pull = ; + }; + + uart4_pins: uart4@0 { + allwinner,pins = "PD2", "PD3", "PD4", "PD5"; + allwinner,function = "uart4"; + allwinner,drive = ; + allwinner,pull = ; + }; + + mmc0_pins: mmc0@0 { + allwinner,pins = "PF0", "PF1", "PF2", "PF3", + "PF4", "PF5"; + allwinner,function = "mmc0"; + allwinner,drive = ; + allwinner,pull = ; + }; + + mmc0_default_cd_pin: mmc0_cd_pin@0 { + allwinner,pins = "PF6"; + allwinner,function = "gpio_in"; + allwinner,drive = ; + allwinner,pull = ; + }; + + mmc1_pins: mmc1@0 { + allwinner,pins = "PG0", "PG1", "PG2", "PG3", + "PG4", "PG5"; + allwinner,function = "mmc1"; + allwinner,drive = ; + allwinner,pull = ; + }; + + mmc2_pins: mmc2@0 { + allwinner,pins = "PC1", "PC5", "PC6", "PC8", + "PC9", "PC10"; + allwinner,function = "mmc2"; + allwinner,drive = ; + allwinner,pull = ; + }; + }; + + ahb_rst: reset@01c202c0 { + #reset-cells = <1>; + compatible = "allwinner,sun6i-a31-ahb1-reset"; + reg = <0x01c202c0 0xc>; + }; + + apb1_rst: reset@01c202d0 { + #reset-cells = <1>; + compatible = "allwinner,sun6i-a31-clock-reset"; + reg = <0x01c202d0 0x4>; + }; + + apb2_rst: reset@01c202d8 { + #reset-cells = <1>; + compatible = "allwinner,sun6i-a31-clock-reset"; + reg = <0x01c202d8 0x4>; + }; + + uart0: serial@01c28000 { + compatible = "snps,dw-apb-uart"; + reg = <0x01c28000 0x400>; + interrupts = ; + reg-shift = <2>; + reg-io-width = <4>; + clocks = <&bus_gates 112>; + resets = <&apb2_rst 16>; + reset-names = "apb2"; + status = "disabled"; + }; + + uart1: serial@01c28400 { + compatible = "snps,dw-apb-uart"; + reg = <0x01c28400 0x400>; + interrupts = ; + reg-shift = <2>; + reg-io-width = <4>; + clocks = <&bus_gates 113>; + resets = <&apb2_rst 17>; + reset-names = "apb2"; + status = "disabled"; + }; + + uart2: serial@01c28800 { + compatible = "snps,dw-apb-uart"; + reg = <0x01c28800 0x400>; + interrupts = ; + reg-shift = <2>; + reg-io-width = <4>; + clocks = <&bus_gates 114>; + resets = <&apb2_rst 18>; + reset-names = "apb2"; + status = "disabled"; + }; + + uart3: serial@01c28c00 { + compatible = "snps,dw-apb-uart"; + reg = <0x01c28c00 0x400>; + interrupts = ; + reg-shift = <2>; + reg-io-width = <4>; + clocks = <&bus_gates 115>; + resets = <&apb2_rst 19>; + reset-names = "apb2"; + status = "disabled"; + }; + + uart4: serial@01c29000 { + compatible = "snps,dw-apb-uart"; + reg = <0x01c29000 0x400>; + interrupts = ; + reg-shift = <2>; + reg-io-width = <4>; + clocks = <&bus_gates 116>; + resets = <&apb2_rst 20>; + reset-names = "apb2"; + status = "disabled"; + }; + + rtc: rtc@01f00000 { + compatible = "allwinner,sun6i-a31-rtc"; + reg = <0x01f00000 0x54>; + interrupts = , + ; + }; + }; + + gic: interrupt-controller@{ + compatible = "arm,gic-400"; + interrupt-controller; + #interrupt-cells = <3>; + #address-cells = <0>; + + reg = <0x01C81000 0x1000>, + <0x01C82000 0x2000>, + <0x01C84000 0x2000>, + <0x01C86000 0x2000>; + interrupts = ; + }; +}; diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h index 6c0573fe587..3747f74d360 100644 --- a/arch/arm/include/asm/arch-sunxi/clock.h +++ b/arch/arm/include/asm/arch-sunxi/clock.h @@ -17,7 +17,8 @@ /* clock control module regs definition */ #if defined(CONFIG_MACH_SUN8I_A83T) #include -#elif defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) +#elif defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) || \ + defined(CONFIG_MACH_SUN50I) #include #elif defined(CONFIG_MACH_SUN9I) #include diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h index 9de7754bb03..f2990db9289 100644 --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h @@ -350,10 +350,12 @@ struct sunxi_ccm_reg { #define CCM_HDMI_CTRL_DDC_GATE (0x1 << 30) #define CCM_HDMI_CTRL_GATE (0x1 << 31) -#ifndef CONFIG_MACH_SUN8I -#define MBUS_CLK_DEFAULT 0x81000001 /* PLL6 / 2 */ -#else +#if defined(CONFIG_MACH_SUN50I) +#define MBUS_CLK_DEFAULT 0x81000002 /* PLL6x2 / 3 */ +#elif defined(CONFIG_MACH_SUN8I) #define MBUS_CLK_DEFAULT 0x81000003 /* PLL6 / 4 */ +#else +#define MBUS_CLK_DEFAULT 0x81000001 /* PLL6 / 2 */ #endif #define MBUS_CLK_GATE (0x1 << 31) diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h index 649f6cd840f..1ace5480227 100644 --- a/arch/arm/include/asm/arch-sunxi/gpio.h +++ b/arch/arm/include/asm/arch-sunxi/gpio.h @@ -159,6 +159,7 @@ enum sunxi_gpio_number { #define SUN8I_GPB_UART2 2 #define SUN8I_A33_GPB_UART0 3 #define SUN8I_A83T_GPB_UART0 2 +#define SUN50I_GPB_UART0 4 #define SUNXI_GPC_NAND 2 #define SUNXI_GPC_SDC2 3 diff --git a/arch/arm/include/asm/arch-sunxi/spl.h b/arch/arm/include/asm/arch-sunxi/spl.h index a129dd4ee0a..ca9a4f99ad2 100644 --- a/arch/arm/include/asm/arch-sunxi/spl.h +++ b/arch/arm/include/asm/arch-sunxi/spl.h @@ -12,8 +12,11 @@ #define SPL_SIGNATURE "SPL" /* marks "sunxi" SPL header */ #define SPL_HEADER_VERSION 1 -/* Note: A80 will require special handling here: SPL_ADDR 0x10000 */ +#if defined(CONFIG_MACH_SUN9I) || defined(CONFIG_MACH_SUN50I) +#define SPL_ADDR 0x10000 +#else #define SPL_ADDR 0x0 +#endif /* boot head definition from sun4i boot code */ struct boot_file_head { diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile index 114cc0320f3..ad3d6c49185 100644 --- a/arch/arm/mach-sunxi/Makefile +++ b/arch/arm/mach-sunxi/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_MACH_SUN4I) += clock_sun4i.o obj-$(CONFIG_MACH_SUN5I) += clock_sun4i.o obj-$(CONFIG_MACH_SUN6I) += clock_sun6i.o obj-$(CONFIG_MACH_SUN7I) += clock_sun4i.o +obj-$(CONFIG_MACH_SUN50I) += clock_sun6i.o ifdef CONFIG_MACH_SUN8I_A83T obj-y += clock_sun8i_a83t.o else diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c index bf58fa90ec3..20149dabc8e 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -40,6 +40,30 @@ struct fel_stash { struct fel_stash fel_stash __attribute__((section(".data"))); +#ifdef CONFIG_MACH_SUN50I +#include + +static struct mm_region sunxi_mem_map[] = { + { + /* SRAM, MMIO regions */ + .base = 0x0UL, + .size = 0x40000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE + }, { + /* RAM */ + .base = 0x40000000UL, + .size = 0x80000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, { + /* List terminator */ + 0, + } +}; +struct mm_region *mem_map = sunxi_mem_map; +#endif + static int gpio_init(void) { #if CONFIG_CONS_INDEX == 1 && defined(CONFIG_UART0_PORT_F) @@ -76,6 +100,10 @@ static int gpio_init(void) sunxi_gpio_set_cfgpin(SUNXI_GPA(4), SUN8I_H3_GPA_UART0); sunxi_gpio_set_cfgpin(SUNXI_GPA(5), SUN8I_H3_GPA_UART0); sunxi_gpio_set_pull(SUNXI_GPA(5), SUNXI_GPIO_PULL_UP); +#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUN50I) + sunxi_gpio_set_cfgpin(SUNXI_GPB(8), SUN50I_GPB_UART0); + sunxi_gpio_set_cfgpin(SUNXI_GPB(9), SUN50I_GPB_UART0); + sunxi_gpio_set_pull(SUNXI_GPB(9), SUNXI_GPIO_PULL_UP); #elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUN8I_A83T) sunxi_gpio_set_cfgpin(SUNXI_GPB(9), SUN8I_A83T_GPB_UART0); sunxi_gpio_set_cfgpin(SUNXI_GPB(10), SUN8I_A83T_GPB_UART0); @@ -265,7 +293,7 @@ void reset_cpu(ulong addr) #endif } -#ifndef CONFIG_SYS_DCACHE_OFF +#if !defined(CONFIG_SYS_DCACHE_OFF) && !defined(CONFIG_ARM64) void enable_caches(void) { /* Enable D-cache. I-cache is already enabled in start.S */ diff --git a/arch/arm/mach-sunxi/cpu_info.c b/arch/arm/mach-sunxi/cpu_info.c index b885ea1f0a0..76b6719d99e 100644 --- a/arch/arm/mach-sunxi/cpu_info.c +++ b/arch/arm/mach-sunxi/cpu_info.c @@ -89,6 +89,8 @@ int print_cpuinfo(void) printf("CPU: Allwinner H3 (SUN8I %04x)\n", sunxi_get_sram_id()); #elif defined CONFIG_MACH_SUN9I puts("CPU: Allwinner A80 (SUN9I)\n"); +#elif defined CONFIG_MACH_SUN50I + puts("CPU: Allwinner A64 (SUN50I)\n"); #else #warning Please update cpu_info.c with correct CPU information puts("CPU: SUNXI Family\n"); diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig index 5e72fac7f97..464fa0fa583 100644 --- a/board/sunxi/Kconfig +++ b/board/sunxi/Kconfig @@ -77,6 +77,11 @@ config MACH_SUN8I_H3 select SUPPORT_SPL select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT +config MACH_SUN50I + bool "sun50i (Allwinner A64)" + select ARM64 + select SUNXI_GEN_SUN6I + config MACH_SUN8I_A83T bool "sun8i (Allwinner A83T)" select CPU_V7 @@ -213,6 +218,7 @@ config DRAM_ODT_CORRECTION endif config SYS_CLK_FREQ + default 816000000 if MACH_SUN50I default 912000000 if MACH_SUN7I default 1008000000 if MACH_SUN4I || MACH_SUN5I || MACH_SUN6I || MACH_SUN8I @@ -223,6 +229,7 @@ config SYS_CONFIG_NAME default "sun7i" if MACH_SUN7I default "sun8i" if MACH_SUN8I default "sun9i" if MACH_SUN9I + default "sun50i" if MACH_SUN50I config SYS_BOARD default "sunxi" @@ -604,7 +611,7 @@ config GMAC_TX_DELAY Set the GMAC Transmit Clock Delay Chain value. config SPL_STACK_R_ADDR - default 0x4fe00000 if MACH_SUN4I || MACH_SUN5I || MACH_SUN6I || MACH_SUN7I || MACH_SUN8I + default 0x4fe00000 if MACH_SUN4I || MACH_SUN5I || MACH_SUN6I || MACH_SUN7I || MACH_SUN8I || MACH_SUN50I default 0x2fe00000 if MACH_SUN9I endif diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 2271c895c20..ccf4129b153 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -21,6 +21,9 @@ #include #include #include +#ifndef CONFIG_ARM64 +#include +#endif #include #include #include @@ -73,18 +76,38 @@ DECLARE_GLOBAL_DATA_PTR; /* add board specific code here */ int board_init(void) { - int id_pfr1, ret; + __maybe_unused int id_pfr1, ret; gd->bd->bi_boot_params = (PHYS_SDRAM_0 + 0x100); +#ifndef CONFIG_ARM64 asm volatile("mrc p15, 0, %0, c0, c1, 1" : "=r"(id_pfr1)); debug("id_pfr1: 0x%08x\n", id_pfr1); /* Generic Timer Extension available? */ - if ((id_pfr1 >> 16) & 0xf) { + if ((id_pfr1 >> CPUID_ARM_GENTIMER_SHIFT) & 0xf) { + uint32_t freq; + debug("Setting CNTFRQ\n"); - /* CNTFRQ == 24 MHz */ - asm volatile("mcr p15, 0, %0, c14, c0, 0" : : "r"(24000000)); + + /* + * CNTFRQ is a secure register, so we will crash if we try to + * write this from the non-secure world (read is OK, though). + * In case some bootcode has already set the correct value, + * we avoid the risk of writing to it. + */ + asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r"(freq)); + if (freq != CONFIG_TIMER_CLK_FREQ) { + debug("arch timer frequency is %d Hz, should be %d, fixing ...\n", + freq, CONFIG_TIMER_CLK_FREQ); +#ifdef CONFIG_NON_SECURE + printf("arch timer frequency is wrong, but cannot adjust it\n"); +#else + asm volatile("mcr p15, 0, %0, c14, c0, 0" + : : "r"(CONFIG_TIMER_CLK_FREQ)); +#endif + } } +#endif /* !CONFIG_ARM64 */ ret = axp_gpio_init(); if (ret) @@ -264,7 +287,7 @@ static void mmc_pinmux_setup(int sdc) sunxi_gpio_set_pull(SUNXI_GPC(24), SUNXI_GPIO_PULL_UP); sunxi_gpio_set_drv(SUNXI_GPC(24), 2); } -#elif defined(CONFIG_MACH_SUN8I) +#elif defined(CONFIG_MACH_SUN8I) || defined(CONFIG_MACH_SUN50I) /* SDC2: PC5-PC6, PC8-PC16 */ for (pin = SUNXI_GPC(5); pin <= SUNXI_GPC(6); pin++) { sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2); @@ -547,7 +570,7 @@ void get_board_serial(struct tag_serialnr *serialnr) */ static void parse_spl_header(const uint32_t spl_addr) { - struct boot_file_head *spl = (void *)spl_addr; + struct boot_file_head *spl = (void *)(ulong)spl_addr; if (memcmp(spl->spl_signature, SPL_SIGNATURE, 3) == 0) { uint8_t spl_header_version = spl->spl_signature[3]; if (spl_header_version == SPL_HEADER_VERSION) { diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index 44d1a768c18..ce2dc4ae41c 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -480,6 +480,10 @@ struct mmc *sunxi_mmc_init(int sdc_no) cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; cfg->host_caps = MMC_MODE_4BIT; +#ifdef CONFIG_MACH_SUN50I + if (sdc_no == 2) + cfg->host_caps = MMC_MODE_8BIT; +#endif cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 937b9aa246b..3c41bca32ac 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -10,7 +10,7 @@ choice default AXP209_POWER if MACH_SUN4I || MACH_SUN5I || MACH_SUN7I default AXP221_POWER if MACH_SUN6I || MACH_SUN8I_A23 || MACH_SUN8I_A33 default AXP818_POWER if MACH_SUN8I_A83T - default SUNXI_NO_PMIC if MACH_SUN8I_H3 + default SUNXI_NO_PMIC if MACH_SUN8I_H3 || MACH_SUN50I config SUNXI_NO_PMIC boolean "board without a pmic" diff --git a/include/configs/sun50i.h b/include/configs/sun50i.h new file mode 100644 index 00000000000..0fdb4c7b99c --- /dev/null +++ b/include/configs/sun50i.h @@ -0,0 +1,25 @@ +/* + * Configuration settings for the Allwinner A64 (sun50i) CPU + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * A64 specific configuration + */ + +#define CONFIG_SUNXI_USB_PHYS 1 + +#define COUNTER_FREQUENCY CONFIG_TIMER_CLK_FREQ +#define GICD_BASE 0x1c81000 +#define GICC_BASE 0x1c82000 + +/* + * Include common sunxi configuration where most the settings are + */ +#include + +#endif /* __CONFIG_H */ diff --git a/include/configs/sun6i.h b/include/configs/sun6i.h index 93863b59bc5..95ccc35708a 100644 --- a/include/configs/sun6i.h +++ b/include/configs/sun6i.h @@ -25,7 +25,6 @@ #define CONFIG_ARMV7_PSCI 1 #define CONFIG_ARMV7_PSCI_NR_CPUS 4 #define CONFIG_ARMV7_SECURE_BASE SUNXI_SRAM_B_BASE -#define CONFIG_TIMER_CLK_FREQ 24000000 /* * Include common sunxi configuration where most the settings are diff --git a/include/configs/sun7i.h b/include/configs/sun7i.h index 56101a9ffcd..0dd29029b9b 100644 --- a/include/configs/sun7i.h +++ b/include/configs/sun7i.h @@ -22,7 +22,6 @@ #define CONFIG_ARMV7_PSCI 1 #define CONFIG_ARMV7_SECURE_BASE SUNXI_SRAM_B_BASE -#define CONFIG_TIMER_CLK_FREQ 24000000 /* * Include common sunxi configuration where most the settings are diff --git a/include/configs/sun8i.h b/include/configs/sun8i.h index eb5db4eb16b..bf1b740b186 100644 --- a/include/configs/sun8i.h +++ b/include/configs/sun8i.h @@ -40,8 +40,6 @@ #endif #endif -#define CONFIG_TIMER_CLK_FREQ 24000000 - /* * Include common sunxi configuration where most the settings are */ diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index a3994e1a6ad..8f11eb90c13 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -56,6 +56,7 @@ /* CPU */ #define CONFIG_DISPLAY_CPUINFO #define CONFIG_SYS_CACHELINE_SIZE 64 +#define CONFIG_TIMER_CLK_FREQ 24000000 /* * The DRAM Base differs between some models. We cannot use macros for the @@ -90,7 +91,7 @@ #define CONFIG_SPL_BSS_MAX_SIZE 0x00080000 /* 512 KiB */ -#ifdef CONFIG_MACH_SUN9I +#if defined(CONFIG_MACH_SUN9I) || defined(CONFIG_MACH_SUN50I) /* * The A80's A1 sram starts at 0x00010000 rather then at 0x00000000 and is * slightly bigger. Note that it is possible to map the first 32 KiB of the @@ -99,7 +100,7 @@ * the 1 actually activates the mapping of the first 32 KiB to 0x00000000. */ #define CONFIG_SYS_INIT_RAM_ADDR 0x10000 -#define CONFIG_SYS_INIT_RAM_SIZE 0x0a000 /* 40 KiB */ +#define CONFIG_SYS_INIT_RAM_SIZE 0x08000 /* FIXME: 40 KiB ? */ #else #define CONFIG_SYS_INIT_RAM_ADDR 0x0 #define CONFIG_SYS_INIT_RAM_SIZE 0x8000 /* 32 KiB */ @@ -188,8 +189,16 @@ #define CONFIG_SPL_BOARD_LOAD_IMAGE +#if defined(CONFIG_MACH_SUN9I) +#define CONFIG_SPL_TEXT_BASE 0x10020 /* sram start+header */ +#define CONFIG_SPL_MAX_SIZE 0x5fe0 /* ? KiB on sun9i */ +#elif defined(CONFIG_MACH_SUN50I) +#define CONFIG_SPL_TEXT_BASE 0x10020 /* sram start+header */ +#define CONFIG_SPL_MAX_SIZE 0x7fe0 /* 32 KiB on sun50i */ +#else #define CONFIG_SPL_TEXT_BASE 0x20 /* sram start+header */ #define CONFIG_SPL_MAX_SIZE 0x5fe0 /* 24KB on sun4i/sun7i */ +#endif #define CONFIG_SPL_LIBDISK_SUPPORT @@ -197,14 +206,22 @@ #define CONFIG_SPL_MMC_SUPPORT #endif +#ifndef CONFIG_ARM64 #define CONFIG_SPL_LDSCRIPT "arch/arm/cpu/armv7/sunxi/u-boot-spl.lds" +#endif #define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 80 /* 40KiB */ #define CONFIG_SPL_PAD_TO 32768 /* decimal for 'dd' */ +#if defined(CONFIG_MACH_SUN9I) || defined(CONFIG_MACH_SUN50I) +/* FIXME: 40 KiB instead of 32 KiB ? */ +#define LOW_LEVEL_SRAM_STACK 0x00018000 +#define CONFIG_SPL_STACK LOW_LEVEL_SRAM_STACK +#else /* end of 32 KiB in sram */ #define LOW_LEVEL_SRAM_STACK 0x00008000 /* End of sram */ #define CONFIG_SPL_STACK LOW_LEVEL_SRAM_STACK +#endif /* I2C */ #if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \ -- cgit v1.3.1