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/init.h> 2524467832SSimon Guinot #include <linux/irq.h> 2624467832SSimon Guinot #include <linux/slab.h> 2724467832SSimon Guinot #include <linux/spinlock.h> 2824467832SSimon Guinot #include <linux/platform_device.h> 2924467832SSimon Guinot #include <linux/gpio.h> 3024467832SSimon Guinot #include <linux/leds.h> 31c02cecb9SArnd Bergmann #include <linux/platform_data/leds-kirkwood-netxbig.h> 3224467832SSimon Guinot 3324467832SSimon Guinot /* 3424467832SSimon Guinot * GPIO extension bus. 3524467832SSimon Guinot */ 3624467832SSimon Guinot 3724467832SSimon Guinot static DEFINE_SPINLOCK(gpio_ext_lock); 3824467832SSimon Guinot 3924467832SSimon Guinot static void gpio_ext_set_addr(struct netxbig_gpio_ext *gpio_ext, int addr) 4024467832SSimon Guinot { 4124467832SSimon Guinot int pin; 4224467832SSimon Guinot 4324467832SSimon Guinot for (pin = 0; pin < gpio_ext->num_addr; pin++) 4424467832SSimon Guinot gpio_set_value(gpio_ext->addr[pin], (addr >> pin) & 1); 4524467832SSimon Guinot } 4624467832SSimon Guinot 4724467832SSimon Guinot static void gpio_ext_set_data(struct netxbig_gpio_ext *gpio_ext, int data) 4824467832SSimon Guinot { 4924467832SSimon Guinot int pin; 5024467832SSimon Guinot 5124467832SSimon Guinot for (pin = 0; pin < gpio_ext->num_data; pin++) 5224467832SSimon Guinot gpio_set_value(gpio_ext->data[pin], (data >> pin) & 1); 5324467832SSimon Guinot } 5424467832SSimon Guinot 5524467832SSimon Guinot static void gpio_ext_enable_select(struct netxbig_gpio_ext *gpio_ext) 5624467832SSimon Guinot { 5724467832SSimon Guinot /* Enable select is done on the raising edge. */ 5824467832SSimon Guinot gpio_set_value(gpio_ext->enable, 0); 5924467832SSimon Guinot gpio_set_value(gpio_ext->enable, 1); 6024467832SSimon Guinot } 6124467832SSimon Guinot 6224467832SSimon Guinot static void gpio_ext_set_value(struct netxbig_gpio_ext *gpio_ext, 6324467832SSimon Guinot int addr, int value) 6424467832SSimon Guinot { 6524467832SSimon Guinot unsigned long flags; 6624467832SSimon Guinot 6724467832SSimon Guinot spin_lock_irqsave(&gpio_ext_lock, flags); 6824467832SSimon Guinot gpio_ext_set_addr(gpio_ext, addr); 6924467832SSimon Guinot gpio_ext_set_data(gpio_ext, value); 7024467832SSimon Guinot gpio_ext_enable_select(gpio_ext); 7124467832SSimon Guinot spin_unlock_irqrestore(&gpio_ext_lock, flags); 7224467832SSimon Guinot } 7324467832SSimon Guinot 7424467832SSimon Guinot static int __devinit gpio_ext_init(struct netxbig_gpio_ext *gpio_ext) 7524467832SSimon Guinot { 7624467832SSimon Guinot int err; 7724467832SSimon Guinot int i; 7824467832SSimon Guinot 7924467832SSimon Guinot if (unlikely(!gpio_ext)) 8024467832SSimon Guinot return -EINVAL; 8124467832SSimon Guinot 8224467832SSimon Guinot /* Configure address GPIOs. */ 8324467832SSimon Guinot for (i = 0; i < gpio_ext->num_addr; i++) { 84b96a573fSAxel Lin err = gpio_request_one(gpio_ext->addr[i], GPIOF_OUT_INIT_LOW, 85b96a573fSAxel Lin "GPIO extension addr"); 8624467832SSimon Guinot if (err) 8724467832SSimon Guinot goto err_free_addr; 8824467832SSimon Guinot } 8924467832SSimon Guinot /* Configure data GPIOs. */ 9024467832SSimon Guinot for (i = 0; i < gpio_ext->num_data; i++) { 91b96a573fSAxel Lin err = gpio_request_one(gpio_ext->data[i], GPIOF_OUT_INIT_LOW, 92b96a573fSAxel Lin "GPIO extension data"); 9324467832SSimon Guinot if (err) 9424467832SSimon Guinot goto err_free_data; 9524467832SSimon Guinot } 9624467832SSimon Guinot /* Configure "enable select" GPIO. */ 97b96a573fSAxel Lin err = gpio_request_one(gpio_ext->enable, GPIOF_OUT_INIT_LOW, 98b96a573fSAxel Lin "GPIO extension enable"); 9924467832SSimon Guinot if (err) 10024467832SSimon Guinot goto err_free_data; 10124467832SSimon Guinot 10224467832SSimon Guinot return 0; 10324467832SSimon Guinot 10424467832SSimon Guinot err_free_data: 10524467832SSimon Guinot for (i = i - 1; i >= 0; i--) 10624467832SSimon Guinot gpio_free(gpio_ext->data[i]); 10724467832SSimon Guinot i = gpio_ext->num_addr; 10824467832SSimon Guinot err_free_addr: 10924467832SSimon Guinot for (i = i - 1; i >= 0; i--) 11024467832SSimon Guinot gpio_free(gpio_ext->addr[i]); 11124467832SSimon Guinot 11224467832SSimon Guinot return err; 11324467832SSimon Guinot } 11424467832SSimon Guinot 115b8cd742aSArnd Bergmann static void gpio_ext_free(struct netxbig_gpio_ext *gpio_ext) 11624467832SSimon Guinot { 11724467832SSimon Guinot int i; 11824467832SSimon Guinot 11924467832SSimon Guinot gpio_free(gpio_ext->enable); 12024467832SSimon Guinot for (i = gpio_ext->num_addr - 1; i >= 0; i--) 12124467832SSimon Guinot gpio_free(gpio_ext->addr[i]); 12224467832SSimon Guinot for (i = gpio_ext->num_data - 1; i >= 0; i--) 12324467832SSimon Guinot gpio_free(gpio_ext->data[i]); 12424467832SSimon Guinot } 12524467832SSimon Guinot 12624467832SSimon Guinot /* 12724467832SSimon Guinot * Class LED driver. 12824467832SSimon Guinot */ 12924467832SSimon Guinot 13024467832SSimon Guinot struct netxbig_led_data { 13124467832SSimon Guinot struct netxbig_gpio_ext *gpio_ext; 13224467832SSimon Guinot struct led_classdev cdev; 13324467832SSimon Guinot int mode_addr; 13424467832SSimon Guinot int *mode_val; 13524467832SSimon Guinot int bright_addr; 13624467832SSimon Guinot int bright_max; 13724467832SSimon Guinot struct netxbig_led_timer *timer; 13824467832SSimon Guinot int num_timer; 13924467832SSimon Guinot enum netxbig_led_mode mode; 14024467832SSimon Guinot int sata; 14124467832SSimon Guinot spinlock_t lock; 14224467832SSimon Guinot }; 14324467832SSimon Guinot 14424467832SSimon Guinot static int netxbig_led_get_timer_mode(enum netxbig_led_mode *mode, 14524467832SSimon Guinot unsigned long delay_on, 14624467832SSimon Guinot unsigned long delay_off, 14724467832SSimon Guinot struct netxbig_led_timer *timer, 14824467832SSimon Guinot int num_timer) 14924467832SSimon Guinot { 15024467832SSimon Guinot int i; 15124467832SSimon Guinot 15224467832SSimon Guinot for (i = 0; i < num_timer; i++) { 15324467832SSimon Guinot if (timer[i].delay_on == delay_on && 15424467832SSimon Guinot timer[i].delay_off == delay_off) { 15524467832SSimon Guinot *mode = timer[i].mode; 15624467832SSimon Guinot return 0; 15724467832SSimon Guinot } 15824467832SSimon Guinot } 15924467832SSimon Guinot return -EINVAL; 16024467832SSimon Guinot } 16124467832SSimon Guinot 16224467832SSimon Guinot static int netxbig_led_blink_set(struct led_classdev *led_cdev, 16324467832SSimon Guinot unsigned long *delay_on, 16424467832SSimon Guinot unsigned long *delay_off) 16524467832SSimon Guinot { 16624467832SSimon Guinot struct netxbig_led_data *led_dat = 16724467832SSimon Guinot container_of(led_cdev, struct netxbig_led_data, cdev); 16824467832SSimon Guinot enum netxbig_led_mode mode; 16924467832SSimon Guinot int mode_val; 17024467832SSimon Guinot int ret; 17124467832SSimon Guinot 17224467832SSimon Guinot /* Look for a LED mode with the requested timer frequency. */ 17324467832SSimon Guinot ret = netxbig_led_get_timer_mode(&mode, *delay_on, *delay_off, 17424467832SSimon Guinot led_dat->timer, led_dat->num_timer); 17524467832SSimon Guinot if (ret < 0) 17624467832SSimon Guinot return ret; 17724467832SSimon Guinot 17824467832SSimon Guinot mode_val = led_dat->mode_val[mode]; 17924467832SSimon Guinot if (mode_val == NETXBIG_LED_INVALID_MODE) 18024467832SSimon Guinot return -EINVAL; 18124467832SSimon Guinot 18224467832SSimon Guinot spin_lock_irq(&led_dat->lock); 18324467832SSimon Guinot 18424467832SSimon Guinot gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val); 18524467832SSimon Guinot led_dat->mode = mode; 18624467832SSimon Guinot 18724467832SSimon Guinot spin_unlock_irq(&led_dat->lock); 18824467832SSimon Guinot 18924467832SSimon Guinot return 0; 19024467832SSimon Guinot } 19124467832SSimon Guinot 19224467832SSimon Guinot static void netxbig_led_set(struct led_classdev *led_cdev, 19324467832SSimon Guinot enum led_brightness value) 19424467832SSimon Guinot { 19524467832SSimon Guinot struct netxbig_led_data *led_dat = 19624467832SSimon Guinot container_of(led_cdev, struct netxbig_led_data, cdev); 19724467832SSimon Guinot enum netxbig_led_mode mode; 19824467832SSimon Guinot int mode_val, bright_val; 19924467832SSimon Guinot int set_brightness = 1; 20024467832SSimon Guinot unsigned long flags; 20124467832SSimon Guinot 20224467832SSimon Guinot spin_lock_irqsave(&led_dat->lock, flags); 20324467832SSimon Guinot 20424467832SSimon Guinot if (value == LED_OFF) { 20524467832SSimon Guinot mode = NETXBIG_LED_OFF; 20624467832SSimon Guinot set_brightness = 0; 20724467832SSimon Guinot } else { 20824467832SSimon Guinot if (led_dat->sata) 20924467832SSimon Guinot mode = NETXBIG_LED_SATA; 21024467832SSimon Guinot else if (led_dat->mode == NETXBIG_LED_OFF) 21124467832SSimon Guinot mode = NETXBIG_LED_ON; 21224467832SSimon Guinot else /* Keep 'timer' mode. */ 21324467832SSimon Guinot mode = led_dat->mode; 21424467832SSimon Guinot } 21524467832SSimon Guinot mode_val = led_dat->mode_val[mode]; 21624467832SSimon Guinot 21724467832SSimon Guinot gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val); 21824467832SSimon Guinot led_dat->mode = mode; 21924467832SSimon Guinot /* 22024467832SSimon Guinot * Note that the brightness register is shared between all the 22124467832SSimon Guinot * SATA LEDs. So, change the brightness setting for a single 22224467832SSimon Guinot * SATA LED will affect all the others. 22324467832SSimon Guinot */ 22424467832SSimon Guinot if (set_brightness) { 22524467832SSimon Guinot bright_val = DIV_ROUND_UP(value * led_dat->bright_max, 22624467832SSimon Guinot LED_FULL); 22724467832SSimon Guinot gpio_ext_set_value(led_dat->gpio_ext, 22824467832SSimon Guinot led_dat->bright_addr, bright_val); 22924467832SSimon Guinot } 23024467832SSimon Guinot 23124467832SSimon Guinot spin_unlock_irqrestore(&led_dat->lock, flags); 23224467832SSimon Guinot } 23324467832SSimon Guinot 23424467832SSimon Guinot static ssize_t netxbig_led_sata_store(struct device *dev, 23524467832SSimon Guinot struct device_attribute *attr, 23624467832SSimon Guinot const char *buff, size_t count) 23724467832SSimon Guinot { 23824467832SSimon Guinot struct led_classdev *led_cdev = dev_get_drvdata(dev); 23924467832SSimon Guinot struct netxbig_led_data *led_dat = 24024467832SSimon Guinot container_of(led_cdev, struct netxbig_led_data, cdev); 24124467832SSimon Guinot unsigned long enable; 24224467832SSimon Guinot enum netxbig_led_mode mode; 24324467832SSimon Guinot int mode_val; 24424467832SSimon Guinot int ret; 24524467832SSimon Guinot 24624467832SSimon Guinot ret = strict_strtoul(buff, 10, &enable); 24724467832SSimon Guinot if (ret < 0) 24824467832SSimon Guinot return ret; 24924467832SSimon Guinot 25024467832SSimon Guinot enable = !!enable; 25124467832SSimon Guinot 25224467832SSimon Guinot spin_lock_irq(&led_dat->lock); 25324467832SSimon Guinot 25424467832SSimon Guinot if (led_dat->sata == enable) { 25524467832SSimon Guinot ret = count; 25624467832SSimon Guinot goto exit_unlock; 25724467832SSimon Guinot } 25824467832SSimon Guinot 25924467832SSimon Guinot if (led_dat->mode != NETXBIG_LED_ON && 26024467832SSimon Guinot led_dat->mode != NETXBIG_LED_SATA) 26124467832SSimon Guinot mode = led_dat->mode; /* Keep modes 'off' and 'timer'. */ 26224467832SSimon Guinot else if (enable) 26324467832SSimon Guinot mode = NETXBIG_LED_SATA; 26424467832SSimon Guinot else 26524467832SSimon Guinot mode = NETXBIG_LED_ON; 26624467832SSimon Guinot 26724467832SSimon Guinot mode_val = led_dat->mode_val[mode]; 26824467832SSimon Guinot if (mode_val == NETXBIG_LED_INVALID_MODE) { 26924467832SSimon Guinot ret = -EINVAL; 27024467832SSimon Guinot goto exit_unlock; 27124467832SSimon Guinot } 27224467832SSimon Guinot 27324467832SSimon Guinot gpio_ext_set_value(led_dat->gpio_ext, led_dat->mode_addr, mode_val); 27424467832SSimon Guinot led_dat->mode = mode; 27524467832SSimon Guinot led_dat->sata = enable; 27624467832SSimon Guinot 27724467832SSimon Guinot ret = count; 27824467832SSimon Guinot 27924467832SSimon Guinot exit_unlock: 28024467832SSimon Guinot spin_unlock_irq(&led_dat->lock); 28124467832SSimon Guinot 28224467832SSimon Guinot return ret; 28324467832SSimon Guinot } 28424467832SSimon Guinot 28524467832SSimon Guinot static ssize_t netxbig_led_sata_show(struct device *dev, 28624467832SSimon Guinot struct device_attribute *attr, char *buf) 28724467832SSimon Guinot { 28824467832SSimon Guinot struct led_classdev *led_cdev = dev_get_drvdata(dev); 28924467832SSimon Guinot struct netxbig_led_data *led_dat = 29024467832SSimon Guinot container_of(led_cdev, struct netxbig_led_data, cdev); 29124467832SSimon Guinot 29224467832SSimon Guinot return sprintf(buf, "%d\n", led_dat->sata); 29324467832SSimon Guinot } 29424467832SSimon Guinot 29524467832SSimon Guinot static DEVICE_ATTR(sata, 0644, netxbig_led_sata_show, netxbig_led_sata_store); 29624467832SSimon Guinot 297b8cd742aSArnd Bergmann static void delete_netxbig_led(struct netxbig_led_data *led_dat) 29824467832SSimon Guinot { 29924467832SSimon Guinot if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE) 30024467832SSimon Guinot device_remove_file(led_dat->cdev.dev, &dev_attr_sata); 30124467832SSimon Guinot led_classdev_unregister(&led_dat->cdev); 30224467832SSimon Guinot } 30324467832SSimon Guinot 30424467832SSimon Guinot static int __devinit 30524467832SSimon Guinot create_netxbig_led(struct platform_device *pdev, 30624467832SSimon Guinot struct netxbig_led_data *led_dat, 30724467832SSimon Guinot const struct netxbig_led *template) 30824467832SSimon Guinot { 30924467832SSimon Guinot struct netxbig_led_platform_data *pdata = pdev->dev.platform_data; 31024467832SSimon Guinot int ret; 31124467832SSimon Guinot 31224467832SSimon Guinot spin_lock_init(&led_dat->lock); 31324467832SSimon Guinot led_dat->gpio_ext = pdata->gpio_ext; 31424467832SSimon Guinot led_dat->cdev.name = template->name; 31524467832SSimon Guinot led_dat->cdev.default_trigger = template->default_trigger; 31624467832SSimon Guinot led_dat->cdev.blink_set = netxbig_led_blink_set; 31724467832SSimon Guinot led_dat->cdev.brightness_set = netxbig_led_set; 31824467832SSimon Guinot /* 31924467832SSimon Guinot * Because the GPIO extension bus don't allow to read registers 32024467832SSimon Guinot * value, there is no way to probe the LED initial state. 32124467832SSimon Guinot * So, the initial sysfs LED value for the "brightness" and "sata" 32224467832SSimon Guinot * attributes are inconsistent. 32324467832SSimon Guinot * 32424467832SSimon Guinot * Note that the initial LED state can't be reconfigured. 32524467832SSimon Guinot * The reason is that the LED behaviour must stay uniform during 32624467832SSimon Guinot * the whole boot process (bootloader+linux). 32724467832SSimon Guinot */ 32824467832SSimon Guinot led_dat->sata = 0; 32924467832SSimon Guinot led_dat->cdev.brightness = LED_OFF; 33024467832SSimon Guinot led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; 33124467832SSimon Guinot led_dat->mode_addr = template->mode_addr; 33224467832SSimon Guinot led_dat->mode_val = template->mode_val; 33324467832SSimon Guinot led_dat->bright_addr = template->bright_addr; 33424467832SSimon Guinot led_dat->bright_max = (1 << pdata->gpio_ext->num_data) - 1; 33524467832SSimon Guinot led_dat->timer = pdata->timer; 33624467832SSimon Guinot led_dat->num_timer = pdata->num_timer; 33724467832SSimon Guinot 33824467832SSimon Guinot ret = led_classdev_register(&pdev->dev, &led_dat->cdev); 33924467832SSimon Guinot if (ret < 0) 34024467832SSimon Guinot return ret; 34124467832SSimon Guinot 34224467832SSimon Guinot /* 34324467832SSimon Guinot * If available, expose the SATA activity blink capability through 34424467832SSimon Guinot * a "sata" sysfs attribute. 34524467832SSimon Guinot */ 34624467832SSimon Guinot if (led_dat->mode_val[NETXBIG_LED_SATA] != NETXBIG_LED_INVALID_MODE) { 34724467832SSimon Guinot ret = device_create_file(led_dat->cdev.dev, &dev_attr_sata); 34824467832SSimon Guinot if (ret) 34924467832SSimon Guinot led_classdev_unregister(&led_dat->cdev); 35024467832SSimon Guinot } 35124467832SSimon Guinot 35224467832SSimon Guinot return ret; 35324467832SSimon Guinot } 35424467832SSimon Guinot 35524467832SSimon Guinot static int __devinit netxbig_led_probe(struct platform_device *pdev) 35624467832SSimon Guinot { 35724467832SSimon Guinot struct netxbig_led_platform_data *pdata = pdev->dev.platform_data; 35824467832SSimon Guinot struct netxbig_led_data *leds_data; 35924467832SSimon Guinot int i; 36024467832SSimon Guinot int ret; 36124467832SSimon Guinot 36224467832SSimon Guinot if (!pdata) 36324467832SSimon Guinot return -EINVAL; 36424467832SSimon Guinot 3658095c385SBryan Wu leds_data = devm_kzalloc(&pdev->dev, 3668095c385SBryan Wu sizeof(struct netxbig_led_data) * pdata->num_leds, GFP_KERNEL); 36724467832SSimon Guinot if (!leds_data) 36824467832SSimon Guinot return -ENOMEM; 36924467832SSimon Guinot 37024467832SSimon Guinot ret = gpio_ext_init(pdata->gpio_ext); 37124467832SSimon Guinot if (ret < 0) 3728095c385SBryan Wu return ret; 37324467832SSimon Guinot 37424467832SSimon Guinot for (i = 0; i < pdata->num_leds; i++) { 37524467832SSimon Guinot ret = create_netxbig_led(pdev, &leds_data[i], &pdata->leds[i]); 37624467832SSimon Guinot if (ret < 0) 37724467832SSimon Guinot goto err_free_leds; 37824467832SSimon Guinot } 37924467832SSimon Guinot 38024467832SSimon Guinot platform_set_drvdata(pdev, leds_data); 38124467832SSimon Guinot 38224467832SSimon Guinot return 0; 38324467832SSimon Guinot 38424467832SSimon Guinot err_free_leds: 38524467832SSimon Guinot for (i = i - 1; i >= 0; i--) 38624467832SSimon Guinot delete_netxbig_led(&leds_data[i]); 38724467832SSimon Guinot 38824467832SSimon Guinot gpio_ext_free(pdata->gpio_ext); 38924467832SSimon Guinot return ret; 39024467832SSimon Guinot } 39124467832SSimon Guinot 39224467832SSimon Guinot static int __devexit netxbig_led_remove(struct platform_device *pdev) 39324467832SSimon Guinot { 39424467832SSimon Guinot struct netxbig_led_platform_data *pdata = pdev->dev.platform_data; 39524467832SSimon Guinot struct netxbig_led_data *leds_data; 39624467832SSimon Guinot int i; 39724467832SSimon Guinot 39824467832SSimon Guinot leds_data = platform_get_drvdata(pdev); 39924467832SSimon Guinot 40024467832SSimon Guinot for (i = 0; i < pdata->num_leds; i++) 40124467832SSimon Guinot delete_netxbig_led(&leds_data[i]); 40224467832SSimon Guinot 40324467832SSimon Guinot gpio_ext_free(pdata->gpio_ext); 40424467832SSimon Guinot 40524467832SSimon Guinot return 0; 40624467832SSimon Guinot } 40724467832SSimon Guinot 40824467832SSimon Guinot static struct platform_driver netxbig_led_driver = { 40924467832SSimon Guinot .probe = netxbig_led_probe, 410*df07cf81SBill Pemberton .remove = netxbig_led_remove, 41124467832SSimon Guinot .driver = { 41224467832SSimon Guinot .name = "leds-netxbig", 41324467832SSimon Guinot .owner = THIS_MODULE, 41424467832SSimon Guinot }, 41524467832SSimon Guinot }; 41624467832SSimon Guinot 417892a8843SAxel Lin module_platform_driver(netxbig_led_driver); 41824467832SSimon Guinot 41924467832SSimon Guinot MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>"); 42024467832SSimon Guinot MODULE_DESCRIPTION("LED driver for LaCie xBig Network boards"); 42124467832SSimon Guinot MODULE_LICENSE("GPL"); 422892a8843SAxel Lin MODULE_ALIAS("platform:leds-netxbig"); 423