17fa60654SVaibhav Hiremath /* 27fa60654SVaibhav Hiremath * Arche Platform driver to enable Unipro link. 37fa60654SVaibhav Hiremath * 47fa60654SVaibhav Hiremath * Copyright 2014-2015 Google Inc. 57fa60654SVaibhav Hiremath * Copyright 2014-2015 Linaro Ltd. 67fa60654SVaibhav Hiremath * 77fa60654SVaibhav Hiremath * Released under the GPLv2 only. 87fa60654SVaibhav Hiremath */ 97fa60654SVaibhav Hiremath 107fa60654SVaibhav Hiremath #include <linux/clk.h> 11a463fc15SVaibhav Hiremath #include <linux/delay.h> 123b858df0SViresh Kumar #include <linux/gpio.h> 133b858df0SViresh Kumar #include <linux/init.h> 143b858df0SViresh Kumar #include <linux/module.h> 157fa60654SVaibhav Hiremath #include <linux/of_gpio.h> 163b858df0SViresh Kumar #include <linux/of_platform.h> 177fa60654SVaibhav Hiremath #include <linux/pinctrl/consumer.h> 183b858df0SViresh Kumar #include <linux/platform_device.h> 193b858df0SViresh Kumar #include <linux/pm.h> 201e5dd1f8SGreg Kroah-Hartman #include "arche_platform.h" 217fa60654SVaibhav Hiremath 227fa60654SVaibhav Hiremath struct arche_platform_drvdata { 237fa60654SVaibhav Hiremath /* Control GPIO signals to and from AP <=> SVC */ 247fa60654SVaibhav Hiremath int svc_reset_gpio; 257fa60654SVaibhav Hiremath bool is_reset_act_hi; 267fa60654SVaibhav Hiremath int svc_sysboot_gpio; 27a463fc15SVaibhav Hiremath int wake_detect_gpio; /* bi-dir,maps to WAKE_MOD & WAKE_FRAME signals */ 287fa60654SVaibhav Hiremath 29e74d04a5SVaibhav Hiremath enum arche_platform_state state; 30e74d04a5SVaibhav Hiremath 317fa60654SVaibhav Hiremath unsigned int svc_refclk_req; 327fa60654SVaibhav Hiremath struct clk *svc_ref_clk; 337fa60654SVaibhav Hiremath 347fa60654SVaibhav Hiremath struct pinctrl *pinctrl; 357fa60654SVaibhav Hiremath struct pinctrl_state *pin_default; 367fa60654SVaibhav Hiremath 377fa60654SVaibhav Hiremath int num_apbs; 38a463fc15SVaibhav Hiremath 39a463fc15SVaibhav Hiremath struct delayed_work delayed_work; 40a463fc15SVaibhav Hiremath struct device *dev; 417fa60654SVaibhav Hiremath }; 427fa60654SVaibhav Hiremath 437fa60654SVaibhav Hiremath static inline void svc_reset_onoff(unsigned int gpio, bool onoff) 447fa60654SVaibhav Hiremath { 457fa60654SVaibhav Hiremath gpio_set_value(gpio, onoff); 467fa60654SVaibhav Hiremath } 477fa60654SVaibhav Hiremath 48a463fc15SVaibhav Hiremath /** 49a463fc15SVaibhav Hiremath * svc_delayed_work - Time to give SVC to boot. 50a463fc15SVaibhav Hiremath */ 51a463fc15SVaibhav Hiremath static void svc_delayed_work(struct work_struct *work) 52a463fc15SVaibhav Hiremath { 53a463fc15SVaibhav Hiremath struct arche_platform_drvdata *arche_pdata = 54a463fc15SVaibhav Hiremath container_of(work, struct arche_platform_drvdata, delayed_work.work); 55a463fc15SVaibhav Hiremath struct device *dev = arche_pdata->dev; 56a463fc15SVaibhav Hiremath struct device_node *np = dev->of_node; 57a3043d9eSMichael Scott int timeout = 50; 58a463fc15SVaibhav Hiremath int ret; 59a463fc15SVaibhav Hiremath 60a463fc15SVaibhav Hiremath /* 61a463fc15SVaibhav Hiremath * 1. SVC and AP boot independently, with AP<-->SVC wake/detect pin 62a463fc15SVaibhav Hiremath * deasserted (LOW in this case) 63a463fc15SVaibhav Hiremath * 2.1. SVC allows 360 milliseconds to elapse after switch boots to work 64a463fc15SVaibhav Hiremath * around bug described in ENG-330. 65a463fc15SVaibhav Hiremath * 2.2. AP asserts wake/detect pin (HIGH) (this can proceed in parallel with 2.1) 66a463fc15SVaibhav Hiremath * 3. SVC detects assertion of wake/detect pin, and sends "wake out" signal to AP 67a463fc15SVaibhav Hiremath * 4. AP receives "wake out" signal, takes AP Bridges through their power 68a463fc15SVaibhav Hiremath * on reset sequence as defined in the bridge ASIC reference manuals 69a463fc15SVaibhav Hiremath * 5. AP takes USB3613 through its power on reset sequence 70a463fc15SVaibhav Hiremath * 6. AP enumerates AP Bridges 71a463fc15SVaibhav Hiremath */ 72a463fc15SVaibhav Hiremath gpio_set_value(arche_pdata->wake_detect_gpio, 1); 73a463fc15SVaibhav Hiremath gpio_direction_input(arche_pdata->wake_detect_gpio); 74a463fc15SVaibhav Hiremath do { 75a463fc15SVaibhav Hiremath /* Read the wake_detect GPIO, for WAKE_OUT event from SVC */ 76a463fc15SVaibhav Hiremath if (gpio_get_value(arche_pdata->wake_detect_gpio) == 0) 77a463fc15SVaibhav Hiremath break; 78a463fc15SVaibhav Hiremath 79a3043d9eSMichael Scott msleep(100); 80a463fc15SVaibhav Hiremath } while(timeout--); 81a463fc15SVaibhav Hiremath 82a463fc15SVaibhav Hiremath if (timeout >= 0) { 83a463fc15SVaibhav Hiremath ret = of_platform_populate(np, NULL, NULL, dev); 841e83ee33SMichael Scott if (!ret) { 851e83ee33SMichael Scott /* re-assert wake_detect to confirm SVC WAKE_OUT */ 861e83ee33SMichael Scott gpio_direction_output(arche_pdata->wake_detect_gpio, 1); 87a463fc15SVaibhav Hiremath return; 88a463fc15SVaibhav Hiremath } 891e83ee33SMichael Scott } 90a463fc15SVaibhav Hiremath 91a463fc15SVaibhav Hiremath /* FIXME: We may want to limit retries here */ 92a463fc15SVaibhav Hiremath gpio_direction_output(arche_pdata->wake_detect_gpio, 0); 93a463fc15SVaibhav Hiremath schedule_delayed_work(&arche_pdata->delayed_work, msecs_to_jiffies(2000)); 94a463fc15SVaibhav Hiremath } 95a463fc15SVaibhav Hiremath 966da86df3SVaibhav Hiremath /* Export gpio's to user space */ 976da86df3SVaibhav Hiremath static void export_gpios(struct arche_platform_drvdata *arche_pdata) 986da86df3SVaibhav Hiremath { 996da86df3SVaibhav Hiremath gpio_export(arche_pdata->svc_reset_gpio, false); 1006da86df3SVaibhav Hiremath gpio_export(arche_pdata->svc_sysboot_gpio, false); 1016da86df3SVaibhav Hiremath } 1026da86df3SVaibhav Hiremath 1036da86df3SVaibhav Hiremath static void unexport_gpios(struct arche_platform_drvdata *arche_pdata) 1046da86df3SVaibhav Hiremath { 1056da86df3SVaibhav Hiremath gpio_unexport(arche_pdata->svc_reset_gpio); 1066da86df3SVaibhav Hiremath gpio_unexport(arche_pdata->svc_sysboot_gpio); 1076da86df3SVaibhav Hiremath } 1086da86df3SVaibhav Hiremath 109758ca99dSVaibhav Hiremath static int arche_platform_coldboot_seq(struct arche_platform_drvdata *arche_pdata) 110758ca99dSVaibhav Hiremath { 111758ca99dSVaibhav Hiremath int ret; 112758ca99dSVaibhav Hiremath 113758ca99dSVaibhav Hiremath dev_info(arche_pdata->dev, "Booting from cold boot state\n"); 114758ca99dSVaibhav Hiremath 115758ca99dSVaibhav Hiremath svc_reset_onoff(arche_pdata->svc_reset_gpio, 116758ca99dSVaibhav Hiremath arche_pdata->is_reset_act_hi); 117758ca99dSVaibhav Hiremath 118758ca99dSVaibhav Hiremath gpio_set_value(arche_pdata->svc_sysboot_gpio, 0); 119758ca99dSVaibhav Hiremath usleep_range(100, 200); 120758ca99dSVaibhav Hiremath 121758ca99dSVaibhav Hiremath ret = clk_prepare_enable(arche_pdata->svc_ref_clk); 122758ca99dSVaibhav Hiremath if (ret) { 123758ca99dSVaibhav Hiremath dev_err(arche_pdata->dev, "failed to enable svc_ref_clk: %d\n", 124758ca99dSVaibhav Hiremath ret); 125758ca99dSVaibhav Hiremath return ret; 126758ca99dSVaibhav Hiremath } 127758ca99dSVaibhav Hiremath 128758ca99dSVaibhav Hiremath /* bring SVC out of reset */ 129758ca99dSVaibhav Hiremath svc_reset_onoff(arche_pdata->svc_reset_gpio, 130758ca99dSVaibhav Hiremath !arche_pdata->is_reset_act_hi); 131758ca99dSVaibhav Hiremath 132e74d04a5SVaibhav Hiremath arche_pdata->state = ARCHE_PLATFORM_STATE_ACTIVE; 133e74d04a5SVaibhav Hiremath 134758ca99dSVaibhav Hiremath return 0; 135758ca99dSVaibhav Hiremath } 136758ca99dSVaibhav Hiremath 1375993e2bfSVaibhav Hiremath static void arche_platform_poweroff_seq(struct arche_platform_drvdata *arche_pdata) 1387fa60654SVaibhav Hiremath { 139d8b16338SVaibhav Hiremath clk_disable_unprepare(arche_pdata->svc_ref_clk); 1407fa60654SVaibhav Hiremath /* As part of exit, put APB back in reset state */ 1417fa60654SVaibhav Hiremath svc_reset_onoff(arche_pdata->svc_reset_gpio, 1427fa60654SVaibhav Hiremath arche_pdata->is_reset_act_hi); 143e74d04a5SVaibhav Hiremath 144e74d04a5SVaibhav Hiremath arche_pdata->state = ARCHE_PLATFORM_STATE_OFF; 1457fa60654SVaibhav Hiremath } 1467fa60654SVaibhav Hiremath 1477fa60654SVaibhav Hiremath static int arche_platform_probe(struct platform_device *pdev) 1487fa60654SVaibhav Hiremath { 1497fa60654SVaibhav Hiremath struct arche_platform_drvdata *arche_pdata; 1507fa60654SVaibhav Hiremath struct device *dev = &pdev->dev; 1517fa60654SVaibhav Hiremath struct device_node *np = dev->of_node; 1527fa60654SVaibhav Hiremath int ret; 1537fa60654SVaibhav Hiremath 1547fa60654SVaibhav Hiremath arche_pdata = devm_kzalloc(&pdev->dev, sizeof(*arche_pdata), GFP_KERNEL); 1557fa60654SVaibhav Hiremath if (!arche_pdata) 1567fa60654SVaibhav Hiremath return -ENOMEM; 1577fa60654SVaibhav Hiremath 1587fa60654SVaibhav Hiremath /* setup svc reset gpio */ 1597fa60654SVaibhav Hiremath arche_pdata->is_reset_act_hi = of_property_read_bool(np, 1607fa60654SVaibhav Hiremath "svc,reset-active-high"); 1617fa60654SVaibhav Hiremath arche_pdata->svc_reset_gpio = of_get_named_gpio(np, "svc,reset-gpio", 0); 1627fa60654SVaibhav Hiremath if (arche_pdata->svc_reset_gpio < 0) { 1637fa60654SVaibhav Hiremath dev_err(dev, "failed to get reset-gpio\n"); 164f1f251b5SViresh Kumar return arche_pdata->svc_reset_gpio; 1657fa60654SVaibhav Hiremath } 1667fa60654SVaibhav Hiremath ret = devm_gpio_request(dev, arche_pdata->svc_reset_gpio, "svc-reset"); 1677fa60654SVaibhav Hiremath if (ret) { 1687fa60654SVaibhav Hiremath dev_err(dev, "failed to request svc-reset gpio:%d\n", ret); 1697fa60654SVaibhav Hiremath return ret; 1707fa60654SVaibhav Hiremath } 1717fa60654SVaibhav Hiremath ret = gpio_direction_output(arche_pdata->svc_reset_gpio, 1727fa60654SVaibhav Hiremath arche_pdata->is_reset_act_hi); 1737fa60654SVaibhav Hiremath if (ret) { 1747fa60654SVaibhav Hiremath dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret); 1757fa60654SVaibhav Hiremath return ret; 1767fa60654SVaibhav Hiremath } 177e74d04a5SVaibhav Hiremath arche_pdata->state = ARCHE_PLATFORM_STATE_OFF; 1787fa60654SVaibhav Hiremath 1797fa60654SVaibhav Hiremath arche_pdata->svc_sysboot_gpio = of_get_named_gpio(np, 1807fa60654SVaibhav Hiremath "svc,sysboot-gpio", 0); 1817fa60654SVaibhav Hiremath if (arche_pdata->svc_sysboot_gpio < 0) { 1827fa60654SVaibhav Hiremath dev_err(dev, "failed to get sysboot gpio\n"); 183f1f251b5SViresh Kumar return arche_pdata->svc_sysboot_gpio; 1847fa60654SVaibhav Hiremath } 1857fa60654SVaibhav Hiremath ret = devm_gpio_request(dev, arche_pdata->svc_sysboot_gpio, "sysboot0"); 1867fa60654SVaibhav Hiremath if (ret) { 1877fa60654SVaibhav Hiremath dev_err(dev, "failed to request sysboot0 gpio:%d\n", ret); 1887fa60654SVaibhav Hiremath return ret; 1897fa60654SVaibhav Hiremath } 1907fa60654SVaibhav Hiremath ret = gpio_direction_output(arche_pdata->svc_sysboot_gpio, 0); 1917fa60654SVaibhav Hiremath if (ret) { 1927fa60654SVaibhav Hiremath dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret); 1937fa60654SVaibhav Hiremath return ret; 1947fa60654SVaibhav Hiremath } 1957fa60654SVaibhav Hiremath 1967fa60654SVaibhav Hiremath /* setup the clock request gpio first */ 1977fa60654SVaibhav Hiremath arche_pdata->svc_refclk_req = of_get_named_gpio(np, 1987fa60654SVaibhav Hiremath "svc,refclk-req-gpio", 0); 1997fa60654SVaibhav Hiremath if (arche_pdata->svc_refclk_req < 0) { 2007fa60654SVaibhav Hiremath dev_err(dev, "failed to get svc clock-req gpio\n"); 201f1f251b5SViresh Kumar return arche_pdata->svc_refclk_req; 2027fa60654SVaibhav Hiremath } 2037fa60654SVaibhav Hiremath ret = devm_gpio_request(dev, arche_pdata->svc_refclk_req, "svc-clk-req"); 2047fa60654SVaibhav Hiremath if (ret) { 2057fa60654SVaibhav Hiremath dev_err(dev, "failed to request svc-clk-req gpio: %d\n", ret); 2067fa60654SVaibhav Hiremath return ret; 2077fa60654SVaibhav Hiremath } 2087fa60654SVaibhav Hiremath ret = gpio_direction_input(arche_pdata->svc_refclk_req); 2097fa60654SVaibhav Hiremath if (ret) { 2107fa60654SVaibhav Hiremath dev_err(dev, "failed to set svc-clk-req gpio dir :%d\n", ret); 2117fa60654SVaibhav Hiremath return ret; 2127fa60654SVaibhav Hiremath } 2137fa60654SVaibhav Hiremath 2147fa60654SVaibhav Hiremath /* setup refclk2 to follow the pin */ 2157fa60654SVaibhav Hiremath arche_pdata->svc_ref_clk = devm_clk_get(dev, "svc_ref_clk"); 2167fa60654SVaibhav Hiremath if (IS_ERR(arche_pdata->svc_ref_clk)) { 2177fa60654SVaibhav Hiremath ret = PTR_ERR(arche_pdata->svc_ref_clk); 2187fa60654SVaibhav Hiremath dev_err(dev, "failed to get svc_ref_clk: %d\n", ret); 2197fa60654SVaibhav Hiremath return ret; 2207fa60654SVaibhav Hiremath } 2217fa60654SVaibhav Hiremath 2227fa60654SVaibhav Hiremath platform_set_drvdata(pdev, arche_pdata); 2237fa60654SVaibhav Hiremath 2247fa60654SVaibhav Hiremath arche_pdata->num_apbs = of_get_child_count(np); 2257fa60654SVaibhav Hiremath dev_dbg(dev, "Number of APB's available - %d\n", arche_pdata->num_apbs); 2267fa60654SVaibhav Hiremath 227a463fc15SVaibhav Hiremath arche_pdata->wake_detect_gpio = of_get_named_gpio(np, "svc,wake-detect-gpio", 0); 228a463fc15SVaibhav Hiremath if (arche_pdata->wake_detect_gpio < 0) { 229a463fc15SVaibhav Hiremath dev_err(dev, "failed to get wake detect gpio\n"); 230a463fc15SVaibhav Hiremath ret = arche_pdata->wake_detect_gpio; 231758ca99dSVaibhav Hiremath return ret; 23272a8c24bSViresh Kumar } 2337fa60654SVaibhav Hiremath 234a463fc15SVaibhav Hiremath ret = devm_gpio_request(dev, arche_pdata->wake_detect_gpio, "wake detect"); 235a463fc15SVaibhav Hiremath if (ret) { 236a463fc15SVaibhav Hiremath dev_err(dev, "Failed requesting wake_detect gpio %d\n", 237a463fc15SVaibhav Hiremath arche_pdata->wake_detect_gpio); 238758ca99dSVaibhav Hiremath return ret; 239a463fc15SVaibhav Hiremath } 240057aad29SMichael Scott /* deassert wake detect */ 241057aad29SMichael Scott gpio_direction_output(arche_pdata->wake_detect_gpio, 0); 242a463fc15SVaibhav Hiremath 243a463fc15SVaibhav Hiremath arche_pdata->dev = &pdev->dev; 244a463fc15SVaibhav Hiremath INIT_DELAYED_WORK(&arche_pdata->delayed_work, svc_delayed_work); 245a463fc15SVaibhav Hiremath schedule_delayed_work(&arche_pdata->delayed_work, msecs_to_jiffies(2000)); 246a463fc15SVaibhav Hiremath 247758ca99dSVaibhav Hiremath ret = arche_platform_coldboot_seq(arche_pdata); 248758ca99dSVaibhav Hiremath if (ret) { 249758ca99dSVaibhav Hiremath dev_err(dev, "Failed to cold boot svc %d\n", ret); 250758ca99dSVaibhav Hiremath return ret; 251758ca99dSVaibhav Hiremath } 252758ca99dSVaibhav Hiremath 2538adf71d1SViresh Kumar export_gpios(arche_pdata); 2548adf71d1SViresh Kumar 2557fa60654SVaibhav Hiremath dev_info(dev, "Device registered successfully\n"); 25672a8c24bSViresh Kumar return 0; 2577fa60654SVaibhav Hiremath } 2587fa60654SVaibhav Hiremath 259bc142bbbSVaibhav Hiremath static int arche_remove_child(struct device *dev, void *unused) 260bc142bbbSVaibhav Hiremath { 261bc142bbbSVaibhav Hiremath struct platform_device *pdev = to_platform_device(dev); 262bc142bbbSVaibhav Hiremath 263bc142bbbSVaibhav Hiremath platform_device_unregister(pdev); 264bc142bbbSVaibhav Hiremath 265bc142bbbSVaibhav Hiremath return 0; 266bc142bbbSVaibhav Hiremath } 267bc142bbbSVaibhav Hiremath 2687fa60654SVaibhav Hiremath static int arche_platform_remove(struct platform_device *pdev) 2697fa60654SVaibhav Hiremath { 2707fa60654SVaibhav Hiremath struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev); 2717fa60654SVaibhav Hiremath 27249e6e04bSVaibhav Hiremath cancel_delayed_work_sync(&arche_pdata->delayed_work); 273bc142bbbSVaibhav Hiremath device_for_each_child(&pdev->dev, NULL, arche_remove_child); 2745993e2bfSVaibhav Hiremath arche_platform_poweroff_seq(arche_pdata); 2757fa60654SVaibhav Hiremath platform_set_drvdata(pdev, NULL); 2766da86df3SVaibhav Hiremath unexport_gpios(arche_pdata); 2777fa60654SVaibhav Hiremath 2787fa60654SVaibhav Hiremath return 0; 2797fa60654SVaibhav Hiremath } 2807fa60654SVaibhav Hiremath 2817fa60654SVaibhav Hiremath static int arche_platform_suspend(struct device *dev) 2827fa60654SVaibhav Hiremath { 2837fa60654SVaibhav Hiremath /* 2847fa60654SVaibhav Hiremath * If timing profile premits, we may shutdown bridge 2857fa60654SVaibhav Hiremath * completely 2867fa60654SVaibhav Hiremath * 2877fa60654SVaibhav Hiremath * TODO: sequence ?? 2887fa60654SVaibhav Hiremath * 2897fa60654SVaibhav Hiremath * Also, need to make sure we meet precondition for unipro suspend 2907fa60654SVaibhav Hiremath * Precondition: Definition ??? 2917fa60654SVaibhav Hiremath */ 2927fa60654SVaibhav Hiremath return 0; 2937fa60654SVaibhav Hiremath } 2947fa60654SVaibhav Hiremath 2957fa60654SVaibhav Hiremath static int arche_platform_resume(struct device *dev) 2967fa60654SVaibhav Hiremath { 2977fa60654SVaibhav Hiremath /* 2987fa60654SVaibhav Hiremath * Atleast for ES2 we have to meet the delay requirement between 2997fa60654SVaibhav Hiremath * unipro switch and AP bridge init, depending on whether bridge is in 3007fa60654SVaibhav Hiremath * OFF state or standby state. 3017fa60654SVaibhav Hiremath * 3027fa60654SVaibhav Hiremath * Based on whether bridge is in standby or OFF state we may have to 3037fa60654SVaibhav Hiremath * assert multiple signals. Please refer to WDM spec, for more info. 3047fa60654SVaibhav Hiremath * 3057fa60654SVaibhav Hiremath */ 3067fa60654SVaibhav Hiremath return 0; 3077fa60654SVaibhav Hiremath } 3087fa60654SVaibhav Hiremath 3097fa60654SVaibhav Hiremath static SIMPLE_DEV_PM_OPS(arche_platform_pm_ops, 3107fa60654SVaibhav Hiremath arche_platform_suspend, 3117fa60654SVaibhav Hiremath arche_platform_resume); 3127fa60654SVaibhav Hiremath 3137fa60654SVaibhav Hiremath static struct of_device_id arche_platform_of_match[] = { 3147fa60654SVaibhav Hiremath { .compatible = "google,arche-platform", }, /* Use PID/VID of SVC device */ 3157fa60654SVaibhav Hiremath { }, 3167fa60654SVaibhav Hiremath }; 3171e5dd1f8SGreg Kroah-Hartman 3181e5dd1f8SGreg Kroah-Hartman static struct of_device_id arche_apb_ctrl_of_match[] = { 3191e5dd1f8SGreg Kroah-Hartman { .compatible = "usbffff,2", }, 3201e5dd1f8SGreg Kroah-Hartman { }, 3211e5dd1f8SGreg Kroah-Hartman }; 3221e5dd1f8SGreg Kroah-Hartman 3231e5dd1f8SGreg Kroah-Hartman static struct of_device_id arche_combined_id[] = { 3241e5dd1f8SGreg Kroah-Hartman { .compatible = "google,arche-platform", }, /* Use PID/VID of SVC device */ 3251e5dd1f8SGreg Kroah-Hartman { .compatible = "usbffff,2", }, 3261e5dd1f8SGreg Kroah-Hartman { }, 3271e5dd1f8SGreg Kroah-Hartman }; 3281e5dd1f8SGreg Kroah-Hartman MODULE_DEVICE_TABLE(of, arche_combined_id); 3297fa60654SVaibhav Hiremath 3307fa60654SVaibhav Hiremath static struct platform_driver arche_platform_device_driver = { 3317fa60654SVaibhav Hiremath .probe = arche_platform_probe, 3327fa60654SVaibhav Hiremath .remove = arche_platform_remove, 3337fa60654SVaibhav Hiremath .driver = { 3347fa60654SVaibhav Hiremath .name = "arche-platform-ctrl", 3357fa60654SVaibhav Hiremath .pm = &arche_platform_pm_ops, 3361e5dd1f8SGreg Kroah-Hartman .of_match_table = arche_platform_of_match, 3377fa60654SVaibhav Hiremath } 3387fa60654SVaibhav Hiremath }; 3397fa60654SVaibhav Hiremath 3401e5dd1f8SGreg Kroah-Hartman static struct platform_driver arche_apb_ctrl_device_driver = { 3411e5dd1f8SGreg Kroah-Hartman .probe = arche_apb_ctrl_probe, 3421e5dd1f8SGreg Kroah-Hartman .remove = arche_apb_ctrl_remove, 3431e5dd1f8SGreg Kroah-Hartman .driver = { 3441e5dd1f8SGreg Kroah-Hartman .name = "arche-apb-ctrl", 3451e5dd1f8SGreg Kroah-Hartman .pm = &arche_apb_ctrl_pm_ops, 3461e5dd1f8SGreg Kroah-Hartman .of_match_table = arche_apb_ctrl_of_match, 3471e5dd1f8SGreg Kroah-Hartman } 3481e5dd1f8SGreg Kroah-Hartman }; 3491e5dd1f8SGreg Kroah-Hartman 3501e5dd1f8SGreg Kroah-Hartman static int __init arche_init(void) 3511e5dd1f8SGreg Kroah-Hartman { 3521e5dd1f8SGreg Kroah-Hartman int retval; 3531e5dd1f8SGreg Kroah-Hartman 3541e5dd1f8SGreg Kroah-Hartman retval = platform_driver_register(&arche_platform_device_driver); 3551e5dd1f8SGreg Kroah-Hartman if (retval) 3561e5dd1f8SGreg Kroah-Hartman return retval; 3571e5dd1f8SGreg Kroah-Hartman 3581e5dd1f8SGreg Kroah-Hartman retval = platform_driver_register(&arche_apb_ctrl_device_driver); 3591e5dd1f8SGreg Kroah-Hartman if (retval) 3601e5dd1f8SGreg Kroah-Hartman platform_driver_unregister(&arche_platform_device_driver); 3611e5dd1f8SGreg Kroah-Hartman 3621e5dd1f8SGreg Kroah-Hartman return retval; 3631e5dd1f8SGreg Kroah-Hartman } 3641e5dd1f8SGreg Kroah-Hartman module_init(arche_init); 3651e5dd1f8SGreg Kroah-Hartman 3661e5dd1f8SGreg Kroah-Hartman static void __exit arche_exit(void) 3671e5dd1f8SGreg Kroah-Hartman { 3681e5dd1f8SGreg Kroah-Hartman platform_driver_unregister(&arche_apb_ctrl_device_driver); 3691e5dd1f8SGreg Kroah-Hartman platform_driver_unregister(&arche_platform_device_driver); 3701e5dd1f8SGreg Kroah-Hartman } 3711e5dd1f8SGreg Kroah-Hartman module_exit(arche_exit); 3727fa60654SVaibhav Hiremath 3737fa60654SVaibhav Hiremath MODULE_LICENSE("GPL"); 3747fa60654SVaibhav Hiremath MODULE_AUTHOR("Vaibhav Hiremath <vaibhav.hiremath@linaro.org>"); 3757fa60654SVaibhav Hiremath MODULE_DESCRIPTION("Arche Platform Driver"); 376