From 195889829e3f3fc4eabb3297b3d686daf14af7f5 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Wed, 25 May 2016 18:48:45 +0800 Subject: [PATCH 1/5] gpio: support gpio set/get pull status On some platform gpio can set/get pull status when input, add these function so we can set/get gpio pull status when need it. And they are optional function. --- drivers/gpio/gpio.c | 20 ++++++++++++++++++++ include/drivers/gpio.h | 8 ++++++++ 2 files changed, 28 insertions(+) diff --git a/drivers/gpio/gpio.c b/drivers/gpio/gpio.c index c06172fc5..ef6bb9c82 100644 --- a/drivers/gpio/gpio.c +++ b/drivers/gpio/gpio.c @@ -80,6 +80,26 @@ void gpio_set_value(int gpio, int value) ops->set_value(gpio, value); } +void gpio_set_pull(int gpio, int pull) +{ + assert(ops); + assert(ops->set_pull != 0); + assert((pull == GPIO_PULL_NONE) || (pull == GPIO_PULL_UP) || + (pull == GPIO_PULL_DOWN)); + assert(gpio >= 0); + + ops->set_pull(gpio, pull); +} + +int gpio_get_pull(int gpio) +{ + assert(ops); + assert(ops->get_pull != 0); + assert(gpio >= 0); + + return ops->get_pull(gpio); +} + /* * Initialize the gpio. The fields in the provided gpio * ops pointer must be valid. diff --git a/include/drivers/gpio.h b/include/drivers/gpio.h index a5cb5c7f7..633b3f6b0 100644 --- a/include/drivers/gpio.h +++ b/include/drivers/gpio.h @@ -37,17 +37,25 @@ #define GPIO_LEVEL_LOW 0 #define GPIO_LEVEL_HIGH 1 +#define GPIO_PULL_NONE 0 +#define GPIO_PULL_UP 1 +#define GPIO_PULL_DOWN 2 + typedef struct gpio_ops { int (*get_direction)(int gpio); void (*set_direction)(int gpio, int direction); int (*get_value)(int gpio); void (*set_value)(int gpio, int value); + void (*set_pull)(int gpio, int pull); + int (*get_pull)(int gpio); } gpio_ops_t; int gpio_get_direction(int gpio); void gpio_set_direction(int gpio, int direction); int gpio_get_value(int gpio); void gpio_set_value(int gpio, int value); +void gpio_set_pull(int gpio, int pull); +int gpio_get_pull(int gpio); void gpio_init(const gpio_ops_t *ops); #endif /* __GPIO_H__ */ From 9901dcf6bb14813bf9ace57ffb51d62f37a1d2fb Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Wed, 25 May 2016 19:21:43 +0800 Subject: [PATCH 2/5] rockchip: support rk3399 gpio driver There are 5 groups of GPIO (GPIO0~GPIO4), totally have 122 GPIOs on rk3399 platform. The pull direction(pullup or pulldown) for all of GPIOs are software-programmable. At the moment, we add the gpio basic driver since reset or power off the devices from gpio configuration for BL31. --- plat/rockchip/common/include/plat_private.h | 2 + .../rk3399/drivers/gpio/rk3399_gpio.c | 227 ++++++++++++++++++ plat/rockchip/rk3399/drivers/soc/soc.c | 14 +- plat/rockchip/rk3399/drivers/soc/soc.h | 11 + plat/rockchip/rk3399/include/platform_def.h | 2 +- plat/rockchip/rk3399/platform.mk | 2 + plat/rockchip/rk3399/rk3399_def.h | 18 ++ 7 files changed, 274 insertions(+), 2 deletions(-) create mode 100644 plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c diff --git a/plat/rockchip/common/include/plat_private.h b/plat/rockchip/common/include/plat_private.h index e05bda41d..8cd762d06 100644 --- a/plat/rockchip/common/include/plat_private.h +++ b/plat/rockchip/common/include/plat_private.h @@ -110,6 +110,8 @@ void plat_setup_rockchip_pm_ops(struct rockchip_pm_ops_cb *ops); void platform_cpu_warmboot(void); +void plat_rockchip_gpio_init(void); + extern const unsigned char rockchip_power_domain_tree_desc[]; extern void *pmu_cpuson_entrypoint_start; diff --git a/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c b/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c new file mode 100644 index 000000000..eca9fbcc3 --- /dev/null +++ b/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +uint32_t gpio_port[] = { + GPIO0_BASE, + GPIO1_BASE, + GPIO2_BASE, + GPIO3_BASE, + GPIO4_BASE, +}; + +#define SWPORTA_DR 0x00 +#define SWPORTA_DDR 0x04 +#define EXT_PORTA 0x50 + +#define PMU_GPIO_PORT0 0 +#define PMU_GPIO_PORT1 1 + +#define PMU_GRF_GPIO0A_P 0x40 +#define GRF_GPIO2A_P 0xe040 +#define GPIO_P_MASK 0x03 + +/* + * gpio clock disabled when not operate + * so need to enable gpio clock before operate gpio + * after setting, need to disable gpio clock + * gate 1: disable clock; 0: enable clock + */ +static void gpio_clk(int gpio, uint32_t gate) +{ + uint32_t port = gpio / 32; + + assert(port < 5); + + switch (port) { + case 0: + mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1), + BITS_WITH_WMASK(gate, CLK_GATE_MASK, + PCLK_GPIO0_GATE_SHIFT)); + break; + case 1: + mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1), + BITS_WITH_WMASK(gate, CLK_GATE_MASK, + PCLK_GPIO1_GATE_SHIFT)); + break; + case 2: + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), + BITS_WITH_WMASK(gate, CLK_GATE_MASK, + PCLK_GPIO2_GATE_SHIFT)); + break; + case 3: + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), + BITS_WITH_WMASK(gate, CLK_GATE_MASK, + PCLK_GPIO3_GATE_SHIFT)); + + break; + case 4: + mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), + BITS_WITH_WMASK(gate, CLK_GATE_MASK, + PCLK_GPIO4_GATE_SHIFT)); + break; + default: + break; + } +} + +static void set_pull(int gpio, int pull) +{ + uint32_t port = gpio / 32; + uint32_t num = gpio % 32; + uint32_t bank = num / 8; + uint32_t id = num % 8; + + assert((port < 5) && (num < 32)); + + gpio_clk(gpio, 0); + + /* + * in gpio0a, gpio0b, gpio2c, gpio2d, + * 00: Z + * 01: pull down + * 10: Z + * 11: pull up + * different with other gpio, so need to correct it + */ + if (((port == 0) && (bank < 2)) || ((port == 2) && (bank > 2))) { + if (pull == GPIO_PULL_UP) + pull = 3; + else if (pull == GPIO_PULL_DOWN) + pull = 1; + else + pull = 0; + } + + if (port == PMU_GPIO_PORT0 || port == PMU_GPIO_PORT1) { + mmio_write_32(PMUGRF_BASE + PMU_GRF_GPIO0A_P + + port * 16 + bank * 4, + BITS_WITH_WMASK(pull, GPIO_P_MASK, id * 2)); + } else { + mmio_write_32(GRF_BASE + GRF_GPIO2A_P + + (port - 2) * 16 + bank * 4, + BITS_WITH_WMASK(pull, GPIO_P_MASK, id * 2)); + } + gpio_clk(gpio, 1); +} + +static void set_direction(int gpio, int direction) +{ + uint32_t port = gpio / 32; + uint32_t num = gpio % 32; + + assert((port < 5) && (num < 32)); + + gpio_clk(gpio, 0); + + /* + * in gpio.h + * #define GPIO_DIR_OUT 0 + * #define GPIO_DIR_IN 1 + * but rk3399 gpio direction 1: output, 0: input + * so need to revert direction value + */ + mmio_setbits_32(gpio_port[port] + SWPORTA_DDR, !direction << num); + gpio_clk(gpio, 1); +} + +static int get_direction(int gpio) +{ + uint32_t port = gpio / 32; + uint32_t num = gpio % 32; + int direction; + + assert((port < 5) && (num < 32)); + + gpio_clk(gpio, 0); + + /* + * in gpio.h + * #define GPIO_DIR_OUT 0 + * #define GPIO_DIR_IN 1 + * but rk3399 gpio direction 1: output, 0: input + * so need to revert direction value + */ + direction = !((mmio_read_32(gpio_port[port] + + SWPORTA_DDR) >> num) & 0x1); + gpio_clk(gpio, 1); + + return direction; +} + +static int get_value(int gpio) +{ + uint32_t port = gpio / 32; + uint32_t num = gpio % 32; + int value; + + assert((port < 5) && (num < 32)); + + gpio_clk(gpio, 0); + value = (mmio_read_32(gpio_port[port] + EXT_PORTA) >> num) & 0x1; + gpio_clk(gpio, 1); + + return value; +} + +static void set_value(int gpio, int value) +{ + uint32_t port = gpio / 32; + uint32_t num = gpio % 32; + + assert((port < 5) && (num < 32)); + + gpio_clk(gpio, 0); + mmio_clrsetbits_32(gpio_port[port] + SWPORTA_DR, 1 << num, + !!value << num); + gpio_clk(gpio, 0); +} + +const gpio_ops_t rk3399_gpio_ops = { + .get_direction = get_direction, + .set_direction = set_direction, + .get_value = get_value, + .set_value = set_value, + .set_pull = set_pull, +}; + +void plat_rockchip_gpio_init(void) +{ + gpio_init(&rk3399_gpio_ops); +} diff --git a/plat/rockchip/rk3399/drivers/soc/soc.c b/plat/rockchip/rk3399/drivers/soc/soc.c index 5b7613d75..bf2d44133 100644 --- a/plat/rockchip/rk3399/drivers/soc/soc.c +++ b/plat/rockchip/rk3399/drivers/soc/soc.c @@ -57,7 +57,18 @@ const mmap_region_t plat_rk_mmap[] = { MT_DEVICE | MT_RW | MT_SECURE), MAP_REGION_FLAT(PMUGRF_BASE, PMUGRF_SIZE, MT_DEVICE | MT_RW | MT_SECURE), - + MAP_REGION_FLAT(GPIO0_BASE, GPIO0_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(GPIO1_BASE, GPIO1_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(GPIO2_BASE, GPIO2_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(GPIO3_BASE, GPIO3_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(GPIO4_BASE, GPIO4_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(GRF_BASE, GRF_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), { 0 } }; @@ -349,4 +360,5 @@ void plat_rockchip_soc_init(void) dma_secure_cfg(0); sgrf_init(); soc_global_soft_reset_init(); + plat_rockchip_gpio_init(); } diff --git a/plat/rockchip/rk3399/drivers/soc/soc.h b/plat/rockchip/rk3399/drivers/soc/soc.h index e48f2f033..4c6f00010 100644 --- a/plat/rockchip/rk3399/drivers/soc/soc.h +++ b/plat/rockchip/rk3399/drivers/soc/soc.h @@ -72,6 +72,8 @@ #define REG_SIZE 0x04 #define REG_SOC_WMSK 0xffff0000 +#define CLK_GATE_MASK 0x01 + enum plls_id { ALPLL_ID = 0, ABPLL_ID, @@ -152,6 +154,11 @@ struct deepsleep_data_s { #define CRU_GLB_SRST_FST 0x0500 #define CRU_GLB_SRST_SND 0x0504 +#define CRU_CLKGATE_CON(n) (0x300 + n * 4) +#define PCLK_GPIO2_GATE_SHIFT 3 +#define PCLK_GPIO3_GATE_SHIFT 4 +#define PCLK_GPIO4_GATE_SHIFT 5 + /************************************************** * pmu cru reg, offset **************************************************/ @@ -167,6 +174,10 @@ struct deepsleep_data_s { #define CRU_PMU_FIRST_SFTRST_MSK (0x3 << 2) #define CRU_PMU_FIRST_SFTRST_EN 0x0 +#define CRU_PMU_CLKGATE_CON(n) (0x100 + n * 4) +#define PCLK_GPIO0_GATE_SHIFT 3 +#define PCLK_GPIO1_GATE_SHIFT 4 + /************************************************** * sgrf reg, offset **************************************************/ diff --git a/plat/rockchip/rk3399/include/platform_def.h b/plat/rockchip/rk3399/include/platform_def.h index f7da0e704..5f04db922 100644 --- a/plat/rockchip/rk3399/include/platform_def.h +++ b/plat/rockchip/rk3399/include/platform_def.h @@ -109,7 +109,7 @@ ******************************************************************************/ #define ADDR_SPACE_SIZE (1ull << 32) #define MAX_XLAT_TABLES 20 -#define MAX_MMAP_REGIONS 16 +#define MAX_MMAP_REGIONS 20 /******************************************************************************* * Declarations and constants to access the mailboxes safely. Each mailbox is diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk index 45064e7f8..fe1aabcb8 100644 --- a/plat/rockchip/rk3399/platform.mk +++ b/plat/rockchip/rk3399/platform.mk @@ -58,6 +58,7 @@ BL31_SOURCES += ${RK_GIC_SOURCES} drivers/ti/uart/16550_console.S \ drivers/delay_timer/delay_timer.c \ drivers/delay_timer/generic_delay_timer.c \ + drivers/gpio/gpio.c \ lib/cpus/aarch64/cortex_a53.S \ lib/cpus/aarch64/cortex_a72.S \ plat/common/aarch64/platform_mp_stack.S \ @@ -68,6 +69,7 @@ BL31_SOURCES += ${RK_GIC_SOURCES} ${RK_PLAT_COMMON}/plat_pm.c \ ${RK_PLAT_COMMON}/plat_topology.c \ ${RK_PLAT_COMMON}/aarch64/platform_common.c \ + ${RK_PLAT_SOC}/drivers/gpio/rk3399_gpio.c \ ${RK_PLAT_SOC}/drivers/pmu/pmu.c \ ${RK_PLAT_SOC}/drivers/soc/soc.c diff --git a/plat/rockchip/rk3399/rk3399_def.h b/plat/rockchip/rk3399/rk3399_def.h index b1fc1e6a4..ed3a42436 100644 --- a/plat/rockchip/rk3399/rk3399_def.h +++ b/plat/rockchip/rk3399/rk3399_def.h @@ -64,6 +64,24 @@ #define PMUGRF_BASE 0xff320000 #define PMUGRF_SIZE SIZE_K(64) +#define GPIO0_BASE 0xff720000 +#define GPIO0_SIZE SIZE_K(64) + +#define GPIO1_BASE 0xff730000 +#define GPIO1_SIZE SIZE_K(64) + +#define GPIO2_BASE 0xff780000 +#define GPIO2_SIZE SIZE_K(32) + +#define GPIO3_BASE 0xff788000 +#define GPIO3_SIZE SIZE_K(32) + +#define GPIO4_BASE 0xff790000 +#define GPIO4_SIZE SIZE_K(32) + +#define GRF_BASE 0xff770000 +#define GRF_SIZE SIZE_K(64) + /* * include i2c pmu/audio, pwm0-3 rkpwm0-3 uart_dbg,mailbox scr * 0xff650000 -0xff6c0000 From 68ff45f40ada5b571bb6b2e27e23f77526cb4014 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Wed, 25 May 2016 19:03:04 +0800 Subject: [PATCH 3/5] rockchip: add reset or power off gpio configuration for rk3399 We add plat parameter structs to support BL2 to pass variable-length, variable-type parameters to BL31. The parameters are structured as a link list. During bl31 setup time, we travse the list to process each parameter. throuth this way, we can get the reset or power off gpio parameter, and do hardware control in BL31. This structure also can pass other parameter to BL31 in future. --- plat/rockchip/common/bl31_plat_setup.c | 3 + plat/rockchip/common/include/plat_params.h | 91 +++++++++++++++++++++ plat/rockchip/common/include/plat_private.h | 4 + plat/rockchip/common/params_setup.c | 91 +++++++++++++++++++++ plat/rockchip/rk3368/platform.mk | 1 + plat/rockchip/rk3399/platform.mk | 1 + 6 files changed, 191 insertions(+) create mode 100644 plat/rockchip/common/include/plat_params.h create mode 100644 plat/rockchip/common/params_setup.c diff --git a/plat/rockchip/common/bl31_plat_setup.c b/plat/rockchip/common/bl31_plat_setup.c index 727a2c743..47a245a6c 100644 --- a/plat/rockchip/common/bl31_plat_setup.c +++ b/plat/rockchip/common/bl31_plat_setup.c @@ -120,6 +120,9 @@ void bl31_early_platform_setup(bl31_params_t *from_bl2, * Copy the code into pmusram. */ plat_rockchip_pmusram_prepare(); + + /* there may have some board sepcific message need to initialize */ + params_early_setup(plat_params_from_bl2); } /******************************************************************************* diff --git a/plat/rockchip/common/include/plat_params.h b/plat/rockchip/common/include/plat_params.h new file mode 100644 index 000000000..cad453535 --- /dev/null +++ b/plat/rockchip/common/include/plat_params.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __PLAT_PARAMS_H__ +#define __PLAT_PARAMS_H__ + +#include + +/* + * We defined several plat parameter structs for BL2 to pass platform related + * parameters to Rockchip BL31 platform code. All plat parameters start with + * a common header, which has a type field to indicate the parameter type, and + * a next pointer points to next parameter. If the parameter is the last one in + * the list, next pointer will points to NULL. After the header comes the + * variable-sized members that describe the parameter. The picture below shows + * how the parameters are kept in memory. + * + * head of list ---> +----------------+ --+ + * | type | | + * +----------------+ |--> struct bl31_plat_param + * +----| next | | + * | +----------------+ --+ + * | | parameter data | + * | +----------------+ + * | + * +--> +----------------+ --+ + * | type | | + * +----------------+ |--> struct bl31_plat_param + * NULL <---| next | | + * +----------------+ --+ + * | parameter data | + * +----------------+ + * + * Note: The SCTLR_EL3.A bit (Alignment fault check enable) of ARM TF is set, + * so be sure each parameter struct starts on 64-bit aligned address. If not, + * alignment fault will occur during accessing its data member. + */ + +/* param type */ +enum { + PARAM_NONE = 0, + PARAM_RESET, + PARAM_POWEROFF, +}; + +struct gpio_info { + uint8_t polarity; + uint8_t direction; + uint8_t pull_mode; + uint32_t index; +}; + +/* common header for all plat parameter type */ +struct bl31_plat_param { + uint64_t type; + void *next; +}; + +struct bl31_gpio_param { + struct bl31_plat_param h; + struct gpio_info gpio; +}; + +#endif /* __PLAT_PARAMS_H__ */ diff --git a/plat/rockchip/common/include/plat_private.h b/plat/rockchip/common/include/plat_private.h index 8cd762d06..031a3413e 100644 --- a/plat/rockchip/common/include/plat_private.h +++ b/plat/rockchip/common/include/plat_private.h @@ -97,6 +97,8 @@ void plat_cci_disable(void); void plat_delay_timer_init(void); +void params_early_setup(void *plat_params_from_bl2); + void plat_rockchip_gic_driver_init(void); void plat_rockchip_gic_init(void); void plat_rockchip_gic_cpuif_enable(void); @@ -110,6 +112,8 @@ void plat_setup_rockchip_pm_ops(struct rockchip_pm_ops_cb *ops); void platform_cpu_warmboot(void); +void *plat_get_rockchip_gpio_reset(void); +void *plat_get_rockchip_gpio_poweroff(void); void plat_rockchip_gpio_init(void); extern const unsigned char rockchip_power_domain_tree_desc[]; diff --git a/plat/rockchip/common/params_setup.c b/plat/rockchip/common/params_setup.c new file mode 100644 index 000000000..2a49556f4 --- /dev/null +++ b/plat/rockchip/common/params_setup.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct bl31_plat_param *bl31_params_head; +static struct bl31_gpio_param param_reset; +static struct bl31_gpio_param param_poweroff; +static struct gpio_info *rst_gpio; +static struct gpio_info *poweroff_gpio; + +void *plat_get_rockchip_gpio_reset(void) +{ + return rst_gpio; +} + +void *plat_get_rockchip_gpio_poweroff(void) +{ + return poweroff_gpio; +} + +void params_early_setup(void *plat_param_from_bl2) +{ + struct bl31_plat_param *param; + struct bl31_plat_param *bl2_param; + struct bl31_gpio_param *gpio_param; + + /* keep plat parameters for later processing if need */ + bl2_param = (struct bl31_plat_param *)plat_param_from_bl2; + while (bl2_param) { + switch (bl2_param->type) { + case PARAM_RESET: + param = (struct bl31_plat_param *)¶m_reset; + memcpy((void *)param, (void *)bl2_param, + sizeof(struct bl31_gpio_param)); + gpio_param = (struct bl31_gpio_param *)param; + rst_gpio = &gpio_param->gpio; + break; + case PARAM_POWEROFF: + param = (struct bl31_plat_param *)¶m_poweroff; + memcpy((void *)param, (void *)bl2_param, + sizeof(struct bl31_gpio_param)); + gpio_param = (struct bl31_gpio_param *)param; + poweroff_gpio = &gpio_param->gpio; + break; + default: + NOTICE("not expected type found\n"); + return; /* don't continue if unexpected type found */ + } + param->next = bl31_params_head; + bl31_params_head = param; + bl2_param = bl2_param->next; + } +} diff --git a/plat/rockchip/rk3368/platform.mk b/plat/rockchip/rk3368/platform.mk index 0e64b7e85..50eda3223 100644 --- a/plat/rockchip/rk3368/platform.mk +++ b/plat/rockchip/rk3368/platform.mk @@ -63,6 +63,7 @@ BL31_SOURCES += ${RK_GIC_SOURCES} \ plat/common/aarch64/platform_mp_stack.S \ ${RK_PLAT_COMMON}/aarch64/plat_helpers.S \ ${RK_PLAT_COMMON}/bl31_plat_setup.c \ + ${RK_PLAT_COMMON}/params_setup.c \ ${RK_PLAT_COMMON}/pmusram/pmu_sram_cpus_on.S \ ${RK_PLAT_COMMON}/pmusram/pmu_sram.c \ ${RK_PLAT_COMMON}/plat_pm.c \ diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk index fe1aabcb8..b0ce56f3a 100644 --- a/plat/rockchip/rk3399/platform.mk +++ b/plat/rockchip/rk3399/platform.mk @@ -64,6 +64,7 @@ BL31_SOURCES += ${RK_GIC_SOURCES} plat/common/aarch64/platform_mp_stack.S \ ${RK_PLAT_COMMON}/aarch64/plat_helpers.S \ ${RK_PLAT_COMMON}/bl31_plat_setup.c \ + ${RK_PLAT_COMMON}/params_setup.c \ ${RK_PLAT_COMMON}/pmusram/pmu_sram_cpus_on.S \ ${RK_PLAT_COMMON}/pmusram/pmu_sram.c \ ${RK_PLAT_COMMON}/plat_pm.c \ From 8867299f0518f9cdd658d3eaf6e7e744618ad217 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Wed, 25 May 2016 19:04:47 +0800 Subject: [PATCH 4/5] rockchip: support reset SoC through gpio for rk3399 If define a reset gpio, BL31 will use gpio to reset SOC, otherwise use CRU reset. --- plat/rockchip/rk3399/drivers/pmu/pmu.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.c b/plat/rockchip/rk3399/drivers/pmu/pmu.c index 859e89f5c..c5b281ae9 100644 --- a/plat/rockchip/rk3399/drivers/pmu/pmu.c +++ b/plat/rockchip/rk3399/drivers/pmu/pmu.c @@ -34,9 +34,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -384,6 +386,23 @@ static int sys_pwr_domain_resume(void) return 0; } +void __dead2 soc_soft_reset(void) +{ + struct gpio_info *rst_gpio; + + rst_gpio = (struct gpio_info *)plat_get_rockchip_gpio_reset(); + + if (rst_gpio) { + gpio_set_direction(rst_gpio->index, GPIO_DIR_OUT); + gpio_set_value(rst_gpio->index, rst_gpio->polarity); + } else { + soc_global_soft_reset(); + } + + while (1) + ; +} + static struct rockchip_pm_ops_cb pm_ops = { .cores_pwr_dm_on = cores_pwr_domain_on, .cores_pwr_dm_off = cores_pwr_domain_off, @@ -392,7 +411,7 @@ static struct rockchip_pm_ops_cb pm_ops = { .cores_pwr_dm_resume = cores_pwr_domain_resume, .sys_pwr_dm_suspend = sys_pwr_domain_suspend, .sys_pwr_dm_resume = sys_pwr_domain_resume, - .sys_gbl_soft_reset = soc_global_soft_reset, + .sys_gbl_soft_reset = soc_soft_reset, }; void plat_rockchip_pmu_init(void) From 86c253e450a6506a95d4fa846945b769026cf72c Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Wed, 25 May 2016 19:05:19 +0800 Subject: [PATCH 5/5] rockchip: support system off function for rk3399 if define power off gpio, BL31 will do system power off through gpio control. --- plat/rockchip/common/plat_pm.c | 11 +++++++++++ plat/rockchip/rk3399/drivers/pmu/pmu.c | 26 ++++++++++++++++++++++++++ plat/rockchip/rk3399/drivers/pmu/pmu.h | 2 ++ 3 files changed, 39 insertions(+) diff --git a/plat/rockchip/common/plat_pm.c b/plat/rockchip/common/plat_pm.c index 43558b65a..d20a683b3 100644 --- a/plat/rockchip/common/plat_pm.c +++ b/plat/rockchip/common/plat_pm.c @@ -252,6 +252,16 @@ static void __dead2 rockchip_system_reset(void) rockchip_ops->sys_gbl_soft_reset(); } +/******************************************************************************* + * RockChip handlers to power off the system + ******************************************************************************/ +static void __dead2 rockchip_system_poweroff(void) +{ + assert(rockchip_ops && rockchip_ops->system_off); + + rockchip_ops->system_off(); +} + /******************************************************************************* * Export the platform handlers via plat_rockchip_psci_pm_ops. The rockchip * standard @@ -265,6 +275,7 @@ const plat_psci_ops_t plat_rockchip_psci_pm_ops = { .pwr_domain_on_finish = rockchip_pwr_domain_on_finish, .pwr_domain_suspend_finish = rockchip_pwr_domain_suspend_finish, .system_reset = rockchip_system_reset, + .system_off = rockchip_system_poweroff, .validate_power_state = rockchip_validate_power_state, .get_sys_suspend_power_state = rockchip_get_sys_suspend_power_state }; diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.c b/plat/rockchip/rk3399/drivers/pmu/pmu.c index c5b281ae9..9b95621f5 100644 --- a/plat/rockchip/rk3399/drivers/pmu/pmu.c +++ b/plat/rockchip/rk3399/drivers/pmu/pmu.c @@ -403,6 +403,31 @@ void __dead2 soc_soft_reset(void) ; } +void __dead2 soc_system_off(void) +{ + struct gpio_info *poweroff_gpio; + + poweroff_gpio = (struct gpio_info *)plat_get_rockchip_gpio_poweroff(); + + if (poweroff_gpio) { + /* + * if use tsadc over temp pin(GPIO1A6) as shutdown gpio, + * need to set this pin iomux back to gpio function + */ + if (poweroff_gpio->index == TSADC_INT_PIN) { + mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO1A_IOMUX, + GPIO1A6_IOMUX); + } + gpio_set_direction(poweroff_gpio->index, GPIO_DIR_OUT); + gpio_set_value(poweroff_gpio->index, poweroff_gpio->polarity); + } else { + WARN("Do nothing when system off\n"); + } + + while (1) + ; +} + static struct rockchip_pm_ops_cb pm_ops = { .cores_pwr_dm_on = cores_pwr_domain_on, .cores_pwr_dm_off = cores_pwr_domain_off, @@ -412,6 +437,7 @@ static struct rockchip_pm_ops_cb pm_ops = { .sys_pwr_dm_suspend = sys_pwr_domain_suspend, .sys_pwr_dm_resume = sys_pwr_domain_resume, .sys_gbl_soft_reset = soc_soft_reset, + .system_off = soc_system_off, }; void plat_rockchip_pmu_init(void) diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.h b/plat/rockchip/rk3399/drivers/pmu/pmu.h index d5ff8ce09..8f935e98d 100644 --- a/plat/rockchip/rk3399/drivers/pmu/pmu.h +++ b/plat/rockchip/rk3399/drivers/pmu/pmu.h @@ -810,6 +810,8 @@ enum pmu_core_pwr_st { #define PMUGRF_GPIO1A_IOMUX 0x10 #define AP_PWROFF 0x0a +#define GPIO1A6_IOMUX BITS_WITH_WMASK(0, 3, 12) +#define TSADC_INT_PIN 38 #define CORES_PM_DISABLE 0x0 #define PD_CTR_LOOP 500