OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [leds/] [leds-gpio.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * LEDs driver for GPIOs
3
 *
4
 * Copyright (C) 2007 8D Technologies inc.
5
 * Raphael Assenat <raph@8d.com>
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License version 2 as
9
 * published by the Free Software Foundation.
10
 *
11
 */
12
#include <linux/kernel.h>
13
#include <linux/init.h>
14
#include <linux/platform_device.h>
15
#include <linux/leds.h>
16
#include <linux/workqueue.h>
17
 
18
#include <asm/gpio.h>
19
 
20
struct gpio_led_data {
21
        struct led_classdev cdev;
22
        unsigned gpio;
23
        struct work_struct work;
24
        u8 new_level;
25
        u8 can_sleep;
26
        u8 active_low;
27
};
28
 
29
static void gpio_led_work(struct work_struct *work)
30
{
31
        struct gpio_led_data    *led_dat =
32
                container_of(work, struct gpio_led_data, work);
33
 
34
        gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level);
35
}
36
 
37
static void gpio_led_set(struct led_classdev *led_cdev,
38
        enum led_brightness value)
39
{
40
        struct gpio_led_data *led_dat =
41
                container_of(led_cdev, struct gpio_led_data, cdev);
42
        int level;
43
 
44
        if (value == LED_OFF)
45
                level = 0;
46
        else
47
                level = 1;
48
 
49
        if (led_dat->active_low)
50
                level = !level;
51
 
52
        /* setting GPIOs with I2C/etc requires a preemptible task context */
53
        if (led_dat->can_sleep) {
54
                if (preempt_count()) {
55
                        led_dat->new_level = level;
56
                        schedule_work(&led_dat->work);
57
                } else
58
                        gpio_set_value_cansleep(led_dat->gpio, level);
59
        } else
60
                gpio_set_value(led_dat->gpio, level);
61
}
62
 
63
static int gpio_led_probe(struct platform_device *pdev)
64
{
65
        struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
66
        struct gpio_led *cur_led;
67
        struct gpio_led_data *leds_data, *led_dat;
68
        int i, ret = 0;
69
 
70
        if (!pdata)
71
                return -EBUSY;
72
 
73
        leds_data = kzalloc(sizeof(struct gpio_led_data) * pdata->num_leds,
74
                                GFP_KERNEL);
75
        if (!leds_data)
76
                return -ENOMEM;
77
 
78
        for (i = 0; i < pdata->num_leds; i++) {
79
                cur_led = &pdata->leds[i];
80
                led_dat = &leds_data[i];
81
 
82
                led_dat->cdev.name = cur_led->name;
83
                led_dat->cdev.default_trigger = cur_led->default_trigger;
84
                led_dat->gpio = cur_led->gpio;
85
                led_dat->can_sleep = gpio_cansleep(cur_led->gpio);
86
                led_dat->active_low = cur_led->active_low;
87
                led_dat->cdev.brightness_set = gpio_led_set;
88
                led_dat->cdev.brightness = cur_led->active_low ? LED_FULL : LED_OFF;
89
 
90
                ret = gpio_request(led_dat->gpio, led_dat->cdev.name);
91
                if (ret < 0)
92
                        goto err;
93
 
94
                gpio_direction_output(led_dat->gpio, led_dat->active_low);
95
 
96
                INIT_WORK(&led_dat->work, gpio_led_work);
97
 
98
                ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
99
                if (ret < 0) {
100
                        gpio_free(led_dat->gpio);
101
                        goto err;
102
                }
103
        }
104
 
105
        platform_set_drvdata(pdev, leds_data);
106
 
107
        return 0;
108
 
109
err:
110
        if (i > 0) {
111
                for (i = i - 1; i >= 0; i--) {
112
                        led_classdev_unregister(&leds_data[i].cdev);
113
                        cancel_work_sync(&leds_data[i].work);
114
                        gpio_free(leds_data[i].gpio);
115
                }
116
        }
117
 
118
        kfree(leds_data);
119
 
120
        return ret;
121
}
122
 
123
static int __devexit gpio_led_remove(struct platform_device *pdev)
124
{
125
        int i;
126
        struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
127
        struct gpio_led_data *leds_data;
128
 
129
        leds_data = platform_get_drvdata(pdev);
130
 
131
        for (i = 0; i < pdata->num_leds; i++) {
132
                led_classdev_unregister(&leds_data[i].cdev);
133
                cancel_work_sync(&leds_data[i].work);
134
                gpio_free(leds_data[i].gpio);
135
        }
136
 
137
        kfree(leds_data);
138
 
139
        return 0;
140
}
141
 
142
#ifdef CONFIG_PM
143
static int gpio_led_suspend(struct platform_device *pdev, pm_message_t state)
144
{
145
        struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
146
        struct gpio_led_data *leds_data;
147
        int i;
148
 
149
        leds_data = platform_get_drvdata(pdev);
150
 
151
        for (i = 0; i < pdata->num_leds; i++)
152
                led_classdev_suspend(&leds_data[i].cdev);
153
 
154
        return 0;
155
}
156
 
157
static int gpio_led_resume(struct platform_device *pdev)
158
{
159
        struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
160
        struct gpio_led_data *leds_data;
161
        int i;
162
 
163
        leds_data = platform_get_drvdata(pdev);
164
 
165
        for (i = 0; i < pdata->num_leds; i++)
166
                led_classdev_resume(&leds_data[i].cdev);
167
 
168
        return 0;
169
}
170
#else
171
#define gpio_led_suspend NULL
172
#define gpio_led_resume NULL
173
#endif
174
 
175
static struct platform_driver gpio_led_driver = {
176
        .probe          = gpio_led_probe,
177
        .remove         = __devexit_p(gpio_led_remove),
178
        .suspend        = gpio_led_suspend,
179
        .resume         = gpio_led_resume,
180
        .driver         = {
181
                .name   = "leds-gpio",
182
                .owner  = THIS_MODULE,
183
        },
184
};
185
 
186
static int __init gpio_led_init(void)
187
{
188
        return platform_driver_register(&gpio_led_driver);
189
}
190
 
191
static void __exit gpio_led_exit(void)
192
{
193
        platform_driver_unregister(&gpio_led_driver);
194
}
195
 
196
module_init(gpio_led_init);
197
module_exit(gpio_led_exit);
198
 
199
MODULE_AUTHOR("Raphael Assenat <raph@8d.com>");
200
MODULE_DESCRIPTION("GPIO LED driver");
201
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.