blob: bd1379f4400fe5095c0a6f7c05e4103e64796306 [file] [log] [blame]
Matt Porter34c65072014-11-13 09:14:13 -05001/*
2 * PWM Greybus driver.
3 *
4 * Copyright 2014 Google Inc.
5 * Copyright 2014 Linaro Ltd.
6 *
7 * Released under the GPLv2 only.
8 */
9
10#include <linux/kernel.h>
11#include <linux/module.h>
12#include <linux/slab.h>
13#include <linux/pwm.h>
14#include "greybus.h"
15
16struct gb_pwm_chip {
17 struct gb_connection *connection;
18 u8 version_major;
19 u8 version_minor;
20 u8 pwm_max; /* max pwm number */
21
22 struct pwm_chip chip;
23 struct pwm_chip *pwm;
24};
25#define pwm_chip_to_gb_pwm_chip(chip) \
26 container_of(chip, struct gb_pwm_chip, chip)
27
28/* Version of the Greybus PWM protocol we support */
29#define GB_PWM_VERSION_MAJOR 0x00
30#define GB_PWM_VERSION_MINOR 0x01
31
32/* Greybus PWM request types */
33#define GB_PWM_TYPE_INVALID 0x00
34#define GB_PWM_TYPE_PROTOCOL_VERSION 0x01
35#define GB_PWM_TYPE_PWM_COUNT 0x02
36#define GB_PWM_TYPE_ACTIVATE 0x03
37#define GB_PWM_TYPE_DEACTIVATE 0x04
38#define GB_PWM_TYPE_CONFIG 0x05
39#define GB_PWM_TYPE_POLARITY 0x06
40#define GB_PWM_TYPE_ENABLE 0x07
41#define GB_PWM_TYPE_DISABLE 0x08
42#define GB_PWM_TYPE_RESPONSE 0x80 /* OR'd with rest */
43
Matt Porter34c65072014-11-13 09:14:13 -050044/* version request has no payload */
45struct gb_pwm_proto_version_response {
Matt Porter34c65072014-11-13 09:14:13 -050046 __u8 major;
47 __u8 minor;
48};
49
50/* pwm count request has no payload */
51struct gb_pwm_count_response {
Matt Porter34c65072014-11-13 09:14:13 -050052 __u8 count;
53};
54
55struct gb_pwm_activate_request {
56 __u8 which;
57};
58
59struct gb_pwm_deactivate_request {
60 __u8 which;
61};
62
63struct gb_pwm_config_request {
64 __u8 which;
65 __u32 duty;
66 __u32 period;
67};
68
69struct gb_pwm_polarity_request {
70 __u8 which;
71 __u8 polarity;
72};
73
74struct gb_pwm_enable_request {
75 __u8 which;
76};
77
78struct gb_pwm_disable_request {
79 __u8 which;
80};
81
82/*
83 * This request only uses the connection field, and if successful,
84 * fills in the major and minor protocol version of the target.
85 */
86static int gb_pwm_proto_version_operation(struct gb_pwm_chip *pwmc)
87{
Greg Kroah-Hartmanbf2329f2014-11-23 17:45:24 -080088 struct gb_pwm_proto_version_response response;
Matt Porter34c65072014-11-13 09:14:13 -050089 int ret;
90
Greg Kroah-Hartmanbf2329f2014-11-23 17:45:24 -080091 ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_PROTOCOL_VERSION,
92 NULL, 0, &response, sizeof(response));
Matt Porter34c65072014-11-13 09:14:13 -050093
Greg Kroah-Hartmanbf2329f2014-11-23 17:45:24 -080094 if (ret)
95 return ret;
Matt Porter34c65072014-11-13 09:14:13 -050096
Greg Kroah-Hartmanbf2329f2014-11-23 17:45:24 -080097 if (response.major > GB_PWM_VERSION_MAJOR) {
Alex Elder23383de2014-11-21 19:29:12 -060098 pr_err("unsupported major version (%hhu > %hhu)\n",
Greg Kroah-Hartmanbf2329f2014-11-23 17:45:24 -080099 response.major, GB_PWM_VERSION_MAJOR);
100 return -ENOTSUPP;
Matt Porter34c65072014-11-13 09:14:13 -0500101 }
Greg Kroah-Hartmanbf2329f2014-11-23 17:45:24 -0800102 pwmc->version_major = response.major;
103 pwmc->version_minor = response.minor;
104 return 0;
Matt Porter34c65072014-11-13 09:14:13 -0500105}
106
107static int gb_pwm_count_operation(struct gb_pwm_chip *pwmc)
108{
Greg Kroah-Hartmanbf2329f2014-11-23 17:45:24 -0800109 struct gb_pwm_count_response response;
Matt Porter34c65072014-11-13 09:14:13 -0500110 int ret;
111
Greg Kroah-Hartmanbf2329f2014-11-23 17:45:24 -0800112 ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_PWM_COUNT,
113 NULL, 0, &response, sizeof(response));
114 if (ret)
115 return ret;
116 pwmc->pwm_max = response.count;
117 return 0;
Matt Porter34c65072014-11-13 09:14:13 -0500118}
119
120static int gb_pwm_activate_operation(struct gb_pwm_chip *pwmc,
121 u8 which)
122{
Greg Kroah-Hartmanbf2329f2014-11-23 17:45:24 -0800123 struct gb_pwm_activate_request request;
Matt Porter34c65072014-11-13 09:14:13 -0500124
125 if (which > pwmc->pwm_max)
126 return -EINVAL;
127
Greg Kroah-Hartmanbf2329f2014-11-23 17:45:24 -0800128 request.which = which;
129 return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ACTIVATE,
130 &request, sizeof(request), NULL, 0);
Matt Porter34c65072014-11-13 09:14:13 -0500131}
132
133static int gb_pwm_deactivate_operation(struct gb_pwm_chip *pwmc,
134 u8 which)
135{
Greg Kroah-Hartmanbf2329f2014-11-23 17:45:24 -0800136 struct gb_pwm_deactivate_request request;
Matt Porter34c65072014-11-13 09:14:13 -0500137
138 if (which > pwmc->pwm_max)
139 return -EINVAL;
140
Greg Kroah-Hartmanbf2329f2014-11-23 17:45:24 -0800141 request.which = which;
142 return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DEACTIVATE,
143 &request, sizeof(request), NULL, 0);
Matt Porter34c65072014-11-13 09:14:13 -0500144}
145
146static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc,
147 u8 which, u32 duty, u32 period)
148{
Greg Kroah-Hartmanbf2329f2014-11-23 17:45:24 -0800149 struct gb_pwm_config_request request;
Matt Porter34c65072014-11-13 09:14:13 -0500150
151 if (which > pwmc->pwm_max)
152 return -EINVAL;
153
Greg Kroah-Hartmanbf2329f2014-11-23 17:45:24 -0800154 request.which = which;
155 request.duty = duty;
156 request.period = period;
157 return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_CONFIG,
158 &request, sizeof(request), NULL, 0);
Matt Porter34c65072014-11-13 09:14:13 -0500159}
160
161
162static int gb_pwm_set_polarity_operation(struct gb_pwm_chip *pwmc,
163 u8 which, u8 polarity)
164{
Greg Kroah-Hartmanbf2329f2014-11-23 17:45:24 -0800165 struct gb_pwm_polarity_request request;
Matt Porter34c65072014-11-13 09:14:13 -0500166
167 if (which > pwmc->pwm_max)
168 return -EINVAL;
169
Greg Kroah-Hartmanbf2329f2014-11-23 17:45:24 -0800170 request.which = which;
171 request.polarity = polarity;
172 return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_POLARITY,
173 &request, sizeof(request), NULL, 0);
Matt Porter34c65072014-11-13 09:14:13 -0500174}
175
176static int gb_pwm_enable_operation(struct gb_pwm_chip *pwmc,
177 u8 which)
178{
Greg Kroah-Hartmanbf2329f2014-11-23 17:45:24 -0800179 struct gb_pwm_enable_request request;
Matt Porter34c65072014-11-13 09:14:13 -0500180
181 if (which > pwmc->pwm_max)
182 return -EINVAL;
183
Greg Kroah-Hartmanbf2329f2014-11-23 17:45:24 -0800184 request.which = which;
185 return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ENABLE,
186 &request, sizeof(request), NULL, 0);
Matt Porter34c65072014-11-13 09:14:13 -0500187}
188
189static int gb_pwm_disable_operation(struct gb_pwm_chip *pwmc,
190 u8 which)
191{
Greg Kroah-Hartmanbf2329f2014-11-23 17:45:24 -0800192 struct gb_pwm_disable_request request;
Matt Porter34c65072014-11-13 09:14:13 -0500193
194 if (which > pwmc->pwm_max)
195 return -EINVAL;
196
Greg Kroah-Hartmanbf2329f2014-11-23 17:45:24 -0800197 request.which = which;
198 return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DISABLE,
199 &request, sizeof(request), NULL, 0);
Matt Porter34c65072014-11-13 09:14:13 -0500200}
201
202static int gb_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
203{
204 struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
205
206 return gb_pwm_activate_operation(pwmc, pwm->hwpwm);
207};
208
209static void gb_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
210{
211 struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
212
213 if (test_bit(PWMF_ENABLED, &pwm->flags))
214 dev_warn(chip->dev, "freeing PWM device without disabling\n");
215
216 gb_pwm_deactivate_operation(pwmc, pwm->hwpwm);
217}
218
219static int gb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
220 int duty_ns, int period_ns)
221{
222 struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
223
224 return gb_pwm_config_operation(pwmc, pwm->hwpwm, duty_ns, period_ns);
225};
226
227static int gb_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
228 enum pwm_polarity polarity)
229{
230 struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
231
232 return gb_pwm_set_polarity_operation(pwmc, pwm->hwpwm, polarity);
233};
234
235static int gb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
236{
237 struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
238
239 return gb_pwm_enable_operation(pwmc, pwm->hwpwm);
240};
241
242static void gb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
243{
244 struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
245
246 gb_pwm_disable_operation(pwmc, pwm->hwpwm);
247};
248
249static const struct pwm_ops gb_pwm_ops = {
250 .request = gb_pwm_request,
251 .free = gb_pwm_free,
252 .config = gb_pwm_config,
253 .set_polarity = gb_pwm_set_polarity,
254 .enable = gb_pwm_enable,
255 .disable = gb_pwm_disable,
256 .owner = THIS_MODULE,
257};
258
259static int gb_pwm_connection_init(struct gb_connection *connection)
260{
261 struct gb_pwm_chip *pwmc;
262 struct pwm_chip *pwm;
263 int ret;
264
265 pwmc = kzalloc(sizeof(*pwmc), GFP_KERNEL);
266 if (!pwmc)
267 return -ENOMEM;
268 pwmc->connection = connection;
269
270 /* Check for compatible protocol version */
271 ret = gb_pwm_proto_version_operation(pwmc);
272 if (ret)
273 goto out_err;
274
275 /* Query number of pwms present */
276 ret = gb_pwm_count_operation(pwmc);
277 if (ret)
278 goto out_err;
279
280 pwm = &pwmc->chip;
281
282 pwm->dev = &connection->dev;
283 pwm->ops = &gb_pwm_ops;
284 pwm->base = -1; /* Allocate base dynamically */
285 pwm->npwm = pwmc->pwm_max + 1;
286 pwm->can_sleep = true; /* FIXME */
287
288 ret = pwmchip_add(pwm);
289 if (ret) {
290 pr_err("Failed to register PWM\n");
291 return ret;
292 }
293 connection->private = pwmc;
294
295 return 0;
296out_err:
297 kfree(pwmc);
298 return ret;
299}
300
301static void gb_pwm_connection_exit(struct gb_connection *connection)
302{
303 struct gb_pwm_chip *pwmc = connection->private;
304
305 if (!pwmc)
306 return;
307
308 pwmchip_remove(&pwmc->chip);
309 /* kref_put(pwmc->connection) */
310 kfree(pwmc);
311}
312
313static struct gb_protocol pwm_protocol = {
314 .id = GREYBUS_PROTOCOL_PWM,
315 .major = 0,
316 .minor = 1,
317 .connection_init = gb_pwm_connection_init,
318 .connection_exit = gb_pwm_connection_exit,
319 .request_recv = NULL, /* no incoming requests */
320};
321
322bool gb_pwm_protocol_init(void)
323{
324 return gb_protocol_register(&pwm_protocol);
325}
326
327void gb_pwm_protocol_exit(void)
328{
329 gb_protocol_deregister(&pwm_protocol);
330}