lib:utils:support pisces's system reboot

pisces system reboot will ecall gpio chip but not watchdog, and pull up cpu gpio5 to tell
CPLD. CPLD will help for cold reboot.
Add the function, gpio chip will pull up gpio16 after chip is probed.

Signed-off-by: chunzhi.lin <chunzhi.lin@sophgo.com>
This commit is contained in:
chunzhi.lin
2023-06-29 11:55:05 +08:00
committed by xingxg2022
parent d21bf89240
commit d06c0a7858
4 changed files with 93 additions and 36 deletions

View File

@@ -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[] = {

View File

@@ -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,
};

View File

@@ -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) {

View File

@@ -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