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/init.h> 21 #include <linux/platform_device.h> 22 #include <linux/leds.h> 23 #include <linux/workqueue.h> 24 #include <linux/delay.h> 25 #include <linux/gpio.h> 26 27 struct lt3593_led_data { 28 struct led_classdev cdev; 29 unsigned gpio; 30 struct work_struct work; 31 u8 new_level; 32 }; 33 34 static void lt3593_led_work(struct work_struct *work) 35 { 36 int pulses; 37 struct lt3593_led_data *led_dat = 38 container_of(work, struct lt3593_led_data, work); 39 40 /* 41 * The LT3593 resets its internal current level register to the maximum 42 * level on the first falling edge on the control pin. Each following 43 * falling edge decreases the current level by 625uA. Up to 32 pulses 44 * can be sent, so the maximum power reduction is 20mA. 45 * After a timeout of 128us, the value is taken from the register and 46 * applied is to the output driver. 47 */ 48 49 if (led_dat->new_level == 0) { 50 gpio_set_value_cansleep(led_dat->gpio, 0); 51 return; 52 } 53 54 pulses = 32 - (led_dat->new_level * 32) / 255; 55 56 if (pulses == 0) { 57 gpio_set_value_cansleep(led_dat->gpio, 0); 58 mdelay(1); 59 gpio_set_value_cansleep(led_dat->gpio, 1); 60 return; 61 } 62 63 gpio_set_value_cansleep(led_dat->gpio, 1); 64 65 while (pulses--) { 66 gpio_set_value_cansleep(led_dat->gpio, 0); 67 udelay(1); 68 gpio_set_value_cansleep(led_dat->gpio, 1); 69 udelay(1); 70 } 71 } 72 73 static void lt3593_led_set(struct led_classdev *led_cdev, 74 enum led_brightness value) 75 { 76 struct lt3593_led_data *led_dat = 77 container_of(led_cdev, struct lt3593_led_data, cdev); 78 79 led_dat->new_level = value; 80 schedule_work(&led_dat->work); 81 } 82 83 static int __devinit create_lt3593_led(const struct gpio_led *template, 84 struct lt3593_led_data *led_dat, struct device *parent) 85 { 86 int ret, state; 87 88 /* skip leds on GPIOs that aren't available */ 89 if (!gpio_is_valid(template->gpio)) { 90 printk(KERN_INFO "%s: skipping unavailable LT3593 LED at gpio %d (%s)\n", 91 KBUILD_MODNAME, template->gpio, template->name); 92 return 0; 93 } 94 95 ret = gpio_request(template->gpio, template->name); 96 if (ret < 0) 97 return ret; 98 99 led_dat->cdev.name = template->name; 100 led_dat->cdev.default_trigger = template->default_trigger; 101 led_dat->gpio = template->gpio; 102 103 led_dat->cdev.brightness_set = lt3593_led_set; 104 105 state = (template->default_state == LEDS_GPIO_DEFSTATE_ON); 106 led_dat->cdev.brightness = state ? LED_FULL : LED_OFF; 107 108 if (!template->retain_state_suspended) 109 led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; 110 111 ret = gpio_direction_output(led_dat->gpio, state); 112 if (ret < 0) 113 goto err; 114 115 INIT_WORK(&led_dat->work, lt3593_led_work); 116 117 ret = led_classdev_register(parent, &led_dat->cdev); 118 if (ret < 0) 119 goto err; 120 121 printk(KERN_INFO "%s: registered LT3593 LED '%s' at GPIO %d\n", 122 KBUILD_MODNAME, template->name, template->gpio); 123 124 return 0; 125 126 err: 127 gpio_free(led_dat->gpio); 128 return ret; 129 } 130 131 static void delete_lt3593_led(struct lt3593_led_data *led) 132 { 133 if (!gpio_is_valid(led->gpio)) 134 return; 135 136 led_classdev_unregister(&led->cdev); 137 cancel_work_sync(&led->work); 138 gpio_free(led->gpio); 139 } 140 141 static int __devinit lt3593_led_probe(struct platform_device *pdev) 142 { 143 struct gpio_led_platform_data *pdata = pdev->dev.platform_data; 144 struct lt3593_led_data *leds_data; 145 int i, ret = 0; 146 147 if (!pdata) 148 return -EBUSY; 149 150 leds_data = kzalloc(sizeof(struct lt3593_led_data) * pdata->num_leds, 151 GFP_KERNEL); 152 if (!leds_data) 153 return -ENOMEM; 154 155 for (i = 0; i < pdata->num_leds; i++) { 156 ret = create_lt3593_led(&pdata->leds[i], &leds_data[i], 157 &pdev->dev); 158 if (ret < 0) 159 goto err; 160 } 161 162 platform_set_drvdata(pdev, leds_data); 163 164 return 0; 165 166 err: 167 for (i = i - 1; i >= 0; i--) 168 delete_lt3593_led(&leds_data[i]); 169 170 kfree(leds_data); 171 172 return ret; 173 } 174 175 static int __devexit lt3593_led_remove(struct platform_device *pdev) 176 { 177 int i; 178 struct gpio_led_platform_data *pdata = pdev->dev.platform_data; 179 struct lt3593_led_data *leds_data; 180 181 leds_data = platform_get_drvdata(pdev); 182 183 for (i = 0; i < pdata->num_leds; i++) 184 delete_lt3593_led(&leds_data[i]); 185 186 kfree(leds_data); 187 188 return 0; 189 } 190 191 static struct platform_driver lt3593_led_driver = { 192 .probe = lt3593_led_probe, 193 .remove = __devexit_p(lt3593_led_remove), 194 .driver = { 195 .name = "leds-lt3593", 196 .owner = THIS_MODULE, 197 }, 198 }; 199 200 MODULE_ALIAS("platform:leds-lt3593"); 201 202 static int __init lt3593_led_init(void) 203 { 204 return platform_driver_register(<3593_led_driver); 205 } 206 207 static void __exit lt3593_led_exit(void) 208 { 209 platform_driver_unregister(<3593_led_driver); 210 } 211 212 module_init(lt3593_led_init); 213 module_exit(lt3593_led_exit); 214 215 MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); 216 MODULE_DESCRIPTION("LED driver for LT3593 controllers"); 217 MODULE_LICENSE("GPL"); 218