diff --git a/docs/plat/index.rst b/docs/plat/index.rst index 3cbb552466a0e9701b4620dbb57f4a2e1c18b213..06c5c2b1ab3060b6089c776c7dfde58b45f0e79d 100644 --- a/docs/plat/index.rst +++ b/docs/plat/index.rst @@ -20,6 +20,7 @@ Platform Ports marvell/index mt8183 mt8192 + mt8195 nvidia-tegra warp7 imx8 diff --git a/docs/plat/mt8195.rst b/docs/plat/mt8195.rst new file mode 100644 index 0000000000000000000000000000000000000000..b2aeea206a08351f972f90694d751baa309a9c41 --- /dev/null +++ b/docs/plat/mt8195.rst @@ -0,0 +1,21 @@ +MediaTek 8195 +============= + +MediaTek 8195 (MT8195) is a 64-bit ARM SoC introduced by MediaTek in 2021. +The chip incorporates eight cores - four Cortex-A55 little cores and Cortex-A76. +Cortex-A76 can operate at up to 2.2 GHz. +Cortex-A55 can operate at up to 2.0 GHz. + +Boot Sequence +------------- + +:: + + Boot Rom --> Coreboot --> TF-A BL31 --> Depthcharge --> Linux Kernel + +How to Build +------------ + +.. code:: shell + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=mt8195 DEBUG=1 COREBOOT=1 diff --git a/plat/mediatek/mt8192/plat_mt_gic.c b/plat/mediatek/common/drivers/gic600/mt_gic_v3.c similarity index 100% rename from plat/mediatek/mt8192/plat_mt_gic.c rename to plat/mediatek/common/drivers/gic600/mt_gic_v3.c diff --git a/plat/mediatek/mt8192/include/mt_gic_v3.h b/plat/mediatek/common/drivers/gic600/mt_gic_v3.h similarity index 100% rename from plat/mediatek/mt8192/include/mt_gic_v3.h rename to plat/mediatek/common/drivers/gic600/mt_gic_v3.h diff --git a/plat/mediatek/common/drivers/gpio/mtgpio_common.c b/plat/mediatek/common/drivers/gpio/mtgpio_common.c new file mode 100644 index 0000000000000000000000000000000000000000..89977a55037630a2a3950ce4762d7c7db24259f1 --- /dev/null +++ b/plat/mediatek/common/drivers/gpio/mtgpio_common.c @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +/****************************************************************************** + *Macro Definition + ******************************************************************************/ +#define GPIO_MODE_BITS 4 +#define MAX_GPIO_MODE_PER_REG 8 +#define MAX_GPIO_REG_BITS 32 +#define DIR_BASE (GPIO_BASE + 0x000) +#define DOUT_BASE (GPIO_BASE + 0x100) +#define DIN_BASE (GPIO_BASE + 0x200) +#define MODE_BASE (GPIO_BASE + 0x300) +#define SET 0x4 +#define CLR 0x8 + +static void mt_set_gpio_dir_chip(uint32_t pin, int dir) +{ + uint32_t pos, bit; + + assert(pin < MAX_GPIO_PIN); + assert(dir < MT_GPIO_DIR_MAX); + + pos = pin / MAX_GPIO_REG_BITS; + bit = pin % MAX_GPIO_REG_BITS; + + if (dir == MT_GPIO_DIR_IN) { + mmio_write_32(DIR_BASE + 0x10U * pos + CLR, 1U << bit); + } else { + mmio_write_32(DIR_BASE + 0x10U * pos + SET, 1U << bit); + } +} + +static int mt_get_gpio_dir_chip(uint32_t pin) +{ + uint32_t pos, bit; + uint32_t reg; + + assert(pin < MAX_GPIO_PIN); + + pos = pin / MAX_GPIO_REG_BITS; + bit = pin % MAX_GPIO_REG_BITS; + + reg = mmio_read_32(DIR_BASE + 0x10U * pos); + return (((reg & (1U << bit)) != 0U) ? MT_GPIO_DIR_OUT : MT_GPIO_DIR_IN); +} + +static void mt_set_gpio_out_chip(uint32_t pin, int output) +{ + uint32_t pos, bit; + + assert(pin < MAX_GPIO_PIN); + assert(output < MT_GPIO_OUT_MAX); + + pos = pin / MAX_GPIO_REG_BITS; + bit = pin % MAX_GPIO_REG_BITS; + + if (output == MT_GPIO_OUT_ZERO) { + mmio_write_32(DOUT_BASE + 0x10U * pos + CLR, 1U << bit); + } else { + mmio_write_32(DOUT_BASE + 0x10U * pos + SET, 1U << bit); + } +} + +static int mt_get_gpio_in_chip(uint32_t pin) +{ + uint32_t pos, bit; + uint32_t reg; + + assert(pin < MAX_GPIO_PIN); + + pos = pin / MAX_GPIO_REG_BITS; + bit = pin % MAX_GPIO_REG_BITS; + + reg = mmio_read_32(DIN_BASE + 0x10U * pos); + return (((reg & (1U << bit)) != 0U) ? 1 : 0); +} + +static void mt_gpio_set_spec_pull_pupd(uint32_t pin, int enable, + int select) +{ + uintptr_t reg1; + uintptr_t reg2; + struct mt_pin_info gpio_info; + + gpio_info = mt_pin_infos[pin]; + uint32_t bit = gpio_info.bit; + + reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset; + reg2 = reg1 + (gpio_info.base & 0xf0); + if (enable == MT_GPIO_PULL_ENABLE) { + mmio_write_32(reg2 + SET, (1U << bit)); + if (select == MT_GPIO_PULL_DOWN) { + mmio_write_32(reg1 + SET, (1U << bit)); + } else { + mmio_write_32(reg1 + CLR, (1U << bit)); + } + } else { + mmio_write_32(reg2 + CLR, (1U << bit)); + mmio_write_32((reg2 + 0x010U) + CLR, (1U << bit)); + } +} + +static void mt_gpio_set_pull_pu_pd(uint32_t pin, int enable, + int select) +{ + uintptr_t reg1; + uintptr_t reg2; + struct mt_pin_info gpio_info; + + gpio_info = mt_pin_infos[pin]; + uint32_t bit = gpio_info.bit; + + reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset; + reg2 = reg1 - (gpio_info.base & 0xf0); + + if (enable == MT_GPIO_PULL_ENABLE) { + if (select == MT_GPIO_PULL_DOWN) { + mmio_write_32(reg1 + CLR, (1U << bit)); + mmio_write_32(reg2 + SET, (1U << bit)); + } else { + mmio_write_32(reg2 + CLR, (1U << bit)); + mmio_write_32(reg1 + SET, (1U << bit)); + } + } else { + mmio_write_32(reg1 + CLR, (1U << bit)); + mmio_write_32(reg2 + CLR, (1U << bit)); + } +} + +static void mt_gpio_set_pull_chip(uint32_t pin, int enable, + int select) +{ + struct mt_pin_info gpio_info; + + gpio_info = mt_pin_infos[pin]; + if (gpio_info.flag) { + mt_gpio_set_spec_pull_pupd(pin, enable, select); + } else { + mt_gpio_set_pull_pu_pd(pin, enable, select); + } +} + +static int mt_gpio_get_spec_pull_pupd(uint32_t pin) +{ + uintptr_t reg1; + uintptr_t reg2; + uint32_t r0; + uint32_t r1; + + struct mt_pin_info gpio_info; + + gpio_info = mt_pin_infos[pin]; + uint32_t bit = gpio_info.bit; + + reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset; + reg2 = reg1 + (gpio_info.base & 0xf0); + + r0 = (mmio_read_32(reg2) >> bit) & 1U; + r1 = (mmio_read_32(reg2 + 0x010) >> bit) & 1U; + if (r0 == 0U && r1 == 0U) { + return MT_GPIO_PULL_NONE; + } else { + if (mmio_read_32(reg1) & (1U << bit)) { + return MT_GPIO_PULL_DOWN; + } else { + return MT_GPIO_PULL_UP; + } + } +} + +static int mt_gpio_get_pull_pu_pd(uint32_t pin) +{ + uintptr_t reg1; + uintptr_t reg2; + uint32_t pu; + uint32_t pd; + + struct mt_pin_info gpio_info; + + gpio_info = mt_pin_infos[pin]; + uint32_t bit = gpio_info.bit; + + reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset; + reg2 = reg1 - (gpio_info.base & 0xf0); + pu = (mmio_read_32(reg1) >> bit) & 1U; + pd = (mmio_read_32(reg2) >> bit) & 1U; + if (pu == 1U) { + return MT_GPIO_PULL_UP; + } else if (pd == 1U) { + return MT_GPIO_PULL_DOWN; + } else { + return MT_GPIO_PULL_NONE; + } +} + +static int mt_gpio_get_pull_chip(uint32_t pin) +{ + struct mt_pin_info gpio_info; + + gpio_info = mt_pin_infos[pin]; + if (gpio_info.flag) { + return mt_gpio_get_spec_pull_pupd(pin); + } else { + return mt_gpio_get_pull_pu_pd(pin); + } +} + +static void mt_set_gpio_pull_select_chip(uint32_t pin, int sel) +{ + assert(pin < MAX_GPIO_PIN); + + if (sel == MT_GPIO_PULL_NONE) { + mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_DISABLE, MT_GPIO_PULL_DOWN); + } else if (sel == MT_GPIO_PULL_UP) { + mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_UP); + } else if (sel == MT_GPIO_PULL_DOWN) { + mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_DOWN); + } +} + +/* get pull-up or pull-down, regardless of resistor value */ +static int mt_get_gpio_pull_select_chip(uint32_t pin) +{ + assert(pin < MAX_GPIO_PIN); + + return mt_gpio_get_pull_chip(pin); +} + +static void mt_set_gpio_dir(int gpio, int direction) +{ + mt_set_gpio_dir_chip((uint32_t)gpio, direction); +} + +static int mt_get_gpio_dir(int gpio) +{ + uint32_t pin; + + pin = (uint32_t)gpio; + return mt_get_gpio_dir_chip(pin); +} + +static void mt_set_gpio_pull(int gpio, int pull) +{ + uint32_t pin; + + pin = (uint32_t)gpio; + mt_set_gpio_pull_select_chip(pin, pull); +} + +static int mt_get_gpio_pull(int gpio) +{ + uint32_t pin; + + pin = (uint32_t)gpio; + return mt_get_gpio_pull_select_chip(pin); +} + +static void mt_set_gpio_out(int gpio, int value) +{ + uint32_t pin; + + pin = (uint32_t)gpio; + mt_set_gpio_out_chip(pin, value); +} + +static int mt_get_gpio_in(int gpio) +{ + uint32_t pin; + + pin = (uint32_t)gpio; + return mt_get_gpio_in_chip(pin); +} + +const gpio_ops_t mtgpio_ops = { + .get_direction = mt_get_gpio_dir, + .set_direction = mt_set_gpio_dir, + .get_value = mt_get_gpio_in, + .set_value = mt_set_gpio_out, + .set_pull = mt_set_gpio_pull, + .get_pull = mt_get_gpio_pull, +}; + +void mt_gpio_init(void) +{ + gpio_init(&mtgpio_ops); +} diff --git a/plat/mediatek/common/drivers/gpio/mtgpio_common.h b/plat/mediatek/common/drivers/gpio/mtgpio_common.h new file mode 100644 index 0000000000000000000000000000000000000000..bf5105571f778082a43702786c0f44e45137975b --- /dev/null +++ b/plat/mediatek/common/drivers/gpio/mtgpio_common.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_GPIO_COMMON_H +#define MT_GPIO_COMMON_H + +#include +#include + +#include + +/* Error Code No. */ +#define RSUCCESS 0 +#define ERACCESS 1 +#define ERINVAL 2 +#define ERWRAPPER 3 +#define MAX_GPIO_PIN MT_GPIO_BASE_MAX + +/* GPIO MODE CONTROL VALUE*/ +typedef enum { + GPIO_MODE_UNSUPPORTED = -1, + GPIO_MODE_GPIO = 0, + GPIO_MODE_00 = 0, + GPIO_MODE_01, + GPIO_MODE_02, + GPIO_MODE_03, + GPIO_MODE_04, + GPIO_MODE_05, + GPIO_MODE_06, + GPIO_MODE_07, + + GPIO_MODE_MAX, + GPIO_MODE_DEFAULT = GPIO_MODE_00, +} GPIO_MODE; + +/* GPIO DIRECTION */ +typedef enum { + MT_GPIO_DIR_UNSUPPORTED = -1, + MT_GPIO_DIR_OUT = 0, + MT_GPIO_DIR_IN = 1, + MT_GPIO_DIR_MAX, + MT_GPIO_DIR_DEFAULT = MT_GPIO_DIR_IN, +} GPIO_DIR; + +/* GPIO PULL ENABLE*/ +typedef enum { + MT_GPIO_PULL_EN_UNSUPPORTED = -1, + MT_GPIO_PULL_DISABLE = 0, + MT_GPIO_PULL_ENABLE = 1, + MT_GPIO_PULL_ENABLE_R0 = 2, + MT_GPIO_PULL_ENABLE_R1 = 3, + MT_GPIO_PULL_ENABLE_R0R1 = 4, + + MT_GPIO_PULL_EN_MAX, + MT_GPIO_PULL_EN_DEFAULT = MT_GPIO_PULL_ENABLE, +} GPIO_PULL_EN; + +/* GPIO PULL-UP/PULL-DOWN*/ +typedef enum { + MT_GPIO_PULL_UNSUPPORTED = -1, + MT_GPIO_PULL_NONE = 0, + MT_GPIO_PULL_UP = 1, + MT_GPIO_PULL_DOWN = 2, + MT_GPIO_PULL_MAX, + MT_GPIO_PULL_DEFAULT = MT_GPIO_PULL_DOWN +} GPIO_PULL; + +/* GPIO OUTPUT */ +typedef enum { + MT_GPIO_OUT_UNSUPPORTED = -1, + MT_GPIO_OUT_ZERO = 0, + MT_GPIO_OUT_ONE = 1, + + MT_GPIO_OUT_MAX, + MT_GPIO_OUT_DEFAULT = MT_GPIO_OUT_ZERO, + MT_GPIO_DATA_OUT_DEFAULT = MT_GPIO_OUT_ZERO, /*compatible with DCT*/ +} GPIO_OUT; + +/* GPIO INPUT */ +typedef enum { + MT_GPIO_IN_UNSUPPORTED = -1, + MT_GPIO_IN_ZERO = 0, + MT_GPIO_IN_ONE = 1, + + MT_GPIO_IN_MAX, +} GPIO_IN; + +#define PIN(_id, _flag, _bit, _base, _offset) { \ + .id = _id, \ + .flag = _flag, \ + .bit = _bit, \ + .base = _base, \ + .offset = _offset, \ + } + +struct mt_pin_info { + uint8_t id; + uint8_t flag; + uint8_t bit; + uint16_t base; + uint16_t offset; +}; + +void mt_gpio_init(void); +uintptr_t mt_gpio_find_reg_addr(uint32_t pin); +#endif /* MT_GPIO_COMMON_H */ diff --git a/plat/mediatek/mt8192/drivers/rtc/rtc.c b/plat/mediatek/common/drivers/rtc/rtc_mt6359p.c similarity index 100% rename from plat/mediatek/mt8192/drivers/rtc/rtc.c rename to plat/mediatek/common/drivers/rtc/rtc_mt6359p.c diff --git a/plat/mediatek/mt8192/drivers/rtc/rtc.h b/plat/mediatek/common/drivers/rtc/rtc_mt6359p.h similarity index 98% rename from plat/mediatek/mt8192/drivers/rtc/rtc.h rename to plat/mediatek/common/drivers/rtc/rtc_mt6359p.h index 419bfe42c29c1b34b17c9ceecbd95b3ab3c11cfe..04726e3907f50f56f2f7c1e539739482e47a64e1 100644 --- a/plat/mediatek/mt8192/drivers/rtc/rtc.h +++ b/plat/mediatek/common/drivers/rtc/rtc_mt6359p.h @@ -4,8 +4,8 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef RTC_H -#define RTC_H +#ifndef RTC_MT6359P_H +#define RTC_MT6359P_H /* RTC registers */ enum { @@ -194,4 +194,4 @@ int32_t RTC_Write_Trigger(void); int32_t Writeif_unlock(void); void rtc_power_off_sequence(void); -#endif /* RTC_H */ +#endif /* RTC_MT6359P_H */ diff --git a/plat/mediatek/mt8192/drivers/timer/mt_timer.c b/plat/mediatek/common/drivers/timer/mt_timer.c similarity index 100% rename from plat/mediatek/mt8192/drivers/timer/mt_timer.c rename to plat/mediatek/common/drivers/timer/mt_timer.c diff --git a/plat/mediatek/mt8192/drivers/timer/mt_timer.h b/plat/mediatek/common/drivers/timer/mt_timer.h similarity index 100% rename from plat/mediatek/mt8192/drivers/timer/mt_timer.h rename to plat/mediatek/common/drivers/timer/mt_timer.h diff --git a/plat/mediatek/mt8192/plat_mt_cirq.c b/plat/mediatek/common/mtk_cirq.c similarity index 99% rename from plat/mediatek/mt8192/plat_mt_cirq.c rename to plat/mediatek/common/mtk_cirq.c index 9002b7ee1df410bc1cf9c820a2144c23969c71ed..de3798684b1b35626c503e675995217a399b2888 100644 --- a/plat/mediatek/mt8192/plat_mt_cirq.c +++ b/plat/mediatek/common/mtk_cirq.c @@ -10,8 +10,7 @@ #include #include -#include -#include +#include static struct cirq_events cirq_all_events = { .spi_start = CIRQ_SPI_START, diff --git a/plat/mediatek/mt8192/include/plat_mt_cirq.h b/plat/mediatek/common/mtk_cirq.h similarity index 93% rename from plat/mediatek/mt8192/include/plat_mt_cirq.h rename to plat/mediatek/common/mtk_cirq.h index bb8b4577f8520306b600219a043f2f810c37a969..6e63bb834a26e0321ebdd8ee1e25c5e595f6e592 100644 --- a/plat/mediatek/mt8192/include/plat_mt_cirq.h +++ b/plat/mediatek/common/mtk_cirq.h @@ -8,6 +8,7 @@ #define PLAT_MT_CIRQ_H #include +#include enum { IRQ_MASK_HEADER = 0xF1F1F1F1, @@ -35,13 +36,6 @@ struct mtk_irq_mask { /* * Define hardware register */ - -#define SYS_CIRQ_BASE U(0x10204000) -#define CIRQ_REG_NUM U(14) -#define CIRQ_IRQ_NUM U(439) -#define CIRQ_SPI_START U(64) -#define MD_WDT_IRQ_BIT_ID U(110) - #define CIRQ_STA_BASE (SYS_CIRQ_BASE + U(0x000)) #define CIRQ_ACK_BASE (SYS_CIRQ_BASE + U(0x080)) #define CIRQ_MASK_BASE (SYS_CIRQ_BASE + U(0x100)) diff --git a/plat/mediatek/mt8192/bl31_plat_setup.c b/plat/mediatek/mt8192/bl31_plat_setup.c index 61215a862351b2fbbdf5cd2f5e3f078c01eb8b54..c3cb9a555d2708e75281c782fc1c51d2c497071a 100644 --- a/plat/mediatek/mt8192/bl31_plat_setup.c +++ b/plat/mediatek/mt8192/bl31_plat_setup.c @@ -102,7 +102,7 @@ void bl31_platform_setup(void) mt_gic_driver_init(); mt_gic_init(); - plat_mt8192_gpio_init(); + mt_gpio_init(); mt_systimer_init(); generic_delay_timer_init(); spm_boot_init(); diff --git a/plat/mediatek/mt8192/drivers/gpio/mtgpio.c b/plat/mediatek/mt8192/drivers/gpio/mtgpio.c index e07b75a4766169f323d962cf505326296850554a..c78332d348dbe675d984ba5e5680c0ed104bc123 100644 --- a/plat/mediatek/mt8192/drivers/gpio/mtgpio.c +++ b/plat/mediatek/mt8192/drivers/gpio/mtgpio.c @@ -5,94 +5,17 @@ */ #include -#include -#include -#include -#include #include #include -/****************************************************************************** - *Macro Definition - ******************************************************************************/ -#define GPIO_MODE_BITS 4 -#define MAX_GPIO_MODE_PER_REG 8 -#define MAX_GPIO_REG_BITS 32 -#define DIR_BASE (GPIO_BASE + 0x000) -#define DOUT_BASE (GPIO_BASE + 0x100) -#define DIN_BASE (GPIO_BASE + 0x200) -#define MODE_BASE (GPIO_BASE + 0x300) -#define SET 0x4 -#define CLR 0x8 - -static void mt_set_gpio_dir_chip(uint32_t pin, int dir) -{ - uint32_t pos, bit; - - assert(pin < MAX_GPIO_PIN); - assert(dir < MT_GPIO_DIR_MAX); - - pos = pin / MAX_GPIO_REG_BITS; - bit = pin % MAX_GPIO_REG_BITS; - - if (dir == MT_GPIO_DIR_IN) { - mmio_write_32(DIR_BASE + 0x10U * pos + CLR, 1U << bit); - } else { - mmio_write_32(DIR_BASE + 0x10U * pos + SET, 1U << bit); - } -} - -static int mt_get_gpio_dir_chip(uint32_t pin) -{ - uint32_t pos, bit; - uint32_t reg; - - assert(pin < MAX_GPIO_PIN); - - pos = pin / MAX_GPIO_REG_BITS; - bit = pin % MAX_GPIO_REG_BITS; - - reg = mmio_read_32(DIR_BASE + 0x10U * pos); - return (((reg & (1U << bit)) != 0U) ? MT_GPIO_DIR_OUT : MT_GPIO_DIR_IN); -} - -static void mt_set_gpio_out_chip(uint32_t pin, int output) -{ - uint32_t pos, bit; - - assert(pin < MAX_GPIO_PIN); - assert(output < MT_GPIO_OUT_MAX); - - pos = pin / MAX_GPIO_REG_BITS; - bit = pin % MAX_GPIO_REG_BITS; - - if (output == MT_GPIO_OUT_ZERO) { - mmio_write_32(DOUT_BASE + 0x10U * pos + CLR, 1U << bit); - } else { - mmio_write_32(DOUT_BASE + 0x10U * pos + SET, 1U << bit); - } -} - -static int mt_get_gpio_in_chip(uint32_t pin) -{ - uint32_t pos, bit; - uint32_t reg; - - assert(pin < MAX_GPIO_PIN); - - pos = pin / MAX_GPIO_REG_BITS; - bit = pin % MAX_GPIO_REG_BITS; - - reg = mmio_read_32(DIN_BASE + 0x10U * pos); - return (((reg & (1U << bit)) != 0U) ? 1 : 0); -} - -static uintptr_t mt_gpio_find_reg_addr(uint32_t pin) +uintptr_t mt_gpio_find_reg_addr(uint32_t pin) { uintptr_t reg_addr = 0U; struct mt_pin_info gpio_info; - gpio_info = mt8192_pin_infos[pin]; + assert(pin < MAX_GPIO_PIN); + + gpio_info = mt_pin_infos[pin]; switch (gpio_info.base & 0x0f) { case 0: @@ -128,213 +51,3 @@ static uintptr_t mt_gpio_find_reg_addr(uint32_t pin) return reg_addr; } - -static void mt_gpio_set_spec_pull_pupd(uint32_t pin, int enable, - int select) -{ - uintptr_t reg1; - uintptr_t reg2; - struct mt_pin_info gpio_info; - - gpio_info = mt8192_pin_infos[pin]; - uint32_t bit = gpio_info.bit; - - reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset; - reg2 = reg1 + (gpio_info.base & 0xf0); - if (enable == MT_GPIO_PULL_ENABLE) { - mmio_write_32(reg2 + SET, (1U << bit)); - if (select == MT_GPIO_PULL_DOWN) { - mmio_write_32(reg1 + SET, (1U << bit)); - } else { - mmio_write_32(reg1 + CLR, (1U << bit)); - } - } else { - mmio_write_32(reg2 + CLR, (1U << bit)); - mmio_write_32((reg2 + 0x010U) + CLR, (1U << bit)); - } -} - -static void mt_gpio_set_pull_pu_pd(uint32_t pin, int enable, - int select) -{ - uintptr_t reg1; - uintptr_t reg2; - struct mt_pin_info gpio_info; - - gpio_info = mt8192_pin_infos[pin]; - uint32_t bit = gpio_info.bit; - - reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset; - reg2 = reg1 - (gpio_info.base & 0xf0); - - if (enable == MT_GPIO_PULL_ENABLE) { - if (select == MT_GPIO_PULL_DOWN) { - mmio_write_32(reg1 + CLR, (1U << bit)); - mmio_write_32(reg2 + SET, (1U << bit)); - } else { - mmio_write_32(reg2 + CLR, (1U << bit)); - mmio_write_32(reg1 + SET, (1U << bit)); - } - } else { - mmio_write_32(reg1 + CLR, (1U << bit)); - mmio_write_32(reg2 + CLR, (1U << bit)); - } -} - -static void mt_gpio_set_pull_chip(uint32_t pin, int enable, - int select) -{ - struct mt_pin_info gpio_info; - - gpio_info = mt8192_pin_infos[pin]; - if (gpio_info.flag) { - mt_gpio_set_spec_pull_pupd(pin, enable, select); - } else { - mt_gpio_set_pull_pu_pd(pin, enable, select); - } -} - -static int mt_gpio_get_spec_pull_pupd(uint32_t pin) -{ - uintptr_t reg1; - uintptr_t reg2; - uint32_t r0; - uint32_t r1; - - struct mt_pin_info gpio_info; - - gpio_info = mt8192_pin_infos[pin]; - uint32_t bit = gpio_info.bit; - - reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset; - reg2 = reg1 + (gpio_info.base & 0xf0); - - r0 = (mmio_read_32(reg2) >> bit) & 1U; - r1 = (mmio_read_32(reg2 + 0x010) >> bit) & 1U; - if (r0 == 0U && r1 == 0U) { - return MT_GPIO_PULL_NONE; - } else { - if (mmio_read_32(reg1) & (1U << bit)) { - return MT_GPIO_PULL_DOWN; - } else { - return MT_GPIO_PULL_UP; - } - } -} - -static int mt_gpio_get_pull_pu_pd(uint32_t pin) -{ - uintptr_t reg1; - uintptr_t reg2; - uint32_t pu; - uint32_t pd; - - struct mt_pin_info gpio_info; - - gpio_info = mt8192_pin_infos[pin]; - uint32_t bit = gpio_info.bit; - - reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset; - reg2 = reg1 - (gpio_info.base & 0xf0); - pu = (mmio_read_32(reg1) >> bit) & 1U; - pd = (mmio_read_32(reg2) >> bit) & 1U; - if (pu == 1U) { - return MT_GPIO_PULL_UP; - } else if (pd == 1U) { - return MT_GPIO_PULL_DOWN; - } else { - return MT_GPIO_PULL_NONE; - } -} - -static int mt_gpio_get_pull_chip(uint32_t pin) -{ - struct mt_pin_info gpio_info; - - gpio_info = mt8192_pin_infos[pin]; - if (gpio_info.flag) { - return mt_gpio_get_spec_pull_pupd(pin); - } else { - return mt_gpio_get_pull_pu_pd(pin); - } -} - -static void mt_set_gpio_pull_select_chip(uint32_t pin, int sel) -{ - assert(pin < MAX_GPIO_PIN); - - if (sel == MT_GPIO_PULL_NONE) { - mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_DISABLE, MT_GPIO_PULL_DOWN); - } else if (sel == MT_GPIO_PULL_UP) { - mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_UP); - } else if (sel == MT_GPIO_PULL_DOWN) { - mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_DOWN); - } -} - -/* get pull-up or pull-down, regardless of resistor value */ -static int mt_get_gpio_pull_select_chip(uint32_t pin) -{ - assert(pin < MAX_GPIO_PIN); - - return mt_gpio_get_pull_chip(pin); -} - -static void mt_set_gpio_dir(int gpio, int direction) -{ - mt_set_gpio_dir_chip((uint32_t)gpio, direction); -} - -static int mt_get_gpio_dir(int gpio) -{ - uint32_t pin; - - pin = (uint32_t)gpio; - return mt_get_gpio_dir_chip(pin); -} - -static void mt_set_gpio_pull(int gpio, int pull) -{ - uint32_t pin; - - pin = (uint32_t)gpio; - mt_set_gpio_pull_select_chip(pin, pull); -} - -static int mt_get_gpio_pull(int gpio) -{ - uint32_t pin; - - pin = (uint32_t)gpio; - return mt_get_gpio_pull_select_chip(pin); -} - -static void mt_set_gpio_out(int gpio, int value) -{ - uint32_t pin; - - pin = (uint32_t)gpio; - mt_set_gpio_out_chip(pin, value); -} - -static int mt_get_gpio_in(int gpio) -{ - uint32_t pin; - - pin = (uint32_t)gpio; - return mt_get_gpio_in_chip(pin); -} - -const gpio_ops_t mtgpio_ops = { - .get_direction = mt_get_gpio_dir, - .set_direction = mt_set_gpio_dir, - .get_value = mt_get_gpio_in, - .set_value = mt_set_gpio_out, - .set_pull = mt_set_gpio_pull, - .get_pull = mt_get_gpio_pull, -}; - -void plat_mt8192_gpio_init(void) -{ - gpio_init(&mtgpio_ops); -} diff --git a/plat/mediatek/mt8192/drivers/gpio/mtgpio.h b/plat/mediatek/mt8192/drivers/gpio/mtgpio.h index ca0c964f6ff5fc9f76bf30061258f1db5b47c365..d3aa24db3db20700c97592ea788b04c7013efbe8 100644 --- a/plat/mediatek/mt8192/drivers/gpio/mtgpio.h +++ b/plat/mediatek/mt8192/drivers/gpio/mtgpio.h @@ -7,17 +7,7 @@ #ifndef MT_GPIO_H #define MT_GPIO_H -#include -#include - -#include - -/* Error Code No. */ -#define RSUCCESS 0 -#define ERACCESS 1 -#define ERINVAL 2 -#define ERWRAPPER 3 -#define MAX_GPIO_PIN MT_GPIO_BASE_MAX +#include /* Enumeration for GPIO pin */ typedef enum GPIO_PIN { @@ -54,110 +44,7 @@ typedef enum GPIO_PIN { MT_GPIO_BASE_MAX } GPIO_PIN; -/* GPIO MODE CONTROL VALUE*/ -typedef enum { - GPIO_MODE_UNSUPPORTED = -1, - GPIO_MODE_GPIO = 0, - GPIO_MODE_00 = 0, - GPIO_MODE_01, - GPIO_MODE_02, - GPIO_MODE_03, - GPIO_MODE_04, - GPIO_MODE_05, - GPIO_MODE_06, - GPIO_MODE_07, - - GPIO_MODE_MAX, - GPIO_MODE_DEFAULT = GPIO_MODE_00, -} GPIO_MODE; - -/* GPIO DIRECTION */ -typedef enum { - MT_GPIO_DIR_UNSUPPORTED = -1, - MT_GPIO_DIR_OUT = 0, - MT_GPIO_DIR_IN = 1, - MT_GPIO_DIR_MAX, - MT_GPIO_DIR_DEFAULT = MT_GPIO_DIR_IN, -} GPIO_DIR; - -/* GPIO PULL ENABLE*/ -typedef enum { - MT_GPIO_PULL_EN_UNSUPPORTED = -1, - MT_GPIO_PULL_DISABLE = 0, - MT_GPIO_PULL_ENABLE = 1, - MT_GPIO_PULL_ENABLE_R0 = 2, - MT_GPIO_PULL_ENABLE_R1 = 3, - MT_GPIO_PULL_ENABLE_R0R1 = 4, - - MT_GPIO_PULL_EN_MAX, - MT_GPIO_PULL_EN_DEFAULT = MT_GPIO_PULL_ENABLE, -} GPIO_PULL_EN; - -/* GPIO PULL-UP/PULL-DOWN*/ -typedef enum { - MT_GPIO_PULL_UNSUPPORTED = -1, - MT_GPIO_PULL_NONE = 0, - MT_GPIO_PULL_UP = 1, - MT_GPIO_PULL_DOWN = 2, - MT_GPIO_PULL_MAX, - MT_GPIO_PULL_DEFAULT = MT_GPIO_PULL_DOWN -} GPIO_PULL; - -/* GPIO OUTPUT */ -typedef enum { - MT_GPIO_OUT_UNSUPPORTED = -1, - MT_GPIO_OUT_ZERO = 0, - MT_GPIO_OUT_ONE = 1, - - MT_GPIO_OUT_MAX, - MT_GPIO_OUT_DEFAULT = MT_GPIO_OUT_ZERO, - MT_GPIO_DATA_OUT_DEFAULT = MT_GPIO_OUT_ZERO, /*compatible with DCT*/ -} GPIO_OUT; - -/* GPIO INPUT */ -typedef enum { - MT_GPIO_IN_UNSUPPORTED = -1, - MT_GPIO_IN_ZERO = 0, - MT_GPIO_IN_ONE = 1, - - MT_GPIO_IN_MAX, -} GPIO_IN; - -typedef struct { - uint32_t val; - uint32_t set; - uint32_t rst; - uint32_t _align1; -} VAL_REGS; - -typedef struct { - VAL_REGS dir[7]; - uint8_t rsv00[144]; - VAL_REGS dout[7]; - uint8_t rsv01[144]; - VAL_REGS din[7]; - uint8_t rsv02[144]; - VAL_REGS mode[28]; -} GPIO_REGS; - - -#define PIN(_id, _flag, _bit, _base, _offset) { \ - .id = _id, \ - .flag = _flag, \ - .bit = _bit, \ - .base = _base, \ - .offset = _offset, \ - } - -struct mt_pin_info { - uint8_t id; - uint8_t flag; - uint8_t bit; - uint16_t base; - uint16_t offset; -}; - -static const struct mt_pin_info mt8192_pin_infos[] = { +static const struct mt_pin_info mt_pin_infos[] = { PIN(0, 0, 9, 0x23, 0xb0), PIN(1, 0, 10, 0x23, 0xb0), PIN(2, 0, 11, 0x23, 0xb0), @@ -379,6 +266,4 @@ static const struct mt_pin_info mt8192_pin_infos[] = { PIN(218, 0, 1, 0x14, 0x50), PIN(219, 0, 2, 0x14, 0x50), }; - -void plat_mt8192_gpio_init(void); #endif /* MT_GPIO_H */ diff --git a/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c b/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c index 809518fff21c0379ce13511de5afc211ab5dbc91..e74d3e7bc443cc53c30c3c27e88f5303085b6fb3 100644 --- a/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c +++ b/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c @@ -6,8 +6,8 @@ #include #include +#include #include -#include #define EDMA0_IRQ_ID U(448) #define MDLA_IRQ_ID U(446) diff --git a/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c b/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c index 92fd25fd316716118e68cd8050528e44ea014ddc..f66b8ec932103f717e0865576379f6607ca1c31c 100644 --- a/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c +++ b/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c @@ -24,7 +24,7 @@ #ifndef ATF_PLAT_CIRQ_UNSUPPORT #include -#include +#include #endif #define CONSTRAINT_BUS26M_ALLOW \ diff --git a/plat/mediatek/mt8192/include/platform_def.h b/plat/mediatek/mt8192/include/platform_def.h index 17e9a15072b0b21ca5c69c168d3c215f22d21743..320124f07cfbad19355280183ed5b855c4c55a12 100644 --- a/plat/mediatek/mt8192/include/platform_def.h +++ b/plat/mediatek/mt8192/include/platform_def.h @@ -65,13 +65,19 @@ #define SYS_COUNTER_FREQ_IN_MHZ 13 /******************************************************************************* - * GIC-400 & interrupt handling related constants + * GIC-600 & interrupt handling related constants ******************************************************************************/ /* Base MTK_platform compatible GIC memory map */ #define BASE_GICD_BASE MT_GIC_BASE #define MT_GIC_RDIST_BASE (MT_GIC_BASE + 0x40000) +#define SYS_CIRQ_BASE (IO_PHYS + 0x204000) +#define CIRQ_REG_NUM 14 +#define CIRQ_IRQ_NUM 439 +#define CIRQ_SPI_START 64 +#define MD_WDT_IRQ_BIT_ID 110 + /******************************************************************************* * Platform binary types for linking ******************************************************************************/ diff --git a/plat/mediatek/mt8192/include/rtc.h b/plat/mediatek/mt8192/include/rtc.h new file mode 100644 index 0000000000000000000000000000000000000000..a9c7bc83f4fa537135f40b1db9045e8b34ffa292 --- /dev/null +++ b/plat/mediatek/mt8192/include/rtc.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RTC_H +#define RTC_H + +#include + +#endif /* RTC_H */ diff --git a/plat/mediatek/mt8192/platform.mk b/plat/mediatek/mt8192/platform.mk index c5a9ae0cfc5db7edb0939de14a2dbf1b28e193ce..1a57ea85073f5bf6e0717a0317a598d50dd19916 100644 --- a/plat/mediatek/mt8192/platform.mk +++ b/plat/mediatek/mt8192/platform.mk @@ -8,7 +8,11 @@ MTK_PLAT := plat/mediatek MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT} PLAT_INCLUDES := -I${MTK_PLAT}/common/ \ - -I${MTK_PLAT}/common/drivers/uart/ \ + -I${MTK_PLAT}/common/drivers/gic600/ \ + -I${MTK_PLAT}/common/drivers/gpio/ \ + -I${MTK_PLAT}/common/drivers/rtc/ \ + -I${MTK_PLAT}/common/drivers/timer/ \ + -I${MTK_PLAT}/common/drivers/uart/ \ -I${MTK_PLAT}/common/lpm/ \ -I${MTK_PLAT_SOC}/include/ \ -I${MTK_PLAT_SOC}/drivers/ \ @@ -19,9 +23,7 @@ PLAT_INCLUDES := -I${MTK_PLAT}/common/ \ -I${MTK_PLAT_SOC}/drivers/mcdi/ \ -I${MTK_PLAT_SOC}/drivers/pmic/ \ -I${MTK_PLAT_SOC}/drivers/ptp3/ \ - -I${MTK_PLAT_SOC}/drivers/rtc/ \ - -I${MTK_PLAT_SOC}/drivers/spmc/ \ - -I${MTK_PLAT_SOC}/drivers/timer/ + -I${MTK_PLAT_SOC}/drivers/spmc/ GICV3_SUPPORT_GIC600 := 1 include drivers/arm/gic/v3/gicv3.mk @@ -41,10 +43,15 @@ BL31_SOURCES += common/desc_image_load.c \ lib/cpus/aarch64/cortex_a55.S \ lib/cpus/aarch64/cortex_a76.S \ plat/common/plat_gicv3.c \ + ${MTK_PLAT}/common/drivers/gic600/mt_gic_v3.c \ + ${MTK_PLAT}/common/drivers/gpio/mtgpio_common.c \ ${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init_v2.c \ ${MTK_PLAT}/common/drivers/rtc/rtc_common.c \ + ${MTK_PLAT}/common/drivers/rtc/rtc_mt6359p.c \ + ${MTK_PLAT}/common/drivers/timer/mt_timer.c \ ${MTK_PLAT}/common/drivers/uart/uart.c \ ${MTK_PLAT}/common/lpm/mt_lp_rm.c \ + ${MTK_PLAT}/common/mtk_cirq.c \ ${MTK_PLAT}/common/mtk_plat_common.c \ ${MTK_PLAT}/common/mtk_sip_svc.c \ ${MTK_PLAT}/common/params_setup.c \ @@ -52,11 +59,8 @@ BL31_SOURCES += common/desc_image_load.c \ ${MTK_PLAT_SOC}/aarch64/plat_helpers.S \ ${MTK_PLAT_SOC}/bl31_plat_setup.c \ ${MTK_PLAT_SOC}/drivers/pmic/pmic.c \ - ${MTK_PLAT_SOC}/drivers/rtc/rtc.c \ ${MTK_PLAT_SOC}/plat_pm.c \ ${MTK_PLAT_SOC}/plat_topology.c \ - ${MTK_PLAT_SOC}/plat_mt_gic.c \ - ${MTK_PLAT_SOC}/plat_mt_cirq.c \ ${MTK_PLAT_SOC}/plat_sip_calls.c \ ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c \ ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c \ @@ -68,8 +72,7 @@ BL31_SOURCES += common/desc_image_load.c \ ${MTK_PLAT_SOC}/drivers/mcdi/mt_lp_irqremain.c \ ${MTK_PLAT_SOC}/drivers/mcdi/mt_mcdi.c \ ${MTK_PLAT_SOC}/drivers/ptp3/mtk_ptp3_main.c \ - ${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c \ - ${MTK_PLAT_SOC}/drivers/timer/mt_timer.c + ${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c # Build SPM drivers include ${MTK_PLAT_SOC}/drivers/spm/build.mk diff --git a/plat/mediatek/mt8195/aarch64/plat_helpers.S b/plat/mediatek/mt8195/aarch64/plat_helpers.S new file mode 100644 index 0000000000000000000000000000000000000000..a973f4d2d8acfed2469b81951d2d0b9f8cf901e4 --- /dev/null +++ b/plat/mediatek/mt8195/aarch64/plat_helpers.S @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + .globl plat_mediatek_calc_core_pos + +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #PLAT_PRIMARY_CPU + cset x0, eq + ret +endfunc plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * This function uses the plat_mediatek_calc_core_pos() + * definition to get the index of the calling CPU. + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b plat_mediatek_calc_core_pos +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr); + * + * In ARMv8.2, AFF2 is cluster id, AFF1 is core id and + * AFF0 is thread id. There is only one cluster in ARMv8.2 + * and one thread in current implementation. + * + * With this function: CorePos = CoreID (AFF1) + * we do it with x0 = (x0 >> 8) & 0xff + * ----------------------------------------------------- + */ +func plat_mediatek_calc_core_pos + mov x1, #MPIDR_AFFLVL_MASK + and x0, x1, x0, lsr #MPIDR_AFF1_SHIFT + ret +endfunc plat_mediatek_calc_core_pos diff --git a/plat/mediatek/mt8195/aarch64/platform_common.c b/plat/mediatek/mt8195/aarch64/platform_common.c new file mode 100644 index 0000000000000000000000000000000000000000..745e54750d223572c7b1c3d43738308a460f320b --- /dev/null +++ b/plat/mediatek/mt8195/aarch64/platform_common.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +/* Table of regions to map using the MMU. */ +const mmap_region_t plat_mmap[] = { + /* for TF text, RO, RW */ + MAP_REGION_FLAT(MTK_DEV_RNG0_BASE, MTK_DEV_RNG0_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MTK_DEV_RNG1_BASE, MTK_DEV_RNG1_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(MTK_DEV_RNG2_BASE, MTK_DEV_RNG2_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + { 0 } +}; + +/******************************************************************************* + * Macro generating the code for the function setting up the pagetables as per + * the platform memory map & initialize the mmu, for the given exception level + ******************************************************************************/ +void plat_configure_mmu_el3(uintptr_t total_base, + uintptr_t total_size, + uintptr_t ro_start, + uintptr_t ro_limit) +{ + mmap_add_region(total_base, total_base, total_size, + MT_RW_DATA | MT_SECURE); + mmap_add_region(ro_start, ro_start, ro_limit - ro_start, + MT_CODE | MT_SECURE); + mmap_add(plat_mmap); + init_xlat_tables(); + enable_mmu_el3(0); +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return SYS_COUNTER_FREQ_IN_TICKS; +} diff --git a/plat/mediatek/mt8195/bl31_plat_setup.c b/plat/mediatek/mt8195/bl31_plat_setup.c new file mode 100644 index 0000000000000000000000000000000000000000..eaff3493abddba390a4cc22b2151294d3473075a --- /dev/null +++ b/plat/mediatek/mt8195/bl31_plat_setup.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* System Includes */ +#include + +/* Project Includes */ +#include +#include +#include +#include +#include +#include + +/* Platform Includes */ +#include +#include +#include +#include +#include + +static entry_point_info_t bl32_ep_info; +static entry_point_info_t bl33_ep_info; + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info; + assert(next_image_info->h.type == PARAM_EP); + + /* None of the images on this platform can have 0x0 as the entrypoint */ + if (next_image_info->pc) { + return next_image_info; + } else { + return NULL; + } +} + +/******************************************************************************* + * Perform any BL31 early platform setup. Here is an opportunity to copy + * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before they + * are lost (potentially). This needs to be done before the MMU is initialized + * so that the memory layout can be used while creating page tables. + * BL2 has flushed this information to memory, so we are guaranteed to pick up + * good data. + ******************************************************************************/ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + static console_t console; + + params_early_setup(arg1); + +#if COREBOOT + if (coreboot_serial.type) { + console_16550_register(coreboot_serial.baseaddr, + coreboot_serial.input_hertz, + coreboot_serial.baud, + &console); + } +#else + console_16550_register(UART0_BASE, UART_CLOCK, UART_BAUDRATE, &console); +#endif + + NOTICE("MT8195 bl31_setup\n"); + + bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info); +} + + +/******************************************************************************* + * Perform any BL31 platform setup code + ******************************************************************************/ +void bl31_platform_setup(void) +{ + /* Initialize the GIC driver, CPU and distributor interfaces */ + mt_gic_driver_init(); + mt_gic_init(); + + mt_gpio_init(); + mt_systimer_init(); + generic_delay_timer_init(); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only intializes the mmu in a quick and dirty way. + ******************************************************************************/ +void bl31_plat_arch_setup(void) +{ + plat_configure_mmu_el3(BL31_START, + BL31_END - BL31_START, + BL_CODE_BASE, + BL_CODE_END); +} diff --git a/plat/mediatek/mt8195/drivers/gpio/mtgpio.c b/plat/mediatek/mt8195/drivers/gpio/mtgpio.c new file mode 100644 index 0000000000000000000000000000000000000000..daab84c41f329c7d505488c4d8185bc5d1ece67d --- /dev/null +++ b/plat/mediatek/mt8195/drivers/gpio/mtgpio.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +uintptr_t mt_gpio_find_reg_addr(uint32_t pin) +{ + uintptr_t reg_addr = 0U; + struct mt_pin_info gpio_info; + + assert(pin < MAX_GPIO_PIN); + + gpio_info = mt_pin_infos[pin]; + + switch (gpio_info.base & 0x0f) { + case 0: + reg_addr = IOCFG_BM_BASE; + break; + case 1: + reg_addr = IOCFG_BL_BASE; + break; + case 2: + reg_addr = IOCFG_BR_BASE; + break; + case 3: + reg_addr = IOCFG_LM_BASE; + break; + case 4: + reg_addr = IOCFG_RB_BASE; + break; + case 5: + reg_addr = IOCFG_TL_BASE; + break; + default: + break; + } + + return reg_addr; +} diff --git a/plat/mediatek/mt8195/drivers/gpio/mtgpio.h b/plat/mediatek/mt8195/drivers/gpio/mtgpio.h new file mode 100644 index 0000000000000000000000000000000000000000..88b47068caa03342cd7a21f3847db5f3fe8571c9 --- /dev/null +++ b/plat/mediatek/mt8195/drivers/gpio/mtgpio.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_GPIO_H +#define MT_GPIO_H + +#include + +/* Enumeration for GPIO pin */ +typedef enum GPIO_PIN { + GPIO_UNSUPPORTED = -1, + + GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6, GPIO7, + GPIO8, GPIO9, GPIO10, GPIO11, GPIO12, GPIO13, GPIO14, GPIO15, + GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, GPIO23, + GPIO24, GPIO25, GPIO26, GPIO27, GPIO28, GPIO29, GPIO30, GPIO31, + GPIO32, GPIO33, GPIO34, GPIO35, GPIO36, GPIO37, GPIO38, GPIO39, + GPIO40, GPIO41, GPIO42, GPIO43, GPIO44, GPIO45, GPIO46, GPIO47, + GPIO48, GPIO49, GPIO50, GPIO51, GPIO52, GPIO53, GPIO54, GPIO55, + GPIO56, GPIO57, GPIO58, GPIO59, GPIO60, GPIO61, GPIO62, GPIO63, + GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70, GPIO71, + GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78, GPIO79, + GPIO80, GPIO81, GPIO82, GPIO83, GPIO84, GPIO85, GPIO86, GPIO87, + GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94, GPIO95, + GPIO96, GPIO97, GPIO98, GPIO99, GPIO100, GPIO101, GPIO102, GPIO103, + GPIO104, GPIO105, GPIO106, GPIO107, GPIO108, GPIO109, GPIO110, GPIO111, + GPIO112, GPIO113, GPIO114, GPIO115, GPIO116, GPIO117, GPIO118, GPIO119, + GPIO120, GPIO121, GPIO122, GPIO123, GPIO124, GPIO125, GPIO126, GPIO127, + GPIO128, GPIO129, GPIO130, GPIO131, GPIO132, GPIO133, GPIO134, GPIO135, + GPIO136, GPIO137, GPIO138, GPIO139, GPIO140, GPIO141, GPIO142, GPIO143, + MT_GPIO_BASE_MAX +} GPIO_PIN; + +static const struct mt_pin_info mt_pin_infos[] = { + PIN(0, 1, 0, 0x23, 0x60), + PIN(1, 1, 1, 0x23, 0x60), + PIN(2, 1, 2, 0x23, 0x60), + PIN(3, 1, 3, 0x23, 0x60), + PIN(4, 1, 4, 0x23, 0x60), + PIN(5, 1, 5, 0x23, 0x60), + PIN(6, 0, 6, 0x23, 0x70), + PIN(7, 0, 7, 0x23, 0x70), + PIN(8, 0, 13, 0x23, 0x70), + PIN(9, 0, 8, 0x23, 0x70), + PIN(10, 0, 14, 0x23, 0x70), + PIN(11, 0, 9, 0x23, 0x70), + PIN(12, 0, 15, 0x23, 0x70), + PIN(13, 0, 10, 0x23, 0x70), + PIN(14, 0, 16, 0x23, 0x70), + PIN(15, 0, 11, 0x23, 0x70), + PIN(16, 0, 17, 0x23, 0x70), + PIN(17, 0, 12, 0x23, 0x70), + PIN(18, 0, 5, 0x10, 0x60), + PIN(19, 0, 12, 0x10, 0x60), + PIN(20, 0, 11, 0x10, 0x60), + PIN(21, 0, 10, 0x10, 0x60), + PIN(22, 0, 0, 0x10, 0x60), + PIN(23, 0, 1, 0x10, 0x60), + PIN(24, 0, 2, 0x10, 0x60), + PIN(25, 0, 4, 0x10, 0x60), + PIN(26, 0, 3, 0x10, 0x60), + PIN(27, 0, 6, 0x10, 0x60), + PIN(28, 0, 7, 0x10, 0x60), + PIN(29, 0, 8, 0x10, 0x60), + PIN(30, 0, 9, 0x10, 0x60), + PIN(31, 0, 13, 0x21, 0xa0), + PIN(32, 0, 12, 0x21, 0xa0), + PIN(33, 0, 11, 0x21, 0xa0), + PIN(34, 0, 14, 0x21, 0xa0), + PIN(35, 0, 15, 0x21, 0xa0), + PIN(36, 0, 3, 0x21, 0xb0), + PIN(37, 0, 6, 0x21, 0xb0), + PIN(38, 0, 4, 0x21, 0xb0), + PIN(39, 0, 5, 0x21, 0xb0), + PIN(40, 0, 8, 0x21, 0xb0), + PIN(41, 0, 7, 0x21, 0xb0), + PIN(42, 0, 10, 0x21, 0xb0), + PIN(43, 0, 9, 0x21, 0xb0), + PIN(44, 0, 20, 0x21, 0xb0), + PIN(45, 0, 21, 0x21, 0xb0), + PIN(46, 0, 18, 0x21, 0xa0), + PIN(47, 0, 16, 0x21, 0xa0), + PIN(48, 0, 19, 0x21, 0xa0), + PIN(49, 0, 17, 0x21, 0xa0), + PIN(50, 0, 25, 0x21, 0xa0), + PIN(51, 0, 20, 0x21, 0xa0), + PIN(52, 0, 26, 0x21, 0xa0), + PIN(53, 0, 21, 0x21, 0xa0), + PIN(54, 0, 22, 0x21, 0xa0), + PIN(55, 0, 23, 0x21, 0xa0), + PIN(56, 0, 24, 0x21, 0xa0), + PIN(57, 0, 29, 0x21, 0xa0), + PIN(58, 0, 27, 0x21, 0xa0), + PIN(59, 0, 30, 0x21, 0xa0), + PIN(60, 0, 28, 0x21, 0xa0), + PIN(61, 0, 8, 0x21, 0xa0), + PIN(62, 0, 7, 0x21, 0xa0), + PIN(63, 0, 10, 0x21, 0xa0), + PIN(64, 0, 9, 0x21, 0xa0), + PIN(65, 0, 1, 0x21, 0xb0), + PIN(66, 0, 31, 0x21, 0xa0), + PIN(67, 0, 0, 0x21, 0xb0), + PIN(68, 0, 2, 0x21, 0xb0), + PIN(69, 0, 0, 0x21, 0xa0), + PIN(70, 0, 6, 0x21, 0xa0), + PIN(71, 0, 4, 0x21, 0xa0), + PIN(72, 0, 5, 0x21, 0xa0), + PIN(73, 0, 1, 0x21, 0xa0), + PIN(74, 0, 2, 0x21, 0xa0), + PIN(75, 0, 3, 0x21, 0xa0), + PIN(76, 0, 11, 0x21, 0xb0), + PIN(77, 1, 1, 0x22, 0x60), + PIN(78, 1, 2, 0x22, 0x60), + PIN(79, 1, 9, 0x22, 0x60), + PIN(80, 1, 10, 0x22, 0x60), + PIN(81, 1, 11, 0x22, 0x60), + PIN(82, 1, 12, 0x22, 0x60), + PIN(83, 1, 13, 0x22, 0x60), + PIN(84, 1, 14, 0x22, 0x60), + PIN(85, 1, 15, 0x22, 0x60), + PIN(86, 1, 16, 0x22, 0x60), + PIN(87, 1, 3, 0x22, 0x60), + PIN(88, 1, 4, 0x22, 0x60), + PIN(89, 1, 5, 0x22, 0x60), + PIN(90, 1, 6, 0x22, 0x60), + PIN(91, 1, 7, 0x22, 0x60), + PIN(92, 1, 8, 0x22, 0x60), + PIN(93, 1, 18, 0x22, 0x60), + PIN(94, 1, 19, 0x22, 0x60), + PIN(95, 1, 17, 0x22, 0x60), + PIN(96, 1, 0, 0x22, 0x60), + PIN(97, 0, 20, 0x22, 0x70), + PIN(98, 0, 28, 0x22, 0x70), + PIN(99, 0, 27, 0x22, 0x70), + PIN(100, 0, 30, 0x22, 0x70), + PIN(101, 0, 29, 0x22, 0x70), + PIN(102, 0, 0, 0x22, 0x70), + PIN(103, 0, 31, 0x22, 0x70), + PIN(104, 1, 25, 0x22, 0x60), + PIN(105, 1, 26, 0x22, 0x60), + PIN(106, 1, 23, 0x22, 0x60), + PIN(107, 1, 24, 0x22, 0x60), + PIN(108, 0, 22, 0x22, 0x70), + PIN(109, 0, 21, 0x22, 0x70), + PIN(110, 1, 1, 0x14, 0x20), + PIN(111, 1, 0, 0x14, 0x20), + PIN(112, 1, 2, 0x14, 0x20), + PIN(113, 1, 3, 0x14, 0x20), + PIN(114, 1, 4, 0x14, 0x20), + PIN(115, 1, 5, 0x14, 0x20), + PIN(116, 1, 9, 0x25, 0x50), + PIN(117, 1, 8, 0x25, 0x50), + PIN(118, 1, 7, 0x25, 0x50), + PIN(119, 1, 6, 0x25, 0x50), + PIN(120, 1, 11, 0x25, 0x50), + PIN(121, 1, 1, 0x25, 0x50), + PIN(122, 1, 0, 0x25, 0x50), + PIN(123, 1, 5, 0x25, 0x50), + PIN(124, 1, 4, 0x25, 0x50), + PIN(125, 1, 3, 0x25, 0x50), + PIN(126, 1, 2, 0x25, 0x50), + PIN(127, 1, 10, 0x25, 0x50), + PIN(128, 0, 3, 0x22, 0x70), + PIN(129, 0, 1, 0x22, 0x70), + PIN(130, 0, 4, 0x22, 0x70), + PIN(131, 0, 2, 0x22, 0x70), + PIN(132, 0, 13, 0x25, 0x60), + PIN(133, 0, 12, 0x25, 0x60), + PIN(134, 0, 15, 0x25, 0x60), + PIN(135, 0, 14, 0x25, 0x60), + PIN(136, 0, 13, 0x21, 0xb0), + PIN(137, 0, 12, 0x21, 0xb0), + PIN(138, 0, 15, 0x21, 0xb0), + PIN(139, 0, 14, 0x21, 0xb0), + PIN(140, 0, 17, 0x21, 0xb0), + PIN(141, 0, 16, 0x21, 0xb0), + PIN(142, 0, 19, 0x21, 0xb0), + PIN(143, 0, 18, 0x21, 0xb0), +}; +#endif /* MT_GPIO_H */ diff --git a/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c b/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c new file mode 100644 index 0000000000000000000000000000000000000000..d6d4af742a7506bc56650f1ee504ac9f795577c1 --- /dev/null +++ b/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +DEFINE_SYSREG_RW_FUNCS(dbgprcr_el1); + +static int plat_mt_lp_cpu_rc; + +static int pwr_state_prompt(unsigned int cpu, const psci_power_state_t *state) +{ + return 0; +} + +static int pwr_state_reflect(unsigned int cpu, const psci_power_state_t *state) +{ + mtk_cpc_core_on_hint_clr(cpu); + + if (IS_SYSTEM_SUSPEND_STATE(state)) { + mtk_cpc_time_sync(); + } + + return 0; +} + +static int pwr_cpu_pwron(unsigned int cpu, const psci_power_state_t *state) +{ + return 0; +} + +static int pwr_cpu_pwrdwn(unsigned int cpu, const psci_power_state_t *state) +{ + /* clear DBGPRCR.CORENPDRQ to allow CPU power down */ + write_dbgprcr_el1(0ULL); + + return 0; +} + +static int pwr_cluster_pwron(unsigned int cpu, const psci_power_state_t *state) +{ + return 0; +} + +static int pwr_cluster_pwrdwn(unsigned int cpu, const psci_power_state_t *state) +{ + return 0; +} + +static int pwr_mcusys_pwron(unsigned int cpu, const psci_power_state_t *state) +{ + if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) { + return -1; + } + + mtk_cpc_mcusys_off_reflect(); + + return 0; +} + +static int pwr_mcusys_pwron_finished(unsigned int cpu, + const psci_power_state_t *state) +{ + if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) { + return -1; + } + + return 0; +} + +static int pwr_mcusys_pwrdwn(unsigned int cpu, const psci_power_state_t *state) +{ + if (!IS_MCUSYS_OFF_STATE(state)) { + goto mt_pwr_mcusysoff_break; + } + + if (mcdi_try_init() != 0) { /* not ready to process mcusys-off */ + goto mt_pwr_mcusysoff_break; + } + + return 0; + +mt_pwr_mcusysoff_break: + + plat_mt_lp_cpu_rc = -1; + + return -1; +} + +static const struct mt_lpm_tz plat_pm = { + .pwr_prompt = pwr_state_prompt, + .pwr_reflect = pwr_state_reflect, + .pwr_cpu_on = pwr_cpu_pwron, + .pwr_cpu_dwn = pwr_cpu_pwrdwn, + .pwr_cluster_on = pwr_cluster_pwron, + .pwr_cluster_dwn = pwr_cluster_pwrdwn, + .pwr_mcusys_dwn = pwr_mcusys_pwrdwn, + .pwr_mcusys_on = pwr_mcusys_pwron, + .pwr_mcusys_on_finished = pwr_mcusys_pwron_finished +}; + +const struct mt_lpm_tz *mt_plat_cpu_pm_init(void) +{ + mtk_cpc_init(); + + if (mcdi_try_init() == 0) { + INFO("MCDI init done.\n"); + } + + return &plat_pm; +} diff --git a/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.c b/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.c new file mode 100644 index 0000000000000000000000000000000000000000..f8c51a1995d2a6d171ca82c1303c4b6f9cd3974a --- /dev/null +++ b/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include + +struct mtk_cpc_dev { + int auto_off; + unsigned int auto_thres_tick; +}; + +static struct mtk_cpc_dev cpc; + +static int mtk_cpc_last_core_prot(uint32_t prot_req, + uint32_t resp_reg, uint32_t resp_ofs) +{ + uint32_t sta, retry; + + retry = 0U; + + while (retry++ < RETRY_CNT_MAX) { + + mmio_write_32(CPC_MCUSYS_LAST_CORE_REQ, prot_req); + + udelay(1U); + + sta = (mmio_read_32(resp_reg) >> resp_ofs) & CPC_PROT_RESP_MASK; + + if (sta == PROT_SUCCESS) { + return CPC_SUCCESS; + } else if (sta == PROT_GIVEUP) { + return CPC_ERR_FAIL; + } + } + + return CPC_ERR_TIMEOUT; +} + +int mtk_cpu_pm_mcusys_prot_aquire(void) +{ + return mtk_cpc_last_core_prot( + MCUSYS_PROT_SET, + CPC_MCUSYS_LAST_CORE_RESP, + MCUSYS_RESP_OFS); +} + +void mtk_cpu_pm_mcusys_prot_release(void) +{ + mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, MCUSYS_PROT_CLR); +} + +int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster) +{ + return mtk_cpc_last_core_prot( + CPUSYS_PROT_SET, + CPC_MCUSYS_MP_LAST_CORE_RESP, + CPUSYS_RESP_OFS); +} + +void mtk_cpu_pm_cluster_prot_release(unsigned int cluster) +{ + mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, CPUSYS_PROT_CLR); +} + +static void mtk_cpc_cluster_cnt_backup(void) +{ + uint32_t backup_cnt; + uint32_t curr_cnt; + uint32_t cnt_mask = GENMASK(14, 0); + uint32_t clr_mask = GENMASK(1, 0); + + /* Single Cluster */ + backup_cnt = mmio_read_32(CPC_CLUSTER_CNT_BACKUP); + curr_cnt = mmio_read_32(CPC_MCUSYS_CLUSTER_COUNTER); + + /* Get off count if dormant count is 0 */ + if ((curr_cnt & cnt_mask) == 0U) { + curr_cnt = (curr_cnt >> 16) & cnt_mask; + } else { + curr_cnt = curr_cnt & cnt_mask; + } + + mmio_write_32(CPC_CLUSTER_CNT_BACKUP, backup_cnt + curr_cnt); + mmio_write_32(CPC_MCUSYS_CLUSTER_COUNTER_CLR, clr_mask); +} + +static inline void mtk_cpc_mcusys_off_en(void) +{ + mmio_write_32(CPC_MCUSYS_PWR_CTRL, 1U); +} + +static inline void mtk_cpc_mcusys_off_dis(void) +{ + mmio_write_32(CPC_MCUSYS_PWR_CTRL, 0U); +} + +void mtk_cpc_mcusys_off_reflect(void) +{ + mtk_cpc_mcusys_off_dis(); + mtk_cpu_pm_mcusys_prot_release(); +} + +int mtk_cpc_mcusys_off_prepare(void) +{ + if (mtk_cpu_pm_mcusys_prot_aquire() != CPC_SUCCESS) { + return CPC_ERR_FAIL; + } + + mtk_cpc_cluster_cnt_backup(); + mtk_cpc_mcusys_off_en(); + + return CPC_SUCCESS; +} + +void mtk_cpc_core_on_hint_set(unsigned int cpu) +{ + mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_SET, BIT(cpu)); +} + +void mtk_cpc_core_on_hint_clr(unsigned int cpu) +{ + mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu)); +} + +static void mtk_cpc_dump_timestamp(void) +{ + uint32_t id; + + for (id = 0U; id < CPC_TRACE_ID_NUM; id++) { + mmio_write_32(CPC_MCUSYS_TRACE_SEL, id); + + memcpy((void *)(uintptr_t)CPC_TRACE_SRAM(id), + (const void *)(uintptr_t)CPC_MCUSYS_TRACE_DATA, + CPC_TRACE_SIZE); + } +} + +void mtk_cpc_time_sync(void) +{ + uint64_t kt; + uint32_t systime_l, systime_h; + + kt = sched_clock(); + systime_l = mmio_read_32(CNTSYS_L_REG); + systime_h = mmio_read_32(CNTSYS_H_REG); + + /* sync kernel timer to cpc */ + mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE, (uint32_t)kt); + mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE, (uint32_t)(kt >> 32)); + /* sync system timer to cpc */ + mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE, systime_l); + mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE, systime_h); +} + +static void mtk_cpc_config(uint32_t cfg, uint32_t data) +{ + uint32_t val; + uint32_t reg = 0U; + + switch (cfg) { + case CPC_SMC_CONFIG_PROF: + reg = CPC_MCUSYS_CPC_DBG_SETTING; + val = mmio_read_32(reg); + val = (data != 0U) ? (val | CPC_PROF_EN) : (val & ~CPC_PROF_EN); + break; + case CPC_SMC_CONFIG_AUTO_OFF: + reg = CPC_MCUSYS_CPC_FLOW_CTRL_CFG; + val = mmio_read_32(reg); + if (data != 0U) { + val |= CPC_AUTO_OFF_EN; + cpc.auto_off = 1; + } else { + val &= ~CPC_AUTO_OFF_EN; + cpc.auto_off = 0; + } + break; + case CPC_SMC_CONFIG_AUTO_OFF_THRES: + reg = CPC_MCUSYS_CPC_OFF_THRES; + cpc.auto_thres_tick = us_to_ticks(data); + val = cpc.auto_thres_tick; + break; + case CPC_SMC_CONFIG_CNT_CLR: + reg = CPC_MCUSYS_CLUSTER_COUNTER_CLR; + val = GENMASK(1, 0); /* clr_mask */ + break; + case CPC_SMC_CONFIG_TIME_SYNC: + mtk_cpc_time_sync(); + break; + default: + break; + } + + if (reg != 0U) { + mmio_write_32(reg, val); + } +} + +static uint32_t mtk_cpc_read_config(uint32_t cfg) +{ + uint32_t res = 0U; + + switch (cfg) { + case CPC_SMC_CONFIG_PROF: + res = (mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING) & CPC_PROF_EN) ? + 1U : 0U; + break; + case CPC_SMC_CONFIG_AUTO_OFF: + res = cpc.auto_off; + break; + case CPC_SMC_CONFIG_AUTO_OFF_THRES: + res = ticks_to_us(cpc.auto_thres_tick); + break; + case CPC_SMC_CONFIG_CNT_CLR: + break; + default: + break; + } + + return res; +} + +uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2) +{ + uint64_t res = 0ULL; + + switch (act) { + case CPC_SMC_EVENT_DUMP_TRACE_DATA: + mtk_cpc_dump_timestamp(); + break; + case CPC_SMC_EVENT_GIC_DPG_SET: + /* isolated_status = x2; */ + break; + case CPC_SMC_EVENT_CPC_CONFIG: + mtk_cpc_config((uint32_t)arg1, (uint32_t)arg2); + break; + case CPC_SMC_EVENT_READ_CONFIG: + res = mtk_cpc_read_config((uint32_t)arg1); + break; + default: + break; + } + + return res; +} + +void mtk_cpc_init(void) +{ + mmio_write_32(CPC_MCUSYS_CPC_DBG_SETTING, + mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING) + | CPC_DBG_EN + | CPC_CALC_EN); + + cpc.auto_off = 1; + cpc.auto_thres_tick = us_to_ticks(8000); + + mmio_write_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, + mmio_read_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG) + | CPC_OFF_PRE_EN + | (cpc.auto_off ? CPC_AUTO_OFF_EN : 0U)); + + mmio_write_32(CPC_MCUSYS_CPC_OFF_THRES, cpc.auto_thres_tick); +} diff --git a/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.h b/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.h new file mode 100644 index 0000000000000000000000000000000000000000..19dd6a2837c90e9907cf599ca0f818facf4ef5a0 --- /dev/null +++ b/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_CPU_PM_CPC_H +#define MT_CPU_PM_CPC_H + +#include +#include +#include +#include + +#define NEED_CPUSYS_PROT_WORKAROUND 1 + +/* system sram registers */ +#define CPUIDLE_SRAM_REG(r) (uint32_t)(MTK_MCDI_SRAM_BASE + (r)) + +/* db dump */ +#define CPC_TRACE_SIZE U(0x20) +#define CPC_TRACE_ID_NUM U(10) +#define CPC_TRACE_SRAM(id) (CPUIDLE_SRAM_REG(0x10) + (id) * CPC_TRACE_SIZE) + +/* buckup off count */ +#define CPC_CLUSTER_CNT_BACKUP CPUIDLE_SRAM_REG(0x1F0) +#define CPC_MCUSYS_CNT CPUIDLE_SRAM_REG(0x1F4) + +/* CPC_MCUSYS_CPC_FLOW_CTRL_CFG(0xA814): debug setting */ +#define CPC_PWR_ON_SEQ_DIS BIT(1) +#define CPC_PWR_ON_PRIORITY BIT(2) +#define CPC_AUTO_OFF_EN BIT(5) +#define CPC_DORMANT_WAIT_EN BIT(14) +#define CPC_CTRL_EN BIT(16) +#define CPC_OFF_PRE_EN BIT(29) + +/* CPC_MCUSYS_LAST_CORE_REQ(0xA818) : last core protection */ +#define CPUSYS_PROT_SET BIT(0) +#define MCUSYS_PROT_SET BIT(8) +#define CPUSYS_PROT_CLR BIT(8) +#define MCUSYS_PROT_CLR BIT(9) + +#define CPC_PROT_RESP_MASK U(0x3) +#define CPUSYS_RESP_OFS U(16) +#define MCUSYS_RESP_OFS U(30) + +#define cpusys_resp(r) (((r) >> CPUSYS_RESP_OFS) & CPC_PROT_RESP_MASK) +#define mcusys_resp(r) (((r) >> MCUSYS_RESP_OFS) & CPC_PROT_RESP_MASK) + +#define RETRY_CNT_MAX U(1000) + +#define PROT_RETRY U(0) +#define PROT_SUCCESS U(1) +#define PROT_GIVEUP U(2) + +/* CPC_MCUSYS_CPC_DBG_SETTING(0xAB00): debug setting */ +#define CPC_PROF_EN BIT(0) +#define CPC_DBG_EN BIT(1) +#define CPC_FREEZE BIT(2) +#define CPC_CALC_EN BIT(3) + +enum { + CPC_SUCCESS = 0, + + CPC_ERR_FAIL, + CPC_ERR_TIMEOUT, + + NF_CPC_ERR +}; + +enum { + CPC_SMC_EVENT_DUMP_TRACE_DATA, + CPC_SMC_EVENT_GIC_DPG_SET, + CPC_SMC_EVENT_CPC_CONFIG, + CPC_SMC_EVENT_READ_CONFIG, + + NF_CPC_SMC_EVENT +}; + +enum { + CPC_SMC_CONFIG_PROF, + CPC_SMC_CONFIG_AUTO_OFF, + CPC_SMC_CONFIG_AUTO_OFF_THRES, + CPC_SMC_CONFIG_CNT_CLR, + CPC_SMC_CONFIG_TIME_SYNC, + + NF_CPC_SMC_CONFIG +}; + +#define us_to_ticks(us) ((us) * 13) +#define ticks_to_us(tick) ((tick) / 13) + +int mtk_cpu_pm_cluster_prot_aquire(unsigned int cluster); +void mtk_cpu_pm_cluster_prot_release(unsigned int cluster); + +void mtk_cpc_mcusys_off_reflect(void); +int mtk_cpc_mcusys_off_prepare(void); + +void mtk_cpc_core_on_hint_set(unsigned int cpu); +void mtk_cpc_core_on_hint_clr(unsigned int cpu); +void mtk_cpc_time_sync(void); + +uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2); +void mtk_cpc_init(void); + +#endif /* MT_CPU_PM_CPC_H */ diff --git a/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.c b/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.c new file mode 100644 index 0000000000000000000000000000000000000000..df741221d37ef3779c22978994426a472728cd7e --- /dev/null +++ b/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +/* Read/Write */ +#define APMCU_MCUPM_MBOX_AP_READY U(0) +#define APMCU_MCUPM_MBOX_RESERVED_1 U(1) +#define APMCU_MCUPM_MBOX_RESERVED_2 U(2) +#define APMCU_MCUPM_MBOX_RESERVED_3 U(3) +#define APMCU_MCUPM_MBOX_PWR_CTRL_EN U(4) +#define APMCU_MCUPM_MBOX_L3_CACHE_MODE U(5) +#define APMCU_MCUPM_MBOX_BUCK_MODE U(6) +#define APMCU_MCUPM_MBOX_ARMPLL_MODE U(7) +/* Read only */ +#define APMCU_MCUPM_MBOX_TASK_STA U(8) +#define APMCU_MCUPM_MBOX_RESERVED_9 U(9) +#define APMCU_MCUPM_MBOX_RESERVED_10 U(10) +#define APMCU_MCUPM_MBOX_RESERVED_11 U(11) + +/* CPC mode - Read/Write */ +#define APMCU_MCUPM_MBOX_WAKEUP_CPU U(12) + +/* Mbox Slot: APMCU_MCUPM_MBOX_PWR_CTRL_EN */ +#define MCUPM_MCUSYS_CTRL BIT(0) +#define MCUPM_BUCK_CTRL BIT(1) +#define MCUPM_ARMPLL_CTRL BIT(2) +#define MCUPM_CM_CTRL BIT(3) +#define MCUPM_PWR_CTRL_MASK GENMASK(3, 0) + +/* Mbox Slot: APMCU_MCUPM_MBOX_BUCK_MODE */ +#define MCUPM_BUCK_NORMAL_MODE U(0) /* default */ +#define MCUPM_BUCK_LP_MODE U(1) +#define MCUPM_BUCK_OFF_MODE U(2) +#define NF_MCUPM_BUCK_MODE U(3) + +/* Mbox Slot: APMCU_MCUPM_MBOX_ARMPLL_MODE */ +#define MCUPM_ARMPLL_ON U(0) /* default */ +#define MCUPM_ARMPLL_GATING U(1) +#define MCUPM_ARMPLL_OFF U(2) +#define NF_MCUPM_ARMPLL_MODE U(3) + +/* Mbox Slot: APMCU_MCUPM_MBOX_TASK_STA */ +#define MCUPM_TASK_UNINIT U(0) +#define MCUPM_TASK_INIT U(1) +#define MCUPM_TASK_INIT_FINISH U(2) +#define MCUPM_TASK_WAIT U(3) +#define MCUPM_TASK_RUN U(4) +#define MCUPM_TASK_PAUSE U(5) + +#define SSPM_MBOX_3_BASE U(0x0c55fce0) + +#define MCDI_NOT_INIT 0 +#define MCDI_INIT_1 1 +#define MCDI_INIT_2 2 +#define MCDI_INIT_DONE 3 + +static int mcdi_init_status __section("tzfw_coherent_mem"); + +static inline uint32_t mcdi_mbox_read(uint32_t id) +{ + return mmio_read_32(SSPM_MBOX_3_BASE + (id << 2)); +} + +static inline void mcdi_mbox_write(uint32_t id, uint32_t val) +{ + mmio_write_32(SSPM_MBOX_3_BASE + (id << 2), val); +} + +static void mtk_mcupm_pwr_ctrl_setting(uint32_t dev) +{ + mcdi_mbox_write(APMCU_MCUPM_MBOX_PWR_CTRL_EN, dev); +} + +static void mtk_set_mcupm_pll_mode(uint32_t mode) +{ + if (mode < NF_MCUPM_ARMPLL_MODE) { + mcdi_mbox_write(APMCU_MCUPM_MBOX_ARMPLL_MODE, mode); + } +} + +static void mtk_set_mcupm_buck_mode(uint32_t mode) +{ + if (mode < NF_MCUPM_BUCK_MODE) { + mcdi_mbox_write(APMCU_MCUPM_MBOX_BUCK_MODE, mode); + } +} + +static int mtk_mcupm_is_ready(void) +{ + unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA); + + return (sta == MCUPM_TASK_WAIT) || (sta == MCUPM_TASK_INIT_FINISH); +} + +static int mcdi_init_1(void) +{ + unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA); + + if (sta != MCUPM_TASK_INIT) { + return -1; + } + + mtk_set_mcupm_pll_mode(MCUPM_ARMPLL_OFF); + mtk_set_mcupm_buck_mode(MCUPM_BUCK_OFF_MODE); + + mtk_mcupm_pwr_ctrl_setting( + MCUPM_MCUSYS_CTRL | + MCUPM_BUCK_CTRL | + MCUPM_ARMPLL_CTRL); + + mcdi_mbox_write(APMCU_MCUPM_MBOX_AP_READY, 1); + + return 0; +} + +static int mcdi_init_2(void) +{ + return mtk_mcupm_is_ready() ? 0 : -1; +} + +int mcdi_try_init(void) +{ + if (mcdi_init_status == MCDI_INIT_DONE) { + return 0; + } + + if (mcdi_init_status == MCDI_NOT_INIT) { + mcdi_init_status = MCDI_INIT_1; + } + + if (mcdi_init_status == MCDI_INIT_1 && mcdi_init_1() == 0) { + mcdi_init_status = MCDI_INIT_2; + } + + if (mcdi_init_status == MCDI_INIT_2 && mcdi_init_2() == 0) { + mcdi_init_status = MCDI_INIT_DONE; + } + + return (mcdi_init_status == MCDI_INIT_DONE) ? 0 : mcdi_init_status; +} diff --git a/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.h b/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.h new file mode 100644 index 0000000000000000000000000000000000000000..f3545aabff0dc578482d1f7d2408935bea4fe36f --- /dev/null +++ b/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_MCDI_H +#define MT_MCDI_H + +int mcdi_try_init(void); + +#endif /* MT_MCDI_H */ diff --git a/plat/mediatek/mt8195/drivers/pmic/pmic.c b/plat/mediatek/mt8195/drivers/pmic/pmic.c new file mode 100644 index 0000000000000000000000000000000000000000..cca44139730f6810ac262e9ebba7635e0e383f7c --- /dev/null +++ b/plat/mediatek/mt8195/drivers/pmic/pmic.c @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +void pmic_power_off(void) +{ + pwrap_write(PMIC_PWRHOLD, 0x0); +} diff --git a/plat/mediatek/mt8195/drivers/pmic/pmic.h b/plat/mediatek/mt8195/drivers/pmic/pmic.h new file mode 100644 index 0000000000000000000000000000000000000000..aac22afa39547ca8172fd79480f88221a3884799 --- /dev/null +++ b/plat/mediatek/mt8195/drivers/pmic/pmic.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMIC_H +#define PMIC_H + +#define PMIC_PWRHOLD 0xa08 + +/* external API */ +void pmic_power_off(void); + +#endif /* PMIC_H */ diff --git a/plat/mediatek/mt8195/drivers/pmic/pmic_wrap_init.h b/plat/mediatek/mt8195/drivers/pmic/pmic_wrap_init.h new file mode 100644 index 0000000000000000000000000000000000000000..39e78f5f31551f2a845bf27aca7c7f24df361574 --- /dev/null +++ b/plat/mediatek/mt8195/drivers/pmic/pmic_wrap_init.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMIC_WRAP_INIT_H +#define PMIC_WRAP_INIT_H + +#include + +#include "platform_def.h" + +/* external API */ +int32_t pwrap_read(uint32_t adr, uint32_t *rdata); +int32_t pwrap_write(uint32_t adr, uint32_t wdata); + +static struct mt8195_pmic_wrap_regs *const mtk_pwrap = (void *)PMIC_WRAP_BASE; + +/* PMIC_WRAP registers */ +struct mt8195_pmic_wrap_regs { + uint32_t init_done; + uint32_t reserved[543]; + uint32_t wacs2_cmd; + uint32_t wacs2_wdata; + uint32_t reserved1[3]; + uint32_t wacs2_rdata; + uint32_t reserved2[3]; + uint32_t wacs2_vldclr; + uint32_t wacs2_sta; +}; + +#define GET_WACS_FSM(x) ((x >> 1) & 0x7) + +/* macro for SWINF_FSM */ +#define SWINF_FSM_IDLE (0x00) +#define SWINF_FSM_REQ (0x02) +#define SWINF_FSM_WFDLE (0x04) +#define SWINF_FSM_WFVLDCLR (0x06) +#define SWINF_INIT_DONE (0x01) + +/* timeout setting */ +#define PWRAP_READ_US 1000 +#define PWRAP_WAIT_IDLE_US 1000 + +/* error information flag */ +enum pwrap_errno { + E_PWR_INVALID_ARG = 1, + E_PWR_INVALID_RW = 2, + E_PWR_INVALID_ADDR = 3, + E_PWR_INVALID_WDAT = 4, + E_PWR_INVALID_OP_MANUAL = 5, + E_PWR_NOT_IDLE_STATE = 6, + E_PWR_NOT_INIT_DONE = 7, + E_PWR_NOT_INIT_DONE_READ = 8, + E_PWR_WAIT_IDLE_TIMEOUT = 9, + E_PWR_WAIT_IDLE_TIMEOUT_READ = 10, + E_PWR_INIT_SIDLY_FAIL = 11, + E_PWR_RESET_TIMEOUT = 12, + E_PWR_TIMEOUT = 13, + E_PWR_INIT_RESET_SPI = 20, + E_PWR_INIT_SIDLY = 21, + E_PWR_INIT_REG_CLOCK = 22, + E_PWR_INIT_ENABLE_PMIC = 23, + E_PWR_INIT_DIO = 24, + E_PWR_INIT_CIPHER = 25, + E_PWR_INIT_WRITE_TEST = 26, + E_PWR_INIT_ENABLE_CRC = 27, + E_PWR_INIT_ENABLE_DEWRAP = 28, + E_PWR_INIT_ENABLE_EVENT = 29, + E_PWR_READ_TEST_FAIL = 30, + E_PWR_WRITE_TEST_FAIL = 31, + E_PWR_SWITCH_DIO = 32 +}; + +#endif /* PMIC_WRAP_INIT_H */ diff --git a/plat/mediatek/mt8195/drivers/spmc/mtspmc.c b/plat/mediatek/mt8195/drivers/spmc/mtspmc.c new file mode 100644 index 0000000000000000000000000000000000000000..9b332a00c61ca88f9d547fb8085bb6e48ee2e5c6 --- /dev/null +++ b/plat/mediatek/mt8195/drivers/spmc/mtspmc.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include +#include + + +void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu) +{ + mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu)); +} + +void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu) +{ + mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu)); +} + +void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr) +{ + assert(cluster == 0U); + + mmio_write_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR), bootaddr); +} + +uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu) +{ + assert(cluster == 0U); + + return (uintptr_t)mmio_read_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR)); +} + +void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64) +{ + uint32_t reg; + + assert(cluster == 0U); + + reg = per_cluster(cluster, MCUCFG_INITARCH); + + if (arm64) { + mmio_setbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu)); + } else { + mmio_clrbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu)); + } +} + +/** + * Return subsystem's power state. + * + * @mask: mask to MCUCFG_CPC_SPMC_PWR_STATUS to query the power state + * of one subsystem. + * RETURNS: + * 0 (the subsys was powered off) + * 1 (the subsys was powered on) + */ +bool spm_get_powerstate(uint32_t mask) +{ + return (mmio_read_32(MCUCFG_CPC_SPMC_PWR_STATUS) & mask) != 0U; +} + +bool spm_get_cluster_powerstate(unsigned int cluster) +{ + assert(cluster == 0U); + + return spm_get_powerstate(BIT(14)); +} + +bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu) +{ + uint32_t mask = BIT(cpu); + + assert(cluster == 0U); + + return spm_get_powerstate(mask); +} + +int spmc_init(void) +{ + INFO("SPM: enable CPC mode\n"); + + mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN); + + mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 4, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 5, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 6, SPM_CPU_PWR), PWR_RST_B); + mmio_setbits_32(per_cpu(0, 7, SPM_CPU_PWR), PWR_RST_B); + + mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG); + mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG); + mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG); + + mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE); + mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_CORE_PWR_ON_EN); + + return 0; +} + +/** + * Power on a core with specified cluster and core index + * + * @cluster: the cluster ID of the CPU which to be powered on + * @cpu: the CPU ID of the CPU which to be powered on + */ +void spm_poweron_cpu(unsigned int cluster, unsigned int cpu) +{ + uintptr_t cpu_pwr_con = per_cpu(cluster, cpu, SPM_CPU_PWR); + + /* set to 0 after BIG VPROC bulk on & before B-core power on seq. */ + if (cpu >= 4U) { + mmio_write_32(DREQ20_BIG_VPROC_ISO, 0U); + } + + mmio_setbits_32(cpu_pwr_con, PWR_ON); + + while (!spm_get_cpu_powerstate(cluster, cpu)) { + mmio_clrbits_32(cpu_pwr_con, PWR_ON); + mmio_setbits_32(cpu_pwr_con, PWR_ON); + } +} + +/** + * Power off a core with specified cluster and core index + * + * @cluster: the cluster ID of the CPU which to be powered off + * @cpu: the CPU ID of the CPU which to be powered off + */ +void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu) +{ + /* Set mp0_spmc_pwr_on_cpuX = 0 */ + mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON); +} + +/** + * Power off a cluster with specified index + * + * @cluster: the cluster index which to be powered off + */ +void spm_poweroff_cluster(unsigned int cluster) +{ + /* No need to power on/off cluster on single cluster platform */ + assert(false); +} + +/** + * Power on a cluster with specified index + * + * @cluster: the cluster index which to be powered on + */ +void spm_poweron_cluster(unsigned int cluster) +{ + /* No need to power on/off cluster on single cluster platform */ + assert(false); +} diff --git a/plat/mediatek/mt8195/drivers/spmc/mtspmc.h b/plat/mediatek/mt8195/drivers/spmc/mtspmc.h new file mode 100644 index 0000000000000000000000000000000000000000..34e93d0ef7d0801d52a6a23c034b13f5ce541557 --- /dev/null +++ b/plat/mediatek/mt8195/drivers/spmc/mtspmc.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MTSPMC_H +#define MTSPMC_H + +#include + +int spmc_init(void); + +void spm_poweron_cpu(unsigned int cluster, unsigned int cpu); +void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu); + +void spm_poweroff_cluster(unsigned int cluster); +void spm_poweron_cluster(unsigned int cluster); + +bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu); +bool spm_get_cluster_powerstate(unsigned int cluster); +bool spm_get_powerstate(uint32_t mask); + +void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64); +void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr); +uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu); + +void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu); +void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu); + +#endif /* MTSPMC_H */ diff --git a/plat/mediatek/mt8195/drivers/spmc/mtspmc_private.h b/plat/mediatek/mt8195/drivers/spmc/mtspmc_private.h new file mode 100644 index 0000000000000000000000000000000000000000..bf4092eb2b3af42caa72d8677afab73c79be4b5f --- /dev/null +++ b/plat/mediatek/mt8195/drivers/spmc/mtspmc_private.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MTSPMC_PRIVATE_H +#define MTSPMC_PRIVATE_H + +#include +#include + +unsigned long read_cpuectlr(void); +void write_cpuectlr(unsigned long cpuectlr); + +unsigned long read_cpupwrctlr_el1(void); +void write_cpupwrctlr_el1(unsigned long cpuectlr); + +/* + * per_cpu/cluster helper + */ +struct per_cpu_reg { + unsigned int cluster_addr; + unsigned int cpu_stride; +}; + +#define per_cpu(cluster, cpu, reg) \ + (reg[cluster].cluster_addr + (cpu << reg[cluster].cpu_stride)) + +#define per_cluster(cluster, reg) (reg[cluster].cluster_addr) + +#define SPM_REG(ofs) (uint32_t)(SPM_BASE + (ofs)) +#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs)) +#define INFRACFG_AO_REG(ofs) (uint32_t)(INFRACFG_AO_BASE + (ofs)) + +/* === SPMC related registers */ +#define SPM_POWERON_CONFIG_EN SPM_REG(0x000) +/* bit-fields of SPM_POWERON_CONFIG_EN */ +#define PROJECT_CODE (U(0xb16) << 16) +#define BCLK_CG_EN BIT(0) + +#define SPM_PWR_STATUS SPM_REG(0x16c) +#define SPM_PWR_STATUS_2ND SPM_REG(0x170) +#define SPM_CPU_PWR_STATUS SPM_REG(0x174) + +/* bit-fields of SPM_PWR_STATUS */ +#define MD BIT(0) +#define CONN BIT(1) +#define DDRPHY BIT(2) +#define DISP BIT(3) +#define MFG BIT(4) +#define ISP BIT(5) +#define INFRA BIT(6) +#define VDEC BIT(7) +#define MP0_CPUTOP BIT(8) +#define MP0_CPU0 BIT(9) +#define MP0_CPU1 BIT(10) +#define MP0_CPU2 BIT(11) +#define MP0_CPU3 BIT(12) +#define MCUSYS BIT(14) +#define MP0_CPU4 BIT(15) +#define MP0_CPU5 BIT(16) +#define MP0_CPU6 BIT(17) +#define MP0_CPU7 BIT(18) +#define VEN BIT(21) + +/* === SPMC related registers */ +#define SPM_MCUSYS_PWR_CON MCUCFG_REG(0xd200) +#define SPM_MP0_CPUTOP_PWR_CON MCUCFG_REG(0xd204) +#define SPM_MP0_CPU0_PWR_CON MCUCFG_REG(0xd208) +#define SPM_MP0_CPU1_PWR_CON MCUCFG_REG(0xd20c) +#define SPM_MP0_CPU2_PWR_CON MCUCFG_REG(0xd210) +#define SPM_MP0_CPU3_PWR_CON MCUCFG_REG(0xd214) +#define SPM_MP0_CPU4_PWR_CON MCUCFG_REG(0xd218) +#define SPM_MP0_CPU5_PWR_CON MCUCFG_REG(0xd21c) +#define SPM_MP0_CPU6_PWR_CON MCUCFG_REG(0xd220) +#define SPM_MP0_CPU7_PWR_CON MCUCFG_REG(0xd224) + +/* bit fields of SPM_*_PWR_CON */ +#define PWR_ON_ACK BIT(31) +#define VPROC_EXT_OFF BIT(7) +#define DORMANT_EN BIT(6) +#define RESETPWRON_CONFIG BIT(5) +#define PWR_CLK_DIS BIT(4) +#define PWR_ON BIT(2) +#define PWR_RST_B BIT(0) + +/**** per_cpu registers for SPM_MP0_CPU?_PWR_CON */ +static const struct per_cpu_reg SPM_CPU_PWR[] = { + { .cluster_addr = SPM_MP0_CPU0_PWR_CON, .cpu_stride = 2U } +}; + +/**** per_cluster registers for SPM_MP0_CPUTOP_PWR_CON */ +static const struct per_cpu_reg SPM_CLUSTER_PWR[] = { + { .cluster_addr = SPM_MP0_CPUTOP_PWR_CON, .cpu_stride = 0U } +}; + +/* === MCUCFG related registers */ +/* aa64naa32 */ +#define MCUCFG_MP0_CLUSTER_CFG5 MCUCFG_REG(0xc8e4) +/* reset vectors */ +#define MCUCFG_MP0_CLUSTER_CFG8 MCUCFG_REG(0xc900) +#define MCUCFG_MP0_CLUSTER_CFG10 MCUCFG_REG(0xc908) +#define MCUCFG_MP0_CLUSTER_CFG12 MCUCFG_REG(0xc910) +#define MCUCFG_MP0_CLUSTER_CFG14 MCUCFG_REG(0xc918) +#define MCUCFG_MP0_CLUSTER_CFG16 MCUCFG_REG(0xc920) +#define MCUCFG_MP0_CLUSTER_CFG18 MCUCFG_REG(0xc928) +#define MCUCFG_MP0_CLUSTER_CFG20 MCUCFG_REG(0xc930) +#define MCUCFG_MP0_CLUSTER_CFG22 MCUCFG_REG(0xc938) + +/* MCUSYS DREQ BIG VPROC ISO control */ +#define DREQ20_BIG_VPROC_ISO MCUCFG_REG(0xad8c) + +/**** per_cpu registers for MCUCFG_MP0_CLUSTER_CFG? */ +static const struct per_cpu_reg MCUCFG_BOOTADDR[] = { + { .cluster_addr = MCUCFG_MP0_CLUSTER_CFG8, .cpu_stride = 3U } +}; + +/**** per_cpu registers for MCUCFG_MP0_CLUSTER_CFG5 */ +static const struct per_cpu_reg MCUCFG_INITARCH[] = { + { .cluster_addr = MCUCFG_MP0_CLUSTER_CFG5, .cpu_stride = 0U } +}; + +#define MCUCFG_INITARCH_CPU_BIT(cpu) BIT(16U + cpu) +/* === CPC control */ +#define MCUCFG_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814) +#define MCUCFG_CPC_SPMC_PWR_STATUS MCUCFG_REG(0xa840) + +/* bit fields of CPC_FLOW_CTRL_CFG */ +#define CPC_CTRL_ENABLE BIT(16) +#define SSPM_CORE_PWR_ON_EN BIT(7) /* for cpu-hotplug */ +#define SSPM_ALL_PWR_CTRL_EN BIT(13) /* for cpu-hotplug */ +#define GIC_WAKEUP_IGNORE(cpu) BIT(21 + cpu) + +/* bit fields of CPC_SPMC_PWR_STATUS */ +#define CORE_SPMC_PWR_ON_ACK GENMASK(11, 0) + +/* === APB Module infracfg_ao */ +#define INFRA_TOPAXI_PROTECTEN INFRACFG_AO_REG(0x0220) +#define INFRA_TOPAXI_PROTECTEN_STA0 INFRACFG_AO_REG(0x0224) +#define INFRA_TOPAXI_PROTECTEN_STA1 INFRACFG_AO_REG(0x0228) +#define INFRA_TOPAXI_PROTECTEN_SET INFRACFG_AO_REG(0x02a0) +#define INFRA_TOPAXI_PROTECTEN_CLR INFRACFG_AO_REG(0x02a4) +#define INFRA_TOPAXI_PROTECTEN_1 INFRACFG_AO_REG(0x0250) +#define INFRA_TOPAXI_PROTECTEN_STA0_1 INFRACFG_AO_REG(0x0254) +#define INFRA_TOPAXI_PROTECTEN_STA1_1 INFRACFG_AO_REG(0x0258) +#define INFRA_TOPAXI_PROTECTEN_1_SET INFRACFG_AO_REG(0x02a8) +#define INFRA_TOPAXI_PROTECTEN_1_CLR INFRACFG_AO_REG(0x02ac) + +/* bit fields of INFRA_TOPAXI_PROTECTEN */ +#define MP0_SPMC_PROT_STEP1_0_MASK BIT(12) +#define MP0_SPMC_PROT_STEP1_1_MASK (BIT(26) | BIT(12)) + +/* === SPARK */ +#define VOLTAGE_04 U(0x40) +#define VOLTAGE_05 U(0x60) + +#define PTP3_CPU0_SPMC_SW_CFG MCUCFG_REG(0x200) +#define CPU0_ILDO_CONTROL5 MCUCFG_REG(0x334) +#define CPU0_ILDO_CONTROL8 MCUCFG_REG(0x340) + +/* bit fields of CPU0_ILDO_CONTROL5 */ +#define ILDO_RET_VOSEL GENMASK(7, 0) + +/* bit fields of PTP3_CPU_SPMC_SW_CFG */ +#define SW_SPARK_EN BIT(0) + +/* bit fields of CPU0_ILDO_CONTROL8 */ +#define ILDO_BYPASS_B BIT(0) + +static const struct per_cpu_reg MCUCFG_SPARK[] = { + { .cluster_addr = PTP3_CPU0_SPMC_SW_CFG, .cpu_stride = 11U } +}; + +static const struct per_cpu_reg ILDO_CONTROL5[] = { + { .cluster_addr = CPU0_ILDO_CONTROL5, .cpu_stride = 11U } +}; + +static const struct per_cpu_reg ILDO_CONTROL8[] = { + { .cluster_addr = CPU0_ILDO_CONTROL8, .cpu_stride = 11U } +}; + +#endif /* MTSPMC_PRIVATE_H */ diff --git a/plat/mediatek/mt8195/include/mcucfg.h b/plat/mediatek/mt8195/include/mcucfg.h new file mode 100644 index 0000000000000000000000000000000000000000..046cf7314f2f7645c2998a072daaa9c874691cdb --- /dev/null +++ b/plat/mediatek/mt8195/include/mcucfg.h @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MCUCFG_H +#define MCUCFG_H + +#ifndef __ASSEMBLER__ +#include +#endif /* __ASSEMBLER__ */ + +#include + +#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs)) + +#define MP2_MISC_CONFIG_BOOT_ADDR_L(cpu) (MCUCFG_REG(0x2290) + ((cpu) * 8)) +#define MP2_MISC_CONFIG_BOOT_ADDR_H(cpu) (MCUCFG_REG(0x2294) + ((cpu) * 8)) + +#define MP2_CPUCFG MCUCFG_REG(0x2208) + +#define MP2_CPU0_STANDBYWFE BIT(4) +#define MP2_CPU1_STANDBYWFE BIT(5) + +#define MP0_CPUTOP_SPMC_CTL MCUCFG_REG(0x788) +#define MP1_CPUTOP_SPMC_CTL MCUCFG_REG(0x78C) +#define MP1_CPUTOP_SPMC_SRAM_CTL MCUCFG_REG(0x790) + +#define sw_spark_en BIT(0) +#define sw_no_wait_for_q_channel BIT(1) +#define sw_fsm_override BIT(2) +#define sw_logic_pre1_pdb BIT(3) +#define sw_logic_pre2_pdb BIT(4) +#define sw_logic_pdb BIT(5) +#define sw_iso BIT(6) +#define sw_sram_sleepb (U(0x3F) << 7) +#define sw_sram_isointb BIT(13) +#define sw_clk_dis BIT(14) +#define sw_ckiso BIT(15) +#define sw_pd (U(0x3F) << 16) +#define sw_hot_plug_reset BIT(22) +#define sw_pwr_on_override_en BIT(23) +#define sw_pwr_on BIT(24) +#define sw_coq_dis BIT(25) +#define logic_pdbo_all_off_ack BIT(26) +#define logic_pdbo_all_on_ack BIT(27) +#define logic_pre2_pdbo_all_on_ack BIT(28) +#define logic_pre1_pdbo_all_on_ack BIT(29) + + +#define CPUSYSx_CPUx_SPMC_CTL(cluster, cpu) \ + (MCUCFG_REG(0x1c30) + cluster * 0x2000 + cpu * 4) + +#define CPUSYS0_CPU0_SPMC_CTL MCUCFG_REG(0x1c30) +#define CPUSYS0_CPU1_SPMC_CTL MCUCFG_REG(0x1c34) +#define CPUSYS0_CPU2_SPMC_CTL MCUCFG_REG(0x1c38) +#define CPUSYS0_CPU3_SPMC_CTL MCUCFG_REG(0x1c3C) + +#define CPUSYS1_CPU0_SPMC_CTL MCUCFG_REG(0x3c30) +#define CPUSYS1_CPU1_SPMC_CTL MCUCFG_REG(0x3c34) +#define CPUSYS1_CPU2_SPMC_CTL MCUCFG_REG(0x3c38) +#define CPUSYS1_CPU3_SPMC_CTL MCUCFG_REG(0x3c3C) + +#define cpu_sw_spark_en BIT(0) +#define cpu_sw_no_wait_for_q_channel BIT(1) +#define cpu_sw_fsm_override BIT(2) +#define cpu_sw_logic_pre1_pdb BIT(3) +#define cpu_sw_logic_pre2_pdb BIT(4) +#define cpu_sw_logic_pdb BIT(5) +#define cpu_sw_iso BIT(6) +#define cpu_sw_sram_sleepb BIT(7) +#define cpu_sw_sram_isointb BIT(8) +#define cpu_sw_clk_dis BIT(9) +#define cpu_sw_ckiso BIT(10) +#define cpu_sw_pd (U(0x1F) << 11) +#define cpu_sw_hot_plug_reset BIT(16) +#define cpu_sw_powr_on_override_en BIT(17) +#define cpu_sw_pwr_on BIT(18) +#define cpu_spark2ldo_allswoff BIT(19) +#define cpu_pdbo_all_on_ack BIT(20) +#define cpu_pre2_pdbo_allon_ack BIT(21) +#define cpu_pre1_pdbo_allon_ack BIT(22) + +/* CPC related registers */ +#define CPC_MCUSYS_CPC_OFF_THRES MCUCFG_REG(0xa714) +#define CPC_MCUSYS_PWR_CTRL MCUCFG_REG(0xa804) +#define CPC_MCUSYS_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814) +#define CPC_MCUSYS_LAST_CORE_REQ MCUCFG_REG(0xa818) +#define CPC_MCUSYS_MP_LAST_CORE_RESP MCUCFG_REG(0xa81c) +#define CPC_MCUSYS_LAST_CORE_RESP MCUCFG_REG(0xa824) +#define CPC_MCUSYS_PWR_ON_MASK MCUCFG_REG(0xa828) +#define CPC_MCUSYS_CPU_ON_SW_HINT_SET MCUCFG_REG(0xa8a8) +#define CPC_MCUSYS_CPU_ON_SW_HINT_CLR MCUCFG_REG(0xa8ac) +#define CPC_MCUSYS_CPC_DBG_SETTING MCUCFG_REG(0xab00) +#define CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE MCUCFG_REG(0xab04) +#define CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE MCUCFG_REG(0xab08) +#define CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE MCUCFG_REG(0xab0c) +#define CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE MCUCFG_REG(0xab10) +#define CPC_MCUSYS_TRACE_SEL MCUCFG_REG(0xab14) +#define CPC_MCUSYS_TRACE_DATA MCUCFG_REG(0xab20) +#define CPC_MCUSYS_CLUSTER_COUNTER MCUCFG_REG(0xab70) +#define CPC_MCUSYS_CLUSTER_COUNTER_CLR MCUCFG_REG(0xab74) + +#define SPARK2LDO MCUCFG_REG(0x2700) +/* APB Module mcucfg */ +#define MP0_CA7_CACHE_CONFIG MCUCFG_REG(0x000) +#define MP0_AXI_CONFIG MCUCFG_REG(0x02C) +#define MP0_MISC_CONFIG0 MCUCFG_REG(0x030) +#define MP0_MISC_CONFIG1 MCUCFG_REG(0x034) +#define MP0_MISC_CONFIG2 MCUCFG_REG(0x038) +#define MP0_MISC_CONFIG_BOOT_ADDR(cpu) (MP0_MISC_CONFIG2 + ((cpu) * 8)) +#define MP0_MISC_CONFIG3 MCUCFG_REG(0x03C) +#define MP0_MISC_CONFIG9 MCUCFG_REG(0x054) +#define MP0_CA7_MISC_CONFIG MCUCFG_REG(0x064) + +#define MP0_RW_RSVD0 MCUCFG_REG(0x06C) + + +#define MP1_CA7_CACHE_CONFIG MCUCFG_REG(0x200) +#define MP1_AXI_CONFIG MCUCFG_REG(0x22C) +#define MP1_MISC_CONFIG0 MCUCFG_REG(0x230) +#define MP1_MISC_CONFIG1 MCUCFG_REG(0x234) +#define MP1_MISC_CONFIG2 MCUCFG_REG(0x238) +#define MP1_MISC_CONFIG_BOOT_ADDR(cpu) (MP1_MISC_CONFIG2 + ((cpu) * 8)) +#define MP1_MISC_CONFIG3 MCUCFG_REG(0x23C) +#define MP1_MISC_CONFIG9 MCUCFG_REG(0x254) +#define MP1_CA7_MISC_CONFIG MCUCFG_REG(0x264) + +#define CCI_ADB400_DCM_CONFIG MCUCFG_REG(0x740) +#define SYNC_DCM_CONFIG MCUCFG_REG(0x744) + +#define MP0_CLUSTER_CFG0 MCUCFG_REG(0xC8D0) + +#define MP0_SPMC MCUCFG_REG(0x788) +#define MP1_SPMC MCUCFG_REG(0x78C) +#define MP2_AXI_CONFIG MCUCFG_REG(0x220C) +#define MP2_AXI_CONFIG_ACINACTM BIT(0) +#define MP2_AXI_CONFIG_AINACTS BIT(4) + +#define MPx_AXI_CONFIG_ACINACTM BIT(4) +#define MPx_AXI_CONFIG_AINACTS BIT(5) + +#define MPx_CA7_MISC_CONFIG_standbywfil2 BIT(28) + +#define MP0_CPU0_STANDBYWFE BIT(20) +#define MP0_CPU1_STANDBYWFE BIT(21) +#define MP0_CPU2_STANDBYWFE BIT(22) +#define MP0_CPU3_STANDBYWFE BIT(23) + +#define MP1_CPU0_STANDBYWFE BIT(20) +#define MP1_CPU1_STANDBYWFE BIT(21) +#define MP1_CPU2_STANDBYWFE BIT(22) +#define MP1_CPU3_STANDBYWFE BIT(23) + +#define CPUSYS0_SPARKVRETCNTRL MCUCFG_REG(0x1c00) +#define CPUSYS0_SPARKEN MCUCFG_REG(0x1c04) +#define CPUSYS0_AMUXSEL MCUCFG_REG(0x1c08) +#define CPUSYS1_SPARKVRETCNTRL MCUCFG_REG(0x3c00) +#define CPUSYS1_SPARKEN MCUCFG_REG(0x3c04) +#define CPUSYS1_AMUXSEL MCUCFG_REG(0x3c08) + +#define MP2_PWR_RST_CTL MCUCFG_REG(0x2008) +#define MP2_PTP3_CPUTOP_SPMC0 MCUCFG_REG(0x22A0) +#define MP2_PTP3_CPUTOP_SPMC1 MCUCFG_REG(0x22A4) + +#define MP2_COQ MCUCFG_REG(0x22BC) +#define MP2_COQ_SW_DIS BIT(0) + +#define MP2_CA15M_MON_SEL MCUCFG_REG(0x2400) +#define MP2_CA15M_MON_L MCUCFG_REG(0x2404) + +#define CPUSYS2_CPU0_SPMC_CTL MCUCFG_REG(0x2430) +#define CPUSYS2_CPU1_SPMC_CTL MCUCFG_REG(0x2438) +#define CPUSYS2_CPU0_SPMC_STA MCUCFG_REG(0x2434) +#define CPUSYS2_CPU1_SPMC_STA MCUCFG_REG(0x243C) + +#define MP0_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x068) +#define MP1_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x268) +#define BIG_DBG_PWR_CTRL MCUCFG_REG(0x75C) + +#define MP2_SW_RST_B BIT(0) +#define MP2_TOPAON_APB_MASK BIT(1) + +#define B_SW_HOT_PLUG_RESET BIT(30) + +#define B_SW_PD_OFFSET 18U +#define B_SW_PD (U(0x3f) << B_SW_PD_OFFSET) + +#define B_SW_SRAM_SLEEPB_OFFSET 12U +#define B_SW_SRAM_SLEEPB (U(0x3f) << B_SW_SRAM_SLEEPB_OFFSET) + +#define B_SW_SRAM_ISOINTB BIT(9) +#define B_SW_ISO BIT(8) +#define B_SW_LOGIC_PDB BIT(7) +#define B_SW_LOGIC_PRE2_PDB BIT(6) +#define B_SW_LOGIC_PRE1_PDB BIT(5) +#define B_SW_FSM_OVERRIDE BIT(4) +#define B_SW_PWR_ON BIT(3) +#define B_SW_PWR_ON_OVERRIDE_EN BIT(2) + +#define B_FSM_STATE_OUT_OFFSET (6U) +#define B_FSM_STATE_OUT_MASK (U(0x1f) << B_FSM_STATE_OUT_OFFSET) +#define B_SW_LOGIC_PDBO_ALL_OFF_ACK BIT(5) +#define B_SW_LOGIC_PDBO_ALL_ON_ACK BIT(4) +#define B_SW_LOGIC_PRE2_PDBO_ALL_ON_ACK BIT(3) +#define B_SW_LOGIC_PRE1_PDBO_ALL_ON_ACK BIT(2) + +#define B_FSM_OFF (0U << B_FSM_STATE_OUT_OFFSET) +#define B_FSM_ON (1U << B_FSM_STATE_OUT_OFFSET) +#define B_FSM_RET (2U << B_FSM_STATE_OUT_OFFSET) + +#ifndef __ASSEMBLER__ +/* cpu boot mode */ +enum { + MP0_CPUCFG_64BIT_SHIFT = 12U, + MP1_CPUCFG_64BIT_SHIFT = 28U, + MP0_CPUCFG_64BIT = U(0xf) << MP0_CPUCFG_64BIT_SHIFT, + MP1_CPUCFG_64BIT = U(0xf) << MP1_CPUCFG_64BIT_SHIFT +}; + +enum { + MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT = 0U, + MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT = 4U, + MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT = 8U, + MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT = 12U, + MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT = 16U, + + MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK = + U(0xf) << MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK = + U(0xf) << MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK = + U(0xf) << MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK = + U(0xf) << MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT, + MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK = + U(0xf) << MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT +}; + +enum { + MP1_AINACTS_SHIFT = 4U, + MP1_AINACTS = 1U << MP1_AINACTS_SHIFT +}; + +enum { + MP1_SW_CG_GEN_SHIFT = 12U, + MP1_SW_CG_GEN = 1U << MP1_SW_CG_GEN_SHIFT +}; + +enum { + MP1_L2RSTDISABLE_SHIFT = 14U, + MP1_L2RSTDISABLE = 1U << MP1_L2RSTDISABLE_SHIFT +}; +#endif /* __ASSEMBLER__ */ + +#endif /* MCUCFG_H */ diff --git a/plat/mediatek/mt8195/include/plat_helpers.h b/plat/mediatek/mt8195/include/plat_helpers.h new file mode 100644 index 0000000000000000000000000000000000000000..ebc9fa01fad2727ac2072d0b9f5b8d1d4bb64ab6 --- /dev/null +++ b/plat/mediatek/mt8195/include/plat_helpers.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLAT_HELPERS_H__ +#define __PLAT_HELPERS_H__ + +unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr); + +#endif /* __PLAT_HELPERS_H__ */ diff --git a/plat/mediatek/mt8195/include/plat_macros.S b/plat/mediatek/mt8195/include/plat_macros.S new file mode 100644 index 0000000000000000000000000000000000000000..39727ea52201e963315401953c096888086b0b6d --- /dev/null +++ b/plat/mediatek/mt8195/include/plat_macros.S @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include + +.section .rodata.gic_reg_name, "aS" +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \ + " Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + +.section .rodata.cci_reg_name, "aS" +cci_iface_regs: + .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , "" + + /* --------------------------------------------- + * The below macro prints out relevant GIC + * registers whenever an unhandled exception + * is taken in BL31. + * Clobbers: x0 - x10, x26, x27, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + /* TODO: leave implementation to GIC owner */ + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/plat/mediatek/mt8195/include/plat_mtk_lpm.h b/plat/mediatek/mt8195/include/plat_mtk_lpm.h new file mode 100644 index 0000000000000000000000000000000000000000..8ba8b93a8c92ac1a5e319c81bbd4347264aedfe7 --- /dev/null +++ b/plat/mediatek/mt8195/include/plat_mtk_lpm.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MTK_LPM_H +#define PLAT_MTK_LPM_H + +#include +#include + +#define MT_IRQ_REMAIN_MAX U(8) +#define MT_IRQ_REMAIN_CAT_LOG BIT(31) + +struct mt_irqremain { + unsigned int count; + unsigned int irqs[MT_IRQ_REMAIN_MAX]; + unsigned int wakeupsrc_cat[MT_IRQ_REMAIN_MAX]; + unsigned int wakeupsrc[MT_IRQ_REMAIN_MAX]; +}; + +#define PLAT_RC_STATUS_READY BIT(0) +#define PLAT_RC_STATUS_FEATURE_EN BIT(1) +#define PLAT_RC_STATUS_UART_NONSLEEP BIT(31) + +struct mt_lpm_tz { + int (*pwr_prompt)(unsigned int cpu, const psci_power_state_t *state); + int (*pwr_reflect)(unsigned int cpu, const psci_power_state_t *state); + + int (*pwr_cpu_on)(unsigned int cpu, const psci_power_state_t *state); + int (*pwr_cpu_dwn)(unsigned int cpu, const psci_power_state_t *state); + + int (*pwr_cluster_on)(unsigned int cpu, + const psci_power_state_t *state); + int (*pwr_cluster_dwn)(unsigned int cpu, + const psci_power_state_t *state); + + int (*pwr_mcusys_on)(unsigned int cpu, const psci_power_state_t *state); + int (*pwr_mcusys_on_finished)(unsigned int cpu, + const psci_power_state_t *state); + int (*pwr_mcusys_dwn)(unsigned int cpu, + const psci_power_state_t *state); +}; + +const struct mt_lpm_tz *mt_plat_cpu_pm_init(void); + +#endif /* PLAT_MTK_LPM_H */ diff --git a/plat/mediatek/mt8195/include/plat_pm.h b/plat/mediatek/mt8195/include/plat_pm.h new file mode 100644 index 0000000000000000000000000000000000000000..a2881cef647152135828c533e8e5390ac3cde6c1 --- /dev/null +++ b/plat/mediatek/mt8195/include/plat_pm.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_PM_H +#define PLAT_PM_H + +#include + +#define MT_PLAT_PWR_STATE_CPU U(1) +#define MT_PLAT_PWR_STATE_CLUSTER U(2) +#define MT_PLAT_PWR_STATE_MCUSYS U(3) +#define MT_PLAT_PWR_STATE_SUSPEND2IDLE U(8) +#define MT_PLAT_PWR_STATE_SYSTEM_SUSPEND U(9) + +#define MTK_LOCAL_STATE_RUN U(0) +#define MTK_LOCAL_STATE_RET U(1) +#define MTK_LOCAL_STATE_OFF U(2) + +#define MTK_AFFLVL_CPU U(0) +#define MTK_AFFLVL_CLUSTER U(1) +#define MTK_AFFLVL_MCUSYS U(2) +#define MTK_AFFLVL_SYSTEM U(3) + +#define IS_CLUSTER_OFF_STATE(s) \ + is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_CLUSTER]) +#define IS_MCUSYS_OFF_STATE(s) \ + is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_MCUSYS]) +#define IS_SYSTEM_SUSPEND_STATE(s) \ + is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_SYSTEM]) + +#define IS_PLAT_SUSPEND_ID(stateid)\ + ((stateid == MT_PLAT_PWR_STATE_SUSPEND2IDLE) \ + || (stateid == MT_PLAT_PWR_STATE_SYSTEM_SUSPEND)) + +#endif /* PLAT_PM_H */ diff --git a/plat/mediatek/mt8195/include/plat_private.h b/plat/mediatek/mt8195/include/plat_private.h new file mode 100644 index 0000000000000000000000000000000000000000..7ef2b8509739f6b796eb3413dde28ab6d7854a57 --- /dev/null +++ b/plat/mediatek/mt8195/include/plat_private.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_PRIVATE_H +#define PLAT_PRIVATE_H + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ +void plat_configure_mmu_el3(uintptr_t total_base, + uintptr_t total_size, + uintptr_t ro_start, + uintptr_t ro_limit); + +#endif /* PLAT_PRIVATE_H */ diff --git a/plat/mediatek/mt8195/include/plat_sip_calls.h b/plat/mediatek/mt8195/include/plat_sip_calls.h new file mode 100644 index 0000000000000000000000000000000000000000..0e423225ce4e7a928813bb4fafd6b7d94c95770e --- /dev/null +++ b/plat/mediatek/mt8195/include/plat_sip_calls.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_SIP_CALLS_H +#define PLAT_SIP_CALLS_H + +/******************************************************************************* + * Plat SiP function constants + ******************************************************************************/ +#define MTK_PLAT_SIP_NUM_CALLS 0 + +#endif /* PLAT_SIP_CALLS_H */ diff --git a/plat/mediatek/mt8195/include/platform_def.h b/plat/mediatek/mt8195/include/platform_def.h new file mode 100644 index 0000000000000000000000000000000000000000..f6eb742f34e82efbfe1cac6bbed34b6fe3e42191 --- /dev/null +++ b/plat/mediatek/mt8195/include/platform_def.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#define PLAT_PRIMARY_CPU 0x0 + +#define MT_GIC_BASE (0x0C000000) +#define MCUCFG_BASE (0x0C530000) +#define IO_PHYS (0x10000000) + +/* Aggregate of all devices for MMU mapping */ +#define MTK_DEV_RNG0_BASE IO_PHYS +#define MTK_DEV_RNG0_SIZE 0x400000 +#define MTK_DEV_RNG1_BASE (IO_PHYS + 0x1000000) +#define MTK_DEV_RNG1_SIZE 0xa110000 +#define MTK_DEV_RNG2_BASE MT_GIC_BASE +#define MTK_DEV_RNG2_SIZE 0x600000 +#define MTK_MCDI_SRAM_BASE 0x11B000 +#define MTK_MCDI_SRAM_MAP_SIZE 0x1000 + +#define SPM_BASE (IO_PHYS + 0x00006000) + +/******************************************************************************* + * GPIO related constants + ******************************************************************************/ +#define GPIO_BASE (IO_PHYS + 0x00005000) +#define IOCFG_BM_BASE (IO_PHYS + 0x01D10000) +#define IOCFG_BL_BASE (IO_PHYS + 0x01D30000) +#define IOCFG_BR_BASE (IO_PHYS + 0x01D40000) +#define IOCFG_LM_BASE (IO_PHYS + 0x01E20000) +#define IOCFG_RB_BASE (IO_PHYS + 0x01EB0000) +#define IOCFG_TL_BASE (IO_PHYS + 0x01F40000) + +/******************************************************************************* + * UART related constants + ******************************************************************************/ +#define UART0_BASE (IO_PHYS + 0x01001100) +#define UART1_BASE (IO_PHYS + 0x01001200) + +#define UART_BAUDRATE 115200 + +/******************************************************************************* + * PMIC related constants + ******************************************************************************/ +#define PMIC_WRAP_BASE (IO_PHYS + 0x00024000) + +/******************************************************************************* + * System counter frequency related constants + ******************************************************************************/ +#define SYS_COUNTER_FREQ_IN_TICKS 13000000 +#define SYS_COUNTER_FREQ_IN_MHZ 13 + +/******************************************************************************* + * GIC-600 & interrupt handling related constants + ******************************************************************************/ +/* Base MTK_platform compatible GIC memory map */ +#define BASE_GICD_BASE MT_GIC_BASE +#define MT_GIC_RDIST_BASE (MT_GIC_BASE + 0x40000) + +#define SYS_CIRQ_BASE (IO_PHYS + 0x204000) +#define CIRQ_REG_NUM 23 +#define CIRQ_IRQ_NUM 730 +#define CIRQ_SPI_START 96 +#define MD_WDT_IRQ_BIT_ID 141 +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ +#define PLATFORM_STACK_SIZE 0x800 + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define PLAT_MAX_PWR_LVL U(3) +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(9) + +#define PLATFORM_SYSTEM_COUNT U(1) +#define PLATFORM_MCUSYS_COUNT U(1) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT U(8) +#define PLATFORM_CLUSTER1_CORE_COUNT U(0) + +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT) +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(8) + +#define SOC_CHIP_ID U(0x8195) + +/******************************************************************************* + * Platform memory map related constants + ******************************************************************************/ +#define TZRAM_BASE 0x54600000 +#define TZRAM_SIZE 0x00030000 + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL3-1 at the top of the Trusted SRAM (just below the shared memory, if + * present). BL31_BASE is calculated using the current BL3-1 debug size plus a + * little space for growth. + */ +#define BL31_BASE (TZRAM_BASE + 0x1000) +#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE) + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define MAX_XLAT_TABLES 16 +#define MAX_MMAP_REGIONS 16 + +/******************************************************************************* + * Declarations and constants to access the mailboxes safely. Each mailbox is + * aligned on the biggest cache line size in the platform. This is known only + * to the platform as it might have a combination of integrated and external + * caches. Such alignment ensures that two maiboxes do not sit on the same cache + * line at any cache level. They could belong to different cpus/clusters & + * get written while being protected by different locks causing corruption of + * a valid mailbox address. + ******************************************************************************/ +#define CACHE_WRITEBACK_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) +#endif /* PLATFORM_DEF_H */ diff --git a/plat/mediatek/mt8195/include/rtc.h b/plat/mediatek/mt8195/include/rtc.h new file mode 100644 index 0000000000000000000000000000000000000000..a9c7bc83f4fa537135f40b1db9045e8b34ffa292 --- /dev/null +++ b/plat/mediatek/mt8195/include/rtc.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RTC_H +#define RTC_H + +#include + +#endif /* RTC_H */ diff --git a/plat/mediatek/mt8195/plat_pm.c b/plat/mediatek/mt8195/plat_pm.c new file mode 100644 index 0000000000000000000000000000000000000000..522d4437a07a3ebef8c6989bfd40767f4535b803 --- /dev/null +++ b/plat/mediatek/mt8195/plat_pm.c @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* common headers */ +#include + +#include +#include +#include +#include + +/* platform specific headers */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Cluster state request: + * [0] : The CPU requires cluster power down + * [1] : The CPU requires cluster power on + */ +#define coordinate_cluster(onoff) write_clusterpwrdn_el1(onoff) +#define coordinate_cluster_pwron() coordinate_cluster(1) +#define coordinate_cluster_pwroff() coordinate_cluster(0) + +/* platform secure entry point */ +static uintptr_t secure_entrypoint; +/* per-CPU power state */ +static unsigned int plat_power_state[PLATFORM_CORE_COUNT]; + +/* platform CPU power domain - ops */ +static const struct mt_lpm_tz *plat_mt_pm; + +#define plat_mt_pm_invoke(_name, _cpu, _state) ({ \ + int ret = -1; \ + if (plat_mt_pm != NULL && plat_mt_pm->_name != NULL) { \ + ret = plat_mt_pm->_name(_cpu, _state); \ + } \ + ret; }) + +#define plat_mt_pm_invoke_no_check(_name, _cpu, _state) ({ \ + if (plat_mt_pm != NULL && plat_mt_pm->_name != NULL) { \ + (void) plat_mt_pm->_name(_cpu, _state); \ + } \ + }) + +/* + * Common MTK_platform operations to power on/off a + * CPU in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request. + */ + +static void plat_cpu_pwrdwn_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + + plat_mt_pm_invoke_no_check(pwr_cpu_dwn, cpu, state); + + if ((psci_get_pstate_pwrlvl(req_pstate) >= MTK_AFFLVL_CLUSTER) || + (req_pstate == 0U)) { /* hotplug off */ + coordinate_cluster_pwroff(); + } + + /* Prevent interrupts from spuriously waking up this CPU */ + mt_gic_rdistif_save(); + gicv3_cpuif_disable(cpu); + gicv3_rdistif_off(cpu); +} + +static void plat_cpu_pwron_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + + plat_mt_pm_invoke_no_check(pwr_cpu_on, cpu, state); + + coordinate_cluster_pwron(); + + /* Enable the GIC CPU interface */ + gicv3_rdistif_on(cpu); + gicv3_cpuif_enable(cpu); + mt_gic_rdistif_init(); + + /* + * If mcusys does power down before then restore + * all CPUs' GIC Redistributors + */ + if (IS_MCUSYS_OFF_STATE(state)) { + mt_gic_rdistif_restore_all(); + } else { + mt_gic_rdistif_restore(); + } +} + +/* + * Common MTK_platform operations to power on/off a + * cluster in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request. + */ + +static void plat_cluster_pwrdwn_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + + if (plat_mt_pm_invoke(pwr_cluster_dwn, cpu, state) != 0) { + coordinate_cluster_pwron(); + + /* TODO: return on fail. + * Add a 'return' here before adding any code following + * the if-block. + */ + } +} + +static void plat_cluster_pwron_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + + if (plat_mt_pm_invoke(pwr_cluster_on, cpu, state) != 0) { + /* TODO: return on fail. + * Add a 'return' here before adding any code following + * the if-block. + */ + } +} + +/* + * Common MTK_platform operations to power on/off a + * mcusys in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request. + */ + +static void plat_mcusys_pwrdwn_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + + if (plat_mt_pm_invoke(pwr_mcusys_dwn, cpu, state) != 0) { + return; /* return on fail */ + } + + mt_gic_distif_save(); + gic_sgi_save_all(); +} + +static void plat_mcusys_pwron_common(unsigned int cpu, + const psci_power_state_t *state, unsigned int req_pstate) +{ + assert(cpu == plat_my_core_pos()); + + if (plat_mt_pm_invoke(pwr_mcusys_on, cpu, state) != 0) { + return; /* return on fail */ + } + + mt_gic_init(); + mt_gic_distif_restore(); + gic_sgi_restore_all(); + + plat_mt_pm_invoke_no_check(pwr_mcusys_on_finished, cpu, state); +} + +/* + * plat_psci_ops implementation + */ + +static void plat_cpu_standby(plat_local_state_t cpu_state) +{ + uint64_t scr; + + scr = read_scr_el3(); + write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); + + isb(); + dsb(); + wfi(); + + write_scr_el3(scr); +} + +static int plat_power_domain_on(u_register_t mpidr) +{ + unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr); + unsigned int cluster = 0U; + + if (cpu >= PLATFORM_CORE_COUNT) { + return PSCI_E_INVALID_PARAMS; + } + + if (!spm_get_cluster_powerstate(cluster)) { + spm_poweron_cluster(cluster); + } + + /* init CPU reset arch as AARCH64 */ + mcucfg_init_archstate(cluster, cpu, true); + mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint); + spm_poweron_cpu(cluster, cpu); + + return PSCI_E_SUCCESS; +} + +static void plat_power_domain_on_finish(const psci_power_state_t *state) +{ + unsigned long mpidr = read_mpidr_el1(); + unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr); + + assert(cpu < PLATFORM_CORE_COUNT); + + /* Allow IRQs to wakeup this core in IDLE flow */ + mcucfg_enable_gic_wakeup(0U, cpu); + + if (IS_CLUSTER_OFF_STATE(state)) { + plat_cluster_pwron_common(cpu, state, 0U); + } + + plat_cpu_pwron_common(cpu, state, 0U); +} + +static void plat_power_domain_off(const psci_power_state_t *state) +{ + unsigned long mpidr = read_mpidr_el1(); + unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr); + + assert(cpu < PLATFORM_CORE_COUNT); + + plat_cpu_pwrdwn_common(cpu, state, 0U); + spm_poweroff_cpu(0U, cpu); + + /* prevent unintended IRQs from waking up the hot-unplugged core */ + mcucfg_disable_gic_wakeup(0U, cpu); + + if (IS_CLUSTER_OFF_STATE(state)) { + plat_cluster_pwrdwn_common(cpu, state, 0U); + } +} + +static void plat_power_domain_suspend(const psci_power_state_t *state) +{ + unsigned int cpu = plat_my_core_pos(); + + assert(cpu < PLATFORM_CORE_COUNT); + + plat_mt_pm_invoke_no_check(pwr_prompt, cpu, state); + + /* Perform the common CPU specific operations */ + plat_cpu_pwrdwn_common(cpu, state, plat_power_state[cpu]); + + if (IS_CLUSTER_OFF_STATE(state)) { + /* Perform the common cluster specific operations */ + plat_cluster_pwrdwn_common(cpu, state, plat_power_state[cpu]); + } + + if (IS_MCUSYS_OFF_STATE(state)) { + /* Perform the common mcusys specific operations */ + plat_mcusys_pwrdwn_common(cpu, state, plat_power_state[cpu]); + } +} + +static void plat_power_domain_suspend_finish(const psci_power_state_t *state) +{ + unsigned int cpu = plat_my_core_pos(); + + assert(cpu < PLATFORM_CORE_COUNT); + + if (IS_MCUSYS_OFF_STATE(state)) { + /* Perform the common mcusys specific operations */ + plat_mcusys_pwron_common(cpu, state, plat_power_state[cpu]); + } + + if (IS_CLUSTER_OFF_STATE(state)) { + /* Perform the common cluster specific operations */ + plat_cluster_pwron_common(cpu, state, plat_power_state[cpu]); + } + + /* Perform the common CPU specific operations */ + plat_cpu_pwron_common(cpu, state, plat_power_state[cpu]); + + plat_mt_pm_invoke_no_check(pwr_reflect, cpu, state); +} + +static int plat_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int pstate = psci_get_pstate_type(power_state); + unsigned int aff_lvl = psci_get_pstate_pwrlvl(power_state); + unsigned int cpu = plat_my_core_pos(); + + if (aff_lvl > PLAT_MAX_PWR_LVL) { + return PSCI_E_INVALID_PARAMS; + } + + if (pstate == PSTATE_TYPE_STANDBY) { + req_state->pwr_domain_state[0] = PLAT_MAX_RET_STATE; + } else { + unsigned int i; + unsigned int pstate_id = psci_get_pstate_id(power_state); + plat_local_state_t s = MTK_LOCAL_STATE_OFF; + + /* Use pstate_id to be power domain state */ + if (pstate_id > s) { + s = (plat_local_state_t)pstate_id; + } + + for (i = 0U; i <= aff_lvl; i++) { + req_state->pwr_domain_state[i] = s; + } + } + + plat_power_state[cpu] = power_state; + return PSCI_E_SUCCESS; +} + +static void plat_get_sys_suspend_power_state(psci_power_state_t *req_state) +{ + unsigned int lv; + unsigned int cpu = plat_my_core_pos(); + + for (lv = PSCI_CPU_PWR_LVL; lv <= PLAT_MAX_PWR_LVL; lv++) { + req_state->pwr_domain_state[lv] = PLAT_MAX_OFF_STATE; + } + + plat_power_state[cpu] = + psci_make_powerstate( + MT_PLAT_PWR_STATE_SYSTEM_SUSPEND, + PSTATE_TYPE_POWERDOWN, PLAT_MAX_PWR_LVL); + + flush_dcache_range((uintptr_t) + &plat_power_state[cpu], + sizeof(plat_power_state[cpu])); +} + +/******************************************************************************* + * MTK handlers to shutdown/reboot the system + ******************************************************************************/ +static void __dead2 plat_mtk_system_reset(void) +{ + struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset(); + + INFO("MTK System Reset\n"); + + gpio_set_value(gpio_reset->index, gpio_reset->polarity); + + wfi(); + ERROR("MTK System Reset: operation not handled.\n"); + panic(); +} + +static void __dead2 plat_mtk_system_off(void) +{ + INFO("MTK System Off\n"); + + rtc_power_off_sequence(); + pmic_power_off(); + + wfi(); + ERROR("MTK System Off: operation not handled.\n"); + panic(); +} + +static const plat_psci_ops_t plat_psci_ops = { + .system_reset = plat_mtk_system_reset, + .system_off = plat_mtk_system_off, + .cpu_standby = plat_cpu_standby, + .pwr_domain_on = plat_power_domain_on, + .pwr_domain_on_finish = plat_power_domain_on_finish, + .pwr_domain_off = plat_power_domain_off, + .pwr_domain_suspend = plat_power_domain_suspend, + .pwr_domain_suspend_finish = plat_power_domain_suspend_finish, + .validate_power_state = plat_validate_power_state, + .get_sys_suspend_power_state = plat_get_sys_suspend_power_state +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + *psci_ops = &plat_psci_ops; + secure_entrypoint = sec_entrypoint; + + /* + * init the warm reset config for boot CPU + * reset arch as AARCH64 + * reset addr as function bl31_warm_entrypoint() + */ + mcucfg_init_archstate(0U, 0U, true); + mcucfg_set_bootaddr(0U, 0U, secure_entrypoint); + + spmc_init(); + plat_mt_pm = mt_plat_cpu_pm_init(); + + return 0; +} diff --git a/plat/mediatek/mt8195/plat_sip_calls.c b/plat/mediatek/mt8195/plat_sip_calls.c new file mode 100644 index 0000000000000000000000000000000000000000..a1e3c36e83e0a2681a95e6b46cf27d94779c5b25 --- /dev/null +++ b/plat/mediatek/mt8195/plat_sip_calls.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +uintptr_t mediatek_plat_sip_handler(uint32_t smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags) +{ + switch (smc_fid) { + default: + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + break; + } + + SMC_RET1(handle, SMC_UNK); +} diff --git a/plat/mediatek/mt8195/plat_topology.c b/plat/mediatek/mt8195/plat_topology.c new file mode 100644 index 0000000000000000000000000000000000000000..bc95c6405dcbb2ac4954c4850f0b85e772b726db --- /dev/null +++ b/plat/mediatek/mt8195/plat_topology.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +const unsigned char mtk_power_domain_tree_desc[] = { + /* Number of root nodes */ + PLATFORM_SYSTEM_COUNT, + /* Number of children for the root node */ + PLATFORM_MCUSYS_COUNT, + /* Number of children for the mcusys node */ + PLATFORM_CLUSTER_COUNT, + /* Number of children for the first cluster node */ + PLATFORM_CLUSTER0_CORE_COUNT, +}; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return mtk_power_domain_tree_desc; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + if ((read_mpidr() & MPIDR_MT_MASK) != 0) { + /* ARMv8.2 arch */ + if ((mpidr & (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)) != 0) { + return -1; + } + return plat_mediatek_calc_core_pos(mpidr); + } + + mpidr &= MPIDR_AFFINITY_MASK; + + if ((mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) != 0) { + return -1; + } + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) { + return -1; + } + + /* + * Validate cpu_id by checking whether it represents a CPU in + * one of the two clusters present on the platform. + */ + if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) { + return -1; + } + + return (cpu_id + (cluster_id * 8)); +} diff --git a/plat/mediatek/mt8195/platform.mk b/plat/mediatek/mt8195/platform.mk new file mode 100644 index 0000000000000000000000000000000000000000..4d3ad59e1bc14b3920c2f609cb7b3f67b082fdc8 --- /dev/null +++ b/plat/mediatek/mt8195/platform.mk @@ -0,0 +1,78 @@ +# +# Copyright (c) 2021, MediaTek Inc. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +MTK_PLAT := plat/mediatek +MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT} + +PLAT_INCLUDES := -I${MTK_PLAT}/common/ \ + -I${MTK_PLAT}/common/drivers/gic600/ \ + -I${MTK_PLAT}/common/drivers/gpio/ \ + -I${MTK_PLAT}/common/drivers/rtc/ \ + -I${MTK_PLAT}/common/drivers/timer/ \ + -I${MTK_PLAT_SOC}/drivers/gpio/ \ + -I${MTK_PLAT_SOC}/drivers/mcdi/ \ + -I${MTK_PLAT_SOC}/drivers/pmic/ \ + -I${MTK_PLAT_SOC}/drivers/spmc/ \ + -I${MTK_PLAT_SOC}/include/ + +GICV3_SUPPORT_GIC600 := 1 +include drivers/arm/gic/v3/gicv3.mk +include lib/xlat_tables_v2/xlat_tables.mk + +PLAT_BL_COMMON_SOURCES := ${GICV3_SOURCES} \ + ${XLAT_TABLES_LIB_SRCS} \ + plat/common/aarch64/crash_console_helpers.S \ + plat/common/plat_psci_common.c + + +BL31_SOURCES += common/desc_image_load.c \ + drivers/delay_timer/delay_timer.c \ + drivers/gpio/gpio.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/ti/uart/aarch64/16550_console.S \ + lib/bl_aux_params/bl_aux_params.c \ + lib/cpus/aarch64/cortex_a55.S \ + lib/cpus/aarch64/cortex_a78.S \ + plat/common/plat_gicv3.c \ + ${MTK_PLAT}/common/drivers/gic600/mt_gic_v3.c \ + ${MTK_PLAT}/common/drivers/gpio/mtgpio_common.c \ + ${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init_v2.c \ + ${MTK_PLAT}/common/drivers/rtc/rtc_common.c \ + ${MTK_PLAT}/common/drivers/rtc/rtc_mt6359p.c \ + ${MTK_PLAT}/common/drivers/timer/mt_timer.c \ + ${MTK_PLAT}/common/mtk_cirq.c \ + ${MTK_PLAT}/common/mtk_plat_common.c \ + ${MTK_PLAT}/common/mtk_sip_svc.c \ + ${MTK_PLAT}/common/params_setup.c \ + ${MTK_PLAT_SOC}/aarch64/platform_common.c \ + ${MTK_PLAT_SOC}/aarch64/plat_helpers.S \ + ${MTK_PLAT_SOC}/bl31_plat_setup.c \ + ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \ + ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm.c \ + ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm_cpc.c \ + ${MTK_PLAT_SOC}/drivers/mcdi/mt_mcdi.c \ + ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \ + ${MTK_PLAT_SOC}/drivers/pmic/pmic.c \ + ${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c \ + ${MTK_PLAT_SOC}/plat_pm.c \ + ${MTK_PLAT_SOC}/plat_sip_calls.c \ + ${MTK_PLAT_SOC}/plat_topology.c + +# Configs for A78 and A55 +HW_ASSISTED_COHERENCY := 1 +USE_COHERENT_MEM := 0 +CTX_INCLUDE_AARCH32_REGS := 0 +ERRATA_A55_1530923 := 1 + +# indicate the reset vector address can be programmed +PROGRAMMABLE_RESET_ADDRESS := 1 + +COLD_BOOT_SINGLE_CPU := 1 + +MACH_MT8195 := 1 +$(eval $(call add_define,MACH_MT8195)) + +include lib/coreboot/coreboot.mk