12
12
#include <linux/pwm.h>
13
13
#include <linux/slab.h>
14
14
15
+ #include <dt-bindings/mfd/cros_ec.h>
16
+
15
17
/**
16
18
* struct cros_ec_pwm_device - Driver data for EC PWM
17
19
*
18
20
* @dev: Device node
19
21
* @ec: Pointer to EC device
20
22
* @chip: PWM controller chip
23
+ * @use_pwm_type: Use PWM types instead of generic channels
21
24
*/
22
25
struct cros_ec_pwm_device {
23
26
struct device * dev ;
24
27
struct cros_ec_device * ec ;
25
28
struct pwm_chip chip ;
29
+ bool use_pwm_type ;
26
30
};
27
31
28
32
/**
@@ -58,14 +62,31 @@ static void cros_ec_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
58
62
kfree (channel );
59
63
}
60
64
61
- static int cros_ec_pwm_set_duty ( struct cros_ec_device * ec , u8 index , u16 duty )
65
+ static int cros_ec_dt_type_to_pwm_type ( u8 dt_index , u8 * pwm_type )
62
66
{
67
+ switch (dt_index ) {
68
+ case CROS_EC_PWM_DT_KB_LIGHT :
69
+ * pwm_type = EC_PWM_TYPE_KB_LIGHT ;
70
+ return 0 ;
71
+ case CROS_EC_PWM_DT_DISPLAY_LIGHT :
72
+ * pwm_type = EC_PWM_TYPE_DISPLAY_LIGHT ;
73
+ return 0 ;
74
+ default :
75
+ return - EINVAL ;
76
+ }
77
+ }
78
+
79
+ static int cros_ec_pwm_set_duty (struct cros_ec_pwm_device * ec_pwm , u8 index ,
80
+ u16 duty )
81
+ {
82
+ struct cros_ec_device * ec = ec_pwm -> ec ;
63
83
struct {
64
84
struct cros_ec_command msg ;
65
85
struct ec_params_pwm_set_duty params ;
66
86
} __packed buf ;
67
87
struct ec_params_pwm_set_duty * params = & buf .params ;
68
88
struct cros_ec_command * msg = & buf .msg ;
89
+ int ret ;
69
90
70
91
memset (& buf , 0 , sizeof (buf ));
71
92
@@ -75,14 +96,25 @@ static int cros_ec_pwm_set_duty(struct cros_ec_device *ec, u8 index, u16 duty)
75
96
msg -> outsize = sizeof (* params );
76
97
77
98
params -> duty = duty ;
78
- params -> pwm_type = EC_PWM_TYPE_GENERIC ;
79
- params -> index = index ;
99
+
100
+ if (ec_pwm -> use_pwm_type ) {
101
+ ret = cros_ec_dt_type_to_pwm_type (index , & params -> pwm_type );
102
+ if (ret ) {
103
+ dev_err (ec -> dev , "Invalid PWM type index: %d\n" , index );
104
+ return ret ;
105
+ }
106
+ params -> index = 0 ;
107
+ } else {
108
+ params -> pwm_type = EC_PWM_TYPE_GENERIC ;
109
+ params -> index = index ;
110
+ }
80
111
81
112
return cros_ec_cmd_xfer_status (ec , msg );
82
113
}
83
114
84
- static int cros_ec_pwm_get_duty (struct cros_ec_device * ec , u8 index )
115
+ static int cros_ec_pwm_get_duty (struct cros_ec_pwm_device * ec_pwm , u8 index )
85
116
{
117
+ struct cros_ec_device * ec = ec_pwm -> ec ;
86
118
struct {
87
119
struct cros_ec_command msg ;
88
120
union {
@@ -102,8 +134,17 @@ static int cros_ec_pwm_get_duty(struct cros_ec_device *ec, u8 index)
102
134
msg -> insize = sizeof (* resp );
103
135
msg -> outsize = sizeof (* params );
104
136
105
- params -> pwm_type = EC_PWM_TYPE_GENERIC ;
106
- params -> index = index ;
137
+ if (ec_pwm -> use_pwm_type ) {
138
+ ret = cros_ec_dt_type_to_pwm_type (index , & params -> pwm_type );
139
+ if (ret ) {
140
+ dev_err (ec -> dev , "Invalid PWM type index: %d\n" , index );
141
+ return ret ;
142
+ }
143
+ params -> index = 0 ;
144
+ } else {
145
+ params -> pwm_type = EC_PWM_TYPE_GENERIC ;
146
+ params -> index = index ;
147
+ }
107
148
108
149
ret = cros_ec_cmd_xfer_status (ec , msg );
109
150
if (ret < 0 )
@@ -133,7 +174,7 @@ static int cros_ec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
133
174
*/
134
175
duty_cycle = state -> enabled ? state -> duty_cycle : 0 ;
135
176
136
- ret = cros_ec_pwm_set_duty (ec_pwm -> ec , pwm -> hwpwm , duty_cycle );
177
+ ret = cros_ec_pwm_set_duty (ec_pwm , pwm -> hwpwm , duty_cycle );
137
178
if (ret < 0 )
138
179
return ret ;
139
180
@@ -149,7 +190,7 @@ static void cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
149
190
struct cros_ec_pwm * channel = pwm_get_chip_data (pwm );
150
191
int ret ;
151
192
152
- ret = cros_ec_pwm_get_duty (ec_pwm -> ec , pwm -> hwpwm );
193
+ ret = cros_ec_pwm_get_duty (ec_pwm , pwm -> hwpwm );
153
194
if (ret < 0 ) {
154
195
dev_err (chip -> dev , "error getting initial duty: %d\n" , ret );
155
196
return ;
@@ -204,13 +245,13 @@ static const struct pwm_ops cros_ec_pwm_ops = {
204
245
* of PWMs it supports directly, so we have to read the pwm duty cycle for
205
246
* subsequent channels until we get an error.
206
247
*/
207
- static int cros_ec_num_pwms (struct cros_ec_device * ec )
248
+ static int cros_ec_num_pwms (struct cros_ec_pwm_device * ec_pwm )
208
249
{
209
250
int i , ret ;
210
251
211
252
/* The index field is only 8 bits */
212
253
for (i = 0 ; i <= U8_MAX ; i ++ ) {
213
- ret = cros_ec_pwm_get_duty (ec , i );
254
+ ret = cros_ec_pwm_get_duty (ec_pwm , i );
214
255
/*
215
256
* We look for SUCCESS, INVALID_COMMAND, or INVALID_PARAM
216
257
* responses; everything else is treated as an error.
@@ -236,6 +277,7 @@ static int cros_ec_pwm_probe(struct platform_device *pdev)
236
277
{
237
278
struct cros_ec_device * ec = dev_get_drvdata (pdev -> dev .parent );
238
279
struct device * dev = & pdev -> dev ;
280
+ struct device_node * np = pdev -> dev .of_node ;
239
281
struct cros_ec_pwm_device * ec_pwm ;
240
282
struct pwm_chip * chip ;
241
283
int ret ;
@@ -251,17 +293,26 @@ static int cros_ec_pwm_probe(struct platform_device *pdev)
251
293
chip = & ec_pwm -> chip ;
252
294
ec_pwm -> ec = ec ;
253
295
296
+ if (of_device_is_compatible (np , "google,cros-ec-pwm-type" ))
297
+ ec_pwm -> use_pwm_type = true;
298
+
254
299
/* PWM chip */
255
300
chip -> dev = dev ;
256
301
chip -> ops = & cros_ec_pwm_ops ;
257
302
chip -> of_xlate = cros_ec_pwm_xlate ;
258
303
chip -> of_pwm_n_cells = 1 ;
259
- ret = cros_ec_num_pwms (ec );
260
- if (ret < 0 ) {
261
- dev_err (dev , "Couldn't find PWMs: %d\n" , ret );
262
- return ret ;
304
+
305
+ if (ec_pwm -> use_pwm_type ) {
306
+ chip -> npwm = CROS_EC_PWM_DT_COUNT ;
307
+ } else {
308
+ ret = cros_ec_num_pwms (ec_pwm );
309
+ if (ret < 0 ) {
310
+ dev_err (dev , "Couldn't find PWMs: %d\n" , ret );
311
+ return ret ;
312
+ }
313
+ chip -> npwm = ret ;
263
314
}
264
- chip -> npwm = ret ;
315
+
265
316
dev_dbg (dev , "Probed %u PWMs\n" , chip -> npwm );
266
317
267
318
ret = pwmchip_add (chip );
@@ -288,6 +339,7 @@ static int cros_ec_pwm_remove(struct platform_device *dev)
288
339
#ifdef CONFIG_OF
289
340
static const struct of_device_id cros_ec_pwm_of_match [] = {
290
341
{ .compatible = "google,cros-ec-pwm" },
342
+ { .compatible = "google,cros-ec-pwm-type" },
291
343
{},
292
344
};
293
345
MODULE_DEVICE_TABLE (of , cros_ec_pwm_of_match );
0 commit comments