linux/drivers/staging/greybus/arche-platform.c
<<
>>
Prefs
   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
  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,                  /* 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
  45struct 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 */
  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/* Requires arche_pdata->wake_lock is held by calling context */
  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        /*Child nodes are independent, so do not exit coldboot operation */
 100        return 0;
 101}
 102
 103static 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
 114static 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
 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                /* 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
 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                /* 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 */
 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        /* 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 */
 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 * Requires arche_pdata->platform_state_mutex to be held
 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        /* 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
 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                /*  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
 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        /* 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
 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                /* TODO: Should we do anything more here ?? */
 574        return 0;
 575}
 576
 577static __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
 591static __maybe_unused int arche_platform_resume(struct device *dev)
 592{
 593        /*
 594         * Atleast 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
 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        /* Use PID/VID of SVC device */
 620        { .compatible = "google,arche-platform", },
 621        { },
 622};
 623
 624static 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};
 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