1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * LED Driver for SGI Octane machines 4 */ 5 6 #include <asm/io.h> 7 #include <linux/module.h> 8 #include <linux/kernel.h> 9 #include <linux/platform_device.h> 10 #include <linux/leds.h> 11 12 #define IP30_LED_SYSTEM 0 13 #define IP30_LED_FAULT 1 14 15 struct ip30_led { 16 struct led_classdev cdev; 17 u32 __iomem *reg; 18 }; 19 20 static void ip30led_set(struct led_classdev *led_cdev, 21 enum led_brightness value) 22 { 23 struct ip30_led *led = container_of(led_cdev, struct ip30_led, cdev); 24 25 writel(value, led->reg); 26 } 27 28 static int ip30led_create(struct platform_device *pdev, int num) 29 { 30 struct ip30_led *data; 31 32 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 33 if (!data) 34 return -ENOMEM; 35 36 data->reg = devm_platform_ioremap_resource(pdev, num); 37 if (IS_ERR(data->reg)) 38 return PTR_ERR(data->reg); 39 40 switch (num) { 41 case IP30_LED_SYSTEM: 42 data->cdev.name = "white:power"; 43 break; 44 case IP30_LED_FAULT: 45 data->cdev.name = "red:fault"; 46 break; 47 default: 48 return -EINVAL; 49 } 50 51 data->cdev.brightness = readl(data->reg); 52 data->cdev.max_brightness = 1; 53 data->cdev.brightness_set = ip30led_set; 54 55 return devm_led_classdev_register(&pdev->dev, &data->cdev); 56 } 57 58 static int ip30led_probe(struct platform_device *pdev) 59 { 60 int ret; 61 62 ret = ip30led_create(pdev, IP30_LED_SYSTEM); 63 if (ret < 0) 64 return ret; 65 66 return ip30led_create(pdev, IP30_LED_FAULT); 67 } 68 69 static struct platform_driver ip30led_driver = { 70 .probe = ip30led_probe, 71 .driver = { 72 .name = "ip30-leds", 73 }, 74 }; 75 76 module_platform_driver(ip30led_driver); 77 78 MODULE_AUTHOR("Thomas Bogendoerfer <tbogendoerfer@suse.de>"); 79 MODULE_DESCRIPTION("SGI Octane LED driver"); 80 MODULE_LICENSE("GPL"); 81 MODULE_ALIAS("platform:ip30-leds"); 82