From 5f8afd704c09a557f7303eac22d18c76f855c1cb Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 24 Mar 2016 22:37:08 +0100 Subject: sunxi: Add conditional magic sram poke for A33 I noticed that for certain SoC versions boot0 does a magic poke when build for A33. I'm not aware of this actually being necessary anywhere, but better safe then sorry. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- arch/arm/cpu/armv7/sunxi/board.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'arch/arm/cpu/armv7/sunxi') diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c index 7653148c67..bf58fa90ec 100644 --- a/arch/arm/cpu/armv7/sunxi/board.c +++ b/arch/arm/cpu/armv7/sunxi/board.c @@ -120,18 +120,30 @@ void s_init(void) */ #if defined CONFIG_MACH_SUN6I setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0x1800); -#elif defined CONFIG_MACH_SUN8I_A23 - uint version; +#elif defined CONFIG_MACH_SUN8I + __maybe_unused uint version; /* Unlock sram version info reg, read it, relock */ setbits_le32(SUNXI_SRAMC_BASE + 0x24, (1 << 15)); - version = readl(SUNXI_SRAMC_BASE + 0x24); + version = readl(SUNXI_SRAMC_BASE + 0x24) >> 16; clrbits_le32(SUNXI_SRAMC_BASE + 0x24, (1 << 15)); - if ((version & 0xffff0000) == 0x16500000) + /* + * Ideally this would be a switch case, but we do not know exactly + * which versions there are and which version needs which settings, + * so reproduce the per SoC code from the BSP. + */ +#if defined CONFIG_MACH_SUN8I_A23 + if (version == 0x1650) setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0x1800); else /* 0x1661 ? */ setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0xc0); +#elif defined CONFIG_MACH_SUN8I_A33 + if (version != 0x1667) + setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0xc0); +#endif + /* A83T BSP never modifies SUNXI_SRAMC_BASE + 0x44 */ + /* No H3 BSP, boot0 seems to not modify SUNXI_SRAMC_BASE + 0x44 */ #endif #if defined CONFIG_MACH_SUN6I || \ -- cgit From c74384c68011c894a3543f7aca7bc387c1ab4a16 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 24 Mar 2016 22:38:23 +0100 Subject: sunxi: Print soc-id from sram controller for sun8i boards As the need for various magic sram pokes has shown this maybe useful info to have. e.g. this shows one of my a23 tablets having an id of 1661 rather then the usual 1650 for the a23. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- arch/arm/cpu/armv7/sunxi/cpu_info.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'arch/arm/cpu/armv7/sunxi') diff --git a/arch/arm/cpu/armv7/sunxi/cpu_info.c b/arch/arm/cpu/armv7/sunxi/cpu_info.c index b9bc70ca86..c0eabdf91d 100644 --- a/arch/arm/cpu/armv7/sunxi/cpu_info.c +++ b/arch/arm/cpu/armv7/sunxi/cpu_info.c @@ -38,6 +38,20 @@ int sunxi_get_ss_bonding_id(void) } #endif +#ifdef CONFIG_MACH_SUN8I +uint sunxi_get_sram_id(void) +{ + uint id; + + /* Unlock sram info reg, read it, relock */ + setbits_le32(SUNXI_SRAMC_BASE + 0x24, (1 << 15)); + id = readl(SUNXI_SRAMC_BASE + 0x24) >> 16; + clrbits_le32(SUNXI_SRAMC_BASE + 0x24, (1 << 15)); + + return id; +} +#endif + #ifdef CONFIG_DISPLAY_CPUINFO int print_cpuinfo(void) { @@ -66,15 +80,15 @@ int print_cpuinfo(void) #elif defined CONFIG_MACH_SUN7I puts("CPU: Allwinner A20 (SUN7I)\n"); #elif defined CONFIG_MACH_SUN8I_A23 - puts("CPU: Allwinner A23 (SUN8I)\n"); + printf("CPU: Allwinner A23 (SUN8I %04x)\n", sunxi_get_sram_id()); #elif defined CONFIG_MACH_SUN8I_A33 - puts("CPU: Allwinner A33 (SUN8I)\n"); + printf("CPU: Allwinner A33 (SUN8I %04x)\n", sunxi_get_sram_id()); +#elif defined CONFIG_MACH_SUN8I_A83T + printf("CPU: Allwinner A83T (SUN8I %04x)\n", sunxi_get_sram_id()); #elif defined CONFIG_MACH_SUN8I_H3 - puts("CPU: Allwinner H3 (SUN8I)\n"); + 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_SUN8I_A83T - puts("CPU: Allwinner A83T (SUN8I)\n"); #else #warning Please update cpu_info.c with correct CPU information puts("CPU: SUNXI Family\n"); -- cgit From 0c935acb9e5dcc0b5889c95a5f3d4163c8638c70 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 30 Mar 2016 00:26:51 +0800 Subject: sunxi: usb_phy: Add support for A83T USB PHYs The A83T has 3 USB PHYs: 1 for USB OTG, 1 for standard USB 1.1/2.0 host, 1 for USB HSIC. Signed-off-by: Chen-Yu Tsai Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- arch/arm/cpu/armv7/sunxi/usb_phy.c | 48 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) (limited to 'arch/arm/cpu/armv7/sunxi') diff --git a/arch/arm/cpu/armv7/sunxi/usb_phy.c b/arch/arm/cpu/armv7/sunxi/usb_phy.c index 0749fbdadc..fa375f1d16 100644 --- a/arch/arm/cpu/armv7/sunxi/usb_phy.c +++ b/arch/arm/cpu/armv7/sunxi/usb_phy.c @@ -34,6 +34,16 @@ #define REG_PHY_UNK_H3 0x420 #define REG_PMU_UNK_H3 0x810 +/* A83T specific control bits for PHY0 */ +#define SUNXI_PHY_CTL_VBUSVLDEXT BIT(5) +#define SUNXI_PHY_CTL_SIDDQ BIT(3) + +/* A83T HSIC specific bits */ +#define SUNXI_EHCI_HS_FORCE BIT(20) +#define SUNXI_EHCI_CONNECT_DET BIT(17) +#define SUNXI_EHCI_CONNECT_INT BIT(16) +#define SUNXI_EHCI_HSIC BIT(1) + static struct sunxi_usb_phy { int usb_rst_mask; int gpio_vbus; @@ -56,7 +66,12 @@ static struct sunxi_usb_phy { }, #if CONFIG_SUNXI_USB_PHYS >= 3 { +#ifdef CONFIG_MACH_SUN8I_A83T + .usb_rst_mask = CCM_USB_CTRL_HSIC_RST | CCM_USB_CTRL_HSIC_CLK | + CCM_USB_CTRL_12M_CLK, +#else .usb_rst_mask = CCM_USB_CTRL_PHY2_RST | CCM_USB_CTRL_PHY2_CLK, +#endif .id = 2, .base = SUNXI_USB2_BASE, }, @@ -97,8 +112,8 @@ static int get_id_detect_gpio(int index) return -EINVAL; } -static void usb_phy_write(struct sunxi_usb_phy *phy, int addr, - int data, int len) +__maybe_unused static void usb_phy_write(struct sunxi_usb_phy *phy, int addr, + int data, int len) { int j = 0, usbc_bit = 0; void *dest = (void *)SUNXI_USB0_BASE + SUNXI_USB_CSR; @@ -137,6 +152,10 @@ static void sunxi_usb_phy_config(struct sunxi_usb_phy *phy) clrbits_le32(phy->base + REG_PMU_UNK_H3, 0x02); } +#elif defined CONFIG_MACH_SUN8I_A83T +static void sunxi_usb_phy_config(struct sunxi_usb_phy *phy) +{ +} #else static void sunxi_usb_phy_config(struct sunxi_usb_phy *phy) { @@ -174,6 +193,13 @@ static void sunxi_usb_phy_passby(struct sunxi_usb_phy *phy, int enable) SUNXI_EHCI_AHB_INCRX_ALIGN_EN | SUNXI_EHCI_ULPI_BYPASS_EN; +#ifdef CONFIG_MACH_SUN8I_A83T + if (phy->id == 2) + bits |= SUNXI_EHCI_HS_FORCE | + SUNXI_EHCI_CONNECT_INT | + SUNXI_EHCI_HSIC; +#endif + if (enable) setbits_le32(addr, bits); else @@ -184,9 +210,11 @@ static void sunxi_usb_phy_passby(struct sunxi_usb_phy *phy, int enable) void sunxi_usb_phy_enable_squelch_detect(int index, int enable) { +#ifndef CONFIG_MACH_SUN8I_A83T struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; usb_phy_write(phy, 0x3c, enable ? 0 : 2, 2); +#endif } void sunxi_usb_phy_init(int index) @@ -204,6 +232,15 @@ void sunxi_usb_phy_init(int index) if (phy->id != 0) sunxi_usb_phy_passby(phy, SUNXI_USB_PASSBY_EN); + +#ifdef CONFIG_MACH_SUN8I_A83T + if (phy->id == 0) { + setbits_le32(SUNXI_USB0_BASE + SUNXI_USB_CSR, + SUNXI_PHY_CTL_VBUSVLDEXT); + clrbits_le32(SUNXI_USB0_BASE + SUNXI_USB_CSR, + SUNXI_PHY_CTL_SIDDQ); + } +#endif } void sunxi_usb_phy_exit(int index) @@ -218,6 +255,13 @@ void sunxi_usb_phy_exit(int index) if (phy->id != 0) sunxi_usb_phy_passby(phy, !SUNXI_USB_PASSBY_EN); +#ifdef CONFIG_MACH_SUN8I_A83T + if (phy->id == 0) { + setbits_le32(SUNXI_USB0_BASE + SUNXI_USB_CSR, + SUNXI_PHY_CTL_SIDDQ); + } +#endif + clrbits_le32(&ccm->usb_clk_cfg, phy->usb_rst_mask); } -- cgit From e6e505b93cb3fd264227c65ae1bfc9e4681555d8 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 29 Mar 2016 17:29:06 +0200 Subject: sunxi: Move cpu independent code to mach directory Some of the code in arch/arm/cpu/armv7/sunxi is actually armv7 specific, while most of it is just generic code that could as well be used on an AArch64 SoC. Move all files that are not really tied to armv7 into a new mach-sunxi directory. Signed-off-by: Alexander Graf Acked-by: Hans de Goede Signed-off-by: Hans de Goede --- arch/arm/cpu/armv7/sunxi/Makefile | 38 +- arch/arm/cpu/armv7/sunxi/board.c | 274 ----------- arch/arm/cpu/armv7/sunxi/clock.c | 65 --- arch/arm/cpu/armv7/sunxi/clock_sun4i.c | 238 --------- arch/arm/cpu/armv7/sunxi/clock_sun6i.c | 274 ----------- arch/arm/cpu/armv7/sunxi/clock_sun8i_a83t.c | 136 ----- arch/arm/cpu/armv7/sunxi/clock_sun9i.c | 68 --- arch/arm/cpu/armv7/sunxi/cpu_info.c | 114 ----- arch/arm/cpu/armv7/sunxi/dram_helpers.c | 37 -- arch/arm/cpu/armv7/sunxi/dram_sun4i.c | 737 ---------------------------- arch/arm/cpu/armv7/sunxi/dram_sun6i.c | 411 ---------------- arch/arm/cpu/armv7/sunxi/dram_sun8i_a23.c | 343 ------------- arch/arm/cpu/armv7/sunxi/dram_sun8i_a33.c | 362 -------------- arch/arm/cpu/armv7/sunxi/dram_sun8i_a83t.c | 472 ------------------ arch/arm/cpu/armv7/sunxi/dram_sun8i_h3.c | 469 ------------------ arch/arm/cpu/armv7/sunxi/p2wi.c | 117 ----- arch/arm/cpu/armv7/sunxi/pinmux.c | 71 --- arch/arm/cpu/armv7/sunxi/pmic_bus.c | 113 ----- arch/arm/cpu/armv7/sunxi/prcm.c | 47 -- arch/arm/cpu/armv7/sunxi/rsb.c | 175 ------- arch/arm/cpu/armv7/sunxi/usb_phy.c | 400 --------------- 21 files changed, 1 insertion(+), 4960 deletions(-) delete mode 100644 arch/arm/cpu/armv7/sunxi/board.c delete mode 100644 arch/arm/cpu/armv7/sunxi/clock.c delete mode 100644 arch/arm/cpu/armv7/sunxi/clock_sun4i.c delete mode 100644 arch/arm/cpu/armv7/sunxi/clock_sun6i.c delete mode 100644 arch/arm/cpu/armv7/sunxi/clock_sun8i_a83t.c delete mode 100644 arch/arm/cpu/armv7/sunxi/clock_sun9i.c delete mode 100644 arch/arm/cpu/armv7/sunxi/cpu_info.c delete mode 100644 arch/arm/cpu/armv7/sunxi/dram_helpers.c delete mode 100644 arch/arm/cpu/armv7/sunxi/dram_sun4i.c delete mode 100644 arch/arm/cpu/armv7/sunxi/dram_sun6i.c delete mode 100644 arch/arm/cpu/armv7/sunxi/dram_sun8i_a23.c delete mode 100644 arch/arm/cpu/armv7/sunxi/dram_sun8i_a33.c delete mode 100644 arch/arm/cpu/armv7/sunxi/dram_sun8i_a83t.c delete mode 100644 arch/arm/cpu/armv7/sunxi/dram_sun8i_h3.c delete mode 100644 arch/arm/cpu/armv7/sunxi/p2wi.c delete mode 100644 arch/arm/cpu/armv7/sunxi/pinmux.c delete mode 100644 arch/arm/cpu/armv7/sunxi/pmic_bus.c delete mode 100644 arch/arm/cpu/armv7/sunxi/prcm.c delete mode 100644 arch/arm/cpu/armv7/sunxi/rsb.c delete mode 100644 arch/arm/cpu/armv7/sunxi/usb_phy.c (limited to 'arch/arm/cpu/armv7/sunxi') diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile index ce8e5717e7..4d2274a38e 100644 --- a/arch/arm/cpu/armv7/sunxi/Makefile +++ b/arch/arm/cpu/armv7/sunxi/Makefile @@ -8,38 +8,10 @@ # SPDX-License-Identifier: GPL-2.0+ # obj-y += timer.o -obj-y += board.o -obj-y += clock.o -obj-y += cpu_info.o -obj-y += dram_helpers.o -obj-y += pinmux.o -ifndef CONFIG_MACH_SUN9I -obj-y += usb_phy.o -endif -obj-$(CONFIG_MACH_SUN6I) += prcm.o -obj-$(CONFIG_MACH_SUN8I) += prcm.o -obj-$(CONFIG_MACH_SUN9I) += prcm.o -obj-$(CONFIG_MACH_SUN6I) += p2wi.o -obj-$(CONFIG_MACH_SUN8I) += rsb.o -obj-$(CONFIG_MACH_SUN9I) += rsb.o -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 -ifdef CONFIG_MACH_SUN8I_A83T -obj-y += clock_sun8i_a83t.o -else -obj-$(CONFIG_MACH_SUN8I) += clock_sun6i.o -endif -obj-$(CONFIG_MACH_SUN9I) += clock_sun9i.o + obj-$(CONFIG_MACH_SUN6I) += tzpc.o obj-$(CONFIG_MACH_SUN8I_H3) += tzpc.o -obj-$(CONFIG_AXP152_POWER) += pmic_bus.o -obj-$(CONFIG_AXP209_POWER) += pmic_bus.o -obj-$(CONFIG_AXP221_POWER) += pmic_bus.o -obj-$(CONFIG_AXP818_POWER) += pmic_bus.o - ifndef CONFIG_SPL_BUILD ifdef CONFIG_ARMV7_PSCI obj-$(CONFIG_MACH_SUN6I) += psci_sun6i.o @@ -49,13 +21,5 @@ endif endif ifdef CONFIG_SPL_BUILD -obj-$(CONFIG_MACH_SUN4I) += dram_sun4i.o -obj-$(CONFIG_MACH_SUN5I) += dram_sun4i.o -obj-$(CONFIG_MACH_SUN6I) += dram_sun6i.o -obj-$(CONFIG_MACH_SUN7I) += dram_sun4i.o -obj-$(CONFIG_MACH_SUN8I_A23) += dram_sun8i_a23.o -obj-$(CONFIG_MACH_SUN8I_A33) += dram_sun8i_a33.o -obj-$(CONFIG_MACH_SUN8I_A83T) += dram_sun8i_a83t.o -obj-$(CONFIG_MACH_SUN8I_H3) += dram_sun8i_h3.o obj-y += fel_utils.o endif diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c deleted file mode 100644 index bf58fa90ec..0000000000 --- a/arch/arm/cpu/armv7/sunxi/board.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * (C) Copyright 2012 Henrik Nordstrom - * - * (C) Copyright 2007-2011 - * Allwinner Technology Co., Ltd. - * Tom Cubie - * - * Some init for sunxi platform. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#ifdef CONFIG_SPL_BUILD -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -struct fel_stash { - uint32_t sp; - uint32_t lr; - uint32_t cpsr; - uint32_t sctlr; - uint32_t vbar; - uint32_t cr; -}; - -struct fel_stash fel_stash __attribute__((section(".data"))); - -static int gpio_init(void) -{ -#if CONFIG_CONS_INDEX == 1 && defined(CONFIG_UART0_PORT_F) -#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I) - /* disable GPB22,23 as uart0 tx,rx to avoid conflict */ - sunxi_gpio_set_cfgpin(SUNXI_GPB(22), SUNXI_GPIO_INPUT); - sunxi_gpio_set_cfgpin(SUNXI_GPB(23), SUNXI_GPIO_INPUT); -#endif -#if defined(CONFIG_MACH_SUN8I) - sunxi_gpio_set_cfgpin(SUNXI_GPF(2), SUN8I_GPF_UART0); - sunxi_gpio_set_cfgpin(SUNXI_GPF(4), SUN8I_GPF_UART0); -#else - sunxi_gpio_set_cfgpin(SUNXI_GPF(2), SUNXI_GPF_UART0); - sunxi_gpio_set_cfgpin(SUNXI_GPF(4), SUNXI_GPF_UART0); -#endif - sunxi_gpio_set_pull(SUNXI_GPF(4), 1); -#elif CONFIG_CONS_INDEX == 1 && (defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I)) - sunxi_gpio_set_cfgpin(SUNXI_GPB(22), SUN4I_GPB_UART0); - sunxi_gpio_set_cfgpin(SUNXI_GPB(23), SUN4I_GPB_UART0); - sunxi_gpio_set_pull(SUNXI_GPB(23), SUNXI_GPIO_PULL_UP); -#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUN5I) - sunxi_gpio_set_cfgpin(SUNXI_GPB(19), SUN5I_GPB_UART0); - sunxi_gpio_set_cfgpin(SUNXI_GPB(20), SUN5I_GPB_UART0); - sunxi_gpio_set_pull(SUNXI_GPB(20), SUNXI_GPIO_PULL_UP); -#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUN6I) - sunxi_gpio_set_cfgpin(SUNXI_GPH(20), SUN6I_GPH_UART0); - sunxi_gpio_set_cfgpin(SUNXI_GPH(21), SUN6I_GPH_UART0); - sunxi_gpio_set_pull(SUNXI_GPH(21), SUNXI_GPIO_PULL_UP); -#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUN8I_A33) - sunxi_gpio_set_cfgpin(SUNXI_GPB(0), SUN8I_A33_GPB_UART0); - sunxi_gpio_set_cfgpin(SUNXI_GPB(1), SUN8I_A33_GPB_UART0); - sunxi_gpio_set_pull(SUNXI_GPB(1), SUNXI_GPIO_PULL_UP); -#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUN8I_H3) - 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_SUN8I_A83T) - sunxi_gpio_set_cfgpin(SUNXI_GPB(9), SUN8I_A83T_GPB_UART0); - sunxi_gpio_set_cfgpin(SUNXI_GPB(10), SUN8I_A83T_GPB_UART0); - sunxi_gpio_set_pull(SUNXI_GPB(10), SUNXI_GPIO_PULL_UP); -#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUN9I) - sunxi_gpio_set_cfgpin(SUNXI_GPH(12), SUN9I_GPH_UART0); - sunxi_gpio_set_cfgpin(SUNXI_GPH(13), SUN9I_GPH_UART0); - sunxi_gpio_set_pull(SUNXI_GPH(13), SUNXI_GPIO_PULL_UP); -#elif CONFIG_CONS_INDEX == 2 && defined(CONFIG_MACH_SUN5I) - sunxi_gpio_set_cfgpin(SUNXI_GPG(3), SUN5I_GPG_UART1); - sunxi_gpio_set_cfgpin(SUNXI_GPG(4), SUN5I_GPG_UART1); - sunxi_gpio_set_pull(SUNXI_GPG(4), SUNXI_GPIO_PULL_UP); -#elif CONFIG_CONS_INDEX == 3 && defined(CONFIG_MACH_SUN8I) - sunxi_gpio_set_cfgpin(SUNXI_GPB(0), SUN8I_GPB_UART2); - sunxi_gpio_set_cfgpin(SUNXI_GPB(1), SUN8I_GPB_UART2); - sunxi_gpio_set_pull(SUNXI_GPB(1), SUNXI_GPIO_PULL_UP); -#elif CONFIG_CONS_INDEX == 5 && defined(CONFIG_MACH_SUN8I) - sunxi_gpio_set_cfgpin(SUNXI_GPL(2), SUN8I_GPL_R_UART); - sunxi_gpio_set_cfgpin(SUNXI_GPL(3), SUN8I_GPL_R_UART); - sunxi_gpio_set_pull(SUNXI_GPL(3), SUNXI_GPIO_PULL_UP); -#else -#error Unsupported console port number. Please fix pin mux settings in board.c -#endif - - return 0; -} - -int spl_board_load_image(void) -{ - debug("Returning to FEL sp=%x, lr=%x\n", fel_stash.sp, fel_stash.lr); - return_to_fel(fel_stash.sp, fel_stash.lr); - - return 0; -} - -void s_init(void) -{ - /* - * Undocumented magic taken from boot0, without this DRAM - * access gets messed up (seems cache related). - * The boot0 sources describe this as: "config ema for cache sram" - */ -#if defined CONFIG_MACH_SUN6I - setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0x1800); -#elif defined CONFIG_MACH_SUN8I - __maybe_unused uint version; - - /* Unlock sram version info reg, read it, relock */ - setbits_le32(SUNXI_SRAMC_BASE + 0x24, (1 << 15)); - version = readl(SUNXI_SRAMC_BASE + 0x24) >> 16; - clrbits_le32(SUNXI_SRAMC_BASE + 0x24, (1 << 15)); - - /* - * Ideally this would be a switch case, but we do not know exactly - * which versions there are and which version needs which settings, - * so reproduce the per SoC code from the BSP. - */ -#if defined CONFIG_MACH_SUN8I_A23 - if (version == 0x1650) - setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0x1800); - else /* 0x1661 ? */ - setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0xc0); -#elif defined CONFIG_MACH_SUN8I_A33 - if (version != 0x1667) - setbits_le32(SUNXI_SRAMC_BASE + 0x44, 0xc0); -#endif - /* A83T BSP never modifies SUNXI_SRAMC_BASE + 0x44 */ - /* No H3 BSP, boot0 seems to not modify SUNXI_SRAMC_BASE + 0x44 */ -#endif - -#if defined CONFIG_MACH_SUN6I || \ - defined CONFIG_MACH_SUN7I || \ - defined CONFIG_MACH_SUN8I - /* Enable SMP mode for CPU0, by setting bit 6 of Auxiliary Ctl reg */ - asm volatile( - "mrc p15, 0, r0, c1, c0, 1\n" - "orr r0, r0, #1 << 6\n" - "mcr p15, 0, r0, c1, c0, 1\n"); -#endif -#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I_H3 - /* Enable non-secure access to some peripherals */ - tzpc_init(); -#endif - - clock_init(); - timer_init(); - gpio_init(); - i2c_init_board(); - eth_init_board(); -} - -#ifdef CONFIG_SPL_BUILD -DECLARE_GLOBAL_DATA_PTR; - -/* The sunxi internal brom will try to loader external bootloader - * from mmc0, nand flash, mmc2. - */ -u32 spl_boot_device(void) -{ - __maybe_unused struct mmc *mmc0, *mmc1; - /* - * When booting from the SD card or NAND memory, the "eGON.BT0" - * signature is expected to be found in memory at the address 0x0004 - * (see the "mksunxiboot" tool, which generates this header). - * - * When booting in the FEL mode over USB, this signature is patched in - * memory and replaced with something else by the 'fel' tool. This other - * signature is selected in such a way, that it can't be present in a - * valid bootable SD card image (because the BROM would refuse to - * execute the SPL in this case). - * - * This checks for the signature and if it is not found returns to - * the FEL code in the BROM to wait and receive the main u-boot - * binary over USB. If it is found, it determines where SPL was - * read from. - */ - if (!is_boot0_magic(SPL_ADDR + 4)) /* eGON.BT0 */ - return BOOT_DEVICE_BOARD; - - /* The BROM will try to boot from mmc0 first, so try that first. */ -#ifdef CONFIG_MMC - mmc_initialize(gd->bd); - mmc0 = find_mmc_device(0); - if (sunxi_mmc_has_egon_boot_signature(mmc0)) - return BOOT_DEVICE_MMC1; -#endif - - /* Fallback to booting NAND if enabled. */ - if (IS_ENABLED(CONFIG_SPL_NAND_SUPPORT)) - return BOOT_DEVICE_NAND; - -#ifdef CONFIG_MMC - if (CONFIG_MMC_SUNXI_SLOT_EXTRA == 2) { - mmc1 = find_mmc_device(1); - if (sunxi_mmc_has_egon_boot_signature(mmc1)) - return BOOT_DEVICE_MMC2; - } -#endif - - panic("Could not determine boot source\n"); - return -1; /* Never reached */ -} - -/* No confirmation data available in SPL yet. Hardcode bootmode */ -u32 spl_boot_mode(void) -{ - return MMCSD_MODE_RAW; -} - -void board_init_f(ulong dummy) -{ - spl_init(); - preloader_console_init(); - -#ifdef CONFIG_SPL_I2C_SUPPORT - /* Needed early by sunxi_board_init if PMU is enabled */ - i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); -#endif - sunxi_board_init(); -} -#endif - -void reset_cpu(ulong addr) -{ -#ifdef CONFIG_SUNXI_GEN_SUN4I - static const struct sunxi_wdog *wdog = - &((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog; - - /* Set the watchdog for its shortest interval (.5s) and wait */ - writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode); - writel(WDT_CTRL_KEY | WDT_CTRL_RESTART, &wdog->ctl); - - while (1) { - /* sun5i sometimes gets stuck without this */ - writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode); - } -#endif -#ifdef CONFIG_SUNXI_GEN_SUN6I - static const struct sunxi_wdog *wdog = - ((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog; - - /* Set the watchdog for its shortest interval (.5s) and wait */ - writel(WDT_CFG_RESET, &wdog->cfg); - writel(WDT_MODE_EN, &wdog->mode); - writel(WDT_CTRL_KEY | WDT_CTRL_RESTART, &wdog->ctl); - while (1) { } -#endif -} - -#ifndef CONFIG_SYS_DCACHE_OFF -void enable_caches(void) -{ - /* Enable D-cache. I-cache is already enabled in start.S */ - dcache_enable(); -} -#endif diff --git a/arch/arm/cpu/armv7/sunxi/clock.c b/arch/arm/cpu/armv7/sunxi/clock.c deleted file mode 100644 index 0b8fc94711..0000000000 --- a/arch/arm/cpu/armv7/sunxi/clock.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * (C) Copyright 2007-2012 - * Allwinner Technology Co., Ltd. - * Tom Cubie - * - * (C) Copyright 2013 Luke Kenneth Casson Leighton - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include - -__weak void clock_init_sec(void) -{ -} - -int clock_init(void) -{ -#ifdef CONFIG_SPL_BUILD - clock_init_safe(); -#endif - clock_init_uart(); - clock_init_sec(); - - return 0; -} - -/* These functions are shared between various SoCs so put them here. */ -#if defined CONFIG_SUNXI_GEN_SUN6I && !defined CONFIG_MACH_SUN9I -int clock_twi_onoff(int port, int state) -{ - struct sunxi_ccm_reg *const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - - if (port == 5) { - if (state) - prcm_apb0_enable( - PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_I2C); - else - prcm_apb0_disable( - PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_I2C); - return 0; - } - - /* set the apb clock gate and reset for twi */ - if (state) { - setbits_le32(&ccm->apb2_gate, - CLK_GATE_OPEN << (APB2_GATE_TWI_SHIFT + port)); - setbits_le32(&ccm->apb2_reset_cfg, - 1 << (APB2_RESET_TWI_SHIFT + port)); - } else { - clrbits_le32(&ccm->apb2_reset_cfg, - 1 << (APB2_RESET_TWI_SHIFT + port)); - clrbits_le32(&ccm->apb2_gate, - CLK_GATE_OPEN << (APB2_GATE_TWI_SHIFT + port)); - } - - return 0; -} -#endif diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun4i.c b/arch/arm/cpu/armv7/sunxi/clock_sun4i.c deleted file mode 100644 index 7e6bd6137e..0000000000 --- a/arch/arm/cpu/armv7/sunxi/clock_sun4i.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * sun4i, sun5i and sun7i specific clock code - * - * (C) Copyright 2007-2012 - * Allwinner Technology Co., Ltd. - * Tom Cubie - * - * (C) Copyright 2013 Luke Kenneth Casson Leighton - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include - -#ifdef CONFIG_SPL_BUILD -void clock_init_safe(void) -{ - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - - /* Set safe defaults until PMU is configured */ - writel(AXI_DIV_1 << AXI_DIV_SHIFT | - AHB_DIV_2 << AHB_DIV_SHIFT | - APB0_DIV_1 << APB0_DIV_SHIFT | - CPU_CLK_SRC_OSC24M << CPU_CLK_SRC_SHIFT, - &ccm->cpu_ahb_apb0_cfg); - writel(PLL1_CFG_DEFAULT, &ccm->pll1_cfg); - sdelay(200); - writel(AXI_DIV_1 << AXI_DIV_SHIFT | - AHB_DIV_2 << AHB_DIV_SHIFT | - APB0_DIV_1 << APB0_DIV_SHIFT | - CPU_CLK_SRC_PLL1 << CPU_CLK_SRC_SHIFT, - &ccm->cpu_ahb_apb0_cfg); -#ifdef CONFIG_MACH_SUN7I - setbits_le32(&ccm->ahb_gate0, 0x1 << AHB_GATE_OFFSET_DMA); -#endif - writel(PLL6_CFG_DEFAULT, &ccm->pll6_cfg); -#ifdef CONFIG_SUNXI_AHCI - setbits_le32(&ccm->ahb_gate0, 0x1 << AHB_GATE_OFFSET_SATA); - setbits_le32(&ccm->pll6_cfg, 0x1 << CCM_PLL6_CTRL_SATA_EN_SHIFT); -#endif -} -#endif - -void clock_init_uart(void) -{ - struct sunxi_ccm_reg *const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - - /* uart clock source is apb1 */ - writel(APB1_CLK_SRC_OSC24M| - APB1_CLK_RATE_N_1| - APB1_CLK_RATE_M(1), - &ccm->apb1_clk_div_cfg); - - /* open the clock for uart */ - setbits_le32(&ccm->apb1_gate, - CLK_GATE_OPEN << (APB1_GATE_UART_SHIFT+CONFIG_CONS_INDEX - 1)); -} - -int clock_twi_onoff(int port, int state) -{ - struct sunxi_ccm_reg *const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - - /* set the apb clock gate for twi */ - if (state) - setbits_le32(&ccm->apb1_gate, - CLK_GATE_OPEN << (APB1_GATE_TWI_SHIFT + port)); - else - clrbits_le32(&ccm->apb1_gate, - CLK_GATE_OPEN << (APB1_GATE_TWI_SHIFT + port)); - - return 0; -} - -#ifdef CONFIG_SPL_BUILD -#define PLL1_CFG(N, K, M, P) ( 1 << CCM_PLL1_CFG_ENABLE_SHIFT | \ - 0 << CCM_PLL1_CFG_VCO_RST_SHIFT | \ - 8 << CCM_PLL1_CFG_VCO_BIAS_SHIFT | \ - 0 << CCM_PLL1_CFG_PLL4_EXCH_SHIFT | \ - 16 << CCM_PLL1_CFG_BIAS_CUR_SHIFT | \ - (P)<< CCM_PLL1_CFG_DIVP_SHIFT | \ - 2 << CCM_PLL1_CFG_LCK_TMR_SHIFT | \ - (N)<< CCM_PLL1_CFG_FACTOR_N_SHIFT | \ - (K)<< CCM_PLL1_CFG_FACTOR_K_SHIFT | \ - 0 << CCM_PLL1_CFG_SIG_DELT_PAT_IN_SHIFT | \ - 0 << CCM_PLL1_CFG_SIG_DELT_PAT_EN_SHIFT | \ - (M)<< CCM_PLL1_CFG_FACTOR_M_SHIFT) - -static struct { - u32 pll1_cfg; - unsigned int freq; -} pll1_para[] = { - /* This array must be ordered by frequency. */ - { PLL1_CFG(31, 1, 0, 0), 1488000000}, - { PLL1_CFG(30, 1, 0, 0), 1440000000}, - { PLL1_CFG(29, 1, 0, 0), 1392000000}, - { PLL1_CFG(28, 1, 0, 0), 1344000000}, - { PLL1_CFG(27, 1, 0, 0), 1296000000}, - { PLL1_CFG(26, 1, 0, 0), 1248000000}, - { PLL1_CFG(25, 1, 0, 0), 1200000000}, - { PLL1_CFG(24, 1, 0, 0), 1152000000}, - { PLL1_CFG(23, 1, 0, 0), 1104000000}, - { PLL1_CFG(22, 1, 0, 0), 1056000000}, - { PLL1_CFG(21, 1, 0, 0), 1008000000}, - { PLL1_CFG(20, 1, 0, 0), 960000000 }, - { PLL1_CFG(19, 1, 0, 0), 912000000 }, - { PLL1_CFG(16, 1, 0, 0), 768000000 }, - /* Final catchall entry 384MHz*/ - { PLL1_CFG(16, 0, 0, 0), 0 }, - -}; - -void clock_set_pll1(unsigned int hz) -{ - int i = 0; - int axi, ahb, apb0; - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - - /* Find target frequency */ - while (pll1_para[i].freq > hz) - i++; - - hz = pll1_para[i].freq; - if (! hz) - hz = 384000000; - - /* Calculate system clock divisors */ - axi = DIV_ROUND_UP(hz, 432000000); /* Max 450MHz */ - ahb = DIV_ROUND_UP(hz/axi, 204000000); /* Max 250MHz */ - apb0 = 2; /* Max 150MHz */ - - printf("CPU: %uHz, AXI/AHB/APB: %d/%d/%d\n", hz, axi, ahb, apb0); - - /* Map divisors to register values */ - axi = axi - 1; - if (ahb > 4) - ahb = 3; - else if (ahb > 2) - ahb = 2; - else if (ahb > 1) - ahb = 1; - else - ahb = 0; - - apb0 = apb0 - 1; - - /* Switch to 24MHz clock while changing PLL1 */ - writel(AXI_DIV_1 << AXI_DIV_SHIFT | - AHB_DIV_2 << AHB_DIV_SHIFT | - APB0_DIV_1 << APB0_DIV_SHIFT | - CPU_CLK_SRC_OSC24M << CPU_CLK_SRC_SHIFT, - &ccm->cpu_ahb_apb0_cfg); - sdelay(20); - - /* Configure sys clock divisors */ - writel(axi << AXI_DIV_SHIFT | - ahb << AHB_DIV_SHIFT | - apb0 << APB0_DIV_SHIFT | - CPU_CLK_SRC_OSC24M << CPU_CLK_SRC_SHIFT, - &ccm->cpu_ahb_apb0_cfg); - - /* Configure PLL1 at the desired frequency */ - writel(pll1_para[i].pll1_cfg, &ccm->pll1_cfg); - sdelay(200); - - /* Switch CPU to PLL1 */ - writel(axi << AXI_DIV_SHIFT | - ahb << AHB_DIV_SHIFT | - apb0 << APB0_DIV_SHIFT | - CPU_CLK_SRC_PLL1 << CPU_CLK_SRC_SHIFT, - &ccm->cpu_ahb_apb0_cfg); - sdelay(20); -} -#endif - -void clock_set_pll3(unsigned int clk) -{ - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - - if (clk == 0) { - clrbits_le32(&ccm->pll3_cfg, CCM_PLL3_CTRL_EN); - return; - } - - /* PLL3 rate = 3000000 * m */ - writel(CCM_PLL3_CTRL_EN | CCM_PLL3_CTRL_INTEGER_MODE | - CCM_PLL3_CTRL_M(clk / 3000000), &ccm->pll3_cfg); -} - -unsigned int clock_get_pll3(void) -{ - struct sunxi_ccm_reg *const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - uint32_t rval = readl(&ccm->pll3_cfg); - int m = ((rval & CCM_PLL3_CTRL_M_MASK) >> CCM_PLL3_CTRL_M_SHIFT); - return 3000000 * m; -} - -unsigned int clock_get_pll5p(void) -{ - struct sunxi_ccm_reg *const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - uint32_t rval = readl(&ccm->pll5_cfg); - int n = ((rval & CCM_PLL5_CTRL_N_MASK) >> CCM_PLL5_CTRL_N_SHIFT); - int k = ((rval & CCM_PLL5_CTRL_K_MASK) >> CCM_PLL5_CTRL_K_SHIFT) + 1; - int p = ((rval & CCM_PLL5_CTRL_P_MASK) >> CCM_PLL5_CTRL_P_SHIFT); - return (24000000 * n * k) >> p; -} - -unsigned int clock_get_pll6(void) -{ - struct sunxi_ccm_reg *const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - uint32_t rval = readl(&ccm->pll6_cfg); - int n = ((rval & CCM_PLL6_CTRL_N_MASK) >> CCM_PLL6_CTRL_N_SHIFT); - int k = ((rval & CCM_PLL6_CTRL_K_MASK) >> CCM_PLL6_CTRL_K_SHIFT) + 1; - return 24000000 * n * k / 2; -} - -void clock_set_de_mod_clock(u32 *clk_cfg, unsigned int hz) -{ - int pll = clock_get_pll5p(); - int div = 1; - - while ((pll / div) > hz) - div++; - - writel(CCM_DE_CTRL_GATE | CCM_DE_CTRL_RST | CCM_DE_CTRL_PLL5P | - CCM_DE_CTRL_M(div), clk_cfg); -} diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c deleted file mode 100644 index 15272c9e71..0000000000 --- a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * sun6i specific clock code - * - * (C) Copyright 2007-2012 - * Allwinner Technology Co., Ltd. - * Tom Cubie - * - * (C) Copyright 2013 Luke Kenneth Casson Leighton - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include - -#ifdef CONFIG_SPL_BUILD -void clock_init_safe(void) -{ - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - struct sunxi_prcm_reg * const prcm = - (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE; - - /* Set PLL ldo voltage without this PLL6 does not work properly */ - clrsetbits_le32(&prcm->pll_ctrl1, PRCM_PLL_CTRL_LDO_KEY_MASK, - PRCM_PLL_CTRL_LDO_KEY); - clrsetbits_le32(&prcm->pll_ctrl1, ~PRCM_PLL_CTRL_LDO_KEY_MASK, - PRCM_PLL_CTRL_LDO_DIGITAL_EN | PRCM_PLL_CTRL_LDO_ANALOG_EN | - PRCM_PLL_CTRL_EXT_OSC_EN | PRCM_PLL_CTRL_LDO_OUT_L(1140)); - clrbits_le32(&prcm->pll_ctrl1, PRCM_PLL_CTRL_LDO_KEY_MASK); - - clock_set_pll1(408000000); - - writel(PLL6_CFG_DEFAULT, &ccm->pll6_cfg); - while (!(readl(&ccm->pll6_cfg) & CCM_PLL6_CTRL_LOCK)) - ; - - writel(AHB1_ABP1_DIV_DEFAULT, &ccm->ahb1_apb1_div); - - writel(MBUS_CLK_DEFAULT, &ccm->mbus0_clk_cfg); - writel(MBUS_CLK_DEFAULT, &ccm->mbus1_clk_cfg); -} -#endif - -void clock_init_sec(void) -{ -#ifdef CONFIG_MACH_SUN8I_H3 - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - - setbits_le32(&ccm->ccu_sec_switch, - CCM_SEC_SWITCH_MBUS_NONSEC | - CCM_SEC_SWITCH_BUS_NONSEC | - CCM_SEC_SWITCH_PLL_NONSEC); -#endif -} - -void clock_init_uart(void) -{ -#if CONFIG_CONS_INDEX < 5 - struct sunxi_ccm_reg *const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - - /* uart clock source is apb2 */ - writel(APB2_CLK_SRC_OSC24M| - APB2_CLK_RATE_N_1| - APB2_CLK_RATE_M(1), - &ccm->apb2_div); - - /* open the clock for uart */ - setbits_le32(&ccm->apb2_gate, - CLK_GATE_OPEN << (APB2_GATE_UART_SHIFT + - CONFIG_CONS_INDEX - 1)); - - /* deassert uart reset */ - setbits_le32(&ccm->apb2_reset_cfg, - 1 << (APB2_RESET_UART_SHIFT + - CONFIG_CONS_INDEX - 1)); -#else - /* enable R_PIO and R_UART clocks, and de-assert resets */ - prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_UART); -#endif -} - -#ifdef CONFIG_SPL_BUILD -void clock_set_pll1(unsigned int clk) -{ - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - const int p = 0; - int k = 1; - int m = 1; - - if (clk > 1152000000) { - k = 2; - } else if (clk > 768000000) { - k = 3; - m = 2; - } - - /* Switch to 24MHz clock while changing PLL1 */ - writel(AXI_DIV_3 << AXI_DIV_SHIFT | - ATB_DIV_2 << ATB_DIV_SHIFT | - CPU_CLK_SRC_OSC24M << CPU_CLK_SRC_SHIFT, - &ccm->cpu_axi_cfg); - - /* - * sun6i: PLL1 rate = ((24000000 * n * k) >> 0) / m (p is ignored) - * sun8i: PLL1 rate = ((24000000 * n * k) >> p) / m - */ - writel(CCM_PLL1_CTRL_EN | CCM_PLL1_CTRL_P(p) | - CCM_PLL1_CTRL_N(clk / (24000000 * k / m)) | - CCM_PLL1_CTRL_K(k) | CCM_PLL1_CTRL_M(m), &ccm->pll1_cfg); - sdelay(200); - - /* Switch CPU to PLL1 */ - writel(AXI_DIV_3 << AXI_DIV_SHIFT | - ATB_DIV_2 << ATB_DIV_SHIFT | - CPU_CLK_SRC_PLL1 << CPU_CLK_SRC_SHIFT, - &ccm->cpu_axi_cfg); -} -#endif - -void clock_set_pll3(unsigned int clk) -{ - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - const int m = 8; /* 3 MHz steps just like sun4i, sun5i and sun7i */ - - if (clk == 0) { - clrbits_le32(&ccm->pll3_cfg, CCM_PLL3_CTRL_EN); - return; - } - - /* PLL3 rate = 24000000 * n / m */ - writel(CCM_PLL3_CTRL_EN | CCM_PLL3_CTRL_INTEGER_MODE | - CCM_PLL3_CTRL_N(clk / (24000000 / m)) | CCM_PLL3_CTRL_M(m), - &ccm->pll3_cfg); -} - -void clock_set_pll5(unsigned int clk, bool sigma_delta_enable) -{ - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - const int max_n = 32; - int k = 1, m = 2; - - if (sigma_delta_enable) - writel(CCM_PLL5_PATTERN, &ccm->pll5_pattern_cfg); - - /* PLL5 rate = 24000000 * n * k / m */ - if (clk > 24000000 * k * max_n / m) { - m = 1; - if (clk > 24000000 * k * max_n / m) - k = 2; - } - writel(CCM_PLL5_CTRL_EN | - (sigma_delta_enable ? CCM_PLL5_CTRL_SIGMA_DELTA_EN : 0) | - CCM_PLL5_CTRL_UPD | - CCM_PLL5_CTRL_N(clk / (24000000 * k / m)) | - CCM_PLL5_CTRL_K(k) | CCM_PLL5_CTRL_M(m), &ccm->pll5_cfg); - - udelay(5500); -} - -#ifdef CONFIG_MACH_SUN6I -void clock_set_mipi_pll(unsigned int clk) -{ - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - unsigned int k, m, n, value, diff; - unsigned best_k = 0, best_m = 0, best_n = 0, best_diff = 0xffffffff; - unsigned int src = clock_get_pll3(); - - /* All calculations are in KHz to avoid overflows */ - clk /= 1000; - src /= 1000; - - /* Pick the closest lower clock */ - for (k = 1; k <= 4; k++) { - for (m = 1; m <= 16; m++) { - for (n = 1; n <= 16; n++) { - value = src * n * k / m; - if (value > clk) - continue; - - diff = clk - value; - if (diff < best_diff) { - best_diff = diff; - best_k = k; - best_m = m; - best_n = n; - } - if (diff == 0) - goto done; - } - } - } - -done: - writel(CCM_MIPI_PLL_CTRL_EN | CCM_MIPI_PLL_CTRL_LDO_EN | - CCM_MIPI_PLL_CTRL_N(best_n) | CCM_MIPI_PLL_CTRL_K(best_k) | - CCM_MIPI_PLL_CTRL_M(best_m), &ccm->mipi_pll_cfg); -} -#endif - -#ifdef CONFIG_MACH_SUN8I_A33 -void clock_set_pll11(unsigned int clk, bool sigma_delta_enable) -{ - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - - if (sigma_delta_enable) - writel(CCM_PLL11_PATTERN, &ccm->pll5_pattern_cfg); - - writel(CCM_PLL11_CTRL_EN | CCM_PLL11_CTRL_UPD | - (sigma_delta_enable ? CCM_PLL11_CTRL_SIGMA_DELTA_EN : 0) | - CCM_PLL11_CTRL_N(clk / 24000000), &ccm->pll11_cfg); - - while (readl(&ccm->pll11_cfg) & CCM_PLL11_CTRL_UPD) - ; -} -#endif - -unsigned int clock_get_pll3(void) -{ - struct sunxi_ccm_reg *const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - uint32_t rval = readl(&ccm->pll3_cfg); - int n = ((rval & CCM_PLL3_CTRL_N_MASK) >> CCM_PLL3_CTRL_N_SHIFT) + 1; - int m = ((rval & CCM_PLL3_CTRL_M_MASK) >> CCM_PLL3_CTRL_M_SHIFT) + 1; - - /* Multiply by 1000 after dividing by m to avoid integer overflows */ - return (24000 * n / m) * 1000; -} - -unsigned int clock_get_pll6(void) -{ - struct sunxi_ccm_reg *const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - uint32_t rval = readl(&ccm->pll6_cfg); - int n = ((rval & CCM_PLL6_CTRL_N_MASK) >> CCM_PLL6_CTRL_N_SHIFT) + 1; - int k = ((rval & CCM_PLL6_CTRL_K_MASK) >> CCM_PLL6_CTRL_K_SHIFT) + 1; - return 24000000 * n * k / 2; -} - -unsigned int clock_get_mipi_pll(void) -{ - struct sunxi_ccm_reg *const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - uint32_t rval = readl(&ccm->mipi_pll_cfg); - unsigned int n = ((rval & CCM_MIPI_PLL_CTRL_N_MASK) >> CCM_MIPI_PLL_CTRL_N_SHIFT) + 1; - unsigned int k = ((rval & CCM_MIPI_PLL_CTRL_K_MASK) >> CCM_MIPI_PLL_CTRL_K_SHIFT) + 1; - unsigned int m = ((rval & CCM_MIPI_PLL_CTRL_M_MASK) >> CCM_MIPI_PLL_CTRL_M_SHIFT) + 1; - unsigned int src = clock_get_pll3(); - - /* Multiply by 1000 after dividing by m to avoid integer overflows */ - return ((src / 1000) * n * k / m) * 1000; -} - -void clock_set_de_mod_clock(u32 *clk_cfg, unsigned int hz) -{ - int pll = clock_get_pll6() * 2; - int div = 1; - - while ((pll / div) > hz) - div++; - - writel(CCM_DE_CTRL_GATE | CCM_DE_CTRL_PLL6_2X | CCM_DE_CTRL_M(div), - clk_cfg); -} diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun8i_a83t.c b/arch/arm/cpu/armv7/sunxi/clock_sun8i_a83t.c deleted file mode 100644 index 3e8728fff6..0000000000 --- a/arch/arm/cpu/armv7/sunxi/clock_sun8i_a83t.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * A83 specific clock code - * - * (C) Copyright 2007-2012 - * Allwinner Technology Co., Ltd. - * Tom Cubie - * - * (C) Copyright 2015 Vishnu Patekar - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include - -#ifdef CONFIG_SPL_BUILD -void clock_init_safe(void) -{ - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - - clock_set_pll1(408000000); - /* enable pll_hsic, default is 480M */ - writel(PLL8_CFG_DEFAULT, &ccm->pll8_cfg); - writel(readl(&ccm->pll8_cfg) | (0x1 << 31), &ccm->pll8_cfg); - while (!(readl(&ccm->pll_stable_status) & (1 << 8))) {} - - /* switch to default 24MHz before changing to hsic */ - writel(0x0, &ccm->cci400_cfg); - sdelay(50); - writel(CCM_CCI400_CLK_SEL_HSIC, &ccm->cci400_cfg); - sdelay(100); - - /* switch before changing pll6 */ - clrsetbits_le32(&ccm->ahb1_apb1_div, AHB1_CLK_SRC_MASK, - AHB1_CLK_SRC_OSC24M); - writel(PLL6_CFG_DEFAULT, &ccm->pll6_cfg); - while (!(readl(&ccm->pll_stable_status) & (1 << 6))) {} - - writel(AHB1_ABP1_DIV_DEFAULT, &ccm->ahb1_apb1_div); - writel(CCM_MBUS_RESET_RESET, &ccm->mbus_reset); - writel(MBUS_CLK_DEFAULT, &ccm->mbus_clk_cfg); - - /* timestamp */ - writel(1, 0x01720000); -} -#endif - -void clock_init_uart(void) -{ - struct sunxi_ccm_reg *const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - - /* uart clock source is apb2 */ - writel(APB2_CLK_SRC_OSC24M| - APB2_CLK_RATE_N_1| - APB2_CLK_RATE_M(1), - &ccm->apb2_div); - - /* open the clock for uart */ - setbits_le32(&ccm->apb2_gate, - CLK_GATE_OPEN << (APB2_GATE_UART_SHIFT + - CONFIG_CONS_INDEX - 1)); - - /* deassert uart reset */ - setbits_le32(&ccm->apb2_reset_cfg, - 1 << (APB2_RESET_UART_SHIFT + - CONFIG_CONS_INDEX - 1)); -} - -#ifdef CONFIG_SPL_BUILD -void clock_set_pll1(unsigned int clk) -{ - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - const int p = 0; - - /* Switch to 24MHz clock while changing PLL1 */ - writel(AXI_DIV_2 << AXI0_DIV_SHIFT | - AXI_DIV_2 << AXI1_DIV_SHIFT | - CPU_CLK_SRC_OSC24M << C0_CPUX_CLK_SRC_SHIFT | - CPU_CLK_SRC_OSC24M << C1_CPUX_CLK_SRC_SHIFT, - &ccm->cpu_axi_cfg); - - /* clk = 24*n/p, p is ignored if clock is >288MHz */ - writel(CCM_PLL1_CTRL_EN | CCM_PLL1_CTRL_P(p) | CMM_PLL1_CLOCK_TIME_2 | - CCM_PLL1_CTRL_N(clk / 24000000), - &ccm->pll1_c0_cfg); - while (!(readl(&ccm->pll_stable_status) & 0x01)) {} - - writel(CCM_PLL1_CTRL_EN | CCM_PLL1_CTRL_P(p) | CMM_PLL1_CLOCK_TIME_2 | - CCM_PLL1_CTRL_N(clk / (24000000)), - &ccm->pll1_c1_cfg); - while (!(readl(&ccm->pll_stable_status) & 0x02)) {} - - /* Switch CPU to PLL1 */ - writel(AXI_DIV_2 << AXI0_DIV_SHIFT | - AXI_DIV_2 << AXI1_DIV_SHIFT | - CPU_CLK_SRC_PLL1 << C0_CPUX_CLK_SRC_SHIFT | - CPU_CLK_SRC_PLL1 << C1_CPUX_CLK_SRC_SHIFT, - &ccm->cpu_axi_cfg); -} -#endif - -void clock_set_pll5(unsigned int clk) -{ - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - unsigned int div1 = 0, div2 = 0; - - /* A83T PLL5 DDR rate = 24000000 * (n+1)/(div1+1)/(div2+1) */ - writel(CCM_PLL5_CTRL_EN | CCM_PLL5_CTRL_UPD | - CCM_PLL5_CTRL_N(clk / (24000000)) | - div2 << CCM_PLL5_DIV2_SHIFT | - div1 << CCM_PLL5_DIV1_SHIFT, &ccm->pll5_cfg); - - udelay(5500); -} - - -unsigned int clock_get_pll6(void) -{ - struct sunxi_ccm_reg *const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - - uint32_t rval = readl(&ccm->pll6_cfg); - int n = ((rval & CCM_PLL6_CTRL_N_MASK) >> CCM_PLL6_CTRL_N_SHIFT); - int div1 = ((rval & CCM_PLL6_CTRL_DIV1_MASK) >> - CCM_PLL6_CTRL_DIV1_SHIFT) + 1; - int div2 = ((rval & CCM_PLL6_CTRL_DIV2_MASK) >> - CCM_PLL6_CTRL_DIV2_SHIFT) + 1; - return 24000000 * n / div1 / div2; -} diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun9i.c b/arch/arm/cpu/armv7/sunxi/clock_sun9i.c deleted file mode 100644 index 180634c838..0000000000 --- a/arch/arm/cpu/armv7/sunxi/clock_sun9i.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * sun9i specific clock code - * - * (C) Copyright 2015 Hans de Goede - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include - -void clock_init_uart(void) -{ - struct sunxi_ccm_reg *const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - - /* open the clock for uart */ - setbits_le32(&ccm->apb1_gate, - CLK_GATE_OPEN << (APB1_GATE_UART_SHIFT + - CONFIG_CONS_INDEX - 1)); - /* deassert uart reset */ - setbits_le32(&ccm->apb1_reset_cfg, - 1 << (APB1_RESET_UART_SHIFT + - CONFIG_CONS_INDEX - 1)); - - /* Dup with clock_init_safe(), drop once sun9i SPL support lands */ - writel(PLL4_CFG_DEFAULT, &ccm->pll4_periph0_cfg); -} - -int clock_twi_onoff(int port, int state) -{ - struct sunxi_ccm_reg *const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - - if (port > 4) - return -1; - - /* set the apb reset and clock gate for twi */ - if (state) { - setbits_le32(&ccm->apb1_gate, - CLK_GATE_OPEN << (APB1_GATE_TWI_SHIFT + port)); - setbits_le32(&ccm->apb1_reset_cfg, - 1 << (APB1_RESET_TWI_SHIFT + port)); - } else { - clrbits_le32(&ccm->apb1_reset_cfg, - 1 << (APB1_RESET_TWI_SHIFT + port)); - clrbits_le32(&ccm->apb1_gate, - CLK_GATE_OPEN << (APB1_GATE_TWI_SHIFT + port)); - } - - return 0; -} - -unsigned int clock_get_pll4_periph0(void) -{ - struct sunxi_ccm_reg *const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - uint32_t rval = readl(&ccm->pll4_periph0_cfg); - int n = ((rval & CCM_PLL4_CTRL_N_MASK) >> CCM_PLL4_CTRL_N_SHIFT); - int p = ((rval & CCM_PLL4_CTRL_P_MASK) >> CCM_PLL4_CTRL_P_SHIFT); - int m = ((rval & CCM_PLL4_CTRL_M_MASK) >> CCM_PLL4_CTRL_M_SHIFT) + 1; - const int k = 1; - - return ((24000000 * n * k) >> p) / m; -} diff --git a/arch/arm/cpu/armv7/sunxi/cpu_info.c b/arch/arm/cpu/armv7/sunxi/cpu_info.c deleted file mode 100644 index c0eabdf91d..0000000000 --- a/arch/arm/cpu/armv7/sunxi/cpu_info.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * (C) Copyright 2007-2011 - * Allwinner Technology Co., Ltd. - * Tom Cubie - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_MACH_SUN6I -int sunxi_get_ss_bonding_id(void) -{ - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - static int bonding_id = -1; - - if (bonding_id != -1) - return bonding_id; - - /* Enable Security System */ - setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_SS); - setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_SS); - - bonding_id = readl(SUNXI_SS_BASE); - bonding_id = (bonding_id >> 16) & 0x7; - - /* Disable Security System again */ - clrbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_SS); - clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_SS); - - return bonding_id; -} -#endif - -#ifdef CONFIG_MACH_SUN8I -uint sunxi_get_sram_id(void) -{ - uint id; - - /* Unlock sram info reg, read it, relock */ - setbits_le32(SUNXI_SRAMC_BASE + 0x24, (1 << 15)); - id = readl(SUNXI_SRAMC_BASE + 0x24) >> 16; - clrbits_le32(SUNXI_SRAMC_BASE + 0x24, (1 << 15)); - - return id; -} -#endif - -#ifdef CONFIG_DISPLAY_CPUINFO -int print_cpuinfo(void) -{ -#ifdef CONFIG_MACH_SUN4I - puts("CPU: Allwinner A10 (SUN4I)\n"); -#elif defined CONFIG_MACH_SUN5I - u32 val = readl(SUNXI_SID_BASE + 0x08); - switch ((val >> 12) & 0xf) { - case 0: puts("CPU: Allwinner A12 (SUN5I)\n"); break; - case 3: puts("CPU: Allwinner A13 (SUN5I)\n"); break; - case 7: puts("CPU: Allwinner A10s (SUN5I)\n"); break; - default: puts("CPU: Allwinner A1X (SUN5I)\n"); - } -#elif defined CONFIG_MACH_SUN6I - switch (sunxi_get_ss_bonding_id()) { - case SUNXI_SS_BOND_ID_A31: - puts("CPU: Allwinner A31 (SUN6I)\n"); - break; - case SUNXI_SS_BOND_ID_A31S: - puts("CPU: Allwinner A31s (SUN6I)\n"); - break; - default: - printf("CPU: Allwinner A31? (SUN6I, id: %d)\n", - sunxi_get_ss_bonding_id()); - } -#elif defined CONFIG_MACH_SUN7I - puts("CPU: Allwinner A20 (SUN7I)\n"); -#elif defined CONFIG_MACH_SUN8I_A23 - printf("CPU: Allwinner A23 (SUN8I %04x)\n", sunxi_get_sram_id()); -#elif defined CONFIG_MACH_SUN8I_A33 - printf("CPU: Allwinner A33 (SUN8I %04x)\n", sunxi_get_sram_id()); -#elif defined CONFIG_MACH_SUN8I_A83T - printf("CPU: Allwinner A83T (SUN8I %04x)\n", sunxi_get_sram_id()); -#elif defined CONFIG_MACH_SUN8I_H3 - printf("CPU: Allwinner H3 (SUN8I %04x)\n", sunxi_get_sram_id()); -#elif defined CONFIG_MACH_SUN9I - puts("CPU: Allwinner A80 (SUN9I)\n"); -#else -#warning Please update cpu_info.c with correct CPU information - puts("CPU: SUNXI Family\n"); -#endif - return 0; -} -#endif - -int sunxi_get_sid(unsigned int *sid) -{ -#ifdef CONFIG_AXP221_POWER - return axp_get_sid(sid); -#elif defined SUNXI_SID_BASE - int i; - - for (i = 0; i< 4; i++) - sid[i] = readl(SUNXI_SID_BASE + 4 * i); - - return 0; -#else - return -ENODEV; -#endif -} diff --git a/arch/arm/cpu/armv7/sunxi/dram_helpers.c b/arch/arm/cpu/armv7/sunxi/dram_helpers.c deleted file mode 100644 index 9a94e1b679..0000000000 --- a/arch/arm/cpu/armv7/sunxi/dram_helpers.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * DRAM init helper functions - * - * (C) Copyright 2015 Hans de Goede - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include - -/* - * Wait up to 1s for value to be set in given part of reg. - */ -void mctl_await_completion(u32 *reg, u32 mask, u32 val) -{ - unsigned long tmo = timer_get_us() + 1000000; - - while ((readl(reg) & mask) != val) { - if (timer_get_us() > tmo) - panic("Timeout initialising DRAM\n"); - } -} - -/* - * Test if memory at offset offset matches memory at begin of DRAM - */ -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); - /* Check if the same value is actually observed when reading back */ - return readl(CONFIG_SYS_SDRAM_BASE) == - readl(CONFIG_SYS_SDRAM_BASE + offset); -} diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun4i.c b/arch/arm/cpu/armv7/sunxi/dram_sun4i.c deleted file mode 100644 index f7b4915037..0000000000 --- a/arch/arm/cpu/armv7/sunxi/dram_sun4i.c +++ /dev/null @@ -1,737 +0,0 @@ -/* - * sunxi DRAM controller initialization - * (C) Copyright 2012 Henrik Nordstrom - * (C) Copyright 2013 Luke Kenneth Casson Leighton - * - * Based on sun4i Linux kernel sources mach-sunxi/pm/standby/dram*.c - * and earlier U-Boot Allwiner A10 SPL work - * - * (C) Copyright 2007-2012 - * Allwinner Technology Co., Ltd. - * Berg Xing - * Tom Cubie - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Unfortunately the only documentation we have on the sun7i DRAM - * controller is Allwinner boot0 + boot1 code, and that code uses - * magic numbers & shifts with no explanations. Hence this code is - * rather undocumented and full of magic. - */ - -#include -#include -#include -#include -#include -#include - -#define CPU_CFG_CHIP_VER(n) ((n) << 6) -#define CPU_CFG_CHIP_VER_MASK CPU_CFG_CHIP_VER(0x3) -#define CPU_CFG_CHIP_REV_A 0x0 -#define CPU_CFG_CHIP_REV_C1 0x1 -#define CPU_CFG_CHIP_REV_C2 0x2 -#define CPU_CFG_CHIP_REV_B 0x3 - -/* - * Wait up to 1s for mask to be clear in given reg. - */ -static inline void await_bits_clear(u32 *reg, u32 mask) -{ - mctl_await_completion(reg, mask, 0); -} - -/* - * Wait up to 1s for mask to be set in given reg. - */ -static inline void await_bits_set(u32 *reg, u32 mask) -{ - mctl_await_completion(reg, mask, mask); -} - -/* - * This performs the external DRAM reset by driving the RESET pin low and - * then high again. According to the DDR3 spec, the RESET pin needs to be - * kept low for at least 200 us. - */ -static void mctl_ddr3_reset(void) -{ - struct sunxi_dram_reg *dram = - (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; - -#ifdef CONFIG_MACH_SUN4I - struct sunxi_timer_reg *timer = - (struct sunxi_timer_reg *)SUNXI_TIMER_BASE; - u32 reg_val; - - writel(0, &timer->cpu_cfg); - reg_val = readl(&timer->cpu_cfg); - - if ((reg_val & CPU_CFG_CHIP_VER_MASK) != - CPU_CFG_CHIP_VER(CPU_CFG_CHIP_REV_A)) { - setbits_le32(&dram->mcr, DRAM_MCR_RESET); - udelay(200); - clrbits_le32(&dram->mcr, DRAM_MCR_RESET); - } else -#endif - { - clrbits_le32(&dram->mcr, DRAM_MCR_RESET); - udelay(200); - setbits_le32(&dram->mcr, DRAM_MCR_RESET); - } - /* After the RESET pin is de-asserted, the DDR3 spec requires to wait - * for additional 500 us before driving the CKE pin (Clock Enable) - * high. The duration of this delay can be configured in the SDR_IDCR - * (Initialization Delay Configuration Register) and applied - * automatically by the DRAM controller during the DDR3 initialization - * step. But SDR_IDCR has limited range on sun4i/sun5i hardware and - * can't provide sufficient delay at DRAM clock frequencies higher than - * 524 MHz (while Allwinner A13 supports DRAM clock frequency up to - * 533 MHz according to the datasheet). Additionally, there is no - * official documentation for the SDR_IDCR register anywhere, and - * there is always a chance that we are interpreting it wrong. - * Better be safe than sorry, so add an explicit delay here. */ - udelay(500); -} - -static void mctl_set_drive(void) -{ - struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; - -#ifdef CONFIG_MACH_SUN7I - clrsetbits_le32(&dram->mcr, DRAM_MCR_MODE_NORM(0x3) | (0x3 << 28), -#else - clrsetbits_le32(&dram->mcr, DRAM_MCR_MODE_NORM(0x3), -#endif - DRAM_MCR_MODE_EN(0x3) | - 0xffc); -} - -static void mctl_itm_disable(void) -{ - struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; - - clrsetbits_le32(&dram->ccr, DRAM_CCR_INIT, DRAM_CCR_ITM_OFF); -} - -static void mctl_itm_enable(void) -{ - struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; - - clrbits_le32(&dram->ccr, DRAM_CCR_ITM_OFF); -} - -static void mctl_itm_reset(void) -{ - mctl_itm_disable(); - udelay(1); /* ITM reset needs a bit of delay */ - mctl_itm_enable(); - udelay(1); -} - -static void mctl_enable_dll0(u32 phase) -{ - struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; - - clrsetbits_le32(&dram->dllcr[0], 0x3f << 6, - ((phase >> 16) & 0x3f) << 6); - clrsetbits_le32(&dram->dllcr[0], DRAM_DLLCR_NRESET, DRAM_DLLCR_DISABLE); - udelay(2); - - clrbits_le32(&dram->dllcr[0], DRAM_DLLCR_NRESET | DRAM_DLLCR_DISABLE); - udelay(22); - - clrsetbits_le32(&dram->dllcr[0], DRAM_DLLCR_DISABLE, DRAM_DLLCR_NRESET); - udelay(22); -} - -/* Get the number of DDR byte lanes */ -static u32 mctl_get_number_of_lanes(void) -{ - struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; - if ((readl(&dram->dcr) & DRAM_DCR_BUS_WIDTH_MASK) == - DRAM_DCR_BUS_WIDTH(DRAM_DCR_BUS_WIDTH_32BIT)) - return 4; - else - return 2; -} - -/* - * Note: This differs from pm/standby in that it checks the bus width - */ -static void mctl_enable_dllx(u32 phase) -{ - struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; - u32 i, number_of_lanes; - - number_of_lanes = mctl_get_number_of_lanes(); - - for (i = 1; i <= number_of_lanes; i++) { - clrsetbits_le32(&dram->dllcr[i], 0xf << 14, - (phase & 0xf) << 14); - clrsetbits_le32(&dram->dllcr[i], DRAM_DLLCR_NRESET, - DRAM_DLLCR_DISABLE); - phase >>= 4; - } - udelay(2); - - for (i = 1; i <= number_of_lanes; i++) - clrbits_le32(&dram->dllcr[i], DRAM_DLLCR_NRESET | - DRAM_DLLCR_DISABLE); - udelay(22); - - for (i = 1; i <= number_of_lanes; i++) - clrsetbits_le32(&dram->dllcr[i], DRAM_DLLCR_DISABLE, - DRAM_DLLCR_NRESET); - udelay(22); -} - -static u32 hpcr_value[32] = { -#ifdef CONFIG_MACH_SUN5I - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0x1031, 0x1031, 0x0735, 0x1035, - 0x1035, 0x0731, 0x1031, 0, - 0x0301, 0x0301, 0x0301, 0x0301, - 0x0301, 0x0301, 0x0301, 0 -#endif -#ifdef CONFIG_MACH_SUN4I - 0x0301, 0x0301, 0x0301, 0x0301, - 0x0301, 0x0301, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0x1031, 0x1031, 0x0735, 0x5031, - 0x1035, 0x0731, 0x1031, 0x0735, - 0x1035, 0x1031, 0x0731, 0x1035, - 0x1031, 0x0301, 0x0301, 0x0731 -#endif -#ifdef CONFIG_MACH_SUN7I - 0x0301, 0x0301, 0x0301, 0x0301, - 0x0301, 0x0301, 0x0301, 0x0301, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0x1031, 0x1031, 0x0735, 0x1035, - 0x1035, 0x0731, 0x1031, 0x0735, - 0x1035, 0x1031, 0x0731, 0x1035, - 0x0001, 0x1031, 0, 0x1031 - /* last row differs from boot0 source table - * 0x1031, 0x0301, 0x0301, 0x0731 - * but boot0 code skips #28 and #30, and sets #29 and #31 to the - * value from #28 entry (0x1031) - */ -#endif -}; - -static void mctl_configure_hostport(void) -{ - struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; - u32 i; - - for (i = 0; i < 32; i++) - writel(hpcr_value[i], &dram->hpcr[i]); -} - -static void mctl_setup_dram_clock(u32 clk, u32 mbus_clk) -{ - u32 reg_val; - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - u32 pll5p_clk, pll6x_clk; - u32 pll5p_div, pll6x_div; - u32 pll5p_rate, pll6x_rate; - - /* setup DRAM PLL */ - reg_val = readl(&ccm->pll5_cfg); - reg_val &= ~CCM_PLL5_CTRL_M_MASK; /* set M to 0 (x1) */ - reg_val &= ~CCM_PLL5_CTRL_K_MASK; /* set K to 0 (x1) */ - reg_val &= ~CCM_PLL5_CTRL_N_MASK; /* set N to 0 (x0) */ - reg_val &= ~CCM_PLL5_CTRL_P_MASK; /* set P to 0 (x1) */ -#ifdef CONFIG_OLD_SUNXI_KERNEL_COMPAT - /* Old kernels are hardcoded to P=1 (divide by 2) */ - reg_val |= CCM_PLL5_CTRL_P(1); -#endif - if (clk >= 540 && clk < 552) { - /* dram = 540MHz */ - reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2)); - reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(3)); - reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(15)); - } else if (clk >= 512 && clk < 528) { - /* dram = 512MHz */ - reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(3)); - reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(4)); - reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(16)); - } else if (clk >= 496 && clk < 504) { - /* dram = 496MHz */ - reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(3)); - reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(2)); - reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(31)); - } else if (clk >= 468 && clk < 480) { - /* dram = 468MHz */ - reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2)); - reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(3)); - reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(13)); - } else if (clk >= 396 && clk < 408) { - /* dram = 396MHz */ - reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2)); - reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(3)); - reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(11)); - } else { - /* any other frequency that is a multiple of 24 */ - reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2)); - reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(2)); - reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(clk / 24)); - } - reg_val &= ~CCM_PLL5_CTRL_VCO_GAIN; /* PLL VCO Gain off */ - reg_val |= CCM_PLL5_CTRL_EN; /* PLL On */ - writel(reg_val, &ccm->pll5_cfg); - udelay(5500); - - setbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_DDR_CLK); - -#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I) - /* reset GPS */ - clrbits_le32(&ccm->gps_clk_cfg, CCM_GPS_CTRL_RESET | CCM_GPS_CTRL_GATE); - setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_GPS); - udelay(1); - clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_GPS); -#endif - - /* setup MBUS clock */ - if (!mbus_clk) - mbus_clk = 300; - - /* PLL5P and PLL6 are the potential clock sources for MBUS */ - pll6x_clk = clock_get_pll6() / 1000000; -#ifdef CONFIG_MACH_SUN7I - pll6x_clk *= 2; /* sun7i uses PLL6*2, sun5i uses just PLL6 */ -#endif - pll5p_clk = clock_get_pll5p() / 1000000; - pll6x_div = DIV_ROUND_UP(pll6x_clk, mbus_clk); - pll5p_div = DIV_ROUND_UP(pll5p_clk, mbus_clk); - pll6x_rate = pll6x_clk / pll6x_div; - pll5p_rate = pll5p_clk / pll5p_div; - - if (pll6x_div <= 16 && pll6x_rate > pll5p_rate) { - /* use PLL6 as the MBUS clock source */ - reg_val = CCM_MBUS_CTRL_GATE | - CCM_MBUS_CTRL_CLK_SRC(CCM_MBUS_CTRL_CLK_SRC_PLL6) | - CCM_MBUS_CTRL_N(CCM_MBUS_CTRL_N_X(1)) | - CCM_MBUS_CTRL_M(CCM_MBUS_CTRL_M_X(pll6x_div)); - } else if (pll5p_div <= 16) { - /* use PLL5P as the MBUS clock source */ - reg_val = CCM_MBUS_CTRL_GATE | - CCM_MBUS_CTRL_CLK_SRC(CCM_MBUS_CTRL_CLK_SRC_PLL5) | - CCM_MBUS_CTRL_N(CCM_MBUS_CTRL_N_X(1)) | - CCM_MBUS_CTRL_M(CCM_MBUS_CTRL_M_X(pll5p_div)); - } else { - panic("Bad mbus_clk\n"); - } - writel(reg_val, &ccm->mbus_clk_cfg); - - /* - * open DRAMC AHB & DLL register clock - * close it first - */ -#if defined(CONFIG_MACH_SUN5I) || defined(CONFIG_MACH_SUN7I) - clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM | CCM_AHB_GATE_DLL); -#else - clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM); -#endif - udelay(22); - - /* then open it */ -#if defined(CONFIG_MACH_SUN5I) || defined(CONFIG_MACH_SUN7I) - setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM | CCM_AHB_GATE_DLL); -#else - setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM); -#endif - udelay(22); -} - -/* - * The data from rslrX and rdgrX registers (X=rank) is stored - * in a single 32-bit value using the following format: - * bits [31:26] - DQS gating system latency for byte lane 3 - * bits [25:24] - DQS gating phase select for byte lane 3 - * bits [23:18] - DQS gating system latency for byte lane 2 - * bits [17:16] - DQS gating phase select for byte lane 2 - * bits [15:10] - DQS gating system latency for byte lane 1 - * bits [ 9:8 ] - DQS gating phase select for byte lane 1 - * bits [ 7:2 ] - DQS gating system latency for byte lane 0 - * bits [ 1:0 ] - DQS gating phase select for byte lane 0 - */ -static void mctl_set_dqs_gating_delay(int rank, u32 dqs_gating_delay) -{ - struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; - u32 lane, number_of_lanes = mctl_get_number_of_lanes(); - /* rank0 gating system latency (3 bits per lane: cycles) */ - u32 slr = readl(rank == 0 ? &dram->rslr0 : &dram->rslr1); - /* rank0 gating phase select (2 bits per lane: 90, 180, 270, 360) */ - u32 dgr = readl(rank == 0 ? &dram->rdgr0 : &dram->rdgr1); - for (lane = 0; lane < number_of_lanes; lane++) { - u32 tmp = dqs_gating_delay >> (lane * 8); - slr &= ~(7 << (lane * 3)); - slr |= ((tmp >> 2) & 7) << (lane * 3); - dgr &= ~(3 << (lane * 2)); - dgr |= (tmp & 3) << (lane * 2); - } - writel(slr, rank == 0 ? &dram->rslr0 : &dram->rslr1); - writel(dgr, rank == 0 ? &dram->rdgr0 : &dram->rdgr1); -} - -static int dramc_scan_readpipe(void) -{ - struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; - u32 reg_val; - - /* data training trigger */ - clrbits_le32(&dram->csr, DRAM_CSR_FAILED); - setbits_le32(&dram->ccr, DRAM_CCR_DATA_TRAINING); - - /* check whether data training process has completed */ - await_bits_clear(&dram->ccr, DRAM_CCR_DATA_TRAINING); - - /* check data training result */ - reg_val = readl(&dram->csr); - if (reg_val & DRAM_CSR_FAILED) - return -1; - - return 0; -} - -static void dramc_clock_output_en(u32 on) -{ -#if defined(CONFIG_MACH_SUN5I) || defined(CONFIG_MACH_SUN7I) - struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; - - if (on) - setbits_le32(&dram->mcr, DRAM_MCR_DCLK_OUT); - else - clrbits_le32(&dram->mcr, DRAM_MCR_DCLK_OUT); -#endif -#ifdef CONFIG_MACH_SUN4I - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - if (on) - setbits_le32(&ccm->dram_clk_gate, CCM_DRAM_CTRL_DCLK_OUT); - else - clrbits_le32(&ccm->dram_clk_gate, CCM_DRAM_CTRL_DCLK_OUT); -#endif -} - -/* tRFC in nanoseconds for different densities (from the DDR3 spec) */ -static const u16 tRFC_DDR3_table[6] = { - /* 256Mb 512Mb 1Gb 2Gb 4Gb 8Gb */ - 90, 90, 110, 160, 300, 350 -}; - -static void dramc_set_autorefresh_cycle(u32 clk, u32 density) -{ - struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; - u32 tRFC, tREFI; - - tRFC = (tRFC_DDR3_table[density] * clk + 999) / 1000; - tREFI = (7987 * clk) >> 10; /* <= 7.8us */ - - writel(DRAM_DRR_TREFI(tREFI) | DRAM_DRR_TRFC(tRFC), &dram->drr); -} - -/* Calculate the value for A11, A10, A9 bits in MR0 (write recovery) */ -static u32 ddr3_write_recovery(u32 clk) -{ - u32 twr_ns = 15; /* DDR3 spec says that it is 15ns for all speed bins */ - u32 twr_ck = (twr_ns * clk + 999) / 1000; - if (twr_ck < 5) - return 1; - else if (twr_ck <= 8) - return twr_ck - 4; - else if (twr_ck <= 10) - return 5; - else - return 6; -} - -/* - * If the dram->ppwrsctl (SDR_DPCR) register has the lowest bit set to 1, this - * means that DRAM is currently in self-refresh mode and retaining the old - * data. Since we have no idea what to do in this situation yet, just set this - * register to 0 and initialize DRAM in the same way as on any normal reboot - * (discarding whatever was stored there). - * - * Note: on sun7i hardware, the highest 16 bits need to be set to 0x1651 magic - * value for this write operation to have any effect. On sun5i hadware this - * magic value is not necessary. And on sun4i hardware the writes to this - * register seem to have no effect at all. - */ -static void mctl_disable_power_save(void) -{ - struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; - writel(0x16510000, &dram->ppwrsctl); -} - -/* - * After the DRAM is powered up or reset, the DDR3 spec requires to wait at - * least 500 us before driving the CKE pin (Clock Enable) high. The dram->idct - * (SDR_IDCR) register appears to configure this delay, which gets applied - * right at the time when the DRAM initialization is activated in the - * 'mctl_ddr3_initialize' function. - */ -static void mctl_set_cke_delay(void) -{ - struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; - - /* The CKE delay is represented in DRAM clock cycles, multiplied by N - * (where N=2 for sun4i/sun5i and N=3 for sun7i). Here it is set to - * the maximum possible value 0x1ffff, just like in the Allwinner's - * boot0 bootloader. The resulting delay value is somewhere between - * ~0.4 ms (sun5i with 648 MHz DRAM clock speed) and ~1.1 ms (sun7i - * with 360 MHz DRAM clock speed). */ - setbits_le32(&dram->idcr, 0x1ffff); -} - -/* - * This triggers the DRAM initialization. It performs sending the mode registers - * to the DRAM among other things. Very likely the ZQCL command is also getting - * executed (to do the initial impedance calibration on the DRAM side of the - * wire). The memory controller and the PHY must be already configured before - * calling this function. - */ -static void mctl_ddr3_initialize(void) -{ - struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; - setbits_le32(&dram->ccr, DRAM_CCR_INIT); - await_bits_clear(&dram->ccr, DRAM_CCR_INIT); -} - -/* - * Perform impedance calibration on the DRAM controller side of the wire. - */ -static void mctl_set_impedance(u32 zq, bool odt_en) -{ - struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; - u32 reg_val; - u32 zprog = zq & 0xFF, zdata = (zq >> 8) & 0xFFFFF; - -#ifndef CONFIG_MACH_SUN7I - /* Appears that some kind of automatically initiated default - * ZQ calibration is already in progress at this point on sun4i/sun5i - * hardware, but not on sun7i. So it is reasonable to wait for its - * completion before doing anything else. */ - await_bits_set(&dram->zqsr, DRAM_ZQSR_ZDONE); -#endif - - /* ZQ calibration is not really useful unless ODT is enabled */ - if (!odt_en) - return; - -#ifdef CONFIG_MACH_SUN7I - /* Enabling ODT in SDR_IOCR on sun7i hardware results in a deadlock - * unless bit 24 is set in SDR_ZQCR1. Not much is known about the - * SDR_ZQCR1 register, but there are hints indicating that it might - * be related to periodic impedance re-calibration. This particular - * magic value is borrowed from the Allwinner boot0 bootloader, and - * using it helps to avoid troubles */ - writel((1 << 24) | (1 << 1), &dram->zqcr1); -#endif - - /* Needed at least for sun5i, because it does not self clear there */ - clrbits_le32(&dram->zqcr0, DRAM_ZQCR0_ZCAL); - - if (zdata) { - /* Set the user supplied impedance data */ - reg_val = DRAM_ZQCR0_ZDEN | zdata; - writel(reg_val, &dram->zqcr0); - /* no need to wait, this takes effect immediately */ - } else { - /* Do the calibration using the external resistor */ - reg_val = DRAM_ZQCR0_ZCAL | DRAM_ZQCR0_IMP_DIV(zprog); - writel(reg_val, &dram->zqcr0); - /* Wait for the new impedance configuration to settle */ - await_bits_set(&dram->zqsr, DRAM_ZQSR_ZDONE); - } - - /* Needed at least for sun5i, because it does not self clear there */ - clrbits_le32(&dram->zqcr0, DRAM_ZQCR0_ZCAL); - - /* Set I/O configure register */ - writel(DRAM_IOCR_ODT_EN, &dram->iocr); -} - -static unsigned long dramc_init_helper(struct dram_para *para) -{ - struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; - u32 reg_val; - u32 density; - int ret_val; - - /* - * only single rank DDR3 is supported by this code even though the - * hardware can theoretically support DDR2 and up to two ranks - */ - if (para->type != DRAM_MEMORY_TYPE_DDR3 || para->rank_num != 1) - return 0; - - /* setup DRAM relative clock */ - mctl_setup_dram_clock(para->clock, para->mbus_clock); - - /* Disable any pad power save control */ - mctl_disable_power_save(); - - mctl_set_drive(); - - /* dram clock off */ - dramc_clock_output_en(0); - -#ifdef CONFIG_MACH_SUN4I - /* select dram controller 1 */ - writel(DRAM_CSEL_MAGIC, &dram->csel); -#endif - - mctl_itm_disable(); - mctl_enable_dll0(para->tpr3); - - /* configure external DRAM */ - reg_val = DRAM_DCR_TYPE_DDR3; - reg_val |= DRAM_DCR_IO_WIDTH(para->io_width >> 3); - - if (para->density == 256) - density = DRAM_DCR_CHIP_DENSITY_256M; - else if (para->density == 512) - density = DRAM_DCR_CHIP_DENSITY_512M; - else if (para->density == 1024) - density = DRAM_DCR_CHIP_DENSITY_1024M; - else if (para->density == 2048) - density = DRAM_DCR_CHIP_DENSITY_2048M; - else if (para->density == 4096) - density = DRAM_DCR_CHIP_DENSITY_4096M; - else if (para->density == 8192) - density = DRAM_DCR_CHIP_DENSITY_8192M; - else - density = DRAM_DCR_CHIP_DENSITY_256M; - - reg_val |= DRAM_DCR_CHIP_DENSITY(density); - reg_val |= DRAM_DCR_BUS_WIDTH((para->bus_width >> 3) - 1); - reg_val |= DRAM_DCR_RANK_SEL(para->rank_num - 1); - reg_val |= DRAM_DCR_CMD_RANK_ALL; - reg_val |= DRAM_DCR_MODE(DRAM_DCR_MODE_INTERLEAVE); - writel(reg_val, &dram->dcr); - - dramc_clock_output_en(1); - - mctl_set_impedance(para->zq, para->odt_en); - - mctl_set_cke_delay(); - - mctl_ddr3_reset(); - - udelay(1); - - await_bits_clear(&dram->ccr, DRAM_CCR_INIT); - - mctl_enable_dllx(para->tpr3); - - /* set refresh period */ - dramc_set_autorefresh_cycle(para->clock, density); - - /* set timing parameters */ - writel(para->tpr0, &dram->tpr0); - writel(para->tpr1, &dram->tpr1); - writel(para->tpr2, &dram->tpr2); - - reg_val = DRAM_MR_BURST_LENGTH(0x0); -#if (defined(CONFIG_MACH_SUN5I) || defined(CONFIG_MACH_SUN7I)) - reg_val |= DRAM_MR_POWER_DOWN; -#endif - reg_val |= DRAM_MR_CAS_LAT(para->cas - 4); - reg_val |= DRAM_MR_WRITE_RECOVERY(ddr3_write_recovery(para->clock)); - writel(reg_val, &dram->mr); - - writel(para->emr1, &dram->emr); - writel(para->emr2, &dram->emr2); - writel(para->emr3, &dram->emr3); - - /* disable drift compensation and set passive DQS window mode */ - clrsetbits_le32(&dram->ccr, DRAM_CCR_DQS_DRIFT_COMP, DRAM_CCR_DQS_GATE); - -#ifdef CONFIG_MACH_SUN7I - /* Command rate timing mode 2T & 1T */ - if (para->tpr4 & 0x1) - setbits_le32(&dram->ccr, DRAM_CCR_COMMAND_RATE_1T); -#endif - /* initialize external DRAM */ - mctl_ddr3_initialize(); - - /* scan read pipe value */ - mctl_itm_enable(); - - /* Hardware DQS gate training */ - ret_val = dramc_scan_readpipe(); - - if (ret_val < 0) - return 0; - - /* allow to override the DQS training results with a custom delay */ - if (para->dqs_gating_delay) - mctl_set_dqs_gating_delay(0, para->dqs_gating_delay); - - /* set the DQS gating window type */ - if (para->active_windowing) - clrbits_le32(&dram->ccr, DRAM_CCR_DQS_GATE); - else - setbits_le32(&dram->ccr, DRAM_CCR_DQS_GATE); - - mctl_itm_reset(); - - /* configure all host port */ - mctl_configure_hostport(); - - return get_ram_size((long *)PHYS_SDRAM_0, PHYS_SDRAM_0_SIZE); -} - -unsigned long dramc_init(struct dram_para *para) -{ - unsigned long dram_size, actual_density; - - /* If the dram configuration is not provided, use a default */ - if (!para) - return 0; - - /* if everything is known, then autodetection is not necessary */ - if (para->io_width && para->bus_width && para->density) - return dramc_init_helper(para); - - /* try to autodetect the DRAM bus width and density */ - para->io_width = 16; - para->bus_width = 32; -#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN5I) - /* only A0-A14 address lines on A10/A13, limiting max density to 4096 */ - para->density = 4096; -#else - /* all A0-A15 address lines on A20, which allow density 8192 */ - para->density = 8192; -#endif - - dram_size = dramc_init_helper(para); - if (!dram_size) { - /* if 32-bit bus width failed, try 16-bit bus width instead */ - para->bus_width = 16; - dram_size = dramc_init_helper(para); - if (!dram_size) { - /* if 16-bit bus width also failed, then bail out */ - return dram_size; - } - } - - /* check if we need to adjust the density */ - actual_density = (dram_size >> 17) * para->io_width / para->bus_width; - - if (actual_density != para->density) { - /* update the density and re-initialize DRAM again */ - para->density = actual_density; - dram_size = dramc_init_helper(para); - } - - return dram_size; -} diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c deleted file mode 100644 index 5dbbf6186f..0000000000 --- a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - * Sun6i platform dram controller init. - * - * (C) Copyright 2007-2012 - * Allwinner Technology Co., Ltd. - * Berg Xing - * Tom Cubie - * - * (C) Copyright 2014 Hans de Goede - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#include -#include -#include -#include -#include -#include - -#define DRAM_CLK (CONFIG_DRAM_CLK * 1000000) - -struct dram_sun6i_para { - u8 bus_width; - u8 chan; - u8 rank; - u8 rows; - u16 page_size; -}; - -static void mctl_sys_init(void) -{ - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - const int dram_clk_div = 2; - - clock_set_pll5(DRAM_CLK * dram_clk_div, false); - - clrsetbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_DIV0_MASK, - CCM_DRAMCLK_CFG_DIV0(dram_clk_div) | CCM_DRAMCLK_CFG_RST | - CCM_DRAMCLK_CFG_UPD); - mctl_await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0); - - writel(MDFS_CLK_DEFAULT, &ccm->mdfs_clk_cfg); - - /* deassert mctl reset */ - setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL); - - /* enable mctl clock */ - setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL); -} - -static void mctl_dll_init(int ch_index, struct dram_sun6i_para *para) -{ - struct sunxi_mctl_phy_reg *mctl_phy; - - if (ch_index == 0) - mctl_phy = (struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE; - else - mctl_phy = (struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY1_BASE; - - /* disable + reset dlls */ - writel(MCTL_DLLCR_DISABLE, &mctl_phy->acdllcr); - writel(MCTL_DLLCR_DISABLE, &mctl_phy->dx0dllcr); - writel(MCTL_DLLCR_DISABLE, &mctl_phy->dx1dllcr); - if (para->bus_width == 32) { - writel(MCTL_DLLCR_DISABLE, &mctl_phy->dx2dllcr); - writel(MCTL_DLLCR_DISABLE, &mctl_phy->dx3dllcr); - } - udelay(2); - - /* enable + reset dlls */ - writel(0, &mctl_phy->acdllcr); - writel(0, &mctl_phy->dx0dllcr); - writel(0, &mctl_phy->dx1dllcr); - if (para->bus_width == 32) { - writel(0, &mctl_phy->dx2dllcr); - writel(0, &mctl_phy->dx3dllcr); - } - udelay(22); - - /* enable and release reset of dlls */ - writel(MCTL_DLLCR_NRESET, &mctl_phy->acdllcr); - writel(MCTL_DLLCR_NRESET, &mctl_phy->dx0dllcr); - writel(MCTL_DLLCR_NRESET, &mctl_phy->dx1dllcr); - if (para->bus_width == 32) { - writel(MCTL_DLLCR_NRESET, &mctl_phy->dx2dllcr); - writel(MCTL_DLLCR_NRESET, &mctl_phy->dx3dllcr); - } - udelay(22); -} - -static bool mctl_rank_detect(u32 *gsr0, int rank) -{ - const u32 done = MCTL_DX_GSR0_RANK0_TRAIN_DONE << rank; - const u32 err = MCTL_DX_GSR0_RANK0_TRAIN_ERR << rank; - - mctl_await_completion(gsr0, done, done); - mctl_await_completion(gsr0 + 0x10, done, done); - - return !(readl(gsr0) & err) && !(readl(gsr0 + 0x10) & err); -} - -static void mctl_channel_init(int ch_index, struct dram_sun6i_para *para) -{ - struct sunxi_mctl_com_reg * const mctl_com = - (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; - struct sunxi_mctl_ctl_reg *mctl_ctl; - struct sunxi_mctl_phy_reg *mctl_phy; - - if (ch_index == 0) { - mctl_ctl = (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - mctl_phy = (struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE; - } else { - mctl_ctl = (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL1_BASE; - mctl_phy = (struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY1_BASE; - } - - writel(MCTL_MCMD_NOP, &mctl_ctl->mcmd); - mctl_await_completion(&mctl_ctl->mcmd, MCTL_MCMD_BUSY, 0); - - /* PHY initialization */ - writel(MCTL_PGCR, &mctl_phy->pgcr); - writel(MCTL_MR0, &mctl_phy->mr0); - writel(MCTL_MR1, &mctl_phy->mr1); - writel(MCTL_MR2, &mctl_phy->mr2); - writel(MCTL_MR3, &mctl_phy->mr3); - - writel((MCTL_TITMSRST << 18) | (MCTL_TDLLLOCK << 6) | MCTL_TDLLSRST, - &mctl_phy->ptr0); - - writel((MCTL_TDINIT1 << 19) | MCTL_TDINIT0, &mctl_phy->ptr1); - writel((MCTL_TDINIT3 << 17) | MCTL_TDINIT2, &mctl_phy->ptr2); - - writel((MCTL_TCCD << 31) | (MCTL_TRC << 25) | (MCTL_TRRD << 21) | - (MCTL_TRAS << 16) | (MCTL_TRCD << 12) | (MCTL_TRP << 8) | - (MCTL_TWTR << 5) | (MCTL_TRTP << 2) | (MCTL_TMRD << 0), - &mctl_phy->dtpr0); - - writel((MCTL_TDQSCKMAX << 27) | (MCTL_TDQSCK << 24) | - (MCTL_TRFC << 16) | (MCTL_TRTODT << 11) | - ((MCTL_TMOD - 12) << 9) | (MCTL_TFAW << 3) | (0 << 2) | - (MCTL_TAOND << 0), &mctl_phy->dtpr1); - - writel((MCTL_TDLLK << 19) | (MCTL_TCKE << 15) | (MCTL_TXPDLL << 10) | - (MCTL_TEXSR << 0), &mctl_phy->dtpr2); - - writel(1, &mctl_ctl->dfitphyupdtype0); - writel(MCTL_DCR_DDR3, &mctl_phy->dcr); - writel(MCTL_DSGCR, &mctl_phy->dsgcr); - writel(MCTL_DXCCR, &mctl_phy->dxccr); - writel(MCTL_DX_GCR | MCTL_DX_GCR_EN, &mctl_phy->dx0gcr); - writel(MCTL_DX_GCR | MCTL_DX_GCR_EN, &mctl_phy->dx1gcr); - writel(MCTL_DX_GCR | MCTL_DX_GCR_EN, &mctl_phy->dx2gcr); - writel(MCTL_DX_GCR | MCTL_DX_GCR_EN, &mctl_phy->dx3gcr); - - mctl_await_completion(&mctl_phy->pgsr, 0x03, 0x03); - - writel(CONFIG_DRAM_ZQ, &mctl_phy->zq0cr1); - - setbits_le32(&mctl_phy->pir, MCTL_PIR_CLEAR_STATUS); - writel(MCTL_PIR_STEP1, &mctl_phy->pir); - udelay(10); - mctl_await_completion(&mctl_phy->pgsr, 0x1f, 0x1f); - - /* rank detect */ - if (!mctl_rank_detect(&mctl_phy->dx0gsr0, 1)) { - para->rank = 1; - clrbits_le32(&mctl_phy->pgcr, MCTL_PGCR_RANK); - } - - /* - * channel detect, check channel 1 dx0 and dx1 have rank 0, if not - * assume nothing is connected to channel 1. - */ - if (ch_index == 1 && !mctl_rank_detect(&mctl_phy->dx0gsr0, 0)) { - para->chan = 1; - clrbits_le32(&mctl_com->ccr, MCTL_CCR_CH1_CLK_EN); - return; - } - - /* bus width detect, if dx2 and dx3 don't have rank 0, assume 16 bit */ - if (!mctl_rank_detect(&mctl_phy->dx2gsr0, 0)) { - para->bus_width = 16; - para->page_size = 2048; - setbits_le32(&mctl_phy->dx2dllcr, MCTL_DLLCR_DISABLE); - setbits_le32(&mctl_phy->dx3dllcr, MCTL_DLLCR_DISABLE); - clrbits_le32(&mctl_phy->dx2gcr, MCTL_DX_GCR_EN); - clrbits_le32(&mctl_phy->dx3gcr, MCTL_DX_GCR_EN); - } - - setbits_le32(&mctl_phy->pir, MCTL_PIR_CLEAR_STATUS); - writel(MCTL_PIR_STEP2, &mctl_phy->pir); - udelay(10); - mctl_await_completion(&mctl_phy->pgsr, 0x11, 0x11); - - if (readl(&mctl_phy->pgsr) & MCTL_PGSR_TRAIN_ERR_MASK) - panic("Training error initialising DRAM\n"); - - /* Move to configure state */ - writel(MCTL_SCTL_CONFIG, &mctl_ctl->sctl); - mctl_await_completion(&mctl_ctl->sstat, 0x07, 0x01); - - /* Set number of clks per micro-second */ - writel(DRAM_CLK / 1000000, &mctl_ctl->togcnt1u); - /* Set number of clks per 100 nano-seconds */ - writel(DRAM_CLK / 10000000, &mctl_ctl->togcnt100n); - /* Set memory timing registers */ - writel(MCTL_TREFI, &mctl_ctl->trefi); - writel(MCTL_TMRD, &mctl_ctl->tmrd); - writel(MCTL_TRFC, &mctl_ctl->trfc); - writel((MCTL_TPREA << 16) | MCTL_TRP, &mctl_ctl->trp); - writel(MCTL_TRTW, &mctl_ctl->trtw); - writel(MCTL_TAL, &mctl_ctl->tal); - writel(MCTL_TCL, &mctl_ctl->tcl); - writel(MCTL_TCWL, &mctl_ctl->tcwl); - writel(MCTL_TRAS, &mctl_ctl->tras); - writel(MCTL_TRC, &mctl_ctl->trc); - writel(MCTL_TRCD, &mctl_ctl->trcd); - writel(MCTL_TRRD, &mctl_ctl->trrd); - writel(MCTL_TRTP, &mctl_ctl->trtp); - writel(MCTL_TWR, &mctl_ctl->twr); - writel(MCTL_TWTR, &mctl_ctl->twtr); - writel(MCTL_TEXSR, &mctl_ctl->texsr); - writel(MCTL_TXP, &mctl_ctl->txp); - writel(MCTL_TXPDLL, &mctl_ctl->txpdll); - writel(MCTL_TZQCS, &mctl_ctl->tzqcs); - writel(MCTL_TZQCSI, &mctl_ctl->tzqcsi); - writel(MCTL_TDQS, &mctl_ctl->tdqs); - writel(MCTL_TCKSRE, &mctl_ctl->tcksre); - writel(MCTL_TCKSRX, &mctl_ctl->tcksrx); - writel(MCTL_TCKE, &mctl_ctl->tcke); - writel(MCTL_TMOD, &mctl_ctl->tmod); - writel(MCTL_TRSTL, &mctl_ctl->trstl); - writel(MCTL_TZQCL, &mctl_ctl->tzqcl); - writel(MCTL_TMRR, &mctl_ctl->tmrr); - writel(MCTL_TCKESR, &mctl_ctl->tckesr); - writel(MCTL_TDPD, &mctl_ctl->tdpd); - - /* Unknown magic performed by boot0 */ - setbits_le32(&mctl_ctl->dfiodtcfg, 1 << 3); - clrbits_le32(&mctl_ctl->dfiodtcfg1, 0x1f); - - /* Select 16/32-bits mode for MCTL */ - if (para->bus_width == 16) - setbits_le32(&mctl_ctl->ppcfg, 1); - - /* Set DFI timing registers */ - writel(MCTL_TCWL, &mctl_ctl->dfitphywrl); - writel(MCTL_TCL - 1, &mctl_ctl->dfitrdden); - writel(MCTL_DFITPHYRDL, &mctl_ctl->dfitphyrdl); - writel(MCTL_DFISTCFG0, &mctl_ctl->dfistcfg0); - - writel(MCTL_MCFG_DDR3, &mctl_ctl->mcfg); - - /* DFI update configuration register */ - writel(MCTL_DFIUPDCFG_UPD, &mctl_ctl->dfiupdcfg); - - /* Move to access state */ - writel(MCTL_SCTL_ACCESS, &mctl_ctl->sctl); - mctl_await_completion(&mctl_ctl->sstat, 0x07, 0x03); -} - -static void mctl_com_init(struct dram_sun6i_para *para) -{ - struct sunxi_mctl_com_reg * const mctl_com = - (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; - struct sunxi_mctl_phy_reg * const mctl_phy1 = - (struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY1_BASE; - struct sunxi_prcm_reg * const prcm = - (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE; - - writel(MCTL_CR_UNKNOWN | MCTL_CR_CHANNEL(para->chan) | MCTL_CR_DDR3 | - ((para->bus_width == 32) ? MCTL_CR_BUSW32 : MCTL_CR_BUSW16) | - MCTL_CR_PAGE_SIZE(para->page_size) | MCTL_CR_ROW(para->rows) | - MCTL_CR_BANK(1) | MCTL_CR_RANK(para->rank), &mctl_com->cr); - - /* Unknown magic performed by boot0 */ - setbits_le32(&mctl_com->dbgcr, (1 << 6)); - - if (para->chan == 1) { - /* Shutdown channel 1 */ - setbits_le32(&mctl_phy1->aciocr, MCTL_ACIOCR_DISABLE); - setbits_le32(&mctl_phy1->dxccr, MCTL_DXCCR_DISABLE); - clrbits_le32(&mctl_phy1->dsgcr, MCTL_DSGCR_ENABLE); - /* - * CH0 ?? this is what boot0 does. Leave as is until we can - * confirm this. - */ - setbits_le32(&prcm->vdd_sys_pwroff, - PRCM_VDD_SYS_DRAM_CH0_PAD_HOLD_PWROFF); - } -} - -static void mctl_port_cfg(void) -{ - struct sunxi_mctl_com_reg * const mctl_com = - (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - - /* enable DRAM AXI clock for CPU access */ - setbits_le32(&ccm->axi_gate, 1 << AXI_GATE_OFFSET_DRAM); - - /* Bunch of magic writes performed by boot0 */ - writel(0x00400302, &mctl_com->rmcr[0]); - writel(0x01000307, &mctl_com->rmcr[1]); - writel(0x00400302, &mctl_com->rmcr[2]); - writel(0x01000307, &mctl_com->rmcr[3]); - writel(0x01000307, &mctl_com->rmcr[4]); - writel(0x01000303, &mctl_com->rmcr[6]); - writel(0x01000303, &mctl_com->mmcr[0]); - writel(0x00400310, &mctl_com->mmcr[1]); - writel(0x01000307, &mctl_com->mmcr[2]); - writel(0x01000303, &mctl_com->mmcr[3]); - writel(0x01800303, &mctl_com->mmcr[4]); - writel(0x01800303, &mctl_com->mmcr[5]); - writel(0x01800303, &mctl_com->mmcr[6]); - writel(0x01800303, &mctl_com->mmcr[7]); - writel(0x01000303, &mctl_com->mmcr[8]); - writel(0x00000002, &mctl_com->mmcr[15]); - writel(0x00000310, &mctl_com->mbagcr[0]); - writel(0x00400310, &mctl_com->mbagcr[1]); - writel(0x00400310, &mctl_com->mbagcr[2]); - writel(0x00000307, &mctl_com->mbagcr[3]); - writel(0x00000317, &mctl_com->mbagcr[4]); - writel(0x00000307, &mctl_com->mbagcr[5]); -} - -unsigned long sunxi_dram_init(void) -{ - struct sunxi_mctl_com_reg * const mctl_com = - (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; - u32 offset; - int bank, bus, columns; - - /* Set initial parameters, these get modified by the autodetect code */ - struct dram_sun6i_para para = { - .bus_width = 32, - .chan = 2, - .rank = 2, - .page_size = 4096, - .rows = 16, - }; - - /* A31s only has one channel */ - if (sunxi_get_ss_bonding_id() == SUNXI_SS_BOND_ID_A31S) - para.chan = 1; - - mctl_sys_init(); - - mctl_dll_init(0, ¶); - setbits_le32(&mctl_com->ccr, MCTL_CCR_CH0_CLK_EN); - - if (para.chan == 2) { - mctl_dll_init(1, ¶); - setbits_le32(&mctl_com->ccr, MCTL_CCR_CH1_CLK_EN); - } - - setbits_le32(&mctl_com->ccr, MCTL_CCR_MASTER_CLK_EN); - - mctl_channel_init(0, ¶); - if (para.chan == 2) - mctl_channel_init(1, ¶); - - mctl_com_init(¶); - mctl_port_cfg(); - - /* - * Change to 1 ch / sequence / 8192 byte pages / 16 rows / - * 8 bit banks / 1 rank mode. - */ - clrsetbits_le32(&mctl_com->cr, - MCTL_CR_CHANNEL_MASK | MCTL_CR_PAGE_SIZE_MASK | - MCTL_CR_ROW_MASK | MCTL_CR_BANK_MASK | MCTL_CR_RANK_MASK, - MCTL_CR_CHANNEL(1) | MCTL_CR_SEQUENCE | - MCTL_CR_PAGE_SIZE(8192) | MCTL_CR_ROW(16) | - MCTL_CR_BANK(1) | MCTL_CR_RANK(1)); - - /* Detect and set page size */ - for (columns = 7; columns < 20; columns++) { - if (mctl_mem_matches(1 << columns)) - break; - } - bus = (para.bus_width == 32) ? 2 : 1; - columns -= bus; - para.page_size = (1 << columns) * (bus << 1); - clrsetbits_le32(&mctl_com->cr, MCTL_CR_PAGE_SIZE_MASK, - MCTL_CR_PAGE_SIZE(para.page_size)); - - /* Detect and set rows */ - for (para.rows = 11; para.rows < 16; para.rows++) { - offset = 1 << (para.rows + columns + bus); - if (mctl_mem_matches(offset)) - break; - } - clrsetbits_le32(&mctl_com->cr, MCTL_CR_ROW_MASK, - MCTL_CR_ROW(para.rows)); - - /* Detect bank size */ - offset = 1 << (para.rows + columns + bus + 2); - bank = mctl_mem_matches(offset) ? 0 : 1; - - /* Restore interleave, chan and rank values, set bank size */ - clrsetbits_le32(&mctl_com->cr, - MCTL_CR_CHANNEL_MASK | MCTL_CR_SEQUENCE | - MCTL_CR_BANK_MASK | MCTL_CR_RANK_MASK, - MCTL_CR_CHANNEL(para.chan) | MCTL_CR_BANK(bank) | - MCTL_CR_RANK(para.rank)); - - return 1 << (para.rank + para.rows + bank + columns + para.chan + bus); -} diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun8i_a23.c b/arch/arm/cpu/armv7/sunxi/dram_sun8i_a23.c deleted file mode 100644 index c53671a0e9..0000000000 --- a/arch/arm/cpu/armv7/sunxi/dram_sun8i_a23.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Sun8i platform dram controller init. - * - * (C) Copyright 2014 Hans de Goede - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* - * Note this code uses a lot of magic hex values, that is because this code - * simply replays the init sequence as done by the Allwinner boot0 code, so - * we do not know what these values mean. There are no symbolic constants for - * these magic values, since we do not know how to name them and making up - * names for them is not useful. - * - * The register-layout of the sunxi_mctl_phy_reg-s looks a lot like the one - * found in the TI Keystone2 documentation: - * http://www.ti.com/lit/ug/spruhn7a/spruhn7a.pdf - * "Table4-2 DDR3 PHY Registers" - * This may be used as a (possible) reference for future work / cleanups. - */ - -#include -#include -#include -#include -#include -#include - -static const struct dram_para dram_para = { - .clock = CONFIG_DRAM_CLK, - .type = 3, - .zq = CONFIG_DRAM_ZQ, - .odt_en = IS_ENABLED(CONFIG_DRAM_ODT_EN), - .odt_correction = CONFIG_DRAM_ODT_CORRECTION, - .para1 = 0, /* not used (only used when tpr13 bit 31 is set */ - .para2 = 0, /* not used (only used when tpr13 bit 31 is set */ - .mr0 = 6736, - .mr1 = 4, - .mr2 = 16, - .mr3 = 0, - /* tpr0 - 10 contain timing constants or-ed together in u32 vals */ - .tpr0 = 0x2ab83def, - .tpr1 = 0x18082356, - .tpr2 = 0x00034156, - .tpr3 = 0x448c5533, - .tpr4 = 0x08010d00, - .tpr5 = 0x0340b20f, - .tpr6 = 0x20d118cc, - .tpr7 = 0x14062485, - .tpr8 = 0x220d1d52, - .tpr9 = 0x1e078c22, - .tpr10 = 0x3c, - .tpr11 = 0, /* not used */ - .tpr12 = 0, /* not used */ - .tpr13 = 0x30000, -}; - -static void mctl_sys_init(void) -{ - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - - /* enable pll5, note the divide by 2 is deliberate! */ - clock_set_pll5(dram_para.clock * 1000000 / 2, - dram_para.tpr13 & 0x40000); - - /* deassert ahb mctl reset */ - setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL); - - /* enable ahb mctl clock */ - setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL); -} - -static void mctl_apply_odt_correction(u32 *reg, int correction) -{ - int val; - - val = (readl(reg) >> 8) & 0xff; - val += correction; - - /* clamp */ - if (val < 0) - val = 0; - else if (val > 255) - val = 255; - - clrsetbits_le32(reg, 0xff00, val << 8); -} - -static void mctl_init(u32 *bus_width) -{ - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - struct sunxi_mctl_com_reg * const mctl_com = - (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - struct sunxi_mctl_phy_reg * const mctl_phy = - (struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE; - - if (dram_para.tpr13 & 0x20) - writel(0x40b, &mctl_phy->dcr); - else - writel(0x1000040b, &mctl_phy->dcr); - - if (dram_para.clock >= 480) - writel(0x5c000, &mctl_phy->dllgcr); - else - writel(0xdc000, &mctl_phy->dllgcr); - - writel(0x0a003e3f, &mctl_phy->pgcr0); - writel(0x03008421, &mctl_phy->pgcr1); - - writel(dram_para.mr0, &mctl_phy->mr0); - writel(dram_para.mr1, &mctl_phy->mr1); - writel(dram_para.mr2, &mctl_phy->mr2); - writel(dram_para.mr3, &mctl_phy->mr3); - - if (!(dram_para.tpr13 & 0x10000)) { - clrsetbits_le32(&mctl_phy->dx0gcr, 0x3800, 0x2000); - clrsetbits_le32(&mctl_phy->dx1gcr, 0x3800, 0x2000); - } - - /* - * All the masking and shifting below converts what I assume are DDR - * timing constants from Allwinner dram_para tpr format to the actual - * timing registers format. - */ - - writel((dram_para.tpr0 & 0x000fffff), &mctl_phy->ptr2); - writel((dram_para.tpr1 & 0x1fffffff), &mctl_phy->ptr3); - writel((dram_para.tpr0 & 0x3ff00000) >> 2 | - (dram_para.tpr2 & 0x0003ffff), &mctl_phy->ptr4); - - writel(dram_para.tpr3, &mctl_phy->dtpr0); - writel(dram_para.tpr4, &mctl_phy->dtpr2); - - writel(0x01000081, &mctl_phy->dtcr); - - if (dram_para.clock <= 240 || !dram_para.odt_en) { - clrbits_le32(&mctl_phy->dx0gcr, 0x600); - clrbits_le32(&mctl_phy->dx1gcr, 0x600); - } - if (dram_para.clock <= 240) { - writel(0, &mctl_phy->odtcr); - writel(0, &mctl_ctl->odtmap); - } - - writel(((dram_para.tpr5 & 0x0f00) << 12) | - ((dram_para.tpr5 & 0x00f8) << 9) | - ((dram_para.tpr5 & 0x0007) << 8), - &mctl_ctl->rfshctl0); - - writel(((dram_para.tpr5 & 0x0003f000) << 12) | - ((dram_para.tpr5 & 0x00fc0000) >> 2) | - ((dram_para.tpr5 & 0x3f000000) >> 16) | - ((dram_para.tpr6 & 0x0000003f) >> 0), - &mctl_ctl->dramtmg0); - - writel(((dram_para.tpr6 & 0x000007c0) << 10) | - ((dram_para.tpr6 & 0x0000f800) >> 3) | - ((dram_para.tpr6 & 0x003f0000) >> 16), - &mctl_ctl->dramtmg1); - - writel(((dram_para.tpr6 & 0x0fc00000) << 2) | - ((dram_para.tpr7 & 0x0000001f) << 16) | - ((dram_para.tpr7 & 0x000003e0) << 3) | - ((dram_para.tpr7 & 0x0000fc00) >> 10), - &mctl_ctl->dramtmg2); - - writel(((dram_para.tpr7 & 0x03ff0000) >> 16) | - ((dram_para.tpr6 & 0xf0000000) >> 16), - &mctl_ctl->dramtmg3); - - writel(((dram_para.tpr7 & 0x3c000000) >> 2 ) | - ((dram_para.tpr8 & 0x00000007) << 16) | - ((dram_para.tpr8 & 0x00000038) << 5) | - ((dram_para.tpr8 & 0x000003c0) >> 6), - &mctl_ctl->dramtmg4); - - writel(((dram_para.tpr8 & 0x00003c00) << 14) | - ((dram_para.tpr8 & 0x0003c000) << 2) | - ((dram_para.tpr8 & 0x00fc0000) >> 10) | - ((dram_para.tpr8 & 0x0f000000) >> 24), - &mctl_ctl->dramtmg5); - - writel(0x00000008, &mctl_ctl->dramtmg8); - - writel(((dram_para.tpr8 & 0xf0000000) >> 4) | - ((dram_para.tpr9 & 0x00007c00) << 6) | - ((dram_para.tpr9 & 0x000003e0) << 3) | - ((dram_para.tpr9 & 0x0000001f) >> 0), - &mctl_ctl->pitmg0); - - setbits_le32(&mctl_ctl->pitmg1, 0x80000); - - writel(((dram_para.tpr9 & 0x003f8000) << 9) | 0x2001, - &mctl_ctl->sched); - - writel((dram_para.mr0 << 16) | dram_para.mr1, &mctl_ctl->init3); - writel((dram_para.mr2 << 16) | dram_para.mr3, &mctl_ctl->init4); - - writel(0x00000000, &mctl_ctl->pimisc); - writel(0x80000000, &mctl_ctl->upd0); - - writel(((dram_para.tpr9 & 0xffc00000) >> 22) | - ((dram_para.tpr10 & 0x00000fff) << 16), - &mctl_ctl->rfshtmg); - - if (dram_para.tpr13 & 0x20) - writel(0x01040001, &mctl_ctl->mstr); - else - writel(0x01040401, &mctl_ctl->mstr); - - if (!(dram_para.tpr13 & 0x20000)) { - writel(0x00000002, &mctl_ctl->pwrctl); - writel(0x00008001, &mctl_ctl->pwrtmg); - } - - writel(0x00000001, &mctl_ctl->rfshctl3); - writel(0x00000001, &mctl_ctl->pimisc); - - /* deassert dram_clk_cfg reset */ - setbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST); - - setbits_le32(&mctl_com->ccr, 0x80000); - - /* zq stuff */ - writel((dram_para.zq >> 8) & 0xff, &mctl_phy->zqcr1); - - writel(0x00000003, &mctl_phy->pir); - udelay(10); - mctl_await_completion(&mctl_phy->pgsr0, 0x09, 0x09); - - writel(readl(&mctl_phy->zqsr0) | 0x10000000, &mctl_phy->zqcr2); - writel(dram_para.zq & 0xff, &mctl_phy->zqcr1); - - /* A23-v1.0 SDK uses 0xfdf3, A23-v2.0 SDK uses 0x5f3 */ - writel(0x000005f3, &mctl_phy->pir); - udelay(10); - mctl_await_completion(&mctl_phy->pgsr0, 0x03, 0x03); - - if (readl(&mctl_phy->dx1gsr0) & 0x1000000) { - *bus_width = 8; - writel(0, &mctl_phy->dx1gcr); - writel(dram_para.zq & 0xff, &mctl_phy->zqcr1); - writel(0x5f3, &mctl_phy->pir); - udelay(10000); - setbits_le32(&mctl_ctl->mstr, 0x1000); - } else - *bus_width = 16; - - if (dram_para.odt_correction) { - mctl_apply_odt_correction(&mctl_phy->dx0lcdlr1, - dram_para.odt_correction); - mctl_apply_odt_correction(&mctl_phy->dx1lcdlr1, - dram_para.odt_correction); - } - - mctl_await_completion(&mctl_ctl->statr, 0x01, 0x01); - - writel(0x08003e3f, &mctl_phy->pgcr0); - writel(0x00000000, &mctl_ctl->rfshctl3); -} - -unsigned long sunxi_dram_init(void) -{ - struct sunxi_mctl_com_reg * const mctl_com = - (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; - const u32 columns = 13; - u32 bus, bus_width, offset, page_size, rows; - - mctl_sys_init(); - mctl_init(&bus_width); - - if (bus_width == 16) { - page_size = 8; - bus = 1; - } else { - page_size = 7; - bus = 0; - } - - if (!(dram_para.tpr13 & 0x80000000)) { - /* Detect and set rows */ - writel(0x000310f4 | MCTL_CR_PAGE_SIZE(page_size), - &mctl_com->cr); - setbits_le32(&mctl_com->swonr, 0x0003ffff); - for (rows = 11; rows < 16; rows++) { - offset = 1 << (rows + columns + bus); - if (mctl_mem_matches(offset)) - break; - } - clrsetbits_le32(&mctl_com->cr, MCTL_CR_ROW_MASK, - MCTL_CR_ROW(rows)); - } else { - rows = (dram_para.para1 >> 16) & 0xff; - writel(((dram_para.para2 & 0x000000f0) << 11) | - ((rows - 1) << 4) | - ((dram_para.para1 & 0x0f000000) >> 22) | - 0x31000 | MCTL_CR_PAGE_SIZE(page_size), - &mctl_com->cr); - setbits_le32(&mctl_com->swonr, 0x0003ffff); - } - - /* Setup DRAM master priority? If this is left out things still work */ - writel(0x00000008, &mctl_com->mcr0_0); - writel(0x0001000d, &mctl_com->mcr1_0); - writel(0x00000004, &mctl_com->mcr0_1); - writel(0x00000080, &mctl_com->mcr1_1); - writel(0x00000004, &mctl_com->mcr0_2); - writel(0x00000019, &mctl_com->mcr1_2); - writel(0x00000004, &mctl_com->mcr0_3); - writel(0x00000080, &mctl_com->mcr1_3); - writel(0x00000004, &mctl_com->mcr0_4); - writel(0x01010040, &mctl_com->mcr1_4); - writel(0x00000004, &mctl_com->mcr0_5); - writel(0x0001002f, &mctl_com->mcr1_5); - writel(0x00000004, &mctl_com->mcr0_6); - writel(0x00010020, &mctl_com->mcr1_6); - writel(0x00000004, &mctl_com->mcr0_7); - writel(0x00010020, &mctl_com->mcr1_7); - writel(0x00000008, &mctl_com->mcr0_8); - writel(0x00000001, &mctl_com->mcr1_8); - writel(0x00000008, &mctl_com->mcr0_9); - writel(0x00000005, &mctl_com->mcr1_9); - writel(0x00000008, &mctl_com->mcr0_10); - writel(0x00000003, &mctl_com->mcr1_10); - writel(0x00000008, &mctl_com->mcr0_11); - writel(0x00000005, &mctl_com->mcr1_11); - writel(0x00000008, &mctl_com->mcr0_12); - writel(0x00000003, &mctl_com->mcr1_12); - writel(0x00000008, &mctl_com->mcr0_13); - writel(0x00000004, &mctl_com->mcr1_13); - writel(0x00000008, &mctl_com->mcr0_14); - writel(0x00000002, &mctl_com->mcr1_14); - writel(0x00000008, &mctl_com->mcr0_15); - writel(0x00000003, &mctl_com->mcr1_15); - writel(0x00010138, &mctl_com->bwcr); - - return 1 << (rows + columns + bus); -} diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun8i_a33.c b/arch/arm/cpu/armv7/sunxi/dram_sun8i_a33.c deleted file mode 100644 index fa1620cb39..0000000000 --- a/arch/arm/cpu/armv7/sunxi/dram_sun8i_a33.c +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Sun8i a33 platform dram controller init. - * - * (C) Copyright 2007-2015 Allwinner Technology Co. - * Jerry Wang - * (C) Copyright 2015 Vishnu Patekar - * (C) Copyright 2015 Hans de Goede - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#include -#include -#include -#include -#include -#include - -/* PLL runs at 2x dram-clk, controller runs at PLL / 4 (dram-clk / 2) */ -#define DRAM_CLK_MUL 2 -#define DRAM_CLK_DIV 4 -#define DRAM_SIGMA_DELTA_ENABLE 1 - -struct dram_para { - u8 cs1; - u8 seq; - u8 bank; - u8 rank; - u8 rows; - u8 bus_width; - u16 page_size; -}; - -static void mctl_set_cr(struct dram_para *para) -{ - struct sunxi_mctl_com_reg * const mctl_com = - (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; - - writel(MCTL_CR_CS1_CONTROL(para->cs1) | MCTL_CR_UNKNOWN | - MCTL_CR_CHANNEL(1) | MCTL_CR_DDR3 | - (para->seq ? MCTL_CR_SEQUENCE : 0) | - ((para->bus_width == 16) ? MCTL_CR_BUSW16 : MCTL_CR_BUSW8) | - MCTL_CR_PAGE_SIZE(para->page_size) | MCTL_CR_ROW(para->rows) | - MCTL_CR_BANK(para->bank) | MCTL_CR_RANK(para->rank), - &mctl_com->cr); -} - -static void auto_detect_dram_size(struct dram_para *para) -{ - u8 orig_rank = para->rank; - int rows, columns; - - /* Row detect */ - para->page_size = 512; - para->seq = 1; - para->rows = 16; - para->rank = 1; - mctl_set_cr(para); - for (rows = 11 ; rows < 16 ; rows++) { - if (mctl_mem_matches(1 << (rows + 9))) /* row-column */ - break; - } - - /* Column (page size) detect */ - para->rows = 11; - para->page_size = 8192; - mctl_set_cr(para); - for (columns = 9 ; columns < 13 ; columns++) { - if (mctl_mem_matches(1 << columns)) - break; - } - - para->seq = 0; - para->rank = orig_rank; - para->rows = rows; - para->page_size = 1 << columns; - mctl_set_cr(para); -} - -static inline int ns_to_t(int nanoseconds) -{ - const unsigned int ctrl_freq = - CONFIG_DRAM_CLK * DRAM_CLK_MUL / DRAM_CLK_DIV; - - return (ctrl_freq * nanoseconds + 999) / 1000; -} - -static void auto_set_timing_para(struct dram_para *para) -{ - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - u32 reg_val; - - u8 tccd = 2; - u8 tfaw = ns_to_t(50); - u8 trrd = max(ns_to_t(10), 4); - u8 trcd = ns_to_t(15); - u8 trc = ns_to_t(53); - u8 txp = max(ns_to_t(8), 3); - u8 twtr = max(ns_to_t(8), 4); - u8 trtp = max(ns_to_t(8), 4); - u8 twr = max(ns_to_t(15), 3); - u8 trp = ns_to_t(15); - u8 tras = ns_to_t(38); - - u16 trefi = ns_to_t(7800) / 32; - u16 trfc = ns_to_t(350); - - /* Fixed timing parameters */ - u8 tmrw = 0; - u8 tmrd = 4; - u8 tmod = 12; - u8 tcke = 3; - u8 tcksrx = 5; - u8 tcksre = 5; - u8 tckesr = 4; - u8 trasmax = 24; - u8 tcl = 6; /* CL 12 */ - u8 tcwl = 4; /* CWL 8 */ - u8 t_rdata_en = 4; - u8 wr_latency = 2; - - u32 tdinit0 = (500 * CONFIG_DRAM_CLK) + 1; /* 500us */ - u32 tdinit1 = (360 * CONFIG_DRAM_CLK) / 1000 + 1; /* 360ns */ - u32 tdinit2 = (200 * CONFIG_DRAM_CLK) + 1; /* 200us */ - u32 tdinit3 = (1 * CONFIG_DRAM_CLK) + 1; /* 1us */ - - u8 twtp = tcwl + 2 + twr; /* WL + BL / 2 + tWR */ - u8 twr2rd = tcwl + 2 + twtr; /* WL + BL / 2 + tWTR */ - u8 trd2wr = tcl + 2 + 1 - tcwl; /* RL + BL / 2 + 2 - WL */ - - /* Set work mode register */ - mctl_set_cr(para); - /* Set mode register */ - writel(MCTL_MR0, &mctl_ctl->mr0); - writel(MCTL_MR1, &mctl_ctl->mr1); - writel(MCTL_MR2, &mctl_ctl->mr2); - writel(MCTL_MR3, &mctl_ctl->mr3); - /* Set dram timing */ - reg_val = (twtp << 24) | (tfaw << 16) | (trasmax << 8) | (tras << 0); - writel(reg_val, &mctl_ctl->dramtmg0); - reg_val = (txp << 16) | (trtp << 8) | (trc << 0); - writel(reg_val, &mctl_ctl->dramtmg1); - reg_val = (tcwl << 24) | (tcl << 16) | (trd2wr << 8) | (twr2rd << 0); - writel(reg_val, &mctl_ctl->dramtmg2); - reg_val = (tmrw << 16) | (tmrd << 12) | (tmod << 0); - writel(reg_val, &mctl_ctl->dramtmg3); - reg_val = (trcd << 24) | (tccd << 16) | (trrd << 8) | (trp << 0); - writel(reg_val, &mctl_ctl->dramtmg4); - reg_val = (tcksrx << 24) | (tcksre << 16) | (tckesr << 8) | (tcke << 0); - writel(reg_val, &mctl_ctl->dramtmg5); - /* Set two rank timing and exit self-refresh timing */ - reg_val = readl(&mctl_ctl->dramtmg8); - reg_val &= ~(0xff << 8); - reg_val &= ~(0xff << 0); - reg_val |= (0x33 << 8); - reg_val |= (0x8 << 0); - writel(reg_val, &mctl_ctl->dramtmg8); - /* Set phy interface time */ - reg_val = (0x2 << 24) | (t_rdata_en << 16) | (0x1 << 8) - | (wr_latency << 0); - /* PHY interface write latency and read latency configure */ - writel(reg_val, &mctl_ctl->pitmg0); - /* Set phy time PTR0-2 use default */ - writel(((tdinit0 << 0) | (tdinit1 << 20)), &mctl_ctl->ptr3); - writel(((tdinit2 << 0) | (tdinit3 << 20)), &mctl_ctl->ptr4); - /* Set refresh timing */ - reg_val = (trefi << 16) | (trfc << 0); - writel(reg_val, &mctl_ctl->rfshtmg); -} - -static void mctl_set_pir(u32 val) -{ - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - - writel(val, &mctl_ctl->pir); - mctl_await_completion(&mctl_ctl->pgsr0, 0x1, 0x1); -} - -static void mctl_data_train_cfg(struct dram_para *para) -{ - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - - if (para->rank == 2) - clrsetbits_le32(&mctl_ctl->dtcr, 0x3 << 24, 0x3 << 24); - else - clrsetbits_le32(&mctl_ctl->dtcr, 0x3 << 24, 0x1 << 24); -} - -static int mctl_train_dram(struct dram_para *para) -{ - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - - mctl_data_train_cfg(para); - mctl_set_pir(0x5f3); - - return ((readl(&mctl_ctl->pgsr0) >> 20) & 0xff) ? -EIO : 0; -} - -static int mctl_channel_init(struct dram_para *para) -{ - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - struct sunxi_mctl_com_reg * const mctl_com = - (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; - u32 low_data_lines_status; /* Training status of datalines 0 - 7 */ - u32 high_data_lines_status; /* Training status of datalines 8 - 15 */ - - auto_set_timing_para(para); - - /* Disable dram VTC */ - clrbits_le32(&mctl_ctl->pgcr0, 0x3f << 0); - - /* Set ODT */ - if ((CONFIG_DRAM_CLK > 400) && IS_ENABLED(CONFIG_DRAM_ODT_EN)) { - setbits_le32(DXnGCR0(0), 0x3 << 9); - setbits_le32(DXnGCR0(1), 0x3 << 9); - } else { - clrbits_le32(DXnGCR0(0), 0x3 << 9); - clrbits_le32(DXnGCR0(1), 0x3 << 9); - } - - /* set PLL configuration */ - if (CONFIG_DRAM_CLK >= 480) - setbits_le32(&mctl_ctl->pllgcr, 0x1 << 18); - else - setbits_le32(&mctl_ctl->pllgcr, 0x3 << 18); - - /* Auto detect dram config, set 2 rank and 16bit bus-width */ - para->cs1 = 0; - para->rank = 2; - para->bus_width = 16; - mctl_set_cr(para); - - /* Open DQS gating */ - clrbits_le32(&mctl_ctl->pgcr2, (0x3 << 6)); - clrbits_le32(&mctl_ctl->dqsgmr, (0x1 << 8) | (0x7)); - - mctl_data_train_cfg(para); - - /* ZQ calibration */ - writel(CONFIG_DRAM_ZQ & 0xff, &mctl_ctl->zqcr1); - /* CA calibration */ - mctl_set_pir(0x00000003); - /* More ZQ calibration */ - writel(readl(&mctl_ctl->zqsr0) | 0x10000000, &mctl_ctl->zqcr2); - writel((CONFIG_DRAM_ZQ >> 8) & 0xff, &mctl_ctl->zqcr1); - - /* DQS gate training */ - if (mctl_train_dram(para) != 0) { - low_data_lines_status = (readl(DXnGSR0(0)) >> 24) & 0x03; - high_data_lines_status = (readl(DXnGSR0(1)) >> 24) & 0x03; - - if (low_data_lines_status == 0x3) - return -EIO; - - /* DRAM has only one rank */ - para->rank = 1; - mctl_set_cr(para); - - if (low_data_lines_status == high_data_lines_status) - goto done; /* 16 bit bus, 1 rank */ - - if (!(low_data_lines_status & high_data_lines_status)) { - /* Retry 16 bit bus-width with CS1 set */ - para->cs1 = 1; - mctl_set_cr(para); - if (mctl_train_dram(para) == 0) - goto done; - } - - /* Try 8 bit bus-width */ - writel(0x0, DXnGCR0(1)); /* Disable high DQ */ - para->cs1 = 0; - para->bus_width = 8; - mctl_set_cr(para); - if (mctl_train_dram(para) != 0) - return -EIO; - } -done: - /* Check the dramc status */ - mctl_await_completion(&mctl_ctl->statr, 0x1, 0x1); - - /* Close DQS gating */ - setbits_le32(&mctl_ctl->pgcr2, 0x3 << 6); - - /* Enable master access */ - writel(0xffffffff, &mctl_com->maer); - - return 0; -} - -static void mctl_sys_init(struct dram_para *para) -{ - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - struct sunxi_mctl_com_reg * const mctl_com = - (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; - - clrsetbits_le32(&ccm->dram_pll_cfg, CCM_DRAMPLL_CFG_SRC_MASK, - CCM_DRAMPLL_CFG_SRC_PLL11); - - clock_set_pll11(CONFIG_DRAM_CLK * 1000000 * DRAM_CLK_MUL, - DRAM_SIGMA_DELTA_ENABLE); - - clrsetbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_DIV_MASK, - CCM_DRAMCLK_CFG_DIV(DRAM_CLK_DIV) | - CCM_DRAMCLK_CFG_RST | CCM_DRAMCLK_CFG_UPD); - mctl_await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0); - - setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL); - setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL); - setbits_le32(&ccm->mbus_reset, CCM_MBUS_RESET_RESET); - setbits_le32(&ccm->mbus0_clk_cfg, MBUS_CLK_GATE); - - /* Set dram master access priority */ - writel(0x0, &mctl_com->mapr); - writel(0x0f802f01, &mctl_ctl->sched); - writel(0x0000400f, &mctl_ctl->clken); /* normal */ - - udelay(250); -} - -unsigned long sunxi_dram_init(void) -{ - struct sunxi_mctl_com_reg * const mctl_com = - (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - - struct dram_para para = { - .cs1 = 0, - .bank = 1, - .rank = 1, - .rows = 15, - .bus_width = 16, - .page_size = 2048, - }; - - mctl_sys_init(¶); - - if (mctl_channel_init(¶) != 0) - return 0; - - auto_detect_dram_size(¶); - - /* Enable master software clk */ - writel(readl(&mctl_com->swonr) | 0x3ffff, &mctl_com->swonr); - - /* Set DRAM ODT MAP */ - if (para.rank == 2) - writel(0x00000303, &mctl_ctl->odtmap); - else - writel(0x00000201, &mctl_ctl->odtmap); - - return para.page_size * (para.bus_width / 8) * - (1 << (para.bank + para.rank + para.rows)); -} diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun8i_a83t.c b/arch/arm/cpu/armv7/sunxi/dram_sun8i_a83t.c deleted file mode 100644 index 55df1b9d54..0000000000 --- a/arch/arm/cpu/armv7/sunxi/dram_sun8i_a83t.c +++ /dev/null @@ -1,472 +0,0 @@ -/* - * Sun8i a33 platform dram controller init. - * - * (C) Copyright 2007-2015 Allwinner Technology Co. - * Jerry Wang - * (C) Copyright 2015 Vishnu Patekar - * (C) Copyright 2015 Hans de Goede - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#include -#include -#include -#include -#include -#include - -#define DRAM_CLK_MUL 2 -#define DRAM_CLK_DIV 1 - -struct dram_para { - u8 cs1; - u8 seq; - u8 bank; - u8 rank; - u8 rows; - u8 bus_width; - u8 dram_type; - u16 page_size; -}; - -static void mctl_set_cr(struct dram_para *para) -{ - struct sunxi_mctl_com_reg * const mctl_com = - (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; - - writel(MCTL_CR_CS1_CONTROL(para->cs1) | MCTL_CR_UNKNOWN | - MCTL_CR_CHANNEL(1) | MCTL_CR_DRAM_TYPE(para->dram_type) | - (para->seq ? MCTL_CR_SEQUENCE : 0) | - ((para->bus_width == 16) ? MCTL_CR_BUSW16 : MCTL_CR_BUSW8) | - MCTL_CR_PAGE_SIZE(para->page_size) | MCTL_CR_ROW(para->rows) | - MCTL_CR_BANK(para->bank) | MCTL_CR_RANK(para->rank), - &mctl_com->cr); -} - -static void auto_detect_dram_size(struct dram_para *para) -{ - u8 orig_rank = para->rank; - int rows, columns; - - /* Row detect */ - para->page_size = 512; - para->seq = 1; - para->rows = 16; - para->rank = 1; - mctl_set_cr(para); - for (rows = 11 ; rows < 16 ; rows++) { - if (mctl_mem_matches(1 << (rows + 9))) /* row-column */ - break; - } - - /* Column (page size) detect */ - para->rows = 11; - para->page_size = 8192; - mctl_set_cr(para); - for (columns = 9 ; columns < 13 ; columns++) { - if (mctl_mem_matches(1 << columns)) - break; - } - - para->seq = 0; - para->rank = orig_rank; - para->rows = rows; - para->page_size = 1 << columns; - mctl_set_cr(para); -} - -static inline int ns_to_t(int nanoseconds) -{ - const unsigned int ctrl_freq = - CONFIG_DRAM_CLK * DRAM_CLK_MUL / DRAM_CLK_DIV; - - return (ctrl_freq * nanoseconds + 999) / 1000; -} - -static void auto_set_timing_para(struct dram_para *para) -{ - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - - u32 reg_val; - - u8 tccd = 2; - u8 tfaw = ns_to_t(50); - u8 trrd = max(ns_to_t(10), 4); - u8 trcd = ns_to_t(15); - u8 trc = ns_to_t(53); - u8 txp = max(ns_to_t(8), 3); - u8 twtr = max(ns_to_t(8), 4); - u8 trtp = max(ns_to_t(8), 4); - u8 twr = max(ns_to_t(15), 3); - u8 trp = ns_to_t(15); - u8 tras = ns_to_t(38); - - u16 trefi = ns_to_t(7800) / 32; - u16 trfc = ns_to_t(350); - - /* Fixed timing parameters */ - u8 tmrw = 0; - u8 tmrd = 4; - u8 tmod = 12; - u8 tcke = 3; - u8 tcksrx = 5; - u8 tcksre = 5; - u8 tckesr = 4; - u8 trasmax = 24; - u8 tcl = 6; /* CL 12 */ - u8 tcwl = 4; /* CWL 8 */ - u8 t_rdata_en = 4; - u8 wr_latency = 2; - - u32 tdinit0 = (500 * CONFIG_DRAM_CLK) + 1; /* 500us */ - u32 tdinit1 = (360 * CONFIG_DRAM_CLK) / 1000 + 1; /* 360ns */ - u32 tdinit2 = (200 * CONFIG_DRAM_CLK) + 1; /* 200us */ - u32 tdinit3 = (1 * CONFIG_DRAM_CLK) + 1; /* 1us */ - - u8 twtp = tcwl + 2 + twr; /* WL + BL / 2 + tWR */ - u8 twr2rd = tcwl + 2 + twtr; /* WL + BL / 2 + tWTR */ - u8 trd2wr = tcl + 2 + 1 - tcwl; /* RL + BL / 2 + 2 - WL */ - - /* Set work mode register */ - mctl_set_cr(para); - /* Set mode register */ - if (para->dram_type == DRAM_TYPE_DDR3) { - writel(MCTL_MR0, &mctl_ctl->mr0); - writel(MCTL_MR1, &mctl_ctl->mr1); - writel(MCTL_MR2, &mctl_ctl->mr2); - writel(MCTL_MR3, &mctl_ctl->mr3); - } else if (para->dram_type == DRAM_TYPE_LPDDR3) { - writel(MCTL_LPDDR3_MR0, &mctl_ctl->mr0); - writel(MCTL_LPDDR3_MR1, &mctl_ctl->mr1); - writel(MCTL_LPDDR3_MR2, &mctl_ctl->mr2); - writel(MCTL_LPDDR3_MR3, &mctl_ctl->mr3); - - /* timing parameters for LPDDR3 */ - tfaw = max(ns_to_t(50), 4); - trrd = max(ns_to_t(10), 2); - trcd = max(ns_to_t(24), 2); - trc = ns_to_t(70); - txp = max(ns_to_t(8), 2); - twtr = max(ns_to_t(8), 2); - trtp = max(ns_to_t(8), 2); - trp = max(ns_to_t(27), 2); - tras = ns_to_t(42); - trefi = ns_to_t(3900) / 32; - trfc = ns_to_t(210); - tmrw = 5; - tmrd = 5; - tckesr = 5; - tcwl = 3; /* CWL 8 */ - t_rdata_en = 5; - tdinit0 = (200 * CONFIG_DRAM_CLK) + 1; /* 200us */ - tdinit1 = (100 * CONFIG_DRAM_CLK) / 1000 + 1; /* 100ns */ - tdinit2 = (11 * CONFIG_DRAM_CLK) + 1; /* 200us */ - tdinit3 = (1 * CONFIG_DRAM_CLK) + 1; /* 1us */ - twtp = tcwl + 4 + twr + 1; /* CWL + BL/2 + tWR */ - twr2rd = tcwl + 4 + 1 + twtr; /* WL + BL / 2 + tWTR */ - trd2wr = tcl + 4 + 5 - tcwl + 1; /* RL + BL / 2 + 2 - WL */ - } - /* Set dram timing */ - reg_val = (twtp << 24) | (tfaw << 16) | (trasmax << 8) | (tras << 0); - writel(reg_val, &mctl_ctl->dramtmg0); - reg_val = (txp << 16) | (trtp << 8) | (trc << 0); - writel(reg_val, &mctl_ctl->dramtmg1); - reg_val = (tcwl << 24) | (tcl << 16) | (trd2wr << 8) | (twr2rd << 0); - writel(reg_val, &mctl_ctl->dramtmg2); - reg_val = (tmrw << 16) | (tmrd << 12) | (tmod << 0); - writel(reg_val, &mctl_ctl->dramtmg3); - reg_val = (trcd << 24) | (tccd << 16) | (trrd << 8) | (trp << 0); - writel(reg_val, &mctl_ctl->dramtmg4); - reg_val = (tcksrx << 24) | (tcksre << 16) | (tckesr << 8) | (tcke << 0); - writel(reg_val, &mctl_ctl->dramtmg5); - /* Set two rank timing and exit self-refresh timing */ - reg_val = readl(&mctl_ctl->dramtmg8); - reg_val &= ~(0xff << 8); - reg_val &= ~(0xff << 0); - reg_val |= (0x33 << 8); - reg_val |= (0x8 << 0); - writel(reg_val, &mctl_ctl->dramtmg8); - /* Set phy interface time */ - reg_val = (0x2 << 24) | (t_rdata_en << 16) | (0x1 << 8) - | (wr_latency << 0); - /* PHY interface write latency and read latency configure */ - writel(reg_val, &mctl_ctl->pitmg0); - /* Set phy time PTR0-2 use default */ - writel(((tdinit0 << 0) | (tdinit1 << 20)), &mctl_ctl->ptr3); - writel(((tdinit2 << 0) | (tdinit3 << 20)), &mctl_ctl->ptr4); - /* Set refresh timing */ - reg_val = (trefi << 16) | (trfc << 0); - writel(reg_val, &mctl_ctl->rfshtmg); -} - -static void mctl_set_pir(u32 val) -{ - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - - writel(val, &mctl_ctl->pir); - mctl_await_completion(&mctl_ctl->pgsr0, 0x1, 0x1); -} - -static void mctl_data_train_cfg(struct dram_para *para) -{ - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - - if (para->rank == 2) - clrsetbits_le32(&mctl_ctl->dtcr, 0x3 << 24, 0x3 << 24); - else - clrsetbits_le32(&mctl_ctl->dtcr, 0x3 << 24, 0x1 << 24); -} - -static int mctl_train_dram(struct dram_para *para) -{ - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - - mctl_data_train_cfg(para); - mctl_set_pir(0x5f3); - - return ((readl(&mctl_ctl->pgsr0) >> 20) & 0xff) ? -EIO : 0; -} - -static void set_master_priority(void) -{ - writel(0x00a0000d, MCTL_MASTER_CFG0(0)); - writel(0x00500064, MCTL_MASTER_CFG1(0)); - writel(0x07000009, MCTL_MASTER_CFG0(1)); - writel(0x00000600, MCTL_MASTER_CFG1(1)); - writel(0x01000009, MCTL_MASTER_CFG0(3)); - writel(0x00000064, MCTL_MASTER_CFG1(3)); - writel(0x08000009, MCTL_MASTER_CFG0(4)); - writel(0x00000640, MCTL_MASTER_CFG1(4)); - writel(0x20000308, MCTL_MASTER_CFG0(8)); - writel(0x00001000, MCTL_MASTER_CFG1(8)); - writel(0x02800009, MCTL_MASTER_CFG0(9)); - writel(0x00000100, MCTL_MASTER_CFG1(9)); - writel(0x01800009, MCTL_MASTER_CFG0(5)); - writel(0x00000100, MCTL_MASTER_CFG1(5)); - writel(0x01800009, MCTL_MASTER_CFG0(7)); - writel(0x00000100, MCTL_MASTER_CFG1(7)); - writel(0x00640009, MCTL_MASTER_CFG0(6)); - writel(0x00000032, MCTL_MASTER_CFG1(6)); - writel(0x0100000d, MCTL_MASTER_CFG0(2)); - writel(0x00500080, MCTL_MASTER_CFG1(2)); -} - -static int mctl_channel_init(struct dram_para *para) -{ - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - struct sunxi_mctl_com_reg * const mctl_com = - (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; - u32 low_data_lines_status; /* Training status of datalines 0 - 7 */ - u32 high_data_lines_status; /* Training status of datalines 8 - 15 */ - u32 i, rval; - - auto_set_timing_para(para); - - /* Set dram master access priority */ - writel(0x000101a0, &mctl_com->bwcr); - /* set cpu high priority */ - writel(0x1, &mctl_com->mapr); - set_master_priority(); - udelay(250); - - /* Disable dram VTC */ - clrbits_le32(&mctl_ctl->pgcr0, 0x3f << 0 | 0x1 << 30); - clrsetbits_le32(&mctl_ctl->pgcr1, 0x1 << 24, 0x1 << 26); - - writel(0x94be6fa3, MCTL_PROTECT); - udelay(100); - clrsetbits_le32(MX_UPD2, 0xfff << 16, 0x50 << 16); - writel(0x0, MCTL_PROTECT); - udelay(100); - - - /* Set ODT */ - if (IS_ENABLED(CONFIG_DRAM_ODT_EN)) - rval = 0x0; - else - rval = 0x2; - - for (i = 0 ; i < 11 ; i++) { - clrsetbits_le32(DATX0IOCR(i), (0x3 << 24) | (0x3 << 16), - rval << 24); - clrsetbits_le32(DATX1IOCR(i), (0x3 << 24) | (0x3 << 16), - rval << 24); - clrsetbits_le32(DATX2IOCR(i), (0x3 << 24) | (0x3 << 16), - rval << 24); - clrsetbits_le32(DATX3IOCR(i), (0x3 << 24) | (0x3 << 16), - rval << 24); - } - - for (i = 0; i < 31; i++) - clrsetbits_le32(CAIOCR(i), 0x3 << 26 | 0x3 << 16, 0x2 << 26); - - /* set PLL configuration */ - if (CONFIG_DRAM_CLK >= 480) - setbits_le32(&mctl_ctl->pllgcr, 0x1 << 19); - else - setbits_le32(&mctl_ctl->pllgcr, 0x3 << 19); - - /* Auto detect dram config, set 2 rank and 16bit bus-width */ - para->cs1 = 0; - para->rank = 2; - para->bus_width = 16; - mctl_set_cr(para); - - /* Open DQS gating */ - clrbits_le32(&mctl_ctl->pgcr2, (0x3 << 6)); - clrbits_le32(&mctl_ctl->dqsgmr, (0x1 << 8) | (0x7)); - - if (para->dram_type == DRAM_TYPE_LPDDR3) - clrsetbits_le32(&mctl_ctl->dxccr, (0x1 << 27) | (0x3<<6) , - 0x1 << 31); - if (readl(&mctl_com->cr) & 0x1) - writel(0x00000303, &mctl_ctl->odtmap); - else - writel(0x00000201, &mctl_ctl->odtmap); - - mctl_data_train_cfg(para); - /* ZQ calibration */ - clrsetbits_le32(ZQnPR(0), 0x000000ff, CONFIG_DRAM_ZQ & 0xff); - clrsetbits_le32(ZQnPR(1), 0x000000ff, (CONFIG_DRAM_ZQ >> 8) & 0xff); - /* CA calibration */ - - if (para->dram_type == DRAM_TYPE_DDR3) - mctl_set_pir(0x0201f3 | 0x1<<10); - else - mctl_set_pir(0x020173 | 0x1<<10); - - /* DQS gate training */ - if (mctl_train_dram(para) != 0) { - low_data_lines_status = (readl(DXnGSR0(0)) >> 24) & 0x03; - high_data_lines_status = (readl(DXnGSR0(1)) >> 24) & 0x03; - - if (low_data_lines_status == 0x3) - return -EIO; - - /* DRAM has only one rank */ - para->rank = 1; - mctl_set_cr(para); - - if (low_data_lines_status == high_data_lines_status) - goto done; /* 16 bit bus, 1 rank */ - - if (!(low_data_lines_status & high_data_lines_status)) { - /* Retry 16 bit bus-width with CS1 set */ - para->cs1 = 1; - mctl_set_cr(para); - if (mctl_train_dram(para) == 0) - goto done; - } - - /* Try 8 bit bus-width */ - writel(0x0, DXnGCR0(1)); /* Disable high DQ */ - para->cs1 = 0; - para->bus_width = 8; - mctl_set_cr(para); - if (mctl_train_dram(para) != 0) - return -EIO; - } -done: - /* Check the dramc status */ - mctl_await_completion(&mctl_ctl->statr, 0x1, 0x1); - - /* Close DQS gating */ - setbits_le32(&mctl_ctl->pgcr2, 0x3 << 6); - - /* set PGCR3,CKE polarity */ - writel(0x00aa0060, &mctl_ctl->pgcr3); - /* Enable master access */ - writel(0xffffffff, &mctl_com->maer); - - return 0; -} - -static void mctl_sys_init(struct dram_para *para) -{ - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - - clrbits_le32(&ccm->mbus_clk_cfg, MBUS_CLK_GATE); - clrbits_le32(&ccm->mbus_reset, CCM_MBUS_RESET_RESET); - clrbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL); - clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL); - clrbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_EN); - udelay(1000); - clrbits_le32(&ccm->dram_clk_cfg, 0x01<<31); - - clock_set_pll5(CONFIG_DRAM_CLK * 1000000 * DRAM_CLK_MUL); - - clrsetbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_DIV_MASK, - CCM_DRAMCLK_CFG_DIV(DRAM_CLK_DIV) | - CCM_DRAMCLK_CFG_RST | CCM_DRAMCLK_CFG_UPD); - mctl_await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0); - - setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL); - setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL); - setbits_le32(&ccm->mbus_reset, CCM_MBUS_RESET_RESET); - setbits_le32(&ccm->mbus_clk_cfg, MBUS_CLK_GATE); - - para->rank = 2; - para->bus_width = 16; - mctl_set_cr(para); - - /* Set dram master access priority */ - writel(0x0000e00f, &mctl_ctl->clken); /* normal */ - - udelay(250); -} - -unsigned long sunxi_dram_init(void) -{ - struct sunxi_mctl_com_reg * const mctl_com = - (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - - struct dram_para para = { - .cs1 = 0, - .bank = 1, - .rank = 1, - .rows = 15, - .bus_width = 16, - .page_size = 2048, - }; - -#if defined(CONFIG_MACH_SUN8I_A83T) -#if (CONFIG_DRAM_TYPE == 3) || (CONFIG_DRAM_TYPE == 7) - para.dram_type = CONFIG_DRAM_TYPE; -#else -#error Unsupported DRAM type, Please set DRAM type (3:DDR3, 7:LPDDR3) -#endif -#endif - setbits_le32(SUNXI_PRCM_BASE + 0x1e0, 0x1 << 8); - - writel(0, (SUNXI_PRCM_BASE + 0x1e8)); - udelay(10); - - mctl_sys_init(¶); - - if (mctl_channel_init(¶) != 0) - return 0; - - auto_detect_dram_size(¶); - - /* Enable master software clk */ - writel(readl(&mctl_com->swonr) | 0x3ffff, &mctl_com->swonr); - - /* Set DRAM ODT MAP */ - if (para.rank == 2) - writel(0x00000303, &mctl_ctl->odtmap); - else - writel(0x00000201, &mctl_ctl->odtmap); - - return para.page_size * (para.bus_width / 8) * - (1 << (para.bank + para.rank + para.rows)); -} diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun8i_h3.c b/arch/arm/cpu/armv7/sunxi/dram_sun8i_h3.c deleted file mode 100644 index 2020d75fd1..0000000000 --- a/arch/arm/cpu/armv7/sunxi/dram_sun8i_h3.c +++ /dev/null @@ -1,469 +0,0 @@ -/* - * sun8i H3 platform dram controller init - * - * (C) Copyright 2007-2015 Allwinner Technology Co. - * Jerry Wang - * (C) Copyright 2015 Vishnu Patekar - * (C) Copyright 2015 Hans de Goede - * (C) Copyright 2015 Jens Kuske - * - * SPDX-License-Identifier: GPL-2.0+ - */ -#include -#include -#include -#include -#include - -struct dram_para { - u32 read_delays; - u32 write_delays; - u16 page_size; - u8 bus_width; - u8 dual_rank; - u8 row_bits; -}; - -static inline int ns_to_t(int nanoseconds) -{ - const unsigned int ctrl_freq = CONFIG_DRAM_CLK / 2; - - return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000); -} - -static u32 bin_to_mgray(int val) -{ - static const u8 lookup_table[32] = { - 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05, - 0x0c, 0x0d, 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09, - 0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x1f, 0x1c, 0x1d, - 0x14, 0x15, 0x16, 0x17, 0x12, 0x13, 0x10, 0x11, - }; - - return lookup_table[clamp(val, 0, 31)]; -} - -static int mgray_to_bin(u32 val) -{ - static const u8 lookup_table[32] = { - 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05, - 0x0e, 0x0f, 0x0c, 0x0d, 0x08, 0x09, 0x0a, 0x0b, - 0x1e, 0x1f, 0x1c, 0x1d, 0x18, 0x19, 0x1a, 0x1b, - 0x10, 0x11, 0x12, 0x13, 0x16, 0x17, 0x14, 0x15, - }; - - return lookup_table[val & 0x1f]; -} - -static void mctl_phy_init(u32 val) -{ - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - - writel(val | PIR_INIT, &mctl_ctl->pir); - mctl_await_completion(&mctl_ctl->pgsr[0], PGSR_INIT_DONE, 0x1); -} - -static void mctl_dq_delay(u32 read, u32 write) -{ - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - int i, j; - u32 val; - - for (i = 0; i < 4; i++) { - val = DATX_IOCR_WRITE_DELAY((write >> (i * 4)) & 0xf) | - DATX_IOCR_READ_DELAY(((read >> (i * 4)) & 0xf) * 2); - - for (j = DATX_IOCR_DQ(0); j <= DATX_IOCR_DM; j++) - writel(val, &mctl_ctl->datx[i].iocr[j]); - } - - clrbits_le32(&mctl_ctl->pgcr[0], 1 << 26); - - for (i = 0; i < 4; i++) { - val = DATX_IOCR_WRITE_DELAY((write >> (16 + i * 4)) & 0xf) | - DATX_IOCR_READ_DELAY((read >> (16 + i * 4)) & 0xf); - - writel(val, &mctl_ctl->datx[i].iocr[DATX_IOCR_DQS]); - writel(val, &mctl_ctl->datx[i].iocr[DATX_IOCR_DQSN]); - } - - setbits_le32(&mctl_ctl->pgcr[0], 1 << 26); - - udelay(1); -} - -static void mctl_set_master_priority(void) -{ - struct sunxi_mctl_com_reg * const mctl_com = - (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; - - /* enable bandwidth limit windows and set windows size 1us */ - writel(0x00010190, &mctl_com->bwcr); - - /* set cpu high priority */ - writel(0x00000001, &mctl_com->mapr); - - writel(0x0200000d, &mctl_com->mcr[0][0]); - writel(0x00800100, &mctl_com->mcr[0][1]); - writel(0x06000009, &mctl_com->mcr[1][0]); - writel(0x01000400, &mctl_com->mcr[1][1]); - writel(0x0200000d, &mctl_com->mcr[2][0]); - writel(0x00600100, &mctl_com->mcr[2][1]); - writel(0x0100000d, &mctl_com->mcr[3][0]); - writel(0x00200080, &mctl_com->mcr[3][1]); - writel(0x07000009, &mctl_com->mcr[4][0]); - writel(0x01000640, &mctl_com->mcr[4][1]); - writel(0x0100000d, &mctl_com->mcr[5][0]); - writel(0x00200080, &mctl_com->mcr[5][1]); - writel(0x01000009, &mctl_com->mcr[6][0]); - writel(0x00400080, &mctl_com->mcr[6][1]); - writel(0x0100000d, &mctl_com->mcr[7][0]); - writel(0x00400080, &mctl_com->mcr[7][1]); - writel(0x0100000d, &mctl_com->mcr[8][0]); - writel(0x00400080, &mctl_com->mcr[8][1]); - writel(0x04000009, &mctl_com->mcr[9][0]); - writel(0x00400100, &mctl_com->mcr[9][1]); - writel(0x2000030d, &mctl_com->mcr[10][0]); - writel(0x04001800, &mctl_com->mcr[10][1]); - writel(0x04000009, &mctl_com->mcr[11][0]); - writel(0x00400120, &mctl_com->mcr[11][1]); -} - -static void mctl_set_timing_params(struct dram_para *para) -{ - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - - u8 tccd = 2; - u8 tfaw = ns_to_t(50); - u8 trrd = max(ns_to_t(10), 4); - u8 trcd = ns_to_t(15); - u8 trc = ns_to_t(53); - u8 txp = max(ns_to_t(8), 3); - u8 twtr = max(ns_to_t(8), 4); - u8 trtp = max(ns_to_t(8), 4); - u8 twr = max(ns_to_t(15), 3); - u8 trp = ns_to_t(15); - u8 tras = ns_to_t(38); - u16 trefi = ns_to_t(7800) / 32; - u16 trfc = ns_to_t(350); - - u8 tmrw = 0; - u8 tmrd = 4; - u8 tmod = 12; - u8 tcke = 3; - u8 tcksrx = 5; - u8 tcksre = 5; - u8 tckesr = 4; - u8 trasmax = 24; - - u8 tcl = 6; /* CL 12 */ - u8 tcwl = 4; /* CWL 8 */ - u8 t_rdata_en = 4; - u8 wr_latency = 2; - - u32 tdinit0 = (500 * CONFIG_DRAM_CLK) + 1; /* 500us */ - u32 tdinit1 = (360 * CONFIG_DRAM_CLK) / 1000 + 1; /* 360ns */ - u32 tdinit2 = (200 * CONFIG_DRAM_CLK) + 1; /* 200us */ - u32 tdinit3 = (1 * CONFIG_DRAM_CLK) + 1; /* 1us */ - - u8 twtp = tcwl + 2 + twr; /* WL + BL / 2 + tWR */ - u8 twr2rd = tcwl + 2 + twtr; /* WL + BL / 2 + tWTR */ - u8 trd2wr = tcl + 2 + 1 - tcwl; /* RL + BL / 2 + 2 - WL */ - - /* set mode register */ - writel(0x1c70, &mctl_ctl->mr[0]); /* CL=11, WR=12 */ - writel(0x40, &mctl_ctl->mr[1]); - writel(0x18, &mctl_ctl->mr[2]); /* CWL=8 */ - writel(0x0, &mctl_ctl->mr[3]); - - /* set DRAM timing */ - writel(DRAMTMG0_TWTP(twtp) | DRAMTMG0_TFAW(tfaw) | - DRAMTMG0_TRAS_MAX(trasmax) | DRAMTMG0_TRAS(tras), - &mctl_ctl->dramtmg[0]); - writel(DRAMTMG1_TXP(txp) | DRAMTMG1_TRTP(trtp) | DRAMTMG1_TRC(trc), - &mctl_ctl->dramtmg[1]); - writel(DRAMTMG2_TCWL(tcwl) | DRAMTMG2_TCL(tcl) | - DRAMTMG2_TRD2WR(trd2wr) | DRAMTMG2_TWR2RD(twr2rd), - &mctl_ctl->dramtmg[2]); - writel(DRAMTMG3_TMRW(tmrw) | DRAMTMG3_TMRD(tmrd) | DRAMTMG3_TMOD(tmod), - &mctl_ctl->dramtmg[3]); - writel(DRAMTMG4_TRCD(trcd) | DRAMTMG4_TCCD(tccd) | DRAMTMG4_TRRD(trrd) | - DRAMTMG4_TRP(trp), &mctl_ctl->dramtmg[4]); - writel(DRAMTMG5_TCKSRX(tcksrx) | DRAMTMG5_TCKSRE(tcksre) | - DRAMTMG5_TCKESR(tckesr) | DRAMTMG5_TCKE(tcke), - &mctl_ctl->dramtmg[5]); - - /* set two rank timing */ - clrsetbits_le32(&mctl_ctl->dramtmg[8], (0xff << 8) | (0xff << 0), - (0x66 << 8) | (0x10 << 0)); - - /* set PHY interface timing, write latency and read latency configure */ - writel((0x2 << 24) | (t_rdata_en << 16) | (0x1 << 8) | - (wr_latency << 0), &mctl_ctl->pitmg[0]); - - /* set PHY timing, PTR0-2 use default */ - writel(PTR3_TDINIT0(tdinit0) | PTR3_TDINIT1(tdinit1), &mctl_ctl->ptr[3]); - writel(PTR4_TDINIT2(tdinit2) | PTR4_TDINIT3(tdinit3), &mctl_ctl->ptr[4]); - - /* set refresh timing */ - writel(RFSHTMG_TREFI(trefi) | RFSHTMG_TRFC(trfc), &mctl_ctl->rfshtmg); -} - -static void mctl_zq_calibration(struct dram_para *para) -{ - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - - int i; - u16 zq_val[6]; - u8 val; - - writel(0x0a0a0a0a, &mctl_ctl->zqdr[2]); - - for (i = 0; i < 6; i++) { - u8 zq = (CONFIG_DRAM_ZQ >> (i * 4)) & 0xf; - - writel((zq << 20) | (zq << 16) | (zq << 12) | - (zq << 8) | (zq << 4) | (zq << 0), - &mctl_ctl->zqcr); - - writel(PIR_CLRSR, &mctl_ctl->pir); - mctl_phy_init(PIR_ZCAL); - - zq_val[i] = readl(&mctl_ctl->zqdr[0]) & 0xff; - writel(REPEAT_BYTE(zq_val[i]), &mctl_ctl->zqdr[2]); - - writel(PIR_CLRSR, &mctl_ctl->pir); - mctl_phy_init(PIR_ZCAL); - - val = readl(&mctl_ctl->zqdr[0]) >> 24; - zq_val[i] |= bin_to_mgray(mgray_to_bin(val) - 1) << 8; - } - - writel((zq_val[1] << 16) | zq_val[0], &mctl_ctl->zqdr[0]); - writel((zq_val[3] << 16) | zq_val[2], &mctl_ctl->zqdr[1]); - writel((zq_val[5] << 16) | zq_val[4], &mctl_ctl->zqdr[2]); -} - -static void mctl_set_cr(struct dram_para *para) -{ - struct sunxi_mctl_com_reg * const mctl_com = - (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; - - writel(MCTL_CR_BL8 | MCTL_CR_2T | MCTL_CR_DDR3 | MCTL_CR_INTERLEAVED | - MCTL_CR_EIGHT_BANKS | MCTL_CR_BUS_WIDTH(para->bus_width) | - (para->dual_rank ? MCTL_CR_DUAL_RANK : MCTL_CR_SINGLE_RANK) | - MCTL_CR_PAGE_SIZE(para->page_size) | - MCTL_CR_ROW_BITS(para->row_bits), &mctl_com->cr); -} - -static void mctl_sys_init(struct dram_para *para) -{ - struct sunxi_ccm_reg * const ccm = - (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - - clrbits_le32(&ccm->mbus0_clk_cfg, MBUS_CLK_GATE); - clrbits_le32(&ccm->mbus_reset, CCM_MBUS_RESET_RESET); - clrbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL); - clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL); - clrbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_EN); - udelay(10); - - clrbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST); - udelay(1000); - - clock_set_pll5(CONFIG_DRAM_CLK * 2 * 1000000, false); - clrsetbits_le32(&ccm->dram_clk_cfg, - CCM_DRAMCLK_CFG_DIV_MASK | CCM_DRAMCLK_CFG_SRC_MASK, - CCM_DRAMCLK_CFG_DIV(1) | CCM_DRAMCLK_CFG_SRC_PLL5 | - CCM_DRAMCLK_CFG_UPD); - mctl_await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0); - - setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL); - setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL); - setbits_le32(&ccm->mbus_reset, CCM_MBUS_RESET_RESET); - setbits_le32(&ccm->mbus0_clk_cfg, MBUS_CLK_GATE); - - setbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST); - udelay(10); - - writel(0xc00e, &mctl_ctl->clken); - udelay(500); -} - -static int mctl_channel_init(struct dram_para *para) -{ - struct sunxi_mctl_com_reg * const mctl_com = - (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - - unsigned int i; - - mctl_set_cr(para); - mctl_set_timing_params(para); - mctl_set_master_priority(); - - /* setting VTC, default disable all VT */ - clrbits_le32(&mctl_ctl->pgcr[0], (1 << 30) | 0x3f); - clrsetbits_le32(&mctl_ctl->pgcr[1], 1 << 24, 1 << 26); - - /* increase DFI_PHY_UPD clock */ - writel(PROTECT_MAGIC, &mctl_com->protect); - udelay(100); - clrsetbits_le32(&mctl_ctl->upd2, 0xfff << 16, 0x50 << 16); - writel(0x0, &mctl_com->protect); - udelay(100); - - /* set dramc odt */ - for (i = 0; i < 4; i++) - clrsetbits_le32(&mctl_ctl->datx[i].gcr, (0x3 << 4) | - (0x1 << 1) | (0x3 << 2) | (0x3 << 12) | - (0x3 << 14), - IS_ENABLED(CONFIG_DRAM_ODT_EN) ? 0x0 : 0x2); - - /* AC PDR should always ON */ - setbits_le32(&mctl_ctl->aciocr, 0x1 << 1); - - /* set DQS auto gating PD mode */ - setbits_le32(&mctl_ctl->pgcr[2], 0x3 << 6); - - /* dx ddr_clk & hdr_clk dynamic mode */ - clrbits_le32(&mctl_ctl->pgcr[0], (0x3 << 14) | (0x3 << 12)); - - /* dphy & aphy phase select 270 degree */ - clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8), - (0x1 << 10) | (0x2 << 8)); - - /* set half DQ */ - if (para->bus_width != 32) { - writel(0x0, &mctl_ctl->datx[2].gcr); - writel(0x0, &mctl_ctl->datx[3].gcr); - } - - /* data training configuration */ - clrsetbits_le32(&mctl_ctl->dtcr, 0xf << 24, - (para->dual_rank ? 0x3 : 0x1) << 24); - - - if (para->read_delays || para->write_delays) { - mctl_dq_delay(para->read_delays, para->write_delays); - udelay(50); - } - - mctl_zq_calibration(para); - - mctl_phy_init(PIR_PLLINIT | PIR_DCAL | PIR_PHYRST | PIR_DRAMRST | - PIR_DRAMINIT | PIR_QSGATE); - - /* detect ranks and bus width */ - if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20)) { - /* only one rank */ - if (((readl(&mctl_ctl->datx[0].gsr[0]) >> 24) & 0x2) || - ((readl(&mctl_ctl->datx[1].gsr[0]) >> 24) & 0x2)) { - clrsetbits_le32(&mctl_ctl->dtcr, 0xf << 24, 0x1 << 24); - para->dual_rank = 0; - } - - /* only half DQ width */ - if (((readl(&mctl_ctl->datx[2].gsr[0]) >> 24) & 0x1) || - ((readl(&mctl_ctl->datx[3].gsr[0]) >> 24) & 0x1)) { - writel(0x0, &mctl_ctl->datx[2].gcr); - writel(0x0, &mctl_ctl->datx[3].gcr); - para->bus_width = 16; - } - - mctl_set_cr(para); - udelay(20); - - /* re-train */ - mctl_phy_init(PIR_QSGATE); - if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20)) - return 1; - } - - /* check the dramc status */ - mctl_await_completion(&mctl_ctl->statr, 0x1, 0x1); - - /* liuke added for refresh debug */ - setbits_le32(&mctl_ctl->rfshctl0, 0x1 << 31); - udelay(10); - clrbits_le32(&mctl_ctl->rfshctl0, 0x1 << 31); - udelay(10); - - /* set PGCR3, CKE polarity */ - writel(0x00aa0060, &mctl_ctl->pgcr[3]); - - /* power down zq calibration module for power save */ - setbits_le32(&mctl_ctl->zqcr, ZQCR_PWRDOWN); - - /* enable master access */ - writel(0xffffffff, &mctl_com->maer); - - return 0; -} - -static void mctl_auto_detect_dram_size(struct dram_para *para) -{ - /* detect row address bits */ - para->page_size = 512; - para->row_bits = 16; - mctl_set_cr(para); - - for (para->row_bits = 11; para->row_bits < 16; para->row_bits++) - if (mctl_mem_matches((1 << (para->row_bits + 3)) * para->page_size)) - break; - - /* detect page size */ - para->page_size = 8192; - mctl_set_cr(para); - - for (para->page_size = 512; para->page_size < 8192; para->page_size *= 2) - if (mctl_mem_matches(para->page_size)) - break; -} - -unsigned long sunxi_dram_init(void) -{ - struct sunxi_mctl_com_reg * const mctl_com = - (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; - struct sunxi_mctl_ctl_reg * const mctl_ctl = - (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; - - struct dram_para para = { - .read_delays = 0x00007979, /* dram_tpr12 */ - .write_delays = 0x6aaa0000, /* dram_tpr11 */ - .dual_rank = 0, - .bus_width = 32, - .row_bits = 15, - .page_size = 4096, - }; - - mctl_sys_init(¶); - if (mctl_channel_init(¶)) - return 0; - - if (para.dual_rank) - writel(0x00000303, &mctl_ctl->odtmap); - else - writel(0x00000201, &mctl_ctl->odtmap); - udelay(1); - - /* odt delay */ - writel(0x0c000400, &mctl_ctl->odtcfg); - - /* clear credit value */ - setbits_le32(&mctl_com->cccr, 1 << 31); - udelay(10); - - mctl_auto_detect_dram_size(¶); - mctl_set_cr(¶); - - return (1 << (para.row_bits + 3)) * para.page_size * - (para.dual_rank ? 2 : 1); -} diff --git a/arch/arm/cpu/armv7/sunxi/p2wi.c b/arch/arm/cpu/armv7/sunxi/p2wi.c deleted file mode 100644 index 26a9cfc68b..0000000000 --- a/arch/arm/cpu/armv7/sunxi/p2wi.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Sunxi A31 Power Management Unit - * - * (C) Copyright 2013 Oliver Schinagl - * http://linux-sunxi.org - * - * Based on sun6i sources and earlier U-Boot Allwiner A10 SPL work - * - * (C) Copyright 2006-2013 - * Allwinner Technology Co., Ltd. - * Berg Xing - * Tom Cubie - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void p2wi_init(void) -{ - struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE; - - /* Enable p2wi and PIO clk, and de-assert their resets */ - prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_P2WI); - - sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN6I_GPL0_R_P2WI_SCK); - sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN6I_GPL1_R_P2WI_SDA); - - /* Reset p2wi controller and set clock to CLKIN(12)/8 = 1.5 MHz */ - writel(P2WI_CTRL_RESET, &p2wi->ctrl); - sdelay(0x100); - writel(P2WI_CC_SDA_OUT_DELAY(1) | P2WI_CC_CLK_DIV(8), - &p2wi->cc); -} - -int p2wi_change_to_p2wi_mode(u8 slave_addr, u8 ctrl_reg, u8 init_data) -{ - struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE; - unsigned long tmo = timer_get_us() + 1000000; - - writel(P2WI_PM_DEV_ADDR(slave_addr) | - P2WI_PM_CTRL_ADDR(ctrl_reg) | - P2WI_PM_INIT_DATA(init_data) | - P2WI_PM_INIT_SEND, - &p2wi->pm); - - while ((readl(&p2wi->pm) & P2WI_PM_INIT_SEND)) { - if (timer_get_us() > tmo) - return -ETIME; - } - - return 0; -} - -static int p2wi_await_trans(void) -{ - struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE; - unsigned long tmo = timer_get_us() + 1000000; - int ret; - u8 reg; - - while (1) { - reg = readl(&p2wi->status); - if (reg & P2WI_STAT_TRANS_ERR) { - ret = -EIO; - break; - } - if (reg & P2WI_STAT_TRANS_DONE) { - ret = 0; - break; - } - if (timer_get_us() > tmo) { - ret = -ETIME; - break; - } - } - writel(reg, &p2wi->status); /* Clear status bits */ - return ret; -} - -int p2wi_read(const u8 addr, u8 *data) -{ - struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE; - int ret; - - writel(P2WI_DATADDR_BYTE_1(addr), &p2wi->dataddr0); - writel(P2WI_DATA_NUM_BYTES(1) | - P2WI_DATA_NUM_BYTES_READ, &p2wi->numbytes); - writel(P2WI_STAT_TRANS_DONE, &p2wi->status); - writel(P2WI_CTRL_TRANS_START, &p2wi->ctrl); - - ret = p2wi_await_trans(); - - *data = readl(&p2wi->data0) & P2WI_DATA_BYTE_1_MASK; - return ret; -} - -int p2wi_write(const u8 addr, u8 data) -{ - struct sunxi_p2wi_reg *p2wi = (struct sunxi_p2wi_reg *)SUN6I_P2WI_BASE; - - writel(P2WI_DATADDR_BYTE_1(addr), &p2wi->dataddr0); - writel(P2WI_DATA_BYTE_1(data), &p2wi->data0); - writel(P2WI_DATA_NUM_BYTES(1), &p2wi->numbytes); - writel(P2WI_STAT_TRANS_DONE, &p2wi->status); - writel(P2WI_CTRL_TRANS_START, &p2wi->ctrl); - - return p2wi_await_trans(); -} diff --git a/arch/arm/cpu/armv7/sunxi/pinmux.c b/arch/arm/cpu/armv7/sunxi/pinmux.c deleted file mode 100644 index b026f78ca5..0000000000 --- a/arch/arm/cpu/armv7/sunxi/pinmux.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * (C) Copyright 2007-2011 - * Allwinner Technology Co., Ltd. - * Tom Cubie - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include - -void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val) -{ - u32 index = GPIO_CFG_INDEX(bank_offset); - u32 offset = GPIO_CFG_OFFSET(bank_offset); - - clrsetbits_le32(&pio->cfg[0] + index, 0xf << offset, val << offset); -} - -void sunxi_gpio_set_cfgpin(u32 pin, u32 val) -{ - u32 bank = GPIO_BANK(pin); - struct sunxi_gpio *pio = BANK_TO_GPIO(bank); - - sunxi_gpio_set_cfgbank(pio, pin, val); -} - -int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset) -{ - u32 index = GPIO_CFG_INDEX(bank_offset); - u32 offset = GPIO_CFG_OFFSET(bank_offset); - u32 cfg; - - cfg = readl(&pio->cfg[0] + index); - cfg >>= offset; - - return cfg & 0xf; -} - -int sunxi_gpio_get_cfgpin(u32 pin) -{ - u32 bank = GPIO_BANK(pin); - struct sunxi_gpio *pio = BANK_TO_GPIO(bank); - - return sunxi_gpio_get_cfgbank(pio, pin); -} - -int sunxi_gpio_set_drv(u32 pin, u32 val) -{ - u32 bank = GPIO_BANK(pin); - u32 index = GPIO_DRV_INDEX(pin); - u32 offset = GPIO_DRV_OFFSET(pin); - struct sunxi_gpio *pio = BANK_TO_GPIO(bank); - - clrsetbits_le32(&pio->drv[0] + index, 0x3 << offset, val << offset); - - return 0; -} - -int sunxi_gpio_set_pull(u32 pin, u32 val) -{ - u32 bank = GPIO_BANK(pin); - u32 index = GPIO_PULL_INDEX(pin); - u32 offset = GPIO_PULL_OFFSET(pin); - struct sunxi_gpio *pio = BANK_TO_GPIO(bank); - - clrsetbits_le32(&pio->pull[0] + index, 0x3 << offset, val << offset); - - return 0; -} diff --git a/arch/arm/cpu/armv7/sunxi/pmic_bus.c b/arch/arm/cpu/armv7/sunxi/pmic_bus.c deleted file mode 100644 index 5b81a8d8e1..0000000000 --- a/arch/arm/cpu/armv7/sunxi/pmic_bus.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * (C) Copyright 2015 Hans de Goede - * - * Sunxi PMIC bus access helpers - * - * The axp152 & axp209 use an i2c bus, the axp221 uses the p2wi bus and the - * axp223 uses the rsb bus, these functions abstract this. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include - -#define AXP152_I2C_ADDR 0x30 - -#define AXP209_I2C_ADDR 0x34 - -#define AXP221_CHIP_ADDR 0x68 -#define AXP221_CTRL_ADDR 0x3e -#define AXP221_INIT_DATA 0x3e - -/* AXP818 device and runtime addresses are same as AXP223 */ -#define AXP223_DEVICE_ADDR 0x3a3 -#define AXP223_RUNTIME_ADDR 0x2d - -int pmic_bus_init(void) -{ - /* This cannot be 0 because it is used in SPL before BSS is ready */ - static int needs_init = 1; - __maybe_unused int ret; - - if (!needs_init) - return 0; - -#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP818_POWER -# ifdef CONFIG_MACH_SUN6I - p2wi_init(); - ret = p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR, - AXP221_INIT_DATA); -# else - ret = rsb_init(); - if (ret) - return ret; - - ret = rsb_set_device_address(AXP223_DEVICE_ADDR, AXP223_RUNTIME_ADDR); -# endif - if (ret) - return ret; -#endif - - needs_init = 0; - return 0; -} - -int pmic_bus_read(u8 reg, u8 *data) -{ -#ifdef CONFIG_AXP152_POWER - return i2c_read(AXP152_I2C_ADDR, reg, 1, data, 1); -#elif defined CONFIG_AXP209_POWER - return i2c_read(AXP209_I2C_ADDR, reg, 1, data, 1); -#elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP818_POWER -# ifdef CONFIG_MACH_SUN6I - return p2wi_read(reg, data); -# else - return rsb_read(AXP223_RUNTIME_ADDR, reg, data); -# endif -#endif -} - -int pmic_bus_write(u8 reg, u8 data) -{ -#ifdef CONFIG_AXP152_POWER - return i2c_write(AXP152_I2C_ADDR, reg, 1, &data, 1); -#elif defined CONFIG_AXP209_POWER - return i2c_write(AXP209_I2C_ADDR, reg, 1, &data, 1); -#elif defined CONFIG_AXP221_POWER || defined CONFIG_AXP818_POWER -# ifdef CONFIG_MACH_SUN6I - return p2wi_write(reg, data); -# else - return rsb_write(AXP223_RUNTIME_ADDR, reg, data); -# endif -#endif -} - -int pmic_bus_setbits(u8 reg, u8 bits) -{ - int ret; - u8 val; - - ret = pmic_bus_read(reg, &val); - if (ret) - return ret; - - val |= bits; - return pmic_bus_write(reg, val); -} - -int pmic_bus_clrbits(u8 reg, u8 bits) -{ - int ret; - u8 val; - - ret = pmic_bus_read(reg, &val); - if (ret) - return ret; - - val &= ~bits; - return pmic_bus_write(reg, val); -} diff --git a/arch/arm/cpu/armv7/sunxi/prcm.c b/arch/arm/cpu/armv7/sunxi/prcm.c deleted file mode 100644 index e1d091fd57..0000000000 --- a/arch/arm/cpu/armv7/sunxi/prcm.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Sunxi A31 Power Management Unit - * - * (C) Copyright 2013 Oliver Schinagl - * http://linux-sunxi.org - * - * Based on sun6i sources and earlier U-Boot Allwinner A10 SPL work - * - * (C) Copyright 2006-2013 - * Allwinner Technology Co., Ltd. - * Berg Xing - * Tom Cubie - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include - -/* APB0 clock gate and reset bit offsets are the same. */ -void prcm_apb0_enable(u32 flags) -{ - struct sunxi_prcm_reg *prcm = - (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE; - - /* open the clock for module */ - setbits_le32(&prcm->apb0_gate, flags); - - /* deassert reset for module */ - setbits_le32(&prcm->apb0_reset, flags); -} - -void prcm_apb0_disable(u32 flags) -{ - struct sunxi_prcm_reg *prcm = - (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE; - - /* assert reset for module */ - clrbits_le32(&prcm->apb0_reset, flags); - - /* close the clock for module */ - clrbits_le32(&prcm->apb0_gate, flags); -} diff --git a/arch/arm/cpu/armv7/sunxi/rsb.c b/arch/arm/cpu/armv7/sunxi/rsb.c deleted file mode 100644 index 6fd11f1529..0000000000 --- a/arch/arm/cpu/armv7/sunxi/rsb.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * (C) Copyright 2014 Hans de Goede - * - * Based on allwinner u-boot sources rsb code which is: - * (C) Copyright 2007-2013 - * Allwinner Technology Co., Ltd. - * lixiang - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include - -static int rsb_set_device_mode(void); - -static void rsb_cfg_io(void) -{ -#ifdef CONFIG_MACH_SUN8I - sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_GPL_R_RSB); - sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN8I_GPL_R_RSB); - sunxi_gpio_set_pull(SUNXI_GPL(0), 1); - sunxi_gpio_set_pull(SUNXI_GPL(1), 1); - sunxi_gpio_set_drv(SUNXI_GPL(0), 2); - sunxi_gpio_set_drv(SUNXI_GPL(1), 2); -#elif defined CONFIG_MACH_SUN9I - sunxi_gpio_set_cfgpin(SUNXI_GPN(0), SUN9I_GPN_R_RSB); - sunxi_gpio_set_cfgpin(SUNXI_GPN(1), SUN9I_GPN_R_RSB); - sunxi_gpio_set_pull(SUNXI_GPN(0), 1); - sunxi_gpio_set_pull(SUNXI_GPN(1), 1); - sunxi_gpio_set_drv(SUNXI_GPN(0), 2); - sunxi_gpio_set_drv(SUNXI_GPN(1), 2); -#else -#error unsupported MACH_SUNXI -#endif -} - -static void rsb_set_clk(void) -{ - struct sunxi_rsb_reg * const rsb = - (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; - u32 div = 0; - u32 cd_odly = 0; - - /* Source is Hosc24M, set RSB clk to 3Mhz */ - div = 24000000 / 3000000 / 2 - 1; - cd_odly = div >> 1; - if (!cd_odly) - cd_odly = 1; - - writel((cd_odly << 8) | div, &rsb->ccr); -} - -int rsb_init(void) -{ - struct sunxi_rsb_reg * const rsb = - (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; - - /* Enable RSB and PIO clk, and de-assert their resets */ - prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_RSB); - - /* Setup external pins */ - rsb_cfg_io(); - - writel(RSB_CTRL_SOFT_RST, &rsb->ctrl); - rsb_set_clk(); - - return rsb_set_device_mode(); -} - -static int rsb_await_trans(void) -{ - struct sunxi_rsb_reg * const rsb = - (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; - unsigned long tmo = timer_get_us() + 1000000; - u32 stat; - int ret; - - while (1) { - stat = readl(&rsb->stat); - if (stat & RSB_STAT_LBSY_INT) { - ret = -EBUSY; - break; - } - if (stat & RSB_STAT_TERR_INT) { - ret = -EIO; - break; - } - if (stat & RSB_STAT_TOVER_INT) { - ret = 0; - break; - } - if (timer_get_us() > tmo) { - ret = -ETIME; - break; - } - } - writel(stat, &rsb->stat); /* Clear status bits */ - - return ret; -} - -static int rsb_set_device_mode(void) -{ - struct sunxi_rsb_reg * const rsb = - (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; - unsigned long tmo = timer_get_us() + 1000000; - - writel(RSB_DMCR_DEVICE_MODE_START | RSB_DMCR_DEVICE_MODE_DATA, - &rsb->dmcr); - - while (readl(&rsb->dmcr) & RSB_DMCR_DEVICE_MODE_START) { - if (timer_get_us() > tmo) - return -ETIME; - } - - return rsb_await_trans(); -} - -static int rsb_do_trans(void) -{ - struct sunxi_rsb_reg * const rsb = - (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; - - setbits_le32(&rsb->ctrl, RSB_CTRL_START_TRANS); - return rsb_await_trans(); -} - -int rsb_set_device_address(u16 device_addr, u16 runtime_addr) -{ - struct sunxi_rsb_reg * const rsb = - (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; - - writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_addr) | - RSB_DEVADDR_DEVICE_ADDR(device_addr), &rsb->devaddr); - writel(RSB_CMD_SET_RTSADDR, &rsb->cmd); - - return rsb_do_trans(); -} - -int rsb_write(const u16 runtime_device_addr, const u8 reg_addr, u8 data) -{ - struct sunxi_rsb_reg * const rsb = - (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; - - writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_device_addr), &rsb->devaddr); - writel(reg_addr, &rsb->addr); - writel(data, &rsb->data); - writel(RSB_CMD_BYTE_WRITE, &rsb->cmd); - - return rsb_do_trans(); -} - -int rsb_read(const u16 runtime_device_addr, const u8 reg_addr, u8 *data) -{ - struct sunxi_rsb_reg * const rsb = - (struct sunxi_rsb_reg *)SUNXI_RSB_BASE; - int ret; - - writel(RSB_DEVADDR_RUNTIME_ADDR(runtime_device_addr), &rsb->devaddr); - writel(reg_addr, &rsb->addr); - writel(RSB_CMD_BYTE_READ, &rsb->cmd); - - ret = rsb_do_trans(); - if (ret) - return ret; - - *data = readl(&rsb->data) & 0xff; - - return 0; -} diff --git a/arch/arm/cpu/armv7/sunxi/usb_phy.c b/arch/arm/cpu/armv7/sunxi/usb_phy.c deleted file mode 100644 index fa375f1d16..0000000000 --- a/arch/arm/cpu/armv7/sunxi/usb_phy.c +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Sunxi usb-phy code - * - * Copyright (C) 2015 Hans de Goede - * Copyright (C) 2014 Roman Byshko - * - * Based on code from - * Allwinner Technology Co., Ltd. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include - -#define SUNXI_USB_PMU_IRQ_ENABLE 0x800 -#ifdef CONFIG_MACH_SUN8I_A33 -#define SUNXI_USB_CSR 0x410 -#else -#define SUNXI_USB_CSR 0x404 -#endif -#define SUNXI_USB_PASSBY_EN 1 - -#define SUNXI_EHCI_AHB_ICHR8_EN (1 << 10) -#define SUNXI_EHCI_AHB_INCR4_BURST_EN (1 << 9) -#define SUNXI_EHCI_AHB_INCRX_ALIGN_EN (1 << 8) -#define SUNXI_EHCI_ULPI_BYPASS_EN (1 << 0) - -#define REG_PHY_UNK_H3 0x420 -#define REG_PMU_UNK_H3 0x810 - -/* A83T specific control bits for PHY0 */ -#define SUNXI_PHY_CTL_VBUSVLDEXT BIT(5) -#define SUNXI_PHY_CTL_SIDDQ BIT(3) - -/* A83T HSIC specific bits */ -#define SUNXI_EHCI_HS_FORCE BIT(20) -#define SUNXI_EHCI_CONNECT_DET BIT(17) -#define SUNXI_EHCI_CONNECT_INT BIT(16) -#define SUNXI_EHCI_HSIC BIT(1) - -static struct sunxi_usb_phy { - int usb_rst_mask; - int gpio_vbus; - int gpio_vbus_det; - int gpio_id_det; - int id; - int init_count; - int power_on_count; - int base; -} sunxi_usb_phy[] = { - { - .usb_rst_mask = CCM_USB_CTRL_PHY0_RST | CCM_USB_CTRL_PHY0_CLK, - .id = 0, - .base = SUNXI_USB0_BASE, - }, - { - .usb_rst_mask = CCM_USB_CTRL_PHY1_RST | CCM_USB_CTRL_PHY1_CLK, - .id = 1, - .base = SUNXI_USB1_BASE, - }, -#if CONFIG_SUNXI_USB_PHYS >= 3 - { -#ifdef CONFIG_MACH_SUN8I_A83T - .usb_rst_mask = CCM_USB_CTRL_HSIC_RST | CCM_USB_CTRL_HSIC_CLK | - CCM_USB_CTRL_12M_CLK, -#else - .usb_rst_mask = CCM_USB_CTRL_PHY2_RST | CCM_USB_CTRL_PHY2_CLK, -#endif - .id = 2, - .base = SUNXI_USB2_BASE, - }, -#endif -#if CONFIG_SUNXI_USB_PHYS >= 4 - { - .usb_rst_mask = CCM_USB_CTRL_PHY3_RST | CCM_USB_CTRL_PHY3_CLK, - .id = 3, - .base = SUNXI_USB3_BASE, - } -#endif -}; - -static int get_vbus_gpio(int index) -{ - switch (index) { - case 0: return sunxi_name_to_gpio(CONFIG_USB0_VBUS_PIN); - case 1: return sunxi_name_to_gpio(CONFIG_USB1_VBUS_PIN); - case 2: return sunxi_name_to_gpio(CONFIG_USB2_VBUS_PIN); - case 3: return sunxi_name_to_gpio(CONFIG_USB3_VBUS_PIN); - } - return -EINVAL; -} - -static int get_vbus_detect_gpio(int index) -{ - switch (index) { - case 0: return sunxi_name_to_gpio(CONFIG_USB0_VBUS_DET); - } - return -EINVAL; -} - -static int get_id_detect_gpio(int index) -{ - switch (index) { - case 0: return sunxi_name_to_gpio(CONFIG_USB0_ID_DET); - } - return -EINVAL; -} - -__maybe_unused static void usb_phy_write(struct sunxi_usb_phy *phy, int addr, - int data, int len) -{ - int j = 0, usbc_bit = 0; - void *dest = (void *)SUNXI_USB0_BASE + SUNXI_USB_CSR; - -#ifdef CONFIG_MACH_SUN8I_A33 - /* CSR needs to be explicitly initialized to 0 on A33 */ - writel(0, dest); -#endif - - usbc_bit = 1 << (phy->id * 2); - for (j = 0; j < len; j++) { - /* set the bit address to be written */ - clrbits_le32(dest, 0xff << 8); - setbits_le32(dest, (addr + j) << 8); - - clrbits_le32(dest, usbc_bit); - /* set data bit */ - if (data & 0x1) - setbits_le32(dest, 1 << 7); - else - clrbits_le32(dest, 1 << 7); - - setbits_le32(dest, usbc_bit); - - clrbits_le32(dest, usbc_bit); - - data >>= 1; - } -} - -#if defined CONFIG_MACH_SUN8I_H3 -static void sunxi_usb_phy_config(struct sunxi_usb_phy *phy) -{ - if (phy->id == 0) - clrbits_le32(SUNXI_USBPHY_BASE + REG_PHY_UNK_H3, 0x01); - - clrbits_le32(phy->base + REG_PMU_UNK_H3, 0x02); -} -#elif defined CONFIG_MACH_SUN8I_A83T -static void sunxi_usb_phy_config(struct sunxi_usb_phy *phy) -{ -} -#else -static void sunxi_usb_phy_config(struct sunxi_usb_phy *phy) -{ - /* The following comments are machine - * translated from Chinese, you have been warned! - */ - - /* Regulation 45 ohms */ - if (phy->id == 0) - usb_phy_write(phy, 0x0c, 0x01, 1); - - /* adjust PHY's magnitude and rate */ - usb_phy_write(phy, 0x20, 0x14, 5); - - /* threshold adjustment disconnect */ -#if defined CONFIG_MACH_SUN5I || defined CONFIG_MACH_SUN7I - usb_phy_write(phy, 0x2a, 2, 2); -#else - usb_phy_write(phy, 0x2a, 3, 2); -#endif - - return; -} -#endif - -static void sunxi_usb_phy_passby(struct sunxi_usb_phy *phy, int enable) -{ - unsigned long bits = 0; - void *addr; - - addr = (void *)phy->base + SUNXI_USB_PMU_IRQ_ENABLE; - - bits = SUNXI_EHCI_AHB_ICHR8_EN | - SUNXI_EHCI_AHB_INCR4_BURST_EN | - SUNXI_EHCI_AHB_INCRX_ALIGN_EN | - SUNXI_EHCI_ULPI_BYPASS_EN; - -#ifdef CONFIG_MACH_SUN8I_A83T - if (phy->id == 2) - bits |= SUNXI_EHCI_HS_FORCE | - SUNXI_EHCI_CONNECT_INT | - SUNXI_EHCI_HSIC; -#endif - - if (enable) - setbits_le32(addr, bits); - else - clrbits_le32(addr, bits); - - return; -} - -void sunxi_usb_phy_enable_squelch_detect(int index, int enable) -{ -#ifndef CONFIG_MACH_SUN8I_A83T - struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; - - usb_phy_write(phy, 0x3c, enable ? 0 : 2, 2); -#endif -} - -void sunxi_usb_phy_init(int index) -{ - struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - - phy->init_count++; - if (phy->init_count != 1) - return; - - setbits_le32(&ccm->usb_clk_cfg, phy->usb_rst_mask); - - sunxi_usb_phy_config(phy); - - if (phy->id != 0) - sunxi_usb_phy_passby(phy, SUNXI_USB_PASSBY_EN); - -#ifdef CONFIG_MACH_SUN8I_A83T - if (phy->id == 0) { - setbits_le32(SUNXI_USB0_BASE + SUNXI_USB_CSR, - SUNXI_PHY_CTL_VBUSVLDEXT); - clrbits_le32(SUNXI_USB0_BASE + SUNXI_USB_CSR, - SUNXI_PHY_CTL_SIDDQ); - } -#endif -} - -void sunxi_usb_phy_exit(int index) -{ - struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - - phy->init_count--; - if (phy->init_count != 0) - return; - - if (phy->id != 0) - sunxi_usb_phy_passby(phy, !SUNXI_USB_PASSBY_EN); - -#ifdef CONFIG_MACH_SUN8I_A83T - if (phy->id == 0) { - setbits_le32(SUNXI_USB0_BASE + SUNXI_USB_CSR, - SUNXI_PHY_CTL_SIDDQ); - } -#endif - - clrbits_le32(&ccm->usb_clk_cfg, phy->usb_rst_mask); -} - -void sunxi_usb_phy_power_on(int index) -{ - struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; - - phy->power_on_count++; - if (phy->power_on_count != 1) - return; - - if (phy->gpio_vbus >= 0) - gpio_set_value(phy->gpio_vbus, 1); -} - -void sunxi_usb_phy_power_off(int index) -{ - struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; - - phy->power_on_count--; - if (phy->power_on_count != 0) - return; - - if (phy->gpio_vbus >= 0) - gpio_set_value(phy->gpio_vbus, 0); -} - -int sunxi_usb_phy_power_is_on(int index) -{ - struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; - - return phy->power_on_count > 0; -} - -int sunxi_usb_phy_vbus_detect(int index) -{ - struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; - int err, retries = 3; - - if (phy->gpio_vbus_det < 0) - return phy->gpio_vbus_det; - - err = gpio_get_value(phy->gpio_vbus_det); - /* - * Vbus may have been provided by the board and just been turned of - * some milliseconds ago on reset, what we're measuring then is a - * residual charge on Vbus, sleep a bit and try again. - */ - while (err > 0 && retries--) { - mdelay(100); - err = gpio_get_value(phy->gpio_vbus_det); - } - - return err; -} - -int sunxi_usb_phy_id_detect(int index) -{ - struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; - - if (phy->gpio_id_det < 0) - return phy->gpio_id_det; - - return gpio_get_value(phy->gpio_id_det); -} - -int sunxi_usb_phy_probe(void) -{ - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - struct sunxi_usb_phy *phy; - int i, ret = 0; - - for (i = 0; i < CONFIG_SUNXI_USB_PHYS; i++) { - phy = &sunxi_usb_phy[i]; - - phy->gpio_vbus = get_vbus_gpio(i); - if (phy->gpio_vbus >= 0) { - ret = gpio_request(phy->gpio_vbus, "usb_vbus"); - if (ret) - return ret; - ret = gpio_direction_output(phy->gpio_vbus, 0); - if (ret) - return ret; - } - - phy->gpio_vbus_det = get_vbus_detect_gpio(i); - if (phy->gpio_vbus_det >= 0) { - ret = gpio_request(phy->gpio_vbus_det, "usb_vbus_det"); - if (ret) - return ret; - ret = gpio_direction_input(phy->gpio_vbus_det); - if (ret) - return ret; - } - - phy->gpio_id_det = get_id_detect_gpio(i); - if (phy->gpio_id_det >= 0) { - ret = gpio_request(phy->gpio_id_det, "usb_id_det"); - if (ret) - return ret; - ret = gpio_direction_input(phy->gpio_id_det); - if (ret) - return ret; - sunxi_gpio_set_pull(phy->gpio_id_det, - SUNXI_GPIO_PULL_UP); - } - } - - setbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE); - - return 0; -} - -int sunxi_usb_phy_remove(void) -{ - struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - struct sunxi_usb_phy *phy; - int i; - - clrbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE); - - for (i = 0; i < CONFIG_SUNXI_USB_PHYS; i++) { - phy = &sunxi_usb_phy[i]; - - if (phy->gpio_vbus >= 0) - gpio_free(phy->gpio_vbus); - - if (phy->gpio_vbus_det >= 0) - gpio_free(phy->gpio_vbus_det); - - if (phy->gpio_id_det >= 0) - gpio_free(phy->gpio_id_det); - } - - return 0; -} -- cgit