]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/greybus/pwm.c
77b05e895550d9733b2407a0de95470b2a61282b
[karo-tx-linux.git] / drivers / staging / greybus / pwm.c
1 /*
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
15 #include "greybus.h"
16 #include "gbphy.h"
17
18 struct gb_pwm_chip {
19         struct gb_connection    *connection;
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
29 static int gb_pwm_count_operation(struct gb_pwm_chip *pwmc)
30 {
31         struct gb_pwm_count_response response;
32         int ret;
33
34         ret = gb_operation_sync(pwmc->connection, GB_PWM_TYPE_PWM_COUNT,
35                                 NULL, 0, &response, sizeof(response));
36         if (ret)
37                 return ret;
38         pwmc->pwm_max = response.count;
39         return 0;
40 }
41
42 static int gb_pwm_activate_operation(struct gb_pwm_chip *pwmc,
43                                      u8 which)
44 {
45         struct gb_pwm_activate_request request;
46
47         if (which > pwmc->pwm_max)
48                 return -EINVAL;
49
50         request.which = which;
51         return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ACTIVATE,
52                                  &request, sizeof(request), NULL, 0);
53 }
54
55 static int gb_pwm_deactivate_operation(struct gb_pwm_chip *pwmc,
56                                        u8 which)
57 {
58         struct gb_pwm_deactivate_request request;
59
60         if (which > pwmc->pwm_max)
61                 return -EINVAL;
62
63         request.which = which;
64         return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DEACTIVATE,
65                                  &request, sizeof(request), NULL, 0);
66 }
67
68 static int gb_pwm_config_operation(struct gb_pwm_chip *pwmc,
69                                    u8 which, u32 duty, u32 period)
70 {
71         struct gb_pwm_config_request request;
72
73         if (which > pwmc->pwm_max)
74                 return -EINVAL;
75
76         request.which = which;
77         request.duty = cpu_to_le32(duty);
78         request.period = cpu_to_le32(period);
79         return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_CONFIG,
80                                  &request, sizeof(request), NULL, 0);
81 }
82
83
84 static int gb_pwm_set_polarity_operation(struct gb_pwm_chip *pwmc,
85                                          u8 which, u8 polarity)
86 {
87         struct gb_pwm_polarity_request request;
88
89         if (which > pwmc->pwm_max)
90                 return -EINVAL;
91
92         request.which = which;
93         request.polarity = polarity;
94         return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_POLARITY,
95                                  &request, sizeof(request), NULL, 0);
96 }
97
98 static int gb_pwm_enable_operation(struct gb_pwm_chip *pwmc,
99                                    u8 which)
100 {
101         struct gb_pwm_enable_request request;
102
103         if (which > pwmc->pwm_max)
104                 return -EINVAL;
105
106         request.which = which;
107         return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_ENABLE,
108                                  &request, sizeof(request), NULL, 0);
109 }
110
111 static int gb_pwm_disable_operation(struct gb_pwm_chip *pwmc,
112                                     u8 which)
113 {
114         struct gb_pwm_disable_request request;
115
116         if (which > pwmc->pwm_max)
117                 return -EINVAL;
118
119         request.which = which;
120         return gb_operation_sync(pwmc->connection, GB_PWM_TYPE_DISABLE,
121                                  &request, sizeof(request), NULL, 0);
122 }
123
124 static int gb_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
125 {
126         struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
127
128         return gb_pwm_activate_operation(pwmc, pwm->hwpwm);
129 };
130
131 static void gb_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
132 {
133         struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
134
135         if (test_bit(PWMF_ENABLED, &pwm->flags))
136                 dev_warn(chip->dev, "freeing PWM device without disabling\n");
137
138         gb_pwm_deactivate_operation(pwmc, pwm->hwpwm);
139 }
140
141 static int gb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
142                          int duty_ns, int period_ns)
143 {
144         struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
145
146         return gb_pwm_config_operation(pwmc, pwm->hwpwm, duty_ns, period_ns);
147 };
148
149 static int gb_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
150                                enum pwm_polarity polarity)
151 {
152         struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
153
154         return gb_pwm_set_polarity_operation(pwmc, pwm->hwpwm, polarity);
155 };
156
157 static int gb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
158 {
159         struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
160
161         return gb_pwm_enable_operation(pwmc, pwm->hwpwm);
162 };
163
164 static void gb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
165 {
166         struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip);
167
168         gb_pwm_disable_operation(pwmc, pwm->hwpwm);
169 };
170
171 static const struct pwm_ops gb_pwm_ops = {
172         .request = gb_pwm_request,
173         .free = gb_pwm_free,
174         .config = gb_pwm_config,
175         .set_polarity = gb_pwm_set_polarity,
176         .enable = gb_pwm_enable,
177         .disable = gb_pwm_disable,
178         .owner = THIS_MODULE,
179 };
180
181 static int gb_pwm_probe(struct gbphy_device *gbphy_dev,
182                         const struct gbphy_device_id *id)
183 {
184         struct gb_connection *connection;
185         struct gb_pwm_chip *pwmc;
186         struct pwm_chip *pwm;
187         int ret;
188
189         pwmc = kzalloc(sizeof(*pwmc), GFP_KERNEL);
190         if (!pwmc)
191                 return -ENOMEM;
192
193         connection = gb_connection_create(gbphy_dev->bundle,
194                                           le16_to_cpu(gbphy_dev->cport_desc->id),
195                                           NULL);
196         if (IS_ERR(connection)) {
197                 ret = PTR_ERR(connection);
198                 goto exit_pwmc_free;
199         }
200
201         pwmc->connection = connection;
202         gb_connection_set_data(connection, pwmc);
203         gb_gbphy_set_data(gbphy_dev, pwmc);
204
205         ret = gb_connection_enable(connection);
206         if (ret)
207                 goto exit_connection_destroy;
208
209         ret = gb_gbphy_get_version(connection);
210         if (ret)
211                 goto exit_connection_disable;
212
213         /* Query number of pwms present */
214         ret = gb_pwm_count_operation(pwmc);
215         if (ret)
216                 goto exit_connection_disable;
217
218         pwm = &pwmc->chip;
219
220         pwm->dev = &gbphy_dev->dev;
221         pwm->ops = &gb_pwm_ops;
222         pwm->base = -1;                 /* Allocate base dynamically */
223         pwm->npwm = pwmc->pwm_max + 1;
224         pwm->can_sleep = true;          /* FIXME */
225
226         ret = pwmchip_add(pwm);
227         if (ret) {
228                 dev_err(&gbphy_dev->dev,
229                         "failed to register PWM: %d\n", ret);
230                 goto exit_connection_disable;
231         }
232
233         return 0;
234
235 exit_connection_disable:
236         gb_connection_disable(connection);
237 exit_connection_destroy:
238         gb_connection_destroy(connection);
239 exit_pwmc_free:
240         kfree(pwmc);
241         return ret;
242 }
243
244 static void gb_pwm_remove(struct gbphy_device *gbphy_dev)
245 {
246         struct gb_pwm_chip *pwmc = gb_gbphy_get_data(gbphy_dev);
247         struct gb_connection *connection = pwmc->connection;
248
249         pwmchip_remove(&pwmc->chip);
250         gb_connection_disable(connection);
251         gb_connection_destroy(connection);
252         kfree(pwmc);
253 }
254
255 static const struct gbphy_device_id gb_pwm_id_table[] = {
256         { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_PWM) },
257         { },
258 };
259 MODULE_DEVICE_TABLE(gbphy, gb_pwm_id_table);
260
261 static struct gbphy_driver pwm_driver = {
262         .name           = "pwm",
263         .probe          = gb_pwm_probe,
264         .remove         = gb_pwm_remove,
265         .id_table       = gb_pwm_id_table,
266 };
267
268 module_gbphy_driver(pwm_driver);
269 MODULE_LICENSE("GPL v2");