Merge tag 'vboxsf-v6.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/hansg...
[linux-block.git] / drivers / pwm / pwm-cros-ec.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Expose a PWM controlled by the ChromeOS EC to the host processor.
4  *
5  * Copyright (C) 2016 Google, Inc.
6  */
7
8 #include <linux/module.h>
9 #include <linux/of.h>
10 #include <linux/platform_data/cros_ec_commands.h>
11 #include <linux/platform_data/cros_ec_proto.h>
12 #include <linux/platform_device.h>
13 #include <linux/pwm.h>
14 #include <linux/slab.h>
15
16 #include <dt-bindings/mfd/cros_ec.h>
17
18 /**
19  * struct cros_ec_pwm_device - Driver data for EC PWM
20  *
21  * @ec: Pointer to EC device
22  * @use_pwm_type: Use PWM types instead of generic channels
23  * @channel: array with per-channel data
24  */
25 struct cros_ec_pwm_device {
26         struct cros_ec_device *ec;
27         bool use_pwm_type;
28         struct cros_ec_pwm *channel;
29 };
30
31 /**
32  * struct cros_ec_pwm - per-PWM driver data
33  * @duty_cycle: cached duty cycle
34  */
35 struct cros_ec_pwm {
36         u16 duty_cycle;
37 };
38
39 static inline struct cros_ec_pwm_device *pwm_to_cros_ec_pwm(struct pwm_chip *chip)
40 {
41         return pwmchip_get_drvdata(chip);
42 }
43
44 static int cros_ec_dt_type_to_pwm_type(u8 dt_index, u8 *pwm_type)
45 {
46         switch (dt_index) {
47         case CROS_EC_PWM_DT_KB_LIGHT:
48                 *pwm_type = EC_PWM_TYPE_KB_LIGHT;
49                 return 0;
50         case CROS_EC_PWM_DT_DISPLAY_LIGHT:
51                 *pwm_type = EC_PWM_TYPE_DISPLAY_LIGHT;
52                 return 0;
53         default:
54                 return -EINVAL;
55         }
56 }
57
58 static int cros_ec_pwm_set_duty(struct cros_ec_pwm_device *ec_pwm, u8 index,
59                                 u16 duty)
60 {
61         struct cros_ec_device *ec = ec_pwm->ec;
62         struct {
63                 struct cros_ec_command msg;
64                 struct ec_params_pwm_set_duty params;
65         } __packed buf;
66         struct ec_params_pwm_set_duty *params = &buf.params;
67         struct cros_ec_command *msg = &buf.msg;
68         int ret;
69
70         memset(&buf, 0, sizeof(buf));
71
72         msg->version = 0;
73         msg->command = EC_CMD_PWM_SET_DUTY;
74         msg->insize = 0;
75         msg->outsize = sizeof(*params);
76
77         params->duty = duty;
78
79         if (ec_pwm->use_pwm_type) {
80                 ret = cros_ec_dt_type_to_pwm_type(index, &params->pwm_type);
81                 if (ret) {
82                         dev_err(ec->dev, "Invalid PWM type index: %d\n", index);
83                         return ret;
84                 }
85                 params->index = 0;
86         } else {
87                 params->pwm_type = EC_PWM_TYPE_GENERIC;
88                 params->index = index;
89         }
90
91         return cros_ec_cmd_xfer_status(ec, msg);
92 }
93
94 static int cros_ec_pwm_get_duty(struct cros_ec_device *ec, bool use_pwm_type, u8 index)
95 {
96         struct {
97                 struct cros_ec_command msg;
98                 union {
99                         struct ec_params_pwm_get_duty params;
100                         struct ec_response_pwm_get_duty resp;
101                 };
102         } __packed buf;
103         struct ec_params_pwm_get_duty *params = &buf.params;
104         struct ec_response_pwm_get_duty *resp = &buf.resp;
105         struct cros_ec_command *msg = &buf.msg;
106         int ret;
107
108         memset(&buf, 0, sizeof(buf));
109
110         msg->version = 0;
111         msg->command = EC_CMD_PWM_GET_DUTY;
112         msg->insize = sizeof(*resp);
113         msg->outsize = sizeof(*params);
114
115         if (use_pwm_type) {
116                 ret = cros_ec_dt_type_to_pwm_type(index, &params->pwm_type);
117                 if (ret) {
118                         dev_err(ec->dev, "Invalid PWM type index: %d\n", index);
119                         return ret;
120                 }
121                 params->index = 0;
122         } else {
123                 params->pwm_type = EC_PWM_TYPE_GENERIC;
124                 params->index = index;
125         }
126
127         ret = cros_ec_cmd_xfer_status(ec, msg);
128         if (ret < 0)
129                 return ret;
130
131         return resp->duty;
132 }
133
134 static int cros_ec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
135                              const struct pwm_state *state)
136 {
137         struct cros_ec_pwm_device *ec_pwm = pwm_to_cros_ec_pwm(chip);
138         struct cros_ec_pwm *channel = &ec_pwm->channel[pwm->hwpwm];
139         u16 duty_cycle;
140         int ret;
141
142         /* The EC won't let us change the period */
143         if (state->period != EC_PWM_MAX_DUTY)
144                 return -EINVAL;
145
146         if (state->polarity != PWM_POLARITY_NORMAL)
147                 return -EINVAL;
148
149         /*
150          * EC doesn't separate the concept of duty cycle and enabled, but
151          * kernel does. Translate.
152          */
153         duty_cycle = state->enabled ? state->duty_cycle : 0;
154
155         ret = cros_ec_pwm_set_duty(ec_pwm, pwm->hwpwm, duty_cycle);
156         if (ret < 0)
157                 return ret;
158
159         channel->duty_cycle = state->duty_cycle;
160
161         return 0;
162 }
163
164 static int cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
165                                  struct pwm_state *state)
166 {
167         struct cros_ec_pwm_device *ec_pwm = pwm_to_cros_ec_pwm(chip);
168         struct cros_ec_pwm *channel = &ec_pwm->channel[pwm->hwpwm];
169         int ret;
170
171         ret = cros_ec_pwm_get_duty(ec_pwm->ec, ec_pwm->use_pwm_type, pwm->hwpwm);
172         if (ret < 0) {
173                 dev_err(pwmchip_parent(chip), "error getting initial duty: %d\n", ret);
174                 return ret;
175         }
176
177         state->enabled = (ret > 0);
178         state->period = EC_PWM_MAX_DUTY;
179         state->polarity = PWM_POLARITY_NORMAL;
180
181         /*
182          * Note that "disabled" and "duty cycle == 0" are treated the same. If
183          * the cached duty cycle is not zero, used the cached duty cycle. This
184          * ensures that the configured duty cycle is kept across a disable and
185          * enable operation and avoids potentially confusing consumers.
186          *
187          * For the case of the initial hardware readout, channel->duty_cycle
188          * will be 0 and the actual duty cycle read from the EC is used.
189          */
190         if (ret == 0 && channel->duty_cycle > 0)
191                 state->duty_cycle = channel->duty_cycle;
192         else
193                 state->duty_cycle = ret;
194
195         return 0;
196 }
197
198 static struct pwm_device *
199 cros_ec_pwm_xlate(struct pwm_chip *chip, const struct of_phandle_args *args)
200 {
201         struct pwm_device *pwm;
202
203         if (args->args[0] >= chip->npwm)
204                 return ERR_PTR(-EINVAL);
205
206         pwm = pwm_request_from_chip(chip, args->args[0], NULL);
207         if (IS_ERR(pwm))
208                 return pwm;
209
210         /* The EC won't let us change the period */
211         pwm->args.period = EC_PWM_MAX_DUTY;
212
213         return pwm;
214 }
215
216 static const struct pwm_ops cros_ec_pwm_ops = {
217         .get_state      = cros_ec_pwm_get_state,
218         .apply          = cros_ec_pwm_apply,
219 };
220
221 /*
222  * Determine the number of supported PWMs. The EC does not return the number
223  * of PWMs it supports directly, so we have to read the pwm duty cycle for
224  * subsequent channels until we get an error.
225  */
226 static int cros_ec_num_pwms(struct cros_ec_device *ec)
227 {
228         int i, ret;
229
230         /* The index field is only 8 bits */
231         for (i = 0; i <= U8_MAX; i++) {
232                 /*
233                  * Note that this function is only called when use_pwm_type is
234                  * false. With use_pwm_type == true the number of PWMs is fixed.
235                  */
236                 ret = cros_ec_pwm_get_duty(ec, false, i);
237                 /*
238                  * We look for SUCCESS, INVALID_COMMAND, or INVALID_PARAM
239                  * responses; everything else is treated as an error.
240                  * The EC error codes map to -EOPNOTSUPP and -EINVAL,
241                  * so check for those.
242                  */
243                 switch (ret) {
244                 case -EOPNOTSUPP:       /* invalid command */
245                         return -ENODEV;
246                 case -EINVAL:           /* invalid parameter */
247                         return i;
248                 default:
249                         if (ret < 0)
250                                 return ret;
251                         break;
252                 }
253         }
254
255         return U8_MAX;
256 }
257
258 static int cros_ec_pwm_probe(struct platform_device *pdev)
259 {
260         struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
261         struct device *dev = &pdev->dev;
262         struct device_node *np = pdev->dev.of_node;
263         struct cros_ec_pwm_device *ec_pwm;
264         struct pwm_chip *chip;
265         bool use_pwm_type = false;
266         unsigned int npwm;
267         int ret;
268
269         if (!ec)
270                 return dev_err_probe(dev, -EINVAL, "no parent EC device\n");
271
272         if (of_device_is_compatible(np, "google,cros-ec-pwm-type")) {
273                 use_pwm_type = true;
274                 npwm = CROS_EC_PWM_DT_COUNT;
275         } else {
276                 ret = cros_ec_num_pwms(ec);
277                 if (ret < 0)
278                         return dev_err_probe(dev, ret, "Couldn't find PWMs\n");
279                 npwm = ret;
280         }
281
282         chip = devm_pwmchip_alloc(dev, npwm, sizeof(*ec_pwm));
283         if (IS_ERR(chip))
284                 return PTR_ERR(chip);
285
286         ec_pwm = pwm_to_cros_ec_pwm(chip);
287         ec_pwm->use_pwm_type = use_pwm_type;
288         ec_pwm->ec = ec;
289
290         /* PWM chip */
291         chip->ops = &cros_ec_pwm_ops;
292         chip->of_xlate = cros_ec_pwm_xlate;
293
294         ec_pwm->channel = devm_kcalloc(dev, chip->npwm, sizeof(*ec_pwm->channel),
295                                         GFP_KERNEL);
296         if (!ec_pwm->channel)
297                 return -ENOMEM;
298
299         dev_dbg(dev, "Probed %u PWMs\n", chip->npwm);
300
301         ret = devm_pwmchip_add(dev, chip);
302         if (ret < 0)
303                 return dev_err_probe(dev, ret, "cannot register PWM\n");
304
305         return 0;
306 }
307
308 #ifdef CONFIG_OF
309 static const struct of_device_id cros_ec_pwm_of_match[] = {
310         { .compatible = "google,cros-ec-pwm" },
311         { .compatible = "google,cros-ec-pwm-type" },
312         {},
313 };
314 MODULE_DEVICE_TABLE(of, cros_ec_pwm_of_match);
315 #endif
316
317 static struct platform_driver cros_ec_pwm_driver = {
318         .probe = cros_ec_pwm_probe,
319         .driver = {
320                 .name = "cros-ec-pwm",
321                 .of_match_table = of_match_ptr(cros_ec_pwm_of_match),
322         },
323 };
324 module_platform_driver(cros_ec_pwm_driver);
325
326 MODULE_ALIAS("platform:cros-ec-pwm");
327 MODULE_DESCRIPTION("ChromeOS EC PWM driver");
328 MODULE_LICENSE("GPL v2");