diff options
Diffstat (limited to 'drivers')
91 files changed, 1172 insertions, 1236 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 1b75a56ebd0..897a77dfa9d 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -388,6 +388,14 @@ config LEDS_RENESAS_TPU pin function. The latter to support brightness control. Brightness control is supported but hardware blinking is not. +config LEDS_TCA6507 + tristate "LED Support for TCA6507 I2C chip" + depends on LEDS_CLASS && I2C + help + This option enables support for LEDs connected to TC6507 + LED driver chips accessed via the I2C bus. + Driver support brightness control and hardware-assisted blinking. + config LEDS_TRIGGERS bool "LED Trigger support" depends on LEDS_CLASS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index e4f6bf56888..5c9dc4b000d 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o obj-$(CONFIG_LEDS_LP5523) += leds-lp5523.o +obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o obj-$(CONFIG_LEDS_FSG) += leds-fsg.o diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c index 0810604dc70..4ca00624bd1 100644 --- a/drivers/leds/leds-88pm860x.c +++ b/drivers/leds/leds-88pm860x.c @@ -238,17 +238,7 @@ static struct platform_driver pm860x_led_driver = { .remove = pm860x_led_remove, }; -static int __devinit pm860x_led_init(void) -{ - return platform_driver_register(&pm860x_led_driver); -} -module_init(pm860x_led_init); - -static void __devexit pm860x_led_exit(void) -{ - platform_driver_unregister(&pm860x_led_driver); -} -module_exit(pm860x_led_exit); +module_platform_driver(pm860x_led_driver); MODULE_DESCRIPTION("LED driver for Marvell PM860x"); MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); diff --git a/drivers/leds/leds-adp5520.c b/drivers/leds/leds-adp5520.c index 7ba4c7b5b97..b1400db3f83 100644 --- a/drivers/leds/leds-adp5520.c +++ b/drivers/leds/leds-adp5520.c @@ -213,17 +213,7 @@ static struct platform_driver adp5520_led_driver = { .remove = __devexit_p(adp5520_led_remove), }; -static int __init adp5520_led_init(void) -{ - return platform_driver_register(&adp5520_led_driver); -} -module_init(adp5520_led_init); - -static void __exit adp5520_led_exit(void) -{ - platform_driver_unregister(&adp5520_led_driver); -} -module_exit(adp5520_led_exit); +module_platform_driver(adp5520_led_driver); MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); MODULE_DESCRIPTION("LEDS ADP5520(01) Driver"); diff --git a/drivers/leds/leds-ams-delta.c b/drivers/leds/leds-ams-delta.c index 8c00937bf7e..07428357c83 100644 --- a/drivers/leds/leds-ams-delta.c +++ b/drivers/leds/leds-ams-delta.c @@ -118,18 +118,7 @@ static struct platform_driver ams_delta_led_driver = { }, }; -static int __init ams_delta_led_init(void) -{ - return platform_driver_register(&ams_delta_led_driver); -} - -static void __exit ams_delta_led_exit(void) -{ - platform_driver_unregister(&ams_delta_led_driver); -} - -module_init(ams_delta_led_init); -module_exit(ams_delta_led_exit); +module_platform_driver(ams_delta_led_driver); MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>"); MODULE_DESCRIPTION("Amstrad Delta LED driver"); diff --git a/drivers/leds/leds-asic3.c b/drivers/leds/leds-asic3.c index 48d9fe61bdf..525a9249283 100644 --- a/drivers/leds/leds-asic3.c +++ b/drivers/leds/leds-asic3.c @@ -179,21 +179,9 @@ static struct platform_driver asic3_led_driver = { }, }; -MODULE_ALIAS("platform:leds-asic3"); - -static int __init asic3_led_init(void) -{ - return platform_driver_register(&asic3_led_driver); -} - -static void __exit asic3_led_exit(void) -{ - platform_driver_unregister(&asic3_led_driver); -} - -module_init(asic3_led_init); -module_exit(asic3_led_exit); +module_platform_driver(asic3_led_driver); MODULE_AUTHOR("Paul Parsons <lost.distance@yahoo.com>"); MODULE_DESCRIPTION("HTC ASIC3 LED driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:leds-asic3"); diff --git a/drivers/leds/leds-atmel-pwm.c b/drivers/leds/leds-atmel-pwm.c index 109c875ea23..800243b6037 100644 --- a/drivers/leds/leds-atmel-pwm.c +++ b/drivers/leds/leds-atmel-pwm.c @@ -134,29 +134,18 @@ static int __exit pwmled_remove(struct platform_device *pdev) return 0; } -/* work with hotplug and coldplug */ -MODULE_ALIAS("platform:leds-atmel-pwm"); - static struct platform_driver pwmled_driver = { .driver = { .name = "leds-atmel-pwm", .owner = THIS_MODULE, }, /* REVISIT add suspend() and resume() methods */ + .probe = pwmled_probe, .remove = __exit_p(pwmled_remove), }; -static int __init modinit(void) -{ - return platform_driver_probe(&pwmled_driver, pwmled_probe); -} -module_init(modinit); - -static void __exit modexit(void) -{ - platform_driver_unregister(&pwmled_driver); -} -module_exit(modexit); +module_platform_driver(pwmled_driver); MODULE_DESCRIPTION("Driver for LEDs with PWM-controlled brightness"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:leds-atmel-pwm"); diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c index ea2185531f8..591cbdf5a04 100644 --- a/drivers/leds/leds-bd2802.c +++ b/drivers/leds/leds-bd2802.c @@ -688,8 +688,7 @@ static int __devinit bd2802_probe(struct i2c_client *client, i2c_set_clientdata(client, led); /* Configure RESET GPIO (L: RESET, H: RESET cancel) */ - gpio_request(pdata->reset_gpio, "RGB_RESETB"); - gpio_direction_output(pdata->reset_gpio, 1); + gpio_request_one(pdata->reset_gpio, GPIOF_OUT_INIT_HIGH, "RGB_RESETB"); /* Tacss = min 0.1ms */ udelay(100); @@ -813,17 +812,7 @@ static struct i2c_driver bd2802_i2c_driver = { .id_table = bd2802_id, }; -static int __init bd2802_init(void) -{ - return i2c_add_driver(&bd2802_i2c_driver); -} -module_init(bd2802_init); - -static void __exit bd2802_exit(void) -{ - i2c_del_driver(&bd2802_i2c_driver); -} -module_exit(bd2802_exit); +module_i2c_driver(bd2802_i2c_driver); MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>"); MODULE_DESCRIPTION("BD2802 LED driver"); diff --git a/drivers/leds/leds-cobalt-qube.c b/drivers/leds/leds-cobalt-qube.c index da5fb016b1a..6a8725cc7b4 100644 --- a/drivers/leds/leds-cobalt-qube.c +++ b/drivers/leds/leds-cobalt-qube.c @@ -75,9 +75,6 @@ static int __devexit cobalt_qube_led_remove(struct platform_device *pdev) return 0; } -/* work with hotplug and coldplug */ -MODULE_ALIAS("platform:cobalt-qube-leds"); - static struct platform_driver cobalt_qube_led_driver = { .probe = cobalt_qube_led_probe, .remove = __devexit_p(cobalt_qube_led_remove), @@ -87,19 +84,9 @@ static struct platform_driver cobalt_qube_led_driver = { }, }; -static int __init cobalt_qube_led_init(void) -{ - return platform_driver_register(&cobalt_qube_led_driver); -} - -static void __exit cobalt_qube_led_exit(void) -{ - platform_driver_unregister(&cobalt_qube_led_driver); -} - -module_init(cobalt_qube_led_init); -module_exit(cobalt_qube_led_exit); +module_platform_driver(cobalt_qube_led_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Front LED support for Cobalt Server"); MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); +MODULE_ALIAS("platform:cobalt-qube-leds"); diff --git a/drivers/leds/leds-da903x.c b/drivers/leds/leds-da903x.c index f28931cf678..d9cd73ebd6c 100644 --- a/drivers/leds/leds-da903x.c +++ b/drivers/leds/leds-da903x.c @@ -158,17 +158,7 @@ static struct platform_driver da903x_led_driver = { .remove = __devexit_p(da903x_led_remove), }; -static int __init da903x_led_init(void) -{ - return platform_driver_register(&da903x_led_driver); -} -module_init(da903x_led_init); - -static void __exit da903x_led_exit(void) -{ - platform_driver_unregister(&da903x_led_driver); -} -module_exit(da903x_led_exit); +module_platform_driver(da903x_led_driver); MODULE_DESCRIPTION("LEDs driver for Dialog Semiconductor DA9030/DA9034"); MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>" diff --git a/drivers/leds/leds-dac124s085.c b/drivers/leds/leds-dac124s085.c index 31cf0d60a9a..d56c14269ff 100644 --- a/drivers/leds/leds-dac124s085.c +++ b/drivers/leds/leds-dac124s085.c @@ -131,18 +131,7 @@ static struct spi_driver dac124s085_driver = { }, }; -static int __init dac124s085_leds_init(void) -{ - return spi_register_driver(&dac124s085_driver); -} - -static void __exit dac124s085_leds_exit(void) -{ - spi_unregister_driver(&dac124s085_driver); -} - -module_init(dac124s085_leds_init); -module_exit(dac124s085_leds_exit); +module_spi_driver(dac124s085_driver); MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>"); MODULE_DESCRIPTION("DAC124S085 LED driver"); diff --git a/drivers/leds/leds-fsg.c b/drivers/leds/leds-fsg.c index 49aceffaa5b..b9053fa6e25 100644 --- a/drivers/leds/leds-fsg.c +++ b/drivers/leds/leds-fsg.c @@ -224,20 +224,7 @@ static struct platform_driver fsg_led_driver = { }, }; - -static int __init fsg_led_init(void) -{ - return platform_driver_register(&fsg_led_driver); -} - -static void __exit fsg_led_exit(void) -{ - platform_driver_unregister(&fsg_led_driver); -} - - -module_init(fsg_led_init); -module_exit(fsg_led_exit); +module_platform_driver(fsg_led_driver); MODULE_AUTHOR("Rod Whitby <rod@whitby.id.au>"); MODULE_DESCRIPTION("Freecom FSG-3 LED driver"); diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 399a86f2013..7df74cb97e7 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -293,21 +293,9 @@ static struct platform_driver gpio_led_driver = { }, }; -MODULE_ALIAS("platform:leds-gpio"); - -static int __init gpio_led_init(void) -{ - return platform_driver_register(&gpio_led_driver); -} - -static void __exit gpio_led_exit(void) -{ - platform_driver_unregister(&gpio_led_driver); -} - -module_init(gpio_led_init); -module_exit(gpio_led_exit); +module_platform_driver(gpio_led_driver); MODULE_AUTHOR("Raphael Assenat <raph@8d.com>, Trent Piepho <tpiepho@freescale.com>"); MODULE_DESCRIPTION("GPIO LED driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:leds-gpio"); diff --git a/drivers/leds/leds-hp6xx.c b/drivers/leds/leds-hp6xx.c index bcfbd3a60ea..366b6055e33 100644 --- a/drivers/leds/leds-hp6xx.c +++ b/drivers/leds/leds-hp6xx.c @@ -79,9 +79,6 @@ static int hp6xxled_remove(struct platform_device *pdev) return 0; } -/* work with hotplug and coldplug */ -MODULE_ALIAS("platform:hp6xx-led"); - static struct platform_driver hp6xxled_driver = { .probe = hp6xxled_probe, .remove = hp6xxled_remove, @@ -91,19 +88,9 @@ static struct platform_driver hp6xxled_driver = { }, }; -static int __init hp6xxled_init(void) -{ - return platform_driver_register(&hp6xxled_driver); -} - -static void __exit hp6xxled_exit(void) -{ - platform_driver_unregister(&hp6xxled_driver); -} - -module_init(hp6xxled_init); -module_exit(hp6xxled_exit); +module_platform_driver(hp6xxled_driver); MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>"); MODULE_DESCRIPTION("HP Jornada 6xx LED driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:hp6xx-led"); diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c index 0630e4f4b28..45e6878d737 100644 --- a/drivers/leds/leds-lm3530.c +++ b/drivers/leds/leds-lm3530.c @@ -457,18 +457,7 @@ static struct i2c_driver lm3530_i2c_driver = { }, }; -static int __init lm3530_init(void) -{ - return i2c_add_driver(&lm3530_i2c_driver); -} - -static void __exit lm3530_exit(void) -{ - i2c_del_driver(&lm3530_i2c_driver); -} - -module_init(lm3530_init); -module_exit(lm3530_exit); +module_i2c_driver(lm3530_i2c_driver); MODULE_DESCRIPTION("Back Light driver for LM3530"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c index 9010c054615..b8f9f0a5d43 100644 --- a/drivers/leds/leds-lp3944.c +++ b/drivers/leds/leds-lp3944.c @@ -453,18 +453,7 @@ static struct i2c_driver lp3944_driver = { .id_table = lp3944_id, }; -static int __init lp3944_module_init(void) -{ - return i2c_add_driver(&lp3944_driver); -} - -static void __exit lp3944_module_exit(void) -{ - i2c_del_driver(&lp3944_driver); -} - -module_init(lp3944_module_init); -module_exit(lp3944_module_exit); +module_i2c_driver(lp3944_driver); MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); MODULE_DESCRIPTION("LP3944 Fun Light Chip"); diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index cb641f1b334..d62a7982a5e 100644 --- a/drivers/leds/leds-lp5521.c +++ b/drivers/leds/leds-lp5521.c @@ -797,25 +797,7 @@ static struct i2c_driver lp5521_driver = { .id_table = lp5521_id, }; -static int __init lp5521_init(void) -{ - int ret; - - ret = i2c_add_driver(&lp5521_driver); - - if (ret < 0) - printk(KERN_ALERT "Adding lp5521 driver failed\n"); - - return ret; -} - -static void __exit lp5521_exit(void) -{ - i2c_del_driver(&lp5521_driver); -} - -module_init(lp5521_init); -module_exit(lp5521_exit); +module_i2c_driver(lp5521_driver); MODULE_AUTHOR("Mathias Nyman, Yuri Zaporozhets, Samu Onkalo"); MODULE_DESCRIPTION("LP5521 LED engine"); diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c index 5971e309b23..73e791ae725 100644 --- a/drivers/leds/leds-lp5523.c +++ b/drivers/leds/leds-lp5523.c @@ -870,8 +870,6 @@ static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev, return 0; } -static struct i2c_driver lp5523_driver; - static int __devinit lp5523_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1021,25 +1019,7 @@ static struct i2c_driver lp5523_driver = { .id_table = lp5523_id, }; -static int __init lp5523_init(void) -{ - int ret; - - ret = i2c_add_driver(&lp5523_driver); - - if (ret < 0) - printk(KERN_ALERT "Adding lp5523 driver failed\n"); - - return ret; -} - -static void __exit lp5523_exit(void) -{ - i2c_del_driver(&lp5523_driver); -} - -module_init(lp5523_init); -module_exit(lp5523_exit); +module_i2c_driver(lp5523_driver); MODULE_AUTHOR("Mathias Nyman <mathias.nyman@nokia.com>"); MODULE_DESCRIPTION("LP5523 LED engine"); diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c index 53f67b8ce55..e311a96c446 100644 --- a/drivers/leds/leds-lt3593.c +++ b/drivers/leds/leds-lt3593.c @@ -199,21 +199,9 @@ static struct platform_driver lt3593_led_driver = { }, }; -MODULE_ALIAS("platform:leds-lt3593"); - -static int __init lt3593_led_init(void) -{ - return platform_driver_register(<3593_led_driver); -} - -static void __exit lt3593_led_exit(void) -{ - platform_driver_unregister(<3593_led_driver); -} - -module_init(lt3593_led_init); -module_exit(lt3593_led_exit); +module_platform_driver(lt3593_led_driver); MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); MODULE_DESCRIPTION("LED driver for LT3593 controllers"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:leds-lt3593"); diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c index b3393a9f213..8bc49154155 100644 --- a/drivers/leds/leds-mc13783.c +++ b/drivers/leds/leds-mc13783.c @@ -275,7 +275,7 @@ static int __devinit mc13783_led_probe(struct platform_device *pdev) return -ENODEV; } - if (pdata->num_leds < 1 || pdata->num_leds > MC13783_LED_MAX) { + if (pdata->num_leds < 1 || pdata->num_leds > (MC13783_LED_MAX + 1)) { dev_err(&pdev->dev, "Invalid led count %d\n", pdata->num_leds); return -EINVAL; } @@ -385,17 +385,7 @@ static struct platform_driver mc13783_led_driver = { .remove = __devexit_p(mc13783_led_remove), }; -static int __init mc13783_led_init(void) -{ - return platform_driver_register(&mc13783_led_driver); -} -module_init(mc13783_led_init); - -static void __exit mc13783_led_exit(void) -{ - platform_driver_unregister(&mc13783_led_driver); -} -module_exit(mc13783_led_exit); +module_platform_driver(mc13783_led_driver); MODULE_DESCRIPTION("LEDs driver for Freescale MC13783 PMIC"); MODULE_AUTHOR("Philippe Retornaz <philippe.retornaz@epfl.ch>"); diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c index f2e51c13439..d8433f2d53b 100644 --- a/drivers/leds/leds-netxbig.c +++ b/drivers/leds/leds-netxbig.c @@ -81,35 +81,23 @@ static int __devinit gpio_ext_init(struct netxbig_gpio_ext *gpio_ext) /* Configure address GPIOs. */ for (i = 0; i < gpio_ext->num_addr; i++) { - err = gpio_request(gpio_ext->addr[i], "GPIO extension addr"); + err = gpio_request_one(gpio_ext->addr[i], GPIOF_OUT_INIT_LOW, + "GPIO extension addr"); if (err) goto err_free_addr; - err = gpio_direction_output(gpio_ext->addr[i], 0); - if (err) { - gpio_free(gpio_ext->addr[i]); - goto err_free_addr; - } } /* Configure data GPIOs. */ for (i = 0; i < gpio_ext->num_data; i++) { - err = gpio_request(gpio_ext->data[i], "GPIO extension data"); + err = gpio_request_one(gpio_ext->data[i], GPIOF_OUT_INIT_LOW, + "GPIO extension data"); if (err) goto err_free_data; - err = gpio_direction_output(gpio_ext->data[i], 0); - if (err) { - gpio_free(gpio_ext->data[i]); - goto err_free_data; - } } /* Configure "enable select" GPIO. */ - err = gpio_request(gpio_ext->enable, "GPIO extension enable"); + err = gpio_request_one(gpio_ext->enable, GPIOF_OUT_INIT_LOW, + "GPIO extension enable"); if (err) goto err_free_data; - err = gpio_direction_output(gpio_ext->enable, 0); - if (err) { - gpio_free(gpio_ext->enable); - goto err_free_data; - } return 0; @@ -429,21 +417,10 @@ static struct platform_driver netxbig_led_driver = { .owner = THIS_MODULE, }, }; -MODULE_ALIAS("platform:leds-netxbig"); -static int __init netxbig_led_init(void) -{ - return platform_driver_register(&netxbig_led_driver); -} - -static void __exit netxbig_led_exit(void) -{ - platform_driver_unregister(&netxbig_led_driver); -} - -module_init(netxbig_led_init); -module_exit(netxbig_led_exit); +module_platform_driver(netxbig_led_driver); MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>"); MODULE_DESCRIPTION("LED driver for LaCie xBig Network boards"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:leds-netxbig"); diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c index 37b7d0cfe58..2f0a14421a7 100644 --- a/drivers/leds/leds-ns2.c +++ b/drivers/leds/leds-ns2.c @@ -323,21 +323,10 @@ static struct platform_driver ns2_led_driver = { .owner = THIS_MODULE, }, }; -MODULE_ALIAS("platform:leds-ns2"); - -static int __init ns2_led_init(void) -{ - return platform_driver_register(&ns2_led_driver); -} -static void __exit ns2_led_exit(void) -{ - platform_driver_unregister(&ns2_led_driver); -} - -module_init(ns2_led_init); -module_exit(ns2_led_exit); +module_platform_driver(ns2_led_driver); MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>"); MODULE_DESCRIPTION("Network Space v2 LED driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:leds-ns2"); diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c index a2c874623e3..ceccab44b5b 100644 --- a/drivers/leds/leds-pca9532.c +++ b/drivers/leds/leds-pca9532.c @@ -489,20 +489,8 @@ static int pca9532_remove(struct i2c_client *client) return 0; } -static int __init pca9532_init(void) -{ - return i2c_add_driver(&pca9532_driver); -} - -static void __exit pca9532_exit(void) -{ - i2c_del_driver(&pca9532_driver); -} +module_i2c_driver(pca9532_driver); MODULE_AUTHOR("Riku Voipio"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("PCA 9532 LED dimmer"); - -module_init(pca9532_init); -module_exit(pca9532_exit); - diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c index 66aa3e8e786..dcc3bc3d38d 100644 --- a/drivers/leds/leds-pca955x.c +++ b/drivers/leds/leds-pca955x.c @@ -371,18 +371,7 @@ static struct i2c_driver pca955x_driver = { .id_table = pca955x_id, }; -static int __init pca955x_leds_init(void) -{ - return i2c_add_driver(&pca955x_driver); -} - -static void __exit pca955x_leds_exit(void) -{ - i2c_del_driver(&pca955x_driver); -} - -module_init(pca955x_leds_init); -module_exit(pca955x_leds_exit); +module_i2c_driver(pca955x_driver); MODULE_AUTHOR("Nate Case <ncase@xes-inc.com>"); MODULE_DESCRIPTION("PCA955x LED driver"); diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index 666daf77872..3ed92f34bd4 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c @@ -135,18 +135,7 @@ static struct platform_driver led_pwm_driver = { }, }; -static int __init led_pwm_init(void) -{ - return platform_driver_register(&led_pwm_driver); -} - -static void __exit led_pwm_exit(void) -{ - platform_driver_unregister(&led_pwm_driver); -} - -module_init(led_pwm_init); -module_exit(led_pwm_exit); +module_platform_driver(led_pwm_driver); MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>"); MODULE_DESCRIPTION("PWM LED driver for PXA"); diff --git a/drivers/leds/leds-rb532.c b/drivers/leds/leds-rb532.c index c3525f37f73..a7815b6cd85 100644 --- a/drivers/leds/leds-rb532.c +++ b/drivers/leds/leds-rb532.c @@ -57,21 +57,9 @@ static struct platform_driver rb532_led_driver = { }, }; -static int __init rb532_led_init(void) -{ - return platform_driver_register(&rb532_led_driver); -} - -static void __exit rb532_led_exit(void) -{ - platform_driver_unregister(&rb532_led_driver); -} - -module_init(rb532_led_init); -module_exit(rb532_led_exit); - -MODULE_ALIAS("platform:rb532-led"); +module_platform_driver(rb532_led_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("User LED support for Routerboard532"); MODULE_AUTHOR("Phil Sutter <n0-1@freewrt.org>"); +MODULE_ALIAS("platform:rb532-led"); diff --git a/drivers/leds/leds-regulator.c b/drivers/leds/leds-regulator.c index 8497f56f8e4..df7e963bddd 100644 --- a/drivers/leds/leds-regulator.c +++ b/drivers/leds/leds-regulator.c @@ -229,17 +229,7 @@ static struct platform_driver regulator_led_driver = { .remove = __devexit_p(regulator_led_remove), }; -static int __init regulator_led_init(void) -{ - return platform_driver_register(®ulator_led_driver); -} -module_init(regulator_led_init); - -static void __exit regulator_led_exit(void) -{ - platform_driver_unregister(®ulator_led_driver); -} -module_exit(regulator_led_exit); +module_platform_driver(regulator_led_driver); MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); MODULE_DESCRIPTION("Regulator driven LED driver"); diff --git a/drivers/leds/leds-renesas-tpu.c b/drivers/leds/leds-renesas-tpu.c index 3ee540eb127..32fe337d5c6 100644 --- a/drivers/leds/leds-renesas-tpu.c +++ b/drivers/leds/leds-renesas-tpu.c @@ -339,18 +339,7 @@ static struct platform_driver r_tpu_device_driver = { } }; -static int __init r_tpu_init(void) -{ - return platform_driver_register(&r_tpu_device_driver); -} - -static void __exit r_tpu_exit(void) -{ - platform_driver_unregister(&r_tpu_device_driver); -} - -module_init(r_tpu_init); -module_exit(r_tpu_exit); +module_platform_driver(r_tpu_device_driver); MODULE_AUTHOR("Magnus Damm"); MODULE_DESCRIPTION("Renesas TPU LED Driver"); diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c index 29f8b0f0e2c..bd0a5ed49c4 100644 --- a/drivers/leds/leds-s3c24xx.c +++ b/drivers/leds/leds-s3c24xx.c @@ -121,18 +121,7 @@ static struct platform_driver s3c24xx_led_driver = { }, }; -static int __init s3c24xx_led_init(void) -{ - return platform_driver_register(&s3c24xx_led_driver); -} - -static void __exit s3c24xx_led_exit(void) -{ - platform_driver_unregister(&s3c24xx_led_driver); -} - -module_init(s3c24xx_led_init); -module_exit(s3c24xx_led_exit); +module_platform_driver(s3c24xx_led_driver); MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); MODULE_DESCRIPTION("S3C24XX LED driver"); diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c new file mode 100644 index 00000000000..133f89fb707 --- /dev/null +++ b/drivers/leds/leds-tca6507.c @@ -0,0 +1,779 @@ +/* + * leds-tca6507 + * + * The TCA6507 is a programmable LED controller that can drive 7 + * separate lines either by holding them low, or by pulsing them + * with modulated width. + * The modulation can be varied in a simple pattern to produce a blink or + * double-blink. + * + * This driver can configure each line either as a 'GPIO' which is out-only + * (no pull-up) or as an LED with variable brightness and hardware-assisted + * blinking. + * + * Apart from OFF and ON there are three programmable brightness levels which + * can be programmed from 0 to 15 and indicate how many 500usec intervals in + * each 8msec that the led is 'on'. The levels are named MASTER, BANK0 and + * BANK1. + * + * There are two different blink rates that can be programmed, each with + * separate time for rise, on, fall, off and second-off. Thus if 3 or more + * different non-trivial rates are required, software must be used for the extra + * rates. The two different blink rates must align with the two levels BANK0 and + * BANK1. + * This driver does not support double-blink so 'second-off' always matches + * 'off'. + * + * Only 16 different times can be programmed in a roughly logarithmic scale from + * 64ms to 16320ms. To be precise the possible times are: + * 0, 64, 128, 192, 256, 384, 512, 768, + * 1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320 + * + * Times that cannot be closely matched with these must be + * handled in software. This driver allows 12.5% error in matching. + * + * This driver does not allow rise/fall rates to be set explicitly. When trying + * to match a given 'on' or 'off' period, an appropriate pair of 'change' and + * 'hold' times are chosen to get a close match. If the target delay is even, + * the 'change' number will be the smaller; if odd, the 'hold' number will be + * the smaller. + + * Choosing pairs of delays with 12.5% errors allows us to match delays in the + * ranges: 56-72, 112-144, 168-216, 224-27504, 28560-36720. + * 26% of the achievable sums can be matched by multiple pairings. For example + * 1536 == 1536+0, 1024+512, or 768+768. This driver will always choose the + * pairing with the least maximum - 768+768 in this case. Other pairings are + * not available. + * + * Access to the 3 levels and 2 blinks are on a first-come, first-served basis. + * Access can be shared by multiple leds if they have the same level and + * either same blink rates, or some don't blink. + * When a led changes, it relinquishes access and tries again, so it might + * lose access to hardware blink. + * If a blink engine cannot be allocated, software blink is used. + * If the desired brightness cannot be allocated, the closest available non-zero + * brightness is used. As 'full' is always available, the worst case would be + * to have two different blink rates at '1', with Max at '2', then other leds + * will have to choose between '2' and '16'. Hopefully this is not likely. + * + * Each bank (BANK0 and BANK1) has two usage counts - LEDs using the brightness + * and LEDs using the blink. It can only be reprogrammed when the appropriate + * counter is zero. The MASTER level has a single usage count. + * + * Each Led has programmable 'on' and 'off' time as milliseconds. With each + * there is a flag saying if it was explicitly requested or defaulted. + * Similarly the banks know if each time was explicit or a default. Defaults + * are permitted to be changed freely - they are not recognised when matching. + * + * + * An led-tca6507 device must be provided with platform data. This data + * lists for each output: the name, default trigger, and whether the signal + * is being used as a GPiO rather than an led. 'struct led_plaform_data' + * is used for this. If 'name' is NULL, the output isn't used. If 'flags' + * is TCA6507_MAKE_CPIO, the output is a GPO. + * The "struct led_platform_data" can be embedded in a + * "struct tca6507_platform_data" which adds a 'gpio_base' for the GPiOs, + * and a 'setup' callback which is called once the GPiOs are available. + * + */ + +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/leds.h> +#include <linux/err.h> +#include <linux/i2c.h> +#include <linux/gpio.h> +#include <linux/workqueue.h> +#include <linux/leds-tca6507.h> + +/* LED select registers determine the source that drives LED outputs */ +#define TCA6507_LS_LED_OFF 0x0 /* Output HI-Z (off) */ +#define TCA6507_LS_LED_OFF1 0x1 /* Output HI-Z (off) - not used */ +#define TCA6507_LS_LED_PWM0 0x2 /* Output LOW with Bank0 rate */ +#define TCA6507_LS_LED_PWM1 0x3 /* Output LOW with Bank1 rate */ +#define TCA6507_LS_LED_ON 0x4 /* Output LOW (on) */ +#define TCA6507_LS_LED_MIR 0x5 /* Output LOW with Master Intensity */ +#define TCA6507_LS_BLINK0 0x6 /* Blink at Bank0 rate */ +#define TCA6507_LS_BLINK1 0x7 /* Blink at Bank1 rate */ + +enum { + BANK0, + BANK1, + MASTER, +}; +static int bank_source[3] = { + TCA6507_LS_LED_PWM0, + TCA6507_LS_LED_PWM1, + TCA6507_LS_LED_MIR, +}; +static int blink_source[2] = { + TCA6507_LS_BLINK0, + TCA6507_LS_BLINK1, +}; + +/* PWM registers */ +#define TCA6507_REG_CNT 11 + +/* + * 0x00, 0x01, 0x02 encode the TCA6507_LS_* values, each output + * owns one bit in each register + */ +#define TCA6507_FADE_ON 0x03 +#define TCA6507_FULL_ON 0x04 +#define TCA6507_FADE_OFF 0x05 +#define TCA6507_FIRST_OFF 0x06 +#define TCA6507_SECOND_OFF 0x07 +#define TCA6507_MAX_INTENSITY 0x08 +#define TCA6507_MASTER_INTENSITY 0x09 +#define TCA6507_INITIALIZE 0x0A + +#define INIT_CODE 0x8 + +#define TIMECODES 16 +static int time_codes[TIMECODES] = { + 0, 64, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 5760, 8128, 16320 +}; + +/* Convert an led.brightness level (0..255) to a TCA6507 level (0..15) */ +static inline int TO_LEVEL(int brightness) +{ + return brightness >> 4; +} + +/* ...and convert back */ +static inline int TO_BRIGHT(int level) +{ + if (level) + return (level << 4) | 0xf; + return 0; +} + +#define NUM_LEDS 7 +struct tca6507_chip { + int reg_set; /* One bit per register where + * a '1' means the register + * should be written */ + u8 reg_file[TCA6507_REG_CNT]; + /* Bank 2 is Master Intensity and doesn't use times */ + struct bank { + int level; + int ontime, offtime; + int on_dflt, off_dflt; + int time_use, level_use; + } bank[3]; + struct i2c_client *client; + struct work_struct work; + spinlock_t lock; + + struct tca6507_led { + struct tca6507_chip *chip; + struct led_classdev led_cdev; + int num; + int ontime, offtime; + int on_dflt, off_dflt; + int bank; /* Bank used, or -1 */ + int blink; /* Set if hardware-blinking */ + } leds[NUM_LEDS]; +#ifdef CONFIG_GPIOLIB + struct gpio_chip gpio; + const char *gpio_name[NUM_LEDS]; + int gpio_map[NUM_LEDS]; +#endif +}; + +static const struct i2c_device_id tca6507_id[] = { + { "tca6507" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tca6507_id); + +static int choose_times(int msec, int *c1p, int *c2p) +{ + /* + * Choose two timecodes which add to 'msec' as near as possible. + * The first returned is the 'on' or 'off' time. The second is to be + * used as a 'fade-on' or 'fade-off' time. If 'msec' is even, + * the first will not be smaller than the second. If 'msec' is odd, + * the first will not be larger than the second. + * If we cannot get a sum within 1/8 of 'msec' fail with -EINVAL, + * otherwise return the sum that was achieved, plus 1 if the first is + * smaller. + * If two possibilities are equally good (e.g. 512+0, 256+256), choose + * the first pair so there is more change-time visible (i.e. it is + * softer). + */ + int c1, c2; + int tmax = msec * 9 / 8; + int tmin = msec * 7 / 8; + int diff = 65536; + + /* We start at '1' to ensure we never even think of choosing a + * total time of '0'. + */ + for (c1 = 1; c1 < TIMECODES; c1++) { + int t = time_codes[c1]; + if (t*2 < tmin) + continue; + if (t > tmax) + break; + for (c2 = 0; c2 <= c1; c2++) { + int tt = t + time_codes[c2]; + int d; + if (tt < tmin) + continue; + if (tt > tmax) + break; + /* This works! */ + d = abs(msec - tt); + if (d >= diff) + continue; + /* Best yet */ + *c1p = c1; + *c2p = c2; + diff = d; + if (d == 0) + return msec; + } + } + if (diff < 65536) { + int actual; + if (msec & 1) { + c1 = *c2p; + *c2p = *c1p; + *c1p = c1; + } + actual = time_codes[*c1p] + time_codes[*c2p]; + if (*c1p < *c2p) + return actual + 1; + else + return actual; + } + /* No close match */ + return -EINVAL; +} + +/* + * Update the register file with the appropriate 3-bit state for + * the given led. + */ +static void set_select(struct tca6507_chip *tca, int led, int val) +{ + int mask = (1 << led); + int bit; + + for (bit = 0; bit < 3; bit++) { + int n = tca->reg_file[bit] & ~mask; + if (val & (1 << bit)) + n |= mask; + if (tca->reg_file[bit] != n) { + tca->reg_file[bit] = n; + tca->reg_set |= (1 << bit); + } + } +} + +/* Update the register file with the appropriate 4-bit code for + * one bank or other. This can be used for timers, for levels, or + * for initialisation. + */ +static void set_code(struct tca6507_chip *tca, int reg, int bank, int new) +{ + int mask = 0xF; + int n; + if (bank) { + mask <<= 4; + new <<= 4; + } + n = tca->reg_file[reg] & ~mask; + n |= new; + if (tca->reg_file[reg] != n) { + tca->reg_file[reg] = n; + tca->reg_set |= 1 << reg; + } +} + +/* Update brightness level. */ +static void set_level(struct tca6507_chip *tca, int bank, int level) +{ + switch (bank) { + case BANK0: + case BANK1: + set_code(tca, TCA6507_MAX_INTENSITY, bank, level); + break; + case MASTER: + set_code(tca, TCA6507_MASTER_INTENSITY, 0, level); + break; + } + tca->bank[bank].level = level; +} + +/* Record all relevant time code for a given bank */ +static void set_times(struct tca6507_chip *tca, int bank) +{ + int c1, c2; + int result; + + result = choose_times(tca->bank[bank].ontime, &c1, &c2); + dev_dbg(&tca->client->dev, + "Chose on times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1], + c2, time_codes[c2], tca->bank[bank].ontime); + set_code(tca, TCA6507_FADE_ON, bank, c2); + set_code(tca, TCA6507_FULL_ON, bank, c1); + tca->bank[bank].ontime = result; + + result = choose_times(tca->bank[bank].offtime, &c1, &c2); + dev_dbg(&tca->client->dev, + "Chose off times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1], + c2, time_codes[c2], tca->bank[bank].offtime); + set_code(tca, TCA6507_FADE_OFF, bank, c2); + set_code(tca, TCA6507_FIRST_OFF, bank, c1); + set_code(tca, TCA6507_SECOND_OFF, bank, c1); + tca->bank[bank].offtime = result; + + set_code(tca, TCA6507_INITIALIZE, bank, INIT_CODE); +} + +/* Write all needed register of tca6507 */ + +static void tca6507_work(struct work_struct *work) +{ + struct tca6507_chip *tca = container_of(work, struct tca6507_chip, + work); + struct i2c_client *cl = tca->client; + int set; + u8 file[TCA6507_REG_CNT]; + int r; + + spin_lock_irq(&tca->lock); + set = tca->reg_set; + memcpy(file, tca->reg_file, TCA6507_REG_CNT); + tca->reg_set = 0; + spin_unlock_irq(&tca->lock); + + for (r = 0; r < TCA6507_REG_CNT; r++) + if (set & (1<<r)) + i2c_smbus_write_byte_data(cl, r, file[r]); +} + +static void led_release(struct tca6507_led *led) +{ + /* If led owns any resource, release it. */ + struct tca6507_chip *tca = led->chip; + if (led->bank >= 0) { + struct bank *b = tca->bank + led->bank; + if (led->blink) + b->time_use--; + b->level_use--; + } + led->blink = 0; + led->bank = -1; +} + +static int led_prepare(struct tca6507_led *led) +{ + /* Assign this led to a bank, configuring that bank if necessary. */ + int level = TO_LEVEL(led->led_cdev.brightness); + struct tca6507_chip *tca = led->chip; + int c1, c2; + int i; + struct bank *b; + int need_init = 0; + + led->led_cdev.brightness = TO_BRIGHT(level); + if (level == 0) { + set_select(tca, led->num, TCA6507_LS_LED_OFF); + return 0; + } + + if (led->ontime == 0 || led->offtime == 0) { + /* + * Just set the brightness, choosing first usable bank. + * If none perfect, choose best. + * Count backwards so we check MASTER bank first + * to avoid wasting a timer. + */ + int best = -1;/* full-on */ + int diff = 15-level; + + if (level == 15) { + set_select(tca, led->num, TCA6507_LS_LED_ON); + return 0; + } + + for (i = MASTER; i >= BANK0; i--) { + int d; + if (tca->bank[i].level == level || + tca->bank[i].level_use == 0) { + best = i; + break; + } + d = abs(level - tca->bank[i].level); + if (d < diff) { + diff = d; + best = i; + } + } + if (best == -1) { + /* Best brightness is full-on */ + set_select(tca, led->num, TCA6507_LS_LED_ON); + led->led_cdev.brightness = LED_FULL; + return 0; + } + + if (!tca->bank[best].level_use) + set_level(tca, best, level); + + tca->bank[best].level_use++; + led->bank = best; + set_select(tca, led->num, bank_source[best]); + led->led_cdev.brightness = TO_BRIGHT(tca->bank[best].level); + return 0; + } + + /* + * We have on/off time so we need to try to allocate a timing bank. + * First check if times are compatible with hardware and give up if + * not. + */ + if (choose_times(led->ontime, &c1, &c2) < 0) + return -EINVAL; + if (choose_times(led->offtime, &c1, &c2) < 0) + return -EINVAL; + + for (i = BANK0; i <= BANK1; i++) { + if (tca->bank[i].level_use == 0) + /* not in use - it is ours! */ + break; + if (tca->bank[i].level != level) + /* Incompatible level - skip */ + /* FIX: if timer matches we maybe should consider + * this anyway... + */ + continue; + + if (tca->bank[i].time_use == 0) + /* Timer not in use, and level matches - use it */ + break; + + if (!(tca->bank[i].on_dflt || + led->on_dflt || + tca->bank[i].ontime == led->ontime)) + /* on time is incompatible */ + continue; + + if (!(tca->bank[i].off_dflt || + led->off_dflt || + tca->bank[i].offtime == led->offtime)) + /* off time is incompatible */ + continue; + + /* looks like a suitable match */ + break; + } + + if (i > BANK1) + /* Nothing matches - how sad */ + return -EINVAL; + + b = &tca->bank[i]; + if (b->level_use == 0) + set_level(tca, i, level); + b->level_use++; + led->bank = i; + + if (b->on_dflt || + !led->on_dflt || + b->time_use == 0) { + b->ontime = led->ontime; + b->on_dflt = led->on_dflt; + need_init = 1; + } + + if (b->off_dflt || + !led->off_dflt || + b->time_use == 0) { + b->offtime = led->offtime; + b->off_dflt = led->off_dflt; + need_init = 1; + } + + if (need_init) + set_times(tca, i); + + led->ontime = b->ontime; + led->offtime = b->offtime; + + b->time_use++; + led->blink = 1; + led->led_cdev.brightness = TO_BRIGHT(b->level); + set_select(tca, led->num, blink_source[i]); + return 0; +} + +static int led_assign(struct tca6507_led *led) +{ + struct tca6507_chip *tca = led->chip; + int err; + unsigned long flags; + + spin_lock_irqsave(&tca->lock, flags); + led_release(led); + err = led_prepare(led); + if (err) { + /* + * Can only fail on timer setup. In that case we need to + * re-establish as steady level. + */ + led->ontime = 0; + led->offtime = 0; + led_prepare(led); + } + spin_unlock_irqrestore(&tca->lock, flags); + + if (tca->reg_set) + schedule_work(&tca->work); + return err; +} + +static void tca6507_brightness_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct tca6507_led *led = container_of(led_cdev, struct tca6507_led, + led_cdev); + led->led_cdev.brightness = brightness; + led->ontime = 0; + led->offtime = 0; + led_assign(led); +} + +static int tca6507_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + struct tca6507_led *led = container_of(led_cdev, struct tca6507_led, + led_cdev); + + if (*delay_on == 0) + led->on_dflt = 1; + else if (delay_on != &led_cdev->blink_delay_on) + led->on_dflt = 0; + led->ontime = *delay_on; + + if (*delay_off == 0) + led->off_dflt = 1; + else if (delay_off != &led_cdev->blink_delay_off) + led->off_dflt = 0; + led->offtime = *delay_off; + + if (led->ontime == 0) + led->ontime = 512; + if (led->offtime == 0) + led->offtime = 512; + + if (led->led_cdev.brightness == LED_OFF) + led->led_cdev.brightness = LED_FULL; + if (led_assign(led) < 0) { + led->ontime = 0; + led->offtime = 0; + led->led_cdev.brightness = LED_OFF; + return -EINVAL; + } + *delay_on = led->ontime; + *delay_off = led->offtime; + return 0; +} + +#ifdef CONFIG_GPIOLIB +static void tca6507_gpio_set_value(struct gpio_chip *gc, + unsigned offset, int val) +{ + struct tca6507_chip *tca = container_of(gc, struct tca6507_chip, gpio); + unsigned long flags; + + spin_lock_irqsave(&tca->lock, flags); + /* + * 'OFF' is floating high, and 'ON' is pulled down, so it has the + * inverse sense of 'val'. + */ + set_select(tca, tca->gpio_map[offset], + val ? TCA6507_LS_LED_OFF : TCA6507_LS_LED_ON); + spin_unlock_irqrestore(&tca->lock, flags); + if (tca->reg_set) + schedule_work(&tca->work); +} + +static int tca6507_gpio_direction_output(struct gpio_chip *gc, + unsigned offset, int val) +{ + tca6507_gpio_set_value(gc, offset, val); + return 0; +} + +static int tca6507_probe_gpios(struct i2c_client *client, + struct tca6507_chip *tca, + struct tca6507_platform_data *pdata) +{ + int err; + int i = 0; + int gpios = 0; + + for (i = 0; i < NUM_LEDS; i++) + if (pdata->leds.leds[i].name && pdata->leds.leds[i].flags) { + /* Configure as a gpio */ + tca->gpio_name[gpios] = pdata->leds.leds[i].name; + tca->gpio_map[gpios] = i; + gpios++; + } + + if (!gpios) + return 0; + + tca->gpio.label = "gpio-tca6507"; + tca->gpio.names = tca->gpio_name; + tca->gpio.ngpio = gpios; + tca->gpio.base = pdata->gpio_base; + tca->gpio.owner = THIS_MODULE; + tca->gpio.direction_output = tca6507_gpio_direction_output; + tca->gpio.set = tca6507_gpio_set_value; + tca->gpio.dev = &client->dev; + err = gpiochip_add(&tca->gpio); + if (err) { + tca->gpio.ngpio = 0; + return err; + } + if (pdata->setup) + pdata->setup(tca->gpio.base, tca->gpio.ngpio); + return 0; +} + +static void tca6507_remove_gpio(struct tca6507_chip *tca) +{ + if (tca->gpio.ngpio) { + int err = gpiochip_remove(&tca->gpio); + dev_err(&tca->client->dev, "%s failed, %d\n", + "gpiochip_remove()", err); + } +} +#else /* CONFIG_GPIOLIB */ +static int tca6507_probe_gpios(struct i2c_client *client, + struct tca6507_chip *tca, + struct tca6507_platform_data *pdata) +{ + return 0; +} +static void tca6507_remove_gpio(struct tca6507_chip *tca) +{ +} +#endif /* CONFIG_GPIOLIB */ + +static int __devinit tca6507_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct tca6507_chip *tca; + struct i2c_adapter *adapter; + struct tca6507_platform_data *pdata; + int err; + int i = 0; + + adapter = to_i2c_adapter(client->dev.parent); + pdata = client->dev.platform_data; + + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) + return -EIO; + + if (!pdata || pdata->leds.num_leds != NUM_LEDS) { + dev_err(&client->dev, "Need %d entries in platform-data list\n", + NUM_LEDS); + return -ENODEV; + } + err = -ENOMEM; + tca = kzalloc(sizeof(*tca), GFP_KERNEL); + if (!tca) + goto exit; + + tca->client = client; + INIT_WORK(&tca->work, tca6507_work); + spin_lock_init(&tca->lock); + i2c_set_clientdata(client, tca); + + for (i = 0; i < NUM_LEDS; i++) { + struct tca6507_led *l = tca->leds + i; + + l->chip = tca; + l->num = i; + if (pdata->leds.leds[i].name && !pdata->leds.leds[i].flags) { + l->led_cdev.name = pdata->leds.leds[i].name; + l->led_cdev.default_trigger + = pdata->leds.leds[i].default_trigger; + l->led_cdev.brightness_set = tca6507_brightness_set; + l->led_cdev.blink_set = tca6507_blink_set; + l->bank = -1; + err = led_classdev_register(&client->dev, + &l->led_cdev); + if (err < 0) + goto exit; + } + } + err = tca6507_probe_gpios(client, tca, pdata); + if (err) + goto exit; + /* set all registers to known state - zero */ + tca->reg_set = 0x7f; + schedule_work(&tca->work); + + return 0; +exit: + while (i--) + if (tca->leds[i].led_cdev.name) + led_classdev_unregister(&tca->leds[i].led_cdev); + cancel_work_sync(&tca->work); + i2c_set_clientdata(client, NULL); + kfree(tca); + return err; +} + +static int __devexit tca6507_remove(struct i2c_client *client) +{ + int i; + struct tca6507_chip *tca = i2c_get_clientdata(client); + struct tca6507_led *tca_leds = tca->leds; + + for (i = 0; i < NUM_LEDS; i++) { + if (tca_leds[i].led_cdev.name) + led_classdev_unregister(&tca_leds[i].led_cdev); + } + tca6507_remove_gpio(tca); + cancel_work_sync(&tca->work); + i2c_set_clientdata(client, NULL); + kfree(tca); + + return 0; +} + +static struct i2c_driver tca6507_driver = { + .driver = { + .name = "leds-tca6507", + .owner = THIS_MODULE, + }, + .probe = tca6507_probe, + .remove = __devexit_p(tca6507_remove), + .id_table = tca6507_id, +}; + +static int __init tca6507_leds_init(void) +{ + return i2c_add_driver(&tca6507_driver); +} + +static void __exit tca6507_leds_exit(void) +{ + i2c_del_driver(&tca6507_driver); +} + +module_init(tca6507_leds_init); +module_exit(tca6507_leds_exit); + +MODULE_AUTHOR("NeilBrown <neilb@suse.de>"); +MODULE_DESCRIPTION("TCA6507 LED/GPO driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/leds/leds-wm831x-status.c b/drivers/leds/leds-wm831x-status.c index b1eb34c3e81..74a24cf897c 100644 --- a/drivers/leds/leds-wm831x-status.c +++ b/drivers/leds/leds-wm831x-status.c @@ -237,7 +237,8 @@ static int wm831x_status_probe(struct platform_device *pdev) goto err; } - drvdata = kzalloc(sizeof(struct wm831x_status), GFP_KERNEL); + drvdata = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_status), + GFP_KERNEL); if (!drvdata) return -ENOMEM; dev_set_drvdata(&pdev->dev, drvdata); @@ -300,7 +301,6 @@ static int wm831x_status_probe(struct platform_device *pdev) err_led: led_classdev_unregister(&drvdata->cdev); - kfree(drvdata); err: return ret; } @@ -311,7 +311,6 @@ static int wm831x_status_remove(struct platform_device *pdev) device_remove_file(drvdata->cdev.dev, &dev_attr_src); led_classdev_unregister(&drvdata->cdev); - kfree(drvdata); return 0; } @@ -325,17 +324,7 @@ static struct platform_driver wm831x_status_driver = { .remove = wm831x_status_remove, }; -static int __devinit wm831x_status_init(void) -{ - return platform_driver_register(&wm831x_status_driver); -} -module_init(wm831x_status_init); - -static void wm831x_status_exit(void) -{ - platform_driver_unregister(&wm831x_status_driver); -} -module_exit(wm831x_status_exit); +module_platform_driver(wm831x_status_driver); MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); MODULE_DESCRIPTION("WM831x status LED driver"); diff --git a/drivers/leds/leds-wm8350.c b/drivers/leds/leds-wm8350.c index 4a127657835..918d4baff1c 100644 --- a/drivers/leds/leds-wm8350.c +++ b/drivers/leds/leds-wm8350.c @@ -227,7 +227,7 @@ static int wm8350_led_probe(struct platform_device *pdev) goto err_isink; } - led = kzalloc(sizeof(*led), GFP_KERNEL); + led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL); if (led == NULL) { ret = -ENOMEM; goto err_dcdc; @@ -259,12 +259,10 @@ static int wm8350_led_probe(struct platform_device *pdev) ret = led_classdev_register(&pdev->dev, &led->cdev); if (ret < 0) - goto err_led; + goto err_dcdc; return 0; - err_led: - kfree(led); err_dcdc: regulator_put(dcdc); err_isink: @@ -281,7 +279,6 @@ static int wm8350_led_remove(struct platform_device *pdev) wm8350_led_disable(led); regulator_put(led->dcdc); regulator_put(led->isink); - kfree(led); return 0; } @@ -295,17 +292,7 @@ static struct platform_driver wm8350_led_driver = { .shutdown = wm8350_led_shutdown, }; -static int __devinit wm8350_led_init(void) -{ - return platform_driver_register(&wm8350_led_driver); -} -module_init(wm8350_led_init); - -static void wm8350_led_exit(void) -{ - platform_driver_unregister(&wm8350_led_driver); -} -module_exit(wm8350_led_exit); +module_platform_driver(wm8350_led_driver); MODULE_AUTHOR("Mark Brown"); MODULE_DESCRIPTION("WM8350 LED driver"); diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 8e286259a00..8a1c031391d 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -228,11 +228,11 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) alarm->time.tm_hour = now.tm_hour; /* For simplicity, only support date rollover for now */ - if (alarm->time.tm_mday == -1) { + if (alarm->time.tm_mday < 1 || alarm->time.tm_mday > 31) { alarm->time.tm_mday = now.tm_mday; missing = day; } - if (alarm->time.tm_mon == -1) { + if ((unsigned)alarm->time.tm_mon >= 12) { alarm->time.tm_mon = now.tm_mon; if (missing == none) missing = month; diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c index 64b847b7f97..f04761e6622 100644 --- a/drivers/rtc/rtc-88pm860x.c +++ b/drivers/rtc/rtc-88pm860x.c @@ -410,17 +410,7 @@ static struct platform_driver pm860x_rtc_driver = { .remove = __devexit_p(pm860x_rtc_remove), }; -static int __init pm860x_rtc_init(void) -{ - return platform_driver_register(&pm860x_rtc_driver); -} -module_init(pm860x_rtc_init); - -static void __exit pm860x_rtc_exit(void) -{ - platform_driver_unregister(&pm860x_rtc_driver); -} -module_exit(pm860x_rtc_exit); +module_platform_driver(pm860x_rtc_driver); MODULE_DESCRIPTION("Marvell 88PM860x RTC driver"); MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c index e346705aae9..a0a9810adf0 100644 --- a/drivers/rtc/rtc-ab8500.c +++ b/drivers/rtc/rtc-ab8500.c @@ -90,7 +90,7 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) /* Early AB8500 chips will not clear the rtc read request bit */ if (abx500_get_chip_id(dev) == 0) { - msleep(1); + usleep_range(1000, 1000); } else { /* Wait for some cycles after enabling the rtc read in ab8500 */ while (time_before(jiffies, timeout)) { @@ -102,7 +102,7 @@ static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) if (!(value & RTC_READ_REQUEST)) break; - msleep(1); + usleep_range(1000, 5000); } } @@ -258,6 +258,109 @@ static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) return ab8500_rtc_irq_enable(dev, alarm->enabled); } + +static int ab8500_rtc_set_calibration(struct device *dev, int calibration) +{ + int retval; + u8 rtccal = 0; + + /* + * Check that the calibration value (which is in units of 0.5 + * parts-per-million) is in the AB8500's range for RtcCalibration + * register. -128 (0x80) is not permitted because the AB8500 uses + * a sign-bit rather than two's complement, so 0x80 is just another + * representation of zero. + */ + if ((calibration < -127) || (calibration > 127)) { + dev_err(dev, "RtcCalibration value outside permitted range\n"); + return -EINVAL; + } + + /* + * The AB8500 uses sign (in bit7) and magnitude (in bits0-7) + * so need to convert to this sort of representation before writing + * into RtcCalibration register... + */ + if (calibration >= 0) + rtccal = 0x7F & calibration; + else + rtccal = ~(calibration - 1) | 0x80; + + retval = abx500_set_register_interruptible(dev, AB8500_RTC, + AB8500_RTC_CALIB_REG, rtccal); + + return retval; +} + +static int ab8500_rtc_get_calibration(struct device *dev, int *calibration) +{ + int retval; + u8 rtccal = 0; + + retval = abx500_get_register_interruptible(dev, AB8500_RTC, + AB8500_RTC_CALIB_REG, &rtccal); + if (retval >= 0) { + /* + * The AB8500 uses sign (in bit7) and magnitude (in bits0-7) + * so need to convert value from RtcCalibration register into + * a two's complement signed value... + */ + if (rtccal & 0x80) + *calibration = 0 - (rtccal & 0x7F); + else + *calibration = 0x7F & rtccal; + } + + return retval; +} + +static ssize_t ab8500_sysfs_store_rtc_calibration(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int retval; + int calibration = 0; + + if (sscanf(buf, " %i ", &calibration) != 1) { + dev_err(dev, "Failed to store RTC calibration attribute\n"); + return -EINVAL; + } + + retval = ab8500_rtc_set_calibration(dev, calibration); + + return retval ? retval : count; +} + +static ssize_t ab8500_sysfs_show_rtc_calibration(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval = 0; + int calibration = 0; + + retval = ab8500_rtc_get_calibration(dev, &calibration); + if (retval < 0) { + dev_err(dev, "Failed to read RTC calibration attribute\n"); + sprintf(buf, "0\n"); + return retval; + } + + return sprintf(buf, "%d\n", calibration); +} + +static DEVICE_ATTR(rtc_calibration, S_IRUGO | S_IWUSR, + ab8500_sysfs_show_rtc_calibration, + ab8500_sysfs_store_rtc_calibration); + +static int ab8500_sysfs_rtc_register(struct device *dev) +{ + return device_create_file(dev, &dev_attr_rtc_calibration); +} + +static void ab8500_sysfs_rtc_unregister(struct device *dev) +{ + device_remove_file(dev, &dev_attr_rtc_calibration); +} + static irqreturn_t rtc_alarm_handler(int irq, void *data) { struct rtc_device *rtc = data; @@ -295,7 +398,7 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev) return err; /* Wait for reset by the PorRtc */ - msleep(1); + usleep_range(1000, 5000); err = abx500_get_register_interruptible(&pdev->dev, AB8500_RTC, AB8500_RTC_STAT_REG, &rtc_ctrl); @@ -308,6 +411,8 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev) return -ENODEV; } + device_init_wakeup(&pdev->dev, true); + rtc = rtc_device_register("ab8500-rtc", &pdev->dev, &ab8500_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { @@ -316,8 +421,8 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev) return err; } - err = request_threaded_irq(irq, NULL, rtc_alarm_handler, 0, - "ab8500-rtc", rtc); + err = request_threaded_irq(irq, NULL, rtc_alarm_handler, + IRQF_NO_SUSPEND, "ab8500-rtc", rtc); if (err < 0) { rtc_device_unregister(rtc); return err; @@ -325,6 +430,13 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc); + + err = ab8500_sysfs_rtc_register(&pdev->dev); + if (err) { + dev_err(&pdev->dev, "sysfs RTC failed to register\n"); + return err; + } + return 0; } @@ -333,6 +445,8 @@ static int __devexit ab8500_rtc_remove(struct platform_device *pdev) struct rtc_device *rtc = platform_get_drvdata(pdev); int irq = platform_get_irq_byname(pdev, "ALARM"); + ab8500_sysfs_rtc_unregister(&pdev->dev); + free_irq(irq, rtc); rtc_device_unregister(rtc); platform_set_drvdata(pdev, NULL); @@ -349,18 +463,8 @@ static struct platform_driver ab8500_rtc_driver = { .remove = __devexit_p(ab8500_rtc_remove), }; -static int __init ab8500_rtc_init(void) -{ - return platform_driver_register(&ab8500_rtc_driver); -} - -static void __exit ab8500_rtc_exit(void) -{ - platform_driver_unregister(&ab8500_rtc_driver); -} +module_platform_driver(ab8500_rtc_driver); -module_init(ab8500_rtc_init); -module_exit(ab8500_rtc_exit); MODULE_AUTHOR("Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com>"); MODULE_DESCRIPTION("AB8500 RTC Driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index 90d866272c8..abfc1a0c07d 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c @@ -456,18 +456,7 @@ static struct platform_driver bfin_rtc_driver = { .resume = bfin_rtc_resume, }; -static int __init bfin_rtc_init(void) -{ - return platform_driver_register(&bfin_rtc_driver); -} - -static void __exit bfin_rtc_exit(void) -{ - platform_driver_unregister(&bfin_rtc_driver); -} - -module_init(bfin_rtc_init); -module_exit(bfin_rtc_exit); +module_platform_driver(bfin_rtc_driver); MODULE_DESCRIPTION("Blackfin On-Chip Real Time Clock Driver"); MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>"); diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c index 128270ce355..bf612ef2294 100644 --- a/drivers/rtc/rtc-bq4802.c +++ b/drivers/rtc/rtc-bq4802.c @@ -218,15 +218,4 @@ static struct platform_driver bq4802_driver = { .remove = __devexit_p(bq4802_remove), }; -static int __init bq4802_init(void) -{ - return platform_driver_register(&bq4802_driver); -} - -static void __exit bq4802_exit(void) -{ - platform_driver_unregister(&bq4802_driver); -} - -module_init(bq4802_init); -module_exit(bq4802_exit); +module_platform_driver(bq4802_driver); diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 05beb6c1ca7..d7782aa0994 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -164,7 +164,7 @@ static inline unsigned char cmos_read_bank2(unsigned char addr) static inline void cmos_write_bank2(unsigned char val, unsigned char addr) { outb(addr, RTC_PORT(2)); - outb(val, RTC_PORT(2)); + outb(val, RTC_PORT(3)); } #else diff --git a/drivers/rtc/rtc-dm355evm.c b/drivers/rtc/rtc-dm355evm.c index 2322c43af20..d4457afcba8 100644 --- a/drivers/rtc/rtc-dm355evm.c +++ b/drivers/rtc/rtc-dm355evm.c @@ -161,16 +161,6 @@ static struct platform_driver rtc_dm355evm_driver = { }, }; -static int __init dm355evm_rtc_init(void) -{ - return platform_driver_register(&rtc_dm355evm_driver); -} -module_init(dm355evm_rtc_init); - -static void __exit dm355evm_rtc_exit(void) -{ - platform_driver_unregister(&rtc_dm355evm_driver); -} -module_exit(dm355evm_rtc_exit); +module_platform_driver(rtc_dm355evm_driver); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c index 68e6caf2549..990c3ff489b 100644 --- a/drivers/rtc/rtc-ds1286.c +++ b/drivers/rtc/rtc-ds1286.c @@ -396,21 +396,10 @@ static struct platform_driver ds1286_platform_driver = { .remove = __devexit_p(ds1286_remove), }; -static int __init ds1286_init(void) -{ - return platform_driver_register(&ds1286_platform_driver); -} - -static void __exit ds1286_exit(void) -{ - platform_driver_unregister(&ds1286_platform_driver); -} +module_platform_driver(ds1286_platform_driver); MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>"); MODULE_DESCRIPTION("DS1286 RTC driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); MODULE_ALIAS("platform:rtc-ds1286"); - -module_init(ds1286_init); -module_exit(ds1286_exit); diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index 586c244a05d..761f36bc83a 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c @@ -580,20 +580,7 @@ static struct platform_driver ds1511_rtc_driver = { }, }; - static int __init -ds1511_rtc_init(void) -{ - return platform_driver_register(&ds1511_rtc_driver); -} - - static void __exit -ds1511_rtc_exit(void) -{ - platform_driver_unregister(&ds1511_rtc_driver); -} - -module_init(ds1511_rtc_init); -module_exit(ds1511_rtc_exit); +module_platform_driver(ds1511_rtc_driver); MODULE_AUTHOR("Andrew Sharp <andy.sharp@lsi.com>"); MODULE_DESCRIPTION("Dallas DS1511 RTC driver"); diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index 1350029044e..6f0a1b530f2 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c @@ -361,18 +361,7 @@ static struct platform_driver ds1553_rtc_driver = { }, }; -static __init int ds1553_init(void) -{ - return platform_driver_register(&ds1553_rtc_driver); -} - -static __exit void ds1553_exit(void) -{ - platform_driver_unregister(&ds1553_rtc_driver); -} - -module_init(ds1553_init); -module_exit(ds1553_exit); +module_platform_driver(ds1553_rtc_driver); MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); MODULE_DESCRIPTION("Dallas DS1553 RTC driver"); diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index e3e0f92b60f..76112667c50 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c @@ -240,18 +240,7 @@ static struct platform_driver ds1742_rtc_driver = { }, }; -static __init int ds1742_init(void) -{ - return platform_driver_register(&ds1742_rtc_driver); -} - -static __exit void ds1742_exit(void) -{ - platform_driver_unregister(&ds1742_rtc_driver); -} - -module_init(ds1742_init); -module_exit(ds1742_exit); +module_platform_driver(ds1742_rtc_driver); MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); MODULE_DESCRIPTION("Dallas DS1742 RTC driver"); diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c index b6473631d18..05ab227eeff 100644 --- a/drivers/rtc/rtc-jz4740.c +++ b/drivers/rtc/rtc-jz4740.c @@ -345,7 +345,7 @@ static const struct dev_pm_ops jz4740_pm_ops = { #define JZ4740_RTC_PM_OPS NULL #endif /* CONFIG_PM */ -struct platform_driver jz4740_rtc_driver = { +static struct platform_driver jz4740_rtc_driver = { .probe = jz4740_rtc_probe, .remove = __devexit_p(jz4740_rtc_remove), .driver = { @@ -355,17 +355,7 @@ struct platform_driver jz4740_rtc_driver = { }, }; -static int __init jz4740_rtc_init(void) -{ - return platform_driver_register(&jz4740_rtc_driver); -} -module_init(jz4740_rtc_init); - -static void __exit jz4740_rtc_exit(void) -{ - platform_driver_unregister(&jz4740_rtc_driver); -} -module_exit(jz4740_rtc_exit); +module_platform_driver(jz4740_rtc_driver); MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-lpc32xx.c b/drivers/rtc/rtc-lpc32xx.c index ae16250c762..ecc1713b2b4 100644 --- a/drivers/rtc/rtc-lpc32xx.c +++ b/drivers/rtc/rtc-lpc32xx.c @@ -396,17 +396,7 @@ static struct platform_driver lpc32xx_rtc_driver = { }, }; -static int __init lpc32xx_rtc_init(void) -{ - return platform_driver_register(&lpc32xx_rtc_driver); -} -module_init(lpc32xx_rtc_init); - -static void __exit lpc32xx_rtc_exit(void) -{ - platform_driver_unregister(&lpc32xx_rtc_driver); -} -module_exit(lpc32xx_rtc_exit); +module_platform_driver(lpc32xx_rtc_driver); MODULE_AUTHOR("Kevin Wells <wellsk40@gmail.com"); MODULE_DESCRIPTION("RTC driver for the LPC32xx SoC"); diff --git a/drivers/rtc/rtc-m41t93.c b/drivers/rtc/rtc-m41t93.c index 7317d3b9a3d..ef71132ff20 100644 --- a/drivers/rtc/rtc-m41t93.c +++ b/drivers/rtc/rtc-m41t93.c @@ -200,7 +200,6 @@ static int __devexit m41t93_remove(struct spi_device *spi) static struct spi_driver m41t93_driver = { .driver = { .name = "rtc-m41t93", - .bus = &spi_bus_type, .owner = THIS_MODULE, }, .probe = m41t93_probe, diff --git a/drivers/rtc/rtc-m41t94.c b/drivers/rtc/rtc-m41t94.c index e259ed76ae8..2a4721f6179 100644 --- a/drivers/rtc/rtc-m41t94.c +++ b/drivers/rtc/rtc-m41t94.c @@ -147,7 +147,6 @@ static int __devexit m41t94_remove(struct spi_device *spi) static struct spi_driver m41t94_driver = { .driver = { .name = "rtc-m41t94", - .bus = &spi_bus_type, .owner = THIS_MODULE, }, .probe = m41t94_probe, diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c index 8e2a24e33ed..f9e3b358373 100644 --- a/drivers/rtc/rtc-m48t35.c +++ b/drivers/rtc/rtc-m48t35.c @@ -216,21 +216,10 @@ static struct platform_driver m48t35_platform_driver = { .remove = __devexit_p(m48t35_remove), }; -static int __init m48t35_init(void) -{ - return platform_driver_register(&m48t35_platform_driver); -} - -static void __exit m48t35_exit(void) -{ - platform_driver_unregister(&m48t35_platform_driver); -} +module_platform_driver(m48t35_platform_driver); MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>"); MODULE_DESCRIPTION("M48T35 RTC driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); MODULE_ALIAS("platform:rtc-m48t35"); - -module_init(m48t35_init); -module_exit(m48t35_exit); diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 28365388fb6..30ebfec9fd2 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c @@ -530,18 +530,7 @@ static struct platform_driver m48t59_rtc_driver = { .remove = __devexit_p(m48t59_rtc_remove), }; -static int __init m48t59_rtc_init(void) -{ - return platform_driver_register(&m48t59_rtc_driver); -} - -static void __exit m48t59_rtc_exit(void) -{ - platform_driver_unregister(&m48t59_rtc_driver); -} - -module_init(m48t59_rtc_init); -module_exit(m48t59_rtc_exit); +module_platform_driver(m48t59_rtc_driver); MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>"); MODULE_DESCRIPTION("M48T59/M48T02/M48T08 RTC driver"); diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c index f981287d582..863fb3363aa 100644 --- a/drivers/rtc/rtc-m48t86.c +++ b/drivers/rtc/rtc-m48t86.c @@ -185,21 +185,10 @@ static struct platform_driver m48t86_rtc_platform_driver = { .remove = __devexit_p(m48t86_rtc_remove), }; -static int __init m48t86_rtc_init(void) -{ - return platform_driver_register(&m48t86_rtc_platform_driver); -} - -static void __exit m48t86_rtc_exit(void) -{ - platform_driver_unregister(&m48t86_rtc_platform_driver); -} +module_platform_driver(m48t86_rtc_platform_driver); MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); MODULE_DESCRIPTION("M48T86 RTC driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); MODULE_ALIAS("platform:rtc-m48t86"); - -module_init(m48t86_rtc_init); -module_exit(m48t86_rtc_exit); diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c index 0ec3f588a25..1f6b3cc58e8 100644 --- a/drivers/rtc/rtc-max6902.c +++ b/drivers/rtc/rtc-max6902.c @@ -154,7 +154,6 @@ static int __devexit max6902_remove(struct spi_device *spi) static struct spi_driver max6902_driver = { .driver = { .name = "rtc-max6902", - .bus = &spi_bus_type, .owner = THIS_MODULE, }, .probe = max6902_probe, diff --git a/drivers/rtc/rtc-max8925.c b/drivers/rtc/rtc-max8925.c index 3bc046f427e..4a5529346b4 100644 --- a/drivers/rtc/rtc-max8925.c +++ b/drivers/rtc/rtc-max8925.c @@ -299,17 +299,7 @@ static struct platform_driver max8925_rtc_driver = { .remove = __devexit_p(max8925_rtc_remove), }; -static int __init max8925_rtc_init(void) -{ - return platform_driver_register(&max8925_rtc_driver); -} -module_init(max8925_rtc_init); - -static void __exit max8925_rtc_exit(void) -{ - platform_driver_unregister(&max8925_rtc_driver); -} -module_exit(max8925_rtc_exit); +module_platform_driver(max8925_rtc_driver); MODULE_DESCRIPTION("Maxim MAX8925 RTC driver"); MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); diff --git a/drivers/rtc/rtc-max8998.c b/drivers/rtc/rtc-max8998.c index 2e48aa60427..7196f438c08 100644 --- a/drivers/rtc/rtc-max8998.c +++ b/drivers/rtc/rtc-max8998.c @@ -327,17 +327,7 @@ static struct platform_driver max8998_rtc_driver = { .id_table = max8998_rtc_id, }; -static int __init max8998_rtc_init(void) -{ - return platform_driver_register(&max8998_rtc_driver); -} -module_init(max8998_rtc_init); - -static void __exit max8998_rtc_exit(void) -{ - platform_driver_unregister(&max8998_rtc_driver); -} -module_exit(max8998_rtc_exit); +module_platform_driver(max8998_rtc_driver); MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>"); MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c index 9d0c3b478d5..546f6850bff 100644 --- a/drivers/rtc/rtc-mc13xxx.c +++ b/drivers/rtc/rtc-mc13xxx.c @@ -399,7 +399,7 @@ static int __exit mc13xxx_rtc_remove(struct platform_device *pdev) return 0; } -const struct platform_device_id mc13xxx_rtc_idtable[] = { +static const struct platform_device_id mc13xxx_rtc_idtable[] = { { .name = "mc13783-rtc", }, { diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index da60915818b..9d3caccfc25 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c @@ -418,17 +418,7 @@ static struct platform_driver mpc5121_rtc_driver = { .remove = __devexit_p(mpc5121_rtc_remove), }; -static int __init mpc5121_rtc_init(void) -{ - return platform_driver_register(&mpc5121_rtc_driver); -} -module_init(mpc5121_rtc_init); - -static void __exit mpc5121_rtc_exit(void) -{ - platform_driver_unregister(&mpc5121_rtc_driver); -} -module_exit(mpc5121_rtc_exit); +module_platform_driver(mpc5121_rtc_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("John Rigby <jcrigby@gmail.com>"); diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c index bb21f443fb7..6cd6c723534 100644 --- a/drivers/rtc/rtc-mrst.c +++ b/drivers/rtc/rtc-mrst.c @@ -537,18 +537,7 @@ static struct platform_driver vrtc_mrst_platform_driver = { } }; -static int __init vrtc_mrst_init(void) -{ - return platform_driver_register(&vrtc_mrst_platform_driver); -} - -static void __exit vrtc_mrst_exit(void) -{ - platform_driver_unregister(&vrtc_mrst_platform_driver); -} - -module_init(vrtc_mrst_init); -module_exit(vrtc_mrst_exit); +module_platform_driver(vrtc_mrst_platform_driver); MODULE_AUTHOR("Jacob Pan; Feng Tang"); MODULE_DESCRIPTION("Driver for Moorestown virtual RTC"); diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index 39e41fbdf08..5e1d64ee522 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c @@ -155,7 +155,6 @@ static int rtc_update_alarm(struct device *dev, struct rtc_time *alrm) { struct rtc_time alarm_tm, now_tm; unsigned long now, time; - int ret; struct platform_device *pdev = to_platform_device(dev); struct rtc_plat_data *pdata = platform_get_drvdata(pdev); void __iomem *ioaddr = pdata->ioaddr; @@ -168,21 +167,33 @@ static int rtc_update_alarm(struct device *dev, struct rtc_time *alrm) alarm_tm.tm_hour = alrm->tm_hour; alarm_tm.tm_min = alrm->tm_min; alarm_tm.tm_sec = alrm->tm_sec; - rtc_tm_to_time(&now_tm, &now); rtc_tm_to_time(&alarm_tm, &time); - if (time < now) { - time += 60 * 60 * 24; - rtc_time_to_tm(time, &alarm_tm); - } - - ret = rtc_tm_to_time(&alarm_tm, &time); - /* clear all the interrupt status bits */ writew(readw(ioaddr + RTC_RTCISR), ioaddr + RTC_RTCISR); set_alarm_or_time(dev, MXC_RTC_ALARM, time); - return ret; + return 0; +} + +static void mxc_rtc_irq_enable(struct device *dev, unsigned int bit, + unsigned int enabled) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + void __iomem *ioaddr = pdata->ioaddr; + u32 reg; + + spin_lock_irq(&pdata->rtc->irq_lock); + reg = readw(ioaddr + RTC_RTCIENR); + + if (enabled) + reg |= bit; + else + reg &= ~bit; + + writew(reg, ioaddr + RTC_RTCIENR); + spin_unlock_irq(&pdata->rtc->irq_lock); } /* This function is the RTC interrupt service routine. */ @@ -199,13 +210,12 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id) /* clear interrupt sources */ writew(status, ioaddr + RTC_RTCISR); - /* clear alarm interrupt if it has occurred */ - if (status & RTC_ALM_BIT) - status &= ~RTC_ALM_BIT; - /* update irq data & counter */ - if (status & RTC_ALM_BIT) + if (status & RTC_ALM_BIT) { events |= (RTC_AF | RTC_IRQF); + /* RTC alarm should be one-shot */ + mxc_rtc_irq_enable(&pdev->dev, RTC_ALM_BIT, 0); + } if (status & RTC_1HZ_BIT) events |= (RTC_UF | RTC_IRQF); @@ -213,9 +223,6 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id) if (status & PIT_ALL_ON) events |= (RTC_PF | RTC_IRQF); - if ((status & RTC_ALM_BIT) && rtc_valid_tm(&pdata->g_rtc_alarm)) - rtc_update_alarm(&pdev->dev, &pdata->g_rtc_alarm); - rtc_update_irq(pdata->rtc, 1, events); spin_unlock_irq(&pdata->rtc->irq_lock); @@ -242,26 +249,6 @@ static void mxc_rtc_release(struct device *dev) spin_unlock_irq(&pdata->rtc->irq_lock); } -static void mxc_rtc_irq_enable(struct device *dev, unsigned int bit, - unsigned int enabled) -{ - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); - void __iomem *ioaddr = pdata->ioaddr; - u32 reg; - - spin_lock_irq(&pdata->rtc->irq_lock); - reg = readw(ioaddr + RTC_RTCIENR); - - if (enabled) - reg |= bit; - else - reg &= ~bit; - - writew(reg, ioaddr + RTC_RTCIENR); - spin_unlock_irq(&pdata->rtc->irq_lock); -} - static int mxc_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) { mxc_rtc_irq_enable(dev, RTC_ALM_BIT, enabled); @@ -290,6 +277,17 @@ static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm) */ static int mxc_rtc_set_mmss(struct device *dev, unsigned long time) { + /* + * TTC_DAYR register is 9-bit in MX1 SoC, save time and day of year only + */ + if (cpu_is_mx1()) { + struct rtc_time tm; + + rtc_time_to_tm(time, &tm); + tm.tm_year = 70; + rtc_tm_to_time(&tm, &time); + } + /* Avoid roll-over from reading the different registers */ do { set_alarm_or_time(dev, MXC_RTC_TIME, time); @@ -324,21 +322,7 @@ static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) struct rtc_plat_data *pdata = platform_get_drvdata(pdev); int ret; - if (rtc_valid_tm(&alrm->time)) { - if (alrm->time.tm_sec > 59 || - alrm->time.tm_hour > 23 || - alrm->time.tm_min > 59) - return -EINVAL; - - ret = rtc_update_alarm(dev, &alrm->time); - } else { - ret = rtc_valid_tm(&alrm->time); - if (ret) - return ret; - - ret = rtc_update_alarm(dev, &alrm->time); - } - + ret = rtc_update_alarm(dev, &alrm->time); if (ret) return ret; @@ -424,6 +408,9 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) pdata->irq = -1; } + if (pdata->irq >=0) + device_init_wakeup(&pdev->dev, 1); + rtc = rtc_device_register(pdev->name, &pdev->dev, &mxc_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { @@ -459,9 +446,39 @@ static int __exit mxc_rtc_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM +static int mxc_rtc_suspend(struct device *dev) +{ + struct rtc_plat_data *pdata = dev_get_drvdata(dev); + + if (device_may_wakeup(dev)) + enable_irq_wake(pdata->irq); + + return 0; +} + +static int mxc_rtc_resume(struct device *dev) +{ + struct rtc_plat_data *pdata = dev_get_drvdata(dev); + + if (device_may_wakeup(dev)) + disable_irq_wake(pdata->irq); + + return 0; +} + +static struct dev_pm_ops mxc_rtc_pm_ops = { + .suspend = mxc_rtc_suspend, + .resume = mxc_rtc_resume, +}; +#endif + static struct platform_driver mxc_rtc_driver = { .driver = { .name = "mxc_rtc", +#ifdef CONFIG_PM + .pm = &mxc_rtc_pm_ops, +#endif .owner = THIS_MODULE, }, .remove = __exit_p(mxc_rtc_remove), diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index 2ee3bbf7e5e..b46c4004d8f 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -340,7 +340,6 @@ static int __devexit pcf2123_remove(struct spi_device *spi) static struct spi_driver pcf2123_driver = { .driver = { .name = "rtc-pcf2123", - .bus = &spi_bus_type, .owner = THIS_MODULE, }, .probe = pcf2123_probe, diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c index 0c423892923..a20202f9ee5 100644 --- a/drivers/rtc/rtc-pcf50633.c +++ b/drivers/rtc/rtc-pcf50633.c @@ -294,17 +294,7 @@ static struct platform_driver pcf50633_rtc_driver = { .remove = __devexit_p(pcf50633_rtc_remove), }; -static int __init pcf50633_rtc_init(void) -{ - return platform_driver_register(&pcf50633_rtc_driver); -} -module_init(pcf50633_rtc_init); - -static void __exit pcf50633_rtc_exit(void) -{ - platform_driver_unregister(&pcf50633_rtc_driver); -} -module_exit(pcf50633_rtc_exit); +module_platform_driver(pcf50633_rtc_driver); MODULE_DESCRIPTION("PCF50633 RTC driver"); MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>"); diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c index d420e9d877e..9f1d6bcbdf6 100644 --- a/drivers/rtc/rtc-pm8xxx.c +++ b/drivers/rtc/rtc-pm8xxx.c @@ -532,17 +532,7 @@ static struct platform_driver pm8xxx_rtc_driver = { }, }; -static int __init pm8xxx_rtc_init(void) -{ - return platform_driver_register(&pm8xxx_rtc_driver); -} -module_init(pm8xxx_rtc_init); - -static void __exit pm8xxx_rtc_exit(void) -{ - platform_driver_unregister(&pm8xxx_rtc_driver); -} -module_exit(pm8xxx_rtc_exit); +module_platform_driver(pm8xxx_rtc_driver); MODULE_ALIAS("platform:rtc-pm8xxx"); MODULE_DESCRIPTION("PMIC8xxx RTC driver"); diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c index 971bc8e08da..ce2ca8523dd 100644 --- a/drivers/rtc/rtc-rs5c348.c +++ b/drivers/rtc/rtc-rs5c348.c @@ -229,7 +229,6 @@ static int __devexit rs5c348_remove(struct spi_device *spi) static struct spi_driver rs5c348_driver = { .driver = { .name = "rtc-rs5c348", - .bus = &spi_bus_type, .owner = THIS_MODULE, }, .probe = rs5c348_probe, diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 175067a17c4..aef40bd2957 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -673,21 +673,7 @@ static struct platform_driver s3c_rtc_driver = { }, }; -static char __initdata banner[] = "S3C24XX RTC, (c) 2004,2006 Simtec Electronics\n"; - -static int __init s3c_rtc_init(void) -{ - printk(banner); - return platform_driver_register(&s3c_rtc_driver); -} - -static void __exit s3c_rtc_exit(void) -{ - platform_driver_unregister(&s3c_rtc_driver); -} - -module_init(s3c_rtc_init); -module_exit(s3c_rtc_exit); +module_platform_driver(s3c_rtc_driver); MODULE_DESCRIPTION("Samsung S3C RTC Driver"); MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index fc1ffe97fca..4595d3e645a 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c @@ -435,18 +435,7 @@ static struct platform_driver sa1100_rtc_driver = { }, }; -static int __init sa1100_rtc_init(void) -{ - return platform_driver_register(&sa1100_rtc_driver); -} - -static void __exit sa1100_rtc_exit(void) -{ - platform_driver_unregister(&sa1100_rtc_driver); -} - -module_init(sa1100_rtc_init); -module_exit(sa1100_rtc_exit); +module_platform_driver(sa1100_rtc_driver); MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); MODULE_DESCRIPTION("SA11x0/PXA2xx Realtime Clock Driver (RTC)"); diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c index 893bac2bb21..19a28a671a8 100644 --- a/drivers/rtc/rtc-spear.c +++ b/drivers/rtc/rtc-spear.c @@ -516,17 +516,7 @@ static struct platform_driver spear_rtc_driver = { }, }; -static int __init rtc_init(void) -{ - return platform_driver_register(&spear_rtc_driver); -} -module_init(rtc_init); - -static void __exit rtc_exit(void) -{ - platform_driver_unregister(&spear_rtc_driver); -} -module_exit(rtc_exit); +module_platform_driver(spear_rtc_driver); MODULE_ALIAS("platform:rtc-spear"); MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>"); diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index ed3e9b59903..7621116bd20 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c @@ -370,18 +370,7 @@ static struct platform_driver stk17ta8_rtc_driver = { }, }; -static __init int stk17ta8_init(void) -{ - return platform_driver_register(&stk17ta8_rtc_driver); -} - -static __exit void stk17ta8_exit(void) -{ - platform_driver_unregister(&stk17ta8_rtc_driver); -} - -module_init(stk17ta8_init); -module_exit(stk17ta8_exit); +module_platform_driver(stk17ta8_rtc_driver); MODULE_AUTHOR("Thomas Hommel <thomas.hommel@ge.com>"); MODULE_DESCRIPTION("Simtek STK17TA8 RTC driver"); diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index 7315068daa5..10287865e33 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c @@ -276,18 +276,7 @@ static struct platform_driver stmp3xxx_rtcdrv = { }, }; -static int __init stmp3xxx_rtc_init(void) -{ - return platform_driver_register(&stmp3xxx_rtcdrv); -} - -static void __exit stmp3xxx_rtc_exit(void) -{ - platform_driver_unregister(&stmp3xxx_rtcdrv); -} - -module_init(stmp3xxx_rtc_init); -module_exit(stmp3xxx_rtc_exit); +module_platform_driver(stmp3xxx_rtcdrv); MODULE_DESCRIPTION("STMP3xxx RTC Driver"); MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com> and " diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index 20687d55e7a..d43b4f6eb4e 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c @@ -550,6 +550,11 @@ static int twl_rtc_resume(struct platform_device *pdev) #define twl_rtc_resume NULL #endif +static const struct of_device_id twl_rtc_of_match[] = { + {.compatible = "ti,twl4030-rtc", }, + { }, +}; +MODULE_DEVICE_TABLE(of, twl_rtc_of_match); MODULE_ALIAS("platform:twl_rtc"); static struct platform_driver twl4030rtc_driver = { @@ -559,8 +564,9 @@ static struct platform_driver twl4030rtc_driver = { .suspend = twl_rtc_suspend, .resume = twl_rtc_resume, .driver = { - .owner = THIS_MODULE, - .name = "twl_rtc", + .owner = THIS_MODULE, + .name = "twl_rtc", + .of_match_table = twl_rtc_of_match, }, }; diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c index f71c3ce1803..bca5d677bc8 100644 --- a/drivers/rtc/rtc-v3020.c +++ b/drivers/rtc/rtc-v3020.c @@ -393,18 +393,7 @@ static struct platform_driver rtc_device_driver = { }, }; -static __init int v3020_init(void) -{ - return platform_driver_register(&rtc_device_driver); -} - -static __exit void v3020_exit(void) -{ - platform_driver_unregister(&rtc_device_driver); -} - -module_init(v3020_init); -module_exit(v3020_exit); +module_platform_driver(rtc_device_driver); MODULE_DESCRIPTION("V3020 RTC"); MODULE_AUTHOR("Raphael Assenat"); diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index c5698cda366..fcbfdda2993 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c @@ -405,15 +405,4 @@ static struct platform_driver rtc_platform_driver = { }, }; -static int __init vr41xx_rtc_init(void) -{ - return platform_driver_register(&rtc_platform_driver); -} - -static void __exit vr41xx_rtc_exit(void) -{ - platform_driver_unregister(&rtc_platform_driver); -} - -module_init(vr41xx_rtc_init); -module_exit(vr41xx_rtc_exit); +module_platform_driver(rtc_platform_driver); diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c index f93f412423c..9e94fb147c2 100644 --- a/drivers/rtc/rtc-vt8500.c +++ b/drivers/rtc/rtc-vt8500.c @@ -311,17 +311,7 @@ static struct platform_driver vt8500_rtc_driver = { }, }; -static int __init vt8500_rtc_init(void) -{ - return platform_driver_register(&vt8500_rtc_driver); -} -module_init(vt8500_rtc_init); - -static void __exit vt8500_rtc_exit(void) -{ - platform_driver_unregister(&vt8500_rtc_driver); -} -module_exit(vt8500_rtc_exit); +module_platform_driver(vt8500_rtc_driver); MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>"); MODULE_DESCRIPTION("VIA VT8500 SoC Realtime Clock Driver (RTC)"); diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c index bdc909bd56d..3b6e6a67e76 100644 --- a/drivers/rtc/rtc-wm831x.c +++ b/drivers/rtc/rtc-wm831x.c @@ -324,15 +324,6 @@ static irqreturn_t wm831x_alm_irq(int irq, void *data) return IRQ_HANDLED; } -static irqreturn_t wm831x_per_irq(int irq, void *data) -{ - struct wm831x_rtc *wm831x_rtc = data; - - rtc_update_irq(wm831x_rtc->rtc, 1, RTC_IRQF | RTC_UF); - - return IRQ_HANDLED; -} - static const struct rtc_class_ops wm831x_rtc_ops = { .read_time = wm831x_rtc_readtime, .set_mmss = wm831x_rtc_set_mmss, @@ -405,11 +396,10 @@ static int wm831x_rtc_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_rtc *wm831x_rtc; - int per_irq = platform_get_irq_byname(pdev, "PER"); int alm_irq = platform_get_irq_byname(pdev, "ALM"); int ret = 0; - wm831x_rtc = kzalloc(sizeof(*wm831x_rtc), GFP_KERNEL); + wm831x_rtc = devm_kzalloc(&pdev->dev, sizeof(*wm831x_rtc), GFP_KERNEL); if (wm831x_rtc == NULL) return -ENOMEM; @@ -433,14 +423,6 @@ static int wm831x_rtc_probe(struct platform_device *pdev) goto err; } - ret = request_threaded_irq(per_irq, NULL, wm831x_per_irq, - IRQF_TRIGGER_RISING, "RTC period", - wm831x_rtc); - if (ret != 0) { - dev_err(&pdev->dev, "Failed to request periodic IRQ %d: %d\n", - per_irq, ret); - } - ret = request_threaded_irq(alm_irq, NULL, wm831x_alm_irq, IRQF_TRIGGER_RISING, "RTC alarm", wm831x_rtc); @@ -452,20 +434,16 @@ static int wm831x_rtc_probe(struct platform_device *pdev) return 0; err: - kfree(wm831x_rtc); return ret; } static int __devexit wm831x_rtc_remove(struct platform_device *pdev) { struct wm831x_rtc *wm831x_rtc = platform_get_drvdata(pdev); - int per_irq = platform_get_irq_byname(pdev, "PER"); int alm_irq = platform_get_irq_byname(pdev, "ALM"); free_irq(alm_irq, wm831x_rtc); - free_irq(per_irq, wm831x_rtc); rtc_device_unregister(wm831x_rtc->rtc); - kfree(wm831x_rtc); return 0; } @@ -490,17 +468,7 @@ static struct platform_driver wm831x_rtc_driver = { }, }; -static int __init wm831x_rtc_init(void) -{ - return platform_driver_register(&wm831x_rtc_driver); -} -module_init(wm831x_rtc_init); - -static void __exit wm831x_rtc_exit(void) -{ - platform_driver_unregister(&wm831x_rtc_driver); -} -module_exit(wm831x_rtc_exit); +module_platform_driver(wm831x_rtc_driver); MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); MODULE_DESCRIPTION("RTC driver for the WM831x series PMICs"); diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c index 66421426e40..c2e52d15abb 100644 --- a/drivers/rtc/rtc-wm8350.c +++ b/drivers/rtc/rtc-wm8350.c @@ -486,17 +486,7 @@ static struct platform_driver wm8350_rtc_driver = { }, }; -static int __init wm8350_rtc_init(void) -{ - return platform_driver_register(&wm8350_rtc_driver); -} -module_init(wm8350_rtc_init); - -static void __exit wm8350_rtc_exit(void) -{ - platform_driver_unregister(&wm8350_rtc_driver); -} -module_exit(wm8350_rtc_exit); +module_platform_driver(wm8350_rtc_driver); MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); MODULE_DESCRIPTION("RTC driver for the WM8350"); diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c index 1105fa1ed7f..a1376dc73d7 100644 --- a/drivers/video/backlight/88pm860x_bl.c +++ b/drivers/video/backlight/88pm860x_bl.c @@ -270,17 +270,7 @@ static struct platform_driver pm860x_backlight_driver = { .remove = pm860x_backlight_remove, }; -static int __init pm860x_backlight_init(void) -{ - return platform_driver_register(&pm860x_backlight_driver); -} -module_init(pm860x_backlight_init); - -static void __exit pm860x_backlight_exit(void) -{ - platform_driver_unregister(&pm860x_backlight_driver); -} -module_exit(pm860x_backlight_exit); +module_platform_driver(pm860x_backlight_driver); MODULE_DESCRIPTION("Backlight Driver for Marvell Semiconductor 88PM8606"); MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 278aeaa9250..681b36929fe 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -280,14 +280,6 @@ config BACKLIGHT_WM831X If you have a backlight driven by the ISINK and DCDC of a WM831x PMIC say y to enable the backlight driver for it. -config BACKLIGHT_ADX - tristate "Avionic Design Xanthos Backlight Driver" - depends on ARCH_PXA_ADX - default y - help - Say Y to enable the backlight driver on Avionic Design Xanthos-based - boards. - config BACKLIGHT_ADP5520 tristate "Backlight Driver for ADP5520/ADP5501 using WLED" depends on PMIC_ADP5520 diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index fdd1fc4b277..af5cf654ec7 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -32,7 +32,6 @@ obj-$(CONFIG_BACKLIGHT_APPLE) += apple_bl.o obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o -obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o obj-$(CONFIG_BACKLIGHT_ADP8860) += adp8860_bl.o obj-$(CONFIG_BACKLIGHT_ADP8870) += adp8870_bl.o diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c index dfb763e9147..2e630bf1164 100644 --- a/drivers/video/backlight/adp5520_bl.c +++ b/drivers/video/backlight/adp5520_bl.c @@ -384,17 +384,7 @@ static struct platform_driver adp5520_bl_driver = { .resume = adp5520_bl_resume, }; -static int __init adp5520_bl_init(void) -{ - return platform_driver_register(&adp5520_bl_driver); -} -module_init(adp5520_bl_init); - -static void __exit adp5520_bl_exit(void) -{ - platform_driver_unregister(&adp5520_bl_driver); -} -module_exit(adp5520_bl_exit); +module_platform_driver(adp5520_bl_driver); MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); MODULE_DESCRIPTION("ADP5520(01) Backlight Driver"); diff --git a/drivers/video/backlight/adx_bl.c b/drivers/video/backlight/adx_bl.c deleted file mode 100644 index c861c41af44..00000000000 --- a/drivers/video/backlight/adx_bl.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * linux/drivers/video/backlight/adx.c - * - * Copyright (C) 2009 Avionic Design GmbH - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Written by Thierry Reding <thierry.reding@avionic-design.de> - */ - -#include <linux/backlight.h> -#include <linux/fb.h> -#include <linux/gfp.h> -#include <linux/io.h> -#include <linux/module.h> -#include <linux/platform_device.h> - -/* register definitions */ -#define ADX_BACKLIGHT_CONTROL 0x00 -#define ADX_BACKLIGHT_CONTROL_ENABLE (1 << 0) -#define ADX_BACKLIGHT_BRIGHTNESS 0x08 -#define ADX_BACKLIGHT_STATUS 0x10 -#define ADX_BACKLIGHT_ERROR 0x18 - -struct adxbl { - void __iomem *base; -}; - -static int adx_backlight_update_status(struct backlight_device *bldev) -{ - struct adxbl *bl = bl_get_data(bldev); - u32 value; - - value = bldev->props.brightness; - writel(value, bl->base + ADX_BACKLIGHT_BRIGHTNESS); - - value = readl(bl->base + ADX_BACKLIGHT_CONTROL); - - if (bldev->props.state & BL_CORE_FBBLANK) - value &= ~ADX_BACKLIGHT_CONTROL_ENABLE; - else - value |= ADX_BACKLIGHT_CONTROL_ENABLE; - - writel(value, bl->base + ADX_BACKLIGHT_CONTROL); - - return 0; -} - -static int adx_backlight_get_brightness(struct backlight_device *bldev) -{ - struct adxbl *bl = bl_get_data(bldev); - u32 brightness; - - brightness = readl(bl->base + ADX_BACKLIGHT_BRIGHTNESS); - return brightness & 0xff; -} - -static int adx_backlight_check_fb(struct backlight_device *bldev, struct fb_info *fb) -{ - return 1; -} - -static const struct backlight_ops adx_backlight_ops = { - .options = 0, - .update_status = adx_backlight_update_status, - .get_brightness = adx_backlight_get_brightness, - .check_fb = adx_backlight_check_fb, -}; - -static int __devinit adx_backlight_probe(struct platform_device *pdev) -{ - struct backlight_properties props; - struct backlight_device *bldev; - struct resource *res; - struct adxbl *bl; - int ret = 0; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - ret = -ENXIO; - goto out; - } - - res = devm_request_mem_region(&pdev->dev, res->start, - resource_size(res), res->name); - if (!res) { - ret = -ENXIO; - goto out; - } - - bl = devm_kzalloc(&pdev->dev, sizeof(*bl), GFP_KERNEL); - if (!bl) { - ret = -ENOMEM; - goto out; - } - - bl->base = devm_ioremap_nocache(&pdev->dev, res->start, - resource_size(res)); - if (!bl->base) { - ret = -ENXIO; - goto out; - } - - memset(&props, 0, sizeof(struct backlight_properties)); - props.type = BACKLIGHT_RAW; - props.max_brightness = 0xff; - bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, - bl, &adx_backlight_ops, &props); - if (IS_ERR(bldev)) { - ret = PTR_ERR(bldev); - goto out; - } - - bldev->props.brightness = 0xff; - bldev->props.power = FB_BLANK_UNBLANK; - - platform_set_drvdata(pdev, bldev); - -out: - return ret; -} - -static int __devexit adx_backlight_remove(struct platform_device *pdev) -{ - struct backlight_device *bldev; - int ret = 0; - - bldev = platform_get_drvdata(pdev); - bldev->props.power = FB_BLANK_UNBLANK; - bldev->props.brightness = 0xff; - backlight_update_status(bldev); - backlight_device_unregister(bldev); - platform_set_drvdata(pdev, NULL); - - return ret; -} - -#ifdef CONFIG_PM -static int adx_backlight_suspend(struct platform_device *pdev, - pm_message_t state) -{ - return 0; -} - -static int adx_backlight_resume(struct platform_device *pdev) -{ - return 0; -} -#else -#define adx_backlight_suspend NULL -#define adx_backlight_resume NULL -#endif - -static struct platform_driver adx_backlight_driver = { - .probe = adx_backlight_probe, - .remove = __devexit_p(adx_backlight_remove), - .suspend = adx_backlight_suspend, - .resume = adx_backlight_resume, - .driver = { - .name = "adx-backlight", - .owner = THIS_MODULE, - }, -}; - -static int __init adx_backlight_init(void) -{ - return platform_driver_register(&adx_backlight_driver); -} - -static void __exit adx_backlight_exit(void) -{ - platform_driver_unregister(&adx_backlight_driver); -} - -module_init(adx_backlight_init); -module_exit(adx_backlight_exit); - -MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>"); -MODULE_DESCRIPTION("Avionic Design Xanthos Backlight Driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 7363c1b169e..bf5b1ece716 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -102,7 +102,7 @@ static void backlight_generate_event(struct backlight_device *bd, } static ssize_t backlight_show_power(struct device *dev, - struct device_attribute *attr,char *buf) + struct device_attribute *attr, char *buf) { struct backlight_device *bd = to_backlight_device(dev); @@ -116,7 +116,7 @@ static ssize_t backlight_store_power(struct device *dev, struct backlight_device *bd = to_backlight_device(dev); unsigned long power; - rc = strict_strtoul(buf, 0, &power); + rc = kstrtoul(buf, 0, &power); if (rc) return rc; @@ -150,7 +150,7 @@ static ssize_t backlight_store_brightness(struct device *dev, struct backlight_device *bd = to_backlight_device(dev); unsigned long brightness; - rc = strict_strtoul(buf, 0, &brightness); + rc = kstrtoul(buf, 0, &brightness); if (rc) return rc; diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c index d68f14bbb68..abb4a06268f 100644 --- a/drivers/video/backlight/da903x_bl.c +++ b/drivers/video/backlight/da903x_bl.c @@ -199,17 +199,7 @@ static struct platform_driver da903x_backlight_driver = { .remove = da903x_backlight_remove, }; -static int __init da903x_backlight_init(void) -{ - return platform_driver_register(&da903x_backlight_driver); -} -module_init(da903x_backlight_init); - -static void __exit da903x_backlight_exit(void) -{ - platform_driver_unregister(&da903x_backlight_driver); -} -module_exit(da903x_backlight_exit); +module_platform_driver(da903x_backlight_driver); MODULE_DESCRIPTION("Backlight Driver for Dialog Semiconductor DA9030/DA9034"); MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>" diff --git a/drivers/video/backlight/ep93xx_bl.c b/drivers/video/backlight/ep93xx_bl.c index c74a6f4baa1..b62b8b9063b 100644 --- a/drivers/video/backlight/ep93xx_bl.c +++ b/drivers/video/backlight/ep93xx_bl.c @@ -13,7 +13,6 @@ #include <linux/module.h> #include <linux/platform_device.h> -#include <linux/module.h> #include <linux/io.h> #include <linux/fb.h> #include <linux/backlight.h> @@ -144,17 +143,7 @@ static struct platform_driver ep93xxbl_driver = { .resume = ep93xxbl_resume, }; -static int __init ep93xxbl_init(void) -{ - return platform_driver_register(&ep93xxbl_driver); -} -module_init(ep93xxbl_init); - -static void __exit ep93xxbl_exit(void) -{ - platform_driver_unregister(&ep93xxbl_driver); -} -module_exit(ep93xxbl_exit); +module_platform_driver(ep93xxbl_driver); MODULE_DESCRIPTION("EP93xx Backlight Driver"); MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>"); diff --git a/drivers/video/backlight/generic_bl.c b/drivers/video/backlight/generic_bl.c index adb191466d6..9ce6170c186 100644 --- a/drivers/video/backlight/generic_bl.c +++ b/drivers/video/backlight/generic_bl.c @@ -132,18 +132,7 @@ static struct platform_driver genericbl_driver = { }, }; -static int __init genericbl_init(void) -{ - return platform_driver_register(&genericbl_driver); -} - -static void __exit genericbl_exit(void) -{ - platform_driver_unregister(&genericbl_driver); -} - -module_init(genericbl_init); -module_exit(genericbl_exit); +module_platform_driver(genericbl_driver); MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); MODULE_DESCRIPTION("Generic Backlight Driver"); diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c index de65d80159b..2f8af5d786a 100644 --- a/drivers/video/backlight/jornada720_bl.c +++ b/drivers/video/backlight/jornada720_bl.c @@ -147,19 +147,8 @@ static struct platform_driver jornada_bl_driver = { }, }; -static int __init jornada_bl_init(void) -{ - return platform_driver_register(&jornada_bl_driver); -} - -static void __exit jornada_bl_exit(void) -{ - platform_driver_unregister(&jornada_bl_driver); -} +module_platform_driver(jornada_bl_driver); MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson>"); MODULE_DESCRIPTION("HP Jornada 710/720/728 Backlight driver"); MODULE_LICENSE("GPL"); - -module_init(jornada_bl_init); -module_exit(jornada_bl_exit); diff --git a/drivers/video/backlight/jornada720_lcd.c b/drivers/video/backlight/jornada720_lcd.c index d2ff658b414..22d231a17e3 100644 --- a/drivers/video/backlight/jornada720_lcd.c +++ b/drivers/video/backlight/jornada720_lcd.c @@ -135,19 +135,8 @@ static struct platform_driver jornada_lcd_driver = { }, }; -static int __init jornada_lcd_init(void) -{ - return platform_driver_register(&jornada_lcd_driver); -} - -static void __exit jornada_lcd_exit(void) -{ - platform_driver_unregister(&jornada_lcd_driver); -} +module_platform_driver(jornada_lcd_driver); MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>"); MODULE_DESCRIPTION("HP Jornada 710/720/728 LCD driver"); MODULE_LICENSE("GPL"); - -module_init(jornada_lcd_init); -module_exit(jornada_lcd_exit); diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 71a11cadffc..79c1b0d609a 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -97,19 +97,16 @@ static ssize_t lcd_store_power(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int rc = -ENXIO; - char *endp; struct lcd_device *ld = to_lcd_device(dev); - int power = simple_strtoul(buf, &endp, 0); - size_t size = endp - buf; + unsigned long power; - if (isspace(*endp)) - size++; - if (size != count) - return -EINVAL; + rc = kstrtoul(buf, 0, &power); + if (rc) + return rc; mutex_lock(&ld->ops_lock); if (ld->ops && ld->ops->set_power) { - pr_debug("lcd: set power to %d\n", power); + pr_debug("lcd: set power to %lu\n", power); ld->ops->set_power(ld, power); rc = count; } @@ -136,19 +133,16 @@ static ssize_t lcd_store_contrast(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int rc = -ENXIO; - char *endp; struct lcd_device *ld = to_lcd_device(dev); - int contrast = simple_strtoul(buf, &endp, 0); - size_t size = endp - buf; + unsigned long contrast; - if (isspace(*endp)) - size++; - if (size != count) - return -EINVAL; + rc = kstrtoul(buf, 0, &contrast); + if (rc) + return rc; mutex_lock(&ld->ops_lock); if (ld->ops && ld->ops->set_contrast) { - pr_debug("lcd: set contrast to %d\n", contrast); + pr_debug("lcd: set contrast to %lu\n", contrast); ld->ops->set_contrast(ld, contrast); rc = count; } diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c index da9a5ce0ccb..78dafc0c8fc 100644 --- a/drivers/video/backlight/ld9040.c +++ b/drivers/video/backlight/ld9040.c @@ -31,6 +31,7 @@ #include <linux/lcd.h> #include <linux/backlight.h> #include <linux/module.h> +#include <linux/regulator/consumer.h> #include "ld9040_gamma.h" @@ -53,8 +54,51 @@ struct ld9040 { struct lcd_device *ld; struct backlight_device *bd; struct lcd_platform_data *lcd_pd; + + struct mutex lock; + bool enabled; +}; + +static struct regulator_bulk_data supplies[] = { + { .supply = "vdd3", }, + { .supply = "vci", }, }; +static void ld9040_regulator_enable(struct ld9040 *lcd) +{ + int ret = 0; + struct lcd_platform_data *pd = NULL; + + pd = lcd->lcd_pd; + mutex_lock(&lcd->lock); + if (!lcd->enabled) { + ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies); + if (ret) + goto out; + + lcd->enabled = true; + } + mdelay(pd->power_on_delay); +out: + mutex_unlock(&lcd->lock); +} + +static void ld9040_regulator_disable(struct ld9040 *lcd) +{ + int ret = 0; + + mutex_lock(&lcd->lock); + if (lcd->enabled) { + ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies); + if (ret) + goto out; + + lcd->enabled = false; + } +out: + mutex_unlock(&lcd->lock); +} + static const unsigned short seq_swreset[] = { 0x01, COMMAND_ONLY, ENDDEF, 0x00 @@ -532,13 +576,8 @@ static int ld9040_power_on(struct ld9040 *lcd) return -EFAULT; } - if (!pd->power_on) { - dev_err(lcd->dev, "power_on is NULL.\n"); - return -EFAULT; - } else { - pd->power_on(lcd->ld, 1); - mdelay(pd->power_on_delay); - } + /* lcd power on */ + ld9040_regulator_enable(lcd); if (!pd->reset) { dev_err(lcd->dev, "reset is NULL.\n"); @@ -582,11 +621,8 @@ static int ld9040_power_off(struct ld9040 *lcd) mdelay(pd->power_off_delay); - if (!pd->power_on) { - dev_err(lcd->dev, "power_on is NULL.\n"); - return -EFAULT; - } else - pd->power_on(lcd->ld, 0); + /* lcd power off */ + ld9040_regulator_disable(lcd); return 0; } @@ -693,6 +729,14 @@ static int ld9040_probe(struct spi_device *spi) goto out_free_lcd; } + mutex_init(&lcd->lock); + + ret = regulator_bulk_get(lcd->dev, ARRAY_SIZE(supplies), supplies); + if (ret) { + dev_err(lcd->dev, "Failed to get regulators: %d\n", ret); + goto out_free_lcd; + } + ld = lcd_device_register("ld9040", &spi->dev, lcd, &ld9040_lcd_ops); if (IS_ERR(ld)) { ret = PTR_ERR(ld); @@ -739,6 +783,8 @@ static int ld9040_probe(struct spi_device *spi) out_unregister_lcd: lcd_device_unregister(lcd->ld); out_free_lcd: + regulator_bulk_free(ARRAY_SIZE(supplies), supplies); + kfree(lcd); return ret; } @@ -750,6 +796,7 @@ static int __devexit ld9040_remove(struct spi_device *spi) ld9040_power(lcd, FB_BLANK_POWERDOWN); backlight_device_unregister(lcd->bd); lcd_device_unregister(lcd->ld); + regulator_bulk_free(ARRAY_SIZE(supplies), supplies); kfree(lcd); return 0; diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c index 7bbc802560e..c915e3b5388 100644 --- a/drivers/video/backlight/max8925_bl.c +++ b/drivers/video/backlight/max8925_bl.c @@ -188,17 +188,7 @@ static struct platform_driver max8925_backlight_driver = { .remove = __devexit_p(max8925_backlight_remove), }; -static int __init max8925_backlight_init(void) -{ - return platform_driver_register(&max8925_backlight_driver); -} -module_init(max8925_backlight_init); - -static void __exit max8925_backlight_exit(void) -{ - platform_driver_unregister(&max8925_backlight_driver); -}; -module_exit(max8925_backlight_exit); +module_platform_driver(max8925_backlight_driver); MODULE_DESCRIPTION("Backlight Driver for Maxim MAX8925"); MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c index 08d26a72394..d8cde277ec8 100644 --- a/drivers/video/backlight/omap1_bl.c +++ b/drivers/video/backlight/omap1_bl.c @@ -195,18 +195,7 @@ static struct platform_driver omapbl_driver = { }, }; -static int __init omapbl_init(void) -{ - return platform_driver_register(&omapbl_driver); -} - -static void __exit omapbl_exit(void) -{ - platform_driver_unregister(&omapbl_driver); -} - -module_init(omapbl_init); -module_exit(omapbl_exit); +module_platform_driver(omapbl_driver); MODULE_AUTHOR("Andrzej Zaborowski <balrog@zabor.org>"); MODULE_DESCRIPTION("OMAP LCD Backlight driver"); diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c index ef5628d6056..13e88b71dae 100644 --- a/drivers/video/backlight/pcf50633-backlight.c +++ b/drivers/video/backlight/pcf50633-backlight.c @@ -173,17 +173,7 @@ static struct platform_driver pcf50633_bl_driver = { }, }; -static int __init pcf50633_bl_init(void) -{ - return platform_driver_register(&pcf50633_bl_driver); -} -module_init(pcf50633_bl_init); - -static void __exit pcf50633_bl_exit(void) -{ - platform_driver_unregister(&pcf50633_bl_driver); -} -module_exit(pcf50633_bl_exit); +module_platform_driver(pcf50633_bl_driver); MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); MODULE_DESCRIPTION("PCF50633 backlight driver"); diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c index 302330acf62..f0bf491ed08 100644 --- a/drivers/video/backlight/platform_lcd.c +++ b/drivers/video/backlight/platform_lcd.c @@ -85,7 +85,8 @@ static int __devinit platform_lcd_probe(struct platform_device *pdev) return -EINVAL; } - plcd = kzalloc(sizeof(struct platform_lcd), GFP_KERNEL); + plcd = devm_kzalloc(&pdev->dev, sizeof(struct platform_lcd), + GFP_KERNEL); if (!plcd) { dev_err(dev, "no memory for state\n"); return -ENOMEM; @@ -98,7 +99,7 @@ static int __devinit platform_lcd_probe(struct platform_device *pdev) if (IS_ERR(plcd->lcd)) { dev_err(dev, "cannot register lcd device\n"); err = PTR_ERR(plcd->lcd); - goto err_mem; + goto err; } platform_set_drvdata(pdev, plcd); @@ -106,8 +107,7 @@ static int __devinit platform_lcd_probe(struct platform_device *pdev) return 0; - err_mem: - kfree(plcd); + err: return err; } @@ -116,7 +116,6 @@ static int __devexit platform_lcd_remove(struct platform_device *pdev) struct platform_lcd *plcd = platform_get_drvdata(pdev); lcd_device_unregister(plcd->lcd); - kfree(plcd); return 0; } @@ -157,18 +156,7 @@ static struct platform_driver platform_lcd_driver = { .resume = platform_lcd_resume, }; -static int __init platform_lcd_init(void) -{ - return platform_driver_register(&platform_lcd_driver); -} - -static void __exit platform_lcd_cleanup(void) -{ - platform_driver_unregister(&platform_lcd_driver); -} - -module_init(platform_lcd_init); -module_exit(platform_lcd_cleanup); +module_platform_driver(platform_lcd_driver); MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c index 8b5b2a4124c..7496d04e1d3 100644 --- a/drivers/video/backlight/pwm_bl.c +++ b/drivers/video/backlight/pwm_bl.c @@ -169,10 +169,9 @@ static int pwm_backlight_remove(struct platform_device *pdev) } #ifdef CONFIG_PM -static int pwm_backlight_suspend(struct platform_device *pdev, - pm_message_t state) +static int pwm_backlight_suspend(struct device *dev) { - struct backlight_device *bl = platform_get_drvdata(pdev); + struct backlight_device *bl = dev_get_drvdata(dev); struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); if (pb->notify) @@ -184,40 +183,32 @@ static int pwm_backlight_suspend(struct platform_device *pdev, return 0; } -static int pwm_backlight_resume(struct platform_device *pdev) +static int pwm_backlight_resume(struct device *dev) { - struct backlight_device *bl = platform_get_drvdata(pdev); + struct backlight_device *bl = dev_get_drvdata(dev); backlight_update_status(bl); return 0; } -#else -#define pwm_backlight_suspend NULL -#define pwm_backlight_resume NULL + +static SIMPLE_DEV_PM_OPS(pwm_backlight_pm_ops, pwm_backlight_suspend, + pwm_backlight_resume); + #endif static struct platform_driver pwm_backlight_driver = { .driver = { .name = "pwm-backlight", .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &pwm_backlight_pm_ops, +#endif }, .probe = pwm_backlight_probe, .remove = pwm_backlight_remove, - .suspend = pwm_backlight_suspend, - .resume = pwm_backlight_resume, }; -static int __init pwm_backlight_init(void) -{ - return platform_driver_register(&pwm_backlight_driver); -} -module_init(pwm_backlight_init); - -static void __exit pwm_backlight_exit(void) -{ - platform_driver_unregister(&pwm_backlight_driver); -} -module_exit(pwm_backlight_exit); +module_platform_driver(pwm_backlight_driver); MODULE_DESCRIPTION("PWM based Backlight Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/backlight/wm831x_bl.c b/drivers/video/backlight/wm831x_bl.c index fbe9e9316f3..4e915f5eca9 100644 --- a/drivers/video/backlight/wm831x_bl.c +++ b/drivers/video/backlight/wm831x_bl.c @@ -236,17 +236,7 @@ static struct platform_driver wm831x_backlight_driver = { .remove = wm831x_backlight_remove, }; -static int __init wm831x_backlight_init(void) -{ - return platform_driver_register(&wm831x_backlight_driver); -} -module_init(wm831x_backlight_init); - -static void __exit wm831x_backlight_exit(void) -{ - platform_driver_unregister(&wm831x_backlight_driver); -} -module_exit(wm831x_backlight_exit); +module_platform_driver(wm831x_backlight_driver); MODULE_DESCRIPTION("Backlight Driver for WM831x PMICs"); MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com"); |