GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / staging / greybus / arche-platform.c
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
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 */
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 */
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
86 static inline void svc_reset_onoff(struct gpio_desc *gpio, bool onoff)
87 {
88         gpiod_set_raw_value(gpio, onoff);
89 }
90
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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");