summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/superio/ite/Makefile.mk4
-rw-r--r--src/superio/ite/common/Kconfig27
-rw-r--r--src/superio/ite/common/gpio.c191
-rw-r--r--src/superio/ite/common/ite_gpio.h75
4 files changed, 297 insertions, 0 deletions
diff --git a/src/superio/ite/Makefile.mk b/src/superio/ite/Makefile.mk
index 678ea95203..afbce8a527 100644
--- a/src/superio/ite/Makefile.mk
+++ b/src/superio/ite/Makefile.mk
@@ -4,11 +4,15 @@
bootblock-$(CONFIG_SUPERIO_ITE_COMMON_PRE_RAM) += common/early_serial.c
romstage-$(CONFIG_SUPERIO_ITE_COMMON_PRE_RAM) += common/early_serial.c
+bootblock-$(CONFIG_SUPERIO_ITE_COMMON_GPIO_PRE_RAM) += common/gpio.c
+romstage-$(CONFIG_SUPERIO_ITE_COMMON_GPIO_PRE_RAM) += common/gpio.c
+
## include generic ite environment controller driver
ramstage-$(CONFIG_SUPERIO_ITE_ENV_CTRL) += common/env_ctrl.c
## include generic ite driver to smm to control S3-relevant functions
smm-$(CONFIG_SUPERIO_ITE_COMMON_PRE_RAM) += common/early_serial.c
+smm-$(CONFIG_SUPERIO_ITE_COMMON_GPIO_PRE_RAM) += common/gpio.c
subdirs-y += it8528e
subdirs-y += it8613e
diff --git a/src/superio/ite/common/Kconfig b/src/superio/ite/common/Kconfig
index 4701056bfa..c5eeec6c87 100644
--- a/src/superio/ite/common/Kconfig
+++ b/src/superio/ite/common/Kconfig
@@ -5,6 +5,33 @@
config SUPERIO_ITE_COMMON_PRE_RAM
bool
+config SUPERIO_ITE_COMMON_GPIO_PRE_RAM
+ bool
+ help
+ Enable generic pre-ram driver for configuring ITE SIO GPIOs.
+ It applies only to ITE SIOs not ITE ECs using LDN 7 (typically)
+ to configure GPIO Simple I/O mode.
+
+if SUPERIO_ITE_COMMON_GPIO_PRE_RAM
+
+config SUPERIO_ITE_COMMON_NUM_GPIO_SETS
+ int
+ help
+ The maximum number of GPIO sets supported by ITE SIO chip.
+ Each SIO chip must set this config option to a proper values
+ if it intends to enable SUPERIO_ITE_COMMON_GPIO_PRE_RAM.
+
+config SUPERIO_ITE_COMMON_GPIO_LED_FREQ_5BIT
+ bool
+ default n
+ help
+ Selected ITE SIOs control the GPIO LED frequency using 5 bits
+ instead of two. The LED register layout is also different for
+ these chips. Select this if the SIO GP LED Frequency control
+ field has 5 bits and support duty cycle as well.
+
+endif
+
# Generic ITE environment controller driver
config SUPERIO_ITE_ENV_CTRL
bool
diff --git a/src/superio/ite/common/gpio.c b/src/superio/ite/common/gpio.c
new file mode 100644
index 0000000000..11c02ba1c8
--- /dev/null
+++ b/src/superio/ite/common/gpio.c
@@ -0,0 +1,191 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <device/pnp_ops.h>
+#include <device/pnp.h>
+#include <stdint.h>
+
+#include "ite.h"
+#include "ite_gpio.h"
+
+/* Catch ITE SIOs that enable the driver but do not configure the number of sets */
+#if CONFIG_SUPERIO_ITE_COMMON_NUM_GPIO_SETS == 0
+#error "Maximum number of ITE SIO GPIO sets not provided"
+#endif
+
+#if CONFIG_SUPERIO_ITE_COMMON_NUM_GPIO_SETS > 10
+#error "ITE SIO GPIO drivers only support up to 10 GPIO sets"
+#endif
+
+/* GPIO Polarity Select: 1: Inverting, 0: Non-inverting */
+#define ITE_GPIO_REG_POLARITY(x) \
+ (((x) > 8) ? (0xd1 + ((x) - 9) * 5) \
+ : (0xb0 + ((x) - 1)) \
+ )
+
+/* GPIO Internal Pull-up: 1: Enable, 0: Disable */
+#define ITE_GPIO_REG_PULLUP(x) \
+ (((x) > 8) ? (0xd4 + ((x) - 9) * 5) \
+ : (0xb8 + ((x) - 1)) \
+ )
+
+/* GPIO Function Select: 1: Simple I/O, 0: Alternate function */
+#define ITE_GPIO_REG_FN_SELECT(x) \
+ (((x) > 8) ? (0xd3 + ((x) - 9) * 5) \
+ : (0xc0 + ((x) - 1)) \
+ )
+
+/* GPIO Mode: 0: input mode, 1: output mode */
+#define ITE_GPIO_REG_OUTPUT(x) \
+ (((x) > 8) ? (0xd2 + ((x) - 9) * 5) \
+ : (0xc8 + ((x) - 1)) \
+ )
+
+/* GPIO LED pin mapping register */
+#define ITE_GPIO_REG_LED_PINMAP(x) (0xf8 + ((x) & 1) * 2)
+#define ITE_GPIO_LED_PIN_LOC(set, pin) ((((set) & 7) << 3) | ((pin) & 7))
+#define ITE_GPIO_LED_PIN_LOC_MASK 0x3f
+/* GPIO LED control register */
+#define ITE_GPIO_REG_LED_CONTROL(x) (0xf9 + ((x) & 1) * 2)
+#define ITE_GPIO_LED_OUTPUT_LOW (1 << 0)
+#define ITE_GPIO_LED_PINMAP_CLEAR (1 << 4)
+#define ITE_GPIO_LED_SHORT_LOW_PULSE \
+ (CONFIG(SUPERIO_ITE_COMMON_GPIO_LED_FREQ_5BIT) ? (1 << 5) \
+ : (1 << 3) \
+ )
+#define ITE_GPIO_LED_FREQ_SEL(x) \
+ (CONFIG(SUPERIO_ITE_COMMON_GPIO_LED_FREQ_5BIT) \
+ ? ((((x) & 0x18) << 3) | (((x) & 0x7) << 1)) \
+ : (((x) & 0x3) << 1) \
+ )
+#define ITE_GPIO_LED_FREQ_SEL_MASK \
+ (CONFIG(SUPERIO_ITE_COMMON_GPIO_LED_FREQ_5BIT) ? 0xce : 0x06)
+
+static bool ite_has_gpio_fn_select_reg(u8 set)
+{
+ /* IT8718F has all registers for all sets. */
+ if (CONFIG(SUPERIO_ITE_IT8718F))
+ return true;
+
+ /* Typically ITE GPIO sets 6 to 8 don't have enable and polarity registers. */
+ if (set < 6 || set > 8)
+ return true;
+
+ return false;
+}
+
+static bool ite_has_gpio_polarity_reg(u8 set)
+{
+ /* IT8718F has all registers for all sets. */
+ if (CONFIG(SUPERIO_ITE_IT8718F))
+ return true;
+
+ /* IT8720F/IT8721F has polarity register for all GPIO sets */
+ if (CONFIG(SUPERIO_ITE_IT8720F) || CONFIG(SUPERIO_ITE_IT8721F))
+ return true;
+
+ /* Typically ITE GPIO sets 6 to 8 don't have enable and polarity registers. */
+ if (set < 6 || set > 8)
+ return true;
+
+ return false;
+}
+
+static bool ite_has_gpio_pullup_reg(u8 set)
+{
+ /* IT8718F/IT8720F does not have pull-up register for set 2 */
+ if ((CONFIG(SUPERIO_ITE_IT8718F) || CONFIG(SUPERIO_ITE_IT8720F)) && (set == 2))
+ return false;
+
+ /* IT8783E/F does not have pull-up register for set 6 */
+ if (CONFIG(SUPERIO_ITE_IT8783EF) && (set == 6))
+ return false;
+
+ /*
+ * ITE GPIO Sets 7 and 8 don't have a pullup register.
+ * See IT8786/IT8625 datasheet section 8.10.10.
+ * Also applies to IT8728F.
+ */
+ if (set != 7 && set != 8)
+ return true;
+
+ return false;
+}
+
+/*
+ * Configures a single GPIO given its number as gpio_num, direction ("in_out"
+ * parameter) and properties, such as polarity and pull ("gpio_ctrl"
+ * parameter). The "enable" parameter can configure the GPIO in Simple I/O
+ * mode when set or Alternate function mode when clear. Some chips may also
+ * not support configuring all properties for a particular GPIO. It is left to
+ * the implementer to check if GPIO settings are valid for given gpio_num.
+ */
+void ite_gpio_setup(pnp_devfn_t gpiodev, u8 gpio_num, enum ite_gpio_direction in_out,
+ enum ite_gpio_mode enable, u8 gpio_ctrl)
+{
+ u8 set = (gpio_num / 10);
+ u8 pin = (gpio_num % 10);
+
+ /* Number of configurable sets is chip dependent, 8 pins each */
+ if (gpio_num < 10 || set > CONFIG_SUPERIO_ITE_COMMON_NUM_GPIO_SETS || pin > 7)
+ return;
+
+ pnp_enter_conf_state(gpiodev);
+ pnp_set_logical_device(gpiodev);
+
+ if (ite_has_gpio_fn_select_reg(set))
+ pnp_unset_and_set_config(gpiodev, ITE_GPIO_REG_FN_SELECT(set),
+ 1 << pin, (enable & 1) << pin);
+
+ if (ite_has_gpio_polarity_reg(set))
+ pnp_unset_and_set_config(gpiodev, ITE_GPIO_REG_POLARITY(set),
+ 1 << pin,
+ (gpio_ctrl & ITE_GPIO_POL_INVERT) ? 1 << pin : 0);
+
+
+ pnp_unset_and_set_config(gpiodev, ITE_GPIO_REG_OUTPUT(set), 1 << pin, (in_out & 1) << pin);
+
+ if (ite_has_gpio_pullup_reg(set))
+ pnp_unset_and_set_config(gpiodev, ITE_GPIO_REG_PULLUP(set), 1 << pin,
+ (gpio_ctrl & ITE_GPIO_PULLUP_ENABLE) ? 1 << pin : 0);
+
+ pnp_exit_conf_state(gpiodev);
+}
+
+void ite_gpio_setup_led(pnp_devfn_t gpiodev, u8 gpio_num,
+ enum ite_gpio_led led_no,
+ enum ite_led_frequency freq,
+ u8 led_ctrl)
+{
+ u8 set = (gpio_num / 10);
+ u8 pin = (gpio_num % 10);
+ u8 reg = 0;
+
+ /* Number of configurable sets is chip dependent, 8 pins each */
+ if (gpio_num < 10 || set > CONFIG_SUPERIO_ITE_COMMON_NUM_GPIO_SETS || pin > 7)
+ return;
+
+ /* LED is available only for GPIO sets 1-5 */
+ if (set > 5)
+ return;
+
+ pnp_enter_conf_state(gpiodev);
+ pnp_set_logical_device(gpiodev);
+
+ /* Pinmap clear bit is only available when frequency is controlled with 5 bits */
+ if (CONFIG(SUPERIO_ITE_COMMON_GPIO_LED_FREQ_5BIT) && (led_ctrl & ITE_LED_PINMAP_CLEAR))
+ reg |= ITE_GPIO_LED_PINMAP_CLEAR;
+
+ if (led_ctrl & ITE_LED_OUTPUT_LOW)
+ reg |= ITE_GPIO_LED_OUTPUT_LOW;
+
+ if (led_ctrl & ITE_LED_SHORT_LOW_PULSE)
+ reg |= ITE_GPIO_LED_SHORT_LOW_PULSE;
+
+ reg |= ITE_GPIO_LED_FREQ_SEL(freq);
+ pnp_write_config(gpiodev, ITE_GPIO_REG_LED_CONTROL(led_no), reg);
+
+ reg = ITE_GPIO_LED_PIN_LOC(set, pin);
+ pnp_write_config(gpiodev, ITE_GPIO_REG_LED_PINMAP(led_no), reg);
+
+ pnp_exit_conf_state(gpiodev);
+}
diff --git a/src/superio/ite/common/ite_gpio.h b/src/superio/ite/common/ite_gpio.h
new file mode 100644
index 0000000000..ca1b209953
--- /dev/null
+++ b/src/superio/ite/common/ite_gpio.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef SUPERIO_ITE_COMMON_GPIO_PRE_RAM_H
+#define SUPERIO_ITE_COMMON_GPIO_PRE_RAM_H
+
+#include <device/pnp_type.h>
+#include <stdint.h>
+
+#define ITE_GPIO_REG_SELECT(x) (0x25 + (x))
+
+enum ite_gpio_control {
+ ITE_GPIO_CONTROL_DEFAULT = 0,
+ ITE_GPIO_POL_INVERT = (1 << 0),
+ ITE_GPIO_PULLUP_ENABLE = (1 << 1),
+};
+
+enum ite_gpio_direction {
+ ITE_GPIO_INPUT,
+ ITE_GPIO_OUTPUT
+};
+
+enum ite_gpio_mode {
+ ITE_GPIO_ALT_FN_MODE,
+ ITE_GPIO_SIMPLE_IO_MODE
+};
+
+/* There are two GP LED blink register sets */
+enum ite_gpio_led {
+ ITE_GPIO_LED_1,
+ ITE_GPIO_LED_2
+};
+
+enum ite_led_control {
+ ITE_LED_CONTROL_DEFAULT = 0,
+ ITE_LED_SHORT_LOW_PULSE = (1 << 0),
+ ITE_LED_OUTPUT_LOW = (1 << 1),
+ /*
+ * Only for ITE SIOs with 5-bit frequency selection.
+ * When enabled, the LED pin mapping register is cleared when PANSWH# is low for over 4s.
+ */
+ ITE_LED_PINMAP_CLEAR = (1 << 2),
+};
+
+enum ite_led_frequency {
+ /* Most ITE SIOs have 2-bit frequency selection */
+ ITE_LED_FREQ_4HZ = 0,
+ ITE_LED_FREQ_1HZ = 1,
+ ITE_LED_FREQ_0P25HZ = 2,
+ ITE_LED_FREQ_0P125HZ = 3,
+ /* ITE SIOs with 5-bit frequency selection: IT8625, IT8613 */
+ ITE_LED_FREQ_4HZ_DUTY_50 = 0,
+ ITE_LED_FREQ_1HZ_DUTY_50 = 1,
+ ITE_LED_FREQ_0P25HZ_DUTY_50 = 2,
+ ITE_LED_FREQ_2HZ_DUTY_50 = 3,
+ ITE_LED_FREQ_0P25HZ_DUTY_25 = 4,
+ ITE_LED_FREQ_0P25HZ_DUTY_75 = 5,
+ ITE_LED_FREQ_0P125HZ_DUTY_25 = 6,
+ ITE_LED_FREQ_0P125HZ_DUTY_75 = 7,
+ ITE_LED_FREQ_0P4HZ_DUTY_20 = 8,
+ ITE_LED_FREQ_0P5HZ_DUTY_50 = 16,
+ ITE_LED_FREQ_0P125HZ_DUTY_50 = 24,
+};
+
+void ite_gpio_setup(pnp_devfn_t gpiodev, u8 gpio_num,
+ enum ite_gpio_direction output,
+ enum ite_gpio_mode enable,
+ u8 gpio_ctrl);
+
+void ite_gpio_setup_led(pnp_devfn_t gpiodev, u8 gpio_num,
+ enum ite_gpio_led led_no,
+ enum ite_led_frequency freq,
+ u8 led_ctrl);
+
+
+#endif /* SUPERIO_ITE_COMMON_PRE_RAM_H */