1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * PWM Greybus driver. |
4 | * |
5 | * Copyright 2014 Google Inc. |
6 | * Copyright 2014 Linaro Ltd. |
7 | */ |
8 | |
9 | #include <linux/kernel.h> |
10 | #include <linux/module.h> |
11 | #include <linux/slab.h> |
12 | #include <linux/pwm.h> |
13 | #include <linux/greybus.h> |
14 | |
15 | #include "gbphy.h" |
16 | |
17 | struct gb_pwm_chip { |
18 | struct gb_connection *connection; |
19 | struct pwm_chip chip; |
20 | }; |
21 | |
22 | static inline struct gb_pwm_chip *pwm_chip_to_gb_pwm_chip(struct pwm_chip *chip) |
23 | { |
24 | return container_of(chip, struct gb_pwm_chip, chip); |
25 | } |
26 | |
27 | static int gb_pwm_get_npwm(struct gb_connection *connection) |
28 | { |
29 | struct gb_pwm_count_response response; |
30 | int ret; |
31 | |
32 | ret = gb_operation_sync(connection, GB_PWM_TYPE_PWM_COUNT, |
33 | NULL, request_size: 0, response: &response, response_size: sizeof(response)); |
34 | if (ret) |
35 | return ret; |
36 | |
37 | /* |
38 | * The request returns the highest allowed PWM id parameter. So add one |
39 | * to get the number of PWMs. |
40 | */ |
41 | return response.count + 1; |
42 | } |
43 | |
44 | static int gb_pwm_activate_operation(struct pwm_chip *chip, u8 which) |
45 | { |
46 | struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); |
47 | struct gb_pwm_activate_request request; |
48 | struct gbphy_device *gbphy_dev; |
49 | int ret; |
50 | |
51 | request.which = which; |
52 | |
53 | gbphy_dev = to_gbphy_dev(pwmchip_parent(chip)); |
54 | ret = gbphy_runtime_get_sync(gbphy_dev); |
55 | if (ret) |
56 | return ret; |
57 | |
58 | ret = gb_operation_sync(connection: pwmc->connection, GB_PWM_TYPE_ACTIVATE, |
59 | request: &request, request_size: sizeof(request), NULL, response_size: 0); |
60 | |
61 | gbphy_runtime_put_autosuspend(gbphy_dev); |
62 | |
63 | return ret; |
64 | } |
65 | |
66 | static int gb_pwm_deactivate_operation(struct pwm_chip *chip, u8 which) |
67 | { |
68 | struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); |
69 | struct gb_pwm_deactivate_request request; |
70 | struct gbphy_device *gbphy_dev; |
71 | int ret; |
72 | |
73 | request.which = which; |
74 | |
75 | gbphy_dev = to_gbphy_dev(pwmchip_parent(chip)); |
76 | ret = gbphy_runtime_get_sync(gbphy_dev); |
77 | if (ret) |
78 | return ret; |
79 | |
80 | ret = gb_operation_sync(connection: pwmc->connection, GB_PWM_TYPE_DEACTIVATE, |
81 | request: &request, request_size: sizeof(request), NULL, response_size: 0); |
82 | |
83 | gbphy_runtime_put_autosuspend(gbphy_dev); |
84 | |
85 | return ret; |
86 | } |
87 | |
88 | static int gb_pwm_config_operation(struct pwm_chip *chip, |
89 | u8 which, u32 duty, u32 period) |
90 | { |
91 | struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); |
92 | struct gb_pwm_config_request request; |
93 | struct gbphy_device *gbphy_dev; |
94 | int ret; |
95 | |
96 | request.which = which; |
97 | request.duty = cpu_to_le32(duty); |
98 | request.period = cpu_to_le32(period); |
99 | |
100 | gbphy_dev = to_gbphy_dev(pwmchip_parent(chip)); |
101 | ret = gbphy_runtime_get_sync(gbphy_dev); |
102 | if (ret) |
103 | return ret; |
104 | |
105 | ret = gb_operation_sync(connection: pwmc->connection, GB_PWM_TYPE_CONFIG, |
106 | request: &request, request_size: sizeof(request), NULL, response_size: 0); |
107 | |
108 | gbphy_runtime_put_autosuspend(gbphy_dev); |
109 | |
110 | return ret; |
111 | } |
112 | |
113 | static int gb_pwm_set_polarity_operation(struct pwm_chip *chip, |
114 | u8 which, u8 polarity) |
115 | { |
116 | struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); |
117 | struct gb_pwm_polarity_request request; |
118 | struct gbphy_device *gbphy_dev; |
119 | int ret; |
120 | |
121 | request.which = which; |
122 | request.polarity = polarity; |
123 | |
124 | gbphy_dev = to_gbphy_dev(pwmchip_parent(chip)); |
125 | ret = gbphy_runtime_get_sync(gbphy_dev); |
126 | if (ret) |
127 | return ret; |
128 | |
129 | ret = gb_operation_sync(connection: pwmc->connection, GB_PWM_TYPE_POLARITY, |
130 | request: &request, request_size: sizeof(request), NULL, response_size: 0); |
131 | |
132 | gbphy_runtime_put_autosuspend(gbphy_dev); |
133 | |
134 | return ret; |
135 | } |
136 | |
137 | static int gb_pwm_enable_operation(struct pwm_chip *chip, u8 which) |
138 | { |
139 | struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); |
140 | struct gb_pwm_enable_request request; |
141 | struct gbphy_device *gbphy_dev; |
142 | int ret; |
143 | |
144 | request.which = which; |
145 | |
146 | gbphy_dev = to_gbphy_dev(pwmchip_parent(chip)); |
147 | ret = gbphy_runtime_get_sync(gbphy_dev); |
148 | if (ret) |
149 | return ret; |
150 | |
151 | ret = gb_operation_sync(connection: pwmc->connection, GB_PWM_TYPE_ENABLE, |
152 | request: &request, request_size: sizeof(request), NULL, response_size: 0); |
153 | if (ret) |
154 | gbphy_runtime_put_autosuspend(gbphy_dev); |
155 | |
156 | return ret; |
157 | } |
158 | |
159 | static int gb_pwm_disable_operation(struct pwm_chip *chip, u8 which) |
160 | { |
161 | struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); |
162 | struct gb_pwm_disable_request request; |
163 | struct gbphy_device *gbphy_dev; |
164 | int ret; |
165 | |
166 | request.which = which; |
167 | |
168 | ret = gb_operation_sync(connection: pwmc->connection, GB_PWM_TYPE_DISABLE, |
169 | request: &request, request_size: sizeof(request), NULL, response_size: 0); |
170 | |
171 | gbphy_dev = to_gbphy_dev(pwmchip_parent(chip)); |
172 | gbphy_runtime_put_autosuspend(gbphy_dev); |
173 | |
174 | return ret; |
175 | } |
176 | |
177 | static int gb_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) |
178 | { |
179 | return gb_pwm_activate_operation(chip, which: pwm->hwpwm); |
180 | }; |
181 | |
182 | static void gb_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) |
183 | { |
184 | if (pwm_is_enabled(pwm)) |
185 | dev_warn(pwmchip_parent(chip), "freeing PWM device without disabling\n" ); |
186 | |
187 | gb_pwm_deactivate_operation(chip, which: pwm->hwpwm); |
188 | } |
189 | |
190 | static int gb_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
191 | const struct pwm_state *state) |
192 | { |
193 | int err; |
194 | bool enabled = pwm->state.enabled; |
195 | u64 period = state->period; |
196 | u64 duty_cycle = state->duty_cycle; |
197 | |
198 | /* Set polarity */ |
199 | if (state->polarity != pwm->state.polarity) { |
200 | if (enabled) { |
201 | gb_pwm_disable_operation(chip, which: pwm->hwpwm); |
202 | enabled = false; |
203 | } |
204 | err = gb_pwm_set_polarity_operation(chip, which: pwm->hwpwm, polarity: state->polarity); |
205 | if (err) |
206 | return err; |
207 | } |
208 | |
209 | if (!state->enabled) { |
210 | if (enabled) |
211 | gb_pwm_disable_operation(chip, which: pwm->hwpwm); |
212 | return 0; |
213 | } |
214 | |
215 | /* |
216 | * Set period and duty cycle |
217 | * |
218 | * PWM privodes 64-bit period and duty_cycle, but greybus only accepts |
219 | * 32-bit, so their values have to be limited to U32_MAX. |
220 | */ |
221 | if (period > U32_MAX) |
222 | period = U32_MAX; |
223 | |
224 | if (duty_cycle > period) |
225 | duty_cycle = period; |
226 | |
227 | err = gb_pwm_config_operation(chip, which: pwm->hwpwm, duty: duty_cycle, period); |
228 | if (err) |
229 | return err; |
230 | |
231 | /* enable/disable */ |
232 | if (!enabled) |
233 | return gb_pwm_enable_operation(chip, which: pwm->hwpwm); |
234 | |
235 | return 0; |
236 | } |
237 | |
238 | static const struct pwm_ops gb_pwm_ops = { |
239 | .request = gb_pwm_request, |
240 | .free = gb_pwm_free, |
241 | .apply = gb_pwm_apply, |
242 | }; |
243 | |
244 | static int gb_pwm_probe(struct gbphy_device *gbphy_dev, |
245 | const struct gbphy_device_id *id) |
246 | { |
247 | struct gb_connection *connection; |
248 | struct gb_pwm_chip *pwmc; |
249 | struct pwm_chip *chip; |
250 | int ret, npwm; |
251 | |
252 | connection = gb_connection_create(bundle: gbphy_dev->bundle, |
253 | le16_to_cpu(gbphy_dev->cport_desc->id), |
254 | NULL); |
255 | if (IS_ERR(ptr: connection)) |
256 | return PTR_ERR(ptr: connection); |
257 | |
258 | ret = gb_connection_enable(connection); |
259 | if (ret) |
260 | goto exit_connection_destroy; |
261 | |
262 | /* Query number of pwms present */ |
263 | ret = gb_pwm_get_npwm(connection); |
264 | if (ret < 0) |
265 | goto exit_connection_disable; |
266 | npwm = ret; |
267 | |
268 | chip = pwmchip_alloc(parent: &gbphy_dev->dev, npwm, sizeof_priv: sizeof(*pwmc)); |
269 | if (IS_ERR(ptr: chip)) { |
270 | ret = PTR_ERR(ptr: chip); |
271 | goto exit_connection_disable; |
272 | } |
273 | gb_gbphy_set_data(gdev: gbphy_dev, data: chip); |
274 | |
275 | pwmc = pwm_chip_to_gb_pwm_chip(chip); |
276 | pwmc->connection = connection; |
277 | |
278 | chip->ops = &gb_pwm_ops; |
279 | |
280 | ret = pwmchip_add(chip); |
281 | if (ret) { |
282 | dev_err(&gbphy_dev->dev, |
283 | "failed to register PWM: %d\n" , ret); |
284 | goto exit_pwmchip_put; |
285 | } |
286 | |
287 | gbphy_runtime_put_autosuspend(gbphy_dev); |
288 | return 0; |
289 | |
290 | exit_pwmchip_put: |
291 | pwmchip_put(chip); |
292 | exit_connection_disable: |
293 | gb_connection_disable(connection); |
294 | exit_connection_destroy: |
295 | gb_connection_destroy(connection); |
296 | return ret; |
297 | } |
298 | |
299 | static void gb_pwm_remove(struct gbphy_device *gbphy_dev) |
300 | { |
301 | struct pwm_chip *chip = gb_gbphy_get_data(gdev: gbphy_dev); |
302 | struct gb_pwm_chip *pwmc = pwm_chip_to_gb_pwm_chip(chip); |
303 | struct gb_connection *connection = pwmc->connection; |
304 | int ret; |
305 | |
306 | ret = gbphy_runtime_get_sync(gbphy_dev); |
307 | if (ret) |
308 | gbphy_runtime_get_noresume(gbphy_dev); |
309 | |
310 | pwmchip_remove(chip); |
311 | pwmchip_put(chip); |
312 | gb_connection_disable(connection); |
313 | gb_connection_destroy(connection); |
314 | } |
315 | |
316 | static const struct gbphy_device_id gb_pwm_id_table[] = { |
317 | { GBPHY_PROTOCOL(GREYBUS_PROTOCOL_PWM) }, |
318 | { }, |
319 | }; |
320 | MODULE_DEVICE_TABLE(gbphy, gb_pwm_id_table); |
321 | |
322 | static struct gbphy_driver pwm_driver = { |
323 | .name = "pwm" , |
324 | .probe = gb_pwm_probe, |
325 | .remove = gb_pwm_remove, |
326 | .id_table = gb_pwm_id_table, |
327 | }; |
328 | |
329 | module_gbphy_driver(pwm_driver); |
330 | MODULE_LICENSE("GPL v2" ); |
331 | |