1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Arche Platform driver to control APB. |
4 | * |
5 | * Copyright 2014-2015 Google Inc. |
6 | * Copyright 2014-2015 Linaro Ltd. |
7 | */ |
8 | |
9 | #include <linux/clk.h> |
10 | #include <linux/delay.h> |
11 | #include <linux/gpio/consumer.h> |
12 | #include <linux/interrupt.h> |
13 | #include <linux/of_irq.h> |
14 | #include <linux/module.h> |
15 | #include <linux/pinctrl/consumer.h> |
16 | #include <linux/platform_device.h> |
17 | #include <linux/pm.h> |
18 | #include <linux/regulator/consumer.h> |
19 | #include <linux/spinlock.h> |
20 | #include "arche_platform.h" |
21 | |
22 | static void apb_bootret_deassert(struct device *dev); |
23 | |
24 | struct arche_apb_ctrl_drvdata { |
25 | /* Control GPIO signals to and from AP <=> AP Bridges */ |
26 | struct gpio_desc *resetn; |
27 | struct gpio_desc *boot_ret; |
28 | struct gpio_desc *pwroff; |
29 | struct gpio_desc *wake_in; |
30 | struct gpio_desc *wake_out; |
31 | struct gpio_desc *pwrdn; |
32 | |
33 | enum arche_platform_state state; |
34 | bool init_disabled; |
35 | |
36 | struct regulator *vcore; |
37 | struct regulator *vio; |
38 | |
39 | struct gpio_desc *clk_en; |
40 | struct clk *clk; |
41 | |
42 | struct pinctrl *pinctrl; |
43 | struct pinctrl_state *pin_default; |
44 | |
45 | /* V2: SPI Bus control */ |
46 | struct gpio_desc *spi_en; |
47 | bool spi_en_polarity_high; |
48 | }; |
49 | |
50 | /* |
51 | * Note that these low level api's are active high |
52 | */ |
53 | static inline void deassert_reset(struct gpio_desc *gpio) |
54 | { |
55 | gpiod_set_raw_value(desc: gpio, value: 1); |
56 | } |
57 | |
58 | static inline void assert_reset(struct gpio_desc *gpio) |
59 | { |
60 | gpiod_set_raw_value(desc: gpio, value: 0); |
61 | } |
62 | |
63 | /* |
64 | * Note: Please do not modify the below sequence, as it is as per the spec |
65 | */ |
66 | static int coldboot_seq(struct platform_device *pdev) |
67 | { |
68 | struct device *dev = &pdev->dev; |
69 | struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); |
70 | int ret; |
71 | |
72 | if (apb->init_disabled || |
73 | apb->state == ARCHE_PLATFORM_STATE_ACTIVE) |
74 | return 0; |
75 | |
76 | /* Hold APB in reset state */ |
77 | assert_reset(gpio: apb->resetn); |
78 | |
79 | if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && apb->spi_en) |
80 | devm_gpiod_put(dev, desc: apb->spi_en); |
81 | |
82 | /* Enable power to APB */ |
83 | if (!IS_ERR(ptr: apb->vcore)) { |
84 | ret = regulator_enable(regulator: apb->vcore); |
85 | if (ret) { |
86 | dev_err(dev, "failed to enable core regulator\n" ); |
87 | return ret; |
88 | } |
89 | } |
90 | |
91 | if (!IS_ERR(ptr: apb->vio)) { |
92 | ret = regulator_enable(regulator: apb->vio); |
93 | if (ret) { |
94 | dev_err(dev, "failed to enable IO regulator\n" ); |
95 | return ret; |
96 | } |
97 | } |
98 | |
99 | apb_bootret_deassert(dev); |
100 | |
101 | /* On DB3 clock was not mandatory */ |
102 | if (apb->clk_en) |
103 | gpiod_set_value(desc: apb->clk_en, value: 1); |
104 | |
105 | usleep_range(min: 100, max: 200); |
106 | |
107 | /* deassert reset to APB : Active-low signal */ |
108 | deassert_reset(gpio: apb->resetn); |
109 | |
110 | apb->state = ARCHE_PLATFORM_STATE_ACTIVE; |
111 | |
112 | return 0; |
113 | } |
114 | |
115 | static int fw_flashing_seq(struct platform_device *pdev) |
116 | { |
117 | struct device *dev = &pdev->dev; |
118 | struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); |
119 | int ret; |
120 | |
121 | if (apb->init_disabled || |
122 | apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING) |
123 | return 0; |
124 | |
125 | ret = regulator_enable(regulator: apb->vcore); |
126 | if (ret) { |
127 | dev_err(dev, "failed to enable core regulator\n" ); |
128 | return ret; |
129 | } |
130 | |
131 | ret = regulator_enable(regulator: apb->vio); |
132 | if (ret) { |
133 | dev_err(dev, "failed to enable IO regulator\n" ); |
134 | return ret; |
135 | } |
136 | |
137 | if (apb->spi_en) { |
138 | unsigned long flags; |
139 | |
140 | if (apb->spi_en_polarity_high) |
141 | flags = GPIOD_OUT_HIGH; |
142 | else |
143 | flags = GPIOD_OUT_LOW; |
144 | |
145 | apb->spi_en = devm_gpiod_get(dev, con_id: "spi-en" , flags); |
146 | if (IS_ERR(ptr: apb->spi_en)) { |
147 | ret = PTR_ERR(ptr: apb->spi_en); |
148 | dev_err(dev, "Failed requesting SPI bus en GPIO: %d\n" , |
149 | ret); |
150 | return ret; |
151 | } |
152 | } |
153 | |
154 | /* for flashing device should be in reset state */ |
155 | assert_reset(gpio: apb->resetn); |
156 | apb->state = ARCHE_PLATFORM_STATE_FW_FLASHING; |
157 | |
158 | return 0; |
159 | } |
160 | |
161 | static int standby_boot_seq(struct platform_device *pdev) |
162 | { |
163 | struct device *dev = &pdev->dev; |
164 | struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); |
165 | |
166 | if (apb->init_disabled) |
167 | return 0; |
168 | |
169 | /* |
170 | * Even if it is in OFF state, |
171 | * then we do not want to change the state |
172 | */ |
173 | if (apb->state == ARCHE_PLATFORM_STATE_STANDBY || |
174 | apb->state == ARCHE_PLATFORM_STATE_OFF) |
175 | return 0; |
176 | |
177 | if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && apb->spi_en) |
178 | devm_gpiod_put(dev, desc: apb->spi_en); |
179 | |
180 | /* |
181 | * As per WDM spec, do nothing |
182 | * |
183 | * Pasted from WDM spec, |
184 | * - A falling edge on POWEROFF_L is detected (a) |
185 | * - WDM enters standby mode, but no output signals are changed |
186 | */ |
187 | |
188 | /* TODO: POWEROFF_L is input to WDM module */ |
189 | apb->state = ARCHE_PLATFORM_STATE_STANDBY; |
190 | return 0; |
191 | } |
192 | |
193 | static void poweroff_seq(struct platform_device *pdev) |
194 | { |
195 | struct device *dev = &pdev->dev; |
196 | struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); |
197 | |
198 | if (apb->init_disabled || apb->state == ARCHE_PLATFORM_STATE_OFF) |
199 | return; |
200 | |
201 | if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && apb->spi_en) |
202 | devm_gpiod_put(dev, desc: apb->spi_en); |
203 | |
204 | /* disable the clock */ |
205 | if (apb->clk_en) |
206 | gpiod_set_value(desc: apb->clk_en, value: 0); |
207 | |
208 | if (!IS_ERR(ptr: apb->vcore) && regulator_is_enabled(regulator: apb->vcore) > 0) |
209 | regulator_disable(regulator: apb->vcore); |
210 | |
211 | if (!IS_ERR(ptr: apb->vio) && regulator_is_enabled(regulator: apb->vio) > 0) |
212 | regulator_disable(regulator: apb->vio); |
213 | |
214 | /* As part of exit, put APB back in reset state */ |
215 | assert_reset(gpio: apb->resetn); |
216 | apb->state = ARCHE_PLATFORM_STATE_OFF; |
217 | |
218 | /* TODO: May have to send an event to SVC about this exit */ |
219 | } |
220 | |
221 | static void apb_bootret_deassert(struct device *dev) |
222 | { |
223 | struct arche_apb_ctrl_drvdata *apb = dev_get_drvdata(dev); |
224 | |
225 | gpiod_set_value(desc: apb->boot_ret, value: 0); |
226 | } |
227 | |
228 | int apb_ctrl_coldboot(struct device *dev) |
229 | { |
230 | return coldboot_seq(to_platform_device(dev)); |
231 | } |
232 | |
233 | int apb_ctrl_fw_flashing(struct device *dev) |
234 | { |
235 | return fw_flashing_seq(to_platform_device(dev)); |
236 | } |
237 | |
238 | int apb_ctrl_standby_boot(struct device *dev) |
239 | { |
240 | return standby_boot_seq(to_platform_device(dev)); |
241 | } |
242 | |
243 | void apb_ctrl_poweroff(struct device *dev) |
244 | { |
245 | poweroff_seq(to_platform_device(dev)); |
246 | } |
247 | |
248 | static ssize_t state_store(struct device *dev, |
249 | struct device_attribute *attr, |
250 | const char *buf, size_t count) |
251 | { |
252 | struct platform_device *pdev = to_platform_device(dev); |
253 | struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev); |
254 | int ret = 0; |
255 | bool is_disabled; |
256 | |
257 | if (sysfs_streq(s1: buf, s2: "off" )) { |
258 | if (apb->state == ARCHE_PLATFORM_STATE_OFF) |
259 | return count; |
260 | |
261 | poweroff_seq(pdev); |
262 | } else if (sysfs_streq(s1: buf, s2: "active" )) { |
263 | if (apb->state == ARCHE_PLATFORM_STATE_ACTIVE) |
264 | return count; |
265 | |
266 | poweroff_seq(pdev); |
267 | is_disabled = apb->init_disabled; |
268 | apb->init_disabled = false; |
269 | ret = coldboot_seq(pdev); |
270 | if (ret) |
271 | apb->init_disabled = is_disabled; |
272 | } else if (sysfs_streq(s1: buf, s2: "standby" )) { |
273 | if (apb->state == ARCHE_PLATFORM_STATE_STANDBY) |
274 | return count; |
275 | |
276 | ret = standby_boot_seq(pdev); |
277 | } else if (sysfs_streq(s1: buf, s2: "fw_flashing" )) { |
278 | if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING) |
279 | return count; |
280 | |
281 | /* |
282 | * First we want to make sure we power off everything |
283 | * and then enter FW flashing state |
284 | */ |
285 | poweroff_seq(pdev); |
286 | ret = fw_flashing_seq(pdev); |
287 | } else { |
288 | dev_err(dev, "unknown state\n" ); |
289 | ret = -EINVAL; |
290 | } |
291 | |
292 | return ret ? ret : count; |
293 | } |
294 | |
295 | static ssize_t state_show(struct device *dev, |
296 | struct device_attribute *attr, char *buf) |
297 | { |
298 | struct arche_apb_ctrl_drvdata *apb = dev_get_drvdata(dev); |
299 | |
300 | switch (apb->state) { |
301 | case ARCHE_PLATFORM_STATE_OFF: |
302 | return sprintf(buf, fmt: "off%s\n" , |
303 | apb->init_disabled ? ",disabled" : "" ); |
304 | case ARCHE_PLATFORM_STATE_ACTIVE: |
305 | return sprintf(buf, fmt: "active\n" ); |
306 | case ARCHE_PLATFORM_STATE_STANDBY: |
307 | return sprintf(buf, fmt: "standby\n" ); |
308 | case ARCHE_PLATFORM_STATE_FW_FLASHING: |
309 | return sprintf(buf, fmt: "fw_flashing\n" ); |
310 | default: |
311 | return sprintf(buf, fmt: "unknown state\n" ); |
312 | } |
313 | } |
314 | |
315 | static DEVICE_ATTR_RW(state); |
316 | |
317 | static int apb_ctrl_get_devtree_data(struct platform_device *pdev, |
318 | struct arche_apb_ctrl_drvdata *apb) |
319 | { |
320 | struct device *dev = &pdev->dev; |
321 | int ret; |
322 | |
323 | apb->resetn = devm_gpiod_get(dev, con_id: "reset" , flags: GPIOD_OUT_LOW); |
324 | if (IS_ERR(ptr: apb->resetn)) { |
325 | ret = PTR_ERR(ptr: apb->resetn); |
326 | dev_err(dev, "Failed requesting reset GPIO: %d\n" , ret); |
327 | return ret; |
328 | } |
329 | |
330 | apb->boot_ret = devm_gpiod_get(dev, con_id: "boot-ret" , flags: GPIOD_OUT_LOW); |
331 | if (IS_ERR(ptr: apb->boot_ret)) { |
332 | ret = PTR_ERR(ptr: apb->boot_ret); |
333 | dev_err(dev, "Failed requesting bootret GPIO: %d\n" , ret); |
334 | return ret; |
335 | } |
336 | |
337 | /* It's not mandatory to support power management interface */ |
338 | apb->pwroff = devm_gpiod_get_optional(dev, con_id: "pwr-off" , flags: GPIOD_IN); |
339 | if (IS_ERR(ptr: apb->pwroff)) { |
340 | ret = PTR_ERR(ptr: apb->pwroff); |
341 | dev_err(dev, "Failed requesting pwroff_n GPIO: %d\n" , ret); |
342 | return ret; |
343 | } |
344 | |
345 | /* Do not make clock mandatory as of now (for DB3) */ |
346 | apb->clk_en = devm_gpiod_get_optional(dev, con_id: "clock-en" , flags: GPIOD_OUT_LOW); |
347 | if (IS_ERR(ptr: apb->clk_en)) { |
348 | ret = PTR_ERR(ptr: apb->clk_en); |
349 | dev_err(dev, "Failed requesting APB clock en GPIO: %d\n" , ret); |
350 | return ret; |
351 | } |
352 | |
353 | apb->pwrdn = devm_gpiod_get(dev, con_id: "pwr-down" , flags: GPIOD_OUT_LOW); |
354 | if (IS_ERR(ptr: apb->pwrdn)) { |
355 | ret = PTR_ERR(ptr: apb->pwrdn); |
356 | dev_warn(dev, "Failed requesting power down GPIO: %d\n" , ret); |
357 | return ret; |
358 | } |
359 | |
360 | /* Regulators are optional, as we may have fixed supply coming in */ |
361 | apb->vcore = devm_regulator_get(dev, id: "vcore" ); |
362 | if (IS_ERR(ptr: apb->vcore)) |
363 | dev_warn(dev, "no core regulator found\n" ); |
364 | |
365 | apb->vio = devm_regulator_get(dev, id: "vio" ); |
366 | if (IS_ERR(ptr: apb->vio)) |
367 | dev_warn(dev, "no IO regulator found\n" ); |
368 | |
369 | apb->pinctrl = devm_pinctrl_get(dev: &pdev->dev); |
370 | if (IS_ERR(ptr: apb->pinctrl)) { |
371 | dev_err(&pdev->dev, "could not get pinctrl handle\n" ); |
372 | return PTR_ERR(ptr: apb->pinctrl); |
373 | } |
374 | apb->pin_default = pinctrl_lookup_state(p: apb->pinctrl, name: "default" ); |
375 | if (IS_ERR(ptr: apb->pin_default)) { |
376 | dev_err(&pdev->dev, "could not get default pin state\n" ); |
377 | return PTR_ERR(ptr: apb->pin_default); |
378 | } |
379 | |
380 | /* Only applicable for platform >= V2 */ |
381 | if (of_property_read_bool(np: pdev->dev.of_node, propname: "gb,spi-en-active-high" )) |
382 | apb->spi_en_polarity_high = true; |
383 | |
384 | return 0; |
385 | } |
386 | |
387 | static int arche_apb_ctrl_probe(struct platform_device *pdev) |
388 | { |
389 | int ret; |
390 | struct arche_apb_ctrl_drvdata *apb; |
391 | struct device *dev = &pdev->dev; |
392 | |
393 | apb = devm_kzalloc(dev: &pdev->dev, size: sizeof(*apb), GFP_KERNEL); |
394 | if (!apb) |
395 | return -ENOMEM; |
396 | |
397 | ret = apb_ctrl_get_devtree_data(pdev, apb); |
398 | if (ret) { |
399 | dev_err(dev, "failed to get apb devicetree data %d\n" , ret); |
400 | return ret; |
401 | } |
402 | |
403 | /* Initially set APB to OFF state */ |
404 | apb->state = ARCHE_PLATFORM_STATE_OFF; |
405 | /* Check whether device needs to be enabled on boot */ |
406 | if (of_property_read_bool(np: pdev->dev.of_node, propname: "arche,init-disable" )) |
407 | apb->init_disabled = true; |
408 | |
409 | platform_set_drvdata(pdev, data: apb); |
410 | |
411 | /* Create sysfs interface to allow user to change state dynamically */ |
412 | ret = device_create_file(device: dev, entry: &dev_attr_state); |
413 | if (ret) { |
414 | dev_err(dev, "failed to create state file in sysfs\n" ); |
415 | return ret; |
416 | } |
417 | |
418 | dev_info(&pdev->dev, "Device registered successfully\n" ); |
419 | return 0; |
420 | } |
421 | |
422 | static void arche_apb_ctrl_remove(struct platform_device *pdev) |
423 | { |
424 | device_remove_file(dev: &pdev->dev, attr: &dev_attr_state); |
425 | poweroff_seq(pdev); |
426 | platform_set_drvdata(pdev, NULL); |
427 | } |
428 | |
429 | static int __maybe_unused arche_apb_ctrl_suspend(struct device *dev) |
430 | { |
431 | /* |
432 | * If timing profile permits, we may shutdown bridge |
433 | * completely |
434 | * |
435 | * TODO: sequence ?? |
436 | * |
437 | * Also, need to make sure we meet precondition for unipro suspend |
438 | * Precondition: Definition ??? |
439 | */ |
440 | return 0; |
441 | } |
442 | |
443 | static int __maybe_unused arche_apb_ctrl_resume(struct device *dev) |
444 | { |
445 | /* |
446 | * At least for ES2 we have to meet the delay requirement between |
447 | * unipro switch and AP bridge init, depending on whether bridge is in |
448 | * OFF state or standby state. |
449 | * |
450 | * Based on whether bridge is in standby or OFF state we may have to |
451 | * assert multiple signals. Please refer to WDM spec, for more info. |
452 | * |
453 | */ |
454 | return 0; |
455 | } |
456 | |
457 | static void arche_apb_ctrl_shutdown(struct platform_device *pdev) |
458 | { |
459 | apb_ctrl_poweroff(dev: &pdev->dev); |
460 | } |
461 | |
462 | static SIMPLE_DEV_PM_OPS(arche_apb_ctrl_pm_ops, arche_apb_ctrl_suspend, |
463 | arche_apb_ctrl_resume); |
464 | |
465 | static const struct of_device_id arche_apb_ctrl_of_match[] = { |
466 | { .compatible = "usbffff,2" , }, |
467 | { }, |
468 | }; |
469 | |
470 | static struct platform_driver arche_apb_ctrl_device_driver = { |
471 | .probe = arche_apb_ctrl_probe, |
472 | .remove_new = arche_apb_ctrl_remove, |
473 | .shutdown = arche_apb_ctrl_shutdown, |
474 | .driver = { |
475 | .name = "arche-apb-ctrl" , |
476 | .pm = &arche_apb_ctrl_pm_ops, |
477 | .of_match_table = arche_apb_ctrl_of_match, |
478 | } |
479 | }; |
480 | |
481 | int __init arche_apb_init(void) |
482 | { |
483 | return platform_driver_register(&arche_apb_ctrl_device_driver); |
484 | } |
485 | |
486 | void __exit arche_apb_exit(void) |
487 | { |
488 | platform_driver_unregister(&arche_apb_ctrl_device_driver); |
489 | } |
490 | |