From 813598e3b46601d6dd8d373e689f60f7c60fbb48 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 19 May 2015 23:34:00 +0200 Subject: sunxi: Use axp221 sid on a33 Unlike the A31 and the A23 the A33 actually has a SID inside the SoC again, but sid[3] is 0 (at least on some SoCs), so it is better to use the axp221 sid. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- arch/arm/cpu/armv7/sunxi/cpu_info.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/cpu/armv7/sunxi/cpu_info.c b/arch/arm/cpu/armv7/sunxi/cpu_info.c index 30ec4ac..8e8c84f 100644 --- a/arch/arm/cpu/armv7/sunxi/cpu_info.c +++ b/arch/arm/cpu/armv7/sunxi/cpu_info.c @@ -78,18 +78,16 @@ int print_cpuinfo(void) int sunxi_get_sid(unsigned int *sid) { -#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I_A23 #ifdef CONFIG_AXP221_POWER return axp221_get_sid(sid); -#else - return -ENODEV; -#endif -#else +#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 } -- cgit v1.1 From 93fc39a7c3ec5d4ed9f1b75cdbac641c3fe12369 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 19 May 2015 21:44:44 +0200 Subject: sunxi: Remove support for building "old-fashioned" fel binaries The latest versions of the fel tool support loading normal u-boot builds directly, and this is now the preferred way to use the fel boot method. This commit removes support for the old deprecated standalone fel builds. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- arch/arm/cpu/armv7/sunxi/board.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c index e6730c0..75ce7b5 100644 --- a/arch/arm/cpu/armv7/sunxi/board.c +++ b/arch/arm/cpu/armv7/sunxi/board.c @@ -120,13 +120,6 @@ void s_init(void) */ u32 spl_boot_device(void) { -#ifdef CONFIG_SPL_FEL - /* - * This is the legacy compile time configuration for a special FEL - * enabled build. It has many restrictions and can only boot over USB. - */ - return BOOT_DEVICE_BOARD; -#else /* * When booting from the SD card, the "eGON.BT0" signature is expected * to be found in memory at the address 0x0004 (see the "mksunxiboot" @@ -147,7 +140,6 @@ u32 spl_boot_device(void) return BOOT_DEVICE_MMC1; else return BOOT_DEVICE_BOARD; -#endif } /* No confirmation data available in SPL yet. Hardcode bootmode */ -- cgit v1.1 From 1871a8ca62a9f1a3c339b04850a486cf723a4134 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 13 Jan 2015 19:25:06 +0100 Subject: sun9i: Basic sun9i (A80) support Add initial sun9i (A80) support, only uart + mmc are supported for now. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- arch/arm/cpu/armv7/sunxi/Makefile | 2 ++ arch/arm/cpu/armv7/sunxi/board.c | 4 ++++ arch/arm/cpu/armv7/sunxi/cpu_info.c | 3 +++ arch/arm/include/asm/arch-sunxi/gpio.h | 1 + 4 files changed, 10 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile index 6a0299f..7ef6b4c 100644 --- a/arch/arm/cpu/armv7/sunxi/Makefile +++ b/arch/arm/cpu/armv7/sunxi/Makefile @@ -13,7 +13,9 @@ 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 diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c index 75ce7b5..23aa249 100644 --- a/arch/arm/cpu/armv7/sunxi/board.c +++ b/arch/arm/cpu/armv7/sunxi/board.c @@ -64,6 +64,10 @@ static int gpio_init(void) 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_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); diff --git a/arch/arm/cpu/armv7/sunxi/cpu_info.c b/arch/arm/cpu/armv7/sunxi/cpu_info.c index 8e8c84f..a276fad 100644 --- a/arch/arm/cpu/armv7/sunxi/cpu_info.c +++ b/arch/arm/cpu/armv7/sunxi/cpu_info.c @@ -11,6 +11,7 @@ #include #include #include +#include #ifdef CONFIG_MACH_SUN6I int sunxi_get_ss_bonding_id(void) @@ -68,6 +69,8 @@ int print_cpuinfo(void) puts("CPU: Allwinner A23 (SUN8I)\n"); #elif defined CONFIG_MACH_SUN8I_A33 puts("CPU: Allwinner A33 (SUN8I)\n"); +#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"); diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h index 148123a..496295d 100644 --- a/arch/arm/include/asm/arch-sunxi/gpio.h +++ b/arch/arm/include/asm/arch-sunxi/gpio.h @@ -185,6 +185,7 @@ enum sunxi_gpio_number { #define SUN8I_GPH_TWI1 2 #define SUN6I_GPH_TWI2 2 #define SUN6I_GPH_UART0 2 +#define SUN9I_GPH_UART0 2 #define SUNXI_GPI_SDC3 2 #define SUN7I_GPI_TWI3 3 -- cgit v1.1 From a19e735d3cbf8fb50a69e911d107635be858c84f Mon Sep 17 00:00:00 2001 From: Roy Spliet Date: Tue, 26 May 2015 17:00:40 +0200 Subject: sunxi: Add DMA definitions Signed-off-by: Roy Spliet Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- arch/arm/include/asm/arch-sunxi/dma.h | 16 +++++++ arch/arm/include/asm/arch-sunxi/dma_sun4i.h | 68 +++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 arch/arm/include/asm/arch-sunxi/dma.h create mode 100644 arch/arm/include/asm/arch-sunxi/dma_sun4i.h (limited to 'arch/arm') diff --git a/arch/arm/include/asm/arch-sunxi/dma.h b/arch/arm/include/asm/arch-sunxi/dma.h new file mode 100644 index 0000000..e54a2ba --- /dev/null +++ b/arch/arm/include/asm/arch-sunxi/dma.h @@ -0,0 +1,16 @@ +/* + * (C) Copyright 2015 Roy Spliet + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _SUNXI_DMA_H +#define _SUNXI_DMA_H + +#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN5I) || defined(CONFIG_MACH_SUN7I) +#include +#else +#error "DMA definition not available for this architecture" +#endif + +#endif /* _SUNXI_DMA_H */ diff --git a/arch/arm/include/asm/arch-sunxi/dma_sun4i.h b/arch/arm/include/asm/arch-sunxi/dma_sun4i.h new file mode 100644 index 0000000..778a04b --- /dev/null +++ b/arch/arm/include/asm/arch-sunxi/dma_sun4i.h @@ -0,0 +1,68 @@ +/* + * (C) Copyright 2015 Roy Spliet + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _SUNXI_DMA_SUN4I_H +#define _SUNXI_DMA_SUN4I_H + +struct sunxi_dma_cfg +{ + u32 ctl; /* 0x00 Control */ + u32 src_addr; /* 0x04 Source address */ + u32 dst_addr; /* 0x08 Destination address */ + u32 bc; /* 0x0C Byte counter */ + u32 res0[2]; + u32 ddma_para; /* 0x18 extra parameter (dedicated DMA only) */ + u32 res1; +}; + +struct sunxi_dma +{ + u32 irq_en; /* 0x000 IRQ enable */ + u32 irq_pend; /* 0x004 IRQ pending */ + u32 auto_gate; /* 0x008 auto gating */ + u32 res0[61]; + struct sunxi_dma_cfg ndma[8]; /* 0x100 Normal DMA */ + u32 res1[64]; + struct sunxi_dma_cfg ddma[8]; /* 0x300 Dedicated DMA */ +}; + +enum ddma_drq_type { + DDMA_DST_DRQ_SRAM = 0, + DDMA_SRC_DRQ_SRAM = 0, + DDMA_DST_DRQ_SDRAM = 1, + DDMA_SRC_DRQ_SDRAM = 1, + DDMA_DST_DRQ_PATA = 2, + DDMA_SRC_DRQ_PATA = 2, + DDMA_DST_DRQ_NAND = 3, + DDMA_SRC_DRQ_NAND = 3, + DDMA_DST_DRQ_USB0 = 4, + DDMA_SRC_DRQ_USB0 = 4, + DDMA_DST_DRQ_ETHERNET_MAC_TX = 6, + DDMA_SRC_DRQ_ETHERNET_MAC_RX = 7, + DDMA_DST_DRQ_SPI1_TX = 8, + DDMA_SRC_DRQ_SPI1_RX = 9, + DDMA_DST_DRQ_SECURITY_SYS_TX = 10, + DDMA_SRC_DRQ_SECURITY_SYS_RX = 11, + DDMA_DST_DRQ_TCON0 = 14, + DDMA_DST_DRQ_TCON1 = 15, + DDMA_DST_DRQ_MSC = 23, + DDMA_SRC_DRQ_MSC = 23, + DDMA_DST_DRQ_SPI0_TX = 26, + DDMA_SRC_DRQ_SPI0_RX = 27, + DDMA_DST_DRQ_SPI2_TX = 28, + DDMA_SRC_DRQ_SPI2_RX = 29, + DDMA_DST_DRQ_SPI3_TX = 30, + DDMA_SRC_DRQ_SPI3_RX = 31, +}; + +#define SUNXI_DMA_CTL_SRC_DRQ(a) ((a) & 0x1f) +#define SUNXI_DMA_CTL_MODE_IO (1 << 5) +#define SUNXI_DMA_CTL_SRC_DATA_WIDTH_32 (2 << 9) +#define SUNXI_DMA_CTL_DST_DRQ(a) (((a) & 0x1f) << 16) +#define SUNXI_DMA_CTL_DST_DATA_WIDTH_32 (2 << 25) +#define SUNXI_DMA_CTL_TRIGGER (1 << 31) + +#endif /* _SUNXI_DMA_SUN4I_H */ -- cgit v1.1 From d0f4200392515194bf67213165be906e5b9e5748 Mon Sep 17 00:00:00 2001 From: Roy Spliet Date: Tue, 26 May 2015 17:00:41 +0200 Subject: sunxi: Match sun4i, sun6i, sun9i CCI definitions for NAND and DMA Make sure definitions for NAND clock and DMA gate bits are the same across boards. Signed-off-by: Roy Spliet Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- arch/arm/include/asm/arch-sunxi/clock_sun4i.h | 4 ++-- arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 3 +++ arch/arm/include/asm/arch-sunxi/clock_sun9i.h | 6 +++++- 3 files changed, 10 insertions(+), 3 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h index 63c3319..58aff16 100644 --- a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h +++ b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h @@ -39,7 +39,7 @@ struct sunxi_ccm_reg { u32 apb0_gate; /* 0x68 apb0 module clock gating */ u32 apb1_gate; /* 0x6c apb1 module clock gating */ u8 res4[0x10]; - u32 nand_sclk_cfg; /* 0x80 nand sub clock control */ + u32 nand0_clk_cfg; /* 0x80 nand sub clock control */ u32 ms_sclk_cfg; /* 0x84 memory stick sub clock control */ u32 sd0_clk_cfg; /* 0x88 sd0 clock control */ u32 sd1_clk_cfg; /* 0x8c sd1 clock control */ @@ -177,7 +177,7 @@ struct sunxi_ccm_reg { #define AHB_GATE_OFFSET_ACE 16 #define AHB_GATE_OFFSET_DLL 15 #define AHB_GATE_OFFSET_SDRAM 14 -#define AHB_GATE_OFFSET_NAND 13 +#define AHB_GATE_OFFSET_NAND0 13 #define AHB_GATE_OFFSET_MS 12 #define AHB_GATE_OFFSET_MMC3 11 #define AHB_GATE_OFFSET_MMC2 10 diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h index 6465f21..8a26b9f 100644 --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h @@ -215,11 +215,14 @@ struct sunxi_ccm_reg { #define AHB_GATE_OFFSET_USB0 24 #define AHB_GATE_OFFSET_MCTL 14 #define AHB_GATE_OFFSET_GMAC 17 +#define AHB_GATE_OFFSET_NAND0 13 +#define AHB_GATE_OFFSET_NAND1 12 #define AHB_GATE_OFFSET_MMC3 11 #define AHB_GATE_OFFSET_MMC2 10 #define AHB_GATE_OFFSET_MMC1 9 #define AHB_GATE_OFFSET_MMC0 8 #define AHB_GATE_OFFSET_MMC(n) (AHB_GATE_OFFSET_MMC0 + (n)) +#define AHB_GATE_OFFSET_DMA 6 #define AHB_GATE_OFFSET_SS 5 /* ahb_gate1 offsets */ diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun9i.h b/arch/arm/include/asm/arch-sunxi/clock_sun9i.h index c506b0a..a61934f 100644 --- a/arch/arm/include/asm/arch-sunxi/clock_sun9i.h +++ b/arch/arm/include/asm/arch-sunxi/clock_sun9i.h @@ -42,7 +42,7 @@ struct sunxi_ccm_reg { u32 clk_output_b; /* 0x184 clk_output_a */ u8 reserved5[0x278]; /* 0x188 */ - u32 nand0_clk_cfg0; /* 0x400 nand0 clock configuration0 */ + u32 nand0_clk_cfg; /* 0x400 nand0 clock configuration0 */ u32 nand0_clk_cfg1; /* 0x404 nand1 clock configuration */ u8 reserved6[0x08]; /* 0x408 */ u32 sd0_clk_cfg; /* 0x410 sd0 clock configuration */ @@ -113,8 +113,12 @@ struct sunxi_ccm_reg { /* ahb_gate0 fields */ /* On sun9i all sdc-s share their ahb gate, so ignore (x) */ +#define AHB_GATE_OFFSET_NAND0 13 #define AHB_GATE_OFFSET_MMC(x) 8 +/* ahb gate1 field */ +#define AHB_GATE_OFFSET_DMA 24 + /* apb1_gate fields */ #define APB1_GATE_UART_SHIFT 16 #define APB1_GATE_UART_MASK (0xff << APB1_GATE_UART_SHIFT) -- cgit v1.1 From f76eba38b3eda905ff3bdc18dd1240d3dcbc6e5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kochma=C5=84ski?= Date: Tue, 26 May 2015 17:00:42 +0200 Subject: sunxi/nand: Add support to the SPL for loading u-boot from internal NAND memory This commit adds support to the sunxi SPL to load u-boot from the internal NAND. Note this only adds support to access the boot partitions to load u-boot, full NAND support to load the kernel, etc. from the nand data partition will come later. Signed-off-by: Roy Spliet Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- arch/arm/cpu/armv7/sunxi/board.c | 14 ++++++- arch/arm/include/asm/arch-sunxi/gpio.h | 2 + arch/arm/include/asm/arch-sunxi/nand.h | 67 ++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 arch/arm/include/asm/arch-sunxi/nand.h (limited to 'arch/arm') diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c index 23aa249..a82c8b9 100644 --- a/arch/arm/cpu/armv7/sunxi/board.c +++ b/arch/arm/cpu/armv7/sunxi/board.c @@ -119,11 +119,20 @@ void s_init(void) #ifdef CONFIG_SPL_BUILD /* The sunxi internal brom will try to loader external bootloader * from mmc0, nand flash, mmc2. - * Unfortunately we can't check how SPL was loaded so assume - * it's always the first SD/MMC controller + * + * Unfortunately we can't check how SPL was loaded so assume it's + * always the first SD/MMC controller, unless it was explicitly + * stated that SPL is on nand flash. */ u32 spl_boot_device(void) { +#if defined(CONFIG_SPL_NAND_SUPPORT) + /* + * This is compile time configuration informing SPL, that it + * was loaded from nand flash. + */ + return BOOT_DEVICE_NAND; +#else /* * When booting from the SD card, the "eGON.BT0" signature is expected * to be found in memory at the address 0x0004 (see the "mksunxiboot" @@ -144,6 +153,7 @@ u32 spl_boot_device(void) return BOOT_DEVICE_MMC1; else return BOOT_DEVICE_BOARD; +#endif } /* No confirmation data available in SPL yet. Hardcode bootmode */ diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h index 496295d..b628fee 100644 --- a/arch/arm/include/asm/arch-sunxi/gpio.h +++ b/arch/arm/include/asm/arch-sunxi/gpio.h @@ -157,6 +157,8 @@ enum sunxi_gpio_number { #define SUN5I_GPB_UART0 2 #define SUN8I_GPB_UART2 2 +#define SUNXI_GPC_NAND 2 + #define SUNXI_GPC_SDC2 3 #define SUN6I_GPC_SDC3 4 diff --git a/arch/arm/include/asm/arch-sunxi/nand.h b/arch/arm/include/asm/arch-sunxi/nand.h new file mode 100644 index 0000000..22844d8 --- /dev/null +++ b/arch/arm/include/asm/arch-sunxi/nand.h @@ -0,0 +1,67 @@ +/* + * (C) Copyright 2015 Roy Spliet + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _SUNXI_NAND_H +#define _SUNXI_NAND_H + +#include + +struct sunxi_nand +{ + u32 ctl; /* 0x000 Configure and control */ + u32 st; /* 0x004 Status information */ + u32 intr; /* 0x008 Interrupt control */ + u32 timing_ctl; /* 0x00C Timing control */ + u32 timing_cfg; /* 0x010 Timing configure */ + u32 addr_low; /* 0x014 Low word address */ + u32 addr_high; /* 0x018 High word address */ + u32 block_num; /* 0x01C Data block number */ + u32 data_cnt; /* 0x020 Data counter for transfer */ + u32 cmd; /* 0x024 NDFC commands */ + u32 rcmd_set; /* 0x028 Read command set for vendor NAND mem */ + u32 wcmd_set; /* 0x02C Write command set */ + u32 io_data; /* 0x030 IO data */ + u32 ecc_ctl; /* 0x034 ECC configure and control */ + u32 ecc_st; /* 0x038 ECC status and operation info */ + u32 efr; /* 0x03C Enhanced feature */ + u32 err_cnt0; /* 0x040 Corrected error bit counter 0 */ + u32 err_cnt1; /* 0x044 Corrected error bit counter 1 */ + u32 user_data[16]; /* 0x050[16] User data field */ + u32 efnand_st; /* 0x090 EFNAND status */ + u32 res0[3]; + u32 spare_area; /* 0x0A0 Spare area configure */ + u32 pat_id; /* 0x0A4 Pattern ID register */ + u32 rdata_sta_ctl; /* 0x0A8 Read data status control */ + u32 rdata_sta_0; /* 0x0AC Read data status 0 */ + u32 rdata_sta_1; /* 0x0B0 Read data status 1 */ + u32 res1[3]; + u32 mdma_addr; /* 0x0C0 MBUS DMA Address */ + u32 mdma_cnt; /* 0x0C4 MBUS DMA data counter */ +}; + +#define SUNXI_NAND_CTL_EN (1 << 0) +#define SUNXI_NAND_CTL_RST (1 << 1) +#define SUNXI_NAND_CTL_PAGE_SIZE(a) ((fls(a) - 11) << 8) +#define SUNXI_NAND_CTL_RAM_METHOD_DMA (1 << 14) + +#define SUNXI_NAND_ST_CMD_INT (1 << 1) +#define SUNXI_NAND_ST_DMA_INT (1 << 2) +#define SUNXI_NAND_ST_FIFO_FULL (1 << 3) + +#define SUNXI_NAND_CMD_ADDR_CYCLES(a) ((a - 1) << 16); +#define SUNXI_NAND_CMD_SEND_CMD1 (1 << 22) +#define SUNXI_NAND_CMD_WAIT_FLAG (1 << 23) +#define SUNXI_NAND_CMD_ORDER_INTERLEAVE 0 +#define SUNXI_NAND_CMD_ORDER_SEQ (1 << 25) + +#define SUNXI_NAND_ECC_CTL_ECC_EN (1 << 0) +#define SUNXI_NAND_ECC_CTL_PIPELINE (1 << 3) +#define SUNXI_NAND_ECC_CTL_BS_512B (1 << 5) +#define SUNXI_NAND_ECC_CTL_RND_EN (1 << 9) +#define SUNXI_NAND_ECC_CTL_MODE(a) ((a) << 12) +#define SUNXI_NAND_ECC_CTL_RND_SEED(a) ((a) << 16) + +#endif /* _SUNXI_NAND_H */ -- cgit v1.1 From 4ffd62451243c226709924c1459935739478231c Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 28 May 2015 21:25:29 +0800 Subject: ARM: sunxi: Document registers in PSCI code The PSCI CPU_ON code accesses quite a few registers. Document their names to make it easier to cross reference. Also explain "lock cpu" and "unlock cpu" as enabling/disabling debug access. Signed-off-by: Chen-Yu Tsai Acked-by: Hans de Goede Signed-off-by: Hans de Goede --- arch/arm/cpu/armv7/sunxi/psci.S | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/cpu/armv7/sunxi/psci.S b/arch/arm/cpu/armv7/sunxi/psci.S index 7ec0500..bbfeec8 100644 --- a/arch/arm/cpu/armv7/sunxi/psci.S +++ b/arch/arm/cpu/armv7/sunxi/psci.S @@ -165,12 +165,12 @@ psci_cpu_on: str r6, [r5] @ Reset CPU @ l1 invalidate - ldr r6, [r0, #0x184] + ldr r6, [r0, #0x184] @ CPUCFG_GEN_CTRL_REG bic r6, r6, r4 str r6, [r0, #0x184] - @ Lock CPU - ldr r6, [r0, #0x1e4] + @ Lock CPU (Disable external debug access) + ldr r6, [r0, #0x1e4] @ CPUCFG_DBG_CTL1_REG bic r6, r6, r4 str r6, [r0, #0x1e4] @@ -178,13 +178,13 @@ psci_cpu_on: movw r6, #0x1ff movt r6, #0 1: lsrs r6, r6, #1 - str r6, [r0, #0x1b0] + str r6, [r0, #0x1b0] @ CPU1_PWR_CLAMP bne 1b timer_wait r1, TEN_MS @ Clear power gating - ldr r6, [r0, #0x1b4] + ldr r6, [r0, #0x1b4] @ CPU1_PWROFF_REG bic r6, r6, #1 str r6, [r0, #0x1b4] @@ -192,8 +192,8 @@ psci_cpu_on: mov r6, #3 str r6, [r5] - @ Unlock CPU - ldr r6, [r0, #0x1e4] + @ Unlock CPU (Enable external debug access) + ldr r6, [r0, #0x1e4] @ CPUCFG_DBG_CTL1_REG orr r6, r6, r4 str r6, [r0, #0x1e4] -- cgit v1.1 From d4611aff4d17010d0d753a92d9e887035dc4eae5 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 28 May 2015 21:25:30 +0800 Subject: ARM: sunxi: Make PSCI code sun7i specific The PSCI code only works for sun7i. Rename it with _sun7i suffix, and build only if building for sun7i. This paves the way for adding PSCI support for other platforms. Signed-off-by: Chen-Yu Tsai Acked-by: Hans de Goede Signed-off-by: Hans de Goede --- arch/arm/cpu/armv7/sunxi/Makefile | 2 +- arch/arm/cpu/armv7/sunxi/psci.S | 255 ---------------------------------- arch/arm/cpu/armv7/sunxi/psci_sun7i.S | 255 ++++++++++++++++++++++++++++++++++ 3 files changed, 256 insertions(+), 256 deletions(-) delete mode 100644 arch/arm/cpu/armv7/sunxi/psci.S create mode 100644 arch/arm/cpu/armv7/sunxi/psci_sun7i.S (limited to 'arch/arm') diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile index 7ef6b4c..85fbc85 100644 --- a/arch/arm/cpu/armv7/sunxi/Makefile +++ b/arch/arm/cpu/armv7/sunxi/Makefile @@ -35,7 +35,7 @@ obj-$(CONFIG_AXP221_POWER) += pmic_bus.o ifndef CONFIG_SPL_BUILD ifdef CONFIG_ARMV7_PSCI -obj-y += psci.o +obj-$(CONFIG_MACH_SUN7I) += psci_sun7i.o endif endif diff --git a/arch/arm/cpu/armv7/sunxi/psci.S b/arch/arm/cpu/armv7/sunxi/psci.S deleted file mode 100644 index bbfeec8..0000000 --- a/arch/arm/cpu/armv7/sunxi/psci.S +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright (C) 2013 - ARM Ltd - * Author: Marc Zyngier - * - * Based on code by Carl van Schaik . - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include -#include - -/* - * Memory layout: - * - * SECURE_RAM to text_end : - * ._secure_text section - * text_end to ALIGN_PAGE(text_end): - * nothing - * ALIGN_PAGE(text_end) to ALIGN_PAGE(text_end) + 0x1000) - * 1kB of stack per CPU (4 CPUs max). - */ - - .pushsection ._secure.text, "ax" - - .arch_extension sec - -#define ONE_MS (CONFIG_TIMER_CLK_FREQ / 1000) -#define TEN_MS (10 * ONE_MS) -#define GICD_BASE 0x1c81000 -#define GICC_BASE 0x1c82000 - -.macro timer_wait reg, ticks - @ Program CNTP_TVAL - movw \reg, #(\ticks & 0xffff) - movt \reg, #(\ticks >> 16) - mcr p15, 0, \reg, c14, c2, 0 - isb - @ Enable physical timer, mask interrupt - mov \reg, #3 - mcr p15, 0, \reg, c14, c2, 1 - @ Poll physical timer until ISTATUS is on -1: isb - mrc p15, 0, \reg, c14, c2, 1 - ands \reg, \reg, #4 - bne 1b - @ Disable timer - mov \reg, #0 - mcr p15, 0, \reg, c14, c2, 1 - isb -.endm - -.globl psci_fiq_enter -psci_fiq_enter: - push {r0-r12} - - @ Switch to secure - mrc p15, 0, r7, c1, c1, 0 - bic r8, r7, #1 - mcr p15, 0, r8, c1, c1, 0 - isb - - @ Validate reason based on IAR and acknowledge - movw r8, #(GICC_BASE & 0xffff) - movt r8, #(GICC_BASE >> 16) - ldr r9, [r8, #GICC_IAR] - movw r10, #0x3ff - movt r10, #0 - cmp r9, r10 @ skip spurious interrupt 1023 - beq out - movw r10, #0x3fe @ ...and 1022 - cmp r9, r10 - beq out - str r9, [r8, #GICC_EOIR] @ acknowledge the interrupt - dsb - - @ Compute CPU number - lsr r9, r9, #10 - and r9, r9, #0xf - - movw r8, #(SUN7I_CPUCFG_BASE & 0xffff) - movt r8, #(SUN7I_CPUCFG_BASE >> 16) - - @ Wait for the core to enter WFI - lsl r11, r9, #6 @ x64 - add r11, r11, r8 - -1: ldr r10, [r11, #0x48] - tst r10, #(1 << 2) - bne 2f - timer_wait r10, ONE_MS - b 1b - - @ Reset CPU -2: mov r10, #0 - str r10, [r11, #0x40] - - @ Lock CPU - mov r10, #1 - lsl r9, r10, r9 @ r9 is now CPU mask - ldr r10, [r8, #0x1e4] - bic r10, r10, r9 - str r10, [r8, #0x1e4] - - @ Set power gating - ldr r10, [r8, #0x1b4] - orr r10, r10, #1 - str r10, [r8, #0x1b4] - timer_wait r10, ONE_MS - - @ Activate power clamp - mov r10, #1 -1: str r10, [r8, #0x1b0] - lsl r10, r10, #1 - orr r10, r10, #1 - tst r10, #0x100 - beq 1b - - @ Restore security level -out: mcr p15, 0, r7, c1, c1, 0 - - pop {r0-r12} - subs pc, lr, #4 - - @ r1 = target CPU - @ r2 = target PC -.globl psci_cpu_on -psci_cpu_on: - push {lr} - - mov r0, r1 - bl psci_get_cpu_stack_top @ get stack top of target CPU - str r2, [r0] @ store target PC at stack top - dsb - - movw r0, #(SUN7I_CPUCFG_BASE & 0xffff) - movt r0, #(SUN7I_CPUCFG_BASE >> 16) - - @ CPU mask - and r1, r1, #3 @ only care about first cluster - mov r4, #1 - lsl r4, r4, r1 - - ldr r6, =psci_cpu_entry - str r6, [r0, #0x1a4] @ PRIVATE_REG (boot vector) - - @ Assert reset on target CPU - mov r6, #0 - lsl r5, r1, #6 @ 64 bytes per CPU - add r5, r5, #0x40 @ Offset from base - add r5, r5, r0 @ CPU control block - str r6, [r5] @ Reset CPU - - @ l1 invalidate - ldr r6, [r0, #0x184] @ CPUCFG_GEN_CTRL_REG - bic r6, r6, r4 - str r6, [r0, #0x184] - - @ Lock CPU (Disable external debug access) - ldr r6, [r0, #0x1e4] @ CPUCFG_DBG_CTL1_REG - bic r6, r6, r4 - str r6, [r0, #0x1e4] - - @ Release power clamp - movw r6, #0x1ff - movt r6, #0 -1: lsrs r6, r6, #1 - str r6, [r0, #0x1b0] @ CPU1_PWR_CLAMP - bne 1b - - timer_wait r1, TEN_MS - - @ Clear power gating - ldr r6, [r0, #0x1b4] @ CPU1_PWROFF_REG - bic r6, r6, #1 - str r6, [r0, #0x1b4] - - @ Deassert reset on target CPU - mov r6, #3 - str r6, [r5] - - @ Unlock CPU (Enable external debug access) - ldr r6, [r0, #0x1e4] @ CPUCFG_DBG_CTL1_REG - orr r6, r6, r4 - str r6, [r0, #0x1e4] - - mov r0, #ARM_PSCI_RET_SUCCESS @ Return PSCI_RET_SUCCESS - pop {pc} - -.globl psci_cpu_off -psci_cpu_off: - bl psci_cpu_off_common - - @ Ask CPU0 to pull the rug... - movw r0, #(GICD_BASE & 0xffff) - movt r0, #(GICD_BASE >> 16) - movw r1, #15 @ SGI15 - movt r1, #1 @ Target is CPU0 - str r1, [r0, #GICD_SGIR] - dsb - -1: wfi - b 1b - -.globl psci_arch_init -psci_arch_init: - mov r6, lr - - movw r4, #(GICD_BASE & 0xffff) - movt r4, #(GICD_BASE >> 16) - - ldr r5, [r4, #GICD_IGROUPRn] - bic r5, r5, #(1 << 15) @ SGI15 as Group-0 - str r5, [r4, #GICD_IGROUPRn] - - mov r5, #0 @ Set SGI15 priority to 0 - strb r5, [r4, #(GICD_IPRIORITYRn + 15)] - - add r4, r4, #0x1000 @ GICC address - - mov r5, #0xff - str r5, [r4, #GICC_PMR] @ Be cool with non-secure - - ldr r5, [r4, #GICC_CTLR] - orr r5, r5, #(1 << 3) @ Switch FIQEn on - str r5, [r4, #GICC_CTLR] - - mrc p15, 0, r5, c1, c1, 0 @ Read SCR - orr r5, r5, #4 @ Enable FIQ in monitor mode - bic r5, r5, #1 @ Secure mode - mcr p15, 0, r5, c1, c1, 0 @ Write SCR - isb - - bl psci_get_cpu_id @ CPU ID => r0 - bl psci_get_cpu_stack_top @ stack top => r0 - mov sp, r0 - - bx r6 - - .globl psci_text_end -psci_text_end: - .popsection diff --git a/arch/arm/cpu/armv7/sunxi/psci_sun7i.S b/arch/arm/cpu/armv7/sunxi/psci_sun7i.S new file mode 100644 index 0000000..bbfeec8 --- /dev/null +++ b/arch/arm/cpu/armv7/sunxi/psci_sun7i.S @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2013 - ARM Ltd + * Author: Marc Zyngier + * + * Based on code by Carl van Schaik . + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include + +/* + * Memory layout: + * + * SECURE_RAM to text_end : + * ._secure_text section + * text_end to ALIGN_PAGE(text_end): + * nothing + * ALIGN_PAGE(text_end) to ALIGN_PAGE(text_end) + 0x1000) + * 1kB of stack per CPU (4 CPUs max). + */ + + .pushsection ._secure.text, "ax" + + .arch_extension sec + +#define ONE_MS (CONFIG_TIMER_CLK_FREQ / 1000) +#define TEN_MS (10 * ONE_MS) +#define GICD_BASE 0x1c81000 +#define GICC_BASE 0x1c82000 + +.macro timer_wait reg, ticks + @ Program CNTP_TVAL + movw \reg, #(\ticks & 0xffff) + movt \reg, #(\ticks >> 16) + mcr p15, 0, \reg, c14, c2, 0 + isb + @ Enable physical timer, mask interrupt + mov \reg, #3 + mcr p15, 0, \reg, c14, c2, 1 + @ Poll physical timer until ISTATUS is on +1: isb + mrc p15, 0, \reg, c14, c2, 1 + ands \reg, \reg, #4 + bne 1b + @ Disable timer + mov \reg, #0 + mcr p15, 0, \reg, c14, c2, 1 + isb +.endm + +.globl psci_fiq_enter +psci_fiq_enter: + push {r0-r12} + + @ Switch to secure + mrc p15, 0, r7, c1, c1, 0 + bic r8, r7, #1 + mcr p15, 0, r8, c1, c1, 0 + isb + + @ Validate reason based on IAR and acknowledge + movw r8, #(GICC_BASE & 0xffff) + movt r8, #(GICC_BASE >> 16) + ldr r9, [r8, #GICC_IAR] + movw r10, #0x3ff + movt r10, #0 + cmp r9, r10 @ skip spurious interrupt 1023 + beq out + movw r10, #0x3fe @ ...and 1022 + cmp r9, r10 + beq out + str r9, [r8, #GICC_EOIR] @ acknowledge the interrupt + dsb + + @ Compute CPU number + lsr r9, r9, #10 + and r9, r9, #0xf + + movw r8, #(SUN7I_CPUCFG_BASE & 0xffff) + movt r8, #(SUN7I_CPUCFG_BASE >> 16) + + @ Wait for the core to enter WFI + lsl r11, r9, #6 @ x64 + add r11, r11, r8 + +1: ldr r10, [r11, #0x48] + tst r10, #(1 << 2) + bne 2f + timer_wait r10, ONE_MS + b 1b + + @ Reset CPU +2: mov r10, #0 + str r10, [r11, #0x40] + + @ Lock CPU + mov r10, #1 + lsl r9, r10, r9 @ r9 is now CPU mask + ldr r10, [r8, #0x1e4] + bic r10, r10, r9 + str r10, [r8, #0x1e4] + + @ Set power gating + ldr r10, [r8, #0x1b4] + orr r10, r10, #1 + str r10, [r8, #0x1b4] + timer_wait r10, ONE_MS + + @ Activate power clamp + mov r10, #1 +1: str r10, [r8, #0x1b0] + lsl r10, r10, #1 + orr r10, r10, #1 + tst r10, #0x100 + beq 1b + + @ Restore security level +out: mcr p15, 0, r7, c1, c1, 0 + + pop {r0-r12} + subs pc, lr, #4 + + @ r1 = target CPU + @ r2 = target PC +.globl psci_cpu_on +psci_cpu_on: + push {lr} + + mov r0, r1 + bl psci_get_cpu_stack_top @ get stack top of target CPU + str r2, [r0] @ store target PC at stack top + dsb + + movw r0, #(SUN7I_CPUCFG_BASE & 0xffff) + movt r0, #(SUN7I_CPUCFG_BASE >> 16) + + @ CPU mask + and r1, r1, #3 @ only care about first cluster + mov r4, #1 + lsl r4, r4, r1 + + ldr r6, =psci_cpu_entry + str r6, [r0, #0x1a4] @ PRIVATE_REG (boot vector) + + @ Assert reset on target CPU + mov r6, #0 + lsl r5, r1, #6 @ 64 bytes per CPU + add r5, r5, #0x40 @ Offset from base + add r5, r5, r0 @ CPU control block + str r6, [r5] @ Reset CPU + + @ l1 invalidate + ldr r6, [r0, #0x184] @ CPUCFG_GEN_CTRL_REG + bic r6, r6, r4 + str r6, [r0, #0x184] + + @ Lock CPU (Disable external debug access) + ldr r6, [r0, #0x1e4] @ CPUCFG_DBG_CTL1_REG + bic r6, r6, r4 + str r6, [r0, #0x1e4] + + @ Release power clamp + movw r6, #0x1ff + movt r6, #0 +1: lsrs r6, r6, #1 + str r6, [r0, #0x1b0] @ CPU1_PWR_CLAMP + bne 1b + + timer_wait r1, TEN_MS + + @ Clear power gating + ldr r6, [r0, #0x1b4] @ CPU1_PWROFF_REG + bic r6, r6, #1 + str r6, [r0, #0x1b4] + + @ Deassert reset on target CPU + mov r6, #3 + str r6, [r5] + + @ Unlock CPU (Enable external debug access) + ldr r6, [r0, #0x1e4] @ CPUCFG_DBG_CTL1_REG + orr r6, r6, r4 + str r6, [r0, #0x1e4] + + mov r0, #ARM_PSCI_RET_SUCCESS @ Return PSCI_RET_SUCCESS + pop {pc} + +.globl psci_cpu_off +psci_cpu_off: + bl psci_cpu_off_common + + @ Ask CPU0 to pull the rug... + movw r0, #(GICD_BASE & 0xffff) + movt r0, #(GICD_BASE >> 16) + movw r1, #15 @ SGI15 + movt r1, #1 @ Target is CPU0 + str r1, [r0, #GICD_SGIR] + dsb + +1: wfi + b 1b + +.globl psci_arch_init +psci_arch_init: + mov r6, lr + + movw r4, #(GICD_BASE & 0xffff) + movt r4, #(GICD_BASE >> 16) + + ldr r5, [r4, #GICD_IGROUPRn] + bic r5, r5, #(1 << 15) @ SGI15 as Group-0 + str r5, [r4, #GICD_IGROUPRn] + + mov r5, #0 @ Set SGI15 priority to 0 + strb r5, [r4, #(GICD_IPRIORITYRn + 15)] + + add r4, r4, #0x1000 @ GICC address + + mov r5, #0xff + str r5, [r4, #GICC_PMR] @ Be cool with non-secure + + ldr r5, [r4, #GICC_CTLR] + orr r5, r5, #(1 << 3) @ Switch FIQEn on + str r5, [r4, #GICC_CTLR] + + mrc p15, 0, r5, c1, c1, 0 @ Read SCR + orr r5, r5, #4 @ Enable FIQ in monitor mode + bic r5, r5, #1 @ Secure mode + mcr p15, 0, r5, c1, c1, 0 @ Write SCR + isb + + bl psci_get_cpu_id @ CPU ID => r0 + bl psci_get_cpu_stack_top @ stack top => r0 + mov sp, r0 + + bx r6 + + .globl psci_text_end +psci_text_end: + .popsection -- cgit v1.1 From 073f29843847163c407878511cbf2a6cb36ed97b Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 28 May 2015 21:25:31 +0800 Subject: ARM: sunxi: Add sun6i specific PSCI implementation This adds PSCI support for sun6i. So far it only supports the PWR_ON method. Signed-off-by: Chen-Yu Tsai Acked-by: Hans de Goede Signed-off-by: Hans de Goede --- arch/arm/cpu/armv7/sunxi/Makefile | 1 + arch/arm/cpu/armv7/sunxi/psci_sun6i.S | 276 ++++++++++++++++++++++++++++++++++ 2 files changed, 277 insertions(+) create mode 100644 arch/arm/cpu/armv7/sunxi/psci_sun6i.S (limited to 'arch/arm') diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile index 85fbc85..4b783e0 100644 --- a/arch/arm/cpu/armv7/sunxi/Makefile +++ b/arch/arm/cpu/armv7/sunxi/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_AXP221_POWER) += pmic_bus.o ifndef CONFIG_SPL_BUILD ifdef CONFIG_ARMV7_PSCI +obj-$(CONFIG_MACH_SUN6I) += psci_sun6i.o obj-$(CONFIG_MACH_SUN7I) += psci_sun7i.o endif endif diff --git a/arch/arm/cpu/armv7/sunxi/psci_sun6i.S b/arch/arm/cpu/armv7/sunxi/psci_sun6i.S new file mode 100644 index 0000000..2516804 --- /dev/null +++ b/arch/arm/cpu/armv7/sunxi/psci_sun6i.S @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2015 - Chen-Yu Tsai + * Author: Chen-Yu Tsai + * + * Based on psci_sun7i.S by Marc Zyngier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include + +/* + * Memory layout: + * + * SECURE_RAM to text_end : + * ._secure_text section + * text_end to ALIGN_PAGE(text_end): + * nothing + * ALIGN_PAGE(text_end) to ALIGN_PAGE(text_end) + 0x1000) + * 1kB of stack per CPU (4 CPUs max). + */ + + .pushsection ._secure.text, "ax" + + .arch_extension sec + +#define ONE_MS (CONFIG_TIMER_CLK_FREQ / 1000) +#define TEN_MS (10 * ONE_MS) +#define GICD_BASE 0x1c81000 +#define GICC_BASE 0x1c82000 + +.macro timer_wait reg, ticks + @ Program CNTP_TVAL + movw \reg, #(\ticks & 0xffff) + movt \reg, #(\ticks >> 16) + mcr p15, 0, \reg, c14, c2, 0 + isb + @ Enable physical timer, mask interrupt + mov \reg, #3 + mcr p15, 0, \reg, c14, c2, 1 + @ Poll physical timer until ISTATUS is on +1: isb + mrc p15, 0, \reg, c14, c2, 1 + ands \reg, \reg, #4 + bne 1b + @ Disable timer + mov \reg, #0 + mcr p15, 0, \reg, c14, c2, 1 + isb +.endm + +.globl psci_fiq_enter +psci_fiq_enter: + push {r0-r12} + + @ Switch to secure + mrc p15, 0, r7, c1, c1, 0 + bic r8, r7, #1 + mcr p15, 0, r8, c1, c1, 0 + isb + + @ Validate reason based on IAR and acknowledge + movw r8, #(GICC_BASE & 0xffff) + movt r8, #(GICC_BASE >> 16) + ldr r9, [r8, #GICC_IAR] + movw r10, #0x3ff + movt r10, #0 + cmp r9, r10 @ skip spurious interrupt 1023 + beq out + movw r10, #0x3fe @ ...and 1022 + cmp r9, r10 + beq out + str r9, [r8, #GICC_EOIR] @ acknowledge the interrupt + dsb + + @ Compute CPU number + lsr r9, r9, #10 + and r9, r9, #0xf + + movw r8, #(SUN6I_CPUCFG_BASE & 0xffff) + movt r8, #(SUN6I_CPUCFG_BASE >> 16) + + @ Wait for the core to enter WFI + lsl r11, r9, #6 @ x64 + add r11, r11, r8 + +1: ldr r10, [r11, #0x48] + tst r10, #(1 << 2) + bne 2f + timer_wait r10, ONE_MS + b 1b + + @ Reset CPU +2: mov r10, #0 + str r10, [r11, #0x40] + + @ Lock CPU + mov r10, #1 + lsl r11, r10, r9 @ r11 is now CPU mask + ldr r10, [r8, #0x1e4] + bic r10, r10, r11 + str r10, [r8, #0x1e4] + + movw r8, #(SUNXI_PRCM_BASE & 0xffff) + movt r8, #(SUNXI_PRCM_BASE >> 16) + + @ Set power gating + ldr r10, [r8, #0x100] + orr r10, r10, r11 + str r10, [r8, #0x100] + timer_wait r10, ONE_MS + + @ Activate power clamp + lsl r12, r9, #2 @ x4 + add r12, r12, r8 + mov r10, #0xff + str r10, [r12, #0x140] + + movw r8, #(SUN6I_CPUCFG_BASE & 0xffff) + movt r8, #(SUN6I_CPUCFG_BASE >> 16) + + @ Unlock CPU + ldr r10, [r8, #0x1e4] + orr r10, r10, r11 + str r10, [r8, #0x1e4] + + @ Restore security level +out: mcr p15, 0, r7, c1, c1, 0 + + pop {r0-r12} + subs pc, lr, #4 + + @ r1 = target CPU + @ r2 = target PC +.globl psci_cpu_on +psci_cpu_on: + push {lr} + + mov r0, r1 + bl psci_get_cpu_stack_top @ get stack top of target CPU + str r2, [r0] @ store target PC at stack top + dsb + + movw r0, #(SUN6I_CPUCFG_BASE & 0xffff) + movt r0, #(SUN6I_CPUCFG_BASE >> 16) + + @ CPU mask + and r1, r1, #3 @ only care about first cluster + mov r4, #1 + lsl r4, r4, r1 + + ldr r6, =psci_cpu_entry + str r6, [r0, #0x1a4] @ PRIVATE_REG (boot vector) + + @ Assert reset on target CPU + mov r6, #0 + lsl r5, r1, #6 @ 64 bytes per CPU + add r5, r5, #0x40 @ Offset from base + add r5, r5, r0 @ CPU control block + str r6, [r5] @ Reset CPU + + @ l1 invalidate + ldr r6, [r0, #0x184] @ CPUCFG_GEN_CTRL_REG + bic r6, r6, r4 + str r6, [r0, #0x184] + + @ Lock CPU (Disable external debug access) + ldr r6, [r0, #0x1e4] @ CPUCFG_DBG_CTL1_REG + bic r6, r6, r4 + str r6, [r0, #0x1e4] + + movw r0, #(SUNXI_PRCM_BASE & 0xffff) + movt r0, #(SUNXI_PRCM_BASE >> 16) + + @ Release power clamp + lsl r5, r1, #2 @ 1 register per CPU + add r5, r5, r0 @ PRCM + movw r6, #0x1ff + movt r6, #0 +1: lsrs r6, r6, #1 + str r6, [r5, #0x140] @ CPUx_PWR_CLAMP + bne 1b + + timer_wait r6, TEN_MS + + @ Clear power gating + ldr r6, [r0, #0x100] @ CPU_PWROFF_GATING + bic r6, r6, r4 + str r6, [r0, #0x100] + + @ re-calculate CPU control register address + movw r0, #(SUN6I_CPUCFG_BASE & 0xffff) + movt r0, #(SUN6I_CPUCFG_BASE >> 16) + + @ Deassert reset on target CPU + mov r6, #3 + lsl r5, r1, #6 @ 64 bytes per CPU + add r5, r5, #0x40 @ Offset from base + add r5, r5, r0 @ CPU control block + str r6, [r5] + + @ Unlock CPU (Enable external debug access) + ldr r6, [r0, #0x1e4] @ CPUCFG_DBG_CTL1_REG + orr r6, r6, r4 + str r6, [r0, #0x1e4] + + mov r0, #ARM_PSCI_RET_SUCCESS @ Return PSCI_RET_SUCCESS + pop {pc} + +.globl psci_cpu_off +psci_cpu_off: + bl psci_cpu_off_common + + @ Ask CPU0 to pull the rug... + movw r0, #(GICD_BASE & 0xffff) + movt r0, #(GICD_BASE >> 16) + movw r1, #15 @ SGI15 + movt r1, #1 @ Target is CPU0 + str r1, [r0, #GICD_SGIR] + dsb + +1: wfi + b 1b + +.globl psci_arch_init +psci_arch_init: + mov r6, lr + + movw r4, #(GICD_BASE & 0xffff) + movt r4, #(GICD_BASE >> 16) + + ldr r5, [r4, #GICD_IGROUPRn] + bic r5, r5, #(1 << 15) @ SGI15 as Group-0 + str r5, [r4, #GICD_IGROUPRn] + + mov r5, #0 @ Set SGI15 priority to 0 + strb r5, [r4, #(GICD_IPRIORITYRn + 15)] + + add r4, r4, #0x1000 @ GICC address + + mov r5, #0xff + str r5, [r4, #GICC_PMR] @ Be cool with non-secure + + ldr r5, [r4, #GICC_CTLR] + orr r5, r5, #(1 << 3) @ Switch FIQEn on + str r5, [r4, #GICC_CTLR] + + mrc p15, 0, r5, c1, c1, 0 @ Read SCR + orr r5, r5, #4 @ Enable FIQ in monitor mode + bic r5, r5, #1 @ Secure mode + mcr p15, 0, r5, c1, c1, 0 @ Write SCR + isb + + bl psci_get_cpu_id @ CPU ID => r0 + bl psci_get_cpu_stack_top @ stack top => r0 + mov sp, r0 + + bx r6 + + .globl psci_text_end +psci_text_end: + .popsection -- cgit v1.1 From 98167430317a6275e582def8cb4aee76799789af Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 28 May 2015 21:25:33 +0800 Subject: ARM: sunxi: Share sun6i PSCI backend with sun8i sun8i can share the PSCI backend with sun6i. Only difference is sun8i does not have CPU power clamp controls. Signed-off-by: Chen-Yu Tsai Acked-by: Hans de Goede Signed-off-by: Hans de Goede --- arch/arm/cpu/armv7/sunxi/Makefile | 1 + arch/arm/cpu/armv7/sunxi/psci_sun6i.S | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile index 4b783e0..76c7e55 100644 --- a/arch/arm/cpu/armv7/sunxi/Makefile +++ b/arch/arm/cpu/armv7/sunxi/Makefile @@ -37,6 +37,7 @@ ifndef CONFIG_SPL_BUILD ifdef CONFIG_ARMV7_PSCI obj-$(CONFIG_MACH_SUN6I) += psci_sun6i.o obj-$(CONFIG_MACH_SUN7I) += psci_sun7i.o +obj-$(CONFIG_MACH_SUN8I) += psci_sun6i.o endif endif diff --git a/arch/arm/cpu/armv7/sunxi/psci_sun6i.S b/arch/arm/cpu/armv7/sunxi/psci_sun6i.S index 2516804..d4cb51e 100644 --- a/arch/arm/cpu/armv7/sunxi/psci_sun6i.S +++ b/arch/arm/cpu/armv7/sunxi/psci_sun6i.S @@ -124,11 +124,13 @@ psci_fiq_enter: str r10, [r8, #0x100] timer_wait r10, ONE_MS +#ifdef CONFIG_MACH_SUN6I @ Activate power clamp lsl r12, r9, #2 @ x4 add r12, r12, r8 mov r10, #0xff str r10, [r12, #0x140] +#endif movw r8, #(SUN6I_CPUCFG_BASE & 0xffff) movt r8, #(SUN6I_CPUCFG_BASE >> 16) @@ -186,6 +188,7 @@ psci_cpu_on: movw r0, #(SUNXI_PRCM_BASE & 0xffff) movt r0, #(SUNXI_PRCM_BASE >> 16) +#ifdef CONFIG_MACH_SUN6I @ Release power clamp lsl r5, r1, #2 @ 1 register per CPU add r5, r5, r0 @ PRCM @@ -194,6 +197,7 @@ psci_cpu_on: 1: lsrs r6, r6, #1 str r6, [r5, #0x140] @ CPUx_PWR_CLAMP bne 1b +#endif timer_wait r6, TEN_MS -- cgit v1.1