hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/leds/leds-pwm.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * linux/drivers/leds-pwm.c
34 *
....@@ -6,10 +7,6 @@
67 * Copyright 2009 Luotao Fu @ Pengutronix (l.fu@pengutronix.de)
78 *
89 * based on leds-gpio.c by Raphael Assenat <raph@8d.com>
9
- *
10
- * This program is free software; you can redistribute it and/or modify
11
- * it under the terms of the GNU General Public License version 2 as
12
- * published by the Free Software Foundation.
1310 */
1411
1512 #include <linux/module.h>
....@@ -19,33 +16,25 @@
1916 #include <linux/leds.h>
2017 #include <linux/err.h>
2118 #include <linux/pwm.h>
22
-#include <linux/leds_pwm.h>
2319 #include <linux/slab.h>
20
+
21
+struct led_pwm {
22
+ const char *name;
23
+ u8 active_low;
24
+ unsigned int max_brightness;
25
+};
2426
2527 struct led_pwm_data {
2628 struct led_classdev cdev;
2729 struct pwm_device *pwm;
30
+ struct pwm_state pwmstate;
2831 unsigned int active_low;
29
- unsigned int period;
30
- int duty;
3132 };
3233
3334 struct led_pwm_priv {
3435 int num_leds;
35
- struct led_pwm_data leds[0];
36
+ struct led_pwm_data leds[];
3637 };
37
-
38
-static void __led_pwm_set(struct led_pwm_data *led_dat)
39
-{
40
- int new_duty = led_dat->duty;
41
-
42
- pwm_config(led_dat->pwm, new_duty, led_dat->period);
43
-
44
- if (new_duty == 0)
45
- pwm_disable(led_dat->pwm);
46
- else
47
- pwm_enable(led_dat->pwm);
48
-}
4938
5039 static int led_pwm_set(struct led_classdev *led_cdev,
5140 enum led_brightness brightness)
....@@ -53,106 +42,87 @@
5342 struct led_pwm_data *led_dat =
5443 container_of(led_cdev, struct led_pwm_data, cdev);
5544 unsigned int max = led_dat->cdev.max_brightness;
56
- unsigned long long duty = led_dat->period;
45
+ unsigned long long duty = led_dat->pwmstate.period;
5746
5847 duty *= brightness;
5948 do_div(duty, max);
6049
6150 if (led_dat->active_low)
62
- duty = led_dat->period - duty;
51
+ duty = led_dat->pwmstate.period - duty;
6352
64
- led_dat->duty = duty;
65
-
66
- __led_pwm_set(led_dat);
67
-
68
- return 0;
53
+ led_dat->pwmstate.duty_cycle = duty;
54
+ led_dat->pwmstate.enabled = duty > 0;
55
+ return pwm_apply_state(led_dat->pwm, &led_dat->pwmstate);
6956 }
7057
71
-static inline size_t sizeof_pwm_leds_priv(int num_leds)
72
-{
73
- return sizeof(struct led_pwm_priv) +
74
- (sizeof(struct led_pwm_data) * num_leds);
75
-}
76
-
77
-static void led_pwm_cleanup(struct led_pwm_priv *priv)
78
-{
79
- while (priv->num_leds--)
80
- led_classdev_unregister(&priv->leds[priv->num_leds].cdev);
81
-}
82
-
58
+__attribute__((nonnull))
8359 static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
84
- struct led_pwm *led, struct device_node *child)
60
+ struct led_pwm *led, struct fwnode_handle *fwnode)
8561 {
8662 struct led_pwm_data *led_data = &priv->leds[priv->num_leds];
87
- struct pwm_args pargs;
63
+ struct led_init_data init_data = { .fwnode = fwnode };
8864 int ret;
8965
9066 led_data->active_low = led->active_low;
9167 led_data->cdev.name = led->name;
92
- led_data->cdev.default_trigger = led->default_trigger;
9368 led_data->cdev.brightness = LED_OFF;
9469 led_data->cdev.max_brightness = led->max_brightness;
9570 led_data->cdev.flags = LED_CORE_SUSPENDRESUME;
9671
97
- if (child)
98
- led_data->pwm = devm_of_pwm_get(dev, child, NULL);
99
- else
100
- led_data->pwm = devm_pwm_get(dev, led->name);
101
- if (IS_ERR(led_data->pwm)) {
102
- ret = PTR_ERR(led_data->pwm);
103
- if (ret != -EPROBE_DEFER)
104
- dev_err(dev, "unable to request PWM for %s: %d\n",
105
- led->name, ret);
106
- return ret;
107
- }
72
+ led_data->pwm = devm_fwnode_pwm_get(dev, fwnode, NULL);
73
+ if (IS_ERR(led_data->pwm))
74
+ return dev_err_probe(dev, PTR_ERR(led_data->pwm),
75
+ "unable to request PWM for %s\n",
76
+ led->name);
10877
10978 led_data->cdev.brightness_set_blocking = led_pwm_set;
11079
111
- /*
112
- * FIXME: pwm_apply_args() should be removed when switching to the
113
- * atomic PWM API.
114
- */
115
- pwm_apply_args(led_data->pwm);
80
+ pwm_init_state(led_data->pwm, &led_data->pwmstate);
11681
117
- pwm_get_args(led_data->pwm, &pargs);
118
-
119
- led_data->period = pargs.period;
120
- if (!led_data->period && (led->pwm_period_ns > 0))
121
- led_data->period = led->pwm_period_ns;
122
-
123
- ret = led_classdev_register(dev, &led_data->cdev);
124
- if (ret == 0) {
125
- priv->num_leds++;
126
- led_pwm_set(&led_data->cdev, led_data->cdev.brightness);
127
- } else {
82
+ ret = devm_led_classdev_register_ext(dev, &led_data->cdev, &init_data);
83
+ if (ret) {
12884 dev_err(dev, "failed to register PWM led for %s: %d\n",
12985 led->name, ret);
86
+ return ret;
13087 }
13188
132
- return ret;
89
+ ret = led_pwm_set(&led_data->cdev, led_data->cdev.brightness);
90
+ if (ret) {
91
+ dev_err(dev, "failed to set led PWM value for %s: %d",
92
+ led->name, ret);
93
+ return ret;
94
+ }
95
+
96
+ priv->num_leds++;
97
+ return 0;
13398 }
13499
135
-static int led_pwm_create_of(struct device *dev, struct led_pwm_priv *priv)
100
+static int led_pwm_create_fwnode(struct device *dev, struct led_pwm_priv *priv)
136101 {
137
- struct device_node *child;
102
+ struct fwnode_handle *fwnode;
138103 struct led_pwm led;
139104 int ret = 0;
140105
141106 memset(&led, 0, sizeof(led));
142107
143
- for_each_child_of_node(dev->of_node, child) {
144
- led.name = of_get_property(child, "label", NULL) ? :
145
- child->name;
108
+ device_for_each_child_node(dev, fwnode) {
109
+ ret = fwnode_property_read_string(fwnode, "label", &led.name);
110
+ if (ret && is_of_node(fwnode))
111
+ led.name = to_of_node(fwnode)->name;
146112
147
- led.default_trigger = of_get_property(child,
148
- "linux,default-trigger", NULL);
149
- led.active_low = of_property_read_bool(child, "active-low");
150
- of_property_read_u32(child, "max-brightness",
151
- &led.max_brightness);
113
+ if (!led.name) {
114
+ fwnode_handle_put(fwnode);
115
+ return -EINVAL;
116
+ }
152117
153
- ret = led_pwm_add(dev, priv, &led, child);
118
+ led.active_low = fwnode_property_read_bool(fwnode,
119
+ "active-low");
120
+ fwnode_property_read_u32(fwnode, "max-brightness",
121
+ &led.max_brightness);
122
+
123
+ ret = led_pwm_add(dev, priv, &led, fwnode);
154124 if (ret) {
155
- of_node_put(child);
125
+ fwnode_handle_put(fwnode);
156126 break;
157127 }
158128 }
....@@ -162,50 +132,26 @@
162132
163133 static int led_pwm_probe(struct platform_device *pdev)
164134 {
165
- struct led_pwm_platform_data *pdata = dev_get_platdata(&pdev->dev);
166135 struct led_pwm_priv *priv;
167
- int count, i;
168136 int ret = 0;
137
+ int count;
169138
170
- if (pdata)
171
- count = pdata->num_leds;
172
- else
173
- count = of_get_child_count(pdev->dev.of_node);
139
+ count = device_get_child_node_count(&pdev->dev);
174140
175141 if (!count)
176142 return -EINVAL;
177143
178
- priv = devm_kzalloc(&pdev->dev, sizeof_pwm_leds_priv(count),
144
+ priv = devm_kzalloc(&pdev->dev, struct_size(priv, leds, count),
179145 GFP_KERNEL);
180146 if (!priv)
181147 return -ENOMEM;
182148
183
- if (pdata) {
184
- for (i = 0; i < count; i++) {
185
- ret = led_pwm_add(&pdev->dev, priv, &pdata->leds[i],
186
- NULL);
187
- if (ret)
188
- break;
189
- }
190
- } else {
191
- ret = led_pwm_create_of(&pdev->dev, priv);
192
- }
149
+ ret = led_pwm_create_fwnode(&pdev->dev, priv);
193150
194
- if (ret) {
195
- led_pwm_cleanup(priv);
151
+ if (ret)
196152 return ret;
197
- }
198153
199154 platform_set_drvdata(pdev, priv);
200
-
201
- return 0;
202
-}
203
-
204
-static int led_pwm_remove(struct platform_device *pdev)
205
-{
206
- struct led_pwm_priv *priv = platform_get_drvdata(pdev);
207
-
208
- led_pwm_cleanup(priv);
209155
210156 return 0;
211157 }
....@@ -218,7 +164,6 @@
218164
219165 static struct platform_driver led_pwm_driver = {
220166 .probe = led_pwm_probe,
221
- .remove = led_pwm_remove,
222167 .driver = {
223168 .name = "leds_pwm",
224169 .of_match_table = of_pwm_leds_match,