1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Arche Platform driver to enable Unipro link.
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/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
usb3613_hub_mode_ctrl(bool unused)28 static 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
36 enum svc_wakedetect_state {
37 WD_STATE_IDLE, /* Default state = pulled high/low */
38 WD_STATE_BOOT_INIT, /* WD = falling edge (low) */
39 WD_STATE_COLDBOOT_TRIG, /* WD = rising edge (high), > 30msec */
40 WD_STATE_STANDBYBOOT_TRIG, /* As of now not used ?? */
41 WD_STATE_COLDBOOT_START, /* Cold boot process started */
42 WD_STATE_STANDBYBOOT_START, /* Not used */
43 };
44
45 struct arche_platform_drvdata {
46 /* Control GPIO signals to and from AP <=> SVC */
47 struct gpio_desc *svc_reset;
48 bool is_reset_act_hi;
49 struct gpio_desc *svc_sysboot;
50 struct gpio_desc *wake_detect; /* bi-dir,maps to WAKE_MOD & WAKE_FRAME signals */
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; /* Protect wake_detect_state */
65 struct mutex platform_state_mutex; /* Protect state */
66 unsigned long wake_detect_start;
67 struct notifier_block pm_notifier;
68
69 struct device *dev;
70 };
71
72 /* Requires calling context to hold arche_pdata->platform_state_mutex */
arche_platform_set_state(struct arche_platform_drvdata * arche_pdata,enum arche_platform_state state)73 static 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 /* Requires arche_pdata->wake_lock is held by calling context */
arche_platform_set_wake_detect_state(struct arche_platform_drvdata * arche_pdata,enum svc_wakedetect_state state)80 static 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
svc_reset_onoff(struct gpio_desc * gpio,bool onoff)86 static inline void svc_reset_onoff(struct gpio_desc *gpio, bool onoff)
87 {
88 gpiod_set_raw_value(gpio, onoff);
89 }
90
apb_cold_boot(struct device * dev,void * data)91 static 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 /*Child nodes are independent, so do not exit coldboot operation */
100 return 0;
101 }
102
apb_poweroff(struct device * dev,void * data)103 static int apb_poweroff(struct device *dev, void *data)
104 {
105 apb_ctrl_poweroff(dev);
106
107 /* Enable HUB3613 into HUB mode. */
108 if (usb3613_hub_mode_ctrl(false))
109 dev_warn(dev, "failed to control hub device\n");
110
111 return 0;
112 }
113
arche_platform_wd_irq_en(struct arche_platform_drvdata * arche_pdata)114 static void arche_platform_wd_irq_en(struct arche_platform_drvdata *arche_pdata)
115 {
116 /* Enable interrupt here, to read event back from SVC */
117 enable_irq(arche_pdata->wake_detect_irq);
118 }
119
arche_platform_wd_irq_thread(int irq,void * devid)120 static 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 /* Something is wrong */
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 /* It should complete power cycle, so first make sure it is poweroff */
137 device_for_each_child(arche_pdata->dev, NULL, apb_poweroff);
138
139 /* Bring APB out of reset: cold boot sequence */
140 device_for_each_child(arche_pdata->dev, NULL, apb_cold_boot);
141
142 /* Enable HUB3613 into HUB mode. */
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
arche_platform_wd_irq(int irq,void * devid)153 static 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 /* wake/detect rising */
162
163 /*
164 * If wake/detect line goes high after low, within less than
165 * 30msec, then standby boot sequence is initiated, which is not
166 * supported/implemented as of now. So ignore it.
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 * Check we are not in middle of irq thread
177 * already
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 /* wake/detect falling */
191 if (arche_pdata->wake_detect_state == WD_STATE_IDLE) {
192 arche_pdata->wake_detect_start = jiffies;
193 /*
194 * In the beginning, when wake/detect goes low
195 * (first time), we assume it is meant for coldboot
196 * and set the flag. If wake/detect line stays low
197 * beyond 30msec, then it is coldboot else fallback
198 * to standby boot.
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 * Requires arche_pdata->platform_state_mutex to be held
212 */
213 static int
arche_platform_coldboot_seq(struct arche_platform_drvdata * arche_pdata)214 arche_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 /* bring SVC out of reset */
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 * Requires arche_pdata->platform_state_mutex to be held
245 */
246 static int
arche_platform_fw_flashing_seq(struct arche_platform_drvdata * arche_pdata)247 arche_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 * Requires arche_pdata->platform_state_mutex to be held
278 */
279 static void
arche_platform_poweroff_seq(struct arche_platform_drvdata * arche_pdata)280 arche_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 /* If in fw_flashing mode, then no need to repeate things again */
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 /* As part of exit, put APB back in reset state */
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
state_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)305 static 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 /* If SVC goes down, bring down APB's as well */
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 /* First we want to make sure we power off everything
328 * and then activate back again
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 * Here we only control SVC.
349 *
350 * In case of FW_FLASHING mode we do not want to control
351 * APBs, as in case of V2, SPI bus is shared between both
352 * the APBs. So let user chose which APB he wants to flash.
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
364 exit:
365 mutex_unlock(&arche_pdata->platform_state_mutex);
366 return ret ? ret : count;
367 }
368
state_show(struct device * dev,struct device_attribute * attr,char * buf)369 static 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
388 static DEVICE_ATTR_RW(state);
389
arche_platform_pm_notifier(struct notifier_block * notifier,unsigned long pm_event,void * unused)390 static 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
arche_platform_probe(struct platform_device * pdev)423 static 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 /* setup svc reset gpio */
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 /* setup the clock request gpio first */
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 /* setup refclk2 to follow the pin */
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 /* Explicitly power off if requested */
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
546 err_coldboot:
547 mutex_unlock(&arche_pdata->platform_state_mutex);
548 err_device_remove:
549 device_remove_file(&pdev->dev, &dev_attr_state);
550 return ret;
551 }
552
arche_remove_child(struct device * dev,void * unused)553 static 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
arche_platform_remove(struct platform_device * pdev)562 static 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 /* TODO: Should we do anything more here ?? */
574 return 0;
575 }
576
arche_platform_suspend(struct device * dev)577 static __maybe_unused int arche_platform_suspend(struct device *dev)
578 {
579 /*
580 * If timing profile premits, we may shutdown bridge
581 * completely
582 *
583 * TODO: sequence ??
584 *
585 * Also, need to make sure we meet precondition for unipro suspend
586 * Precondition: Definition ???
587 */
588 return 0;
589 }
590
arche_platform_resume(struct device * dev)591 static __maybe_unused int arche_platform_resume(struct device *dev)
592 {
593 /*
594 * At least for ES2 we have to meet the delay requirement between
595 * unipro switch and AP bridge init, depending on whether bridge is in
596 * OFF state or standby state.
597 *
598 * Based on whether bridge is in standby or OFF state we may have to
599 * assert multiple signals. Please refer to WDM spec, for more info.
600 *
601 */
602 return 0;
603 }
604
arche_platform_shutdown(struct platform_device * pdev)605 static 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
614 static SIMPLE_DEV_PM_OPS(arche_platform_pm_ops,
615 arche_platform_suspend,
616 arche_platform_resume);
617
618 static const struct of_device_id arche_platform_of_match[] = {
619 /* Use PID/VID of SVC device */
620 { .compatible = "google,arche-platform", },
621 { },
622 };
623
624 static const struct of_device_id arche_combined_id[] = {
625 /* Use PID/VID of SVC device */
626 { .compatible = "google,arche-platform", },
627 { .compatible = "usbffff,2", },
628 { },
629 };
630 MODULE_DEVICE_TABLE(of, arche_combined_id);
631
632 static 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
arche_init(void)643 static 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 }
657 module_init(arche_init);
658
arche_exit(void)659 static void __exit arche_exit(void)
660 {
661 arche_apb_exit();
662 platform_driver_unregister(&arche_platform_device_driver);
663 }
664 module_exit(arche_exit);
665
666 MODULE_LICENSE("GPL v2");
667 MODULE_AUTHOR("Vaibhav Hiremath <vaibhav.hiremath@linaro.org>");
668 MODULE_DESCRIPTION("Arche Platform Driver");
669