From 054af8f233d94670dca1a27992296a5afc6b1f73 Mon Sep 17 00:00:00 2001 From: Po Xu Date: Fri, 18 Sep 2020 09:32:31 +0800 Subject: [PATCH 1/4] mediatek: mt8192: add GPIO driver support add GPIO driver Change-Id: I67a9abef078e7a62b34dfbd366b45c03892800cd Signed-off-by: Po Xu --- plat/mediatek/mt8192/bl31_plat_setup.c | 2 + plat/mediatek/mt8192/drivers/gpio/mtgpio.c | 340 +++++++++++++++++ plat/mediatek/mt8192/drivers/gpio/mtgpio.h | 384 ++++++++++++++++++++ plat/mediatek/mt8192/include/platform_def.h | 10 + plat/mediatek/mt8192/platform.mk | 8 +- 5 files changed, 742 insertions(+), 2 deletions(-) create mode 100644 plat/mediatek/mt8192/drivers/gpio/mtgpio.c create mode 100644 plat/mediatek/mt8192/drivers/gpio/mtgpio.h diff --git a/plat/mediatek/mt8192/bl31_plat_setup.c b/plat/mediatek/mt8192/bl31_plat_setup.c index f96528196..9a01bef65 100644 --- a/plat/mediatek/mt8192/bl31_plat_setup.c +++ b/plat/mediatek/mt8192/bl31_plat_setup.c @@ -15,6 +15,7 @@ #include /* Platform Includes */ +#include #include #include #include @@ -83,6 +84,7 @@ void bl31_platform_setup(void) /* Initialize the GIC driver, CPU and distributor interfaces */ mt_gic_driver_init(); mt_gic_init(); + plat_mt8192_gpio_init(); } /******************************************************************************* diff --git a/plat/mediatek/mt8192/drivers/gpio/mtgpio.c b/plat/mediatek/mt8192/drivers/gpio/mtgpio.c new file mode 100644 index 000000000..e07b75a47 --- /dev/null +++ b/plat/mediatek/mt8192/drivers/gpio/mtgpio.c @@ -0,0 +1,340 @@ +/* + * 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 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]; + + switch (gpio_info.base & 0x0f) { + case 0: + reg_addr = IOCFG_RM_BASE; + break; + case 1: + reg_addr = IOCFG_BM_BASE; + break; + case 2: + reg_addr = IOCFG_BL_BASE; + break; + case 3: + reg_addr = IOCFG_BR_BASE; + break; + case 4: + reg_addr = IOCFG_LM_BASE; + break; + case 5: + reg_addr = IOCFG_LB_BASE; + break; + case 6: + reg_addr = IOCFG_RT_BASE; + break; + case 7: + reg_addr = IOCFG_LT_BASE; + break; + case 8: + reg_addr = IOCFG_TL_BASE; + break; + default: + break; + } + + 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 new file mode 100644 index 000000000..ca0c964f6 --- /dev/null +++ b/plat/mediatek/mt8192/drivers/gpio/mtgpio.h @@ -0,0 +1,384 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#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 + +/* 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, + GPIO144, GPIO145, GPIO146, GPIO147, GPIO148, GPIO149, GPIO150, GPIO151, + GPIO152, GPIO153, GPIO154, GPIO155, GPIO156, GPIO157, GPIO158, GPIO159, + GPIO160, GPIO161, GPIO162, GPIO163, GPIO164, GPIO165, GPIO166, GPIO167, + GPIO168, GPIO169, GPIO170, GPIO171, GPIO172, GPIO173, GPIO174, GPIO175, + GPIO176, GPIO177, GPIO178, GPIO179, GPIO180, GPIO181, GPIO182, GPIO183, + GPIO184, GPIO185, GPIO186, GPIO187, GPIO188, GPIO189, GPIO190, GPIO191, + GPIO192, GPIO193, GPIO194, GPIO195, GPIO196, GPIO197, GPIO198, GPIO199, + GPIO200, GPIO201, GPIO202, GPIO203, GPIO204, GPIO205, GPIO206, GPIO207, + GPIO208, GPIO209, GPIO210, GPIO211, GPIO212, GPIO213, GPIO214, GPIO215, + GPIO216, GPIO217, GPIO218, GPIO219, + 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[] = { + PIN(0, 0, 9, 0x23, 0xb0), + PIN(1, 0, 10, 0x23, 0xb0), + PIN(2, 0, 11, 0x23, 0xb0), + PIN(3, 0, 12, 0x23, 0xb0), + PIN(4, 0, 13, 0x23, 0xb0), + PIN(5, 0, 14, 0x23, 0xb0), + PIN(6, 0, 15, 0x23, 0xb0), + PIN(7, 0, 16, 0x23, 0xb0), + PIN(8, 0, 17, 0x23, 0xb0), + PIN(9, 0, 18, 0x23, 0xb0), + PIN(10, 1, 0, 0x15, 0x20), + PIN(11, 1, 1, 0x15, 0x20), + PIN(12, 1, 2, 0x15, 0x20), + PIN(13, 1, 3, 0x15, 0x20), + PIN(14, 1, 4, 0x15, 0x20), + PIN(15, 1, 5, 0x15, 0x20), + PIN(16, 0, 2, 0x17, 0x50), + PIN(17, 0, 3, 0x17, 0x50), + PIN(18, 0, 21, 0x36, 0xa0), + PIN(19, 0, 22, 0x36, 0xa0), + PIN(20, 0, 23, 0x36, 0xa0), + PIN(21, 0, 24, 0x36, 0xa0), + PIN(22, 0, 3, 0x21, 0x90), + PIN(23, 0, 4, 0x21, 0x90), + PIN(24, 0, 5, 0x21, 0x90), + PIN(25, 0, 6, 0x21, 0x90), + PIN(26, 0, 5, 0x22, 0x80), + PIN(27, 0, 6, 0x22, 0x80), + PIN(28, 0, 7, 0x22, 0x80), + PIN(29, 0, 8, 0x22, 0x80), + PIN(30, 0, 9, 0x22, 0x80), + PIN(31, 0, 27, 0x22, 0x70), + PIN(32, 0, 24, 0x22, 0x70), + PIN(33, 0, 26, 0x22, 0x70), + PIN(34, 0, 23, 0x22, 0x70), + PIN(35, 0, 25, 0x22, 0x70), + PIN(36, 0, 20, 0x21, 0x90), + PIN(37, 0, 21, 0x21, 0x90), + PIN(38, 0, 22, 0x21, 0x90), + PIN(39, 0, 23, 0x21, 0x90), + PIN(40, 0, 0, 0x17, 0x50), + PIN(41, 0, 1, 0x17, 0x50), + PIN(42, 0, 4, 0x17, 0x50), + PIN(43, 0, 25, 0x36, 0xa0), + PIN(44, 0, 26, 0x36, 0xa0), + PIN(45, 1, 9, 0x20, 0x60), + PIN(46, 1, 11, 0x20, 0x60), + PIN(47, 1, 10, 0x20, 0x60), + PIN(48, 1, 7, 0x20, 0x60), + PIN(49, 1, 8, 0x20, 0x60), + PIN(50, 1, 6, 0x20, 0x60), + PIN(51, 1, 0, 0x20, 0x60), + PIN(52, 1, 1, 0x20, 0x60), + PIN(53, 1, 5, 0x20, 0x60), + PIN(54, 1, 2, 0x20, 0x60), + PIN(55, 1, 4, 0x20, 0x60), + PIN(56, 1, 3, 0x20, 0x60), + PIN(57, 0, 1, 0x22, 0x80), + PIN(58, 0, 2, 0x22, 0x80), + PIN(59, 0, 3, 0x22, 0x80), + PIN(60, 0, 4, 0x22, 0x80), + PIN(61, 0, 28, 0x22, 0x70), + PIN(62, 0, 22, 0x22, 0x70), + PIN(63, 0, 0, 0x22, 0x70), + PIN(64, 0, 1, 0x22, 0x70), + PIN(65, 0, 12, 0x22, 0x70), + PIN(66, 0, 15, 0x22, 0x70), + PIN(67, 0, 16, 0x22, 0x70), + PIN(68, 0, 17, 0x22, 0x70), + PIN(69, 0, 18, 0x22, 0x70), + PIN(70, 0, 19, 0x22, 0x70), + PIN(71, 0, 20, 0x22, 0x70), + PIN(72, 0, 21, 0x22, 0x70), + PIN(73, 0, 2, 0x22, 0x70), + PIN(74, 0, 3, 0x22, 0x70), + PIN(75, 0, 4, 0x22, 0x70), + PIN(76, 0, 5, 0x22, 0x70), + PIN(77, 0, 6, 0x22, 0x70), + PIN(78, 0, 7, 0x22, 0x70), + PIN(79, 0, 8, 0x22, 0x70), + PIN(80, 0, 9, 0x22, 0x70), + PIN(81, 0, 10, 0x22, 0x70), + PIN(82, 0, 11, 0x22, 0x70), + PIN(83, 0, 13, 0x22, 0x70), + PIN(84, 0, 14, 0x22, 0x70), + PIN(85, 0, 31, 0x22, 0x70), + PIN(86, 0, 0, 0x22, 0x80), + PIN(87, 0, 29, 0x22, 0x70), + PIN(88, 0, 30, 0x22, 0x70), + PIN(89, 0, 24, 0x21, 0x90), + PIN(90, 0, 25, 0x21, 0x90), + PIN(91, 0, 0, 0x21, 0x90), + PIN(92, 0, 2, 0x21, 0xa0), + PIN(93, 0, 4, 0x21, 0xa0), + PIN(94, 0, 3, 0x21, 0xa0), + PIN(95, 0, 5, 0x21, 0xa0), + PIN(96, 0, 31, 0x21, 0x90), + PIN(97, 0, 26, 0x21, 0x90), + PIN(98, 0, 0, 0x21, 0xa0), + PIN(99, 0, 27, 0x21, 0x90), + PIN(100, 0, 28, 0x21, 0x90), + PIN(101, 0, 29, 0x21, 0x90), + PIN(102, 0, 30, 0x21, 0x90), + PIN(103, 0, 18, 0x21, 0x90), + PIN(104, 0, 17, 0x21, 0x90), + PIN(105, 0, 19, 0x21, 0x90), + PIN(106, 0, 16, 0x21, 0x90), + PIN(107, 0, 1, 0x21, 0x90), + PIN(108, 0, 2, 0x21, 0x90), + PIN(109, 0, 10, 0x21, 0x90), + PIN(110, 0, 7, 0x21, 0x90), + PIN(111, 0, 9, 0x21, 0x90), + PIN(112, 0, 11, 0x21, 0x90), + PIN(113, 0, 8, 0x21, 0x90), + PIN(114, 0, 14, 0x21, 0x90), + PIN(115, 0, 13, 0x21, 0x90), + PIN(116, 0, 15, 0x21, 0x90), + PIN(117, 0, 12, 0x21, 0x90), + PIN(118, 0, 23, 0x23, 0xb0), + PIN(119, 0, 29, 0x23, 0xb0), + PIN(120, 0, 28, 0x23, 0xb0), + PIN(121, 0, 2, 0x23, 0xc0), + PIN(122, 0, 27, 0x23, 0xb0), + PIN(123, 0, 1, 0x23, 0xc0), + PIN(124, 0, 26, 0x23, 0xb0), + PIN(125, 0, 0, 0x23, 0xc0), + PIN(126, 0, 19, 0x23, 0xb0), + PIN(127, 0, 20, 0x23, 0xb0), + PIN(128, 0, 21, 0x23, 0xb0), + PIN(129, 0, 22, 0x23, 0xb0), + PIN(130, 0, 6, 0x23, 0xb0), + PIN(131, 0, 7, 0x23, 0xb0), + PIN(132, 0, 8, 0x23, 0xb0), + PIN(133, 0, 3, 0x23, 0xb0), + PIN(134, 0, 4, 0x23, 0xb0), + PIN(135, 0, 5, 0x23, 0xb0), + PIN(136, 0, 0, 0x23, 0xb0), + PIN(137, 0, 1, 0x23, 0xb0), + PIN(138, 0, 2, 0x23, 0xb0), + PIN(139, 0, 25, 0x23, 0xb0), + PIN(140, 0, 31, 0x23, 0xb0), + PIN(141, 0, 24, 0x23, 0xb0), + PIN(142, 0, 30, 0x23, 0xb0), + PIN(143, 0, 6, 0x20, 0x70), + PIN(144, 0, 7, 0x20, 0x70), + PIN(145, 0, 8, 0x20, 0x70), + PIN(146, 0, 3, 0x20, 0x70), + PIN(147, 0, 4, 0x20, 0x70), + PIN(148, 0, 5, 0x20, 0x70), + PIN(149, 0, 0, 0x20, 0x70), + PIN(150, 0, 1, 0x20, 0x70), + PIN(151, 0, 2, 0x20, 0x70), + PIN(152, 1, 3, 0x36, 0x90), + PIN(153, 1, 2, 0x36, 0x90), + PIN(154, 1, 0, 0x36, 0x906), + PIN(155, 1, 1, 0x36, 0x90), + PIN(156, 0, 29, 0x36, 0xa0), + PIN(157, 0, 30, 0x36, 0xa0), + PIN(158, 0, 31, 0x36, 0xa0), + PIN(159, 0, 0, 0x36, 0xb0), + PIN(160, 0, 27, 0x36, 0xa04), + PIN(161, 0, 28, 0x36, 0xa0), + PIN(162, 0, 0, 0x36, 0xa0), + PIN(163, 0, 1, 0x36, 0xa0), + PIN(164, 0, 2, 0x36, 0xa0), + PIN(165, 0, 3, 0x36, 0xa0), + PIN(166, 0, 4, 0x36, 0xa0), + PIN(167, 0, 5, 0x36, 0xa0), + PIN(168, 0, 6, 0x36, 0xa0), + PIN(169, 0, 7, 0x36, 0xa0), + PIN(170, 0, 8, 0x36, 0xa0), + PIN(171, 0, 9, 0x36, 0xa0), + PIN(172, 0, 13, 0x36, 0xa0), + PIN(173, 0, 14, 0x36, 0xa0), + PIN(174, 0, 12, 0x36, 0xa0), + PIN(175, 0, 15, 0x36, 0xa0), + PIN(176, 0, 10, 0x36, 0xa0), + PIN(177, 0, 11, 0x36, 0xa0), + PIN(178, 0, 16, 0x36, 0xa0), + PIN(179, 0, 17, 0x36, 0xa0), + PIN(180, 0, 18, 0x36, 0xa0), + PIN(181, 0, 19, 0x36, 0xa0), + PIN(182, 0, 20, 0x36, 0xa0), + PIN(183, 1, 1, 0x18, 0x30), + PIN(184, 1, 2, 0x18, 0x30), + PIN(185, 1, 4, 0x18, 0x30), + PIN(186, 1, 6, 0x18, 0x30), + PIN(187, 1, 8, 0x18, 0x30), + PIN(188, 1, 3, 0x18, 0x30), + PIN(189, 1, 7, 0x18, 0x30), + PIN(190, 1, 9, 0x18, 0x30), + PIN(191, 1, 10, 0x18, 0x30), + PIN(192, 1, 0, 0x18, 0x30), + PIN(193, 1, 5, 0x18, 0x30), + PIN(194, 1, 11, 0x18, 0x30), + PIN(195, 0, 16, 0x14, 0x50), + PIN(196, 0, 6, 0x14, 0x50), + PIN(197, 0, 8, 0x14, 0x50), + PIN(198, 0, 7, 0x14, 0x50), + PIN(199, 0, 3, 0x14, 0x50), + PIN(200, 0, 6, 0x17, 0x50), + PIN(201, 0, 8, 0x17, 0x50), + PIN(202, 0, 15, 0x14, 0x50), + PIN(203, 0, 17, 0x14, 0x50), + PIN(204, 0, 5, 0x17, 0x50), + PIN(205, 0, 7, 0x17, 0x50), + PIN(206, 0, 18, 0x14, 0x50), + PIN(207, 0, 19, 0x14, 0x50), + PIN(208, 0, 20, 0x14, 0x50), + PIN(209, 0, 12, 0x14, 0x50), + PIN(210, 0, 11, 0x14, 0x50), + PIN(211, 0, 13, 0x14, 0x50), + PIN(212, 0, 10, 0x14, 0x50), + PIN(213, 0, 14, 0x14, 0x50), + PIN(214, 0, 0, 0x14, 0x50), + PIN(215, 0, 9, 0x14, 0x50), + PIN(216, 0, 4, 0x14, 0x50), + PIN(217, 0, 5, 0x14, 0x50), + 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/include/platform_def.h b/plat/mediatek/mt8192/include/platform_def.h index 5ff013ecc..768e7cf82 100644 --- a/plat/mediatek/mt8192/include/platform_def.h +++ b/plat/mediatek/mt8192/include/platform_def.h @@ -24,6 +24,16 @@ #define MTK_DEV_RNG2_BASE 0x0c000000 #define MTK_DEV_RNG2_SIZE 0x600000 +#define GPIO_BASE (IO_PHYS + 0x00005000) +#define IOCFG_RM_BASE (IO_PHYS + 0x01C20000) +#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_LB_BASE (IO_PHYS + 0x01E70000) +#define IOCFG_RT_BASE (IO_PHYS + 0x01EA0000) +#define IOCFG_LT_BASE (IO_PHYS + 0x01F20000) +#define IOCFG_TL_BASE (IO_PHYS + 0x01F30000) /******************************************************************************* * UART related constants ******************************************************************************/ diff --git a/plat/mediatek/mt8192/platform.mk b/plat/mediatek/mt8192/platform.mk index c972ac61d..0d732d50a 100644 --- a/plat/mediatek/mt8192/platform.mk +++ b/plat/mediatek/mt8192/platform.mk @@ -8,7 +8,9 @@ MTK_PLAT := plat/mediatek MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT} PLAT_INCLUDES := -I${MTK_PLAT}/common/ \ - -I${MTK_PLAT_SOC}/include/ + -I${MTK_PLAT_SOC}/include/ \ + -I${MTK_PLAT_SOC}/drivers/ \ + -I${MTK_PLAT_SOC}/drivers/gpio/ GICV3_SUPPORT_GIC600 := 1 include drivers/arm/gic/v3/gicv3.mk @@ -21,6 +23,7 @@ PLAT_BL_COMMON_SOURCES := ${GICV3_SOURCES} \ BL31_SOURCES += common/desc_image_load.c \ drivers/ti/uart/aarch64/16550_console.S \ + drivers/gpio/gpio.c \ lib/bl_aux_params/bl_aux_params.c \ lib/cpus/aarch64/cortex_a55.S \ lib/cpus/aarch64/cortex_a76.S \ @@ -32,7 +35,8 @@ BL31_SOURCES += common/desc_image_load.c \ ${MTK_PLAT_SOC}/bl31_plat_setup.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_gic.c \ + ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c # Configs for A76 and A55 From b6cec337854b80c8ec3a36b0c7a82c531d59acac Mon Sep 17 00:00:00 2001 From: gtk_pangao Date: Thu, 19 Dec 2019 15:58:20 +0800 Subject: [PATCH 2/4] mediatek: mt8192: add sys_cirq driver 1.add sys_cirq driver 2.add gic api for cirq Change-Id: Ie6802d6ddcf7dde3412a050736dfdc85f97cb51b Signed-off-by: gtk_pangao --- plat/mediatek/mt8192/include/mt_gic_v3.h | 3 + plat/mediatek/mt8192/include/plat_mt_cirq.h | 82 ++++ plat/mediatek/mt8192/plat_mt_cirq.c | 494 ++++++++++++++++++++ plat/mediatek/mt8192/plat_mt_gic.c | 19 + plat/mediatek/mt8192/platform.mk | 1 + 5 files changed, 599 insertions(+) create mode 100644 plat/mediatek/mt8192/include/plat_mt_cirq.h create mode 100644 plat/mediatek/mt8192/plat_mt_cirq.c diff --git a/plat/mediatek/mt8192/include/mt_gic_v3.h b/plat/mediatek/mt8192/include/mt_gic_v3.h index 34ba8a7e3..c4ab44fa3 100644 --- a/plat/mediatek/mt8192/include/mt_gic_v3.h +++ b/plat/mediatek/mt8192/include/mt_gic_v3.h @@ -21,4 +21,7 @@ void mt_gic_rdistif_restore(void); void mt_gic_rdistif_restore_all(void); void gic_sgi_save_all(void); void gic_sgi_restore_all(void); +uint32_t mt_irq_get_pending(uint32_t irq); +void mt_irq_set_pending(uint32_t irq); + #endif /* MT_GIC_V3_H */ diff --git a/plat/mediatek/mt8192/include/plat_mt_cirq.h b/plat/mediatek/mt8192/include/plat_mt_cirq.h new file mode 100644 index 000000000..581860109 --- /dev/null +++ b/plat/mediatek/mt8192/include/plat_mt_cirq.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MT_CIRQ_H +#define PLAT_MT_CIRQ_H + +#define SYS_CIRQ_BASE U(0x10204000) +#define CIRQ_IRQ_NUM U(439) +#define CIRQ_SPI_START U(96) +/* + * Define hardware register + */ +#define CIRQ_STA_BASE U(0x000) +#define CIRQ_ACK_BASE U(0x080) +#define CIRQ_MASK_BASE U(0x100) +#define CIRQ_MASK_SET_BASE U(0x180) +#define CIRQ_MASK_CLR_BASE U(0x200) +#define CIRQ_SENS_BASE U(0x280) +#define CIRQ_SENS_SET_BASE U(0x300) +#define CIRQ_SENS_CLR_BASE U(0x380) +#define CIRQ_POL_BASE U(0x400) +#define CIRQ_POL_SET_BASE U(0x480) +#define CIRQ_POL_CLR_BASE U(0x500) +#define CIRQ_CON U(0x600) + +/* + * Register placement + */ +#define CIRQ_CON_EN_BITS U(0) +#define CIRQ_CON_EDGE_ONLY_BITS U(1) +#define CIRQ_CON_FLUSH_BITS U(2) +#define CIRQ_CON_EVENT_BITS U(31) +#define CIRQ_CON_SW_RST_BITS U(20) +#define CIRQ_CON_BITS_MASK U(0x7) + +/* + * Register setting + */ +#define CIRQ_CON_EN U(0x1) +#define CIRQ_CON_EDGE_ONLY U(0x1) +#define CIRQ_SW_RESET U(0x1) +#define CIRQ_CON_FLUSH U(0x1) + +/* + * Define constant + */ +#define CIRQ_CTRL_REG_NUM ((CIRQ_IRQ_NUM + 31U) / 32U) +#define MT_CIRQ_POL_NEG U(0) +#define MT_CIRQ_POL_POS U(1) +#define MT_CIRQ_EDGE_SENSITIVE U(0) +#define MT_CIRQ_LEVEL_SENSITIVE U(1) + +/* + * Define macro + */ +#define IRQ_TO_CIRQ_NUM(irq) ((irq) - (CIRQ_SPI_START)) +#define CIRQ_TO_IRQ_NUM(cirq) ((cirq) + (CIRQ_SPI_START)) + +/* + * Define cirq events + */ +struct cirq_events { + uint32_t spi_start; + uint32_t num_of_events; + uint32_t *wakeup_events; +}; + +/* + * Define function prototypes. + */ +void mt_cirq_enable(void); +void mt_cirq_disable(void); +void mt_cirq_clone_gic(void); +void mt_cirq_flush(void); +void mt_cirq_sw_reset(void); +void set_wakeup_sources(uint32_t *list, uint32_t num_of_events); +void mt_cirq_dump_reg(void); + +#endif /* PLAT_MT_CIRQ_H */ diff --git a/plat/mediatek/mt8192/plat_mt_cirq.c b/plat/mediatek/mt8192/plat_mt_cirq.c new file mode 100644 index 000000000..7fc060799 --- /dev/null +++ b/plat/mediatek/mt8192/plat_mt_cirq.c @@ -0,0 +1,494 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static struct cirq_events cirq_all_events = { + .spi_start = CIRQ_SPI_START +}; + +static inline void mt_cirq_write32(uint32_t val, uint32_t addr) +{ + mmio_write_32(addr + SYS_CIRQ_BASE, val); +} + +static inline uint32_t mt_cirq_read32(uint32_t addr) +{ + return mmio_read_32(addr + SYS_CIRQ_BASE); +} + +/* + * cirq_clone_flush_check_store: + * set 1 if we need to enable clone/flush value's check + */ +static int32_t cirq_clone_flush_check_val; + +/* + * cirq_pattern_clone_flush_check_show: set 1 if we need to do pattern test. + */ +static int32_t cirq_pattern_clone_flush_check_val; + +/* + * cirq_pattern_clone_flush_check_show: set 1 if we need to do pattern test. + */ +static int32_t cirq_pattern_list; + +/* + * mt_cirq_ack_all: Ack all the interrupt on SYS_CIRQ + */ +void mt_cirq_ack_all(void) +{ + unsigned int i; + + for (i = 0U; i < CIRQ_CTRL_REG_NUM; i++) { + mt_cirq_write32(0xFFFFFFFF, CIRQ_ACK_BASE + (i * 4U)); + } + /* make sure all cirq setting take effect before doing other things */ + dmbsy(); +} + +/* + * mt_cirq_enable: Enable SYS_CIRQ + */ +void mt_cirq_enable(void) +{ + uint32_t st; + + mt_cirq_ack_all(); + + st = mt_cirq_read32(CIRQ_CON); + st |= (CIRQ_CON_EN << CIRQ_CON_EN_BITS) | + (CIRQ_CON_EDGE_ONLY << CIRQ_CON_EDGE_ONLY_BITS); + + mt_cirq_write32((st & CIRQ_CON_BITS_MASK), CIRQ_CON); +} + +/* + * mt_cirq_disable: Disable SYS_CIRQ + */ +void mt_cirq_disable(void) +{ + uint32_t st; + + st = mt_cirq_read32(CIRQ_CON); + st &= ~(CIRQ_CON_EN << CIRQ_CON_EN_BITS); + + mt_cirq_write32((st & CIRQ_CON_BITS_MASK), CIRQ_CON); +} + +/* + * mt_cirq_get_mask: Get the specified SYS_CIRQ mask + * @cirq_num: the SYS_CIRQ number to get + * @return: + * 1: this cirq is masked + * 0: this cirq is umasked + * 2: cirq num is out of range + */ +__attribute__((weak)) unsigned int mt_cirq_get_mask(uint32_t cirq_num) +{ + uint32_t st; + unsigned int val; + + if (cirq_num >= CIRQ_IRQ_NUM) { + ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num); + return 2; + } + + st = mt_cirq_read32((cirq_num / 32U) * 4U + CIRQ_MASK_BASE); + val = (st >> (cirq_num % 32U)) & 1U; + return val; +} + +/* + * mt_cirq_mask_all: Mask all interrupts on SYS_CIRQ. + */ +void mt_cirq_mask_all(void) +{ + unsigned int i; + + for (i = 0U; i < CIRQ_CTRL_REG_NUM; i++) { + mt_cirq_write32(0xFFFFFFFF, CIRQ_MASK_SET_BASE + (i * 4U)); + } + /* make sure all cirq setting take effect before doing other things */ + dmbsy(); +} + +/* + * mt_cirq_unmask_all: Unmask all interrupts on SYS_CIRQ. + */ +void mt_cirq_unmask_all(void) +{ + unsigned int i; + + for (i = 0U; i < CIRQ_CTRL_REG_NUM; i++) { + mt_cirq_write32(0xFFFFFFFF, CIRQ_MASK_CLR_BASE + (i * 4U)); + } + /* make sure all cirq setting take effect before doing other things */ + dmbsy(); +} + +/* + * mt_cirq_mask: Mask the specified SYS_CIRQ. + * @cirq_num: the SYS_CIRQ number to mask + * @return: + * 0: mask success + * -1: cirq num is out of range + */ +static int mt_cirq_mask(uint32_t cirq_num) +{ + uint32_t bit = 1U << (cirq_num % 32U); + + if (cirq_num >= CIRQ_IRQ_NUM) { + ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num); + return -1; + } + + mt_cirq_write32(bit, (cirq_num / 32U) * 4U + CIRQ_MASK_SET_BASE); + return 0; +} + +/* + * mt_cirq_unmask: Unmask the specified SYS_CIRQ. + * @cirq_num: the SYS_CIRQ number to unmask + * @return: + * 0: umask success + * -1: cirq num is out of range + */ +static int mt_cirq_unmask(uint32_t cirq_num) +{ + uint32_t bit = 1U << (cirq_num % 32U); + + if (cirq_num >= CIRQ_IRQ_NUM) { + ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num); + return -1; + } + + mt_cirq_write32(bit, (cirq_num / 32U) * 4U + CIRQ_MASK_CLR_BASE); + return 0; +} + +/* + * mt_cirq_set_sens: Set the sensitivity for the specified SYS_CIRQ number. + * @cirq_num: the SYS_CIRQ number to set + * @sens: sensitivity to set + * @return: + * 0: set sens success + * -1: cirq num is out of range + */ +static int mt_cirq_set_sens(uint32_t cirq_num, uint32_t sens) +{ + uint32_t base; + uint32_t bit = 1U << (cirq_num % 32U); + + if (cirq_num >= CIRQ_IRQ_NUM) { + ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num); + return -1; + } + + if (sens == MT_CIRQ_EDGE_SENSITIVE) { + base = (cirq_num / 32U) * 4U + CIRQ_SENS_CLR_BASE; + } else if (sens == MT_CIRQ_LEVEL_SENSITIVE) { + base = (cirq_num / 32U) * 4U + CIRQ_SENS_SET_BASE; + } else { + ERROR("[CIRQ] set_sens invalid sen value %u\n", sens); + return -1; + } + + mt_cirq_write32(bit, base); + return 0; +} + +/* + * mt_cirq_get_sens: Get the specified SYS_CIRQ sensitivity + * @cirq_num: the SYS_CIRQ number to get + * @return: + * 1: this cirq is MT_LEVEL_SENSITIVE + * 0: this cirq is MT_EDGE_SENSITIVE + * 2: cirq num is out of range + */ +__attribute__((weak)) unsigned int mt_cirq_get_sens(uint32_t cirq_num) +{ + uint32_t st; + unsigned int val; + + if (cirq_num >= CIRQ_IRQ_NUM) { + ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num); + return 2; + } + + st = mt_cirq_read32((cirq_num / 32U) * 4U + CIRQ_SENS_BASE); + val = (st >> (cirq_num % 32U)) & 1U; + return val; +} + +/* + * mt_cirq_set_pol: Set the polarity for the specified SYS_CIRQ number. + * @cirq_num: the SYS_CIRQ number to set + * @pol: polarity to set + * @return: + * 0: set pol success + * -1: cirq num is out of range + */ +static int mt_cirq_set_pol(uint32_t cirq_num, uint32_t pol) +{ + uint32_t base; + uint32_t bit = 1U << (cirq_num % 32U); + + if (cirq_num >= CIRQ_IRQ_NUM) { + ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num); + return -1; + } + + if (pol == MT_CIRQ_POL_NEG) { + base = (cirq_num / 32U) * 4U + CIRQ_POL_CLR_BASE; + } else if (pol == MT_CIRQ_POL_POS) { + base = (cirq_num / 32U) * 4U + CIRQ_POL_SET_BASE; + } else { + ERROR("[CIRQ] set_pol invalid polarity value %u\n", pol); + return -1; + } + + mt_cirq_write32(bit, base); + return 0; +} + +/* + * mt_cirq_get_pol: Get the specified SYS_CIRQ polarity + * @cirq_num: the SYS_CIRQ number to get + * @return: + * 1: this cirq is MT_CIRQ_POL_POS + * 0: this cirq is MT_CIRQ_POL_NEG + * 2: cirq num is out of range + */ +__attribute__((weak)) unsigned int mt_cirq_get_pol(uint32_t cirq_num) +{ + uint32_t st; + unsigned int val; + + if (cirq_num >= CIRQ_IRQ_NUM) { + ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num); + return 2; + } + + st = mt_cirq_read32((cirq_num / 32U) * 4U + CIRQ_POL_BASE); + val = (st >> (cirq_num % 32U)) & 1U; + return val; +} + +/* + * mt_cirq_get_pending: Get the specified SYS_CIRQ pending + * @cirq_num: the SYS_CIRQ number to get + * @return: + * 1: this cirq is pending + * 0: this cirq is not pending + * 2: cirq num is out of range + */ +static unsigned int mt_cirq_get_pending(uint32_t cirq_num) +{ + uint32_t st; + unsigned int val; + + if (cirq_num >= CIRQ_IRQ_NUM) { + ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num); + return 2; + } + + st = mt_cirq_read32((cirq_num / 32U) * 4U + CIRQ_STA_BASE); + val = (st >> (cirq_num % 32U)) & 1U; + return val; +} + +/* + * mt_cirq_clone_pol: Copy the polarity setting from GIC to SYS_CIRQ + */ +void mt_cirq_clone_pol(void) +{ + uint32_t cirq_num; + + for (cirq_num = 0U; cirq_num < CIRQ_IRQ_NUM; cirq_num++) { + mt_cirq_set_pol(cirq_num, MT_CIRQ_POL_POS); + } +} + +/* + * mt_cirq_clone_sens: Copy the sensitivity setting from GIC to SYS_CIRQ + */ +void mt_cirq_clone_sens(void) +{ + uint32_t cirq_num, irq_num; + uint32_t st, val; + + for (cirq_num = 0U; cirq_num < CIRQ_IRQ_NUM; cirq_num++) { + irq_num = CIRQ_TO_IRQ_NUM(cirq_num); + + if ((cirq_num == 0U) || (irq_num % 16U == 0U)) { + st = mmio_read_32(BASE_GICD_BASE + GICD_ICFGR + + (irq_num / 16U * 4U)); + } + + val = (st >> ((irq_num % 16U) * 2U)) & 0x2U; + + if (val) { + mt_cirq_set_sens(cirq_num, MT_CIRQ_EDGE_SENSITIVE); + } else { + mt_cirq_set_sens(cirq_num, MT_CIRQ_LEVEL_SENSITIVE); + } + } +} + +/* + * mt_cirq_clone_mask: Copy the mask setting from GIC to SYS_CIRQ + */ +void mt_cirq_clone_mask(void) +{ + uint32_t cirq_num, irq_num; + uint32_t st, val; + + for (cirq_num = 0U; cirq_num < CIRQ_IRQ_NUM; cirq_num++) { + irq_num = CIRQ_TO_IRQ_NUM(cirq_num); + + if ((cirq_num == 0U) || (irq_num % 32U == 0U)) { + st = mmio_read_32(BASE_GICD_BASE + + GICD_ISENABLER + (irq_num / 32U * 4U)); + } + + val = (st >> (irq_num % 32)) & 1U; + + if (val) { + mt_cirq_unmask(cirq_num); + } else { + mt_cirq_mask(cirq_num); + } + } +} + +/* + * mt_cirq_clone_gic: Copy the setting from GIC to SYS_CIRQ + */ +void mt_cirq_clone_gic(void) +{ + mt_cirq_clone_sens(); + mt_cirq_clone_mask(); +} + +/* + * mt_cirq_disable: Flush interrupt from SYS_CIRQ to GIC + */ +void mt_cirq_flush(void) +{ + unsigned int i; + unsigned char cirq_p_val = 0U; + unsigned char irq_p_val = 0U; + uint32_t irq_p = 0U; + unsigned char pass = 1U; + uint32_t first_cirq_found = 0U; + uint32_t first_flushed_cirq; + uint32_t first_irq_flushedto; + uint32_t last_fluashed_cirq; + uint32_t last_irq_flushedto; + + if (cirq_pattern_clone_flush_check_val == 1U) { + if (cirq_pattern_list < CIRQ_IRQ_NUM) { + mt_cirq_unmask(cirq_pattern_list); + mt_cirq_set_sens(cirq_pattern_list, + MT_CIRQ_EDGE_SENSITIVE); + mt_cirq_set_pol(cirq_pattern_list, MT_CIRQ_POL_NEG); + mt_cirq_set_pol(cirq_pattern_list, MT_CIRQ_POL_POS); + mt_cirq_set_pol(cirq_pattern_list, MT_CIRQ_POL_NEG); + } else { + ERROR("[CIRQ] no pattern to test,"); + ERROR("input pattern first\n"); + } + ERROR("[CIRQ] cirq_pattern %u, cirq_p %u,", + cirq_pattern_list, + mt_cirq_get_pending(cirq_pattern_list)); + ERROR("cirq_s %u, cirq_con 0x%x\n", + mt_cirq_get_sens(cirq_pattern_list), + mt_cirq_read32(CIRQ_CON)); + } + + mt_cirq_unmask_all(); + + for (i = 0U; i < CIRQ_IRQ_NUM; i++) { + cirq_p_val = mt_cirq_get_pending(i); + if (cirq_p_val) { + mt_irq_set_pending(CIRQ_TO_IRQ_NUM(i)); + } + + if (cirq_clone_flush_check_val == 1U) { + if (cirq_p_val == 0U) { + continue; + } + irq_p = CIRQ_TO_IRQ_NUM(i); + irq_p_val = mt_irq_get_pending(irq_p); + if (cirq_p_val != irq_p_val) { + ERROR("[CIRQ] CIRQ Flush Failed "); + ERROR("%u(cirq %d)!= %u(gic %d)\n", + cirq_p_val, i, irq_p_val, + CIRQ_TO_IRQ_NUM(i)); + pass = 0; + } else { + ERROR("[CIRQ] CIRQ Flush Pass "); + ERROR("%u(cirq %d) = %u(gic %d)\n", + cirq_p_val, i, irq_p_val, + CIRQ_TO_IRQ_NUM(i)); + } + if (!first_cirq_found) { + first_flushed_cirq = i; + first_irq_flushedto = irq_p; + first_cirq_found = 1U; + } + last_fluashed_cirq = i; + last_irq_flushedto = irq_p; + } + } + + if (cirq_clone_flush_check_val == 1U) { + if (first_cirq_found) { + ERROR("[CIRQ] The first flush : CIRQ%u to IRQ%u\n", + first_flushed_cirq, first_irq_flushedto); + ERROR("[CIRQ] The last flush : CIRQ%u to IRQ%u\n", + last_fluashed_cirq, last_irq_flushedto); + } else { + ERROR("[CIRQ] There are no pending "); + ERROR("interrupt in CIRQ\n"); + ERROR("[CIRQ] so no flush operation happened\n"); + } + ERROR("[CIRQ] The Flush Max Range : CIRQ"); + ERROR("%d to IRQ%d ~ CIRQ%d to IRQ%d\n", 0U, + CIRQ_TO_IRQ_NUM(0U), CIRQ_IRQ_NUM - 1U, + CIRQ_TO_IRQ_NUM(CIRQ_IRQ_NUM - 1U)); + ERROR("[CIRQ] Flush Check %s, Confirm:SPI_START_OFFSET:%d\n", + pass == 1 ? "Pass" : "Failed", CIRQ_SPI_START); + } + mt_cirq_mask_all(); + mt_cirq_ack_all(); +} + +void mt_cirq_sw_reset(void) +{ + uint32_t st; + + st = mt_cirq_read32(CIRQ_CON); + st |= (CIRQ_SW_RESET << CIRQ_CON_SW_RST_BITS); + + mt_cirq_write32(st, CIRQ_CON); +} + +void set_wakeup_sources(uint32_t *list, uint32_t num_of_events) +{ + cirq_all_events.num_of_events = num_of_events; + cirq_all_events.wakeup_events = list; +} diff --git a/plat/mediatek/mt8192/plat_mt_gic.c b/plat/mediatek/mt8192/plat_mt_gic.c index 593f5d04e..ae8d697a5 100644 --- a/plat/mediatek/mt8192/plat_mt_gic.c +++ b/plat/mediatek/mt8192/plat_mt_gic.c @@ -175,3 +175,22 @@ void mt_gic_init(void) gicv3_rdistif_init(plat_my_core_pos()); gicv3_cpuif_enable(plat_my_core_pos()); } + +uint32_t mt_irq_get_pending(uint32_t irq) +{ + uint32_t val; + + val = mmio_read_32(BASE_GICD_BASE + GICD_ISPENDR + + irq / 32 * 4); + val = (val >> (irq % 32)) & 1U; + return val; +} + + +void mt_irq_set_pending(uint32_t irq) +{ + uint32_t bit = 1U << (irq % 32); + + mmio_write_32(BASE_GICD_BASE + GICD_ISPENDR + + irq / 32 * 4, bit); +} diff --git a/plat/mediatek/mt8192/platform.mk b/plat/mediatek/mt8192/platform.mk index 0d732d50a..071700ee9 100644 --- a/plat/mediatek/mt8192/platform.mk +++ b/plat/mediatek/mt8192/platform.mk @@ -36,6 +36,7 @@ BL31_SOURCES += common/desc_image_load.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}/drivers/gpio/mtgpio.c From 0f408247292b6e49a4228dc7bd3941caf1db5dbc Mon Sep 17 00:00:00 2001 From: Nina Wu Date: Thu, 2 Jul 2020 12:10:13 +0800 Subject: [PATCH 3/4] mediatek: mt8192: Add reboot function for PSCI Add system_reset function in psci ops Change-Id: If85be70b8ae9d6487e02626356f0ff1e78b76de9 Signed-off-by: Nina Wu --- plat/mediatek/mt8192/plat_pm.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/plat/mediatek/mt8192/plat_pm.c b/plat/mediatek/mt8192/plat_pm.c index 81a170dd7..becf5d311 100644 --- a/plat/mediatek/mt8192/plat_pm.c +++ b/plat/mediatek/mt8192/plat_pm.c @@ -5,16 +5,36 @@ */ /* common headers */ +#include +#include +#include #include /* mediatek platform specific headers */ +#include +/******************************************************************************* + * 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(); +} /******************************************************************************* * MTK_platform handler called when an affinity instance is about to be turned * on. The level and mpidr determine the affinity instance. ******************************************************************************/ static const plat_psci_ops_t plat_plat_pm_ops = { + .system_reset = plat_mtk_system_reset, }; int plat_setup_psci_ops(uintptr_t sec_entrypoint, From 4a128018b63ca9a4517eeefbe0c1c50b691ce433 Mon Sep 17 00:00:00 2001 From: Dehui Sun Date: Fri, 3 Jul 2020 09:19:06 +0800 Subject: [PATCH 4/4] mediatek: mt8192: add timer support add timer driver. Signed-off-by: Dehui Sun Change-Id: I07448d85a15bb14577b05e4f302860d609420ba7 --- plat/mediatek/mt8192/drivers/timer/mt_timer.c | 30 +++++++++++++++++++ plat/mediatek/mt8192/drivers/timer/mt_timer.h | 30 +++++++++++++++++++ plat/mediatek/mt8192/platform.mk | 6 ++-- 3 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 plat/mediatek/mt8192/drivers/timer/mt_timer.c create mode 100644 plat/mediatek/mt8192/drivers/timer/mt_timer.h diff --git a/plat/mediatek/mt8192/drivers/timer/mt_timer.c b/plat/mediatek/mt8192/drivers/timer/mt_timer.c new file mode 100644 index 000000000..781f940b6 --- /dev/null +++ b/plat/mediatek/mt8192/drivers/timer/mt_timer.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + +uint64_t normal_time_base; +uint64_t atf_time_base; + +void sched_clock_init(uint64_t normal_base, uint64_t atf_base) +{ + normal_time_base += normal_base; + atf_time_base = atf_base; +} + +uint64_t sched_clock(void) +{ + uint64_t cval; + uint64_t rel_base; + + rel_base = read_cntpct_el0() - atf_time_base; + cval = ((rel_base * 1000U) / SYS_COUNTER_FREQ_IN_MHZ) + - normal_time_base; + return cval; +} diff --git a/plat/mediatek/mt8192/drivers/timer/mt_timer.h b/plat/mediatek/mt8192/drivers/timer/mt_timer.h new file mode 100644 index 000000000..7aca4a3bf --- /dev/null +++ b/plat/mediatek/mt8192/drivers/timer/mt_timer.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_TIMER_H +#define MT_TIMER_H + +#define SYSTIMER_BASE (0x10017000) +#define CNTCR_REG (SYSTIMER_BASE + 0x0) +#define CNTSR_REG (SYSTIMER_BASE + 0x4) +#define CNTSYS_L_REG (SYSTIMER_BASE + 0x8) +#define CNTSYS_H_REG (SYSTIMER_BASE + 0xc) + +#define TIEO_EN (1 << 3) +#define COMP_15_EN (1 << 10) +#define COMP_20_EN (1 << 11) +#define COMP_25_EN (1 << 12) + +#define COMP_FEATURE_MASK (COMP_15_EN | COMP_20_EN | COMP_25_EN | TIEO_EN) +#define COMP_15_MASK (COMP_15_EN) +#define COMP_20_MASK (COMP_20_EN | TIEO_EN) +#define COMP_25_MASK (COMP_20_EN | COMP_25_EN) + + +void sched_clock_init(uint64_t normal_base, uint64_t atf_base); +uint64_t sched_clock(void); + +#endif /* MT_TIMER_H */ diff --git a/plat/mediatek/mt8192/platform.mk b/plat/mediatek/mt8192/platform.mk index 071700ee9..7544b2658 100644 --- a/plat/mediatek/mt8192/platform.mk +++ b/plat/mediatek/mt8192/platform.mk @@ -10,7 +10,8 @@ MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT} PLAT_INCLUDES := -I${MTK_PLAT}/common/ \ -I${MTK_PLAT_SOC}/include/ \ -I${MTK_PLAT_SOC}/drivers/ \ - -I${MTK_PLAT_SOC}/drivers/gpio/ + -I${MTK_PLAT_SOC}/drivers/gpio/ \ + -I${MTK_PLAT_SOC}/drivers/timer/ GICV3_SUPPORT_GIC600 := 1 include drivers/arm/gic/v3/gicv3.mk @@ -37,7 +38,8 @@ BL31_SOURCES += common/desc_image_load.c \ ${MTK_PLAT_SOC}/plat_topology.c \ ${MTK_PLAT_SOC}/plat_mt_gic.c \ ${MTK_PLAT_SOC}/plat_mt_cirq.c \ - ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c + ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \ + ${MTK_PLAT_SOC}/drivers/timer/mt_timer.c # Configs for A76 and A55