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.h>
  12#include <linux/init.h>
  13#include <linux/module.h>
  14#include <linux/of_gpio.h>
  15#include <linux/of_platform.h>
  16#include <linux/pinctrl/consumer.h>
  17#include <linux/platform_device.h>
  18#include <linux/pm.h>
  19#include <linux/interrupt.h>
  20#include <linux/irq.h>
  21#include <linux/suspend.h>
  22#include <linux/time.h>
  23#include "arche_platform.h"
  24#include "greybus.h"
  25
  26#if IS_ENABLED(CONFIG_USB_HSIC_USB3613)
  27#include <linux/usb/usb3613.h>
  28#else
  29static inline int usb3613_hub_mode_ctrl(bool unused)
  30{
  31        return 0;
  32}
  33#endif
  34
  35#define WD_COLDBOOT_PULSE_WIDTH_MS      30
  36
  37enum svc_wakedetect_state {
  38        WD_STATE_IDLE,                  /* Default state = pulled high/low */
  39        WD_STATE_BOOT_INIT,             /* WD = falling edge (low) */
  40        WD_STATE_COLDBOOT_TRIG,         /* WD = rising edge (high), > 30msec */
  41        WD_STATE_STANDBYBOOT_TRIG,      /* As of now not used ?? */
  42        WD_STATE_COLDBOOT_START,        /* Cold boot process started */
  43        WD_STATE_STANDBYBOOT_START,     /* Not used */
  44};
  45
  46struct arche_platform_drvdata {
  47        /* Control GPIO signals to and from AP <=> SVC */
  48        int svc_reset_gpio;
  49        bool is_reset_act_hi;
  50        int svc_sysboot_gpio;
  51        int wake_detect_gpio; /* bi-dir,maps to WAKE_MOD & WAKE_FRAME signals */
  52
  53        enum arche_platform_state state;
  54
  55        int svc_refclk_req;
  56        struct clk *svc_ref_clk;
  57
  58        struct pinctrl *pinctrl;
  59        struct pinctrl_state *pin_default;
  60
  61        int num_apbs;
  62
  63        enum svc_wakedetect_state wake_detect_state;
  64        int wake_detect_irq;
  65        spinlock_t wake_lock;                   /* Protect wake_detect_state */
  66        struct mutex platform_state_mutex;      /* Protect state */
  67        unsigned long wake_detect_start;
  68        struct notifier_block pm_notifier;
  69
  70        struct device *dev;
  71};
  72
  73/* Requires calling context to hold arche_pdata->platform_state_mutex */
  74static void arche_platform_set_state(struct arche_platform_drvdata *arche_pdata,
  75                                     enum arche_platform_state state)
  76{
  77        arche_pdata->state = state;
  78}
  79
  80/* Requires arche_pdata->wake_lock is held by calling context */
  81static void arche_platform_set_wake_detect_state(
  82                                struct arche_platform_drvdata *arche_pdata,
  83                                enum svc_wakedetect_state state)
  84{
  85        arche_pdata->wake_detect_state = state;
  86}
  87
  88static inline void svc_reset_onoff(unsigned int gpio, bool onoff)
  89{
  90        gpio_set_value(gpio, onoff);
  91}
  92
  93static int apb_cold_boot(struct device *dev, void *data)
  94{
  95        int ret;
  96
  97        ret = apb_ctrl_coldboot(dev);
  98        if (ret)
  99                dev_warn(dev, "failed to coldboot\n");
 100
 101        /*Child nodes are independent, so do not exit coldboot operation */
 102        return 0;
 103}
 104
 105static int apb_poweroff(struct device *dev, void *data)
 106{
 107        apb_ctrl_poweroff(dev);
 108
 109        /* Enable HUB3613 into HUB mode. */
 110        if (usb3613_hub_mode_ctrl(false))
 111                dev_warn(dev, "failed to control hub device\n");
 112
 113        return 0;
 114}
 115
 116static void arche_platform_wd_irq_en(struct arche_platform_drvdata *arche_pdata)
 117{
 118        /* Enable interrupt here, to read event back from SVC */
 119        gpio_direction_input(arche_pdata->wake_detect_gpio);
 120        enable_irq(arche_pdata->wake_detect_irq);
 121}
 122
 123static irqreturn_t arche_platform_wd_irq_thread(int irq, void *devid)
 124{
 125        struct arche_platform_drvdata *arche_pdata = devid;
 126        unsigned long flags;
 127
 128        spin_lock_irqsave(&arche_pdata->wake_lock, flags);
 129        if (arche_pdata->wake_detect_state != WD_STATE_COLDBOOT_TRIG) {
 130                /* Something is wrong */
 131                spin_unlock_irqrestore(&arche_pdata->wake_lock, flags);
 132                return IRQ_HANDLED;
 133        }
 134
 135        arche_platform_set_wake_detect_state(arche_pdata,
 136                                             WD_STATE_COLDBOOT_START);
 137        spin_unlock_irqrestore(&arche_pdata->wake_lock, flags);
 138
 139        /* It should complete power cycle, so first make sure it is poweroff */
 140        device_for_each_child(arche_pdata->dev, NULL, apb_poweroff);
 141
 142        /* Bring APB out of reset: cold boot sequence */
 143        device_for_each_child(arche_pdata->dev, NULL, apb_cold_boot);
 144
 145        /* Enable HUB3613 into HUB mode. */
 146        if (usb3613_hub_mode_ctrl(true))
 147                dev_warn(arche_pdata->dev, "failed to control hub device\n");
 148
 149        spin_lock_irqsave(&arche_pdata->wake_lock, flags);
 150        arche_platform_set_wake_detect_state(arche_pdata, WD_STATE_IDLE);
 151        spin_unlock_irqrestore(&arche_pdata->wake_lock, flags);
 152
 153        return IRQ_HANDLED;
 154}
 155
 156static irqreturn_t arche_platform_wd_irq(int irq, void *devid)
 157{
 158        struct arche_platform_drvdata *arche_pdata = devid;
 159        unsigned long flags;
 160
 161        spin_lock_irqsave(&arche_pdata->wake_lock, flags);
 162
 163        if (gpio_get_value(arche_pdata->wake_detect_gpio)) {
 164                /* wake/detect rising */
 165
 166                /*
 167                 * If wake/detect line goes high after low, within less than
 168                 * 30msec, then standby boot sequence is initiated, which is not
 169                 * supported/implemented as of now. So ignore it.
 170                 */
 171                if (arche_pdata->wake_detect_state == WD_STATE_BOOT_INIT) {
 172                        if (time_before(jiffies,
 173                                        arche_pdata->wake_detect_start +
 174                                        msecs_to_jiffies(WD_COLDBOOT_PULSE_WIDTH_MS))) {
 175                                arche_platform_set_wake_detect_state(arche_pdata,
 176                                                                     WD_STATE_IDLE);
 177                        } else {
 178                                /*
 179                                 * Check we are not in middle of irq thread
 180                                 * already
 181                                 */
 182                                if (arche_pdata->wake_detect_state !=
 183                                                WD_STATE_COLDBOOT_START) {
 184                                        arche_platform_set_wake_detect_state(arche_pdata,
 185                                                                             WD_STATE_COLDBOOT_TRIG);
 186                                        spin_unlock_irqrestore(
 187                                                &arche_pdata->wake_lock,
 188                                                flags);
 189                                        return IRQ_WAKE_THREAD;
 190                                }
 191                        }
 192                }
 193        } else {
 194                /* wake/detect falling */
 195                if (arche_pdata->wake_detect_state == WD_STATE_IDLE) {
 196                        arche_pdata->wake_detect_start = jiffies;
 197                        /*
 198                         * In the beginning, when wake/detect goes low
 199                         * (first time), we assume it is meant for coldboot
 200                         * and set the flag. If wake/detect line stays low
 201                         * beyond 30msec, then it is coldboot else fallback
 202                         * to standby boot.
 203                         */
 204                        arche_platform_set_wake_detect_state(arche_pdata,
 205                                                             WD_STATE_BOOT_INIT);
 206                }
 207        }
 208
 209        spin_unlock_irqrestore(&arche_pdata->wake_lock, flags);
 210
 211        return IRQ_HANDLED;
 212}
 213
 214/*
 215 * Requires arche_pdata->platform_state_mutex to be held
 216 */
 217static int
 218arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdata)
 219{
 220        int ret;
 221
 222        if (arche_pdata->state == ARCHE_PLATFORM_STATE_ACTIVE)
 223                return 0;
 224
 225        dev_info(arche_pdata->dev, "Booting from cold boot state\n");
 226
 227        svc_reset_onoff(arche_pdata->svc_reset_gpio,
 228                        arche_pdata->is_reset_act_hi);
 229
 230        gpio_set_value(arche_pdata->svc_sysboot_gpio, 0);
 231        usleep_range(100, 200);
 232
 233        ret = clk_prepare_enable(arche_pdata->svc_ref_clk);
 234        if (ret) {
 235                dev_err(arche_pdata->dev, "failed to enable svc_ref_clk: %d\n",
 236                        ret);
 237                return ret;
 238        }
 239
 240        /* bring SVC out of reset */
 241        svc_reset_onoff(arche_pdata->svc_reset_gpio,
 242                        !arche_pdata->is_reset_act_hi);
 243
 244        arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_ACTIVE);
 245
 246        return 0;
 247}
 248
 249/*
 250 * Requires arche_pdata->platform_state_mutex to be held
 251 */
 252static int
 253arche_platform_fw_flashing_seq(struct arche_platform_drvdata *arche_pdata)
 254{
 255        int ret;
 256
 257        if (arche_pdata->state == ARCHE_PLATFORM_STATE_FW_FLASHING)
 258                return 0;
 259
 260        dev_info(arche_pdata->dev, "Switching to FW flashing state\n");
 261
 262        svc_reset_onoff(arche_pdata->svc_reset_gpio,
 263                        arche_pdata->is_reset_act_hi);
 264
 265        gpio_set_value(arche_pdata->svc_sysboot_gpio, 1);
 266
 267        usleep_range(100, 200);
 268
 269        ret = clk_prepare_enable(arche_pdata->svc_ref_clk);
 270        if (ret) {
 271                dev_err(arche_pdata->dev, "failed to enable svc_ref_clk: %d\n",
 272                        ret);
 273                return ret;
 274        }
 275
 276        svc_reset_onoff(arche_pdata->svc_reset_gpio,
 277                        !arche_pdata->is_reset_act_hi);
 278
 279        arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_FW_FLASHING);
 280
 281        return 0;
 282}
 283
 284/*
 285 * Requires arche_pdata->platform_state_mutex to be held
 286 */
 287static void
 288arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pdata)
 289{
 290        unsigned long flags;
 291
 292        if (arche_pdata->state == ARCHE_PLATFORM_STATE_OFF)
 293                return;
 294
 295        /* If in fw_flashing mode, then no need to repeate things again */
 296        if (arche_pdata->state != ARCHE_PLATFORM_STATE_FW_FLASHING) {
 297                disable_irq(arche_pdata->wake_detect_irq);
 298
 299                spin_lock_irqsave(&arche_pdata->wake_lock, flags);
 300                arche_platform_set_wake_detect_state(arche_pdata,
 301                                                     WD_STATE_IDLE);
 302                spin_unlock_irqrestore(&arche_pdata->wake_lock, flags);
 303        }
 304
 305        clk_disable_unprepare(arche_pdata->svc_ref_clk);
 306
 307        /* As part of exit, put APB back in reset state */
 308        svc_reset_onoff(arche_pdata->svc_reset_gpio,
 309                        arche_pdata->is_reset_act_hi);
 310
 311        arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_OFF);
 312}
 313
 314static ssize_t state_store(struct device *dev,
 315                           struct device_attribute *attr,
 316                           const char *buf, size_t count)
 317{
 318        struct arche_platform_drvdata *arche_pdata = dev_get_drvdata(dev);
 319        int ret = 0;
 320
 321        mutex_lock(&arche_pdata->platform_state_mutex);
 322
 323        if (sysfs_streq(buf, "off")) {
 324                if (arche_pdata->state == ARCHE_PLATFORM_STATE_OFF)
 325                        goto exit;
 326
 327                /*  If SVC goes down, bring down APB's as well */
 328                device_for_each_child(arche_pdata->dev, NULL, apb_poweroff);
 329
 330                arche_platform_poweroff_seq(arche_pdata);
 331
 332        } else if (sysfs_streq(buf, "active")) {
 333                if (arche_pdata->state == ARCHE_PLATFORM_STATE_ACTIVE)
 334                        goto exit;
 335
 336                /* First we want to make sure we power off everything
 337                 * and then activate back again
 338                 */
 339                device_for_each_child(arche_pdata->dev, NULL, apb_poweroff);
 340                arche_platform_poweroff_seq(arche_pdata);
 341
 342                arche_platform_wd_irq_en(arche_pdata);
 343                ret = arche_platform_coldboot_seq(arche_pdata);
 344                if (ret)
 345                        goto exit;
 346
 347        } else if (sysfs_streq(buf, "standby")) {
 348                if (arche_pdata->state == ARCHE_PLATFORM_STATE_STANDBY)
 349                        goto exit;
 350
 351                dev_warn(arche_pdata->dev, "standby state not supported\n");
 352        } else if (sysfs_streq(buf, "fw_flashing")) {
 353                if (arche_pdata->state == ARCHE_PLATFORM_STATE_FW_FLASHING)
 354                        goto exit;
 355
 356                /*
 357                 * Here we only control SVC.
 358                 *
 359                 * In case of FW_FLASHING mode we do not want to control
 360                 * APBs, as in case of V2, SPI bus is shared between both
 361                 * the APBs. So let user chose which APB he wants to flash.
 362                 */
 363                arche_platform_poweroff_seq(arche_pdata);
 364
 365                ret = arche_platform_fw_flashing_seq(arche_pdata);
 366                if (ret)
 367                        goto exit;
 368        } else {
 369                dev_err(arche_pdata->dev, "unknown state\n");
 370                ret = -EINVAL;
 371        }
 372
 373exit:
 374        mutex_unlock(&arche_pdata->platform_state_mutex);
 375        return ret ? ret : count;
 376}
 377
 378static ssize_t state_show(struct device *dev,
 379                          struct device_attribute *attr, char *buf)
 380{
 381        struct arche_platform_drvdata *arche_pdata = dev_get_drvdata(dev);
 382
 383        switch (arche_pdata->state) {
 384        case ARCHE_PLATFORM_STATE_OFF:
 385                return sprintf(buf, "off\n");
 386        case ARCHE_PLATFORM_STATE_ACTIVE:
 387                return sprintf(buf, "active\n");
 388        case ARCHE_PLATFORM_STATE_STANDBY:
 389                return sprintf(buf, "standby\n");
 390        case ARCHE_PLATFORM_STATE_FW_FLASHING:
 391                return sprintf(buf, "fw_flashing\n");
 392        default:
 393                return sprintf(buf, "unknown state\n");
 394        }
 395}
 396
 397static DEVICE_ATTR_RW(state);
 398
 399static int arche_platform_pm_notifier(struct notifier_block *notifier,
 400                                      unsigned long pm_event, void *unused)
 401{
 402        struct arche_platform_drvdata *arche_pdata =
 403                container_of(notifier, struct arche_platform_drvdata,
 404                             pm_notifier);
 405        int ret = NOTIFY_DONE;
 406
 407        mutex_lock(&arche_pdata->platform_state_mutex);
 408        switch (pm_event) {
 409        case PM_SUSPEND_PREPARE:
 410                if (arche_pdata->state != ARCHE_PLATFORM_STATE_ACTIVE) {
 411                        ret = NOTIFY_STOP;
 412                        break;
 413                }
 414                device_for_each_child(arche_pdata->dev, NULL, apb_poweroff);
 415                arche_platform_poweroff_seq(arche_pdata);
 416                break;
 417        case PM_POST_SUSPEND:
 418                if (arche_pdata->state != ARCHE_PLATFORM_STATE_OFF)
 419                        break;
 420
 421                arche_platform_wd_irq_en(arche_pdata);
 422                arche_platform_coldboot_seq(arche_pdata);
 423                break;
 424        default:
 425                break;
 426        }
 427        mutex_unlock(&arche_pdata->platform_state_mutex);
 428
 429        return ret;
 430}
 431
 432static int arche_platform_probe(struct platform_device *pdev)
 433{
 434        struct arche_platform_drvdata *arche_pdata;
 435        struct device *dev = &pdev->dev;
 436        struct device_node *np = dev->of_node;
 437        int ret;
 438
 439        arche_pdata = devm_kzalloc(&pdev->dev, sizeof(*arche_pdata),
 440                                   GFP_KERNEL);
 441        if (!arche_pdata)
 442                return -ENOMEM;
 443
 444        /* setup svc reset gpio */
 445        arche_pdata->is_reset_act_hi = of_property_read_bool(np,
 446                                                             "svc,reset-active-high");
 447        arche_pdata->svc_reset_gpio = of_get_named_gpio(np,
 448                                                        "svc,reset-gpio",
 449                                                        0);
 450        if (!gpio_is_valid(arche_pdata->svc_reset_gpio)) {
 451                dev_err(dev, "failed to get reset-gpio\n");
 452                return arche_pdata->svc_reset_gpio;
 453        }
 454        ret = devm_gpio_request(dev, arche_pdata->svc_reset_gpio, "svc-reset");
 455        if (ret) {
 456                dev_err(dev, "failed to request svc-reset gpio:%d\n", ret);
 457                return ret;
 458        }
 459        ret = gpio_direction_output(arche_pdata->svc_reset_gpio,
 460                                    arche_pdata->is_reset_act_hi);
 461        if (ret) {
 462                dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret);
 463                return ret;
 464        }
 465        arche_platform_set_state(arche_pdata, ARCHE_PLATFORM_STATE_OFF);
 466
 467        arche_pdata->svc_sysboot_gpio = of_get_named_gpio(np,
 468                                                          "svc,sysboot-gpio",
 469                                                          0);
 470        if (!gpio_is_valid(arche_pdata->svc_sysboot_gpio)) {
 471                dev_err(dev, "failed to get sysboot gpio\n");
 472                return arche_pdata->svc_sysboot_gpio;
 473        }
 474        ret = devm_gpio_request(dev, arche_pdata->svc_sysboot_gpio, "sysboot0");
 475        if (ret) {
 476                dev_err(dev, "failed to request sysboot0 gpio:%d\n", ret);
 477                return ret;
 478        }
 479        ret = gpio_direction_output(arche_pdata->svc_sysboot_gpio, 0);
 480        if (ret) {
 481                dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret);
 482                return ret;
 483        }
 484
 485        /* setup the clock request gpio first */
 486        arche_pdata->svc_refclk_req = of_get_named_gpio(np,
 487                                                        "svc,refclk-req-gpio",
 488                                                        0);
 489        if (!gpio_is_valid(arche_pdata->svc_refclk_req)) {
 490                dev_err(dev, "failed to get svc clock-req gpio\n");
 491                return arche_pdata->svc_refclk_req;
 492        }
 493        ret = devm_gpio_request(dev, arche_pdata->svc_refclk_req,
 494                                "svc-clk-req");
 495        if (ret) {
 496                dev_err(dev, "failed to request svc-clk-req gpio: %d\n", ret);
 497                return ret;
 498        }
 499        ret = gpio_direction_input(arche_pdata->svc_refclk_req);
 500        if (ret) {
 501                dev_err(dev, "failed to set svc-clk-req gpio dir :%d\n", ret);
 502                return ret;
 503        }
 504
 505        /* setup refclk2 to follow the pin */
 506        arche_pdata->svc_ref_clk = devm_clk_get(dev, "svc_ref_clk");
 507        if (IS_ERR(arche_pdata->svc_ref_clk)) {
 508                ret = PTR_ERR(arche_pdata->svc_ref_clk);
 509                dev_err(dev, "failed to get svc_ref_clk: %d\n", ret);
 510                return ret;
 511        }
 512
 513        platform_set_drvdata(pdev, arche_pdata);
 514
 515        arche_pdata->num_apbs = of_get_child_count(np);
 516        dev_dbg(dev, "Number of APB's available - %d\n", arche_pdata->num_apbs);
 517
 518        arche_pdata->wake_detect_gpio = of_get_named_gpio(np,
 519                                                          "svc,wake-detect-gpio",
 520                                                          0);
 521        if (arche_pdata->wake_detect_gpio < 0) {
 522                dev_err(dev, "failed to get wake detect gpio\n");
 523                return arche_pdata->wake_detect_gpio;
 524        }
 525
 526        ret = devm_gpio_request(dev, arche_pdata->wake_detect_gpio,
 527                                "wake detect");
 528        if (ret) {
 529                dev_err(dev, "Failed requesting wake_detect gpio %d\n",
 530                        arche_pdata->wake_detect_gpio);
 531                return ret;
 532        }
 533
 534        arche_platform_set_wake_detect_state(arche_pdata, WD_STATE_IDLE);
 535
 536        arche_pdata->dev = &pdev->dev;
 537
 538        spin_lock_init(&arche_pdata->wake_lock);
 539        mutex_init(&arche_pdata->platform_state_mutex);
 540        arche_pdata->wake_detect_irq =
 541                gpio_to_irq(arche_pdata->wake_detect_gpio);
 542
 543        ret = devm_request_threaded_irq(dev, arche_pdata->wake_detect_irq,
 544                                        arche_platform_wd_irq,
 545                                        arche_platform_wd_irq_thread,
 546                                        IRQF_TRIGGER_FALLING |
 547                                        IRQF_TRIGGER_RISING | IRQF_ONESHOT,
 548                                        dev_name(dev), arche_pdata);
 549        if (ret) {
 550                dev_err(dev, "failed to request wake detect IRQ %d\n", ret);
 551                return ret;
 552        }
 553        disable_irq(arche_pdata->wake_detect_irq);
 554
 555        ret = device_create_file(dev, &dev_attr_state);
 556        if (ret) {
 557                dev_err(dev, "failed to create state file in sysfs\n");
 558                return ret;
 559        }
 560
 561        ret = of_platform_populate(np, NULL, NULL, dev);
 562        if (ret) {
 563                dev_err(dev, "failed to populate child nodes %d\n", ret);
 564                goto err_device_remove;
 565        }
 566
 567        arche_pdata->pm_notifier.notifier_call = arche_platform_pm_notifier;
 568        ret = register_pm_notifier(&arche_pdata->pm_notifier);
 569
 570        if (ret) {
 571                dev_err(dev, "failed to register pm notifier %d\n", ret);
 572                goto err_device_remove;
 573        }
 574
 575        /* Explicitly power off if requested */
 576        if (!of_property_read_bool(pdev->dev.of_node, "arche,init-off")) {
 577                mutex_lock(&arche_pdata->platform_state_mutex);
 578                ret = arche_platform_coldboot_seq(arche_pdata);
 579                if (ret) {
 580                        dev_err(dev, "Failed to cold boot svc %d\n", ret);
 581                        goto err_coldboot;
 582                }
 583                arche_platform_wd_irq_en(arche_pdata);
 584                mutex_unlock(&arche_pdata->platform_state_mutex);
 585        }
 586
 587        dev_info(dev, "Device registered successfully\n");
 588        return 0;
 589
 590err_coldboot:
 591        mutex_unlock(&arche_pdata->platform_state_mutex);
 592err_device_remove:
 593        device_remove_file(&pdev->dev, &dev_attr_state);
 594        return ret;
 595}
 596
 597static int arche_remove_child(struct device *dev, void *unused)
 598{
 599        struct platform_device *pdev = to_platform_device(dev);
 600
 601        platform_device_unregister(pdev);
 602
 603        return 0;
 604}
 605
 606static int arche_platform_remove(struct platform_device *pdev)
 607{
 608        struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev);
 609
 610        unregister_pm_notifier(&arche_pdata->pm_notifier);
 611        device_remove_file(&pdev->dev, &dev_attr_state);
 612        device_for_each_child(&pdev->dev, NULL, arche_remove_child);
 613        arche_platform_poweroff_seq(arche_pdata);
 614
 615        if (usb3613_hub_mode_ctrl(false))
 616                dev_warn(arche_pdata->dev, "failed to control hub device\n");
 617                /* TODO: Should we do anything more here ?? */
 618        return 0;
 619}
 620
 621static __maybe_unused int arche_platform_suspend(struct device *dev)
 622{
 623        /*
 624         * If timing profile premits, we may shutdown bridge
 625         * completely
 626         *
 627         * TODO: sequence ??
 628         *
 629         * Also, need to make sure we meet precondition for unipro suspend
 630         * Precondition: Definition ???
 631         */
 632        return 0;
 633}
 634
 635static __maybe_unused int arche_platform_resume(struct device *dev)
 636{
 637        /*
 638         * Atleast for ES2 we have to meet the delay requirement between
 639         * unipro switch and AP bridge init, depending on whether bridge is in
 640         * OFF state or standby state.
 641         *
 642         * Based on whether bridge is in standby or OFF state we may have to
 643         * assert multiple signals. Please refer to WDM spec, for more info.
 644         *
 645         */
 646        return 0;
 647}
 648
 649static void arche_platform_shutdown(struct platform_device *pdev)
 650{
 651        struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev);
 652
 653        arche_platform_poweroff_seq(arche_pdata);
 654
 655        usb3613_hub_mode_ctrl(false);
 656}
 657
 658static SIMPLE_DEV_PM_OPS(arche_platform_pm_ops,
 659                        arche_platform_suspend,
 660                        arche_platform_resume);
 661
 662static const struct of_device_id arche_platform_of_match[] = {
 663        /* Use PID/VID of SVC device */
 664        { .compatible = "google,arche-platform", },
 665        { },
 666};
 667
 668static const struct of_device_id arche_combined_id[] = {
 669        /* Use PID/VID of SVC device */
 670        { .compatible = "google,arche-platform", },
 671        { .compatible = "usbffff,2", },
 672        { },
 673};
 674MODULE_DEVICE_TABLE(of, arche_combined_id);
 675
 676static struct platform_driver arche_platform_device_driver = {
 677        .probe          = arche_platform_probe,
 678        .remove         = arche_platform_remove,
 679        .shutdown       = arche_platform_shutdown,
 680        .driver         = {
 681                .name   = "arche-platform-ctrl",
 682                .pm     = &arche_platform_pm_ops,
 683                .of_match_table = arche_platform_of_match,
 684        }
 685};
 686
 687static int __init arche_init(void)
 688{
 689        int retval;
 690
 691        retval = platform_driver_register(&arche_platform_device_driver);
 692        if (retval)
 693                return retval;
 694
 695        retval = arche_apb_init();
 696        if (retval)
 697                platform_driver_unregister(&arche_platform_device_driver);
 698
 699        return retval;
 700}
 701module_init(arche_init);
 702
 703static void __exit arche_exit(void)
 704{
 705        arche_apb_exit();
 706        platform_driver_unregister(&arche_platform_device_driver);
 707}
 708module_exit(arche_exit);
 709
 710MODULE_LICENSE("GPL v2");
 711MODULE_AUTHOR("Vaibhav Hiremath <vaibhav.hiremath@linaro.org>");
 712MODULE_DESCRIPTION("Arche Platform Driver");
 713