Blame view
drivers/leds/leds-syscon.c
3.24 KB
1a59d1b8e treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
535f09cc1 leds: add a drive... |
2 3 4 5 6 |
/* * Generic Syscon LEDs Driver * * Copyright (c) 2014, Linaro Limited * Author: Linus Walleij <linus.walleij@linaro.org> |
535f09cc1 leds: add a drive... |
7 8 |
*/ #include <linux/io.h> |
f7d98a65d leds: syscon: Mak... |
9 |
#include <linux/init.h> |
535f09cc1 leds: add a drive... |
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
#include <linux/of_device.h> #include <linux/of_address.h> #include <linux/platform_device.h> #include <linux/stat.h> #include <linux/slab.h> #include <linux/mfd/syscon.h> #include <linux/regmap.h> #include <linux/leds.h> /** * struct syscon_led - state container for syscon based LEDs * @cdev: LED class device for this LED * @map: regmap to access the syscon device backing this LED * @offset: the offset into the syscon regmap for the LED register * @mask: the bit in the register corresponding to the LED * @state: current state of the LED */ struct syscon_led { struct led_classdev cdev; struct regmap *map; u32 offset; u32 mask; bool state; }; static void syscon_led_set(struct led_classdev *led_cdev, enum led_brightness value) { struct syscon_led *sled = container_of(led_cdev, struct syscon_led, cdev); u32 val; int ret; if (value == LED_OFF) { val = 0; sled->state = false; } else { val = sled->mask; sled->state = true; } ret = regmap_update_bits(sled->map, sled->offset, sled->mask, val); if (ret < 0) dev_err(sled->cdev.dev, "error updating LED status "); } |
a917d4b44 leds: syscon: ins... |
56 |
static int syscon_led_probe(struct platform_device *pdev) |
535f09cc1 leds: add a drive... |
57 |
{ |
006631969 leds: syscon: use... |
58 |
struct led_init_data init_data = {}; |
a917d4b44 leds: syscon: ins... |
59 |
struct device *dev = &pdev->dev; |
8853c95e9 leds: various: us... |
60 |
struct device_node *np = dev_of_node(dev); |
a917d4b44 leds: syscon: ins... |
61 62 63 64 |
struct device *parent; struct regmap *map; struct syscon_led *sled; const char *state; |
535f09cc1 leds: add a drive... |
65 |
int ret; |
a917d4b44 leds: syscon: ins... |
66 67 68 69 70 71 |
parent = dev->parent; if (!parent) { dev_err(dev, "no parent for syscon LED "); return -ENODEV; } |
8853c95e9 leds: various: us... |
72 |
map = syscon_node_to_regmap(dev_of_node(parent)); |
991a3f61f leds: syscon: Cor... |
73 |
if (IS_ERR(map)) { |
a917d4b44 leds: syscon: ins... |
74 75 |
dev_err(dev, "no regmap for syscon LED parent "); |
991a3f61f leds: syscon: Cor... |
76 |
return PTR_ERR(map); |
a917d4b44 leds: syscon: ins... |
77 78 79 80 81 82 83 84 85 86 87 88 |
} sled = devm_kzalloc(dev, sizeof(*sled), GFP_KERNEL); if (!sled) return -ENOMEM; sled->map = map; if (of_property_read_u32(np, "offset", &sled->offset)) return -EINVAL; if (of_property_read_u32(np, "mask", &sled->mask)) return -EINVAL; |
a917d4b44 leds: syscon: ins... |
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
state = of_get_property(np, "default-state", NULL); if (state) { if (!strcmp(state, "keep")) { u32 val; ret = regmap_read(map, sled->offset, &val); if (ret < 0) return ret; sled->state = !!(val & sled->mask); } else if (!strcmp(state, "on")) { sled->state = true; ret = regmap_update_bits(map, sled->offset, sled->mask, sled->mask); if (ret < 0) return ret; } else { sled->state = false; ret = regmap_update_bits(map, sled->offset, sled->mask, 0); if (ret < 0) return ret; |
535f09cc1 leds: add a drive... |
112 |
} |
a917d4b44 leds: syscon: ins... |
113 114 |
} sled->cdev.brightness_set = syscon_led_set; |
535f09cc1 leds: add a drive... |
115 |
|
006631969 leds: syscon: use... |
116 117 118 |
init_data.fwnode = of_fwnode_handle(np); ret = devm_led_classdev_register_ext(dev, &sled->cdev, &init_data); |
a917d4b44 leds: syscon: ins... |
119 120 121 122 123 124 |
if (ret < 0) return ret; platform_set_drvdata(pdev, sled); dev_info(dev, "registered LED %s ", sled->cdev.name); |
535f09cc1 leds: add a drive... |
125 |
|
3f6e42c80 leds: syscon: han... |
126 127 |
return 0; } |
a917d4b44 leds: syscon: ins... |
128 129 130 131 |
static const struct of_device_id of_syscon_leds_match[] = { { .compatible = "register-bit-led", }, {}, }; |
3f6e42c80 leds: syscon: han... |
132 |
|
a917d4b44 leds: syscon: ins... |
133 134 |
static struct platform_driver syscon_led_driver = { .probe = syscon_led_probe, |
a917d4b44 leds: syscon: ins... |
135 136 137 |
.driver = { .name = "leds-syscon", .of_match_table = of_syscon_leds_match, |
f7d98a65d leds: syscon: Mak... |
138 |
.suppress_bind_attrs = true, |
a917d4b44 leds: syscon: ins... |
139 140 |
}, }; |
f7d98a65d leds: syscon: Mak... |
141 |
builtin_platform_driver(syscon_led_driver); |