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