summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2013-08-02 14:28:43 -0700
committerDave Parker <dparker@chromium.org>2013-08-13 16:42:16 -0700
commite8191bc0eafdf8387767c05f7ca0a5134987dd07 (patch)
tree49f733a4b2fa327c17d6e478ce776e44481193b6
parent67307c572a7f6a9687a364c1e83480b7f7933aec (diff)
downloadchrome-ec-e8191bc0eafdf8387767c05f7ca0a5134987dd07.tar.gz
CHERRY-PICK:Clean up configuring GPIO alternate functions
GPIO alternate functions used to be configured throughout the code, which made it hard to tell which ones you needed to configure yourself in board.c. It also sometimes (chip/lm4/i2c.c) led to GPIOs being configured as alternate functions even if they weren't used on a given board. With this change, every board has a table in board.c which lists ALL GPIOs which have alternate functions. This is now the only place where alternate functions are configured. Each module then calls gpio_init_module() to set up its GPIOs. This also fixes a bug where gpio_set_flags() ignored most of the flags passed to it (only direction and level were actually used). On stm32f, gpio_set_alternate() does not exist, and pins are configured via direct register writes from board.c. Rather than attempt to change that in the same CL, I've stubbed out gpio_set_alternate() for stm32f, and will fix the register writes in a follow-up CL. BUG=chrome-os-partner:21618 BRANCH=peppy (fixes I2C1 being initialized even though those pins are used for other things) TEST=boot link, falco, pit, spring Original-Change-Id: I40f47025d8f767e0723c6b40c80413af9ba8deba Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/64400 Conflicts: board/kirby/board.c board/kirby/board.h board/pit/board.c chip/stm32/gpio-stm32f.c Change-Id: I14d07af1bb6017d53099b4d0973e44336a3b17e4 Reviewed-on: https://gerrit.chromium.org/gerrit/65768 Reviewed-by: Dave Parker <dparker@chromium.org> Tested-by: Dave Parker <dparker@chromium.org>
-rw-r--r--board/bds/board.c13
-rw-r--r--board/bds/board.h13
-rw-r--r--board/bolt/board.c37
-rw-r--r--board/bolt/board.h16
-rw-r--r--board/daisy/board.c20
-rw-r--r--board/daisy/board.h9
-rw-r--r--board/falco/board.c27
-rw-r--r--board/falco/board.h15
-rw-r--r--board/host/board.c5
-rw-r--r--board/host/board.h6
-rw-r--r--board/link/board.c37
-rw-r--r--board/link/board.h19
-rw-r--r--board/mccroskey/board.c9
-rw-r--r--board/mccroskey/board.h7
-rw-r--r--board/peppy/board.c25
-rw-r--r--board/peppy/board.h15
-rw-r--r--board/pit/board.c9
-rw-r--r--board/pit/board.h10
-rw-r--r--board/puppy/board.c21
-rw-r--r--board/puppy/board.h10
-rw-r--r--board/slippy/board.c25
-rw-r--r--board/slippy/board.h15
-rw-r--r--board/snow/board.c9
-rw-r--r--board/snow/board.h8
-rw-r--r--board/spring/board.c9
-rw-r--r--board/spring/board.h7
-rw-r--r--board/wolf/board.c25
-rw-r--r--board/wolf/board.h15
-rw-r--r--chip/host/gpio.c11
-rw-r--r--chip/lm4/gpio.c80
-rw-r--r--chip/lm4/i2c.c26
-rw-r--r--chip/lm4/lpc.c16
-rw-r--r--chip/lm4/peci.c17
-rw-r--r--chip/lm4/pwm_fan.c2
-rw-r--r--chip/lm4/pwm_kblight.c2
-rw-r--r--chip/lm4/registers.h17
-rw-r--r--chip/lm4/spi.c6
-rw-r--r--chip/lm4/uart.c25
-rw-r--r--chip/stm32/gpio-stm32f.c35
-rw-r--r--chip/stm32/gpio-stm32l.c28
-rw-r--r--chip/stm32/i2c-stm32l.c3
-rw-r--r--chip/stm32/power_led.c7
-rw-r--r--chip/stm32/spi.c4
-rw-r--r--chip/stm32/uart.c4
-rw-r--r--common/gpio_common.c28
-rw-r--r--include/config.h5
-rw-r--r--include/gpio.h97
-rw-r--r--include/pwm.h10
48 files changed, 533 insertions, 326 deletions
diff --git a/board/bds/board.c b/board/bds/board.c
index 830b8fcf41..915679d4c3 100644
--- a/board/bds/board.c
+++ b/board/bds/board.c
@@ -41,10 +41,19 @@ BUILD_ASSERT(ARRAY_SIZE(i2c_ports) == I2C_PORTS_USED);
/* GPIO signal list. Must match order from enum gpio_signal. */
const struct gpio_info gpio_list[] = {
- {"RECOVERYn", LM4_GPIO_D, (1<<1), GPIO_PULL_UP, NULL},
- {"DEBUG_LED", LM4_GPIO_A, (1<<7), GPIO_OUT_LOW, NULL},
+ {"RECOVERYn", GPIO_D, (1<<1), GPIO_PULL_UP, NULL},
+ {"DEBUG_LED", GPIO_A, (1<<7), GPIO_OUT_LOW, NULL},
/* Unimplemented signals which we need to emulate for now */
GPIO_SIGNAL_NOT_IMPLEMENTED("WP"),
GPIO_SIGNAL_NOT_IMPLEMENTED("ENTERING_RW"),
};
BUILD_ASSERT(ARRAY_SIZE(gpio_list) == GPIO_COUNT);
+
+/* Pins with alternate functions */
+const struct gpio_alt_func gpio_alt_funcs[] = {
+ {GPIO_A, 0x03, 1, MODULE_UART}, /* UART0 */
+ {GPIO_G, 0x40, 3, MODULE_I2C}, /* I2C5 SCL */
+ {GPIO_G, 0x80, 3, GPIO_OPEN_DRAIN}, /* I2C5 SDA */
+ {GPIO_B, 0x03, 1, MODULE_UART}, /* UART1 */
+};
+const int gpio_alt_funcs_count = ARRAY_SIZE(gpio_alt_funcs);
diff --git a/board/bds/board.h b/board/bds/board.h
index 61c7c5a7f9..9d4672a34d 100644
--- a/board/bds/board.h
+++ b/board/bds/board.h
@@ -27,8 +27,14 @@
#ifndef __ASSEMBLER__
-enum adc_channel
-{
+/* Module IDs */
+/* TODO(rspangler): use this in place of enum console_channel as well */
+enum module_id {
+ MODULE_I2C,
+ MODULE_UART,
+};
+
+enum adc_channel {
ADC_CH_EC_TEMP = 0, /* EC internal die temperature in degrees K. */
ADC_CH_BDS_POT, /* BDS pot input. */
ADC_CH_COUNT
@@ -39,9 +45,8 @@ enum adc_channel
/* Number of I2C ports used */
#define I2C_PORTS_USED 1
-/* GPIOs for second UART port */
+/* Second UART port */
#define CONFIG_UART_HOST 1
-#define CONFIG_UART_HOST_GPIOS_PB0_1
/* GPIO signal list */
enum gpio_signal {
diff --git a/board/bolt/board.c b/board/bolt/board.c
index c567749bff..df104627ad 100644
--- a/board/bolt/board.c
+++ b/board/bolt/board.c
@@ -126,6 +126,25 @@ const struct gpio_info gpio_list[] = {
};
BUILD_ASSERT(ARRAY_SIZE(gpio_list) == GPIO_COUNT);
+/* Pins with alternate functions */
+const struct gpio_alt_func gpio_alt_funcs[] = {
+ {GPIO_A, 0x03, 1, MODULE_UART}, /* UART0 */
+ {GPIO_A, 0x40, 3, MODULE_I2C}, /* I2C1 SCL */
+ {GPIO_A, 0x80, 3, MODULE_I2C, GPIO_OPEN_DRAIN}, /* I2C1 SDA */
+ {GPIO_B, 0x04, 3, MODULE_I2C}, /* I2C0 SCL */
+ {GPIO_B, 0x08, 3, MODULE_I2C, GPIO_OPEN_DRAIN}, /* I2C0 SDA */
+ {GPIO_B, 0x40, 3, MODULE_I2C}, /* I2C5 SCL */
+ {GPIO_B, 0x80, 3, MODULE_I2C, GPIO_OPEN_DRAIN}, /* I2C5 SDA */
+ {GPIO_G, 0x30, 1, MODULE_UART}, /* UART2 */
+ {GPIO_J, 0x40, 1, MODULE_PECI}, /* PECI Tx */
+ {GPIO_J, 0x80, 0, MODULE_PECI, GPIO_ANALOG}, /* PECI Rx */
+ {GPIO_L, 0x3f, 15, MODULE_LPC}, /* LPC */
+ {GPIO_M, 0x33, 15, MODULE_LPC}, /* LPC */
+ {GPIO_N, 0x0c, 1, MODULE_PWM_FAN}, /* Fan0 PWM/tach */
+ {GPIO_N, 0x40, 1, MODULE_PWM_KBLIGHT}, /* Fan1 PWM */
+};
+const int gpio_alt_funcs_count = ARRAY_SIZE(gpio_alt_funcs);
+
/* x86 signal list. Must match order of enum x86_signal. */
const struct x86_signal_info x86_signal_list[] = {
{GPIO_PP5000_PGOOD, 1, "PGOOD_PP5000"},
@@ -192,15 +211,6 @@ struct keyboard_scan_config keyscan_config = {
};
/**
- * Configure the GPIOs for the pwm module.
- */
-void configure_fan_gpios(void)
-{
- /* PN2:3 alternate function 1 = channel 0 PWM/tach */
- gpio_set_alternate_function(LM4_GPIO_N, 0x0c, 1);
-}
-
-/**
* Perform necessary actions on host wake events.
*/
void board_process_wake_events(uint32_t active_wake_events)
@@ -216,12 +226,3 @@ void board_process_wake_events(uint32_t active_wake_events)
else
gpio_set_level(GPIO_PCH_WAKE_L, 1);
}
-
-/**
- * Configure the GPIOs for the pwm module.
- */
-void configure_kblight_gpios(void)
-{
- /* PN6 alternate function 1 = channel 4 PWM */
- gpio_set_alternate_function(LM4_GPIO_N, 0x40, 1);
-}
diff --git a/board/bolt/board.h b/board/bolt/board.h
index 36e274011d..8de07f2bff 100644
--- a/board/bolt/board.h
+++ b/board/bolt/board.h
@@ -44,6 +44,7 @@
#define CONFIG_PWM_FAN
#define CONFIG_PWM_KBLIGHT
#define CONFIG_TEMP_SENSOR
+#define CONFIG_UART_HOST 2
#define CONFIG_WIRELESS
#if 0
#define CONFIG_USB_PORT_POWER_DUMB
@@ -52,6 +53,17 @@
#ifndef __ASSEMBLER__
+/* Module IDs */
+/* TODO(rspangler): use this in place of enum console_channel as well */
+enum module_id {
+ MODULE_I2C,
+ MODULE_LPC,
+ MODULE_PECI,
+ MODULE_PWM_FAN,
+ MODULE_PWM_KBLIGHT,
+ MODULE_UART,
+};
+
/* PWM channels */
#define FAN_CH_CPU 2 /* CPU fan */
#define FAN_CH_KBLIGHT 4 /* Keyboard backlight */
@@ -75,10 +87,6 @@
/* USB ports */
#define USB_PORT_COUNT 2
-/* GPIOs for second UART port */
-#define CONFIG_UART_HOST 2
-#define CONFIG_UART_HOST_GPIOS_PG4_5
-
/* GPIO signal definitions. */
enum gpio_signal {
/* Inputs with interrupt handlers are first for efficiency */
diff --git a/board/daisy/board.c b/board/daisy/board.c
index 39eda5e549..2a6eb6e3a5 100644
--- a/board/daisy/board.c
+++ b/board/daisy/board.c
@@ -101,6 +101,14 @@ const struct gpio_info gpio_list[] = {
};
BUILD_ASSERT(ARRAY_SIZE(gpio_list) == GPIO_COUNT);
+/* Pins with alternate functions */
+const struct gpio_alt_func gpio_alt_funcs[] = {
+ {GPIO_A, 0x0004, GPIO_ALT_TIM2, MODULE_POWER_LED},
+ {GPIO_A, 0x0600, GPIO_ALT_USART, MODULE_UART},
+ {GPIO_B, 0x0cc0, GPIO_ALT_I2C, MODULE_I2C},
+};
+const int gpio_alt_funcs_count = ARRAY_SIZE(gpio_alt_funcs);
+
/* Battery temperature ranges in degrees C */
const struct battery_temperature_ranges bat_temp_ranges = {
.start_charging_min_c = 5,
@@ -158,18 +166,6 @@ int board_i2c_host_port(void)
}
#endif /* CONFIG_I2C_HOST_AUTO */
-void board_config_post_gpio_init(void)
-{
- /* I2C SCL/SDA on PB10-11 and PB6-7 */
- gpio_set_alternate_function(GPIO_B, (1<<11) |
- (1<<10) |
- (1<<7) |
- (1<<6), GPIO_ALT_I2C);
-
- /* Select Alternate function for USART1 on pins PA9/PA10 */
- gpio_set_alternate_function(GPIO_A, (1<<9) | (1<<10), GPIO_ALT_USART);
-}
-
void keyboard_suppress_noise(void)
{
/* notify audio codec of keypress for noise suppression */
diff --git a/board/daisy/board.h b/board/daisy/board.h
index a76735a4f2..c2af3ef525 100644
--- a/board/daisy/board.h
+++ b/board/daisy/board.h
@@ -13,7 +13,6 @@
/* Optional features */
#define CONFIG_BATTERY_SMART
-#define CONFIG_BOARD_POST_GPIO_INIT
#define CONFIG_CHARGER_TPS65090
#ifdef HAS_TASK_CHIPSET
#define CONFIG_CHIPSET_GAIA
@@ -37,6 +36,14 @@
#ifndef __ASSEMBLER__
+/* Module IDs */
+/* TODO(rspangler): use this in place of enum console_channel as well */
+enum module_id {
+ MODULE_I2C,
+ MODULE_POWER_LED,
+ MODULE_UART,
+};
+
/* By default, enable all console messages except keyboard */
#define CC_DEFAULT (CC_ALL & ~CC_MASK(CC_KEYSCAN))
diff --git a/board/falco/board.c b/board/falco/board.c
index 3b9a197584..acb601b917 100644
--- a/board/falco/board.c
+++ b/board/falco/board.c
@@ -125,6 +125,24 @@ const struct gpio_info gpio_list[] = {
};
BUILD_ASSERT(ARRAY_SIZE(gpio_list) == GPIO_COUNT);
+/* Pins with alternate functions */
+const struct gpio_alt_func gpio_alt_funcs[] = {
+ {GPIO_A, 0x03, 1, MODULE_UART}, /* UART0 */
+ {GPIO_A, 0x40, 3, MODULE_I2C}, /* I2C1 SCL */
+ {GPIO_A, 0x80, 3, MODULE_I2C, GPIO_OPEN_DRAIN}, /* I2C1 SDA */
+ {GPIO_B, 0x04, 3, MODULE_I2C}, /* I2C0 SCL */
+ {GPIO_B, 0x08, 3, MODULE_I2C, GPIO_OPEN_DRAIN}, /* I2C0 SDA */
+ {GPIO_B, 0x40, 3, MODULE_I2C}, /* I2C5 SCL */
+ {GPIO_B, 0x80, 3, MODULE_I2C, GPIO_OPEN_DRAIN}, /* I2C5 SDA */
+ {GPIO_G, 0x30, 1, MODULE_UART}, /* UART2 */
+ {GPIO_J, 0x40, 1, MODULE_PECI}, /* PECI Tx */
+ {GPIO_J, 0x80, 0, MODULE_PECI, GPIO_ANALOG}, /* PECI Rx */
+ {GPIO_L, 0x3f, 15, MODULE_LPC}, /* LPC */
+ {GPIO_M, 0x33, 15, MODULE_LPC}, /* LPC */
+ {GPIO_N, 0x0c, 1, MODULE_PWM_FAN}, /* Fan0 PWM/tach */
+};
+const int gpio_alt_funcs_count = ARRAY_SIZE(gpio_alt_funcs);
+
/* x86 signal list. Must match order of enum x86_signal. */
const struct x86_signal_info x86_signal_list[] = {
{GPIO_PP5000_PGOOD, 1, "PGOOD_PP5000"},
@@ -195,15 +213,6 @@ struct keyboard_scan_config keyscan_config = {
};
/**
- * Configure the GPIOs for the pwm module.
- */
-void configure_fan_gpios(void)
-{
- /* PN2:3 alternate function 1 = channel 0 PWM/tach */
- gpio_set_alternate_function(LM4_GPIO_N, 0x0c, 1);
-}
-
-/**
* Perform necessary actions on host wake events.
*/
void board_process_wake_events(uint32_t active_wake_events)
diff --git a/board/falco/board.h b/board/falco/board.h
index cb5190f8b3..b51ad360b4 100644
--- a/board/falco/board.h
+++ b/board/falco/board.h
@@ -30,11 +30,22 @@
#define CONFIG_PWM_FAN
#define CONFIG_TEMP_SENSOR
#define CONFIG_TEMP_SENSOR_G781
+#define CONFIG_UART_HOST 2
#define CONFIG_USB_PORT_POWER_DUMB
#define CONFIG_WIRELESS
#ifndef __ASSEMBLER__
+/* Module IDs */
+/* TODO(rspangler): use this in place of enum console_channel as well */
+enum module_id {
+ MODULE_I2C,
+ MODULE_LPC,
+ MODULE_PECI,
+ MODULE_PWM_FAN,
+ MODULE_UART,
+};
+
/* PWM channels */
#define FAN_CH_CPU 2 /* CPU fan */
#define FAN_CH_BL_DISPLAY 4 /* LVDS backlight (from PCH, cleaned by EC) */
@@ -57,10 +68,6 @@
/* USB ports */
#define USB_PORT_COUNT 2
-/* GPIOs for second UART port */
-#define CONFIG_UART_HOST 2
-#define CONFIG_UART_HOST_GPIOS_PG4_5
-
/* GPIO signal definitions. */
enum gpio_signal {
/* Inputs with interrupt handlers are first for efficiency */
diff --git a/board/host/board.c b/board/host/board.c
index 13389ce001..0490d2287e 100644
--- a/board/host/board.c
+++ b/board/host/board.c
@@ -20,6 +20,11 @@ const struct gpio_info gpio_list[] = {
};
BUILD_ASSERT(ARRAY_SIZE(gpio_list) == GPIO_COUNT);
+/* Pins with alternate functions; not on simulated host platform */
+const struct gpio_alt_func gpio_alt_funcs[] = {
+};
+const int gpio_alt_funcs_count = ARRAY_SIZE(gpio_alt_funcs);
+
static int dummy_temp_get_val(int idx, int *temp_ptr)
{
*temp_ptr = 0;
diff --git a/board/host/board.h b/board/host/board.h
index f84696d58b..3707e2a1f4 100644
--- a/board/host/board.h
+++ b/board/host/board.h
@@ -36,6 +36,12 @@
#define CONFIG_WP_ACTIVE_HIGH
+/* Module IDs */
+enum module_id {
+ MODULE_I2C,
+ MODULE_UART,
+};
+
enum gpio_signal {
GPIO_EC_INT,
GPIO_LID_OPEN,
diff --git a/board/link/board.c b/board/link/board.c
index b4fa8818b4..3f59b8bb85 100644
--- a/board/link/board.c
+++ b/board/link/board.c
@@ -124,6 +124,25 @@ const struct gpio_info gpio_list[] = {
};
BUILD_ASSERT(ARRAY_SIZE(gpio_list) == GPIO_COUNT);
+/* Pins with alternate functions */
+const struct gpio_alt_func gpio_alt_funcs[] = {
+ {GPIO_A, 0x03, 1, MODULE_UART}, /* UART0 */
+ {GPIO_A, 0x40, 3, MODULE_I2C}, /* I2C1 SCL */
+ {GPIO_A, 0x80, 3, MODULE_I2C, GPIO_OPEN_DRAIN}, /* I2C1 SDA */
+ {GPIO_B, 0x04, 3, MODULE_I2C}, /* I2C0 SCL */
+ {GPIO_B, 0x08, 3, MODULE_I2C, GPIO_OPEN_DRAIN}, /* I2C0 SDA */
+ {GPIO_B, 0x40, 3, MODULE_I2C}, /* I2C5 SCL */
+ {GPIO_B, 0x80, 3, MODULE_I2C, GPIO_OPEN_DRAIN}, /* I2C5 SDA */
+ {GPIO_C, 0x30, 2, MODULE_UART}, /* UART1 */
+ {GPIO_J, 0x40, 1, MODULE_PECI}, /* PECI Tx */
+ {GPIO_J, 0x80, 0, MODULE_PECI, GPIO_ANALOG}, /* PECI Rx */
+ {GPIO_K, 0x40, 1, MODULE_PWM_KBLIGHT}, /* Fan1 PWM */
+ {GPIO_L, 0x3f, 15, MODULE_LPC}, /* LPC */
+ {GPIO_M, 0x33, 15, MODULE_LPC}, /* LPC */
+ {GPIO_M, 0xc0, 1, MODULE_PWM_FAN}, /* Fan0 PWM/tach */
+};
+const int gpio_alt_funcs_count = ARRAY_SIZE(gpio_alt_funcs);
+
/* x86 signal list. Must match order of enum x86_signal. */
const struct x86_signal_info x86_signal_list[] = {
{GPIO_PGOOD_5VALW, 1, "PGOOD_5VALW"},
@@ -216,15 +235,6 @@ struct keyboard_scan_config keyscan_config = {
};
/**
- * Configure the GPIOs for the pwm module.
- */
-void configure_fan_gpios(void)
-{
- /* PM6:7 alternate function 1 = channel 0 PWM/tach */
- gpio_set_alternate_function(LM4_GPIO_M, 0xc0, 1);
-}
-
-/**
* Perform necessary actions on host events.
*/
void board_process_wake_events(uint32_t active_wake_events)
@@ -235,12 +245,3 @@ void board_process_wake_events(uint32_t active_wake_events)
else
gpio_set_level(GPIO_PCH_WAKE_L, 1);
}
-
-/**
- * Configure the GPIOs for the pwm module.
- */
-void configure_kblight_gpios(void)
-{
- /* PK6 alternate function 1 = channel 1 PWM */
- gpio_set_alternate_function(LM4_GPIO_K, 0x40, 1);
-}
diff --git a/board/link/board.h b/board/link/board.h
index 422db1dfcd..9b4a826019 100644
--- a/board/link/board.h
+++ b/board/link/board.h
@@ -34,19 +34,30 @@
#define CONFIG_PWM_KBLIGHT
#define CONFIG_TEMP_SENSOR
#define CONFIG_TEMP_SENSOR_TMP006
+#define CONFIG_UART_HOST 1
#define CONFIG_USB_PORT_POWER_SMART
#define CONFIG_WIRELESS
#define CONFIG_WP_ACTIVE_HIGH
#ifndef __ASSEMBLER__
+/* Module IDs */
+/* TODO(rspangler): use this in place of enum console_channel as well */
+enum module_id {
+ MODULE_I2C,
+ MODULE_LPC,
+ MODULE_PECI,
+ MODULE_PWM_FAN,
+ MODULE_PWM_KBLIGHT,
+ MODULE_UART,
+};
+
/* Fan PWM channels */
#define FAN_CH_CPU 0 /* CPU fan */
#define FAN_CH_KBLIGHT 1 /* Keyboard backlight */
#define FAN_CH_POWER_LED 5 /* Power adapter LED */
-enum adc_channel
-{
+enum adc_channel {
/* EC internal die temperature in degrees K. */
ADC_CH_EC_TEMP = 0,
/* Charger current in mA. */
@@ -80,10 +91,6 @@ enum adc_channel
/* USB charge port */
#define USB_CHARGE_PORT_COUNT 2
-/* GPIOs for second UART port */
-#define CONFIG_UART_HOST 1
-#define CONFIG_UART_HOST_GPIOS_PC4_5
-
/* GPIO signal definitions. */
enum gpio_signal {
/* Inputs with interrupt handlers are first for efficiency */
diff --git a/board/mccroskey/board.c b/board/mccroskey/board.c
index 6f76563847..ca38624331 100644
--- a/board/mccroskey/board.c
+++ b/board/mccroskey/board.c
@@ -98,6 +98,15 @@ const struct gpio_info gpio_list[] = {
};
BUILD_ASSERT(ARRAY_SIZE(gpio_list) == GPIO_COUNT);
+/* Pins with alternate functions */
+const struct gpio_alt_func gpio_alt_funcs[] = {
+ /*
+ * TODO(rspangler): use this instead of hard-coded register writes in
+ * board_config_pre_init().
+ */
+};
+const int gpio_alt_funcs_count = ARRAY_SIZE(gpio_alt_funcs);
+
void board_config_pre_init(void)
{
uint32_t val;
diff --git a/board/mccroskey/board.h b/board/mccroskey/board.h
index 0501c06ad6..8d2ac274ab 100644
--- a/board/mccroskey/board.h
+++ b/board/mccroskey/board.h
@@ -30,6 +30,13 @@
#ifndef __ASSEMBLER__
+/* Module IDs */
+/* TODO(rspangler): use this in place of enum console_channel as well */
+enum module_id {
+ MODULE_I2C,
+ MODULE_UART,
+};
+
/* By default, enable all console messages except keyboard */
#define CC_DEFAULT (CC_ALL)
diff --git a/board/peppy/board.c b/board/peppy/board.c
index 5a0cc05d5d..623eed7b50 100644
--- a/board/peppy/board.c
+++ b/board/peppy/board.c
@@ -124,6 +124,22 @@ const struct gpio_info gpio_list[] = {
};
BUILD_ASSERT(ARRAY_SIZE(gpio_list) == GPIO_COUNT);
+/* Pins with alternate functions */
+const struct gpio_alt_func gpio_alt_funcs[] = {
+ {GPIO_A, 0x03, 1, MODULE_UART}, /* UART0 */
+ {GPIO_B, 0x04, 3, MODULE_I2C}, /* I2C0 SCL */
+ {GPIO_B, 0x08, 3, MODULE_I2C, GPIO_OPEN_DRAIN}, /* I2C0 SDA */
+ {GPIO_B, 0x40, 3, MODULE_I2C}, /* I2C5 SCL */
+ {GPIO_B, 0x80, 3, MODULE_I2C, GPIO_OPEN_DRAIN}, /* I2C5 SDA */
+ {GPIO_G, 0x30, 1, MODULE_UART}, /* UART2 */
+ {GPIO_J, 0x40, 1, MODULE_PECI}, /* PECI Tx */
+ {GPIO_J, 0x80, 0, MODULE_PECI, GPIO_ANALOG}, /* PECI Rx */
+ {GPIO_L, 0x3f, 15, MODULE_LPC}, /* LPC */
+ {GPIO_M, 0x33, 15, MODULE_LPC}, /* LPC */
+ {GPIO_N, 0x0c, 1, MODULE_PWM_FAN}, /* Fan0 PWM/tach */
+};
+const int gpio_alt_funcs_count = ARRAY_SIZE(gpio_alt_funcs);
+
/* x86 signal list. Must match order of enum x86_signal. */
const struct x86_signal_info x86_signal_list[] = {
{GPIO_PP5000_PGOOD, 1, "PGOOD_PP5000"},
@@ -188,15 +204,6 @@ struct keyboard_scan_config keyscan_config = {
};
/**
- * Configure the GPIOs for the pwm module.
- */
-void configure_fan_gpios(void)
-{
- /* PN2:3 alternate function 1 = channel 0 PWM/tach */
- gpio_set_alternate_function(LM4_GPIO_N, 0x0c, 1);
-}
-
-/**
* Perform necessary actions on host wake events.
*/
void board_process_wake_events(uint32_t active_wake_events)
diff --git a/board/peppy/board.h b/board/peppy/board.h
index f8988e507a..db323df3e5 100644
--- a/board/peppy/board.h
+++ b/board/peppy/board.h
@@ -30,11 +30,22 @@
#define CONFIG_PWM_FAN
#define CONFIG_TEMP_SENSOR
#define CONFIG_TEMP_SENSOR_G781
+#define CONFIG_UART_HOST 2
#define CONFIG_USB_PORT_POWER_DUMB
#define CONFIG_WIRELESS
#ifndef __ASSEMBLER__
+/* Module IDs */
+/* TODO(rspangler): use this in place of enum console_channel as well */
+enum module_id {
+ MODULE_I2C,
+ MODULE_LPC,
+ MODULE_PECI,
+ MODULE_PWM_FAN,
+ MODULE_UART,
+};
+
/* PWM channels */
#define FAN_CH_CPU 2 /* CPU fan */
#define FAN_CH_BL_DISPLAY 4 /* LVDS backlight (from PCH, cleaned by EC) */
@@ -56,10 +67,6 @@
/* USB ports */
#define USB_PORT_COUNT 2
-/* GPIOs for second UART port */
-#define CONFIG_UART_HOST 2
-#define CONFIG_UART_HOST_GPIOS_PG4_5
-
/* GPIO signal definitions. */
enum gpio_signal {
/* Inputs with interrupt handlers are first for efficiency */
diff --git a/board/pit/board.c b/board/pit/board.c
index 616716ae89..31b13f2a84 100644
--- a/board/pit/board.c
+++ b/board/pit/board.c
@@ -82,6 +82,15 @@ const struct gpio_info gpio_list[] = {
};
BUILD_ASSERT(ARRAY_SIZE(gpio_list) == GPIO_COUNT);
+/* Pins with alternate functions */
+const struct gpio_alt_func gpio_alt_funcs[] = {
+ {GPIO_A, 0x0004, GPIO_ALT_TIM2, MODULE_POWER_LED},
+ {GPIO_A, 0x00f0, GPIO_ALT_SPI, MODULE_SPI},
+ {GPIO_A, 0x0600, GPIO_ALT_USART, MODULE_UART},
+ {GPIO_B, 0x0cc0, GPIO_ALT_I2C, MODULE_I2C},
+};
+const int gpio_alt_funcs_count = ARRAY_SIZE(gpio_alt_funcs);
+
/* Battery temperature ranges in degrees C */
const struct battery_temperature_ranges bat_temp_ranges = {
.start_charging_min_c = 0,
diff --git a/board/pit/board.h b/board/pit/board.h
index 0601d91ad2..046849cdc6 100644
--- a/board/pit/board.h
+++ b/board/pit/board.h
@@ -11,7 +11,6 @@
/* Optional features */
#define CONFIG_BATTERY_BQ20Z453
#define CONFIG_BATTERY_SMART
-#define CONFIG_BOARD_POST_GPIO_INIT
#ifdef HAS_TASK_CHARGER
#define CONFIG_CHARGER_TPS65090
#endif
@@ -30,6 +29,15 @@
#ifndef __ASSEMBLER__
+/* Module IDs */
+/* TODO(rspangler): use this in place of enum console_channel as well */
+enum module_id {
+ MODULE_I2C,
+ MODULE_POWER_LED,
+ MODULE_SPI,
+ MODULE_UART,
+};
+
/* By default, enable all console messages except keyboard */
#define CC_DEFAULT (CC_ALL & ~CC_MASK(CC_KEYSCAN))
diff --git a/board/puppy/board.c b/board/puppy/board.c
index 0bb2eb3a6c..be011561ac 100644
--- a/board/puppy/board.c
+++ b/board/puppy/board.c
@@ -82,6 +82,15 @@ const struct gpio_info gpio_list[] = {
};
BUILD_ASSERT(ARRAY_SIZE(gpio_list) == GPIO_COUNT);
+/* Pins with alternate functions */
+const struct gpio_alt_func gpio_alt_funcs[] = {
+ {GPIO_A, 0x0004, GPIO_ALT_TIM2, MODULE_POWER_LED},
+ {GPIO_A, 0x00f0, GPIO_ALT_SPI, MODULE_SPI},
+ {GPIO_A, 0x0600, GPIO_ALT_USART, MODULE_UART},
+ {GPIO_B, 0x0cc0, GPIO_ALT_I2C, MODULE_I2C},
+};
+const int gpio_alt_funcs_count = ARRAY_SIZE(gpio_alt_funcs);
+
/* Battery temperature ranges in degrees C */
const struct battery_temperature_ranges bat_temp_ranges = {
.start_charging_min_c = 5,
@@ -98,18 +107,6 @@ const struct i2c_port_t i2c_ports[] = {
};
BUILD_ASSERT(ARRAY_SIZE(i2c_ports) == I2C_PORTS_USED);
-void board_config_post_gpio_init(void)
-{
- /* I2C SCL/SDA on PB10-11 and PB6-7 */
- gpio_set_alternate_function(GPIO_B,
- (1 << 11) | (1 << 10) | (1 << 7) | (1 << 6),
- GPIO_ALT_I2C);
-
- /* USART1 on pins PA9/PA10 */
- gpio_set_alternate_function(GPIO_A, (1 << 9) | (1 << 10),
- GPIO_ALT_USART);
-}
-
int pmu_board_init(void)
{
int ver, failure = 0;
diff --git a/board/puppy/board.h b/board/puppy/board.h
index 024d3ec6d4..8a17472d8c 100644
--- a/board/puppy/board.h
+++ b/board/puppy/board.h
@@ -11,7 +11,6 @@
/* Optional features */
#define CONFIG_BATTERY_BQ20Z453
#define CONFIG_BATTERY_SMART
-#define CONFIG_BOARD_POST_GPIO_INIT
#ifdef HAS_TASK_CHARGER
#define CONFIG_CHARGER_TPS65090
#endif
@@ -29,6 +28,15 @@
#ifndef __ASSEMBLER__
+/* Module IDs */
+/* TODO(rspangler): use this in place of enum console_channel as well */
+enum module_id {
+ MODULE_I2C,
+ MODULE_POWER_LED,
+ MODULE_SPI,
+ MODULE_UART,
+};
+
/* By default, enable all console messages except keyboard */
#define CC_DEFAULT (CC_ALL & ~CC_MASK(CC_KEYSCAN))
diff --git a/board/slippy/board.c b/board/slippy/board.c
index fbeb7e7224..8273ca4e3f 100644
--- a/board/slippy/board.c
+++ b/board/slippy/board.c
@@ -122,6 +122,22 @@ const struct gpio_info gpio_list[] = {
};
BUILD_ASSERT(ARRAY_SIZE(gpio_list) == GPIO_COUNT);
+/* Pins with alternate functions */
+const struct gpio_alt_func gpio_alt_funcs[] = {
+ {GPIO_A, 0x03, 1, MODULE_UART}, /* UART0 */
+ {GPIO_B, 0x04, 3, MODULE_I2C}, /* I2C0 SCL */
+ {GPIO_B, 0x08, 3, MODULE_I2C, GPIO_OPEN_DRAIN}, /* I2C0 SDA */
+ {GPIO_B, 0x40, 3, MODULE_I2C}, /* I2C5 SCL */
+ {GPIO_B, 0x80, 3, MODULE_I2C, GPIO_OPEN_DRAIN}, /* I2C5 SDA */
+ {GPIO_G, 0x30, 1, MODULE_UART}, /* UART2 */
+ {GPIO_J, 0x40, 1, MODULE_PECI}, /* PECI Tx */
+ {GPIO_J, 0x80, 0, MODULE_PECI, GPIO_ANALOG}, /* PECI Rx */
+ {GPIO_L, 0x3f, 15, MODULE_LPC}, /* LPC */
+ {GPIO_M, 0x33, 15, MODULE_LPC}, /* LPC */
+ {GPIO_N, 0x0c, 1, MODULE_PWM_FAN}, /* Fan0 PWM/tach */
+};
+const int gpio_alt_funcs_count = ARRAY_SIZE(gpio_alt_funcs);
+
/* x86 signal list. Must match order of enum x86_signal. */
const struct x86_signal_info x86_signal_list[] = {
{GPIO_PP5000_PGOOD, 1, "PGOOD_PP5000"},
@@ -188,15 +204,6 @@ struct keyboard_scan_config keyscan_config = {
};
/**
- * Configure the GPIOs for the pwm module.
- */
-void configure_fan_gpios(void)
-{
- /* PN2:3 alternate function 1 = channel 0 PWM/tach */
- gpio_set_alternate_function(LM4_GPIO_N, 0x0c, 1);
-}
-
-/**
* Perform necessary actions on host wake events.
*/
void board_process_wake_events(uint32_t active_wake_events)
diff --git a/board/slippy/board.h b/board/slippy/board.h
index c8f3d8a38f..aa0cf467e7 100644
--- a/board/slippy/board.h
+++ b/board/slippy/board.h
@@ -31,11 +31,22 @@
#define CONFIG_PWM_FAN
#define CONFIG_TEMP_SENSOR
#define CONFIG_TEMP_SENSOR_G781
+#define CONFIG_UART_HOST 2
#define CONFIG_USB_PORT_POWER_DUMB
#define CONFIG_WIRELESS
#ifndef __ASSEMBLER__
+/* Module IDs */
+/* TODO(rspangler): use this in place of enum console_channel as well */
+enum module_id {
+ MODULE_I2C,
+ MODULE_LPC,
+ MODULE_PECI,
+ MODULE_PWM_FAN,
+ MODULE_UART,
+};
+
/* PWM channels */
#define FAN_CH_CPU 2 /* CPU fan */
#define FAN_CH_BL_DISPLAY 4 /* LVDS backlight (from PCH, cleaned by EC) */
@@ -57,10 +68,6 @@
/* USB ports */
#define USB_PORT_COUNT 2
-/* GPIOs for second UART port */
-#define CONFIG_UART_HOST 2
-#define CONFIG_UART_HOST_GPIOS_PG4_5
-
/* GPIO signal definitions. */
enum gpio_signal {
/* Inputs with interrupt handlers are first for efficiency */
diff --git a/board/snow/board.c b/board/snow/board.c
index 0199674acc..aa034da446 100644
--- a/board/snow/board.c
+++ b/board/snow/board.c
@@ -95,6 +95,15 @@ const struct gpio_info gpio_list[] = {
};
BUILD_ASSERT(ARRAY_SIZE(gpio_list) == GPIO_COUNT);
+/* Pins with alternate functions */
+const struct gpio_alt_func gpio_alt_funcs[] = {
+ /*
+ * TODO(rspangler): use this instead of hard-coded register writes in
+ * board_config_pre_init().
+ */
+};
+const int gpio_alt_funcs_count = ARRAY_SIZE(gpio_alt_funcs);
+
/* Battery temperature ranges in degrees C */
const struct battery_temperature_ranges bat_temp_ranges = {
.start_charging_min_c = 5,
diff --git a/board/snow/board.h b/board/snow/board.h
index 66fd26dd74..35ce991160 100644
--- a/board/snow/board.h
+++ b/board/snow/board.h
@@ -37,6 +37,14 @@
#ifndef __ASSEMBLER__
+/* Module IDs */
+/* TODO(rspangler): use this in place of enum console_channel as well */
+enum module_id {
+ MODULE_I2C,
+ MODULE_POWER_LED,
+ MODULE_UART,
+};
+
/* By default, enable all console messages except keyboard */
#define CC_DEFAULT (CC_ALL & ~CC_MASK(CC_KEYSCAN))
diff --git a/board/spring/board.c b/board/spring/board.c
index 40b6610113..39f5fcbf72 100644
--- a/board/spring/board.c
+++ b/board/spring/board.c
@@ -95,6 +95,15 @@ const struct gpio_info gpio_list[] = {
};
BUILD_ASSERT(ARRAY_SIZE(gpio_list) == GPIO_COUNT);
+/* Pins with alternate functions */
+const struct gpio_alt_func gpio_alt_funcs[] = {
+ /*
+ * TODO(rspangler): use this instead of hard-coded register writes in
+ * board_config_pre_init().
+ */
+};
+const int gpio_alt_funcs_count = ARRAY_SIZE(gpio_alt_funcs);
+
/* Battery temperature ranges in degrees C */
const struct battery_temperature_ranges bat_temp_ranges = {
.start_charging_min_c = 5,
diff --git a/board/spring/board.h b/board/spring/board.h
index 2990a316a4..5a2f31c166 100644
--- a/board/spring/board.h
+++ b/board/spring/board.h
@@ -39,6 +39,13 @@
#ifndef __ASSEMBLER__
+/* Module IDs */
+/* TODO(rspangler): use this in place of enum console_channel as well */
+enum module_id {
+ MODULE_I2C,
+ MODULE_UART,
+};
+
/* By default, enable all console messages except keyboard */
#define CC_DEFAULT (CC_ALL & ~CC_MASK(CC_KEYSCAN))
diff --git a/board/wolf/board.c b/board/wolf/board.c
index fe0db01e86..887ce30cc6 100644
--- a/board/wolf/board.c
+++ b/board/wolf/board.c
@@ -120,6 +120,22 @@ const struct gpio_info gpio_list[] = {
};
BUILD_ASSERT(ARRAY_SIZE(gpio_list) == GPIO_COUNT);
+/* Pins with alternate functions */
+const struct gpio_alt_func gpio_alt_funcs[] = {
+ {GPIO_A, 0x03, 1, MODULE_UART}, /* UART0 */
+ {GPIO_B, 0x04, 3, MODULE_I2C}, /* I2C0 SCL */
+ {GPIO_B, 0x08, 3, MODULE_I2C, GPIO_OPEN_DRAIN}, /* I2C0 SDA */
+ {GPIO_B, 0x40, 3, MODULE_I2C}, /* I2C5 SCL */
+ {GPIO_B, 0x80, 3, MODULE_I2C, GPIO_OPEN_DRAIN}, /* I2C5 SDA */
+ {GPIO_G, 0x30, 1, MODULE_UART}, /* UART2 */
+ {GPIO_J, 0x40, 1, MODULE_PECI}, /* PECI Tx */
+ {GPIO_J, 0x80, 0, MODULE_PECI, GPIO_ANALOG}, /* PECI Rx */
+ {GPIO_L, 0x3f, 15, MODULE_LPC}, /* LPC */
+ {GPIO_M, 0x33, 15, MODULE_LPC}, /* LPC */
+ {GPIO_N, 0x0c, 1, MODULE_PWM_FAN}, /* Fan0 PWM/tach */
+};
+const int gpio_alt_funcs_count = ARRAY_SIZE(gpio_alt_funcs);
+
/* x86 signal list. Must match order of enum x86_signal. */
const struct x86_signal_info x86_signal_list[] = {
{GPIO_PP5000_PGOOD, 1, "PGOOD_PP5000"},
@@ -185,15 +201,6 @@ struct keyboard_scan_config keyscan_config = {
};
/**
- * Configure the GPIOs for the pwm module.
- */
-void configure_fan_gpios(void)
-{
- /* PN2:3 alternate function 1 = channel 0 PWM/tach */
- gpio_set_alternate_function(LM4_GPIO_N, 0x0c, 1);
-}
-
-/**
* Perform necessary actions on host wake events.
*/
void board_process_wake_events(uint32_t active_wake_events)
diff --git a/board/wolf/board.h b/board/wolf/board.h
index 22da17b654..7ade111cf0 100644
--- a/board/wolf/board.h
+++ b/board/wolf/board.h
@@ -23,11 +23,22 @@
#define CONFIG_POWER_BUTTON_X86
#define CONFIG_PWM_FAN
#define CONFIG_TEMP_SENSOR
+#define CONFIG_UART_HOST 2
#define CONFIG_USB_PORT_POWER_DUMB
#define CONFIG_WIRELESS
#ifndef __ASSEMBLER__
+/* Module IDs */
+/* TODO(rspangler): use this in place of enum console_channel as well */
+enum module_id {
+ MODULE_I2C,
+ MODULE_LPC,
+ MODULE_PECI,
+ MODULE_PWM_FAN,
+ MODULE_UART,
+};
+
/* PWM channels */
#define FAN_CH_CPU 2 /* CPU fan */
#define FAN_CH_BL_DISPLAY 4 /* LVDS backlight (from PCH, cleaned by EC) */
@@ -49,10 +60,6 @@
/* USB ports */
#define USB_PORT_COUNT 2
-/* GPIOs for second UART port */
-#define CONFIG_UART_HOST 2
-#define CONFIG_UART_HOST_GPIOS_PG4_5
-
/* GPIO signal definitions. */
enum gpio_signal {
/* Inputs with interrupt handlers are first for efficiency */
diff --git a/chip/host/gpio.c b/chip/host/gpio.c
index 64953d7682..975476961c 100644
--- a/chip/host/gpio.c
+++ b/chip/host/gpio.c
@@ -27,3 +27,14 @@ test_mockable int gpio_enable_interrupt(enum gpio_signal signal)
{
return EC_SUCCESS;
}
+
+test_mockable void gpio_set_flags_by_mask(uint32_t port, uint32_t mask,
+ uint32_t flags)
+{
+ /* Nothing */
+}
+
+test_mockable void gpio_set_alternate_function(int port, int mask, int func)
+{
+ /* Nothing */
+}
diff --git a/chip/lm4/gpio.c b/chip/lm4/gpio.c
index ab6423d570..d3a060904d 100644
--- a/chip/lm4/gpio.c
+++ b/chip/lm4/gpio.c
@@ -74,7 +74,6 @@ void gpio_set_alternate_function(int port, int mask, int func)
} else {
LM4_GPIO_AFSEL(port) &= ~mask;
}
- LM4_GPIO_DEN(port) |= mask;
}
test_mockable int gpio_get_level(enum gpio_signal signal)
@@ -93,58 +92,59 @@ void gpio_set_level(enum gpio_signal signal, int value)
gpio_list[signal].mask) = (value ? 0xff : 0);
}
-void gpio_set_flags(enum gpio_signal signal, int flags)
+void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags)
{
- const struct gpio_info *g = gpio_list + signal;
+ /*
+ * Select open drain first, so that we don't glitch the signal
+ * when changing the line to an output.
+ */
+ if (flags & GPIO_OPEN_DRAIN)
+ LM4_GPIO_ODR(port) |= mask;
+ else
+ LM4_GPIO_ODR(port) &= ~mask;
- if (flags & GPIO_OUTPUT) {
- /*
- * Select open drain first, so that we don't glitch the signal
- * when changing the line to an output.
- */
- if (g->flags & GPIO_OPEN_DRAIN)
- LM4_GPIO_ODR(g->port) |= g->mask;
- else
- LM4_GPIO_ODR(g->port) &= ~g->mask;
-
- LM4_GPIO_DIR(g->port) |= g->mask;
-
- /* Set level if necessary */
- if (flags & GPIO_HIGH)
- gpio_set_level(signal, 1);
- else if (flags & GPIO_LOW)
- gpio_set_level(signal, 0);
- } else {
- /* Input */
- LM4_GPIO_DIR(g->port) &= ~g->mask;
- }
+ if (flags & GPIO_OUTPUT)
+ LM4_GPIO_DIR(port) |= mask;
+ else
+ LM4_GPIO_DIR(port) &= ~mask;
/* Handle pullup / pulldown */
- if (g->flags & GPIO_PULL_UP) {
- LM4_GPIO_PUR(g->port) |= g->mask;
- } else if (g->flags & GPIO_PULL_DOWN) {
- LM4_GPIO_PDR(g->port) |= g->mask;
+ if (flags & GPIO_PULL_UP) {
+ LM4_GPIO_PUR(port) |= mask;
+ } else if (flags & GPIO_PULL_DOWN) {
+ LM4_GPIO_PDR(port) |= mask;
} else {
/* No pull up/down */
- LM4_GPIO_PUR(g->port) &= ~g->mask;
- LM4_GPIO_PDR(g->port) &= ~g->mask;
+ LM4_GPIO_PUR(port) &= ~mask;
+ LM4_GPIO_PDR(port) &= ~mask;
}
/* Set up interrupt type */
- if (g->flags & GPIO_INT_LEVEL)
- LM4_GPIO_IS(g->port) |= g->mask;
+ if (flags & GPIO_INT_LEVEL)
+ LM4_GPIO_IS(port) |= mask;
else
- LM4_GPIO_IS(g->port) &= ~g->mask;
+ LM4_GPIO_IS(port) &= ~mask;
- if (g->flags & (GPIO_INT_RISING | GPIO_INT_HIGH))
- LM4_GPIO_IEV(g->port) |= g->mask;
+ if (flags & (GPIO_INT_RISING | GPIO_INT_HIGH))
+ LM4_GPIO_IEV(port) |= mask;
else
- LM4_GPIO_IEV(g->port) &= ~g->mask;
+ LM4_GPIO_IEV(port) &= ~mask;
- if (g->flags & GPIO_INT_BOTH)
- LM4_GPIO_IBE(g->port) |= g->mask;
+ if (flags & GPIO_INT_BOTH)
+ LM4_GPIO_IBE(port) |= mask;
else
- LM4_GPIO_IBE(g->port) &= ~g->mask;
+ LM4_GPIO_IBE(port) &= ~mask;
+
+ if (flags & GPIO_ANALOG)
+ LM4_GPIO_DEN(port) &= ~mask;
+ else
+ LM4_GPIO_DEN(port) |= mask;
+
+ /* Set level */
+ if (flags & GPIO_HIGH)
+ LM4_GPIO_DATA(port, mask) = 0xff;
+ else if (flags & GPIO_LOW)
+ LM4_GPIO_DATA(port, mask) = 0;
}
int gpio_enable_interrupt(enum gpio_signal signal)
@@ -210,7 +210,7 @@ void gpio_pre_init(void)
flags &= ~(GPIO_LOW | GPIO_HIGH);
/* Set up GPIO based on flags */
- gpio_set_flags(i, flags);
+ gpio_set_flags_by_mask(g->port, g->mask, flags);
/* Use as GPIO, not alternate function */
gpio_set_alternate_function(g->port, g->mask, -1);
diff --git a/chip/lm4/i2c.c b/chip/lm4/i2c.c
index abf82f62f4..8fc1591338 100644
--- a/chip/lm4/i2c.c
+++ b/chip/lm4/i2c.c
@@ -236,30 +236,6 @@ exit:
return rv;
}
-/**
- * Configure I2C GPIOs for the module.
- */
-static void configure_i2c_gpios(void)
-{
-#ifdef BOARD_bds
- /* PG6:7 = I2C5 SCL/SDA */
- gpio_set_alternate_function(LM4_GPIO_G, 0xc0, 3);
-
- /* Configure SDA as open-drain. SCL should not be open-drain,
- * since it has an internal pull-up. */
- LM4_GPIO_ODR(LM4_GPIO_G) |= 0x80;
-#else
- /* PA6:7 = I2C1 SCL/SDA; PB2:3 = I2C0 SCL/SDA; PB6:7 = I2C5 SCL/SDA */
- gpio_set_alternate_function(LM4_GPIO_A, 0xc0, 3);
- gpio_set_alternate_function(LM4_GPIO_B, 0xcc, 3);
-
- /* Configure SDA as open-drain. SCL should not be open-drain,
- * since it has an internal pull-up. */
- LM4_GPIO_ODR(LM4_GPIO_A) |= 0x80;
- LM4_GPIO_ODR(LM4_GPIO_B) |= 0x88;
-#endif
-}
-
/*****************************************************************************/
/* Hooks */
@@ -308,7 +284,7 @@ static void i2c_init(void)
clock_wait_cycles(3);
/* Configure GPIOs */
- configure_i2c_gpios();
+ gpio_config_module(MODULE_I2C, 1);
/* No tasks are waiting on ports */
for (i = 0; i < I2C_PORT_COUNT; i++)
diff --git a/chip/lm4/lpc.c b/chip/lm4/lpc.c
index c3cc908ed7..04563caf66 100644
--- a/chip/lm4/lpc.c
+++ b/chip/lm4/lpc.c
@@ -75,20 +75,6 @@ static uint8_t * const cmd_params = (uint8_t *)LPC_POOL_CMD_DATA +
static struct ec_lpc_host_args * const lpc_host_args =
(struct ec_lpc_host_args *)LPC_POOL_CMD_DATA;
-/* Configure GPIOs for module */
-static void configure_gpio(void)
-{
- /*
- * Set digital alternate function 15 for PL0:5, PM0:2, PM4:5 pins.
- *
- * I/O: PL0:3 = command/address/data
- * inp: PL4 (frame), PL5 (reset), PM0 (powerdown), PM5 (clock)
- * out: PM1 (sci), PM4 (serirq)
- */
- gpio_set_alternate_function(LM4_GPIO_L, 0x3f, 0x0f);
- gpio_set_alternate_function(LM4_GPIO_M, 0x33, 0x0f);
-}
-
static void wait_irq_sent(void)
{
/*
@@ -679,7 +665,7 @@ static void lpc_init(void)
LM4_LPC_LPCIRQCTL = 0;
/* Configure GPIOs */
- configure_gpio();
+ gpio_config_module(MODULE_LPC, 1);
/*
* Set LPC channel 0 to I/O address 0x62 (data) / 0x66 (command),
diff --git a/chip/lm4/peci.c b/chip/lm4/peci.c
index b547165b49..b791c97a89 100644
--- a/chip/lm4/peci.c
+++ b/chip/lm4/peci.c
@@ -40,18 +40,6 @@
static int temp_vals[TEMP_AVG_LENGTH];
static int temp_idx = 0;
-/**
- * Configure the GPIOs for the PECI module.
- */
-static void configure_gpios(void)
-{
- /* PJ6 alternate function 1 = PECI Tx */
- gpio_set_alternate_function(LM4_GPIO_J, 0x40, 1);
-
- /* PJ7 analog input = PECI Rx (comparator) */
- LM4_GPIO_DEN(LM4_GPIO_J) &= ~0x80;
-}
-
int peci_get_cpu_temp(void)
{
int v = LM4_PECI_M0D0 & 0xffff;
@@ -120,15 +108,14 @@ DECLARE_HOOK(HOOK_FREQ_CHANGE, peci_freq_changed, HOOK_PRIO_DEFAULT - 1);
static void peci_init(void)
{
- volatile uint32_t scratch __attribute__((unused));
int i;
/* Enable the PECI module and delay a few clocks */
LM4_SYSTEM_RCGCPECI = 1;
- scratch = LM4_SYSTEM_RCGCPECI;
+ clock_wait_cycles(3);
/* Configure GPIOs */
- configure_gpios();
+ gpio_config_module(MODULE_PECI, 1);
/* Set initial clock frequency */
peci_freq_changed();
diff --git a/chip/lm4/pwm_fan.c b/chip/lm4/pwm_fan.c
index 525b9daca2..6309867dae 100644
--- a/chip/lm4/pwm_fan.c
+++ b/chip/lm4/pwm_fan.c
@@ -278,7 +278,7 @@ static void pwm_fan_init(void)
clock_wait_cycles(3);
/* Configure GPIOs */
- configure_fan_gpios();
+ gpio_config_module(MODULE_PWM_FAN, 1);
/* Disable all fans */
LM4_FAN_FANCTL = 0;
diff --git a/chip/lm4/pwm_kblight.c b/chip/lm4/pwm_kblight.c
index df9f965bda..f4628303c9 100644
--- a/chip/lm4/pwm_kblight.c
+++ b/chip/lm4/pwm_kblight.c
@@ -124,7 +124,7 @@ static void pwm_kblight_init(void)
clock_wait_cycles(3);
/* Configure GPIOs */
- configure_kblight_gpios();
+ gpio_config_module(MODULE_PWM_KBLIGHT, 1);
/* Disable all fans */
LM4_FAN_FANCTL = 0;
diff --git a/chip/lm4/registers.h b/chip/lm4/registers.h
index 4185d7ed50..30332d792b 100644
--- a/chip/lm4/registers.h
+++ b/chip/lm4/registers.h
@@ -445,6 +445,23 @@ static inline int lm4_fan_addr(int ch, int offset)
#define LM4_GPIO_AMSEL(port) LM4GPIOREG(port, 0x528)
#define LM4_GPIO_PCTL(port) LM4GPIOREG(port, 0x52c)
+/* Chip-independent aliases for port base addresses */
+#define GPIO_A LM4_GPIO_A
+#define GPIO_B LM4_GPIO_B
+#define GPIO_C LM4_GPIO_C
+#define GPIO_D LM4_GPIO_D
+#define GPIO_E LM4_GPIO_E
+#define GPIO_F LM4_GPIO_F
+#define GPIO_G LM4_GPIO_G
+#define GPIO_H LM4_GPIO_H
+#define GPIO_J LM4_GPIO_J
+#define GPIO_K LM4_GPIO_K
+#define GPIO_L LM4_GPIO_L
+#define GPIO_M LM4_GPIO_M
+#define GPIO_N LM4_GPIO_N
+#define GPIO_P LM4_GPIO_P
+#define GPIO_Q LM4_GPIO_Q
+
/* Value to write to LM4_GPIO_LOCK to unlock writes */
#define LM4_GPIO_LOCK_UNLOCK 0x4c4f434b
diff --git a/chip/lm4/spi.c b/chip/lm4/spi.c
index 7d3b6485d7..6526ded82c 100644
--- a/chip/lm4/spi.c
+++ b/chip/lm4/spi.c
@@ -22,8 +22,7 @@
int spi_enable(int enable)
{
if (enable) {
- /* SSI0 on PA2(CLK), PA4(RX), PA5(TX) alternate function 2 */
- gpio_set_alternate_function(LM4_GPIO_A, 0x34, 2);
+ gpio_config_module(MODULE_SPI, 1);
/* Don't use the SSI0 frame output. CS# is a GPIO so we can
* keep it low during an entire transaction. */
gpio_set_flags(GPIO_SPI_CSn, GPIO_OUTPUT);
@@ -39,8 +38,7 @@ int spi_enable(int enable)
gpio_set_level(GPIO_SPI_CSn, 1);
gpio_set_flags(GPIO_SPI_CSn, GPIO_ODR_HIGH);
- /* PA2,4,5 normal function (high-Z GPIOs) */
- gpio_set_alternate_function(LM4_GPIO_A, 0x34, -1);
+ gpio_config_module(MODULE_SPI, 0);
}
return EC_SUCCESS;
diff --git a/chip/lm4/uart.c b/chip/lm4/uart.c
index 15b83e5551..17443d9848 100644
--- a/chip/lm4/uart.c
+++ b/chip/lm4/uart.c
@@ -139,28 +139,6 @@ static void uart_host_interrupt(void)
/* Must be same prio as LPC interrupt handler so they don't preempt */
DECLARE_IRQ(CONFIG_UART_HOST_IRQ, uart_host_interrupt, 2);
-/**
- * Configure GPIOs for the UART module.
- */
-static void configure_gpio(void)
-{
- /* UART0 RX and TX are GPIO PA0:1 alternate function 1 */
- gpio_set_alternate_function(LM4_GPIO_A, 0x03, 1);
-
-#if (CONFIG_UART_HOST == 1) && defined(CONFIG_UART_HOST_GPIOS_PC4_5)
- /* UART1 RX and TX are GPIO PC4:5 alternate function 2 */
- gpio_set_alternate_function(LM4_GPIO_C, 0x30, 2);
-#elif (CONFIG_UART_HOST == 1) && defined(CONFIG_UART_HOST_GPIOS_PB0_1)
- /* UART1 RX and TX are GPIO PB0:1 alternate function 1 */
- gpio_set_alternate_function(LM4_GPIO_B, 0x03, 1);
-#elif (CONFIG_UART_HOST == 2) && defined(CONFIG_UART_HOST_GPIOS_PG4_5)
- /* UART2 RX and TX are GPIO PG4:5 alternate function 1 */
- gpio_set_alternate_function(LM4_GPIO_G, 0x30, 1);
-#else
-#error "Must put Host UART GPIOs somewhere"
-#endif
-}
-
static void uart_config(int port)
{
/* Disable the port */
@@ -201,8 +179,7 @@ void uart_init(void)
LM4_SYSTEM_RCGCUART |= (1 << CONFIG_UART_HOST) | 1;
scratch = LM4_SYSTEM_RCGCUART;
- /* Configure GPIOs */
- configure_gpio();
+ gpio_config_module(MODULE_UART, 1);
/* Configure UARTs (identically) */
uart_config(0);
diff --git a/chip/stm32/gpio-stm32f.c b/chip/stm32/gpio-stm32f.c
index df892705d0..0917bd5349 100644
--- a/chip/stm32/gpio-stm32f.c
+++ b/chip/stm32/gpio-stm32f.c
@@ -35,31 +35,30 @@ struct port_config {
/**
* Helper function for generating bitmasks for STM32 GPIO config registers
*/
-static void gpio_config_info(const struct gpio_info *g, uint32_t *addr,
+static void gpio_config_info(uint32_t port, uint32_t mask, uint32_t *addr,
uint32_t *mode, uint32_t *cnf) {
/*
* 2-bit config followed by 2-bit mode for each pin, each
* successive pin raises the exponent for the lowest bit
* set by an order of 4, e.g. 2^0, 2^4, 2^8, etc.
*/
- if (g->mask & 0xff) {
- *addr = g->port; /* GPIOx_CRL */
- *mode = g->mask;
+ if (mask & 0xff) {
+ *addr = port; /* GPIOx_CRL */
+ *mode = mask;
} else {
- *addr = g->port + 0x04; /* GPIOx_CRH */
- *mode = g->mask >> 8;
+ *addr = port + 0x04; /* GPIOx_CRH */
+ *mode = mask >> 8;
}
*mode = *mode * *mode * *mode * *mode;
*mode |= *mode << 1;
*cnf = *mode << 2;
}
-void gpio_set_flags(enum gpio_signal signal, int flags)
+void gpio_set_flags_by_mask(uint32_t port, uint32_t pmask, uint32_t flags)
{
- const struct gpio_info *g = gpio_list + signal;
uint32_t addr, cnf, mode, mask;
- gpio_config_info(g, &addr, &mode, &cnf);
+ gpio_config_info(port, pmask, &addr, &mode, &cnf);
mask = REG32(addr) & ~(cnf | mode);
/*
@@ -80,11 +79,10 @@ void gpio_set_flags(enum gpio_signal signal, int flags)
*/
if (flags & GPIO_PULL_UP) {
mask |= 0x88888888 & cnf;
- STM32_GPIO_BSRR(g->port) |= g->mask;
- gpio_set_level(signal, 1);
+ STM32_GPIO_BSRR(port) = pmask;
} else if (flags & GPIO_PULL_DOWN) {
mask |= 0x88888888 & cnf;
- gpio_set_level(signal, 0);
+ STM32_GPIO_BSRR(port) = pmask << 16;
} else {
mask |= 0x44444444 & cnf;
}
@@ -99,20 +97,25 @@ void gpio_set_flags(enum gpio_signal signal, int flags)
* before it has been configured as such.
*/
if (flags & GPIO_HIGH)
- gpio_set_level(signal, 1);
+ STM32_GPIO_BSRR(port) = pmask;
else if (flags & GPIO_LOW)
- gpio_set_level(signal, 0);
+ STM32_GPIO_BSRR(port) = pmask << 16;
}
/* Set up interrupts if necessary */
ASSERT(!(flags & GPIO_INT_LEVEL));
if (flags & (GPIO_INT_RISING | GPIO_INT_BOTH))
- STM32_EXTI_RTSR |= g->mask;
+ STM32_EXTI_RTSR |= pmask;
if (flags & (GPIO_INT_FALLING | GPIO_INT_BOTH))
- STM32_EXTI_FTSR |= g->mask;
+ STM32_EXTI_FTSR |= pmask;
/* Interrupt is enabled by gpio_enable_interrupt() */
}
+void gpio_set_alternate_function(int port, int mask, int func)
+{
+ /* TODO(rspangler): implement me! */
+}
+
void gpio_pre_init(void)
{
const struct gpio_info *g = gpio_list;
diff --git a/chip/stm32/gpio-stm32l.c b/chip/stm32/gpio-stm32l.c
index 5587625081..22d1350362 100644
--- a/chip/stm32/gpio-stm32l.c
+++ b/chip/stm32/gpio-stm32l.c
@@ -20,30 +20,28 @@
/* For each EXTI bit, record which GPIO entry is using it */
static const struct gpio_info *exti_events[16];
-void gpio_set_flags(enum gpio_signal signal, int flags)
+void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags)
{
- const struct gpio_info *g = gpio_list + signal;
-
/* Bitmask for registers with 2 bits per GPIO pin */
- const uint32_t mask2 = (g->mask * g->mask) | (g->mask * g->mask * 2);
+ const uint32_t mask2 = (mask * mask) | (mask * mask * 2);
uint32_t val;
/* Set up pullup / pulldown */
- val = STM32_GPIO_PUPDR(g->port) & ~mask2;
+ val = STM32_GPIO_PUPDR(port) & ~mask2;
if (flags & GPIO_PULL_UP)
val |= 0x55555555 & mask2; /* Pull Up = 01 */
else if (flags & GPIO_PULL_DOWN)
val |= 0xaaaaaaaa & mask2; /* Pull Down = 10 */
- STM32_GPIO_PUPDR(g->port) = val;
+ STM32_GPIO_PUPDR(port) = val;
/*
* Select open drain first, so that we don't glitch the signal when
* changing the line to an output.
*/
if (flags & GPIO_OPEN_DRAIN)
- STM32_GPIO_OTYPER(g->port) |= g->mask;
+ STM32_GPIO_OTYPER(port) |= mask;
- val = STM32_GPIO_MODER(g->port) & ~mask2;
+ val = STM32_GPIO_MODER(port) & ~mask2;
if (flags & GPIO_OUTPUT) {
/*
* Set pin level first to avoid glitching. This is harmless on
@@ -51,25 +49,25 @@ void gpio_set_flags(enum gpio_signal signal, int flags)
* output drivers until the pin is made an output.
*/
if (flags & GPIO_HIGH)
- gpio_set_level(signal, 1);
+ STM32_GPIO_BSRR(port) = mask;
else if (flags & GPIO_LOW)
- gpio_set_level(signal, 0);
+ STM32_GPIO_BSRR(port) = mask << 16;
/* General purpose, MODE = 01 */
val |= 0x55555555 & mask2;
- STM32_GPIO_MODER(g->port) = val;
+ STM32_GPIO_MODER(port) = val;
} else if (flags & GPIO_INPUT) {
/* Input, MODE=00 */
- STM32_GPIO_MODER(g->port) = val;
+ STM32_GPIO_MODER(port) = val;
}
/* Set up interrupts if necessary */
ASSERT(!(flags & GPIO_INT_LEVEL));
if (flags & (GPIO_INT_RISING | GPIO_INT_BOTH))
- STM32_EXTI_RTSR |= g->mask;
+ STM32_EXTI_RTSR |= mask;
if (flags & (GPIO_INT_FALLING | GPIO_INT_BOTH))
- STM32_EXTI_FTSR |= g->mask;
+ STM32_EXTI_FTSR |= mask;
/* Interrupt is enabled by gpio_enable_interrupt() */
}
@@ -109,7 +107,7 @@ void gpio_pre_init(void)
flags &= ~(GPIO_LOW | GPIO_HIGH);
/* Set up GPIO based on flags */
- gpio_set_flags(i, flags);
+ gpio_set_flags_by_mask(g->port, g->mask, flags);
}
}
diff --git a/chip/stm32/i2c-stm32l.c b/chip/stm32/i2c-stm32l.c
index 28df30fb75..0892dc28e7 100644
--- a/chip/stm32/i2c-stm32l.c
+++ b/chip/stm32/i2c-stm32l.c
@@ -352,6 +352,9 @@ static void i2c_init(void)
}
}
+ /* Configure GPIOs */
+ gpio_config_module(MODULE_I2C, 1);
+
/* Set up initial bus frequencies */
i2c_freq_change();
diff --git a/chip/stm32/power_led.c b/chip/stm32/power_led.c
index 8794c82d7c..237fd14670 100644
--- a/chip/stm32/power_led.c
+++ b/chip/stm32/power_led.c
@@ -65,8 +65,7 @@ static void power_led_use_pwm(void)
val |= 0x00009000; /* alt. function (TIM2/PWM) */
STM32_GPIO_CRL(GPIO_B) = val;
#else
- /* PA2 = TIM2_CH3 */
- gpio_set_alternate_function(GPIO_A, (1 << 2), GPIO_ALT_TIM2);
+ gpio_config_module(MODULE_POWER_LED, 1);
#endif
/* Enable timer */
@@ -123,8 +122,12 @@ static void power_led_manual_off(void)
* configure it as an open-drain output and set it to high impedence,
* but reconfiguring as an input had better results in testing.
*/
+#ifdef BOARD_snow
gpio_set_flags(GPIO_LED_POWER_L, GPIO_INPUT);
gpio_set_level(GPIO_LED_POWER_L, 1);
+#else
+ gpio_config_module(MODULE_POWER_LED, 0);
+#endif
using_pwm = 0;
}
diff --git a/chip/stm32/spi.c b/chip/stm32/spi.c
index 07285e27ef..48f857bb4b 100644
--- a/chip/stm32/spi.c
+++ b/chip/stm32/spi.c
@@ -412,7 +412,7 @@ static void spi_chipset_startup(void)
gpio_set_flags(GPIO_SPI1_NSS, GPIO_INT_BOTH | GPIO_PULL_UP);
/* Set SPI pins to alternate function */
- gpio_set_alternate_function(GPIO_A, 0xf0, GPIO_ALT_SPI);
+ gpio_config_module(MODULE_SPI, 1);
/* Set up for next transaction */
setup_for_transaction();
@@ -430,7 +430,7 @@ static void spi_chipset_shutdown(void)
gpio_set_flags(GPIO_SPI1_NSS, 0);
/* Set SPI pins to inputs so we don't leak power when AP is off */
- gpio_set_alternate_function(GPIO_A, 0xf0, -1);
+ gpio_config_module(MODULE_SPI, 0);
}
DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, spi_chipset_shutdown, HOOK_PRIO_DEFAULT);
DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, spi_chipset_shutdown, HOOK_PRIO_DEFAULT);
diff --git a/chip/stm32/uart.c b/chip/stm32/uart.c
index 77b5d93623..dab5231845 100644
--- a/chip/stm32/uart.c
+++ b/chip/stm32/uart.c
@@ -7,6 +7,7 @@
#include "common.h"
#include "clock.h"
+#include "gpio.h"
#include "hooks.h"
#include "registers.h"
#include "task.h"
@@ -146,6 +147,9 @@ void uart_init(void)
STM32_RCC_APB1ENR |= STM32_RCC_PB1_USART ## UARTN;
#endif
+ /* Configure GPIOs */
+ gpio_config_module(MODULE_UART, 1);
+
/*
* UART enabled, 8 Data bits, oversampling x16, no parity,
* RXNE interrupt, TX and RX enabled.
diff --git a/common/gpio_common.c b/common/gpio_common.c
index 11ab9fa4e7..e310814847 100644
--- a/common/gpio_common.c
+++ b/common/gpio_common.c
@@ -61,6 +61,34 @@ static int last_val_changed(int i, int v)
/*****************************************************************************/
/* GPIO API */
+void gpio_config_module(enum module_id id, int enable)
+{
+ const struct gpio_alt_func *af = gpio_alt_funcs;
+ int i;
+
+ /* Set module's pins to alternate functions */
+ for (i = 0; i < gpio_alt_funcs_count; i++, af++) {
+ if (id != af->module_id)
+ continue; /* Pins for some other module */
+
+ if (enable) {
+ gpio_set_flags_by_mask(af->port, af->mask, af->flags);
+ gpio_set_alternate_function(af->port, af->mask,
+ af->func);
+ } else {
+ gpio_set_flags_by_mask(af->port, af->mask, GPIO_INPUT);
+ gpio_set_alternate_function(af->port, af->mask, -1);
+ }
+ }
+}
+
+void gpio_set_flags(enum gpio_signal signal, int flags)
+{
+ const struct gpio_info *g = gpio_list + signal;
+
+ gpio_set_flags_by_mask(g->port, g->mask, flags);
+}
+
const char *gpio_get_name(enum gpio_signal signal)
{
return gpio_list[signal].name;
diff --git a/include/config.h b/include/config.h
index 6be7516029..67fa3df83f 100644
--- a/include/config.h
+++ b/include/config.h
@@ -545,11 +545,6 @@
/* UART index (number) for host UART, if present */
#undef CONFIG_UART_HOST
-/* GPIOs used by host UART. Choose at most one. */
-#undef CONFIG_UART_HOST_GPIOS_PB0_1
-#undef CONFIG_UART_HOST_GPIOS_PC4_5
-#undef CONFIG_UART_HOST_GPIOS_PG4_5
-
/*
* UART transmit buffer size in bytes. Must be a power of 2 for macros in
* common/uart_buffering.c to work properly.
diff --git a/include/gpio.h b/include/gpio.h
index 9517cf40ee..eee7711ee3 100644
--- a/include/gpio.h
+++ b/include/gpio.h
@@ -10,20 +10,24 @@
#include "common.h"
-/* Flag definitions for gpio_info. */
-#define GPIO_INPUT 0x0000 /* Input */
-#define GPIO_OUTPUT 0x0001 /* Output */
-#define GPIO_OPEN_DRAIN 0x0002 /* Output type is open-drain */
-#define GPIO_PULL_UP 0x0004 /* Enable on-chip pullup */
-#define GPIO_PULL_DOWN 0x0008 /* Enable on-chip pulldown */
-#define GPIO_LOW 0x0010 /* If GPIO_OUTPUT, set level low */
-#define GPIO_HIGH 0x0020 /* If GPIO_OUTPUT, set level high */
-#define GPIO_INT_RISING 0x0040 /* Interrupt on rising edge */
-#define GPIO_INT_FALLING 0x0080 /* Interrupt on falling edge */
-#define GPIO_INT_BOTH 0x0100 /* Interrupt on both edges */
-#define GPIO_INT_LOW 0x0200 /* Interrupt on low level */
-#define GPIO_INT_HIGH 0x0400 /* Interrupt on high level */
-#define GPIO_DEFAULT 0x0800 /* Don't set up on boot */
+/* Flag definitions for gpio_info and gpio_alt_func */
+/* The following are valid for both gpio_info and gpio_alt_func: */
+#define GPIO_OPEN_DRAIN (1 << 0) /* Output type is open-drain */
+#define GPIO_PULL_UP (1 << 1) /* Enable on-chip pullup */
+#define GPIO_PULL_DOWN (1 << 2) /* Enable on-chip pulldown */
+/* The following are valid for gpio_alt_func only */
+#define GPIO_ANALOG (1 << 3) /* Set pin to analog-mode */
+/* The following are valid for gpio_info only */
+#define GPIO_INPUT 0 /* Input */
+#define GPIO_OUTPUT (1 << 4) /* Output */
+#define GPIO_LOW (1 << 5) /* If GPIO_OUTPUT, set level low */
+#define GPIO_HIGH (1 << 6) /* If GPIO_OUTPUT, set level high */
+#define GPIO_INT_RISING (1 << 7) /* Interrupt on rising edge */
+#define GPIO_INT_FALLING (1 << 8) /* Interrupt on falling edge */
+#define GPIO_INT_BOTH (1 << 9) /* Interrupt on both edges */
+#define GPIO_INT_LOW (1 << 10) /* Interrupt on low level */
+#define GPIO_INT_HIGH (1 << 11) /* Interrupt on high level */
+#define GPIO_DEFAULT (1 << 12) /* Don't set up on boot */
/* Common flag combinations */
#define GPIO_OUT_LOW (GPIO_OUTPUT | GPIO_LOW)
@@ -37,11 +41,18 @@
/* GPIO signal definition structure, for use by board.c */
struct gpio_info {
+ /* Signal name */
const char *name;
- int port; /* Port (LM4_GPIO_*) */
- int mask; /* Bitmask on that port (0x01 - 0x80; 0x00 =
- * signal not implemented) */
- uint32_t flags; /* Flags (GPIO_*) */
+
+ /* Port base address */
+ uint32_t port;
+
+ /* Bitmask on that port (1 << N; 0 = signal not implemented) */
+ int mask;
+
+ /* Flags (GPIO_*; see above) */
+ uint32_t flags;
+
/*
* Interrupt handler. If non-NULL, and the signal's interrupt is
* enabled, this will be called in the context of the GPIO interrupt
@@ -60,6 +71,27 @@ extern const struct gpio_info gpio_list[];
#define GPIO_SIGNAL_NOT_IMPLEMENTED(name) {name, GPIO_A, 0, 0, NULL}
#endif
+/* GPIO alternate function structure, for use by board.c */
+struct gpio_alt_func {
+ /* Port base address */
+ uint32_t port;
+
+ /* Bitmask on that port (multiple bits allowed) */
+ uint32_t mask;
+
+ /* Alternate function number */
+ int8_t func;
+
+ /* Module ID (as uint8_t, since enum would be 32-bit) */
+ uint8_t module_id;
+
+ /* Flags (GPIO_*; see above). */
+ uint16_t flags;
+};
+
+extern const struct gpio_alt_func gpio_alt_funcs[];
+extern const int gpio_alt_funcs_count;
+
/**
* Pre-initialize GPIOs.
*
@@ -68,6 +100,14 @@ extern const struct gpio_info gpio_list[];
void gpio_pre_init(void);
/**
+ * Configure GPIO pin functions for a module.
+ *
+ * @param id Module ID to initialize
+ * @param enable Enable alternate functions if 1; high-Z pins if 0.
+ */
+void gpio_config_module(enum module_id id, int enable);
+
+/**
* Get the current value of a signal.
*
* @param signal Signal to get
@@ -123,11 +163,28 @@ void gpio_set_level(enum gpio_signal signal, int value);
int gpio_enable_interrupt(enum gpio_signal signal);
/**
+ * Set flags for GPIO(s) by port and mask.
+ *
+ * Use gpio_set_flags() to set flags for an individual GPIO by id.
+ *
+ * Note that modules should usually declare their GPIO alternate functions in
+ * gpio_alt_funcs[] and call gpio_init_module() instead of calling this
+ * directly.
+ *
+ * @param port GPIO port to set (GPIO_*)
+ * @param mask Bitmask of pins on that port to affect
+ * @param flags Flags (GPIO_*; see above)
+ */
+void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags);
+
+/**
* Set alternate function for GPIO(s).
*
- * This is intended for use by other modules' configure_gpio() functions.
+ * Note that modules should usually declare their GPIO alternate functions in
+ * gpio_alt_funcs[] and call gpio_init_module() instead of calling this
+ * directly.
*
- * @param port GPIO port to set (LM4_GPIO_*)
+ * @param port GPIO port to set (GPIO_*)
* @param mask Bitmask of pins on that port to affect
* @param func Alternate function; if <0, configures the specified
* GPIOs for normal GPIO operation.
diff --git a/include/pwm.h b/include/pwm.h
index a4fae7fc75..bb6b5a8549 100644
--- a/include/pwm.h
+++ b/include/pwm.h
@@ -48,11 +48,6 @@ void pwm_set_fan_target_rpm(int rpm);
void pwm_set_fan_duty(int percent);
/**
- * Set up the keyboard gpios.
- */
-void configure_kblight_gpios(void);
-
-/**
* Enable/disable the keyboard backlight.
*/
void pwm_enable_keyboard_backlight(int enable);
@@ -72,9 +67,4 @@ int pwm_get_keyboard_backlight(void);
*/
void pwm_set_keyboard_backlight(int percent);
-/**
- * Configure the GPIOs for the pwm module -- board-specific.
- */
-void configure_fan_gpios(void);
-
#endif /* __CROS_EC_PWM_H */