From b2b7ffdc878fb29bf9a09c079aab2c6d7de5058f Mon Sep 17 00:00:00 2001 From: zador-blood-stained Date: Fri, 29 Sep 2017 12:59:16 +0300 Subject: [PATCH] Remove unused ATF patches --- .../atf/atf-sun50iw1/01-add-SMC-mailbox.patch | 238 ------- .../02-add-handler-boilerplate.patch | 193 ------ .../atf-sun50iw1/03-add-clock-handling.patch | 208 ------ .../atf-sun50iw1/04-implement-CPU-clock.patch | 140 ---- .../05-allow-setting-CPU-voltage.patch | 78 --- .../atf-sun50iw1/06-refactor-poweroff.patch | 34 - .../atf-sun50iw1/07-refactor-power-code.patch | 648 ------------------ patch/atf/atf-sun50iw1/08-add-DVFS.patch | 195 ------ .../atf/atf-sun50iw1/09-add-THS-sensor.patch | 317 --------- .../10-add-device-power-state.patch | 233 ------- patch/atf/atf-sun50iw2/add-pc2-shutdown.patch | 65 -- 11 files changed, 2349 deletions(-) delete mode 100644 patch/atf/atf-sun50iw1/01-add-SMC-mailbox.patch delete mode 100644 patch/atf/atf-sun50iw1/02-add-handler-boilerplate.patch delete mode 100644 patch/atf/atf-sun50iw1/03-add-clock-handling.patch delete mode 100644 patch/atf/atf-sun50iw1/04-implement-CPU-clock.patch delete mode 100644 patch/atf/atf-sun50iw1/05-allow-setting-CPU-voltage.patch delete mode 100644 patch/atf/atf-sun50iw1/06-refactor-poweroff.patch delete mode 100644 patch/atf/atf-sun50iw1/07-refactor-power-code.patch delete mode 100644 patch/atf/atf-sun50iw1/08-add-DVFS.patch delete mode 100644 patch/atf/atf-sun50iw1/09-add-THS-sensor.patch delete mode 100644 patch/atf/atf-sun50iw1/10-add-device-power-state.patch delete mode 100644 patch/atf/atf-sun50iw2/add-pc2-shutdown.patch diff --git a/patch/atf/atf-sun50iw1/01-add-SMC-mailbox.patch b/patch/atf/atf-sun50iw1/01-add-SMC-mailbox.patch deleted file mode 100644 index 3a30a66ad2..0000000000 --- a/patch/atf/atf-sun50iw1/01-add-SMC-mailbox.patch +++ /dev/null @@ -1,238 +0,0 @@ -From 923ed37b583ad9f78ca36e0bb372e2d397a900af Mon Sep 17 00:00:00 2001 -From: Andre Przywara -Date: Tue, 12 Jul 2016 22:41:52 +0100 -Subject: [PATCH] sunxi: add smc service handler for an SMC mailbox - -The SCPI protocol uses a combination of a shared memory region and a -mailbox to signal requests from the application cores to the management -processor. However the Allwinner mailbox device in the A64 SoC can only -signal requests between the ARM cores and the OpenRISC core, not between -the ARM cores themselves. -As an alternative we can directly trigger SCPI requests by using an -smc instruction to call routines in the runtime code of ARM Trusted -Firmware (similar to what PSCI does). -Add a vendor defined (SiP) runtime service handler, which dispatches -incoming smc calls to the SCPI handler if the function ID matches. - -Signed-off-by: Andre Przywara ---- - plat/sun50iw1p1/bl31_sunxi_setup.c | 2 + - plat/sun50iw1p1/platform.mk | 1 + - plat/sun50iw1p1/sunxi_sip_svc.c | 123 +++++++++++++++++++++++++++++++++++++ - plat/sun50iw1p1/sunxi_sip_svc.h | 53 ++++++++++++++++ - 4 files changed, 179 insertions(+) - create mode 100644 plat/sun50iw1p1/sunxi_sip_svc.c - create mode 100644 plat/sun50iw1p1/sunxi_sip_svc.h - -diff --git a/plat/sun50iw1p1/bl31_sunxi_setup.c b/plat/sun50iw1p1/bl31_sunxi_setup.c -index 3e30814ff..5e71cc589 100644 ---- a/plat/sun50iw1p1/bl31_sunxi_setup.c -+++ b/plat/sun50iw1p1/bl31_sunxi_setup.c -@@ -255,6 +255,8 @@ void bl31_platform_setup(void) - } - - sunxi_setup_clocks(socid); -+ -+ NOTICE("SCPI: installed handler, implementation level: 000000\n"); - } - - /******************************************************************************* -diff --git a/plat/sun50iw1p1/platform.mk b/plat/sun50iw1p1/platform.mk -index b788f81f2..482b11567 100644 ---- a/plat/sun50iw1p1/platform.mk -+++ b/plat/sun50iw1p1/platform.mk -@@ -50,5 +50,6 @@ BL31_SOURCES += drivers/arm/gic/arm_gic.c \ - plat/sun50iw1p1/plat_topology.c \ - plat/sun50iw1p1/aarch64/plat_helpers.S \ - plat/sun50iw1p1/sunxi_clocks.c \ -+ plat/sun50iw1p1/sunxi_sip_svc.c \ - plat/sun50iw1p1/aarch64/sunxi_common.c - -diff --git a/plat/sun50iw1p1/sunxi_sip_svc.c b/plat/sun50iw1p1/sunxi_sip_svc.c -new file mode 100644 -index 000000000..827aa70eb ---- /dev/null -+++ b/plat/sun50iw1p1/sunxi_sip_svc.c -@@ -0,0 +1,123 @@ -+/* -+ * Copyright (c) 2016,2017 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 "sunxi_sip_svc.h" -+#include "sunxi_private.h" -+#include -+#include -+ -+/* SiP Service UUID */ -+DEFINE_SVC_UUID(sunxi_sip_svc_uid, -+ 0x06016e09, 0xd859, 0x4c24, 0xbb, 0x9d, -+ 0x18, 0x92, 0xb4, 0x8d, 0xa5, 0x03); -+ -+#pragma weak sunxi_plat_sip_handler -+uint64_t sunxi_plat_sip_handler(uint32_t smc_fid, -+ uint64_t x1, -+ uint64_t x2, -+ uint64_t x3, -+ uint64_t x4, -+ void *cookie, -+ void *handle, -+ uint64_t flags) -+{ -+ ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); -+ SMC_RET1(handle, SMC_UNK); -+} -+ -+/* -+ * This function handles Allwinner defined SiP Calls */ -+uint64_t sunxi_sip_handler(uint32_t smc_fid, -+ uint64_t x1, -+ uint64_t x2, -+ uint64_t x3, -+ uint64_t x4, -+ void *cookie, -+ void *handle, -+ uint64_t flags) -+{ -+ /* Determine which security state this SMC originated from */ -+ if (!is_caller_non_secure(flags)) -+ SMC_RET1(handle, SMC_UNK); -+ -+ /* SiP SMC service normal world's call */ -+ switch (smc_fid) { -+ case SUNXI_SIP_MBOX_TRIGGER: -+ SMC_RET1(handle, ~0); -+ } -+ -+ return sunxi_plat_sip_handler(smc_fid, x1, x2, x3, x4, -+ cookie, handle, flags); -+} -+ -+/* -+ * This function is responsible for handling all SiP calls from the NS world -+ */ -+uint64_t sip_smc_handler(uint32_t smc_fid, -+ uint64_t x1, -+ uint64_t x2, -+ uint64_t x3, -+ uint64_t x4, -+ void *cookie, -+ void *handle, -+ uint64_t flags) -+{ -+ switch (smc_fid) { -+ case SIP_SVC_CALL_COUNT: -+ /* Return the number of Allwinner SiP Service Calls. */ -+ SMC_RET1(handle, SUNXI_COMMON_SIP_NUM_CALLS); -+ -+ case SIP_SVC_UID: -+ /* Return UID to the caller */ -+ SMC_UUID_RET(handle, sunxi_sip_svc_uid); -+ -+ case SIP_SVC_VERSION: -+ /* Return the version of current implementation */ -+ SMC_RET2(handle, SUNXI_SIP_SVC_VERSION_MAJOR, -+ SUNXI_SIP_SVC_VERSION_MINOR); -+ -+ default: -+ return sunxi_sip_handler(smc_fid, x1, x2, x3, x4, -+ cookie, handle, flags); -+ } -+} -+ -+/* Define a runtime service descriptor for fast SMC calls */ -+DECLARE_RT_SVC( -+ sunxi_sip_svc, -+ OEN_SIP_START, -+ OEN_SIP_END, -+ SMC_TYPE_FAST, -+ NULL, -+ sip_smc_handler -+); -diff --git a/plat/sun50iw1p1/sunxi_sip_svc.h b/plat/sun50iw1p1/sunxi_sip_svc.h -new file mode 100644 -index 000000000..08d52bd7b ---- /dev/null -+++ b/plat/sun50iw1p1/sunxi_sip_svc.h -@@ -0,0 +1,53 @@ -+/* -+ * Copyright (c) 2016,2017 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_SIP_SVC_H__ -+#define __PLAT_SIP_SVC_H__ -+ -+#include -+ -+/* SMC function IDs for SiP Service queries */ -+#define SIP_SVC_CALL_COUNT 0x8200ff00 -+#define SIP_SVC_UID 0x8200ff01 -+/* 0x8200ff02 is reserved */ -+#define SIP_SVC_VERSION 0x8200ff03 -+ -+/* Allwinner SiP Service Calls version numbers */ -+#define SUNXI_SIP_SVC_VERSION_MAJOR 0x0 -+#define SUNXI_SIP_SVC_VERSION_MINOR 0x1 -+ -+#define SMC_AARCH64_BIT 0x40000000 -+ -+/* Number of Allwinner SiP Calls implemented */ -+#define SUNXI_COMMON_SIP_NUM_CALLS 1 -+ -+/* Allwinner SiP Service Calls function IDs */ -+#define SUNXI_SIP_MBOX_TRIGGER 0x82000001 -+ -+#endif /* __PLAT_SIP_SVC_H__ */ diff --git a/patch/atf/atf-sun50iw1/02-add-handler-boilerplate.patch b/patch/atf/atf-sun50iw1/02-add-handler-boilerplate.patch deleted file mode 100644 index 43ba715acd..0000000000 --- a/patch/atf/atf-sun50iw1/02-add-handler-boilerplate.patch +++ /dev/null @@ -1,193 +0,0 @@ -From dbba58ae9f77912f2d6661e8b06817327f1e3565 Mon Sep 17 00:00:00 2001 -From: Andre Przywara -Date: Mon, 8 Aug 2016 23:45:41 +0100 -Subject: [PATCH] sunxi: SCPI: add handler boilerplate - -Add the basic framework to handle request via the SCPI interface. This -reads and decodes the request found in the shared memory region, -provides the function framework to handle a certain command and takes -care about passing on the return value. -This for just the basic capability call is implemented. - -Signed-off-by: Andre Przywara ---- - plat/sun50iw1p1/bl31_sunxi_setup.c | 2 +- - plat/sun50iw1p1/platform.mk | 1 + - plat/sun50iw1p1/sunxi_private.h | 3 + - plat/sun50iw1p1/sunxi_scpi.c | 110 +++++++++++++++++++++++++++++++++++++ - plat/sun50iw1p1/sunxi_sip_svc.c | 7 ++- - 5 files changed, 120 insertions(+), 3 deletions(-) - create mode 100644 plat/sun50iw1p1/sunxi_scpi.c - -diff --git a/plat/sun50iw1p1/bl31_sunxi_setup.c b/plat/sun50iw1p1/bl31_sunxi_setup.c -index 5e71cc589..9e303f688 100644 ---- a/plat/sun50iw1p1/bl31_sunxi_setup.c -+++ b/plat/sun50iw1p1/bl31_sunxi_setup.c -@@ -256,7 +256,7 @@ void bl31_platform_setup(void) - - sunxi_setup_clocks(socid); - -- NOTICE("SCPI: installed handler, implementation level: 000000\n"); -+ NOTICE("SCPI: installed handler, implementation level: 100000\n"); - } - - /******************************************************************************* -diff --git a/plat/sun50iw1p1/platform.mk b/plat/sun50iw1p1/platform.mk -index 482b11567..188e4e84d 100644 ---- a/plat/sun50iw1p1/platform.mk -+++ b/plat/sun50iw1p1/platform.mk -@@ -51,5 +51,6 @@ BL31_SOURCES += drivers/arm/gic/arm_gic.c \ - plat/sun50iw1p1/aarch64/plat_helpers.S \ - plat/sun50iw1p1/sunxi_clocks.c \ - plat/sun50iw1p1/sunxi_sip_svc.c \ -+ plat/sun50iw1p1/sunxi_scpi.c \ - plat/sun50iw1p1/aarch64/sunxi_common.c - -diff --git a/plat/sun50iw1p1/sunxi_private.h b/plat/sun50iw1p1/sunxi_private.h -index aefa763c7..b07e56e79 100644 ---- a/plat/sun50iw1p1/sunxi_private.h -+++ b/plat/sun50iw1p1/sunxi_private.h -@@ -75,6 +75,9 @@ int sunxi_pmic_write(uint8_t address, uint8_t value); - void udelay(unsigned int delay); - int sunxi_setup_clocks(uint16_t socid); - -+/* Declarations for sunxi_scpi.c */ -+uint32_t sunxi_trigger_scpi(uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4); -+ - /* Gets the SPSR for BL33 entry */ - uint32_t sunxi_get_spsr_for_bl33_entry(int aarch); - -diff --git a/plat/sun50iw1p1/sunxi_scpi.c b/plat/sun50iw1p1/sunxi_scpi.c -new file mode 100644 -index 000000000..b13dfa7d5 ---- /dev/null -+++ b/plat/sun50iw1p1/sunxi_scpi.c -@@ -0,0 +1,110 @@ -+/* -+ * Copyright (c) 2016,2017 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 "sunxi_def.h" -+#include "sunxi_private.h" -+ -+#define BIT(n) (1U << (n)) -+#define GENMASK(hi, lo) (BIT(hi) - 1 - BIT(lo) + 1) -+ -+#define SCPI_OK 0 -+#define SCPI_E_PARAM 1 -+#define SCPI_E_ALIGN 2 -+#define SCPI_E_SIZE 3 -+#define SCPI_E_HANDLER 4 -+#define SCPI_E_ACCESS 5 -+#define SCPI_E_RANGE 6 -+#define SCPI_E_TIMEOUT 7 -+#define SCPI_E_NOMEM 8 -+#define SCPI_E_PWRSTATE 9 -+#define SCPI_E_SUPPORT 10 -+#define SCPI_E_DEVICE 11 -+#define SCPI_E_BUSY 12 -+ -+#define SCP_CMD_CAPABILITY 0x02 -+ -+#define SCP_CMDS_IMPLEMENTED \ -+ 0 -+ -+/* end of SRAM A1 */ -+#define SUNXI_SCPI_SHMEM_BASE 0x17e00 -+ -+static uint32_t scpi_handle_cmd(int cmd, uint8_t *payload_size, -+ uintptr_t payload_in, uintptr_t payload_out) -+{ -+ switch (cmd) { -+ case SCP_CMD_CAPABILITY: -+ mmio_write_32(payload_out + 0x00, (1U << 16) | (2U << 0)); -+ /* -+ * The SCPI spec says this field holds the payload sizes for -+ * the receive and transmit channel, but the Linux driver -+ * decodes an event version ID from it. -+ * Let's play nice with Linux for now and ignore the spec. -+ * -+ * mmio_write_32(payload_out + 0x04, -+ * ((256 - 1) << 16) | (256 - 1)); -+ */ -+ mmio_write_32(payload_out + 0x04, 1U << 16); -+ -+ mmio_write_32(payload_out + 0x08, 1U << 24); -+ mmio_write_32(payload_out + 0x0c, SCP_CMDS_IMPLEMENTED); -+ mmio_write_32(payload_out + 0x10, 0x0); -+ mmio_write_32(payload_out + 0x14, 0x0); -+ mmio_write_32(payload_out + 0x18, 0x0); -+ *payload_size = 0x1c; -+ return SCPI_OK; -+ } -+ -+ return SCPI_E_SUPPORT; -+} -+ -+uint32_t sunxi_trigger_scpi(uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4) -+{ -+ uint32_t ret; -+ uint64_t scpi_header; -+ uint8_t payload_size; -+ -+ scpi_header = *(uint64_t *)(SUNXI_SCPI_SHMEM_BASE + 0x100); -+ payload_size = (scpi_header >> 16) & 0xff; -+ -+ ret = scpi_handle_cmd(scpi_header & 0xff, &payload_size, -+ SUNXI_SCPI_SHMEM_BASE + 0x108, -+ SUNXI_SCPI_SHMEM_BASE + 0x8); -+ -+ mmio_write_32(SUNXI_SCPI_SHMEM_BASE, (scpi_header & 0xffff) | -+ (uint32_t)payload_size << 16); -+ mmio_write_32(SUNXI_SCPI_SHMEM_BASE + 4, ret); -+ -+ return ret; -+} -diff --git a/plat/sun50iw1p1/sunxi_sip_svc.c b/plat/sun50iw1p1/sunxi_sip_svc.c -index 827aa70eb..270b488f4 100644 ---- a/plat/sun50iw1p1/sunxi_sip_svc.c -+++ b/plat/sun50iw1p1/sunxi_sip_svc.c -@@ -72,8 +72,11 @@ uint64_t sunxi_sip_handler(uint32_t smc_fid, - - /* SiP SMC service normal world's call */ - switch (smc_fid) { -- case SUNXI_SIP_MBOX_TRIGGER: -- SMC_RET1(handle, ~0); -+ case SUNXI_SIP_MBOX_TRIGGER: { -+ uint32_t ret = sunxi_trigger_scpi(x1, x2, x3, x4); -+ -+ SMC_RET1(handle, ret); -+ } - } - - return sunxi_plat_sip_handler(smc_fid, x1, x2, x3, x4, diff --git a/patch/atf/atf-sun50iw1/03-add-clock-handling.patch b/patch/atf/atf-sun50iw1/03-add-clock-handling.patch deleted file mode 100644 index f2c8214221..0000000000 --- a/patch/atf/atf-sun50iw1/03-add-clock-handling.patch +++ /dev/null @@ -1,208 +0,0 @@ -From 426631883e372b3e95c94a148923396a11afc3ca Mon Sep 17 00:00:00 2001 -From: Andre Przywara -Date: Mon, 8 Aug 2016 23:45:41 +0100 -Subject: [PATCH] sunxi: SCPI: add clock handler framework - -SCPI features an interface to control and query clocks with a variable -frequency. -Implement the SCPI protocol part of that interface and provide a -framework to easily add any specific clock desired. - -Signed-off-by: Andre Przywara ---- - plat/sun50iw1p1/sunxi_clocks.c | 78 +++++++++++++++++++++++++++++++++++++++++ - plat/sun50iw1p1/sunxi_private.h | 8 +++++ - plat/sun50iw1p1/sunxi_scpi.c | 59 ++++++++++++++++++++++++++++++- - 3 files changed, 144 insertions(+), 1 deletion(-) - -diff --git a/plat/sun50iw1p1/sunxi_clocks.c b/plat/sun50iw1p1/sunxi_clocks.c -index ff02bfa14..1c5ec2975 100644 ---- a/plat/sun50iw1p1/sunxi_clocks.c -+++ b/plat/sun50iw1p1/sunxi_clocks.c -@@ -105,3 +105,81 @@ int sunxi_setup_clocks(uint16_t socid) - - return 0; - } -+ -+struct scpi_clock { -+ uint32_t min_freq; -+ uint32_t max_freq; -+ uint32_t (*getter)(uint32_t); -+ uint32_t (*setter)(uint32_t, uint32_t); -+ uint32_t reg_addr; -+ const char *name; -+ uint16_t clockid; -+}; -+ -+struct scpi_clock sunxi_clocks[] = { -+}; -+ -+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) -+ -+static struct scpi_clock *get_sunxi_clock(int clocknr) -+{ -+ if (clocknr < 0 || clocknr >= ARRAY_SIZE(sunxi_clocks)) -+ return NULL; -+ -+ return &sunxi_clocks[clocknr]; -+} -+ -+uint32_t sunxi_clock_get_min_rate(int clocknr) -+{ -+ struct scpi_clock *clk = get_sunxi_clock(clocknr); -+ -+ if (!clk) -+ return ~0; -+ -+ return clk->min_freq; -+} -+ -+uint32_t sunxi_clock_get_max_rate(int clocknr) -+{ -+ struct scpi_clock *clk = get_sunxi_clock(clocknr); -+ -+ if (!clk) -+ return ~0; -+ -+ return clk->max_freq; -+} -+ -+const char* sunxi_clock_get_name(int clocknr) -+{ -+ struct scpi_clock *clk = get_sunxi_clock(clocknr); -+ -+ if (!clk) -+ return NULL; -+ -+ return clk->name; -+} -+ -+uint32_t sunxi_clock_get_rate(int clocknr) -+{ -+ struct scpi_clock *clk = get_sunxi_clock(clocknr); -+ -+ if (!clk) -+ return ~0; -+ -+ return clk->getter(clk->reg_addr); -+} -+ -+int sunxi_clock_set_rate(int clocknr, uint32_t freq) -+{ -+ struct scpi_clock *clk = get_sunxi_clock(clocknr); -+ -+ if (!clk) -+ return ~0; -+ -+ return clk->setter(clk->reg_addr, freq); -+} -+ -+int sunxi_clock_nr_clocks(void) -+{ -+ return ARRAY_SIZE(sunxi_clocks); -+} -diff --git a/plat/sun50iw1p1/sunxi_private.h b/plat/sun50iw1p1/sunxi_private.h -index b07e56e79..08aeb94da 100644 ---- a/plat/sun50iw1p1/sunxi_private.h -+++ b/plat/sun50iw1p1/sunxi_private.h -@@ -78,6 +78,14 @@ int sunxi_setup_clocks(uint16_t socid); - /* Declarations for sunxi_scpi.c */ - uint32_t sunxi_trigger_scpi(uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4); - -+/* Declarations for sunxi_clocks.c */ -+int sunxi_clock_nr_clocks(void); -+uint32_t sunxi_clock_get_min_rate(int clocknr); -+uint32_t sunxi_clock_get_max_rate(int clocknr); -+const char* sunxi_clock_get_name(int clocknr); -+uint32_t sunxi_clock_get_rate(int clocknr); -+int sunxi_clock_set_rate(int clocknr, uint32_t freq); -+ - /* Gets the SPSR for BL33 entry */ - uint32_t sunxi_get_spsr_for_bl33_entry(int aarch); - -diff --git a/plat/sun50iw1p1/sunxi_scpi.c b/plat/sun50iw1p1/sunxi_scpi.c -index b13dfa7d5..3ca287ed2 100644 ---- a/plat/sun50iw1p1/sunxi_scpi.c -+++ b/plat/sun50iw1p1/sunxi_scpi.c -@@ -53,16 +53,42 @@ - #define SCPI_E_BUSY 12 - - #define SCP_CMD_CAPABILITY 0x02 -+#define SCP_CMD_CLOCKS_CAPS 0x0d -+#define SCP_CMD_CLOCK_GET_INFO 0x0e -+#define SCP_CMD_CLOCK_SET_RATE 0x0f -+#define SCP_CMD_CLOCK_GET_RATE 0x10 - - #define SCP_CMDS_IMPLEMENTED \ -- 0 -+ GENMASK(SCP_CMD_CLOCK_GET_RATE, SCP_CMD_CLOCKS_CAPS) - - /* end of SRAM A1 */ - #define SUNXI_SCPI_SHMEM_BASE 0x17e00 - -+static int write_clock_info(uintptr_t payload, int clocknr) -+{ -+ const char *name, *s; -+ int i; -+ -+ name = sunxi_clock_get_name(clocknr); -+ if (!name) -+ return -SCPI_E_PARAM; -+ -+ mmio_write_32(payload + 0x0, (clocknr & 0xffff) | (0x03 << 16)); -+ mmio_write_32(payload + 0x4, sunxi_clock_get_min_rate(clocknr)); -+ mmio_write_32(payload + 0x8, sunxi_clock_get_max_rate(clocknr)); -+ for (i = 0, s = name; s[i] != 0; i++) -+ mmio_write_8(payload + 12 + i, s[i]); -+ mmio_write_8(payload + 12 + i, 0); -+ -+ return 12 + i; -+} -+ - static uint32_t scpi_handle_cmd(int cmd, uint8_t *payload_size, - uintptr_t payload_in, uintptr_t payload_out) - { -+ uint32_t par1 = mmio_read_32(payload_in); -+ uint32_t ret; -+ - switch (cmd) { - case SCP_CMD_CAPABILITY: - mmio_write_32(payload_out + 0x00, (1U << 16) | (2U << 0)); -@@ -84,6 +110,37 @@ static uint32_t scpi_handle_cmd(int cmd, uint8_t *payload_size, - mmio_write_32(payload_out + 0x18, 0x0); - *payload_size = 0x1c; - return SCPI_OK; -+ case SCP_CMD_CLOCKS_CAPS: -+ /* number of implemented clocks */ -+ mmio_write_32(payload_out, sunxi_clock_nr_clocks()); -+ *payload_size = 0x4; -+ return SCPI_OK; -+ case SCP_CMD_CLOCK_GET_INFO: -+ ret = write_clock_info(payload_out, par1 & 0xffff); -+ if (ret < 0) { -+ *payload_size = 0; -+ return SCPI_E_PARAM; -+ } -+ -+ *payload_size = ret; -+ return SCPI_OK; -+ case SCP_CMD_CLOCK_SET_RATE: { -+ uint32_t freq = mmio_read_32(payload_in + 4); -+ -+ ret = sunxi_clock_set_rate(par1 & 0xffff, freq); -+ if (ret < 0) -+ return SCPI_E_RANGE; -+ *payload_size = 0; -+ return SCPI_OK; -+ } -+ case SCP_CMD_CLOCK_GET_RATE: -+ ret = sunxi_clock_get_rate(par1 & 0xffff); -+ if (ret == ~0) -+ return SCPI_E_RANGE; -+ -+ mmio_write_32(payload_out, ret); -+ *payload_size = 4; -+ return 0; - } - - return SCPI_E_SUPPORT; diff --git a/patch/atf/atf-sun50iw1/04-implement-CPU-clock.patch b/patch/atf/atf-sun50iw1/04-implement-CPU-clock.patch deleted file mode 100644 index 95e246ba8e..0000000000 --- a/patch/atf/atf-sun50iw1/04-implement-CPU-clock.patch +++ /dev/null @@ -1,140 +0,0 @@ -From a641a3a8523759cc73a79d062d934949620ba72f Mon Sep 17 00:00:00 2001 -From: Andre Przywara -Date: Thu, 22 Jun 2017 02:17:40 +0100 -Subject: [PATCH] sunxi: clocks: implement CPU clock and export as an SCPI - clock - -Add functions to read and set the frequency of the (single) CPU clock, -which is done via a register controlling the CPUX PLL. -This replaces the hardcoded reset value for the safe 816 MHz by a call -to that function. -Also export the CPU clock via the SCPI interface, so that any OS can -easily change that clock. - -Signed-off-by: Andre Przywara ---- - plat/sun50iw1p1/bl31_sunxi_setup.c | 2 +- - plat/sun50iw1p1/sunxi_clocks.c | 61 ++++++++++++++++++++++++++++++++++---- - plat/sun50iw1p1/sunxi_private.h | 2 ++ - 3 files changed, 59 insertions(+), 6 deletions(-) - -diff --git a/plat/sun50iw1p1/bl31_sunxi_setup.c b/plat/sun50iw1p1/bl31_sunxi_setup.c -index 9e303f688..dc9b3435a 100644 ---- a/plat/sun50iw1p1/bl31_sunxi_setup.c -+++ b/plat/sun50iw1p1/bl31_sunxi_setup.c -@@ -256,7 +256,7 @@ void bl31_platform_setup(void) - - sunxi_setup_clocks(socid); - -- NOTICE("SCPI: installed handler, implementation level: 100000\n"); -+ NOTICE("SCPI: installed handler, implementation level: 101000\n"); - } - - /******************************************************************************* -diff --git a/plat/sun50iw1p1/sunxi_clocks.c b/plat/sun50iw1p1/sunxi_clocks.c -index 1c5ec2975..21e3b7cf8 100644 ---- a/plat/sun50iw1p1/sunxi_clocks.c -+++ b/plat/sun50iw1p1/sunxi_clocks.c -@@ -33,9 +33,10 @@ - #include - #include "sunxi_private.h" - --#define PLL_CPUX_1008MHZ 0x1410 --#define PLL_CPUX_816MHZ 0x1010 --#define PLL_CPUX_408MHZ 0x1000 -+#define INITIAL_CPU_FREQ 816 -+ -+#define MHz(f) ((f) * 1000000) -+#define inMHz(mhzf) ((mhzf) / 1000000) - - static void mmio_clrsetbits32(uintptr_t addr, uint32_t mask, uint32_t bits) - { -@@ -64,6 +65,27 @@ static int pll_wait_until_stable(uintptr_t addr) - return 0; - } - -+int sunxi_clock_set_cpu_clock(uint32_t freq_mhz, int enable) -+{ -+ int n, k = 1, m = 1, factor; -+ uint32_t reg; -+ -+ factor = freq_mhz / 24; -+ if (factor < 10 || factor > 88) -+ return -1; -+ -+ for (n = factor; n > 33 && k < 5; ++k, n = factor / k) -+ ; -+ -+ reg = (m - 1) | ((k - 1) << 4) | ((n - 1) << 8); -+ if (enable) -+ reg |= PLL_ENABLE_BIT; -+ -+ mmio_write_32(CCMU_PLL_CPUX_CTRL_REG, reg); -+ -+ return 24 * n * k / m; -+} -+ - int sunxi_setup_clocks(uint16_t socid) - { - uint32_t reg; -@@ -80,8 +102,8 @@ int sunxi_setup_clocks(uint16_t socid) - AXI_CLKDIV(3) )); - udelay(20); - -- /* Set to 816MHz, but don't enable yet. */ -- mmio_write_32(CCMU_PLL_CPUX_CTRL_REG, PLL_CPUX_816MHZ); -+ /* Setup the clock parameters, but don't enable yet. */ -+ sunxi_clock_set_cpu_clock(INITIAL_CPU_FREQ, 0); - - /* Enable PLL_CPUX again */ - mmio_setbits32(CCMU_PLL_CPUX_CTRL_REG, PLL_ENABLE_BIT); -@@ -116,7 +138,36 @@ struct scpi_clock { - uint16_t clockid; - }; - -+static uint32_t set_cpu_clk_rate(uint32_t reg_addr, uint32_t freq) -+{ -+ return sunxi_clock_set_cpu_clock(inMHz(freq), 1); -+} -+ -+static uint32_t get_cpu_clk_rate(uint32_t reg_addr) -+{ -+ uint32_t clkreg = mmio_read_32(reg_addr); -+ int n, k, m, p; -+ -+ if (!(clkreg & PLL_ENABLE_BIT)) -+ return 0; -+ -+ n = ((clkreg >> 8) & 0x1f) + 1; -+ k = ((clkreg >> 4) & 0x03) + 1; -+ m = ((clkreg >> 0) & 0x03) + 1; -+ p = 1 << ((clkreg >> 16) & 0x3); -+ -+ return MHz(24) * n * k / (m * p); -+} -+ -+#define CPU_CLK_DESC \ -+ {.min_freq = MHz(240), .max_freq= MHz(1536), \ -+ .getter = get_cpu_clk_rate, .setter = set_cpu_clk_rate, \ -+ .reg_addr = CCMU_PLL_CPUX_CTRL_REG, \ -+ .name = "cpu_clk", \ -+ .clockid = 0 } -+ - struct scpi_clock sunxi_clocks[] = { -+ CPU_CLK_DESC, - }; - - #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) -diff --git a/plat/sun50iw1p1/sunxi_private.h b/plat/sun50iw1p1/sunxi_private.h -index 08aeb94da..519422343 100644 ---- a/plat/sun50iw1p1/sunxi_private.h -+++ b/plat/sun50iw1p1/sunxi_private.h -@@ -86,6 +86,8 @@ const char* sunxi_clock_get_name(int clocknr); - uint32_t sunxi_clock_get_rate(int clocknr); - int sunxi_clock_set_rate(int clocknr, uint32_t freq); - -+int sunxi_clock_set_cpu_clock(uint32_t freq_mhz, int enable); -+ - /* Gets the SPSR for BL33 entry */ - uint32_t sunxi_get_spsr_for_bl33_entry(int aarch); - diff --git a/patch/atf/atf-sun50iw1/05-allow-setting-CPU-voltage.patch b/patch/atf/atf-sun50iw1/05-allow-setting-CPU-voltage.patch deleted file mode 100644 index 8a52235c33..0000000000 --- a/patch/atf/atf-sun50iw1/05-allow-setting-CPU-voltage.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 8d1687f42bf86fe8197950b86a50936e28054534 Mon Sep 17 00:00:00 2001 -From: Andre Przywara -Date: Sat, 10 Dec 2016 12:21:38 +0000 -Subject: [PATCH] sunxi: power: allow setting CPU voltage - -Provide high level functions to allow programming certain voltages for -the CPU cores. This calculates the respective AXP803 register value for -the DCDC2/DCDC3 pair from a given voltage. -Also this allow to turn the CPU cores off completely, to easily -implement a shutdown functionality. - -Signed-off-by: Andre Przywara ---- - plat/sun50iw1p1/sunxi_power.c | 30 ++++++++++++++++++++++++++++++ - plat/sun50iw1p1/sunxi_private.h | 2 ++ - 2 files changed, 32 insertions(+) - -diff --git a/plat/sun50iw1p1/sunxi_power.c b/plat/sun50iw1p1/sunxi_power.c -index 0c2487e20..095a0e757 100644 ---- a/plat/sun50iw1p1/sunxi_power.c -+++ b/plat/sun50iw1p1/sunxi_power.c -@@ -176,6 +176,31 @@ static void rsb_wait(const char *desc) - ERROR("%s: 0x%x\n", desc, reg); - } - -+static int axp803_set_cpu_voltage(int millivolt) -+{ -+ uint8_t reg; -+ -+ if (millivolt <= 0) { /* power off system */ -+ sunxi_pmic_write(0x32, sunxi_pmic_read(0x32) | 0x80); -+ return 0; /* hopefully not ... */ -+ } -+ -+ if (millivolt < 800 || millivolt > 1300) -+ return -1; -+ -+ if (millivolt > 1200) -+ reg = (millivolt - 1200) / 20 + 70; -+ else -+ reg = (millivolt - 500) / 10 + 0; -+ -+ sunxi_pmic_write(0x21, reg); /* DCDC2 */ -+ -+ while (!(sunxi_pmic_read(0x21) & 0x80)) -+ ; -+ -+ return 0; -+} -+ - /* Initialize the RSB PMIC connection. */ - static int pmic_init(uint16_t hw_addr, uint8_t rt_addr) - { -@@ -266,6 +291,11 @@ static int pmic_setup(void) - - sunxi_pmic_write(0x15, 0x1a); /* DLDO1 = VCC3V3_HDMI voltage = 3.3V */ - -+ ret = sunxi_rsb_read(0x14); -+ sunxi_rsb_write(0x14, ret | 0x40); /* DCDC2/3 dual phase */ -+ -+ axp803_set_cpu_voltage(1100); -+ - return 0; - } - -diff --git a/plat/sun50iw1p1/sunxi_private.h b/plat/sun50iw1p1/sunxi_private.h -index 519422343..0c8b640bd 100644 ---- a/plat/sun50iw1p1/sunxi_private.h -+++ b/plat/sun50iw1p1/sunxi_private.h -@@ -72,6 +72,8 @@ int sunxi_pmic_setup(void); - int sunxi_pmic_read(uint8_t address); - int sunxi_pmic_write(uint8_t address, uint8_t value); - -+int sunxi_power_set_cpu_voltage(int millivolt); -+ - void udelay(unsigned int delay); - int sunxi_setup_clocks(uint16_t socid); - diff --git a/patch/atf/atf-sun50iw1/06-refactor-poweroff.patch b/patch/atf/atf-sun50iw1/06-refactor-poweroff.patch deleted file mode 100644 index eccbe13851..0000000000 --- a/patch/atf/atf-sun50iw1/06-refactor-poweroff.patch +++ /dev/null @@ -1,34 +0,0 @@ -From b3272daf1df2eb8b96654d2884eab391f85549ea Mon Sep 17 00:00:00 2001 -From: Andre Przywara -Date: Fri, 16 Dec 2016 01:32:36 +0000 -Subject: [PATCH] sunxi: power: move system power off into set_voltage() - function - -Instead of directly poking the appropriate AXP PMIC register to turn the -voltage for the ARM CPU cores off completely, call the newly exported -function to set the CPU voltage with a negative argument. -This abstracts the power off functionality from the actual PMIC used. - -Signed-off-by: Andre Przywara ---- - plat/sun50iw1p1/plat_pm.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/plat/sun50iw1p1/plat_pm.c b/plat/sun50iw1p1/plat_pm.c -index ec26248e0..c2ef5a6b7 100644 ---- a/plat/sun50iw1p1/plat_pm.c -+++ b/plat/sun50iw1p1/plat_pm.c -@@ -254,8 +254,11 @@ static int32_t sunxi_affinst_suspend_finish(uint64_t mpidr, - ******************************************************************************/ - static void __dead2 sunxi_system_off(void) - { -- sunxi_pmic_write(0x32, sunxi_pmic_read(0x32) | 0x80); -- ERROR("PSCI system shutdown: still alive ...\n"); -+ int ret; -+ -+ ret = sunxi_power_set_cpu_voltage(-1); -+ -+ ERROR("PSCI system shutdown: %d: still alive ...\n", ret); - - wfi(); - panic(); diff --git a/patch/atf/atf-sun50iw1/07-refactor-power-code.patch b/patch/atf/atf-sun50iw1/07-refactor-power-code.patch deleted file mode 100644 index 5e17504fa4..0000000000 --- a/patch/atf/atf-sun50iw1/07-refactor-power-code.patch +++ /dev/null @@ -1,648 +0,0 @@ -From 7f15fa4721edf35fa3eb6494c9518379eea4604d Mon Sep 17 00:00:00 2001 -From: Andre Przywara -Date: Sun, 19 Mar 2017 01:02:19 +0000 -Subject: [PATCH] sunxi: power: refactor power specific code into extra file - -At the moment the power code mixes the code to access the RSB bus with -the actual PMIC register control and setup via this bus. -Separate those two to make the code more readable, also to provide -better abstraction. -This for instance later allows using I2C to control different PMICs, -for instance. - -Signed-off-by: Andre Przywara ---- - plat/sun50iw1p1/bl31_sunxi_setup.c | 8 +- - plat/sun50iw1p1/platform.mk | 1 + - plat/sun50iw1p1/sunxi_power.c | 278 +++++++++++-------------------------- - plat/sun50iw1p1/sunxi_private.h | 9 +- - plat/sun50iw1p1/sunxi_rsb.c | 198 ++++++++++++++++++++++++++ - 5 files changed, 286 insertions(+), 208 deletions(-) - create mode 100644 plat/sun50iw1p1/sunxi_rsb.c - -diff --git a/plat/sun50iw1p1/bl31_sunxi_setup.c b/plat/sun50iw1p1/bl31_sunxi_setup.c -index dc9b3435a..7c1109f4e 100644 ---- a/plat/sun50iw1p1/bl31_sunxi_setup.c -+++ b/plat/sun50iw1p1/bl31_sunxi_setup.c -@@ -246,13 +246,7 @@ void bl31_platform_setup(void) - /* Detect if this SoC is a multi-cluster one. */ - plat_setup_topology(); - -- switch (socid) { -- case 0x1689: -- sunxi_pmic_setup(); -- break; -- case 0x1718: -- break; -- } -+ sunxi_power_setup(socid); - - sunxi_setup_clocks(socid); - -diff --git a/plat/sun50iw1p1/platform.mk b/plat/sun50iw1p1/platform.mk -index 188e4e84d..95cff562f 100644 ---- a/plat/sun50iw1p1/platform.mk -+++ b/plat/sun50iw1p1/platform.mk -@@ -52,5 +52,6 @@ BL31_SOURCES += drivers/arm/gic/arm_gic.c \ - plat/sun50iw1p1/sunxi_clocks.c \ - plat/sun50iw1p1/sunxi_sip_svc.c \ - plat/sun50iw1p1/sunxi_scpi.c \ -+ plat/sun50iw1p1/sunxi_rsb.c \ - plat/sun50iw1p1/aarch64/sunxi_common.c - -diff --git a/plat/sun50iw1p1/sunxi_power.c b/plat/sun50iw1p1/sunxi_power.c -index 095a0e757..5aa63fe4f 100644 ---- a/plat/sun50iw1p1/sunxi_power.c -+++ b/plat/sun50iw1p1/sunxi_power.c -@@ -35,153 +35,17 @@ - #include "sunxi_def.h" - #include "sunxi_private.h" - --#define R_PRCM_BASE 0x1f01400ULL --#define R_TWI_BASE 0x1f02400ULL --#define R_PIO_BASE 0x1f02c00ULL -- --#define RSB_BASE 0x1f03400ULL --#define RSB_CTRL 0x00 --#define RSB_CCR 0x04 --#define RSB_INTE 0x08 --#define RSB_STAT 0x0c --#define RSB_DADDR0 0x10 --#define RSB_DLEN 0x18 --#define RSB_DATA0 0x1c --#define RSB_LCR 0x24 --#define RSB_PMCR 0x28 --#define RSB_CMD 0x2c --#define RSB_SADDR 0x30 -- --#define RSBCMD_SRTA 0xE8 --#define RSBCMD_RD8 0x8B --#define RSBCMD_RD16 0x9C --#define RSBCMD_RD32 0xA6 --#define RSBCMD_WR8 0x4E --#define RSBCMD_WR16 0x59 --#define RSBCMD_WR32 0x63 -- - #define BIT(n) (1U << (n)) - - #define RUNTIME_ADDR 0x2d - #define AXP803_HW_ADDR 0x3a3 - --/* Initialize the RSB controller and its pins. */ --static int init_rsb(void) --{ -- uint32_t reg; -- -- /* un-gate PIO clock */ -- reg = mmio_read_32(R_PRCM_BASE + 0x28); -- mmio_write_32(R_PRCM_BASE + 0x28, reg | 0x01); -- -- /* get currently configured function for pins PL0 and PL1 */ -- reg = mmio_read_32(R_PIO_BASE + 0x00); -- if ((reg & 0xff) == 0x33) { -- NOTICE("already configured for TWI\n"); -- return -EBUSY; -- } -- -- if ((reg & 0xff) == 0x22) { -- NOTICE("PMIC: already configured for RSB\n"); -- return -EEXIST; /* configured for RSB mode already */ -- } -- -- /* switch pins PL0 and PL1 to RSB */ -- mmio_write_32(R_PIO_BASE + 0, (reg & ~0xff) | 0x22); -- -- /* level 2 drive strength */ -- reg = mmio_read_32(R_PIO_BASE + 0x14); -- mmio_write_32(R_PIO_BASE + 0x14, (reg & ~0x0f) | 0xa); -- -- /* set both ports to pull-up */ -- reg = mmio_read_32(R_PIO_BASE + 0x1c); -- mmio_write_32(R_PIO_BASE + 0x1c, (reg & ~0x0f) | 0x5); -- -- /* assert & de-assert reset of RSB */ -- reg = mmio_read_32(R_PRCM_BASE + 0xb0); -- mmio_write_32(R_PRCM_BASE + 0xb0, reg & ~0x08); -- reg = mmio_read_32(R_PRCM_BASE + 0xb0); -- mmio_write_32(R_PRCM_BASE + 0xb0, reg | 0x08); -- -- /* un-gate RSB clock */ -- reg = mmio_read_32(R_PRCM_BASE + 0x28); -- mmio_write_32(R_PRCM_BASE + 0x28, reg | 0x08); -- -- mmio_write_32(RSB_BASE + RSB_CTRL, 0x01); /* soft reset */ -- -- mmio_write_32(RSB_BASE + RSB_CCR, 0x11d); /* clock to 400 KHz */ -- -- do { -- reg = mmio_read_32(RSB_BASE + RSB_CTRL); -- } while (reg & 1); /* transaction in progress */ -- -- return 0; --} -- --int sunxi_pmic_read(uint8_t address) --{ -- uint32_t reg; -- -- mmio_write_32(RSB_BASE + RSB_DLEN, 0x10); /* read a byte, snake oil? */ -- mmio_write_32(RSB_BASE + RSB_CMD, RSBCMD_RD8); /* read a byte */ -- mmio_write_32(RSB_BASE + RSB_DADDR0, address); -- mmio_write_32(RSB_BASE + RSB_CTRL, 0x80); /* start transaction */ -- do { -- reg = mmio_read_32(RSB_BASE + RSB_CTRL); -- } while (reg & 0x80); /* transaction in progress */ -- -- reg = mmio_read_32(RSB_BASE + RSB_STAT); -- if (reg == 0x01) { /* transaction complete */ -- reg = mmio_read_32(RSB_BASE + RSB_DATA0); /* result register */ -- return reg & 0xff; -- } -- -- return -reg; --} -- --int sunxi_pmic_write(uint8_t address, uint8_t value) --{ -- uint32_t reg; -- -- mmio_write_32(RSB_BASE + RSB_DLEN, 0x00); /* write a byte, snake oil? */ -- mmio_write_32(RSB_BASE + RSB_CMD, RSBCMD_WR8); /* write a byte */ -- mmio_write_32(RSB_BASE + RSB_DADDR0, address); -- mmio_write_32(RSB_BASE + RSB_DATA0, value); -- mmio_write_32(RSB_BASE + RSB_CTRL, 0x80); /* start transaction */ -- do { -- reg = mmio_read_32(RSB_BASE + RSB_CTRL); -- } while (reg & 0x80); /* transaction in progress */ -- -- reg = mmio_read_32(RSB_BASE + RSB_STAT); -- if (reg == 0x01) /* transaction complete */ -- return 0; -- -- return -reg; --} -- --static void rsb_wait(const char *desc) --{ -- uint32_t reg; -- int cnt = 0; -- -- do { -- reg = mmio_read_32(RSB_BASE + RSB_CTRL); -- cnt++; -- } while (reg & 0x80); /* transaction in progress */ -- -- reg = mmio_read_32(RSB_BASE + RSB_STAT); -- if (reg == 0x01) -- return; -- -- ERROR("%s: 0x%x\n", desc, reg); --} -- - static int axp803_set_cpu_voltage(int millivolt) - { - uint8_t reg; - - if (millivolt <= 0) { /* power off system */ -- sunxi_pmic_write(0x32, sunxi_pmic_read(0x32) | 0x80); -+ sunxi_rsb_write(0x32, sunxi_rsb_read(0x32) | 0x80); - return 0; /* hopefully not ... */ - } - -@@ -193,56 +57,30 @@ static int axp803_set_cpu_voltage(int millivolt) - else - reg = (millivolt - 500) / 10 + 0; - -- sunxi_pmic_write(0x21, reg); /* DCDC2 */ -+ sunxi_rsb_write(0x21, reg); /* DCDC2 */ - -- while (!(sunxi_pmic_read(0x21) & 0x80)) -+ while (!(sunxi_rsb_read(0x21) & 0x80)) - ; - - return 0; - } - --/* Initialize the RSB PMIC connection. */ --static int pmic_init(uint16_t hw_addr, uint8_t rt_addr) --{ -- int ret; -- -- /* Switch PMIC to RSB mode */ -- mmio_write_32(RSB_BASE + RSB_PMCR, -- 0x00 | (0x3e << 8) | (0x7c << 16) | BIT(31)); -- do { -- ret = mmio_read_32(RSB_BASE + RSB_PMCR); -- } while (ret & (1U << 31)); /* transaction in progress */ -- -- mmio_write_32(RSB_BASE + RSB_CCR, 0x103); /* 3 MHz */ -- -- mmio_write_32(RSB_BASE + RSB_SADDR, hw_addr | (rt_addr << 16)); -- mmio_write_32(RSB_BASE + RSB_CMD, RSBCMD_SRTA); -- mmio_write_32(RSB_BASE + RSB_CTRL, 0x80); -- rsb_wait("set run-time address"); -- -- /* Set slave runtime address */ -- mmio_write_32(RSB_BASE + RSB_SADDR, rt_addr << 16); -- -- ret = sunxi_pmic_read(0x03); -- if (ret < 0) { -- ERROR("PMIC: error %d reading PMIC type\n", ret); -- return -2; -- } -- -- if ((ret & 0xcf) != 0x41) { -- ERROR("PMIC: unknown PMIC type number 0x%x\n", ret); -- return -3; -- } -- -- return 0; --} -- --/* Setup the PMIC: DCDC1 to 3.3V, enable DC1SW and DLDO4 */ --static int pmic_setup(void) -+/* -+ * Initial PMIC setup for boards using the AXP803 PMIC. -+ * DCDC1 must be corrected to 3.3 volts. Also we enable: -+ * - DC1SW: Ethernet PHY on most boards -+ * - DLDO1: HDMI power -+ * - DLDO4: WiFi power -+ * Technically those should be enabled by the users (via SCPI), but until -+ * U-Boot learns how to do this we do it here. -+ * Also this contains a quirk to fix the DRAM voltage on Pine64 boards, -+ * which have a wrong default (1.24V instead of 1.36V). -+ */ -+static int axp803_initial_setup(void) - { - int ret; - -- ret = sunxi_pmic_read(0x20); -+ ret = sunxi_rsb_read(0x20); - if (ret != 0x0e && ret != 0x11) { - int voltage = (ret & 0x1f) * 10 + 16; - -@@ -253,14 +91,14 @@ static int pmic_setup(void) - - if (ret != 0x11) { - /* Set DCDC1 voltage to 3.3 Volts */ -- ret = sunxi_pmic_write(0x20, 0x11); -+ ret = sunxi_rsb_write(0x20, 0x11); - if (ret < 0) { - NOTICE("PMIC: error %d writing DCDC1 voltage\n", ret); - return -2; - } - } - -- ret = sunxi_pmic_read(0x12); -+ ret = sunxi_rsb_read(0x12); - if ((ret & 0x37) != 0x01) { - NOTICE("PMIC: Output power control 2 is an unexpected 0x%x\n", - ret); -@@ -268,10 +106,12 @@ static int pmic_setup(void) - } - - if ((ret & 0xc9) != 0xc9) { -- /* Enable DC1SW to power PHY, DLDO4 for WiFi and DLDO1 for HDMI */ -- ret = sunxi_pmic_write(0x12, ret | 0xc8); -+ /* Enable DC1SW to power PHY, DLDO4 for WiFi, DLDO1 for HDMI */ -+ /* TODO: keep WiFi disabled, as not needed in U-Boot? */ -+ ret = sunxi_rsb_write(0x12, ret | 0xc8); - if (ret < 0) { -- NOTICE("PMIC: error %d enabling DC1SW/DLDO4/DLDO1\n", ret); -+ NOTICE("PMIC: error %d enabling DC1SW/DLDO4/DLDO1\n", -+ ret); - return -4; - } - } -@@ -283,13 +123,13 @@ static int pmic_setup(void) - * changes. This should be further confined once we are able to - * reliably detect a Pine64 board. - */ -- ret = sunxi_pmic_read(0x24); /* read DCDC5 register */ -+ ret = sunxi_rsb_read(0x24); /* read DCDC5 register */ - if ((ret & 0x7f) == 0x26) { /* check for 1.24V value */ - NOTICE("PMIC: fixing DRAM voltage from 1.24V to 1.36V\n"); -- sunxi_pmic_write(0x24, 0x2c); -+ sunxi_rsb_write(0x24, 0x2c); - } - -- sunxi_pmic_write(0x15, 0x1a); /* DLDO1 = VCC3V3_HDMI voltage = 3.3V */ -+ sunxi_rsb_write(0x15, 0x1a); /* DLDO1 = VCC3V3_HDMI voltage = 3.3V */ - - ret = sunxi_rsb_read(0x14); - sunxi_rsb_write(0x14, ret | 0x40); /* DCDC2/3 dual phase */ -@@ -302,31 +142,69 @@ static int pmic_setup(void) - /* - * Program the AXP803 via the RSB bus. - */ --int sunxi_pmic_setup(void) -+static int axp803_probe(void) - { - int ret; - -- NOTICE("Configuring AXP PMIC\n"); -- -- ret = init_rsb(); -+ ret = sunxi_rsb_init(); - if (ret && ret != -EEXIST) { - ERROR("Could not init RSB controller.\n"); - return -1; - } - -- if (ret != -EEXIST) { -- ret = pmic_init(AXP803_HW_ADDR, RUNTIME_ADDR); -+ if (ret == -EEXIST) -+ return ret; -+ -+ ret = sunxi_rsb_configure(AXP803_HW_ADDR, RUNTIME_ADDR); -+ if (ret) { -+ ERROR("Could not configure RSB.\n"); -+ return -2; -+ } -+ ret = sunxi_rsb_read(0x03); -+ if (ret < 0) { -+ ERROR("PMIC: error %d reading PMIC type\n", ret); -+ return -2; -+ } -+ if ((ret & 0xcf) != 0x41) { -+ ERROR("PMIC: unknown PMIC type number 0x%x\n", ret); -+ return -3; -+ } -+ -+ return 0; -+} -+ -+enum pmic_type { -+ PMIC_AXP803, -+} pmic_type; -+ -+int sunxi_power_setup(uint16_t socid) -+{ -+ int ret; -+ -+ switch (socid) { -+ case 0x1689: -+ pmic_type = PMIC_AXP803; -+ -+ NOTICE("PMIC: Probing for AXP803 on A64\n"); -+ ret = axp803_probe(); - if (ret) { -- ERROR("Could not connect to AXP PMIC.\n"); -- return -2; -+ ERROR("PMIC: AXP803 initialization failed: %d\n", ret); -+ return ret; -+ } -+ ret = axp803_initial_setup(); -+ if (ret) { -+ ERROR("PMIC: AXP803 power setup failed: %d\n", ret); -+ return ret; - } -+ NOTICE("PMIC: AXP803 successfully setup\n"); -+ break; -+ case 0x1718: -+ ret = -ENXIO; -+ break; -+ default: -+ NOTICE("power setup not defined for SoC 0x%04x\n", socid); -+ ret = -ENODEV; - } - -- ret = pmic_setup(); -- if (!ret) -- NOTICE("PMIC: setup successful\n"); -- else -- ERROR("PMIC: setup failed: %d\n", ret); -- - return ret; - } -diff --git a/plat/sun50iw1p1/sunxi_private.h b/plat/sun50iw1p1/sunxi_private.h -index 0c8b640bd..07a329598 100644 ---- a/plat/sun50iw1p1/sunxi_private.h -+++ b/plat/sun50iw1p1/sunxi_private.h -@@ -71,7 +71,7 @@ void sunxi_security_setup(void); - int sunxi_pmic_setup(void); - int sunxi_pmic_read(uint8_t address); - int sunxi_pmic_write(uint8_t address, uint8_t value); -- -+int sunxi_power_setup(uint16_t socid); - int sunxi_power_set_cpu_voltage(int millivolt); - - void udelay(unsigned int delay); -@@ -90,6 +90,13 @@ int sunxi_clock_set_rate(int clocknr, uint32_t freq); - - int sunxi_clock_set_cpu_clock(uint32_t freq_mhz, int enable); - -+/* Declarations for sunxi_rsb.c */ -+int sunxi_rsb_init(void); -+int sunxi_rsb_read(uint8_t address); -+int sunxi_rsb_write(uint8_t address, uint8_t value); -+void sunxi_rsb_wait(const char *desc); -+int sunxi_rsb_configure(uint16_t hw_addr, uint8_t rt_addr); -+ - /* Gets the SPSR for BL33 entry */ - uint32_t sunxi_get_spsr_for_bl33_entry(int aarch); - -diff --git a/plat/sun50iw1p1/sunxi_rsb.c b/plat/sun50iw1p1/sunxi_rsb.c -new file mode 100644 -index 000000000..098c8ad0f ---- /dev/null -+++ b/plat/sun50iw1p1/sunxi_rsb.c -@@ -0,0 +1,198 @@ -+/* -+ * Copyright (c) 2017 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 "sunxi_def.h" -+#include "sunxi_private.h" -+ -+#define R_PRCM_BASE 0x1f01400ULL -+#define R_TWI_BASE 0x1f02400ULL -+#define R_PIO_BASE 0x1f02c00ULL -+ -+#define RSB_BASE 0x1f03400ULL -+#define RSB_CTRL 0x00 -+#define RSB_CCR 0x04 -+#define RSB_INTE 0x08 -+#define RSB_STAT 0x0c -+#define RSB_DADDR0 0x10 -+#define RSB_DLEN 0x18 -+#define RSB_DATA0 0x1c -+#define RSB_LCR 0x24 -+#define RSB_PMCR 0x28 -+#define RSB_CMD 0x2c -+#define RSB_SADDR 0x30 -+ -+#define RSBCMD_SRTA 0xE8 -+#define RSBCMD_RD8 0x8B -+#define RSBCMD_RD16 0x9C -+#define RSBCMD_RD32 0xA6 -+#define RSBCMD_WR8 0x4E -+#define RSBCMD_WR16 0x59 -+#define RSBCMD_WR32 0x63 -+ -+#define BIT(n) (1U << (n)) -+ -+/* Initialize the RSB controller and its pins. */ -+int sunxi_rsb_init(void) -+{ -+ uint32_t reg; -+ -+ /* un-gate PIO clock */ -+ reg = mmio_read_32(R_PRCM_BASE + 0x28); -+ mmio_write_32(R_PRCM_BASE + 0x28, reg | 0x01); -+ -+ /* get currently configured function for pins PL0 and PL1 */ -+ reg = mmio_read_32(R_PIO_BASE + 0x00); -+ if ((reg & 0xff) == 0x33) { -+ NOTICE("already configured for TWI\n"); -+ return -EBUSY; -+ } -+ -+ if ((reg & 0xff) == 0x22) { -+ NOTICE("PMIC: already configured for RSB\n"); -+ return -EEXIST; /* configured for RSB mode already */ -+ } -+ -+ /* switch pins PL0 and PL1 to RSB */ -+ mmio_write_32(R_PIO_BASE + 0, (reg & ~0xff) | 0x22); -+ -+ /* level 2 drive strength */ -+ reg = mmio_read_32(R_PIO_BASE + 0x14); -+ mmio_write_32(R_PIO_BASE + 0x14, (reg & ~0x0f) | 0xa); -+ -+ /* set both ports to pull-up */ -+ reg = mmio_read_32(R_PIO_BASE + 0x1c); -+ mmio_write_32(R_PIO_BASE + 0x1c, (reg & ~0x0f) | 0x5); -+ -+ /* assert & de-assert reset of RSB */ -+ reg = mmio_read_32(R_PRCM_BASE + 0xb0); -+ mmio_write_32(R_PRCM_BASE + 0xb0, reg & ~0x08); -+ reg = mmio_read_32(R_PRCM_BASE + 0xb0); -+ mmio_write_32(R_PRCM_BASE + 0xb0, reg | 0x08); -+ -+ /* un-gate RSB clock */ -+ reg = mmio_read_32(R_PRCM_BASE + 0x28); -+ mmio_write_32(R_PRCM_BASE + 0x28, reg | 0x08); -+ -+ mmio_write_32(RSB_BASE + RSB_CTRL, 0x01); /* soft reset */ -+ -+ mmio_write_32(RSB_BASE + RSB_CCR, 0x11d); /* clock to 400 KHz */ -+ -+ do { -+ reg = mmio_read_32(RSB_BASE + RSB_CTRL); -+ } while (reg & 1); /* transaction in progress */ -+ -+ return 0; -+} -+ -+int sunxi_rsb_read(uint8_t address) -+{ -+ uint32_t reg; -+ -+ mmio_write_32(RSB_BASE + RSB_DLEN, 0x10); /* read a byte, snake oil? */ -+ mmio_write_32(RSB_BASE + RSB_CMD, RSBCMD_RD8); /* read a byte */ -+ mmio_write_32(RSB_BASE + RSB_DADDR0, address); -+ mmio_write_32(RSB_BASE + RSB_CTRL, 0x80); /* start transaction */ -+ do { -+ reg = mmio_read_32(RSB_BASE + RSB_CTRL); -+ } while (reg & 0x80); /* transaction in progress */ -+ -+ reg = mmio_read_32(RSB_BASE + RSB_STAT); -+ if (reg == 0x01) { /* transaction complete */ -+ reg = mmio_read_32(RSB_BASE + RSB_DATA0); /* result register */ -+ return reg & 0xff; -+ } -+ -+ return -reg; -+} -+ -+int sunxi_rsb_write(uint8_t address, uint8_t value) -+{ -+ uint32_t reg; -+ -+ mmio_write_32(RSB_BASE + RSB_DLEN, 0x00); /* write a byte, snake oil? */ -+ mmio_write_32(RSB_BASE + RSB_CMD, RSBCMD_WR8); /* write a byte */ -+ mmio_write_32(RSB_BASE + RSB_DADDR0, address); -+ mmio_write_32(RSB_BASE + RSB_DATA0, value); -+ mmio_write_32(RSB_BASE + RSB_CTRL, 0x80); /* start transaction */ -+ do { -+ reg = mmio_read_32(RSB_BASE + RSB_CTRL); -+ } while (reg & 0x80); /* transaction in progress */ -+ -+ reg = mmio_read_32(RSB_BASE + RSB_STAT); -+ if (reg == 0x01) /* transaction complete */ -+ return 0; -+ -+ return -reg; -+} -+ -+void sunxi_rsb_wait(const char *desc) -+{ -+ uint32_t reg; -+ int cnt = 0; -+ -+ do { -+ reg = mmio_read_32(RSB_BASE + RSB_CTRL); -+ cnt++; -+ } while (reg & 0x80); /* transaction in progress */ -+ -+ reg = mmio_read_32(RSB_BASE + RSB_STAT); -+ if (reg == 0x01) -+ return; -+ -+ ERROR("%s: 0x%x\n", desc, reg); -+} -+ -+/* Initialize the RSB PMIC connection. */ -+int sunxi_rsb_configure(uint16_t hw_addr, uint8_t rt_addr) -+{ -+ int ret; -+ -+ mmio_write_32(RSB_BASE + RSB_PMCR, -+ 0x00 | (0x3e << 8) | (0x7c << 16) | BIT(31)); -+ -+ do { -+ ret = mmio_read_32(RSB_BASE + RSB_PMCR); -+ } while (ret & (1U << 31)); /* transaction in progress */ -+ -+ mmio_write_32(RSB_BASE + RSB_CCR, 0x103); /* 3 MHz */ -+ mmio_write_32(RSB_BASE + RSB_SADDR, hw_addr | (rt_addr << 16)); -+ mmio_write_32(RSB_BASE + RSB_CMD, RSBCMD_SRTA); -+ mmio_write_32(RSB_BASE + RSB_CTRL, 0x80); -+ sunxi_rsb_wait("set run-time address"); -+ -+ /* Set slave runtime address */ -+ mmio_write_32(RSB_BASE + RSB_SADDR, rt_addr << 16); -+ -+ return 0; -+} diff --git a/patch/atf/atf-sun50iw1/08-add-DVFS.patch b/patch/atf/atf-sun50iw1/08-add-DVFS.patch deleted file mode 100644 index 86e0889d18..0000000000 --- a/patch/atf/atf-sun50iw1/08-add-DVFS.patch +++ /dev/null @@ -1,195 +0,0 @@ -From e2b4f43ae7c138f3502e3df4e3928827a169592b Mon Sep 17 00:00:00 2001 -From: Andre Przywara -Date: Sat, 10 Dec 2016 12:22:49 +0000 -Subject: [PATCH] sunxi: SCPI: add DVFS functionality - -DVFS (dynamic voltage and frequency scaling) allows an OS to set certain -CPU operating points described by a pair of frequency and required voltage. -Using the recently introduced wrappers for the CPU voltage and the PLL -frequency implement the required SCPI boilerplate to export those -operating points and allow an OS to choose from a provided list. -The actual frequency/voltage data used here is taken from Allwinner's BSP -code, which seems to provide stable and sensible values. - -Signed-off-by: Andre Przywara ---- - plat/sun50iw1p1/bl31_sunxi_setup.c | 2 +- - plat/sun50iw1p1/platform.mk | 1 + - plat/sun50iw1p1/sunxi_dvfs.c | 65 ++++++++++++++++++++++++++++++++++++++ - plat/sun50iw1p1/sunxi_private.h | 7 ++++ - plat/sun50iw1p1/sunxi_scpi.c | 35 ++++++++++++++++++++ - 5 files changed, 109 insertions(+), 1 deletion(-) - create mode 100644 plat/sun50iw1p1/sunxi_dvfs.c - -diff --git a/plat/sun50iw1p1/bl31_sunxi_setup.c b/plat/sun50iw1p1/bl31_sunxi_setup.c -index 7c1109f4e..4c480e545 100644 ---- a/plat/sun50iw1p1/bl31_sunxi_setup.c -+++ b/plat/sun50iw1p1/bl31_sunxi_setup.c -@@ -250,7 +250,7 @@ void bl31_platform_setup(void) - - sunxi_setup_clocks(socid); - -- NOTICE("SCPI: installed handler, implementation level: 101000\n"); -+ NOTICE("SCPI: installed handler, implementation level: 111000\n"); - } - - /******************************************************************************* -diff --git a/plat/sun50iw1p1/platform.mk b/plat/sun50iw1p1/platform.mk -index 95cff562f..f56e79355 100644 ---- a/plat/sun50iw1p1/platform.mk -+++ b/plat/sun50iw1p1/platform.mk -@@ -53,5 +53,6 @@ BL31_SOURCES += drivers/arm/gic/arm_gic.c \ - plat/sun50iw1p1/sunxi_sip_svc.c \ - plat/sun50iw1p1/sunxi_scpi.c \ - plat/sun50iw1p1/sunxi_rsb.c \ -+ plat/sun50iw1p1/sunxi_dvfs.c \ - plat/sun50iw1p1/aarch64/sunxi_common.c - -diff --git a/plat/sun50iw1p1/sunxi_dvfs.c b/plat/sun50iw1p1/sunxi_dvfs.c -new file mode 100644 -index 000000000..16049e968 ---- /dev/null -+++ b/plat/sun50iw1p1/sunxi_dvfs.c -@@ -0,0 +1,65 @@ -+#include -+#include -+#include -+#include -+ -+#include "sunxi_def.h" -+#include "sunxi_private.h" -+ -+struct op_points -+{ -+ uint32_t freq; -+ uint32_t voltage; -+} sunxi_op_points[] = { -+ { 408, 1000}, { 648, 1040}, { 816, 1080}, { 912, 1120}, { 960, 1160}, -+ {1008, 1200}, {1056, 1240}, {1104, 1260}, {1152, 1300} -+}; -+ -+#define NR_OPP (sizeof(sunxi_op_points) / sizeof(sunxi_op_points[0])) -+ -+int current_opp_index = 2; -+int current_opp_limit = NR_OPP; -+ -+uint32_t sunxi_dvfs_get_get_opp_voltage(int oppnr) -+{ -+ if (oppnr < 0 || oppnr >= NR_OPP) -+ return ~0; -+ -+ return sunxi_op_points[oppnr].voltage; -+} -+ -+uint32_t sunxi_dvfs_get_get_opp_frequency(int oppnr) -+{ -+ if (oppnr < 0 || oppnr >= NR_OPP) -+ return ~0; -+ -+ return sunxi_op_points[oppnr].freq * 1000000; -+} -+ -+int sunxi_dvfs_set_index(int index) -+{ -+ if (index < 0 || index >= NR_OPP) -+ return -1; -+ -+ if (index < current_opp_index) { -+ sunxi_clock_set_cpu_clock(sunxi_op_points[index].freq, 1); -+ sunxi_power_set_cpu_voltage(sunxi_op_points[index].voltage); -+ } else { -+ sunxi_power_set_cpu_voltage(sunxi_op_points[index].voltage); -+ sunxi_clock_set_cpu_clock(sunxi_op_points[index].freq, 1); -+ } -+ -+ current_opp_index = index; -+ -+ return 0; -+} -+ -+int sunxi_dvfs_get_index(void) -+{ -+ return current_opp_index; -+} -+ -+int sunxi_dvfs_get_nr_opp(void) -+{ -+ return NR_OPP; -+} -diff --git a/plat/sun50iw1p1/sunxi_private.h b/plat/sun50iw1p1/sunxi_private.h -index 07a329598..b98400107 100644 ---- a/plat/sun50iw1p1/sunxi_private.h -+++ b/plat/sun50iw1p1/sunxi_private.h -@@ -97,6 +97,13 @@ int sunxi_rsb_write(uint8_t address, uint8_t value); - void sunxi_rsb_wait(const char *desc); - int sunxi_rsb_configure(uint16_t hw_addr, uint8_t rt_addr); - -+/* Declarations for sunxi_dvfs.c */ -+uint32_t sunxi_dvfs_get_get_opp_voltage(int oppnr); -+uint32_t sunxi_dvfs_get_get_opp_frequency(int oppnr); -+int sunxi_dvfs_set_index(int index); -+int sunxi_dvfs_get_index(void); -+int sunxi_dvfs_get_nr_opp(void); -+ - /* Gets the SPSR for BL33 entry */ - uint32_t sunxi_get_spsr_for_bl33_entry(int aarch); - -diff --git a/plat/sun50iw1p1/sunxi_scpi.c b/plat/sun50iw1p1/sunxi_scpi.c -index 3ca287ed2..50aabeb27 100644 ---- a/plat/sun50iw1p1/sunxi_scpi.c -+++ b/plat/sun50iw1p1/sunxi_scpi.c -@@ -53,12 +53,18 @@ - #define SCPI_E_BUSY 12 - - #define SCP_CMD_CAPABILITY 0x02 -+#define SCP_CMD_DVFS_CAPABILITY 0x08 -+#define SCP_CMD_DVFS_GET_INFO 0x09 -+#define SCP_CMD_DVFS_SET_INDEX 0x0a -+#define SCP_CMD_DVFS_GET_INDEX 0x0b -+#define SCP_CMD_DVFS_GET_STAT 0x0c - #define SCP_CMD_CLOCKS_CAPS 0x0d - #define SCP_CMD_CLOCK_GET_INFO 0x0e - #define SCP_CMD_CLOCK_SET_RATE 0x0f - #define SCP_CMD_CLOCK_GET_RATE 0x10 - - #define SCP_CMDS_IMPLEMENTED \ -+ GENMASK(SCP_CMD_DVFS_GET_INDEX, SCP_CMD_DVFS_CAPABILITY) | \ - GENMASK(SCP_CMD_CLOCK_GET_RATE, SCP_CMD_CLOCKS_CAPS) - - /* end of SRAM A1 */ -@@ -141,6 +147,35 @@ static uint32_t scpi_handle_cmd(int cmd, uint8_t *payload_size, - mmio_write_32(payload_out, ret); - *payload_size = 4; - return 0; -+ case SCP_CMD_DVFS_CAPABILITY: -+ /* number of implemented voltage domains: only one */ -+ mmio_write_32(payload_out, 1); -+ *payload_size = 0x1; -+ return SCPI_OK; -+ case SCP_CMD_DVFS_GET_INFO: { -+ int i, nr_opp = sunxi_dvfs_get_nr_opp(); -+ -+ mmio_write_32(payload_out, nr_opp << 8); -+ for (i = 0; i < nr_opp; i++) { -+ mmio_write_32(payload_out + 4 + 2 * i * 4, -+ sunxi_dvfs_get_get_opp_frequency(i)); -+ mmio_write_32(payload_out + 4 + 2 * i * 4 + 4, -+ sunxi_dvfs_get_get_opp_voltage(i)); -+ } -+ *payload_size = 4 + 2 * nr_opp * 4; -+ return SCPI_OK; -+ } -+ case SCP_CMD_DVFS_SET_INDEX: -+ if ((par1 & 0xff) != 0) -+ return SCPI_E_PARAM; -+ -+ if (sunxi_dvfs_set_index((par1 >> 8) & 0xff)) -+ return SCPI_E_RANGE; -+ return SCPI_OK; -+ case SCP_CMD_DVFS_GET_INDEX: -+ mmio_write_32(payload_out, sunxi_dvfs_get_index()); -+ *payload_size = 0x1; -+ return SCPI_OK; - } - - return SCPI_E_SUPPORT; diff --git a/patch/atf/atf-sun50iw1/09-add-THS-sensor.patch b/patch/atf/atf-sun50iw1/09-add-THS-sensor.patch deleted file mode 100644 index 54731d4f09..0000000000 --- a/patch/atf/atf-sun50iw1/09-add-THS-sensor.patch +++ /dev/null @@ -1,317 +0,0 @@ -From 96fcf67c30ca4526641e08e16ba0992cd15e05c0 Mon Sep 17 00:00:00 2001 -From: Andre Przywara -Date: Fri, 23 Sep 2016 01:30:18 +0100 -Subject: [PATCH] sunxi: SCPI: add temperature sensor readout - -The SCPI interface provides abstracted access to sensors, to monitor -voltage, current, power and temperature. -Introduce the required code to read and decode Allwinner's CPU and GPU -temperature sensors and export them via the SCPI interface. - -Signed-off-by: Andre Przywara ---- - plat/sun50iw1p1/bl31_sunxi_setup.c | 4 +- - plat/sun50iw1p1/platform.mk | 2 + - plat/sun50iw1p1/sunxi_private.h | 10 ++++ - plat/sun50iw1p1/sunxi_scpi.c | 46 +++++++++++++- - plat/sun50iw1p1/sunxi_sensors.c | 40 +++++++++++++ - plat/sun50iw1p1/sunxi_temp.c | 119 +++++++++++++++++++++++++++++++++++++ - 6 files changed, 219 insertions(+), 2 deletions(-) - create mode 100644 plat/sun50iw1p1/sunxi_sensors.c - create mode 100644 plat/sun50iw1p1/sunxi_temp.c - -diff --git a/plat/sun50iw1p1/bl31_sunxi_setup.c b/plat/sun50iw1p1/bl31_sunxi_setup.c -index 4c480e545..503f4006d 100644 ---- a/plat/sun50iw1p1/bl31_sunxi_setup.c -+++ b/plat/sun50iw1p1/bl31_sunxi_setup.c -@@ -248,9 +248,11 @@ void bl31_platform_setup(void) - - sunxi_power_setup(socid); - -+ sunxi_ths_setup(); -+ - sunxi_setup_clocks(socid); - -- NOTICE("SCPI: installed handler, implementation level: 111000\n"); -+ NOTICE("SCPI: installed handler, implementation level: 111010\n"); - } - - /******************************************************************************* -diff --git a/plat/sun50iw1p1/platform.mk b/plat/sun50iw1p1/platform.mk -index f56e79355..b1b0ac298 100644 ---- a/plat/sun50iw1p1/platform.mk -+++ b/plat/sun50iw1p1/platform.mk -@@ -54,5 +54,7 @@ BL31_SOURCES += drivers/arm/gic/arm_gic.c \ - plat/sun50iw1p1/sunxi_scpi.c \ - plat/sun50iw1p1/sunxi_rsb.c \ - plat/sun50iw1p1/sunxi_dvfs.c \ -+ plat/sun50iw1p1/sunxi_sensors.c \ -+ plat/sun50iw1p1/sunxi_temp.c \ - plat/sun50iw1p1/aarch64/sunxi_common.c - -diff --git a/plat/sun50iw1p1/sunxi_private.h b/plat/sun50iw1p1/sunxi_private.h -index b98400107..d2ab0e6c2 100644 ---- a/plat/sun50iw1p1/sunxi_private.h -+++ b/plat/sun50iw1p1/sunxi_private.h -@@ -104,6 +104,16 @@ int sunxi_dvfs_set_index(int index); - int sunxi_dvfs_get_index(void); - int sunxi_dvfs_get_nr_opp(void); - -+/* Declarations for sunxi_sensors.c */ -+int sunxi_setup_sensors(void); -+const char* sunxi_sensor_get_name(int sensornr); -+uint32_t sunxi_sensor_get_value(int sensornr); -+int sunxi_sensors_nr_sensors(void); -+ -+/* Declarations for sunxi_temp.c */ -+int sunxi_ths_setup(void); -+int sunxi_ths_read_temp(int sensornr); -+ - /* Gets the SPSR for BL33 entry */ - uint32_t sunxi_get_spsr_for_bl33_entry(int aarch); - -diff --git a/plat/sun50iw1p1/sunxi_scpi.c b/plat/sun50iw1p1/sunxi_scpi.c -index 50aabeb27..4d0d71e97 100644 ---- a/plat/sun50iw1p1/sunxi_scpi.c -+++ b/plat/sun50iw1p1/sunxi_scpi.c -@@ -62,10 +62,14 @@ - #define SCP_CMD_CLOCK_GET_INFO 0x0e - #define SCP_CMD_CLOCK_SET_RATE 0x0f - #define SCP_CMD_CLOCK_GET_RATE 0x10 -+#define SCP_CMD_SENSORS_CAPS 0x15 -+#define SCP_CMD_SENSORS_INFO 0x16 -+#define SCP_CMD_SENSORS_VALUE 0x17 - - #define SCP_CMDS_IMPLEMENTED \ - GENMASK(SCP_CMD_DVFS_GET_INDEX, SCP_CMD_DVFS_CAPABILITY) | \ -- GENMASK(SCP_CMD_CLOCK_GET_RATE, SCP_CMD_CLOCKS_CAPS) -+ GENMASK(SCP_CMD_CLOCK_GET_RATE, SCP_CMD_CLOCKS_CAPS) | \ -+ GENMASK(SCP_CMD_SENSORS_VALUE, SCP_CMD_SENSORS_CAPS) - - /* end of SRAM A1 */ - #define SUNXI_SCPI_SHMEM_BASE 0x17e00 -@@ -89,6 +93,25 @@ static int write_clock_info(uintptr_t payload, int clocknr) - return 12 + i; - } - -+static int write_sensor_info(uintptr_t payload, int sensornr) -+{ -+ const char *name, *s; -+ int i; -+ -+ name = sunxi_sensor_get_name(sensornr); -+ if (!name) -+ return -SCPI_E_PARAM; -+ -+ /* no triggers, always temperature sensor (for now) */ -+ mmio_write_32(payload + 0x0, (sensornr & 0xffff)); -+ -+ for (i = 0, s = name; s[i] != 0; i++) -+ mmio_write_8(payload + 4 + i, s[i]); -+ mmio_write_8(payload + 4 + i, 0); -+ -+ return 4 + i; -+} -+ - static uint32_t scpi_handle_cmd(int cmd, uint8_t *payload_size, - uintptr_t payload_in, uintptr_t payload_out) - { -@@ -176,6 +199,27 @@ static uint32_t scpi_handle_cmd(int cmd, uint8_t *payload_size, - mmio_write_32(payload_out, sunxi_dvfs_get_index()); - *payload_size = 0x1; - return SCPI_OK; -+ case SCP_CMD_SENSORS_CAPS: -+ /* number of implemented sensors */ -+ mmio_write_32(payload_out, sunxi_sensors_nr_sensors()); -+ *payload_size = 0x2; -+ return SCPI_OK; -+ case SCP_CMD_SENSORS_INFO: -+ ret = write_sensor_info(payload_out, par1 & 0xffff); -+ if (ret < 0) { -+ *payload_size = 0; -+ return SCPI_E_PARAM; -+ } -+ *payload_size = ret; -+ return SCPI_OK; -+ case SCP_CMD_SENSORS_VALUE: -+ ret = sunxi_sensor_get_value(par1 & 0xffff); -+ if (ret == ~0) -+ return SCPI_E_RANGE; -+ mmio_write_32(payload_out, ret); -+ mmio_write_32(payload_out + 4, 0); -+ *payload_size = 8; -+ return 0; - } - - return SCPI_E_SUPPORT; -diff --git a/plat/sun50iw1p1/sunxi_sensors.c b/plat/sun50iw1p1/sunxi_sensors.c -new file mode 100644 -index 000000000..ee8f216b6 ---- /dev/null -+++ b/plat/sun50iw1p1/sunxi_sensors.c -@@ -0,0 +1,40 @@ -+#include -+#include -+#include -+#include -+ -+#include "sunxi_def.h" -+#include "sunxi_private.h" -+ -+int sunxi_setup_sensors(void) -+{ -+ return 0; -+} -+ -+const char* sunxi_sensor_get_name(int sensornr) -+{ -+ switch(sensornr) { -+ case 0: return "cpu_temp"; -+ case 1: return "gpu_temp0"; -+ case 2: return "gpu_temp1"; -+ } -+ -+ return NULL; -+} -+ -+uint32_t sunxi_sensor_get_value(int sensornr) -+{ -+ switch(sensornr) { -+ case 0: -+ case 1: -+ case 2: -+ return sunxi_ths_read_temp(sensornr); -+ } -+ -+ return ~0; -+} -+ -+int sunxi_sensors_nr_sensors(void) -+{ -+ return 3; -+} -diff --git a/plat/sun50iw1p1/sunxi_temp.c b/plat/sun50iw1p1/sunxi_temp.c -new file mode 100644 -index 000000000..8c777a34f ---- /dev/null -+++ b/plat/sun50iw1p1/sunxi_temp.c -@@ -0,0 +1,119 @@ -+/* -+ * 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 "sunxi_def.h" -+#include "sunxi_private.h" -+ -+#define CCU_BASE 0x1c20000ULL -+#define BUS_CLK_GATING_REG2 0x068 -+#define THS_CLK_REG 0x074 -+#define BUS_SOFT_RST_REG3 0x2d0 -+#define THS_BASE 0x1c25000ULL -+ -+#define BIT(n) (1U << (n)) -+ -+/* temperature = ( MINUPA - reg * MULPA) / DIVPA */ -+#define MULPA 25000 -+#define DIVPA 214 -+#define MINUPA 2170 -+static int sun50_th_reg_to_temp(uint32_t reg_data) -+{ -+ return ((MINUPA - (int)reg_data) * MULPA) / DIVPA; -+} -+ -+/* Initialize the temperature sensor */ -+static int init_ths(void) -+{ -+ uint32_t reg; -+ -+ /* de-assert reset of THS */ -+ reg = mmio_read_32(CCU_BASE + BUS_SOFT_RST_REG3); -+ mmio_write_32(CCU_BASE + BUS_SOFT_RST_REG3, reg | BIT(8)); -+ -+ /* enable THS clock at 4 MHz */ -+ reg = mmio_read_32(CCU_BASE + THS_CLK_REG) & ~0x3; -+ mmio_write_32(CCU_BASE + THS_CLK_REG, reg | 0x3 | BIT(31)); -+ -+ /* un-gate THS clock */ -+ reg = mmio_read_32(CCU_BASE + BUS_CLK_GATING_REG2); -+ mmio_write_32(CCU_BASE + BUS_CLK_GATING_REG2, reg | BIT(8)); -+ -+ /* start calibration */ -+ mmio_write_32(THS_BASE + 0x04, BIT(17)); -+ /* set aquire times */ -+ mmio_write_32(THS_BASE + 0x00, 0x190); -+ mmio_write_32(THS_BASE + 0x40, 0x190 << 16); -+ /* enable filter, average over 8 values */ -+ mmio_write_32(THS_BASE + 0x70, 0x06); -+ /* enable sensors 0-2 (CPU & GPUs) measurement */ -+ reg = mmio_read_32(THS_BASE + 0x40); -+ mmio_write_32(THS_BASE + 0x40, reg | BIT(0) | BIT(1) | BIT(2)); -+ -+ return 0; -+} -+ -+/* Setup the temperature sensor */ -+int sunxi_ths_setup(void) -+{ -+ int ret; -+ -+ NOTICE("Configuring thermal sensors\n"); -+ -+ ret = init_ths(); -+ if (ret) { -+ ERROR("THS: cannot initialize temperature sensor\n"); -+ return -1; -+ } -+ -+ return ret; -+} -+ -+int sunxi_ths_read_temp(int sensor) -+{ -+ int reg; -+ -+ if (sensor < 0 || sensor > 2) -+ return ~0; -+ -+ reg = mmio_read_32(THS_BASE + 0x80 + (4 * sensor)); -+ -+ return sun50_th_reg_to_temp(reg & 0xfff); -+} diff --git a/patch/atf/atf-sun50iw1/10-add-device-power-state.patch b/patch/atf/atf-sun50iw1/10-add-device-power-state.patch deleted file mode 100644 index 0481300447..0000000000 --- a/patch/atf/atf-sun50iw1/10-add-device-power-state.patch +++ /dev/null @@ -1,233 +0,0 @@ -From 321bc21a00f9b46735bcfdca5a683ab240cd0f33 Mon Sep 17 00:00:00 2001 -From: Andre Przywara -Date: Mon, 27 Feb 2017 23:10:56 +0000 -Subject: [PATCH] UNTESTED: sunxi: SCPI: add device power state support - -Some generic framework to toggle AXP power rails via the SCPI device -power state interface. -TODO: - - testing - - check how H5 folds in - -Signed-off-by: Andre Przywara ---- - plat/sun50iw1p1/bl31_sunxi_setup.c | 2 +- - plat/sun50iw1p1/sunxi_power.c | 142 +++++++++++++++++++++++++++++++++++++ - plat/sun50iw1p1/sunxi_private.h | 2 + - plat/sun50iw1p1/sunxi_scpi.c | 13 +++- - 4 files changed, 157 insertions(+), 2 deletions(-) - -diff --git a/plat/sun50iw1p1/bl31_sunxi_setup.c b/plat/sun50iw1p1/bl31_sunxi_setup.c -index 503f4006d..027436725 100644 ---- a/plat/sun50iw1p1/bl31_sunxi_setup.c -+++ b/plat/sun50iw1p1/bl31_sunxi_setup.c -@@ -252,7 +252,7 @@ void bl31_platform_setup(void) - - sunxi_setup_clocks(socid); - -- NOTICE("SCPI: installed handler, implementation level: 111010\n"); -+ NOTICE("SCPI: installed handler, implementation level: 111011\n"); - } - - /******************************************************************************* -diff --git a/plat/sun50iw1p1/sunxi_power.c b/plat/sun50iw1p1/sunxi_power.c -index 5aa63fe4f..8849af8bc 100644 ---- a/plat/sun50iw1p1/sunxi_power.c -+++ b/plat/sun50iw1p1/sunxi_power.c -@@ -177,6 +177,148 @@ enum pmic_type { - PMIC_AXP803, - } pmic_type; - -+int sunxi_power_set_cpu_voltage(int millivolt) -+{ -+ switch (pmic_type) { -+ case PMIC_AXP803: -+ return axp803_set_cpu_voltage(millivolt); -+ } -+ -+ return -ENODEV; -+} -+ -+/* -+ * device mapping: blocks of 8 (or 16?) -+ * block 0: DCDCn -+ * block 1: special (DC1SW, ...) -+ * block 2: ALDO -+ * block 3: DLDO -+ * block 4: ELDO -+ * block 5: FLDO -+ * block 6: GPIO -+ * -+ * state: == 0: power off -+ * != 0: power on -+ */ -+ -+static uint32_t axp803_map_devices(uint16_t devid) -+{ -+ unsigned int reg, bit; -+ -+ switch (devid) { -+ case 0: /* DCDC */ -+ case 1: -+ case 2: -+ case 3: -+ case 4: -+ case 5: -+ reg = 0x10; -+ bit = devid; -+ break; -+ case 8: /* DC1SW */ -+ reg = 0x12; -+ bit = 7; -+ break; -+ case 16: /* ALDO */ -+ case 17: -+ case 18: -+ reg = 0x13; -+ bit = (devid & 7) + 5; -+ break; -+ case 24: /* DLDO */ -+ case 25: -+ case 26: -+ case 27: -+ reg = 0x12; -+ bit = (devid & 7) + 3; -+ break; -+ case 32: /* ELDO */ -+ case 33: -+ case 34: -+ reg = 0x13; -+ bit = (devid & 7) + 0; -+ break; -+ case 40: /* FLDO */ -+ case 41: -+ reg = 0x13; -+ bit = (devid & 7) + 2; -+ break; -+ case 48: /* GPIO0LDO */ -+ case 49: /* GPIO1LDO */ -+ /* TODO: implement */ -+ default: -+ return -1; -+ } -+ -+ return (bit & 0xff) | (reg << 8); -+} -+ -+static unsigned int axp803_pstate_get(uint16_t device) -+{ -+ uint32_t regmap = axp803_map_devices(device); -+ uint8_t reg; -+ int bit, val; -+ -+ if (regmap == -1) -+ return -1; -+ -+ reg = (regmap >> 8) & 0xff; -+ bit = regmap & 0xff; -+ -+ val = sunxi_rsb_read(reg); -+ if (val < 0) -+ return -2; -+ -+ if (val & BIT(bit)) -+ return 1; -+ -+ return 0; -+} -+ -+unsigned int sunxi_pstate_get(uint16_t device) -+{ -+ switch (pmic_type) { -+ case PMIC_AXP803: -+ return axp803_pstate_get(device); -+ } -+ -+ return ~0; -+} -+ -+static int axp803_pstate_set(uint16_t device, uint8_t state) -+{ -+ uint32_t regmap = axp803_map_devices(device); -+ uint8_t reg; -+ int bit, val; -+ -+ if (regmap == -1) -+ return -1; -+ -+ reg = (regmap >> 8) & 0xff; -+ bit = regmap & 0xff; -+ -+ val = sunxi_rsb_read(reg); -+ if (val < 0) -+ return -2; -+ -+ if (state) -+ val |= BIT(bit); -+ else -+ val &= ~BIT(bit); -+ -+ return sunxi_rsb_write(reg, val); -+} -+ -+int sunxi_pstate_set(uint16_t device, uint8_t state) -+{ -+ switch (pmic_type) { -+ case PMIC_AXP803: -+ return axp803_pstate_set(device, state); -+ } -+ -+ return -EINVAL; -+} -+ - int sunxi_power_setup(uint16_t socid) - { - int ret; -diff --git a/plat/sun50iw1p1/sunxi_private.h b/plat/sun50iw1p1/sunxi_private.h -index d2ab0e6c2..27f87839a 100644 ---- a/plat/sun50iw1p1/sunxi_private.h -+++ b/plat/sun50iw1p1/sunxi_private.h -@@ -73,6 +73,8 @@ int sunxi_pmic_read(uint8_t address); - int sunxi_pmic_write(uint8_t address, uint8_t value); - int sunxi_power_setup(uint16_t socid); - int sunxi_power_set_cpu_voltage(int millivolt); -+unsigned int sunxi_pstate_get(uint16_t device); -+int sunxi_pstate_set(uint16_t device, uint8_t state); - - void udelay(unsigned int delay); - int sunxi_setup_clocks(uint16_t socid); -diff --git a/plat/sun50iw1p1/sunxi_scpi.c b/plat/sun50iw1p1/sunxi_scpi.c -index 4d0d71e97..6856e400e 100644 ---- a/plat/sun50iw1p1/sunxi_scpi.c -+++ b/plat/sun50iw1p1/sunxi_scpi.c -@@ -65,11 +65,14 @@ - #define SCP_CMD_SENSORS_CAPS 0x15 - #define SCP_CMD_SENSORS_INFO 0x16 - #define SCP_CMD_SENSORS_VALUE 0x17 -+#define SCP_CMD_PSTATE_SET 0x1b -+#define SCP_CMD_PSTATE_GET 0x1c - - #define SCP_CMDS_IMPLEMENTED \ - GENMASK(SCP_CMD_DVFS_GET_INDEX, SCP_CMD_DVFS_CAPABILITY) | \ - GENMASK(SCP_CMD_CLOCK_GET_RATE, SCP_CMD_CLOCKS_CAPS) | \ -- GENMASK(SCP_CMD_SENSORS_VALUE, SCP_CMD_SENSORS_CAPS) -+ GENMASK(SCP_CMD_SENSORS_VALUE, SCP_CMD_SENSORS_CAPS) | \ -+ GENMASK(SCP_CMD_PSTATE_SET, SCP_CMD_PSTATE_GET) - - /* end of SRAM A1 */ - #define SUNXI_SCPI_SHMEM_BASE 0x17e00 -@@ -220,6 +223,14 @@ static uint32_t scpi_handle_cmd(int cmd, uint8_t *payload_size, - mmio_write_32(payload_out + 4, 0); - *payload_size = 8; - return 0; -+ case SCP_CMD_PSTATE_SET: -+ if (sunxi_pstate_set(par1 & 0xffff, (par1 >> 16) & 0xff)) -+ return SCPI_E_RANGE; -+ return SCPI_OK; -+ case SCP_CMD_PSTATE_GET: -+ mmio_write_32(payload_out, sunxi_pstate_get(par1 & 0xffff)); -+ *payload_size = 0x1; -+ return SCPI_OK; - } - - return SCPI_E_SUPPORT; diff --git a/patch/atf/atf-sun50iw2/add-pc2-shutdown.patch b/patch/atf/atf-sun50iw2/add-pc2-shutdown.patch deleted file mode 100644 index b1d9dcbbc4..0000000000 --- a/patch/atf/atf-sun50iw2/add-pc2-shutdown.patch +++ /dev/null @@ -1,65 +0,0 @@ -diff --git a/plat/sun50iw1p1/plat_pm.c b/plat/sun50iw1p1/plat_pm.c -index ec26248..ed53871 100644 ---- a/plat/sun50iw1p1/plat_pm.c -+++ b/plat/sun50iw1p1/plat_pm.c -@@ -254,7 +254,59 @@ static int32_t sunxi_affinst_suspend_finish(uint64_t mpidr, - ******************************************************************************/ - static void __dead2 sunxi_system_off(void) - { -- sunxi_pmic_write(0x32, sunxi_pmic_read(0x32) | 0x80); -+ uint16_t soc_id; -+ uint32_t reg; -+ soc_id = sunxi_get_socid(); -+ -+ switch (soc_id) { -+ case 0x1689: -+ sunxi_pmic_write(0x32, sunxi_pmic_read(0x32) | 0x80); -+ break; -+ case 0x1718: -+ /* Disable EMAC power: PD6 to low */ -+ reg = mmio_read_32(0x01c20800 + 0x6c); -+ reg &= ~(0x7 << 24); -+ reg |= (0x1 << 24); -+ mmio_write_32(0x01f02c00 + 0x6c, reg); -+ -+ reg = mmio_read_32(0x01c20800 + 0x7c); -+ reg &= ~(0x1 << 6); -+ mmio_write_32(0x01f02c00 + 0x7c, reg); -+ -+ /* Disable DRAM regulator: PL9 to low */ -+ reg = mmio_read_32(0x01f02c00 + 0x04); -+ reg &= ~(0x7 << 4); -+ reg |= (0x1 << 4); -+ mmio_write_32(0x01f02c00 + 0x04, reg); -+ -+ reg = mmio_read_32(0x01f02c00 + 0x10); -+ reg &= ~(0x1 << 9); -+ mmio_write_32(0x01f02c00 + 0x10, reg); -+ -+ /* Disable I/O regulator: PL5 to low - Edit: not needed -+ reg = mmio_read_32(0x01f02c00 + 0x00); -+ reg &= ~(0x7 << 20); -+ reg |= (0x1 << 20); -+ mmio_write_32(0x01f02c00 + 0x00, reg); -+ -+ reg = mmio_read_32(0x01f02c00 + 0x10); -+ reg &= ~(0x1 << 5); -+ mmio_write_32(0x01f02c00 + 0x10, reg); */ -+ -+ /* Disable CPU regulator: PL8 to low */ -+ reg = mmio_read_32(0x01f02c00 + 0x04); -+ reg &= ~0x7; -+ reg |= 0x1; -+ mmio_write_32(0x01f02c00 + 0x04, reg); -+ -+ reg = mmio_read_32(0x01f02c00 + 0x10); -+ reg &= ~(0x1 << 8); -+ mmio_write_32(0x01f02c00 + 0x10, reg); -+ -+ udelay(100); -+ break; -+ } -+ - ERROR("PSCI system shutdown: still alive ...\n"); - - wfi();