cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

arche-platform.c (18268B)


      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	 * 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
    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");