diff options
author | lars <lars@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-08-05 12:56:17 +0000 |
---|---|---|
committer | lars <lars@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-08-05 12:56:17 +0000 |
commit | 272ebcedf708210247209f301f39a81c78988ef5 (patch) | |
tree | 5d0693c35f8570a1314d8b0e24a45524abb02fed /target/linux/s3c24xx/files-2.6.30/arch/arm/mach-s3c2442 | |
parent | d9921d98248d4ec15afae92bb6daa23a1abaae4b (diff) |
[s3c24xx] gta02: Workaround hardware bug on rev 5 and earlier
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@17130 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/s3c24xx/files-2.6.30/arch/arm/mach-s3c2442')
-rw-r--r-- | target/linux/s3c24xx/files-2.6.30/arch/arm/mach-s3c2442/mach-gta02.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/target/linux/s3c24xx/files-2.6.30/arch/arm/mach-s3c2442/mach-gta02.c b/target/linux/s3c24xx/files-2.6.30/arch/arm/mach-s3c2442/mach-gta02.c index b74c94eea3..49ab6c43b3 100644 --- a/target/linux/s3c24xx/files-2.6.30/arch/arm/mach-s3c2442/mach-gta02.c +++ b/target/linux/s3c24xx/files-2.6.30/arch/arm/mach-s3c2442/mach-gta02.c @@ -91,6 +91,7 @@ #include <plat/iic.h> #include <plat/usb-control.h> #include <plat/regs-timer.h> +#include <plat/gpio-core.h> #include <mach/gta02-pm-gsm.h> #include <mach/gta02-pm-gps.h> @@ -1636,6 +1637,57 @@ static void gta02_poweroff(void) PCF50633_OOCSHDWN_GOSTDBY, PCF50633_OOCSHDWN_GOSTDBY); } + +/* On hardware rev 5 and earlier the leds are missing a resistor and reading + * from their gpio pins will always return 0, so we have to shadow the + * led states software */ +static unsigned long gpb_shadow; +extern struct s3c_gpio_chip s3c24xx_gpios[]; + +static void gta02_gpb_set(struct gpio_chip *chip, + unsigned offset, int value) +{ + void __iomem *base = S3C24XX_GPIO_BASE(S3C2410_GPB0); + unsigned long flags; + unsigned long dat; + + local_irq_save(flags); + + dat = __raw_readl(base + 0x04) | gpb_shadow; + dat &= ~(1 << offset); + gpb_shadow &= ~(1 << offset); + if (value) { + dat |= 1 << offset; + switch (offset) { + case 0 ... 2: + gpb_shadow |= 1 << offset; + break; + default: + break; + } + } + __raw_writel(dat, base + 0x04); + + local_irq_restore(flags); +} + +static int gta02_gpb_get(struct gpio_chip *chip, unsigned offset) +{ + void __iomem *base = S3C24XX_GPIO_BASE(S3C2410_GPB0); + unsigned long val; + + val = __raw_readl(base + 0x04) | gpb_shadow; + val >>= offset; + val &= 1; + + return val; +} + +static void gta02_hijack_gpb(void) { + s3c24xx_gpios[1].chip.set = gta02_gpb_set; + s3c24xx_gpios[1].chip.get = gta02_gpb_get; +} + static void __init gta02_machine_init(void) { int rc; @@ -1652,6 +1704,8 @@ static void __init gta02_machine_init(void) default: break; } + if (S3C_SYSTEM_REV_ATAG <= GTA02v5_SYSTEM_REV) + gta02_hijack_gpb(); spin_lock_init(&motion_irq_lock); |