diff options
Diffstat (limited to 'driver/ioexpander')
-rw-r--r-- | driver/ioexpander/it8801.c | 86 | ||||
-rw-r--r-- | driver/ioexpander/it8801.h | 60 |
2 files changed, 145 insertions, 1 deletions
diff --git a/driver/ioexpander/it8801.c b/driver/ioexpander/it8801.c index 6b1184c740..00e40e12ed 100644 --- a/driver/ioexpander/it8801.c +++ b/driver/ioexpander/it8801.c @@ -6,13 +6,13 @@ #include "common.h" #include "console.h" #include "gpio.h" -#include "hooks.h" #include "i2c.h" #include "it8801.h" #include "keyboard_raw.h" #include "keyboard_scan.h" #include "registers.h" #include "task.h" +#include "util.h" #define CPRINTS(format, args...) cprints(CC_KEYSCAN, format, ## args) @@ -225,3 +225,87 @@ static int it8801_dump(int argc, char **argv) } DECLARE_CONSOLE_COMMAND(it8801_dump, it8801_dump, "NULL", "Dumps IT8801 registers"); + +#ifdef CONFIG_IO_EXPANDER_IT8801_PWM + +struct it8801_pwm_gpio_map { + int port; + int mask; +}; + +const static struct it8801_pwm_gpio_map it8801_pwm_gpio_map[] = { + [1] = {.port = 1, .mask = BIT(2)}, + [2] = {.port = 1, .mask = BIT(3)}, + [3] = {.port = 1, .mask = BIT(4)}, + [4] = {.port = 1, .mask = BIT(5)}, + [7] = {.port = 2, .mask = BIT(0)}, + [8] = {.port = 2, .mask = BIT(3)}, + [9] = {.port = 2, .mask = BIT(2)}, +}; + +void it8801_pwm_enable(enum pwm_channel ch, int enabled) +{ + int port, mask, val, index; + + index = it8801_pwm_channels[ch].index; + if (index < 0 || index >= ARRAY_SIZE(it8801_pwm_gpio_map)) + return; + port = it8801_pwm_gpio_map[index].port; + mask = it8801_pwm_gpio_map[index].mask; + if (port == 0 && mask == 0) + return; + + /* + * PWM1~4,7: alt func 1 + * PWM8,9: alt func 2 + */ + if (it8801_pwm_channels[ch].index <= 7) + it8801_write(IT8801_REG_GPIO_CR(port, mask), + 0x1 << IT8801_GPIOAFS_SHIFT); + else + it8801_write(IT8801_REG_GPIO_CR(port, mask), + 0x2 << IT8801_GPIOAFS_SHIFT); + + it8801_read(IT8801_REG_PWMMCR(it8801_pwm_channels[ch].index), &val); + val &= (~IT8801_PWMMCR_MCR_MASK); + if (enabled) + val |= IT8801_PWMMCR_MCR_BLINKING; + it8801_write(IT8801_REG_PWMMCR(it8801_pwm_channels[ch].index), val); +} + +int it88801_pwm_get_enabled(enum pwm_channel ch) +{ + int val; + + if (it8801_read(IT8801_REG_PWMMCR(it8801_pwm_channels[ch].index), &val)) + return 0; + return (val & IT8801_PWMMCR_MCR_MASK) == IT8801_PWMMCR_MCR_BLINKING; +} + +void it8801_pwm_set_raw_duty(enum pwm_channel ch, uint16_t duty) +{ + duty = MIN(duty, 255); + duty = MAX(duty, 0); + it8801_write(IT8801_REG_PWMDCR(it8801_pwm_channels[ch].index), duty); +} + +uint16_t it8801_pwm_get_raw_duty(enum pwm_channel ch) +{ + int val; + + if (it8801_read(IT8801_REG_PWMDCR(it8801_pwm_channels[ch].index), &val)) + return 0; + return val; +} + +void it8801_pwm_set_duty(enum pwm_channel ch, int percent) +{ + return it8801_pwm_set_raw_duty(ch, (100 - percent) * 255 / 100); +} + +int it8801_pwm_get_duty(enum pwm_channel ch) +{ + return 100 - it8801_pwm_get_raw_duty(ch) * 100 / 255; +} + +#endif /* CONFIG_IO_EXPANDER_IT8801_PWM */ diff --git a/driver/ioexpander/it8801.h b/driver/ioexpander/it8801.h index 9b84adf764..b7e661effa 100644 --- a/driver/ioexpander/it8801.h +++ b/driver/ioexpander/it8801.h @@ -40,7 +40,67 @@ #define IT8801_REG_HBVIDR 0xFF #define IT8801_KSO_COUNT 18 +/* GPIO Register map */ +/* Input pin status register */ +#define IT8801_REG_GPIO_IPSR(port) (0x00 + (port)) +/* Set output value register */ +#define IT8801_REG_GPIO_SOVR(port) (0x05 + (port)) +/* Control register */ +#define IT8801_REG_GPIO_CR(port, mask) \ + (0x0A + (port) * 8 + GPIO_MASK_TO_NUM(mask)) +/* Interrupt status register */ +#define IT8801_REG_GPIO_ISR(port) (0x32 + (port)) +/* Interrupt enable register */ +#define IT8801_REG_GPIO_IER(port) (0x37 + (port)) + +/* Control register values */ +#define IT8801_GPIOAFS_SHIFT 6 /* bit 6~7 */ + +#define IT8801_GPIODIR BIT(5) /* direction, output=1 */ + +#define IT8801_GPIOIOT_SHIFT 3 /* bit 3~4 */ +#define IT8801_GPIOIOT_MASK 0x3 +#define IT8801_GPIOIOT_INT_LEVEL 0 +#define IT8801_GPIOIOT_INT_RISING 1 +#define IT8801_GPIOIOT_INT_FALLING 2 +#define IT8801_GPIOIOT_INT_EDGE 3 /* = RISING + FALLING */ +#define IT8801_GPIOIOT_OPEN_DRAIN 2 + +#define IT8801_GPIOPOL BIT(2) /* polarity */ +#define IT8801_GPIOPDE BIT(1) /* pull-down enable */ +#define IT8801_GPIOPUE BIT(0) /* pull-up enable */ + /* ISR for IT8801's SMB_INT# */ void io_expander_it8801_interrupt(enum gpio_signal signal); +#ifdef CONFIG_IO_EXPANDER_IT8801_PWM + +/* Mapping PWM_CH_LED_* to it8801 channel */ +struct it8801_pwm_t { + int index; +}; + +extern const struct it8801_pwm_t it8801_pwm_channels[]; + +/* standard pwm interface as defined in pwm.h */ +void it8801_pwm_enable(enum pwm_channel ch, int enabled); +int it88801_pwm_get_enabled(enum pwm_channel ch); +void it8801_pwm_set_raw_duty(enum pwm_channel ch, uint16_t duty); +uint16_t it8801_pwm_get_raw_duty(enum pwm_channel ch); +void it8801_pwm_set_duty(enum pwm_channel ch, int percent); +int it8801_pwm_get_duty(enum pwm_channel ch); + +#define IT8801_REG_PWMMCR(n) (0x60 + ((n) - 1) * 8) +#define IT8801_REG_PWMDCR(n) (0x64 + ((n) - 1) * 8) +#define IT8801_REG_PWMPRSL(n) (0x66 + ((n) - 1) * 8) +#define IT8801_REG_PWMPRSM(n) (0x67 + ((n) - 1) * 8) + +#define IT8801_PWMMCR_MCR_MASK 0x3 +#define IT8801_PWMMCR_MCR_OFF 0 +#define IT8801_PWMMCR_MCR_BLINKING 1 +#define IT8801_PWMMCR_MCR_BREATHING 2 +#define IT8801_PWMMCR_MCR_ON 3 + +#endif /* CONFIG_IO_EXPANDER_IT8801_PWM */ + #endif /* __CROS_EC_KBEXPANDER_IT8801_H */ |