Version:  2.0.40 2.2.26 2.4.37 2.6.39 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15

Linux/drivers/leds/leds-lt3593.c

  1 /*
  2  * LEDs driver for LT3593 controllers
  3  *
  4  * See the datasheet at http://cds.linear.com/docs/Datasheet/3593f.pdf
  5  *
  6  * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
  7  *
  8  * Based on leds-gpio.c,
  9  *
 10  *   Copyright (C) 2007 8D Technologies inc.
 11  *   Raphael Assenat <raph@8d.com>
 12  *   Copyright (C) 2008 Freescale Semiconductor, Inc.
 13  *
 14  * This program is free software; you can redistribute it and/or modify
 15  * it under the terms of the GNU General Public License version 2 as
 16  * published by the Free Software Foundation.
 17  */
 18 
 19 #include <linux/kernel.h>
 20 #include <linux/platform_device.h>
 21 #include <linux/leds.h>
 22 #include <linux/workqueue.h>
 23 #include <linux/delay.h>
 24 #include <linux/gpio.h>
 25 #include <linux/slab.h>
 26 #include <linux/module.h>
 27 
 28 struct lt3593_led_data {
 29         struct led_classdev cdev;
 30         unsigned gpio;
 31         struct work_struct work;
 32         u8 new_level;
 33 };
 34 
 35 static void lt3593_led_work(struct work_struct *work)
 36 {
 37         int pulses;
 38         struct lt3593_led_data *led_dat =
 39                 container_of(work, struct lt3593_led_data, work);
 40 
 41         /*
 42          * The LT3593 resets its internal current level register to the maximum
 43          * level on the first falling edge on the control pin. Each following
 44          * falling edge decreases the current level by 625uA. Up to 32 pulses
 45          * can be sent, so the maximum power reduction is 20mA.
 46          * After a timeout of 128us, the value is taken from the register and
 47          * applied is to the output driver.
 48          */
 49 
 50         if (led_dat->new_level == 0) {
 51                 gpio_set_value_cansleep(led_dat->gpio, 0);
 52                 return;
 53         }
 54 
 55         pulses = 32 - (led_dat->new_level * 32) / 255;
 56 
 57         if (pulses == 0) {
 58                 gpio_set_value_cansleep(led_dat->gpio, 0);
 59                 mdelay(1);
 60                 gpio_set_value_cansleep(led_dat->gpio, 1);
 61                 return;
 62         }
 63 
 64         gpio_set_value_cansleep(led_dat->gpio, 1);
 65 
 66         while (pulses--) {
 67                 gpio_set_value_cansleep(led_dat->gpio, 0);
 68                 udelay(1);
 69                 gpio_set_value_cansleep(led_dat->gpio, 1);
 70                 udelay(1);
 71         }
 72 }
 73 
 74 static void lt3593_led_set(struct led_classdev *led_cdev,
 75         enum led_brightness value)
 76 {
 77         struct lt3593_led_data *led_dat =
 78                 container_of(led_cdev, struct lt3593_led_data, cdev);
 79 
 80         led_dat->new_level = value;
 81         schedule_work(&led_dat->work);
 82 }
 83 
 84 static int create_lt3593_led(const struct gpio_led *template,
 85         struct lt3593_led_data *led_dat, struct device *parent)
 86 {
 87         int ret, state;
 88 
 89         /* skip leds on GPIOs that aren't available */
 90         if (!gpio_is_valid(template->gpio)) {
 91                 dev_info(parent, "%s: skipping unavailable LT3593 LED at gpio %d (%s)\n",
 92                                 KBUILD_MODNAME, template->gpio, template->name);
 93                 return 0;
 94         }
 95 
 96         led_dat->cdev.name = template->name;
 97         led_dat->cdev.default_trigger = template->default_trigger;
 98         led_dat->gpio = template->gpio;
 99 
100         led_dat->cdev.brightness_set = lt3593_led_set;
101 
102         state = (template->default_state == LEDS_GPIO_DEFSTATE_ON);
103         led_dat->cdev.brightness = state ? LED_FULL : LED_OFF;
104 
105         if (!template->retain_state_suspended)
106                 led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
107 
108         ret = devm_gpio_request_one(parent, template->gpio, state ?
109                                     GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
110                                     template->name);
111         if (ret < 0)
112                 return ret;
113 
114         INIT_WORK(&led_dat->work, lt3593_led_work);
115 
116         ret = led_classdev_register(parent, &led_dat->cdev);
117         if (ret < 0)
118                 return ret;
119 
120         dev_info(parent, "%s: registered LT3593 LED '%s' at GPIO %d\n",
121                 KBUILD_MODNAME, template->name, template->gpio);
122 
123         return 0;
124 }
125 
126 static void delete_lt3593_led(struct lt3593_led_data *led)
127 {
128         if (!gpio_is_valid(led->gpio))
129                 return;
130 
131         led_classdev_unregister(&led->cdev);
132         cancel_work_sync(&led->work);
133 }
134 
135 static int lt3593_led_probe(struct platform_device *pdev)
136 {
137         struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
138         struct lt3593_led_data *leds_data;
139         int i, ret = 0;
140 
141         if (!pdata)
142                 return -EBUSY;
143 
144         leds_data = devm_kzalloc(&pdev->dev,
145                         sizeof(struct lt3593_led_data) * pdata->num_leds,
146                         GFP_KERNEL);
147         if (!leds_data)
148                 return -ENOMEM;
149 
150         for (i = 0; i < pdata->num_leds; i++) {
151                 ret = create_lt3593_led(&pdata->leds[i], &leds_data[i],
152                                       &pdev->dev);
153                 if (ret < 0)
154                         goto err;
155         }
156 
157         platform_set_drvdata(pdev, leds_data);
158 
159         return 0;
160 
161 err:
162         for (i = i - 1; i >= 0; i--)
163                 delete_lt3593_led(&leds_data[i]);
164 
165         return ret;
166 }
167 
168 static int lt3593_led_remove(struct platform_device *pdev)
169 {
170         int i;
171         struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
172         struct lt3593_led_data *leds_data;
173 
174         leds_data = platform_get_drvdata(pdev);
175 
176         for (i = 0; i < pdata->num_leds; i++)
177                 delete_lt3593_led(&leds_data[i]);
178 
179         return 0;
180 }
181 
182 static struct platform_driver lt3593_led_driver = {
183         .probe          = lt3593_led_probe,
184         .remove         = lt3593_led_remove,
185         .driver         = {
186                 .name   = "leds-lt3593",
187                 .owner  = THIS_MODULE,
188         },
189 };
190 
191 module_platform_driver(lt3593_led_driver);
192 
193 MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
194 MODULE_DESCRIPTION("LED driver for LT3593 controllers");
195 MODULE_LICENSE("GPL");
196 MODULE_ALIAS("platform:leds-lt3593");
197 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us