10d75565fSKristian Kielhofner /* 20d75565fSKristian Kielhofner * LEDs driver for PCEngines WRAP 30d75565fSKristian Kielhofner * 40d75565fSKristian Kielhofner * Copyright (C) 2006 Kristian Kielhofner <kris@krisk.org> 50d75565fSKristian Kielhofner * 60d75565fSKristian Kielhofner * Based on leds-net48xx.c 70d75565fSKristian Kielhofner * 80d75565fSKristian Kielhofner * This program is free software; you can redistribute it and/or modify 90d75565fSKristian Kielhofner * it under the terms of the GNU General Public License version 2 as 100d75565fSKristian Kielhofner * published by the Free Software Foundation. 110d75565fSKristian Kielhofner */ 120d75565fSKristian Kielhofner 130d75565fSKristian Kielhofner #include <linux/kernel.h> 140d75565fSKristian Kielhofner #include <linux/init.h> 150d75565fSKristian Kielhofner #include <linux/platform_device.h> 160d75565fSKristian Kielhofner #include <linux/leds.h> 170d75565fSKristian Kielhofner #include <linux/err.h> 180d75565fSKristian Kielhofner #include <asm/io.h> 190d75565fSKristian Kielhofner #include <linux/scx200_gpio.h> 200d75565fSKristian Kielhofner 210d75565fSKristian Kielhofner #define DRVNAME "wrap-led" 22f5506a2fSMichael Loeffler #define WRAP_POWER_LED_GPIO 2 230d75565fSKristian Kielhofner #define WRAP_ERROR_LED_GPIO 3 240d75565fSKristian Kielhofner #define WRAP_EXTRA_LED_GPIO 18 250d75565fSKristian Kielhofner 260d75565fSKristian Kielhofner static struct platform_device *pdev; 270d75565fSKristian Kielhofner 28f5506a2fSMichael Loeffler static void wrap_power_led_set(struct led_classdev *led_cdev, 29f5506a2fSMichael Loeffler enum led_brightness value) 30f5506a2fSMichael Loeffler { 31f5506a2fSMichael Loeffler if (value) 32f5506a2fSMichael Loeffler scx200_gpio_set_low(WRAP_POWER_LED_GPIO); 33f5506a2fSMichael Loeffler else 34f5506a2fSMichael Loeffler scx200_gpio_set_high(WRAP_POWER_LED_GPIO); 35f5506a2fSMichael Loeffler } 36f5506a2fSMichael Loeffler 370d75565fSKristian Kielhofner static void wrap_error_led_set(struct led_classdev *led_cdev, 380d75565fSKristian Kielhofner enum led_brightness value) 390d75565fSKristian Kielhofner { 400d75565fSKristian Kielhofner if (value) 410d75565fSKristian Kielhofner scx200_gpio_set_low(WRAP_ERROR_LED_GPIO); 420d75565fSKristian Kielhofner else 430d75565fSKristian Kielhofner scx200_gpio_set_high(WRAP_ERROR_LED_GPIO); 440d75565fSKristian Kielhofner } 450d75565fSKristian Kielhofner 460d75565fSKristian Kielhofner static void wrap_extra_led_set(struct led_classdev *led_cdev, 470d75565fSKristian Kielhofner enum led_brightness value) 480d75565fSKristian Kielhofner { 490d75565fSKristian Kielhofner if (value) 500d75565fSKristian Kielhofner scx200_gpio_set_low(WRAP_EXTRA_LED_GPIO); 510d75565fSKristian Kielhofner else 520d75565fSKristian Kielhofner scx200_gpio_set_high(WRAP_EXTRA_LED_GPIO); 530d75565fSKristian Kielhofner } 540d75565fSKristian Kielhofner 55f5506a2fSMichael Loeffler static struct led_classdev wrap_power_led = { 56f5506a2fSMichael Loeffler .name = "wrap::power", 57f5506a2fSMichael Loeffler .brightness_set = wrap_power_led_set, 586af4f55cSSven Wegener .default_trigger = "default-on", 59f5506a2fSMichael Loeffler }; 60f5506a2fSMichael Loeffler 610d75565fSKristian Kielhofner static struct led_classdev wrap_error_led = { 626c152beeSRichard Purdie .name = "wrap::error", 630d75565fSKristian Kielhofner .brightness_set = wrap_error_led_set, 640d75565fSKristian Kielhofner }; 650d75565fSKristian Kielhofner 660d75565fSKristian Kielhofner static struct led_classdev wrap_extra_led = { 676c152beeSRichard Purdie .name = "wrap::extra", 680d75565fSKristian Kielhofner .brightness_set = wrap_extra_led_set, 690d75565fSKristian Kielhofner }; 700d75565fSKristian Kielhofner 710d75565fSKristian Kielhofner #ifdef CONFIG_PM 720d75565fSKristian Kielhofner static int wrap_led_suspend(struct platform_device *dev, 730d75565fSKristian Kielhofner pm_message_t state) 740d75565fSKristian Kielhofner { 75f5506a2fSMichael Loeffler led_classdev_suspend(&wrap_power_led); 760d75565fSKristian Kielhofner led_classdev_suspend(&wrap_error_led); 770d75565fSKristian Kielhofner led_classdev_suspend(&wrap_extra_led); 780d75565fSKristian Kielhofner return 0; 790d75565fSKristian Kielhofner } 800d75565fSKristian Kielhofner 810d75565fSKristian Kielhofner static int wrap_led_resume(struct platform_device *dev) 820d75565fSKristian Kielhofner { 83f5506a2fSMichael Loeffler led_classdev_resume(&wrap_power_led); 840d75565fSKristian Kielhofner led_classdev_resume(&wrap_error_led); 850d75565fSKristian Kielhofner led_classdev_resume(&wrap_extra_led); 860d75565fSKristian Kielhofner return 0; 870d75565fSKristian Kielhofner } 880d75565fSKristian Kielhofner #else 890d75565fSKristian Kielhofner #define wrap_led_suspend NULL 900d75565fSKristian Kielhofner #define wrap_led_resume NULL 910d75565fSKristian Kielhofner #endif 920d75565fSKristian Kielhofner 930d75565fSKristian Kielhofner static int wrap_led_probe(struct platform_device *pdev) 940d75565fSKristian Kielhofner { 950d75565fSKristian Kielhofner int ret; 960d75565fSKristian Kielhofner 97f5506a2fSMichael Loeffler ret = led_classdev_register(&pdev->dev, &wrap_power_led); 98f5506a2fSMichael Loeffler if (ret < 0) 99f5506a2fSMichael Loeffler return ret; 100f5506a2fSMichael Loeffler 1010d75565fSKristian Kielhofner ret = led_classdev_register(&pdev->dev, &wrap_error_led); 102f5506a2fSMichael Loeffler if (ret < 0) 103f5506a2fSMichael Loeffler goto err1; 104f5506a2fSMichael Loeffler 1050d75565fSKristian Kielhofner ret = led_classdev_register(&pdev->dev, &wrap_extra_led); 1060d75565fSKristian Kielhofner if (ret < 0) 107f5506a2fSMichael Loeffler goto err2; 108f5506a2fSMichael Loeffler 109f5506a2fSMichael Loeffler return ret; 110f5506a2fSMichael Loeffler 111f5506a2fSMichael Loeffler err2: 1120d75565fSKristian Kielhofner led_classdev_unregister(&wrap_error_led); 113f5506a2fSMichael Loeffler err1: 114f5506a2fSMichael Loeffler led_classdev_unregister(&wrap_power_led); 115f5506a2fSMichael Loeffler 1160d75565fSKristian Kielhofner return ret; 1170d75565fSKristian Kielhofner } 1180d75565fSKristian Kielhofner 1190d75565fSKristian Kielhofner static int wrap_led_remove(struct platform_device *pdev) 1200d75565fSKristian Kielhofner { 121f5506a2fSMichael Loeffler led_classdev_unregister(&wrap_power_led); 1220d75565fSKristian Kielhofner led_classdev_unregister(&wrap_error_led); 1230d75565fSKristian Kielhofner led_classdev_unregister(&wrap_extra_led); 1240d75565fSKristian Kielhofner return 0; 1250d75565fSKristian Kielhofner } 1260d75565fSKristian Kielhofner 1270d75565fSKristian Kielhofner static struct platform_driver wrap_led_driver = { 1280d75565fSKristian Kielhofner .probe = wrap_led_probe, 1290d75565fSKristian Kielhofner .remove = wrap_led_remove, 1300d75565fSKristian Kielhofner .suspend = wrap_led_suspend, 1310d75565fSKristian Kielhofner .resume = wrap_led_resume, 1320d75565fSKristian Kielhofner .driver = { 1330d75565fSKristian Kielhofner .name = DRVNAME, 1340d75565fSKristian Kielhofner .owner = THIS_MODULE, 1350d75565fSKristian Kielhofner }, 1360d75565fSKristian Kielhofner }; 1370d75565fSKristian Kielhofner 1380d75565fSKristian Kielhofner static int __init wrap_led_init(void) 1390d75565fSKristian Kielhofner { 1400d75565fSKristian Kielhofner int ret; 1410d75565fSKristian Kielhofner 1420d75565fSKristian Kielhofner if (!scx200_gpio_present()) { 1430d75565fSKristian Kielhofner ret = -ENODEV; 1440d75565fSKristian Kielhofner goto out; 1450d75565fSKristian Kielhofner } 1460d75565fSKristian Kielhofner 1470d75565fSKristian Kielhofner ret = platform_driver_register(&wrap_led_driver); 1480d75565fSKristian Kielhofner if (ret < 0) 1490d75565fSKristian Kielhofner goto out; 1500d75565fSKristian Kielhofner 1510d75565fSKristian Kielhofner pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); 1520d75565fSKristian Kielhofner if (IS_ERR(pdev)) { 1530d75565fSKristian Kielhofner ret = PTR_ERR(pdev); 1540d75565fSKristian Kielhofner platform_driver_unregister(&wrap_led_driver); 1550d75565fSKristian Kielhofner goto out; 1560d75565fSKristian Kielhofner } 1570d75565fSKristian Kielhofner 1580d75565fSKristian Kielhofner out: 1590d75565fSKristian Kielhofner return ret; 1600d75565fSKristian Kielhofner } 1610d75565fSKristian Kielhofner 1620d75565fSKristian Kielhofner static void __exit wrap_led_exit(void) 1630d75565fSKristian Kielhofner { 1640d75565fSKristian Kielhofner platform_device_unregister(pdev); 1650d75565fSKristian Kielhofner platform_driver_unregister(&wrap_led_driver); 1660d75565fSKristian Kielhofner } 1670d75565fSKristian Kielhofner 1680d75565fSKristian Kielhofner module_init(wrap_led_init); 1690d75565fSKristian Kielhofner module_exit(wrap_led_exit); 1700d75565fSKristian Kielhofner 1710d75565fSKristian Kielhofner MODULE_AUTHOR("Kristian Kielhofner <kris@krisk.org>"); 1720d75565fSKristian Kielhofner MODULE_DESCRIPTION("PCEngines WRAP LED driver"); 1730d75565fSKristian Kielhofner MODULE_LICENSE("GPL"); 1740d75565fSKristian Kielhofner 175