Root/drivers/leds/leds-s3c24xx.c

1/* drivers/leds/leds-s3c24xx.c
2 *
3 * (c) 2006 Simtec Electronics
4 * http://armlinux.simtec.co.uk/
5 * Ben Dooks <ben@simtec.co.uk>
6 *
7 * S3C24XX - LEDs GPIO driver
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12*/
13
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/platform_device.h>
17#include <linux/leds.h>
18#include <linux/gpio.h>
19#include <linux/slab.h>
20#include <linux/module.h>
21
22#include <mach/hardware.h>
23#include <mach/regs-gpio.h>
24#include <linux/platform_data/leds-s3c24xx.h>
25
26/* our context */
27
28struct s3c24xx_gpio_led {
29    struct led_classdev cdev;
30    struct s3c24xx_led_platdata *pdata;
31};
32
33static inline struct s3c24xx_gpio_led *pdev_to_gpio(struct platform_device *dev)
34{
35    return platform_get_drvdata(dev);
36}
37
38static inline struct s3c24xx_gpio_led *to_gpio(struct led_classdev *led_cdev)
39{
40    return container_of(led_cdev, struct s3c24xx_gpio_led, cdev);
41}
42
43static void s3c24xx_led_set(struct led_classdev *led_cdev,
44                enum led_brightness value)
45{
46    struct s3c24xx_gpio_led *led = to_gpio(led_cdev);
47    struct s3c24xx_led_platdata *pd = led->pdata;
48    int state = (value ? 1 : 0) ^ (pd->flags & S3C24XX_LEDF_ACTLOW);
49
50    /* there will be a short delay between setting the output and
51     * going from output to input when using tristate. */
52
53    gpio_set_value(pd->gpio, state);
54
55    if (pd->flags & S3C24XX_LEDF_TRISTATE) {
56        if (value)
57            gpio_direction_output(pd->gpio, state);
58        else
59            gpio_direction_input(pd->gpio);
60    }
61}
62
63static int s3c24xx_led_remove(struct platform_device *dev)
64{
65    struct s3c24xx_gpio_led *led = pdev_to_gpio(dev);
66
67    led_classdev_unregister(&led->cdev);
68
69    return 0;
70}
71
72static int s3c24xx_led_probe(struct platform_device *dev)
73{
74    struct s3c24xx_led_platdata *pdata = dev->dev.platform_data;
75    struct s3c24xx_gpio_led *led;
76    int ret;
77
78    led = devm_kzalloc(&dev->dev, sizeof(struct s3c24xx_gpio_led),
79               GFP_KERNEL);
80    if (led == NULL) {
81        dev_err(&dev->dev, "No memory for device\n");
82        return -ENOMEM;
83    }
84
85    platform_set_drvdata(dev, led);
86
87    led->cdev.brightness_set = s3c24xx_led_set;
88    led->cdev.default_trigger = pdata->def_trigger;
89    led->cdev.name = pdata->name;
90    led->cdev.flags |= LED_CORE_SUSPENDRESUME;
91
92    led->pdata = pdata;
93
94    ret = devm_gpio_request(&dev->dev, pdata->gpio, "S3C24XX_LED");
95    if (ret < 0)
96        return ret;
97
98    /* no point in having a pull-up if we are always driving */
99
100    s3c_gpio_setpull(pdata->gpio, S3C_GPIO_PULL_NONE);
101
102    if (pdata->flags & S3C24XX_LEDF_TRISTATE)
103        gpio_direction_input(pdata->gpio);
104    else
105        gpio_direction_output(pdata->gpio,
106            pdata->flags & S3C24XX_LEDF_ACTLOW ? 1 : 0);
107
108    /* register our new led device */
109
110    ret = led_classdev_register(&dev->dev, &led->cdev);
111    if (ret < 0)
112        dev_err(&dev->dev, "led_classdev_register failed\n");
113
114    return ret;
115}
116
117static struct platform_driver s3c24xx_led_driver = {
118    .probe = s3c24xx_led_probe,
119    .remove = s3c24xx_led_remove,
120    .driver = {
121        .name = "s3c24xx_led",
122        .owner = THIS_MODULE,
123    },
124};
125
126module_platform_driver(s3c24xx_led_driver);
127
128MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
129MODULE_DESCRIPTION("S3C24XX LED driver");
130MODULE_LICENSE("GPL");
131MODULE_ALIAS("platform:s3c24xx_led");
132

Archive Download this file



interactive