diff options
author | Justin Waters <justin.waters@timesys.com> | 2012-04-17 13:43:17 -0400 |
---|---|---|
committer | Justin Waters <justin.waters@timesys.com> | 2012-04-17 13:43:17 -0400 |
commit | 4f60d7e7027af17ceffc1a38e6dbe4e3e95c71ec (patch) | |
tree | dd33f3760e08226d5c05036d664d2d68fb3765dc /drivers/gpio | |
parent | b1af6f532e0d348b153d5c148369229d24af361a (diff) |
LogicPD Support for OMAP3/DM3/AM3 boards
From Logic BSP-2.0-5-01
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpio/twl4030-gpio.c | 105 | ||||
-rw-r--r-- | drivers/gpio/twl4030-pwm.c | 126 |
3 files changed, 233 insertions, 0 deletions
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index a5fa2b5d851..fc6eb59244b 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -31,6 +31,8 @@ COBJS-$(CONFIG_MARVELL_MFP) += mvmfp.o COBJS-$(CONFIG_MXC_GPIO) += mxc_gpio.o COBJS-$(CONFIG_PCA953X) += pca953x.o COBJS-$(CONFIG_S5P) += s5p_gpio.o +COBJS-$(CONFIG_TWL4030_GPIO) += twl4030-gpio.o +COBJS-$(CONFIG_TWL4030_PWM) += twl4030-pwm.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/gpio/twl4030-gpio.c b/drivers/gpio/twl4030-gpio.c new file mode 100644 index 00000000000..57c12fcfb95 --- /dev/null +++ b/drivers/gpio/twl4030-gpio.c @@ -0,0 +1,105 @@ +#include <common.h> +#include <twl4030.h> + +#define BIT(x) (1 << (x)) + +/* GPIO_CTRL Fields */ +#define MASK_GPIO_CTRL_GPIO_ON BIT(2) + +/* store usage of each GPIO. - each bit represents one GPIO */ +static unsigned int gpio_usage_count; + +static inline int gpio_twl4030_write(u8 address, u8 data) +{ + return twl4030_i2c_write_u8(TWL4030_CHIP_GPIO, data, address); +} + +static inline int gpio_twl4030_read(u8 address) +{ + u8 data; + int ret = 0; + + ret = twl4030_i2c_read_u8(TWL4030_CHIP_GPIO, &data, address); + return (ret < 0) ? ret : data; +} + +int twl4030_set_gpio_direction(unsigned int gpio, unsigned int is_input) +{ + u8 d_bnk = gpio >> 3; + u8 d_msk = BIT(gpio & 0x7); + u8 reg = 0; + u8 base = REG_GPIODATADIR1 + d_bnk; + int ret = 0; + + ret = gpio_twl4030_read(base); + if (ret >= 0) { + if (is_input) + reg = ret & ~d_msk; + else + reg = ret | d_msk; + + ret = gpio_twl4030_write(base, reg); + } + + return ret; +} + +int twl4030_set_gpio_dataout(unsigned int gpio, unsigned int enable) +{ + u8 d_bnk = gpio >> 3; + u8 d_msk = BIT(gpio & 0x7); + u8 base = 0; + + if (enable) + base = REG_SETGPIODATAOUT1 + d_bnk; + else + base = REG_CLEARGPIODATAOUT1 + d_bnk; + + return gpio_twl4030_write(base, d_msk); +} + +int twl4030_get_gpio_datain(unsigned int gpio) +{ + u8 d_bnk = gpio >> 3; + u8 d_off = gpio & 0x7; + u8 base = 0; + int ret = 0; + + if (unlikely((gpio >= TWL4030_GPIO_MAX) + || !(gpio_usage_count & BIT(gpio)))) + return -1; + + base = REG_GPIODATAIN1 + d_bnk; + ret = gpio_twl4030_read(base); + if (ret > 0) + ret = (ret >> d_off) & 0x1; + + return ret; +} + +int twl4030_request_gpio(unsigned int gpio) +{ + int status = 0; + + /* on first use, turn GPIO module "on" */ + if (!gpio_usage_count) { + // struct twl4030_gpio_platform_data *pdata; + u8 value = MASK_GPIO_CTRL_GPIO_ON; + + status = gpio_twl4030_write(REG_GPIO_CTRL, value); + } + + if (!status) + gpio_usage_count |= (0x1 << gpio); + + return status; +} + +void twl4030_free_gpio(unsigned int gpio) +{ + gpio_usage_count &= ~BIT(gpio); + + /* on last use, switch off GPIO module */ + if (!gpio_usage_count) + gpio_twl4030_write(REG_GPIO_CTRL, 0x0); +} diff --git a/drivers/gpio/twl4030-pwm.c b/drivers/gpio/twl4030-pwm.c new file mode 100644 index 00000000000..dfbb7f5b596 --- /dev/null +++ b/drivers/gpio/twl4030-pwm.c @@ -0,0 +1,126 @@ +#include <common.h> +#include <twl4030.h> + +/* INTRB register offsets (TWL4030_CHIP_INTBR) */ +#define TWL_INTBR_PMBR1 0x92 +#define TWL_INTBR_GPBR1 0x91 + +/*PWM0 register offsets (TWL4030_CHIP_PWM0) */ +#define TWL_LED_PWMON 0xf8 +#define TWL_LED_PWMOFF 0xf9 + +#if 0 +#define PWM_PRINT(fmt, args...) printf(fmt, ## args) +#else +#define PWM_PRINT(fmt, args...) +#endif + +int twl4030_set_pwm0(int level, int max_brightness) +{ + u8 mux_pwm, enb_pwm; + unsigned char c; + int status; + + PWM_PRINT("%s: level %d\n", __FUNCTION__, level); + if (level > max_brightness) + return -1; + + twl4030_i2c_read_u8(TWL4030_CHIP_INTBR, &mux_pwm, TWL_INTBR_PMBR1); + twl4030_i2c_read_u8(TWL4030_CHIP_INTBR, &enb_pwm, TWL_INTBR_GPBR1); + + PWM_PRINT("%s: enb_pwm %02x mux_pwm %02x\n", __FUNCTION__, enb_pwm, mux_pwm); + + if (level == 0) { + /* disable pwm0 output and clock */ + enb_pwm &= ~0x05; + /* change pwm0 pin to gpio pin */ + mux_pwm &= ~0x0c; + + PWM_PRINT("%s: disable enb_pwm %02x mux_pwm %02x\n", __FUNCTION__, enb_pwm, mux_pwm); + + status = twl4030_i2c_write_u8(TWL4030_CHIP_INTBR, + enb_pwm, TWL_INTBR_GPBR1); + if (status) { + printf("%s:%d status %d\n", __FUNCTION__, __LINE__, status); + return -2; + } + status = twl4030_i2c_write_u8(TWL4030_CHIP_INTBR, + mux_pwm, TWL_INTBR_PMBR1); + if (status) { + printf("%s:%d status %d\n", __FUNCTION__, __LINE__, status); + return -3; + } +#if 0 + PWM_PRINT("%s: turn off GPIO_%d as backlight!\n", __FUNCTION__, omap3logic_dss_lcd_data.lcd_gpio_backlight); + /* Turn off the backlight! */ + gpio_set_value(omap3logic_dss_lcd_data.lcd_gpio_backlight, 0); +#endif + return 0; + } + + if (((enb_pwm & 0x5) != 0x5) || ((mux_pwm & 0x0c) != 0x4)) { + /* change gpio pin to pwm0 pin */ + mux_pwm = (mux_pwm & ~0xc) | 0x04; + /* enable pwm0 output and clock*/ + enb_pwm = (enb_pwm & ~0x5) | 0x05; + + PWM_PRINT("%s: enable enb_pwm %02x mux_pwm %02x\n", __FUNCTION__, enb_pwm, mux_pwm); + status = twl4030_i2c_write_u8(TWL4030_CHIP_INTBR, + mux_pwm, TWL_INTBR_PMBR1); + if (status) { + printf("%s:%d status %d\n", __FUNCTION__, __LINE__, status); + return -4; + } + status = twl4030_i2c_write_u8(TWL4030_CHIP_INTBR, + enb_pwm, TWL_INTBR_GPBR1); + if (status) { + printf("%s:%d status %d\n", __FUNCTION__, __LINE__, status); + return -5; + } +#if 0 + PWM_PRINT("%s: turn on GPIO_%d as backlight!\n", __FUNCTION__, omap3logic_dss_lcd_data.lcd_gpio_backlight); + /* Turn on the backlight! */ + gpio_set_value(omap3logic_dss_lcd_data.lcd_gpio_backlight, 1); +#endif + } + + /* 255 -> 1, 1 -> 126 */ + c = (max_brightness * 126 + (1 - 126) * level) / (max_brightness - 1); + + PWM_PRINT("%s: c %d (%d%% on)\n", __FUNCTION__, c, (((max_brightness+1)-c) * 100)/(max_brightness+1)); + status = twl4030_i2c_write_u8(TWL4030_CHIP_PWM0, 0x7F, TWL_LED_PWMOFF); + if (status) { + PWM_PRINT("%s:%d status %d\n", __FUNCTION__, __LINE__, status); + return -6; + } + status = twl4030_i2c_write_u8(TWL4030_CHIP_PWM0, c, TWL_LED_PWMON); + if (status) { + PWM_PRINT("%s:%d status %d\n", __FUNCTION__, __LINE__, status); + return -7; + } + return 0; +} + +void twl4030_dump_pwm0(void) +{ + int result; + u8 mux_pwm, enb_pwm; + u8 off_period, on_period; + + result = twl4030_i2c_read_u8(TWL4030_CHIP_INTBR, &mux_pwm, + TWL_INTBR_PMBR1); + result |= twl4030_i2c_read_u8(TWL4030_CHIP_INTBR, &enb_pwm, + TWL_INTBR_GPBR1); + + result |= twl4030_i2c_read_u8(TWL4030_CHIP_PWM0, &off_period, + TWL_LED_PWMOFF); + result |=twl4030_i2c_read_u8(TWL4030_CHIP_PWM0, &on_period, + TWL_LED_PWMON); + + if (result) { + printf("%s: failed to read TWL regitsters; result %d\n", __FUNCTION__, result); + return; + } + printf("%s: mux_pwm %02x enb_pwm %02x off_period %02x on_period %02x\n", + __FUNCTION__, mux_pwm, enb_pwm, off_period, on_period); +} |