124467832SSimon Guinot /* 224467832SSimon Guinot * leds-netxbig.c - Driver for the 2Big and 5Big Network series LEDs 324467832SSimon Guinot * 424467832SSimon Guinot * Copyright (C) 2010 LaCie 524467832SSimon Guinot * 624467832SSimon Guinot * Author: Simon Guinot <sguinot@lacie.com> 724467832SSimon Guinot * 824467832SSimon Guinot * This program is free software; you can redistribute it and/or modify 924467832SSimon Guinot * it under the terms of the GNU General Public License as published by 1024467832SSimon Guinot * the Free Software Foundation; either version 2 of the License, or 1124467832SSimon Guinot * (at your option) any later version. 1224467832SSimon Guinot * 1324467832SSimon Guinot * This program is distributed in the hope that it will be useful, 1424467832SSimon Guinot * but WITHOUT ANY WARRANTY; without even the implied warranty of 1524467832SSimon Guinot * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1624467832SSimon Guinot * GNU General Public License for more details. 1724467832SSimon Guinot * 1824467832SSimon Guinot * You should have received a copy of the GNU General Public License 1924467832SSimon Guinot * along with this program; if not, write to the Free Software 2024467832SSimon Guinot * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 2124467832SSimon Guinot */ 2224467832SSimon Guinot 2324467832SSimon Guinot #include <linux/module.h> 2424467832SSimon Guinot #include <linux/irq.h> 2524467832SSimon Guinot #include <linux/slab.h> 2624467832SSimon Guinot #include <linux/spinlock.h> 2724467832SSimon Guinot #include <linux/platform_device.h> 2824467832SSimon Guinot #include <linux/gpio.h> 2924467832SSimon Guinot #include <linux/leds.h> 30c02cecb9SArnd Bergmann #include <linux/platform_data/leds-kirkwood-netxbig.h> 3124467832SSimon Guinot 3224467832SSimon Guinot /* 3324467832SSimon Guinot * GPIO extension bus. 3424467832SSimon Guinot */ 3524467832SSimon Guinot 3624467832SSimon Guinot static DEFINE_SPINLOCK(gpio_ext_lock); 3724467832SSimon Guinot 3824467832SSimon Guinot static void gpio_ext_set_addr(struct netxbig_gpio_ext *gpio_ext, int addr) 3924467832SSimon Guinot { 4024467832SSimon Guinot int pin; 4124467832SSimon Guinot 4224467832SSimon Guinot for (pin = 0; pin < gpio_ext->num_addr; pin++) 4324467832SSimon Guinot gpio_set_value(gpio_ext->addr[pin], (addr >> pin) & 1); 4424467832SSimon Guinot } 4524467832SSimon Guinot 4624467832SSimon Guinot static void gpio_ext_set_data(struct netxbig_gpio_ext *gpio_ext, int data) 4724467832SSimon Guinot { 4824467832SSimon Guinot int pin; 4924467832SSimon Guinot 5024467832SSimon Guinot for (pin = 0; pin < gpio_ext->num_data; pin++) 5124467832SSimon Guinot gpio_set_value(gpio_ext->data[pin], (data >> pin) & 1); 5224467832SSimon Guinot } 5324467832SSimon Guinot 5424467832SSimon Guinot static void gpio_ext_enable_select(struct netxbig_gpio_ext *gpio_ext) 5524467832SSimon Guinot { 5624467832SSimon Guinot /* Enable select is done on the raising edge. */ 5724467832SSimon Guinot gpio_set_value(gpio_ext->enable, 0); 5824467832SSimon Guinot gpio_set_value(gpio_ext->enable, 1); 5924467832SSimon Guinot } 6024467832SSimon Guinot 6124467832SSimon Guinot static void gpio_ext_set_value(struct netxbig_gpio_ext *gpio_ext, 6224467832SSimon Guinot int addr, int value) 6324467832SSimon Guinot { 6424467832SSimon Guinot unsigned long flags; 6524467832SSimon Guinot 6624467832SSimon Guinot spin_lock_irqsave(&gpio_ext_lock, flags); 6724467832SSimon Guinot gpio_ext_set_addr(gpio_ext, addr); 6824467832SSimon Guinot gpio_ext_set_data(gpio_ext, value); 6924467832SSimon Guinot gpio_ext_enable_select(gpio_ext); 7024467832SSimon Guinot spin_unlock_irqrestore(&gpio_ext_lock, flags); 7124467832SSimon Guinot } 7224467832SSimon Guinot 7398ea1ea2SBill Pemberton static int gpio_ext_init(struct netxbig_gpio_ext *gpio_ext) 7424467832SSimon Guinot { 7524467832SSimon Guinot int err; 7624467832SSimon Guinot int i; 7724467832SSimon Guinot 7824467832SSimon Guinot if (unlikely(!gpio_ext)) 7924467832SSimon Guinot return -EINVAL; 8024467832SSimon Guinot 8124467832SSimon Guinot /* Configure address GPIOs. */ 8224467832SSimon Guinot for (i = 0; i < gpio_ext->num_addr; i++) { 83b96a573fSAxel Lin err = gpio_request_one(gpio_ext->addr[i], GPIOF_OUT_INIT_LOW, 84b96a573fSAxel Lin "GPIO extension addr"); 8524467832SSimon Guinot if (err) 8624467832SSimon Guinot goto err_free_addr; 8724467832SSimon Guinot } 8824467832SSimon Guinot /* Configure data GPIOs. */ 8924467832SSimon Guinot for (i = 0; i < gpio_ext->num_data; i++) { 90b96a573fSAxel Lin err = gpio_request_one(gpio_ext->data[i], GPIOF_OUT_INIT_LOW, 91b96a573fSAxel Lin "GPIO extension data"); 9224467832SSimon Guinot if (err) 9324467832SSimon Guinot goto err_free_data; 9424467832SSimon Guinot } 9524467832SSimon Guinot /* Configure "enable select" GPIO. */ 96b96a573fSAxel Lin err = gpio_request_one(gpio_ext->enable, GPIOF_OUT_INIT_LOW, 97b96a573fSAxel Lin "GPIO extension enable"); 9824467832SSimon Guinot if (err) 9924467832SSimon Guinot goto err_free_data; 10024467832SSimon Guinot 10124467832SSimon Guinot return 0; 10224467832SSimon Guinot 10324467832SSimon Guinot err_free_data: 10424467832SSimon Guinot for (i = i - 1; i >= 0; i--) 10524467832SSimon Guinot gpio_free(gpio_ext->data[i]); 10624467832SSimon Guinot i = gpio_ext->num_addr; 10724467832SSimon Guinot err_free_addr: 10824467832SSimon Guinot for (i = i - 1; i >= 0; i--) 10924467832SSimon Guinot gpio_free(gpio_ext->addr[i]); 11024467832SSimon Guinot 11124467832SSimon Guinot return err; 11224467832SSimon Guinot } 11324467832SSimon Guinot 114b8cd742aSArnd Bergmann static void gpio_ext_free(struct netxbig_gpio_ext *gpio_ext) 11524467832SSimon Guinot { 11624467832SSimon Guinot int i; 11724467832SSimon Guinot 11824467832SSimon Guinot gpio_free(gpio_ext->enable); 11924467832SSimon Guinot for (i = gpio_ext->num_addr - 1; i >= 0; i--) 12024467832SSimon Guinot gpio_free(gpio_ext->addr[i]); 12124467832SSimon Guinot for (i = gpio_ext->num_data - 1; i >= 0; i--) 12224467832SSimon Guinot gpio_free(gpio_ext->data[i]); 12324467832SSimon Guinot } 12424467832SSimon Guinot 12524467832SSimon Guinot /* 12624467832SSimon Guinot * Class LED driver. 12724467832SSimon Guinot */ 12824467832SSimon Guinot 12924467832SSimon Guinot struct netxbig_led_data { 13024467832SSimon Guinot struct netxbig_gpio_ext *gpio_ext; 13124467832SSimon Guinot struct led_classdev cdev; 13224467832SSimon Guinot int mode_addr; 13324467832SSimon Guinot int *mode_val; 13424467832SSimon Guinot int bright_addr; 13524467832SSimon Guinot int bright_max; 13624467832SSimon Guinot struct netxbig_led_timer *timer; 13724467832SSimon Guinot int num_timer; 13824467832SSimon Guinot enum netxbig_led_mode mode; 13924467832SSimon Guinot int sata; 14024467832SSimon Guinot spinlock_t lock; 14124467832SSimon Guinot }; 14224467832SSimon Guinot 14324467832SSimon Guinot static int netxbig_led_get_timer_mode(enum netxbig_led_mode *mode, 14424467832SSimon Guinot unsigned long delay_on, 14524467832SSimon Guinot unsigned long delay_off, 14624467832SSimon Guinot struct netxbig_led_timer *timer, 14724467832SSimon Guinot int num_timer) 14824467832SSimon Guinot { 14924467832SSimon Guinot int i; 15024467832SSimon Guinot 15124467832SSimon Guinot for (i = 0; i < num_timer; i++) { 15224467832SSimon Guinot if (timer[i].delay_on == delay_on && 15324467832SSimon Guinot timer[i].delay_off == delay_off) { 15424467832SSimon Guinot *mode = timer[i].mode; 15524467832SSimon Guinot return 0; 15624467832SSimon Guinot } 15724467832SSimon Guinot } 15824467832SSimon Guinot return -EINVAL; 15924467832SSimon Guinot } 16024467832SSimon Guinot 16124467832SSimon Guinot static int netxbig_led_blink_set(struct led_classdev *led_cdev, 16224467832SSimon Guinot unsigned long *delay_on, 16324467832SSimon Guinot unsigned long *delay_off) 16424467832SSimon Guinot { 16524467832SSimon Guinot struct netxbig_led_data *led_dat = 16624467832SSimon Guinot container_of(led_cdev, struct netxbig_led_data, cdev); 16724467832SSimon Guinot enum netxbig_led_mode mode; 16824467832SSimon Guinot int mode_val; 16924467832SSimon Guinot int ret; 17024467832SSimon Guinot 17124467832SSimon Guinot /* Look for a LED mode with the requested timer frequency. */ 17224467832SSimon Guinot ret = netxbig_led_get_timer_mode(&mode, *delay_on, *delay_off, 17324467832SSimon Guinot led_dat->timer, led_dat->num_timer); 17424467832SSimon Guinot if (ret < 0) 17524467832SSimon Guinot return ret; 17624467832SSimon Guinot 17724467832SSimon Guinot mode_val = led_dat->mode_val[mode]; 17824467832SSimon Guinot if (mode_val == NETXBIG_LED_INVALID_MODE) 17924467832SSimon Guinot return -EINVAL; 18024467832SSimon Guinot 18124467832SSimon Guinot spin_lock_irq(&led_dat->lock); 18224467832SSimon Guinot 18324467832SSimon Guinot gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val); 18424467832SSimon Guinot led_dat->mode = mode; 18524467832SSimon Guinot 18624467832SSimon Guinot spin_unlock_irq(&led_dat->lock); 18724467832SSimon Guinot 18824467832SSimon Guinot return 0; 18924467832SSimon Guinot } 19024467832SSimon Guinot 19124467832SSimon Guinot static void netxbig_led_set(struct led_classdev *led_cdev, 19224467832SSimon Guinot enum led_brightness value) 19324467832SSimon Guinot { 19424467832SSimon Guinot struct netxbig_led_data *led_dat = 19524467832SSimon Guinot container_of(led_cdev, struct netxbig_led_data, cdev); 19624467832SSimon Guinot enum netxbig_led_mode mode; 19724467832SSimon Guinot int mode_val, bright_val; 19824467832SSimon Guinot int set_brightness = 1; 19924467832SSimon Guinot unsigned long flags; 20024467832SSimon Guinot 20124467832SSimon Guinot spin_lock_irqsave(&led_dat->lock, flags); 20224467832SSimon Guinot 20324467832SSimon Guinot if (value == LED_OFF) { 20424467832SSimon Guinot mode = NETXBIG_LED_OFF; 20524467832SSimon Guinot set_brightness = 0; 20624467832SSimon Guinot } else { 20724467832SSimon Guinot if (led_dat->sata) 20824467832SSimon Guinot mode = NETXBIG_LED_SATA; 20924467832SSimon Guinot else if (led_dat->mode == NETXBIG_LED_OFF) 21024467832SSimon Guinot mode = NETXBIG_LED_ON; 21124467832SSimon Guinot else /* Keep 'timer' mode. */ 21224467832SSimon Guinot mode = led_dat->mode; 21324467832SSimon Guinot } 21424467832SSimon Guinot mode_val = led_dat->mode_val[mode]; 21524467832SSimon Guinot 21624467832SSimon Guinot gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val); 21724467832SSimon Guinot led_dat->mode = mode; 21824467832SSimon Guinot /* 21924467832SSimon Guinot * Note that the brightness register is shared between all the 22024467832SSimon Guinot * SATA LEDs. So, change the brightness setting for a single 22124467832SSimon Guinot * SATA LED will affect all the others. 22224467832SSimon Guinot */ 22324467832SSimon Guinot if (set_brightness) { 22424467832SSimon Guinot bright_val = DIV_ROUND_UP(value * led_dat->bright_max, 22524467832SSimon Guinot LED_FULL); 22624467832SSimon Guinot gpio_ext_set_value(led_dat->gpio_ext, 22724467832SSimon Guinot led_dat->bright_addr, bright_val); 22824467832SSimon Guinot } 22924467832SSimon Guinot 23024467832SSimon Guinot spin_unlock_irqrestore(&led_dat->lock, flags); 23124467832SSimon Guinot } 23224467832SSimon Guinot 23324467832SSimon Guinot static ssize_t netxbig_led_sata_store(struct device *dev, 23424467832SSimon Guinot struct device_attribute *attr, 23524467832SSimon Guinot const char *buff, size_t count) 23624467832SSimon Guinot { 23724467832SSimon Guinot struct led_classdev *led_cdev = dev_get_drvdata(dev); 23824467832SSimon Guinot struct netxbig_led_data *led_dat = 23924467832SSimon Guinot container_of(led_cdev, struct netxbig_led_data, cdev); 24024467832SSimon Guinot unsigned long enable; 24124467832SSimon Guinot enum netxbig_led_mode mode; 24224467832SSimon Guinot int mode_val; 24324467832SSimon Guinot int ret; 24424467832SSimon Guinot 2457517611aSJingoo Han ret = kstrtoul(buff, 10, &enable); 24624467832SSimon Guinot if (ret < 0) 24724467832SSimon Guinot return ret; 24824467832SSimon Guinot 24924467832SSimon Guinot enable = !!enable; 25024467832SSimon Guinot 25124467832SSimon Guinot spin_lock_irq(&led_dat->lock); 25224467832SSimon Guinot 25324467832SSimon Guinot if (led_dat->sata == enable) { 25424467832SSimon Guinot ret = count; 25524467832SSimon Guinot goto exit_unlock; 25624467832SSimon Guinot } 25724467832SSimon Guinot 25824467832SSimon Guinot if (led_dat->mode != NETXBIG_LED_ON && 25924467832SSimon Guinot led_dat->mode != NETXBIG_LED_SATA) 26024467832SSimon Guinot mode = led_dat->mode; /* Keep modes 'off' and 'timer'. */ 26124467832SSimon Guinot else if (enable) 26224467832SSimon Guinot mode = NETXBIG_LED_SATA; 26324467832SSimon Guinot else 26424467832SSimon Guinot mode = NETXBIG_LED_ON; 26524467832SSimon Guinot 26624467832SSimon Guinot mode_val = led_dat->mode_val[mode]; 26724467832SSimon Guinot if (mode_val == NETXBIG_LED_INVALID_MODE) { 26824467832SSimon Guinot ret = -EINVAL; 26924467832SSimon Guinot goto exit_unlock; 27024467832SSimon Guinot } 27124467832SSimon Guinot 27224467832SSimon Guinot gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val); 27324467832SSimon Guinot led_dat->mode = mode; 27424467832SSimon Guinot led_dat->sata = enable; 27524467832SSimon Guinot 27624467832SSimon Guinot ret = count; 27724467832SSimon Guinot 27824467832SSimon Guinot exit_unlock: 27924467832SSimon Guinot spin_unlock_irq(&led_dat->lock); 28024467832SSimon Guinot 28124467832SSimon Guinot return ret; 28224467832SSimon Guinot } 28324467832SSimon Guinot 28424467832SSimon Guinot static ssize_t netxbig_led_sata_show(struct device *dev, 28524467832SSimon Guinot struct device_attribute *attr, char *buf) 28624467832SSimon Guinot { 28724467832SSimon Guinot struct led_classdev *led_cdev = dev_get_drvdata(dev); 28824467832SSimon Guinot struct netxbig_led_data *led_dat = 28924467832SSimon Guinot container_of(led_cdev, struct netxbig_led_data, cdev); 29024467832SSimon Guinot 29124467832SSimon Guinot return sprintf(buf, "%d\n", led_dat->sata); 29224467832SSimon Guinot } 29324467832SSimon Guinot 29424467832SSimon Guinot static DEVICE_ATTR(sata, 0644, netxbig_led_sata_show, netxbig_led_sata_store); 29524467832SSimon Guinot 296588a6a99SJohan Hovold static struct attribute *netxbig_led_attrs[] = { 297588a6a99SJohan Hovold &dev_attr_sata.attr, 298588a6a99SJohan Hovold NULL 299588a6a99SJohan Hovold }; 300588a6a99SJohan Hovold ATTRIBUTE_GROUPS(netxbig_led); 301588a6a99SJohan Hovold 302b8cd742aSArnd Bergmann static void delete_netxbig_led(struct netxbig_led_data *led_dat) 30324467832SSimon Guinot { 30424467832SSimon Guinot led_classdev_unregister(&led_dat->cdev); 30524467832SSimon Guinot } 30624467832SSimon Guinot 30798ea1ea2SBill Pemberton static int 30824467832SSimon Guinot create_netxbig_led(struct platform_device *pdev, 30924467832SSimon Guinot struct netxbig_led_data *led_dat, 31024467832SSimon Guinot const struct netxbig_led *template) 31124467832SSimon Guinot { 31287aae1eaSJingoo Han struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev); 31324467832SSimon Guinot 31424467832SSimon Guinot spin_lock_init(&led_dat->lock); 31524467832SSimon Guinot led_dat->gpio_ext = pdata->gpio_ext; 31624467832SSimon Guinot led_dat->cdev.name = template->name; 31724467832SSimon Guinot led_dat->cdev.default_trigger = template->default_trigger; 31824467832SSimon Guinot led_dat->cdev.blink_set = netxbig_led_blink_set; 31924467832SSimon Guinot led_dat->cdev.brightness_set = netxbig_led_set; 32024467832SSimon Guinot /* 32124467832SSimon Guinot * Because the GPIO extension bus don't allow to read registers 32224467832SSimon Guinot * value, there is no way to probe the LED initial state. 32324467832SSimon Guinot * So, the initial sysfs LED value for the "brightness" and "sata" 32424467832SSimon Guinot * attributes are inconsistent. 32524467832SSimon Guinot * 32624467832SSimon Guinot * Note that the initial LED state can't be reconfigured. 32724467832SSimon Guinot * The reason is that the LED behaviour must stay uniform during 32824467832SSimon Guinot * the whole boot process (bootloader+linux). 32924467832SSimon Guinot */ 33024467832SSimon Guinot led_dat->sata = 0; 33124467832SSimon Guinot led_dat->cdev.brightness = LED_OFF; 33224467832SSimon Guinot led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; 33324467832SSimon Guinot led_dat->mode_addr = template->mode_addr; 33424467832SSimon Guinot led_dat->mode_val = template->mode_val; 33524467832SSimon Guinot led_dat->bright_addr = template->bright_addr; 33624467832SSimon Guinot led_dat->bright_max = (1 << pdata->gpio_ext->num_data) - 1; 33724467832SSimon Guinot led_dat->timer = pdata->timer; 33824467832SSimon Guinot led_dat->num_timer = pdata->num_timer; 339*0c86ac2cSSimon Guinot /* 340*0c86ac2cSSimon Guinot * If available, expose the SATA activity blink capability through 341*0c86ac2cSSimon Guinot * a "sata" sysfs attribute. 342*0c86ac2cSSimon Guinot */ 343*0c86ac2cSSimon Guinot if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE) 344*0c86ac2cSSimon Guinot led_dat->cdev.groups = netxbig_led_groups; 34524467832SSimon Guinot 346588a6a99SJohan Hovold return led_classdev_register(&pdev->dev, &led_dat->cdev); 34724467832SSimon Guinot } 34824467832SSimon Guinot 34998ea1ea2SBill Pemberton static int netxbig_led_probe(struct platform_device *pdev) 35024467832SSimon Guinot { 35187aae1eaSJingoo Han struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev); 35224467832SSimon Guinot struct netxbig_led_data *leds_data; 35324467832SSimon Guinot int i; 35424467832SSimon Guinot int ret; 35524467832SSimon Guinot 35624467832SSimon Guinot if (!pdata) 35724467832SSimon Guinot return -EINVAL; 35824467832SSimon Guinot 3598095c385SBryan Wu leds_data = devm_kzalloc(&pdev->dev, 3608095c385SBryan Wu sizeof(struct netxbig_led_data) * pdata->num_leds, GFP_KERNEL); 36124467832SSimon Guinot if (!leds_data) 36224467832SSimon Guinot return -ENOMEM; 36324467832SSimon Guinot 36424467832SSimon Guinot ret = gpio_ext_init(pdata->gpio_ext); 36524467832SSimon Guinot if (ret < 0) 3668095c385SBryan Wu return ret; 36724467832SSimon Guinot 36824467832SSimon Guinot for (i = 0; i < pdata->num_leds; i++) { 36924467832SSimon Guinot ret = create_netxbig_led(pdev, &leds_data[i], &pdata->leds[i]); 37024467832SSimon Guinot if (ret < 0) 37124467832SSimon Guinot goto err_free_leds; 37224467832SSimon Guinot } 37324467832SSimon Guinot 37424467832SSimon Guinot platform_set_drvdata(pdev, leds_data); 37524467832SSimon Guinot 37624467832SSimon Guinot return 0; 37724467832SSimon Guinot 37824467832SSimon Guinot err_free_leds: 37924467832SSimon Guinot for (i = i - 1; i >= 0; i--) 38024467832SSimon Guinot delete_netxbig_led(&leds_data[i]); 38124467832SSimon Guinot 38224467832SSimon Guinot gpio_ext_free(pdata->gpio_ext); 38324467832SSimon Guinot return ret; 38424467832SSimon Guinot } 38524467832SSimon Guinot 386678e8a6bSBill Pemberton static int netxbig_led_remove(struct platform_device *pdev) 38724467832SSimon Guinot { 38887aae1eaSJingoo Han struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev); 38924467832SSimon Guinot struct netxbig_led_data *leds_data; 39024467832SSimon Guinot int i; 39124467832SSimon Guinot 39224467832SSimon Guinot leds_data = platform_get_drvdata(pdev); 39324467832SSimon Guinot 39424467832SSimon Guinot for (i = 0; i < pdata->num_leds; i++) 39524467832SSimon Guinot delete_netxbig_led(&leds_data[i]); 39624467832SSimon Guinot 39724467832SSimon Guinot gpio_ext_free(pdata->gpio_ext); 39824467832SSimon Guinot 39924467832SSimon Guinot return 0; 40024467832SSimon Guinot } 40124467832SSimon Guinot 40224467832SSimon Guinot static struct platform_driver netxbig_led_driver = { 40324467832SSimon Guinot .probe = netxbig_led_probe, 404df07cf81SBill Pemberton .remove = netxbig_led_remove, 40524467832SSimon Guinot .driver = { 40624467832SSimon Guinot .name = "leds-netxbig", 40724467832SSimon Guinot }, 40824467832SSimon Guinot }; 40924467832SSimon Guinot 410892a8843SAxel Lin module_platform_driver(netxbig_led_driver); 41124467832SSimon Guinot 41224467832SSimon Guinot MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>"); 41324467832SSimon Guinot MODULE_DESCRIPTION("LED driver for LaCie xBig Network boards"); 41424467832SSimon Guinot MODULE_LICENSE("GPL"); 415892a8843SAxel Lin MODULE_ALIAS("platform:leds-netxbig"); 416