1
2
3
4
5
6
7
8
9#include <linux/clk.h>
10#include <linux/delay.h>
11#include <linux/gpio/consumer.h>
12#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/of_platform.h>
15#include <linux/pinctrl/consumer.h>
16#include <linux/platform_device.h>
17#include <linux/pm.h>
18#include <linux/interrupt.h>
19#include <linux/irq.h>
20#include <linux/suspend.h>
21#include <linux/time.h>
22#include <linux/greybus.h>
23#include "arche_platform.h"
24
25#if IS_ENABLED(CONFIG_USB_HSIC_USB3613)
26#include <linux/usb/usb3613.h>
27#else
28static inline int usb3613_hub_mode_ctrl(bool unused)
29{
30 return 0;
31}
32#endif
33
34#define WD_COLDBOOT_PULSE_WIDTH_MS 30
35
36enum svc_wakedetect_state {
37 WD_STATE_IDLE,
38 WD_STATE_BOOT_INIT,
39 WD_STATE_COLDBOOT_TRIG,
40 WD_STATE_STANDBYBOOT_TRIG,
41 WD_STATE_COLDBOOT_START,
42 WD_STATE_STANDBYBOOT_START,
43};
44
45struct arche_platform_drvdata {
46
47 struct gpio_desc *svc_reset;
48 bool is_reset_act_hi;
49 struct gpio_desc *svc_sysboot;
50 struct gpio_desc *wake_detect;
51
52 enum arche_platform_state state;
53
54 struct gpio_desc *svc_refclk_req;
55 struct clk *svc_ref_clk;
56
57 struct pinctrl *pinctrl;
58 struct pinctrl_state *pin_default;
59
60 int num_apbs;
61
62 enum svc_wakedetect_state wake_detect_state;
63 int wake_detect_irq;
64 spinlock_t wake_lock;
65 struct mutex platform_state_mutex;
66 unsigned long wake_detect_start;
67 struct notifier_block pm_notifier;
68
69 struct device *dev;
70};
71
72
73static void arche_platform_set_state(struct arche_platform_drvdata *arche_pdata,
74 enum arche_platform_state state)
75{
76 arche_pdata->state = state;
77}
78
79
80static void arche_platform_set_wake_detect_state(struct arche_platform_drvdata *arche_pdata,
81 enum svc_wakedetect_state state)
82{
83 arche_pdata->wake_detect_state = state;
84}
85
86static inline void svc_reset_onoff(struct gpio_desc *gpio, bool onoff)
87{
88 gpiod_set_raw_value(gpio, onoff);
89}
90
91static int apb_cold_boot(struct device *dev, void *data)
92{
93 int ret;
94
95 ret = apb_ctrl_coldboot(dev);
96 if (ret)
97 dev_warn(dev, "failed to coldboot\n");
98
99
100 return 0;
101}
102
103static int apb_poweroff(struct device *dev, void *data)
104{
105 apb_ctrl_poweroff(dev);
106
107
108 if (usb3613_hub_mode_ctrl(false))
109 dev_warn(dev, "failed to control hub device\n");
110
111 return 0;
112}
113
114static void arche_platform_wd_irq_en(struct arche_platform_drvdata *arche_pdata)
115{
116
117 enable_irq(arche_pdata->wake_detect_irq);
118}
119
120static irqreturn_t arche_platform_wd_irq_thread(int irq, void *devid)
121{
122 struct arche_platform_drvdata *arche_pdata = devid;
123 unsigned long flags;
124
125 spin_lock_irqsave(&arche_pdata->wake_lock, flags);
126 if (arche_pdata->wake_detect_state != WD_STATE_COLDBOOT_TRIG) {
127
128 spin_unlock_irqrestore(&arche_pdata->wake_lock, flags);
129 return IRQ_HANDLED;
130 }
131
132 arche_platform_set_wake_detect_state(arche_pdata,
133 WD_STATE_COLDBOOT_START);
134 spin_unlock_irqrestore(&arche_pdata->wake_lock, flags);
135
136
137 device_for_each_child(arche_pdata->dev, NULL, apb_poweroff);
138
139
140 device_for_each_child(arche_pdata->dev, NULL, apb_cold_boot);
141
142
143 if (usb3613_hub_mode_ctrl(true))
144 dev_warn(arche_pdata->dev, "failed to control hub device\n");
145
146 spin_lock_irqsave(&arche_pdata->wake_lock, flags);
147 arche_platform_set_wake_detect_state(arche_pdata, WD_STATE_IDLE);
148 spin_unlock_irqrestore(&arche_pdata->wake_lock, flags);
149
150 return IRQ_HANDLED;
151}
152
153static irqreturn_t arche_platform_wd_irq(int irq, void *devid)
154{
155 struct arche_platform_drvdata *arche_pdata = devid;
156 unsigned long flags;
157
158 spin_lock_irqsave(&arche_pdata->wake_lock, flags);
159
160 if (gpiod_get_value(arche_pdata->wake_detect)) {
161
162
163
164
165
166
167
168 if (arche_pdata->wake_detect_state == WD_STATE_BOOT_INIT) {
169 if (time_before(jiffies,
170 arche_pdata->wake_detect_start +
171 msecs_to_jiffies(WD_COLDBOOT_PULSE_WIDTH_MS))) {
172 arche_platform_set_wake_detect_state(arche_pdata,
173 WD_STATE_IDLE);
174 } else {
175
176
177
178
179 if (arche_pdata->wake_detect_state !=
180 WD_STATE_COLDBOOT_START) {
181 arche_platform_set_wake_detect_state(arche_pdata,
182 WD_STATE_COLDBOOT_TRIG);
183 spin_unlock_irqrestore(&arche_pdata->wake_lock,
184 flags);
185 return IRQ_WAKE_THREAD;
186 }
187 }
188 }
189 } else {
190
191 if (arche_pdata->wake_detect_state == WD_STATE_IDLE) {
192 arche_pdata->wake_detect_start = jiffies;
193
194
195
196
197
198
199
200 arche_platform_set_wake_detect_state(arche_pdata,
201 WD_STATE_BOOT_INIT);
202 }
203 }
204
205 spin_unlock_irqrestore(&arche_pdata->wake_lock, flags);
206
207 return IRQ_HANDLED;
208}
209
210
211
212
213static int
214arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdata)
215{
216 int ret;
217
218 if (arche_pdata->state == ARCHE_PLATFORM_STATE_ACTIVE)
219 return 0;
220
221 dev_info(arche_pdata->dev, "Booting from cold boot state\n");
222
223 svc_reset_onoff(arche_pdata->svc_reset, arche_pdata->is_reset_act_hi);
224
225 gpiod_set_value(arche_pdata->svc_sysboot, 0);
226 usleep_range(100, 200);
227
228 ret = clk_prepare_enable(arche_pdata->svc_ref_clk);
229 if (ret) {
230 dev_err(arche_pdata->dev, "failed to enable svc_ref_clk: %d\n",
231 ret);
232 return ret;
233 }
234
235
236 svc_reset_onoff(arche_pdata->svc_reset, !arche_pdata->is_reset_act_hi);
237
238 arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_ACTIVE);
239
240 return 0;
241}
242
243
244
245
246static int
247arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_pdata)
248{
249 int ret;
250
251 if (arche_pdata->state == ARCHE_PLATFORM_STATE_FW_FLASHING)
252 return 0;
253
254 dev_info(arche_pdata->dev, "Switching to FW flashing state\n");
255
256 svc_reset_onoff(arche_pdata->svc_reset, arche_pdata->is_reset_act_hi);
257
258 gpiod_set_value(arche_pdata->svc_sysboot, 1);
259
260 usleep_range(100, 200);
261
262 ret = clk_prepare_enable(arche_pdata->svc_ref_clk);
263 if (ret) {
264 dev_err(arche_pdata->dev, "failed to enable svc_ref_clk: %d\n",
265 ret);
266 return ret;
267 }
268
269 svc_reset_onoff(arche_pdata->svc_reset, !arche_pdata->is_reset_act_hi);
270
271 arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_FW_FLASHING);
272
273 return 0;
274}
275
276
277
278
279static void
280arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pdata)
281{
282 unsigned long flags;
283
284 if (arche_pdata->state == ARCHE_PLATFORM_STATE_OFF)
285 return;
286
287
288 if (arche_pdata->state != ARCHE_PLATFORM_STATE_FW_FLASHING) {
289 disable_irq(arche_pdata->wake_detect_irq);
290
291 spin_lock_irqsave(&arche_pdata->wake_lock, flags);
292 arche_platform_set_wake_detect_state(arche_pdata,
293 WD_STATE_IDLE);
294 spin_unlock_irqrestore(&arche_pdata->wake_lock, flags);
295 }
296
297 clk_disable_unprepare(arche_pdata->svc_ref_clk);
298
299
300 svc_reset_onoff(arche_pdata->svc_reset, arche_pdata->is_reset_act_hi);
301
302 arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_OFF);
303}
304
305static ssize_t state_store(struct device *dev,
306 struct device_attribute *attr,
307 const char *buf, size_t count)
308{
309 struct arche_platform_drvdata *arche_pdata = dev_get_drvdata(dev);
310 int ret = 0;
311
312 mutex_lock(&arche_pdata->platform_state_mutex);
313
314 if (sysfs_streq(buf, "off")) {
315 if (arche_pdata->state == ARCHE_PLATFORM_STATE_OFF)
316 goto exit;
317
318
319 device_for_each_child(arche_pdata->dev, NULL, apb_poweroff);
320
321 arche_platform_poweroff_seq(arche_pdata);
322
323 } else if (sysfs_streq(buf, "active")) {
324 if (arche_pdata->state == ARCHE_PLATFORM_STATE_ACTIVE)
325 goto exit;
326
327
328
329
330 device_for_each_child(arche_pdata->dev, NULL, apb_poweroff);
331 arche_platform_poweroff_seq(arche_pdata);
332
333 arche_platform_wd_irq_en(arche_pdata);
334 ret = arche_platform_coldboot_seq(arche_pdata);
335 if (ret)
336 goto exit;
337
338 } else if (sysfs_streq(buf, "standby")) {
339 if (arche_pdata->state == ARCHE_PLATFORM_STATE_STANDBY)
340 goto exit;
341
342 dev_warn(arche_pdata->dev, "standby state not supported\n");
343 } else if (sysfs_streq(buf, "fw_flashing")) {
344 if (arche_pdata->state == ARCHE_PLATFORM_STATE_FW_FLASHING)
345 goto exit;
346
347
348
349
350
351
352
353
354 arche_platform_poweroff_seq(arche_pdata);
355
356 ret = arche_platform_fw_flashing_seq(arche_pdata);
357 if (ret)
358 goto exit;
359 } else {
360 dev_err(arche_pdata->dev, "unknown state\n");
361 ret = -EINVAL;
362 }
363
364exit:
365 mutex_unlock(&arche_pdata->platform_state_mutex);
366 return ret ? ret : count;
367}
368
369static ssize_t state_show(struct device *dev,
370 struct device_attribute *attr, char *buf)
371{
372 struct arche_platform_drvdata *arche_pdata = dev_get_drvdata(dev);
373
374 switch (arche_pdata->state) {
375 case ARCHE_PLATFORM_STATE_OFF:
376 return sprintf(buf, "off\n");
377 case ARCHE_PLATFORM_STATE_ACTIVE:
378 return sprintf(buf, "active\n");
379 case ARCHE_PLATFORM_STATE_STANDBY:
380 return sprintf(buf, "standby\n");
381 case ARCHE_PLATFORM_STATE_FW_FLASHING:
382 return sprintf(buf, "fw_flashing\n");
383 default:
384 return sprintf(buf, "unknown state\n");
385 }
386}
387
388static DEVICE_ATTR_RW(state);
389
390static int arche_platform_pm_notifier(struct notifier_block *notifier,
391 unsigned long pm_event, void *unused)
392{
393 struct arche_platform_drvdata *arche_pdata =
394 container_of(notifier, struct arche_platform_drvdata,
395 pm_notifier);
396 int ret = NOTIFY_DONE;
397
398 mutex_lock(&arche_pdata->platform_state_mutex);
399 switch (pm_event) {
400 case PM_SUSPEND_PREPARE:
401 if (arche_pdata->state != ARCHE_PLATFORM_STATE_ACTIVE) {
402 ret = NOTIFY_STOP;
403 break;
404 }
405 device_for_each_child(arche_pdata->dev, NULL, apb_poweroff);
406 arche_platform_poweroff_seq(arche_pdata);
407 break;
408 case PM_POST_SUSPEND:
409 if (arche_pdata->state != ARCHE_PLATFORM_STATE_OFF)
410 break;
411
412 arche_platform_wd_irq_en(arche_pdata);
413 arche_platform_coldboot_seq(arche_pdata);
414 break;
415 default:
416 break;
417 }
418 mutex_unlock(&arche_pdata->platform_state_mutex);
419
420 return ret;
421}
422
423static int arche_platform_probe(struct platform_device *pdev)
424{
425 struct arche_platform_drvdata *arche_pdata;
426 struct device *dev = &pdev->dev;
427 struct device_node *np = dev->of_node;
428 int ret;
429 unsigned int flags;
430
431 arche_pdata = devm_kzalloc(&pdev->dev, sizeof(*arche_pdata),
432 GFP_KERNEL);
433 if (!arche_pdata)
434 return -ENOMEM;
435
436
437 arche_pdata->is_reset_act_hi = of_property_read_bool(np,
438 "svc,reset-active-high");
439 if (arche_pdata->is_reset_act_hi)
440 flags = GPIOD_OUT_HIGH;
441 else
442 flags = GPIOD_OUT_LOW;
443
444 arche_pdata->svc_reset = devm_gpiod_get(dev, "svc,reset", flags);
445 if (IS_ERR(arche_pdata->svc_reset)) {
446 ret = PTR_ERR(arche_pdata->svc_reset);
447 dev_err(dev, "failed to request svc-reset GPIO: %d\n", ret);
448 return ret;
449 }
450 arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_OFF);
451
452 arche_pdata->svc_sysboot = devm_gpiod_get(dev, "svc,sysboot",
453 GPIOD_OUT_LOW);
454 if (IS_ERR(arche_pdata->svc_sysboot)) {
455 ret = PTR_ERR(arche_pdata->svc_sysboot);
456 dev_err(dev, "failed to request sysboot0 GPIO: %d\n", ret);
457 return ret;
458 }
459
460
461 arche_pdata->svc_refclk_req = devm_gpiod_get(dev, "svc,refclk-req",
462 GPIOD_IN);
463 if (IS_ERR(arche_pdata->svc_refclk_req)) {
464 ret = PTR_ERR(arche_pdata->svc_refclk_req);
465 dev_err(dev, "failed to request svc-clk-req GPIO: %d\n", ret);
466 return ret;
467 }
468
469
470 arche_pdata->svc_ref_clk = devm_clk_get(dev, "svc_ref_clk");
471 if (IS_ERR(arche_pdata->svc_ref_clk)) {
472 ret = PTR_ERR(arche_pdata->svc_ref_clk);
473 dev_err(dev, "failed to get svc_ref_clk: %d\n", ret);
474 return ret;
475 }
476
477 platform_set_drvdata(pdev, arche_pdata);
478
479 arche_pdata->num_apbs = of_get_child_count(np);
480 dev_dbg(dev, "Number of APB's available - %d\n", arche_pdata->num_apbs);
481
482 arche_pdata->wake_detect = devm_gpiod_get(dev, "svc,wake-detect",
483 GPIOD_IN);
484 if (IS_ERR(arche_pdata->wake_detect)) {
485 ret = PTR_ERR(arche_pdata->wake_detect);
486 dev_err(dev, "Failed requesting wake_detect GPIO: %d\n", ret);
487 return ret;
488 }
489
490 arche_platform_set_wake_detect_state(arche_pdata, WD_STATE_IDLE);
491
492 arche_pdata->dev = &pdev->dev;
493
494 spin_lock_init(&arche_pdata->wake_lock);
495 mutex_init(&arche_pdata->platform_state_mutex);
496 arche_pdata->wake_detect_irq =
497 gpiod_to_irq(arche_pdata->wake_detect);
498
499 ret = devm_request_threaded_irq(dev, arche_pdata->wake_detect_irq,
500 arche_platform_wd_irq,
501 arche_platform_wd_irq_thread,
502 IRQF_TRIGGER_FALLING |
503 IRQF_TRIGGER_RISING | IRQF_ONESHOT,
504 dev_name(dev), arche_pdata);
505 if (ret) {
506 dev_err(dev, "failed to request wake detect IRQ %d\n", ret);
507 return ret;
508 }
509 disable_irq(arche_pdata->wake_detect_irq);
510
511 ret = device_create_file(dev, &dev_attr_state);
512 if (ret) {
513 dev_err(dev, "failed to create state file in sysfs\n");
514 return ret;
515 }
516
517 ret = of_platform_populate(np, NULL, NULL, dev);
518 if (ret) {
519 dev_err(dev, "failed to populate child nodes %d\n", ret);
520 goto err_device_remove;
521 }
522
523 arche_pdata->pm_notifier.notifier_call = arche_platform_pm_notifier;
524 ret = register_pm_notifier(&arche_pdata->pm_notifier);
525
526 if (ret) {
527 dev_err(dev, "failed to register pm notifier %d\n", ret);
528 goto err_device_remove;
529 }
530
531
532 if (!of_property_read_bool(pdev->dev.of_node, "arche,init-off")) {
533 mutex_lock(&arche_pdata->platform_state_mutex);
534 ret = arche_platform_coldboot_seq(arche_pdata);
535 if (ret) {
536 dev_err(dev, "Failed to cold boot svc %d\n", ret);
537 goto err_coldboot;
538 }
539 arche_platform_wd_irq_en(arche_pdata);
540 mutex_unlock(&arche_pdata->platform_state_mutex);
541 }
542
543 dev_info(dev, "Device registered successfully\n");
544 return 0;
545
546err_coldboot:
547 mutex_unlock(&arche_pdata->platform_state_mutex);
548err_device_remove:
549 device_remove_file(&pdev->dev, &dev_attr_state);
550 return ret;
551}
552
553static int arche_remove_child(struct device *dev, void *unused)
554{
555 struct platform_device *pdev = to_platform_device(dev);
556
557 platform_device_unregister(pdev);
558
559 return 0;
560}
561
562static int arche_platform_remove(struct platform_device *pdev)
563{
564 struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev);
565
566 unregister_pm_notifier(&arche_pdata->pm_notifier);
567 device_remove_file(&pdev->dev, &dev_attr_state);
568 device_for_each_child(&pdev->dev, NULL, arche_remove_child);
569 arche_platform_poweroff_seq(arche_pdata);
570
571 if (usb3613_hub_mode_ctrl(false))
572 dev_warn(arche_pdata->dev, "failed to control hub device\n");
573
574 return 0;
575}
576
577static __maybe_unused int arche_platform_suspend(struct device *dev)
578{
579
580
581
582
583
584
585
586
587
588 return 0;
589}
590
591static __maybe_unused int arche_platform_resume(struct device *dev)
592{
593
594
595
596
597
598
599
600
601
602 return 0;
603}
604
605static void arche_platform_shutdown(struct platform_device *pdev)
606{
607 struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev);
608
609 arche_platform_poweroff_seq(arche_pdata);
610
611 usb3613_hub_mode_ctrl(false);
612}
613
614static SIMPLE_DEV_PM_OPS(arche_platform_pm_ops,
615 arche_platform_suspend,
616 arche_platform_resume);
617
618static const struct of_device_id arche_platform_of_match[] = {
619
620 { .compatible = "google,arche-platform", },
621 { },
622};
623
624static const struct of_device_id arche_combined_id[] = {
625
626 { .compatible = "google,arche-platform", },
627 { .compatible = "usbffff,2", },
628 { },
629};
630MODULE_DEVICE_TABLE(of, arche_combined_id);
631
632static struct platform_driver arche_platform_device_driver = {
633 .probe = arche_platform_probe,
634 .remove = arche_platform_remove,
635 .shutdown = arche_platform_shutdown,
636 .driver = {
637 .name = "arche-platform-ctrl",
638 .pm = &arche_platform_pm_ops,
639 .of_match_table = arche_platform_of_match,
640 }
641};
642
643static int __init arche_init(void)
644{
645 int retval;
646
647 retval = platform_driver_register(&arche_platform_device_driver);
648 if (retval)
649 return retval;
650
651 retval = arche_apb_init();
652 if (retval)
653 platform_driver_unregister(&arche_platform_device_driver);
654
655 return retval;
656}
657module_init(arche_init);
658
659static void __exit arche_exit(void)
660{
661 arche_apb_exit();
662 platform_driver_unregister(&arche_platform_device_driver);
663}
664module_exit(arche_exit);
665
666MODULE_LICENSE("GPL v2");
667MODULE_AUTHOR("Vaibhav Hiremath <vaibhav.hiremath@linaro.org>");
668MODULE_DESCRIPTION("Arche Platform Driver");
669