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 15struct ip30_led { 16 struct led_classdev cdev; 17 u32 __iomem *reg; 18}; 19 20static 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 28static 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 58static 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 69static struct platform_driver ip30led_driver = { 70 .probe = ip30led_probe, 71 .driver = { 72 .name = "ip30-leds", 73 }, 74}; 75 76module_platform_driver(ip30led_driver); 77 78MODULE_AUTHOR("Thomas Bogendoerfer <tbogendoerfer@suse.de>"); 79MODULE_DESCRIPTION("SGI Octane LED driver"); 80MODULE_LICENSE("GPL"); 81MODULE_ALIAS("platform:ip30-leds"); 82