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