]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/greybus/pwm.c
greybus: gbphy: Remove protocol specific version handling
[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         /* Query number of pwms present */
210         ret = gb_pwm_count_operation(pwmc);
211         if (ret)
212                 goto exit_connection_disable;
213
214         pwm = &pwmc->chip;
215
216         pwm->dev = &gbphy_dev->dev;
217         pwm->ops = &gb_pwm_ops;
218         pwm->base = -1;                 /* Allocate base dynamically */
219         pwm->npwm = pwmc->pwm_max + 1;
220         pwm->can_sleep = true;          /* FIXME */
221
222         ret = pwmchip_add(pwm);
223         if (ret) {
224                 dev_err(&gbphy_dev->dev,
225                         "failed to register PWM: %d\n", ret);
226                 goto exit_connection_disable;
227         }
228
229         return 0;
230
231 exit_connection_disable:
232         gb_connection_disable(connection);
233 exit_connection_destroy:
234         gb_connection_destroy(connection);
235 exit_pwmc_free:
236         kfree(pwmc);
237         return ret;
238 }
239
240 static void gb_pwm_remove(struct gbphy_device *gbphy_dev)
241 {
242         struct gb_pwm_chip *pwmc = gb_gbphy_get_data(gbphy_dev);
243         struct gb_connection *connection = pwmc->connection;
244
245         pwmchip_remove(&pwmc->chip);
246         gb_connection_disable(connection);
247         gb_connection_destroy(connection);
248         kfree(pwmc);
249 }
250
251 static const struct gbphy_device_id gb_pwm_id_table[] = {
252         { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_PWM) },
253         { },
254 };
255 MODULE_DEVICE_TABLE(gbphy, gb_pwm_id_table);
256
257 static struct gbphy_driver pwm_driver = {
258         .name           = "pwm",
259         .probe          = gb_pwm_probe,
260         .remove         = gb_pwm_remove,
261         .id_table       = gb_pwm_id_table,
262 };
263
264 module_gbphy_driver(pwm_driver);
265 MODULE_LICENSE("GPL v2");