diff --git a/lib/utils/gpio/fdt_gpio_sophgo.c b/lib/utils/gpio/fdt_gpio_sophgo.c index 0cc95288..74163305 100644 --- a/lib/utils/gpio/fdt_gpio_sophgo.c +++ b/lib/utils/gpio/fdt_gpio_sophgo.c @@ -25,6 +25,7 @@ #define SOPHGO_GPIO_SWPORTA_CTL_OFFSET 0x08 #define SOPHGO_GPIO_BIT(offset) (1U << (offset)) +#define SOPHGO_GPIO_STARTUP_FLAG SOPHGO_GPIO_BIT(16) struct sophgo_gpio_chip { unsigned long addr; @@ -74,26 +75,43 @@ static void sophgo_gpio_set(struct gpio_pin *gp, int value) static int sophgo_gpio_addr_get(void *fdt, int nodeoff, unsigned long *addr) { - int rc; + int parent, len; unsigned long addr_high, addr_low; + const fdt32_t *prop_addr; - rc = fdt_get_node_addr_size(fdt, nodeoff, 1, &addr_low, NULL); - if (rc) - return rc; + parent = fdt_parent_offset(fdt, nodeoff); + if (parent < 0) + return parent; - rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &addr_high, NULL); - if (rc) - return rc; + prop_addr = fdt_getprop(fdt, parent, "reg", &len); + if (!prop_addr) + return SBI_ENODEV; + + addr_high = fdt32_to_cpu(*prop_addr++); + addr_low = fdt32_to_cpu(*prop_addr); *addr = addr_high << 32 | addr_low; return 0; } +static void sophgo_system_normal_startup_flag(unsigned long addr) +{ + unsigned int v; + + v = readl((volatile void *)(addr + SOPHGO_GPIO_SWPORTA_DDR_OFFSET)); + v |= SOPHGO_GPIO_STARTUP_FLAG; + writel(v, (volatile void *)(addr + SOPHGO_GPIO_SWPORTA_DDR_OFFSET)); + + v = readl((volatile void *)(addr + SOPHGO_GPIO_SWPORTA_DR_OFFSET)); + v |= SOPHGO_GPIO_STARTUP_FLAG; + writel(v, (volatile void *)(addr + SOPHGO_GPIO_SWPORTA_DR_OFFSET)); +} + extern struct fdt_gpio fdt_gpio_sophgo; static int sophgo_gpio_init(void *fdt, int nodeoff, u32 phandle, - const struct fdt_match *match) + const struct fdt_match *match) { int rc; struct sophgo_gpio_chip *chip; @@ -101,14 +119,14 @@ static int sophgo_gpio_init(void *fdt, int nodeoff, u32 phandle, if (SOPHGO_GPIO_CHIP_MAX <= sophgo_gpio_chip_count) { rc = SBI_ENOSPC; - goto out; + return rc; } chip = &sophgo_gpio_chip_array[sophgo_gpio_chip_count]; rc = sophgo_gpio_addr_get(fdt, nodeoff, &addr); if (rc) - goto out; + return rc; chip->addr = addr; chip->chip.driver = &fdt_gpio_sophgo; @@ -119,14 +137,12 @@ static int sophgo_gpio_init(void *fdt, int nodeoff, u32 phandle, rc = gpio_chip_add(&chip->chip); if (rc) - goto out; + return rc; sophgo_gpio_chip_count++; + sophgo_system_normal_startup_flag(addr); -out: - fdt_del_node(fdt, nodeoff); - - return rc; + return 0; } static const struct fdt_match sophgo_gpio_match[] = { diff --git a/lib/utils/reset/fdt_reset_sophgo_cpld.c b/lib/utils/reset/fdt_reset_sophgo_cpld.c index 070437de..7c3fbde9 100644 --- a/lib/utils/reset/fdt_reset_sophgo_cpld.c +++ b/lib/utils/reset/fdt_reset_sophgo_cpld.c @@ -24,20 +24,28 @@ struct cpld_reset { }; static struct cpld_reset poweroff = { - .active_delay = 300, - .inactive_delay = 300 + .active_delay = 300, + .inactive_delay = 300 }; -static struct cpld_reset *cpld_reset_get(u32 type) +static struct cpld_reset reboot = { + .active_delay = 300, + .inactive_delay = 300 +}; + +static struct cpld_reset *cpld_reset_get(bool is_poweroff, u32 type) { struct cpld_reset *reset = NULL; switch (type) { case SBI_SRST_RESET_TYPE_SHUTDOWN: - reset = &poweroff; + if (is_poweroff) + reset = &poweroff; break; case SBI_SRST_RESET_TYPE_COLD_REBOOT: case SBI_SRST_RESET_TYPE_WARM_REBOOT: + if (!is_poweroff) + reset = &reboot; break; } @@ -64,7 +72,7 @@ static void cpld_reset_exec(struct cpld_reset *reset) static int cpld_system_poweroff_check(u32 type, u32 reason) { - if (cpld_reset_get(type)) + if (cpld_reset_get(true, type)) return 128; return 0; @@ -72,34 +80,54 @@ static int cpld_system_poweroff_check(u32 type, u32 reason) static void cpld_system_poweroff(u32 type, u32 reason) { - cpld_reset_exec(cpld_reset_get(type)); + cpld_reset_exec(cpld_reset_get(true, type)); } -static struct sbi_system_reset_device mango_reset_gpio = { +static struct sbi_system_reset_device mango_reset_gpio_poweroff = { .name = "mango-cpld", .system_reset_check = cpld_system_poweroff_check, .system_reset = cpld_system_poweroff }; +static int cpld_system_reboot_check(u32 type, u32 reason) +{ + if (cpld_reset_get(false, type)) + return 128; + + return 0; +} + +static void cpld_system_reboot(u32 type, u32 reason) +{ + cpld_reset_exec(cpld_reset_get(false, type)); +} + +static struct sbi_system_reset_device mango_reset_gpio_reboot = { + .name = "mango-cpld", + .system_reset_check = cpld_system_reboot_check, + .system_reset = cpld_system_reboot +}; + static int mango_cpld_reset_init(void *fdt, int nodeoff, const struct fdt_match *match) { - int rc, len; - const fdt32_t *val; - struct cpld_reset *reset = &poweroff; - const char *dir_prop = "output"; + int rc, len; + const fdt32_t *val; + bool is_poweroff = (ulong)match->data; + struct cpld_reset *reset = (is_poweroff) ? &poweroff : &reboot; + const char *dir_prop = "output"; rc = fdt_gpio_pin_get(fdt, nodeoff, 0, &reset->pin); if (rc) goto out; - if (fdt_getprop(fdt, nodeoff, dir_prop, &len)) { + if (fdt_getprop(fdt, nodeoff, dir_prop, &len)) { rc = gpio_direction_output(&reset->pin, 0); if (rc) goto out; } - val = fdt_getprop(fdt, nodeoff, "active-delay-ms", &len); + val = fdt_getprop(fdt, nodeoff, "active-delay-ms", &len); if (len > 0) reset->active_delay = fdt32_to_cpu(*val); @@ -107,20 +135,33 @@ static int mango_cpld_reset_init(void *fdt, int nodeoff, if (len > 0) reset->inactive_delay = fdt32_to_cpu(*val); - sbi_system_reset_add_device(&mango_reset_gpio); + if (is_poweroff) + sbi_system_reset_add_device(&mango_reset_gpio_poweroff); + else + sbi_system_reset_add_device(&mango_reset_gpio_reboot); out: fdt_del_node(fdt, nodeoff); - return rc; + return rc; } -static const struct fdt_match mango_cpld_reset_match[] = { - { .compatible = "mango,cpld-reset", .data = (void *)true}, +static const struct fdt_match mango_cpld_poweroff_match[] = { + { .compatible = "mango,cpld-poweroff", .data = (void *)true}, { }, }; -struct fdt_reset fdt_reset_sophgo_cpld = { - .match_table = mango_cpld_reset_match, +struct fdt_reset fdt_reset_sophgo_cpld_poweroff = { + .match_table = mango_cpld_poweroff_match, + .init = mango_cpld_reset_init, +}; + +static const struct fdt_match mango_cpld_reboot_match[] = { + { .compatible = "mango,cpld-reboot", .data = (void *)false}, + { }, +}; + +struct fdt_reset fdt_reset_sophgo_cpld_reboot = { + .match_table = mango_cpld_reboot_match, .init = mango_cpld_reset_init, }; \ No newline at end of file diff --git a/lib/utils/reset/fdt_reset_sophgo_wdt.c b/lib/utils/reset/fdt_reset_sophgo_wdt.c index 799eb0bb..55d77130 100644 --- a/lib/utils/reset/fdt_reset_sophgo_wdt.c +++ b/lib/utils/reset/fdt_reset_sophgo_wdt.c @@ -91,7 +91,6 @@ static int mango_wdt_reset_init(void *fdt, int nodeoff, { unsigned long wdt_addr, top_addr; int rc; - // struct device_node *np; rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &wdt_addr, NULL); if (rc < 0 || !wdt_addr) { diff --git a/lib/utils/reset/objects.mk b/lib/utils/reset/objects.mk index a0abf108..7e0c064e 100644 --- a/lib/utils/reset/objects.mk +++ b/lib/utils/reset/objects.mk @@ -23,7 +23,8 @@ libsbiutils-objs-$(CONFIG_FDT_RESET_HTIF) += reset/fdt_reset_htif.o carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_SIFIVE_TEST) += fdt_reset_sifive_test libsbiutils-objs-$(CONFIG_FDT_RESET_SIFIVE_TEST) += reset/fdt_reset_sifive_test.o -carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_SOPHGO_CPLD) += fdt_reset_sophgo_cpld +carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_SOPHGO_CPLD) += fdt_reset_sophgo_cpld_poweroff +carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_SOPHGO_CPLD) += fdt_reset_sophgo_cpld_reboot libsbiutils-objs-$(CONFIG_FDT_RESET_SOPHGO_CPLD) += reset/fdt_reset_sophgo_cpld.o carray-fdt_reset_drivers-$(CONFIG_FDT_RESET_SOPHGO_MCU) += fdt_reset_sophgo_mcu