From 65f05505a6b7e9e1e9b45c9f6aae34fccd7a7f32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Wed, 12 Feb 2020 13:10:23 +0100 Subject: [PATCH] superio/nuvoton/nct5104d: add chip config option to reset GPIOs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define a chip option to explicitly soft reset all enabled GPIOs to default state. TEST=boot FreeBSD 11.2 on PC Engines apu1, change GPIO configuration using nctgpio module and check whether GPIOs are reset after reboot Signed-off-by: Michał Żygowski Change-Id: Iae4205574800138402cbc95f4948167265a80d15 Reviewed-on: https://review.coreboot.org/c/coreboot/+/38850 Tested-by: build bot (Jenkins) Reviewed-by: Felix Held --- src/mainboard/pcengines/apu1/devicetree.cb | 1 + .../apu2/variants/apu2/devicetree.cb | 1 + .../apu2/variants/apu3/devicetree.cb | 1 + .../apu2/variants/apu4/devicetree.cb | 1 + src/superio/nuvoton/nct5104d/chip.h | 1 + src/superio/nuvoton/nct5104d/superio.c | 55 ++++++++++--------- 6 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/mainboard/pcengines/apu1/devicetree.cb b/src/mainboard/pcengines/apu1/devicetree.cb index 4974cfbfbb..dd851a7133 100644 --- a/src/mainboard/pcengines/apu1/devicetree.cb +++ b/src/mainboard/pcengines/apu1/devicetree.cb @@ -41,6 +41,7 @@ chip northbridge/amd/agesa/family14/root_complex device pci 14.3 on # LPC 0x439d chip superio/nuvoton/nct5104d register "irq_trigger_type" = "0" + register "reset_gpios" = "1" device pnp 2e.0 off end device pnp 2e.2 on io 0x60 = 0x3f8 diff --git a/src/mainboard/pcengines/apu2/variants/apu2/devicetree.cb b/src/mainboard/pcengines/apu2/variants/apu2/devicetree.cb index 3528e86362..672155b049 100644 --- a/src/mainboard/pcengines/apu2/variants/apu2/devicetree.cb +++ b/src/mainboard/pcengines/apu2/variants/apu2/devicetree.cb @@ -44,6 +44,7 @@ chip northbridge/amd/pi/00730F01/root_complex device pci 14.3 on # LPC 0x439d chip superio/nuvoton/nct5104d # SIO NCT5104D register "irq_trigger_type" = "0" + register "reset_gpios" = "1" device pnp 2e.0 off end device pnp 2e.2 on io 0x60 = 0x3f8 diff --git a/src/mainboard/pcengines/apu2/variants/apu3/devicetree.cb b/src/mainboard/pcengines/apu2/variants/apu3/devicetree.cb index 13643a42c0..d743da6b66 100644 --- a/src/mainboard/pcengines/apu2/variants/apu3/devicetree.cb +++ b/src/mainboard/pcengines/apu2/variants/apu3/devicetree.cb @@ -44,6 +44,7 @@ chip northbridge/amd/pi/00730F01/root_complex device pci 14.3 on # LPC 0x439d chip superio/nuvoton/nct5104d # SIO NCT5104D register "irq_trigger_type" = "0" + register "reset_gpios" = "1" device pnp 2e.0 off end device pnp 2e.2 on io 0x60 = 0x3f8 diff --git a/src/mainboard/pcengines/apu2/variants/apu4/devicetree.cb b/src/mainboard/pcengines/apu2/variants/apu4/devicetree.cb index f5082d466f..c08e5b24e2 100644 --- a/src/mainboard/pcengines/apu2/variants/apu4/devicetree.cb +++ b/src/mainboard/pcengines/apu2/variants/apu4/devicetree.cb @@ -44,6 +44,7 @@ chip northbridge/amd/pi/00730F01/root_complex device pci 14.3 on # LPC 0x439d chip superio/nuvoton/nct5104d # SIO NCT5104D register "irq_trigger_type" = "0" + register "reset_gpios" = "1" device pnp 2e.0 off end device pnp 2e.2 on io 0x60 = 0x3f8 diff --git a/src/superio/nuvoton/nct5104d/chip.h b/src/superio/nuvoton/nct5104d/chip.h index 5b790372ad..ad1c302d21 100644 --- a/src/superio/nuvoton/nct5104d/chip.h +++ b/src/superio/nuvoton/nct5104d/chip.h @@ -6,6 +6,7 @@ struct superio_nuvoton_nct5104d_config { u8 irq_trigger_type; + u8 reset_gpios; }; #endif diff --git a/src/superio/nuvoton/nct5104d/superio.c b/src/superio/nuvoton/nct5104d/superio.c index e49a7cbda5..55700261e1 100644 --- a/src/superio/nuvoton/nct5104d/superio.c +++ b/src/superio/nuvoton/nct5104d/superio.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* This file is part of the coreboot project. */ +#include #include #include #include @@ -98,42 +99,45 @@ static void route_pins_to_uart(struct device *dev, bool to_uart) static void reset_gpio_default_in(struct device *dev) { pnp_set_logical_device(dev); - - /* Soft reset GPIOs to default state: IN */ - switch (dev->path.pnp.device) { - case NCT5104D_GPIO0: - pnp_write_config(dev, NCT5104D_GPIO0_IO, 0xFF); - break; - case NCT5104D_GPIO1: - pnp_write_config(dev, NCT5104D_GPIO1_IO, 0xFF); - break; - case NCT5104D_GPIO6: - pnp_write_config(dev, NCT5104D_GPIO6_IO, 0xFF); - break; - default: - break; - } + /* + * Soft reset GPIOs to default state: IN. + * The main GPIO LDN holds registers that configure the pins as output + * or input. These registers are located at offset 0xE0 plus the GPIO + * bank number multiplied by 4: 0xE0 for GPIO0, 0xE4 for GPIO1 and + * 0xF8 for GPIO6. + */ + pnp_write_config(dev, NCT5104D_GPIO0_IO + (dev->path.pnp.device >> 8) * 4, 0xFF); } static void reset_gpio_default_od(struct device *dev) { struct device *gpio0, *gpio1, *gpio6; + pnp_set_logical_device(dev); + gpio0 = dev_find_slot_pnp(dev->path.pnp.port, NCT5104D_GPIO0); gpio1 = dev_find_slot_pnp(dev->path.pnp.port, NCT5104D_GPIO1); gpio6 = dev_find_slot_pnp(dev->path.pnp.port, NCT5104D_GPIO6); - pnp_set_logical_device(dev); - - /* Soft reset GPIOs to default state: Open-drain */ + /* + * Soft reset GPIOs to default state: Open-drain. + * The NCT5104D_GPIO_PP_OD LDN holds registers (1 for each GPIO bank) + * that configure each GPIO pin to be open dain or push pull. System + * reset is known to not reset the values in this register. The + * registers are located at offsets begginign from 0xE0 plus GPIO bank + * number, i.e. 0xE0 for GPIO0, 0xE1 for GPIO1 and 0xE6 for GPIO6. + */ if (gpio0 && gpio0->enabled) - pnp_write_config(dev, NCT5104D_GPIO0_PP_OD, 0xFF); + pnp_write_config(dev, + (gpio0->path.pnp.device >> 8) + NCT5104D_GPIO0_PP_OD, 0xFF); if (gpio1 && gpio1->enabled) - pnp_write_config(dev, NCT5104D_GPIO1_PP_OD, 0xFF); + pnp_write_config(dev, + (gpio1->path.pnp.device >> 8) + NCT5104D_GPIO0_PP_OD, 0xFF); if (gpio6 && gpio6->enabled) - pnp_write_config(dev, NCT5104D_GPIO6_PP_OD, 0xFF); + pnp_write_config(dev, + (gpio6->path.pnp.device >> 8) + NCT5104D_GPIO0_PP_OD, 0xFF); } static void disable_gpio_io_port(struct device *dev) @@ -181,13 +185,14 @@ static void nct5104d_init(struct device *dev) case NCT5104D_GPIO0: case NCT5104D_GPIO1: route_pins_to_uart(dev, false); - reset_gpio_default_in(dev); - break; + /* FALLTHROUGH */ case NCT5104D_GPIO6: - reset_gpio_default_in(dev); + if (conf->reset_gpios) + reset_gpio_default_in(dev); break; case NCT5104D_GPIO_PP_OD: - reset_gpio_default_od(dev); + if (conf->reset_gpios) + reset_gpio_default_od(dev); break; case NCT5104D_GPIO_IO: disable_gpio_io_port(dev);