Commit | Line | Data |
---|---|---|
64d7e231 TB |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | |
3 | * LED Driver for SGI Octane machines | |
4 | */ | |
5 | ||
2aebb780 | 6 | #include <asm/io.h> |
64d7e231 TB |
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 resource *res; | |
31 | struct ip30_led *data; | |
32 | ||
33 | res = platform_get_resource(pdev, IORESOURCE_MEM, num); | |
34 | if (!res) | |
35 | return -EBUSY; | |
36 | ||
37 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | |
38 | if (!data) | |
39 | return -ENOMEM; | |
40 | ||
41 | data->reg = devm_ioremap_resource(&pdev->dev, res); | |
42 | if (IS_ERR(data->reg)) | |
43 | return PTR_ERR(data->reg); | |
44 | ||
45 | ||
46 | switch (num) { | |
47 | case IP30_LED_SYSTEM: | |
19aa9840 | 48 | data->cdev.name = "white:power"; |
64d7e231 TB |
49 | break; |
50 | case IP30_LED_FAULT: | |
51 | data->cdev.name = "red:fault"; | |
52 | break; | |
53 | default: | |
54 | return -EINVAL; | |
55 | } | |
56 | ||
57 | data->cdev.brightness = readl(data->reg); | |
58 | data->cdev.max_brightness = 1; | |
59 | data->cdev.brightness_set = ip30led_set; | |
60 | ||
61 | return devm_led_classdev_register(&pdev->dev, &data->cdev); | |
62 | } | |
63 | ||
64 | static int ip30led_probe(struct platform_device *pdev) | |
65 | { | |
66 | int ret; | |
67 | ||
68 | ret = ip30led_create(pdev, IP30_LED_SYSTEM); | |
69 | if (ret < 0) | |
70 | return ret; | |
71 | ||
72 | return ip30led_create(pdev, IP30_LED_FAULT); | |
73 | } | |
74 | ||
75 | static struct platform_driver ip30led_driver = { | |
76 | .probe = ip30led_probe, | |
77 | .driver = { | |
78 | .name = "ip30-leds", | |
79 | }, | |
80 | }; | |
81 | ||
82 | module_platform_driver(ip30led_driver); | |
83 | ||
84 | MODULE_AUTHOR("Thomas Bogendoerfer <tbogendoerfer@suse.de>"); | |
85 | MODULE_DESCRIPTION("SGI Octane LED driver"); | |
86 | MODULE_LICENSE("GPL"); | |
87 | MODULE_ALIAS("platform:ip30-leds"); |