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(
  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        /*Child nodes are independent, so do not exit coldboot operation */
 101        return 0;
 102}
 103
 104static int apb_poweroff(struct device *dev, void *data)
 105{
 106        apb_ctrl_poweroff(dev);
 107
 108        /* Enable HUB3613 into HUB mode. */
 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        /* Enable interrupt here, to read event back from SVC */
 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                /* Something is wrong */
 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        /* It should complete power cycle, so first make sure it is poweroff */
 138        device_for_each_child(arche_pdata->dev, NULL, apb_poweroff);
 139
 140        /* Bring APB out of reset: cold boot sequence */
 141        device_for_each_child(arche_pdata->dev, NULL, apb_cold_boot);
 142
 143        /* Enable HUB3613 into HUB mode. */
 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                /* wake/detect rising */
 163
 164                /*
 165                 * If wake/detect line goes high after low, within less than
 166                 * 30msec, then standby boot sequence is initiated, which is not
 167                 * supported/implemented as of now. So ignore it.
 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                                 * Check we are not in middle of irq thread
 178                                 * already
 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                /* wake/detect falling */
 193                if (arche_pdata->wake_detect_state == WD_STATE_IDLE) {
 194                        arche_pdata->wake_detect_start = jiffies;
 195                        /*
 196                         * In the beginning, when wake/detect goes low
 197                         * (first time), we assume it is meant for coldboot
 198                         * and set the flag. If wake/detect line stays low
 199                         * beyond 30msec, then it is coldboot else fallback
 200                         * to standby boot.
 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 * Requires arche_pdata->platform_state_mutex to be held
 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        /* bring SVC out of reset */
 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 * Requires arche_pdata->platform_state_mutex to be held
 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 * Requires arche_pdata->platform_state_mutex to be held
 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        /* If in fw_flashing mode, then no need to repeate things again */
 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        /* As part of exit, put APB back in reset state */
 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                /*  If SVC goes down, bring down APB's as well */
 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                /* First we want to make sure we power off everything
 330                 * and then activate back again
 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                 * Here we only control SVC.
 351                 *
 352                 * In case of FW_FLASHING mode we do not want to control
 353                 * APBs, as in case of V2, SPI bus is shared between both
 354                 * the APBs. So let user chose which APB he wants to flash.
 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        /* setup svc reset gpio */
 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        /* setup the clock request gpio first */
 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        /* setup refclk2 to follow the pin */
 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        /* Explicitly power off if requested */
 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                /* TODO: Should we do anything more here ?? */
 576        return 0;
 577}
 578
 579static __maybe_unused int arche_platform_suspend(struct device *dev)
 580{
 581        /*
 582         * If timing profile premits, we may shutdown bridge
 583         * completely
 584         *
 585         * TODO: sequence ??
 586         *
 587         * Also, need to make sure we meet precondition for unipro suspend
 588         * Precondition: Definition ???
 589         */
 590        return 0;
 591}
 592
 593static __maybe_unused int arche_platform_resume(struct device *dev)
 594{
 595        /*
 596         * Atleast for ES2 we have to meet the delay requirement between
 597         * unipro switch and AP bridge init, depending on whether bridge is in
 598         * OFF state or standby state.
 599         *
 600         * Based on whether bridge is in standby or OFF state we may have to
 601         * assert multiple signals. Please refer to WDM spec, for more info.
 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        /* Use PID/VID of SVC device */
 622        { .compatible = "google,arche-platform", },
 623        { },
 624};
 625
 626static const struct of_device_id arche_combined_id[] = {
 627        /* Use PID/VID of SVC device */
 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