diff options
author | lars <lars@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-05-18 17:55:41 +0000 |
---|---|---|
committer | lars <lars@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-05-18 17:55:41 +0000 |
commit | fb189822fcab111e55d1c7e83c482dc2c144500a (patch) | |
tree | dd10e61f382ace3afbe40af3af8238757cf5e3d0 /target/linux/s3c24xx/files-2.6.30/drivers/leds | |
parent | c5f7c391b56bb88e21895f0fc9310cd0919e8d0c (diff) |
[s3c24xx] bump to 2.6.30-rc6
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@15918 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/s3c24xx/files-2.6.30/drivers/leds')
-rw-r--r-- | target/linux/s3c24xx/files-2.6.30/drivers/leds/leds-gta02-vibrator.c | 192 | ||||
-rw-r--r-- | target/linux/s3c24xx/files-2.6.30/drivers/leds/leds-gta02.c | 179 |
2 files changed, 371 insertions, 0 deletions
diff --git a/target/linux/s3c24xx/files-2.6.30/drivers/leds/leds-gta02-vibrator.c b/target/linux/s3c24xx/files-2.6.30/drivers/leds/leds-gta02-vibrator.c new file mode 100644 index 0000000000..653a9fb287 --- /dev/null +++ b/target/linux/s3c24xx/files-2.6.30/drivers/leds/leds-gta02-vibrator.c @@ -0,0 +1,192 @@ +/* + * LED driver for the vibrator of the Openmoko GTA01/GTA02 GSM Phones + * + * (C) 2006-2008 by Openmoko, Inc. + * Author: Harald Welte <laforge@openmoko.org> + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Javi Roman <javiroman@kernel-labs.org>: + * Implement PWM support for GTA01Bv4 and later + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/leds.h> +#include <mach/hardware.h> +#include <asm/mach-types.h> +#include <plat/pwm.h> +#include <mach/regs-gpio.h> +#include <plat/regs-timer.h> +#include <linux/gta02-vibrator.h> + +#include <linux/gta02-shadow.h> + +#define COUNTER 64 + +static struct gta02_vib_priv { + struct led_classdev cdev; + unsigned int gpio; + spinlock_t lock; + unsigned int has_pwm; + struct s3c2410_pwm pwm; + + unsigned long vib_gpio_pin; /* which pin to meddle with */ + u8 vib_pwm; /* 0 = OFF -- will ensure GPIO deasserted and stop FIQ */ + u8 vib_pwm_latched; + u32 fiq_count; + + struct gta02_vib_platform_data *pdata; +} gta02_vib_priv; + +int gta02_vibrator_fiq_handler(void) +{ + gta02_vib_priv.fiq_count++; + + if (!gta02_vib_priv.vib_pwm_latched && !gta02_vib_priv.vib_pwm) + /* idle */ + return 0; + + if ((u8)gta02_vib_priv.fiq_count == gta02_vib_priv.vib_pwm_latched) + gta02_gpb_setpin(gta02_vib_priv.vib_gpio_pin, 0); + + if ((u8)gta02_vib_priv.fiq_count) + return 1; + + gta02_vib_priv.vib_pwm_latched = gta02_vib_priv.vib_pwm; + if (gta02_vib_priv.vib_pwm_latched) + gta02_gpb_setpin(gta02_vib_priv.vib_gpio_pin, 1); + + return 1; +} + +static void gta02_vib_vib_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + gta02_vib_priv.vib_pwm = value; /* set it for FIQ */ + gta02_vib_priv.pdata->kick_fiq(); /* start up FIQs if not already going */ +} + +static struct gta02_vib_priv gta02_vib_led = { + .cdev = { + .name = "gta02:vibrator", + .brightness_set = gta02_vib_vib_set, + }, +}; + +static int gta02_vib_init_hw(struct gta02_vib_priv *vp) +{ + int rc; + + rc = s3c2410_pwm_init(&vp->pwm); + if (rc) + return rc; + + vp->pwm.timerid = PWM3; + /* use same prescaler as arch/arm/plat-s3c24xx/time.c */ + vp->pwm.prescaler = (6 - 1) / 2; + vp->pwm.divider = S3C2410_TCFG1_MUX3_DIV2; + vp->pwm.counter = COUNTER; + vp->pwm.comparer = COUNTER; + + rc = s3c2410_pwm_enable(&vp->pwm); + if (rc) + return rc; + + s3c2410_pwm_start(&vp->pwm); + + return 0; +} + +#ifdef CONFIG_PM +static int gta02_vib_suspend(struct platform_device *dev, pm_message_t state) +{ + led_classdev_suspend(>a02_vib_led.cdev); + if (gta02_vib_priv.pdata) + gta02_vib_priv.pdata->disable_fiq(); + return 0; +} + +static int gta02_vib_resume(struct platform_device *dev) +{ + struct gta02_vib_priv *vp = platform_get_drvdata(dev); + + if (vp->has_pwm) + gta02_vib_init_hw(vp); + + led_classdev_resume(>a02_vib_led.cdev); + if (gta02_vib_priv.pdata) + gta02_vib_priv.pdata->enable_fiq(); + + return 0; +} +#endif /* CONFIG_PM */ + +static int __init gta02_vib_probe(struct platform_device *pdev) +{ + struct resource *r; + + r = platform_get_resource(pdev, 0, 0); + if (!r || !r->start) + return -EIO; + + gta02_vib_led.gpio = r->start; + + gta02_vib_priv.pdata = pdev->dev.platform_data; + platform_set_drvdata(pdev, >a02_vib_led); + + gta02_gpb_setpin(gta02_vib_led.gpio, 0); /* off */ + s3c2410_gpio_cfgpin(gta02_vib_led.gpio, S3C2410_GPIO_OUTPUT); + /* safe, kmalloc'd copy needed for FIQ ISR */ + gta02_vib_priv.vib_gpio_pin = gta02_vib_led.gpio; + gta02_vib_priv.vib_pwm = 0; /* off */ + spin_lock_init(>a02_vib_led.lock); + + return led_classdev_register(&pdev->dev, >a02_vib_led.cdev); +} + +static int gta02_vib_remove(struct platform_device *pdev) +{ + gta02_vib_priv.vib_pwm = 0; /* off */ + /* would only need kick if already off so no kick needed */ + + if (gta02_vib_led.has_pwm) + s3c2410_pwm_disable(>a02_vib_led.pwm); + + led_classdev_unregister(>a02_vib_led.cdev); + + return 0; +} + +static struct platform_driver gta02_vib_driver = { + .probe = gta02_vib_probe, + .remove = gta02_vib_remove, +#ifdef CONFIG_PM + .suspend = gta02_vib_suspend, + .resume = gta02_vib_resume, +#endif + .driver = { + .name = "gta02-vibrator", + }, +}; + +static int __init gta02_vib_init(void) +{ + return platform_driver_register(>a02_vib_driver); +} + +static void __exit gta02_vib_exit(void) +{ + platform_driver_unregister(>a02_vib_driver); +} + +module_init(gta02_vib_init); +module_exit(gta02_vib_exit); + +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>"); +MODULE_DESCRIPTION("Openmoko Freerunner vibrator driver"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/s3c24xx/files-2.6.30/drivers/leds/leds-gta02.c b/target/linux/s3c24xx/files-2.6.30/drivers/leds/leds-gta02.c new file mode 100644 index 0000000000..1d65eeaf30 --- /dev/null +++ b/target/linux/s3c24xx/files-2.6.30/drivers/leds/leds-gta02.c @@ -0,0 +1,179 @@ +/* + * LED driver for the Openmoko GTA02 GSM phone + * + * (C) 2006-2008 by Openmoko, Inc. + * Author: Harald Welte <laforge@openmoko.org> + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/leds.h> +#include <mach/hardware.h> +#include <asm/mach-types.h> +#include <mach/gta02.h> +#include <plat/regs-timer.h> +#include <linux/gta02-shadow.h> + +#define MAX_LEDS 3 +#define COUNTER 256 + +struct gta02_led_priv +{ + spinlock_t lock; + struct led_classdev cdev; + unsigned int gpio; +}; + +struct gta02_led_bundle +{ + int num_leds; + struct gta02_led_priv led[MAX_LEDS]; +}; + +static inline struct gta02_led_priv *to_priv(struct led_classdev *led_cdev) +{ + return container_of(led_cdev, struct gta02_led_priv, cdev); +} + +static inline struct gta02_led_bundle *to_bundle(struct led_classdev *led_cdev) +{ + return dev_get_drvdata(led_cdev->dev->parent); +} + +static void gta02led_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + unsigned long flags; + struct gta02_led_priv *lp = to_priv(led_cdev); + + spin_lock_irqsave(&lp->lock, flags); + gta02_gpb_setpin(lp->gpio, value ? 1 : 0); + spin_unlock_irqrestore(&lp->lock, flags); +} + +#ifdef CONFIG_PM +static int gta02led_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct gta02_led_bundle *bundle = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < bundle->num_leds; i++) + led_classdev_suspend(&bundle->led[i].cdev); + + return 0; +} + +static int gta02led_resume(struct platform_device *pdev) +{ + struct gta02_led_bundle *bundle = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < bundle->num_leds; i++) + led_classdev_resume(&bundle->led[i].cdev); + + return 0; +} +#endif + +static int __init gta02led_probe(struct platform_device *pdev) +{ + int i, rc; + struct gta02_led_bundle *bundle; + + if (!machine_is_neo1973_gta02()) + return -EIO; + + bundle = kzalloc(sizeof(struct gta02_led_bundle), GFP_KERNEL); + if (!bundle) + return -ENOMEM; + platform_set_drvdata(pdev, bundle); + + for (i = 0; i < pdev->num_resources; i++) { + struct gta02_led_priv *lp; + struct resource *r; + + if (i >= MAX_LEDS) + break; + + r = platform_get_resource(pdev, 0, i); + if (!r || !r->start || !r->name) + continue; + + lp = &bundle->led[i]; + + lp->gpio = r->start; + lp->cdev.name = r->name; + lp->cdev.brightness_set = gta02led_set; + + switch (lp->gpio) { + case S3C2410_GPB0: + case S3C2410_GPB1: + case S3C2410_GPB2: + s3c2410_gpio_cfgpin(lp->gpio, S3C2410_GPIO_OUTPUT); + gta02_gpb_add_shadow_gpio(lp->gpio); + break; + default: + break; + } + + spin_lock_init(&lp->lock); + rc = led_classdev_register(&pdev->dev, &lp->cdev); + } + + bundle->num_leds = i; + + return 0; +} + +static int gta02led_remove(struct platform_device *pdev) +{ + struct gta02_led_bundle *bundle = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < bundle->num_leds; i++) { + struct gta02_led_priv *lp = &bundle->led[i]; + gta02led_set(&lp->cdev, 0); + led_classdev_unregister(&lp->cdev); + } + + platform_set_drvdata(pdev, NULL); + kfree(bundle); + + return 0; +} + +static struct platform_driver gta02led_driver = { + .probe = gta02led_probe, + .remove = gta02led_remove, +#ifdef CONFIG_PM + .suspend = gta02led_suspend, + .resume = gta02led_resume, +#endif + .driver = { + .name = "gta02-led", + }, +}; + +static int __init gta02led_init(void) +{ + return platform_driver_register(>a02led_driver); +} + +static void __exit gta02led_exit(void) +{ + platform_driver_unregister(>a02led_driver); +} + +module_init(gta02led_init); +module_exit(gta02led_exit); + +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>"); +MODULE_DESCRIPTION("Openmoko GTA02 LED driver"); +MODULE_LICENSE("GPL"); |