greybus: arche-platform: ensure wake-detect pin is deasserted
[linux-2.6/btrfs-unstable.git] / drivers / staging / greybus / arche-platform.c
blob4e49be837b0eea8868b4d80e6ab92bac9b8918f4
1 /*
2 * Arche Platform driver to enable Unipro link.
4 * Copyright 2014-2015 Google Inc.
5 * Copyright 2014-2015 Linaro Ltd.
7 * Released under the GPLv2 only.
8 */
10 #include <linux/clk.h>
11 #include <linux/delay.h>
12 #include <linux/gpio.h>
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/of_gpio.h>
16 #include <linux/of_platform.h>
17 #include <linux/pinctrl/consumer.h>
18 #include <linux/platform_device.h>
19 #include <linux/pm.h>
20 #include "arche_platform.h"
22 struct arche_platform_drvdata {
23 /* Control GPIO signals to and from AP <=> SVC */
24 int svc_reset_gpio;
25 bool is_reset_act_hi;
26 int svc_sysboot_gpio;
27 int wake_detect_gpio; /* bi-dir,maps to WAKE_MOD & WAKE_FRAME signals */
29 unsigned int svc_refclk_req;
30 struct clk *svc_ref_clk;
32 struct pinctrl *pinctrl;
33 struct pinctrl_state *pin_default;
35 int num_apbs;
37 struct delayed_work delayed_work;
38 struct device *dev;
41 static inline void svc_reset_onoff(unsigned int gpio, bool onoff)
43 gpio_set_value(gpio, onoff);
46 /**
47 * svc_delayed_work - Time to give SVC to boot.
49 static void svc_delayed_work(struct work_struct *work)
51 struct arche_platform_drvdata *arche_pdata =
52 container_of(work, struct arche_platform_drvdata, delayed_work.work);
53 struct device *dev = arche_pdata->dev;
54 struct device_node *np = dev->of_node;
55 int timeout = 10;
56 int ret;
59 * 1. SVC and AP boot independently, with AP<-->SVC wake/detect pin
60 * deasserted (LOW in this case)
61 * 2.1. SVC allows 360 milliseconds to elapse after switch boots to work
62 * around bug described in ENG-330.
63 * 2.2. AP asserts wake/detect pin (HIGH) (this can proceed in parallel with 2.1)
64 * 3. SVC detects assertion of wake/detect pin, and sends "wake out" signal to AP
65 * 4. AP receives "wake out" signal, takes AP Bridges through their power
66 * on reset sequence as defined in the bridge ASIC reference manuals
67 * 5. AP takes USB3613 through its power on reset sequence
68 * 6. AP enumerates AP Bridges
70 gpio_set_value(arche_pdata->wake_detect_gpio, 1);
71 gpio_direction_input(arche_pdata->wake_detect_gpio);
72 do {
73 /* Read the wake_detect GPIO, for WAKE_OUT event from SVC */
74 if (gpio_get_value(arche_pdata->wake_detect_gpio) == 0)
75 break;
77 msleep(500);
78 } while(timeout--);
80 if (timeout >= 0) {
81 ret = of_platform_populate(np, NULL, NULL, dev);
82 if (!ret)
83 /* Should we set wake_detect gpio to output again? */
84 return;
87 /* FIXME: We may want to limit retries here */
88 gpio_direction_output(arche_pdata->wake_detect_gpio, 0);
89 schedule_delayed_work(&arche_pdata->delayed_work, msecs_to_jiffies(2000));
92 /* Export gpio's to user space */
93 static void export_gpios(struct arche_platform_drvdata *arche_pdata)
95 gpio_export(arche_pdata->svc_reset_gpio, false);
96 gpio_export(arche_pdata->svc_sysboot_gpio, false);
99 static void unexport_gpios(struct arche_platform_drvdata *arche_pdata)
101 gpio_unexport(arche_pdata->svc_reset_gpio);
102 gpio_unexport(arche_pdata->svc_sysboot_gpio);
105 static void arche_platform_cleanup(struct arche_platform_drvdata *arche_pdata)
107 clk_disable_unprepare(arche_pdata->svc_ref_clk);
108 /* As part of exit, put APB back in reset state */
109 svc_reset_onoff(arche_pdata->svc_reset_gpio,
110 arche_pdata->is_reset_act_hi);
113 static int arche_platform_probe(struct platform_device *pdev)
115 struct arche_platform_drvdata *arche_pdata;
116 struct device *dev = &pdev->dev;
117 struct device_node *np = dev->of_node;
118 int ret;
120 arche_pdata = devm_kzalloc(&pdev->dev, sizeof(*arche_pdata), GFP_KERNEL);
121 if (!arche_pdata)
122 return -ENOMEM;
124 /* setup svc reset gpio */
125 arche_pdata->is_reset_act_hi = of_property_read_bool(np,
126 "svc,reset-active-high");
127 arche_pdata->svc_reset_gpio = of_get_named_gpio(np, "svc,reset-gpio", 0);
128 if (arche_pdata->svc_reset_gpio < 0) {
129 dev_err(dev, "failed to get reset-gpio\n");
130 return arche_pdata->svc_reset_gpio;
132 ret = devm_gpio_request(dev, arche_pdata->svc_reset_gpio, "svc-reset");
133 if (ret) {
134 dev_err(dev, "failed to request svc-reset gpio:%d\n", ret);
135 return ret;
137 ret = gpio_direction_output(arche_pdata->svc_reset_gpio,
138 arche_pdata->is_reset_act_hi);
139 if (ret) {
140 dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret);
141 return ret;
144 arche_pdata->svc_sysboot_gpio = of_get_named_gpio(np,
145 "svc,sysboot-gpio", 0);
146 if (arche_pdata->svc_sysboot_gpio < 0) {
147 dev_err(dev, "failed to get sysboot gpio\n");
148 return arche_pdata->svc_sysboot_gpio;
150 ret = devm_gpio_request(dev, arche_pdata->svc_sysboot_gpio, "sysboot0");
151 if (ret) {
152 dev_err(dev, "failed to request sysboot0 gpio:%d\n", ret);
153 return ret;
155 ret = gpio_direction_output(arche_pdata->svc_sysboot_gpio, 0);
156 if (ret) {
157 dev_err(dev, "failed to set svc-reset gpio dir:%d\n", ret);
158 return ret;
161 /* setup the clock request gpio first */
162 arche_pdata->svc_refclk_req = of_get_named_gpio(np,
163 "svc,refclk-req-gpio", 0);
164 if (arche_pdata->svc_refclk_req < 0) {
165 dev_err(dev, "failed to get svc clock-req gpio\n");
166 return arche_pdata->svc_refclk_req;
168 ret = devm_gpio_request(dev, arche_pdata->svc_refclk_req, "svc-clk-req");
169 if (ret) {
170 dev_err(dev, "failed to request svc-clk-req gpio: %d\n", ret);
171 return ret;
173 ret = gpio_direction_input(arche_pdata->svc_refclk_req);
174 if (ret) {
175 dev_err(dev, "failed to set svc-clk-req gpio dir :%d\n", ret);
176 return ret;
179 /* setup refclk2 to follow the pin */
180 arche_pdata->svc_ref_clk = devm_clk_get(dev, "svc_ref_clk");
181 if (IS_ERR(arche_pdata->svc_ref_clk)) {
182 ret = PTR_ERR(arche_pdata->svc_ref_clk);
183 dev_err(dev, "failed to get svc_ref_clk: %d\n", ret);
184 return ret;
186 ret = clk_prepare_enable(arche_pdata->svc_ref_clk);
187 if (ret) {
188 dev_err(dev, "failed to enable svc_ref_clk: %d\n", ret);
189 return ret;
192 platform_set_drvdata(pdev, arche_pdata);
194 /* bring SVC out of reset */
195 svc_reset_onoff(arche_pdata->svc_reset_gpio,
196 !arche_pdata->is_reset_act_hi);
198 arche_pdata->num_apbs = of_get_child_count(np);
199 dev_dbg(dev, "Number of APB's available - %d\n", arche_pdata->num_apbs);
201 arche_pdata->wake_detect_gpio = of_get_named_gpio(np, "svc,wake-detect-gpio", 0);
202 if (arche_pdata->wake_detect_gpio < 0) {
203 dev_err(dev, "failed to get wake detect gpio\n");
204 ret = arche_pdata->wake_detect_gpio;
205 goto exit;
208 ret = devm_gpio_request(dev, arche_pdata->wake_detect_gpio, "wake detect");
209 if (ret) {
210 dev_err(dev, "Failed requesting wake_detect gpio %d\n",
211 arche_pdata->wake_detect_gpio);
212 goto exit;
214 /* deassert wake detect */
215 gpio_direction_output(arche_pdata->wake_detect_gpio, 0);
217 arche_pdata->dev = &pdev->dev;
218 INIT_DELAYED_WORK(&arche_pdata->delayed_work, svc_delayed_work);
219 schedule_delayed_work(&arche_pdata->delayed_work, msecs_to_jiffies(2000));
221 export_gpios(arche_pdata);
223 dev_info(dev, "Device registered successfully\n");
224 return 0;
226 exit:
227 arche_platform_cleanup(arche_pdata);
228 return ret;
231 static int arche_remove_child(struct device *dev, void *unused)
233 struct platform_device *pdev = to_platform_device(dev);
235 platform_device_unregister(pdev);
237 return 0;
240 static int arche_platform_remove(struct platform_device *pdev)
242 struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev);
244 device_for_each_child(&pdev->dev, NULL, arche_remove_child);
245 arche_platform_cleanup(arche_pdata);
246 platform_set_drvdata(pdev, NULL);
247 unexport_gpios(arche_pdata);
249 return 0;
252 static int arche_platform_suspend(struct device *dev)
255 * If timing profile premits, we may shutdown bridge
256 * completely
258 * TODO: sequence ??
260 * Also, need to make sure we meet precondition for unipro suspend
261 * Precondition: Definition ???
263 return 0;
266 static int arche_platform_resume(struct device *dev)
269 * Atleast for ES2 we have to meet the delay requirement between
270 * unipro switch and AP bridge init, depending on whether bridge is in
271 * OFF state or standby state.
273 * Based on whether bridge is in standby or OFF state we may have to
274 * assert multiple signals. Please refer to WDM spec, for more info.
277 return 0;
280 static SIMPLE_DEV_PM_OPS(arche_platform_pm_ops,
281 arche_platform_suspend,
282 arche_platform_resume);
284 static struct of_device_id arche_platform_of_match[] = {
285 { .compatible = "google,arche-platform", }, /* Use PID/VID of SVC device */
286 { },
289 static struct of_device_id arche_apb_ctrl_of_match[] = {
290 { .compatible = "usbffff,2", },
291 { },
294 static struct of_device_id arche_combined_id[] = {
295 { .compatible = "google,arche-platform", }, /* Use PID/VID of SVC device */
296 { .compatible = "usbffff,2", },
297 { },
299 MODULE_DEVICE_TABLE(of, arche_combined_id);
301 static struct platform_driver arche_platform_device_driver = {
302 .probe = arche_platform_probe,
303 .remove = arche_platform_remove,
304 .driver = {
305 .name = "arche-platform-ctrl",
306 .pm = &arche_platform_pm_ops,
307 .of_match_table = arche_platform_of_match,
311 static struct platform_driver arche_apb_ctrl_device_driver = {
312 .probe = arche_apb_ctrl_probe,
313 .remove = arche_apb_ctrl_remove,
314 .driver = {
315 .name = "arche-apb-ctrl",
316 .pm = &arche_apb_ctrl_pm_ops,
317 .of_match_table = arche_apb_ctrl_of_match,
321 static int __init arche_init(void)
323 int retval;
325 retval = platform_driver_register(&arche_platform_device_driver);
326 if (retval)
327 return retval;
329 retval = platform_driver_register(&arche_apb_ctrl_device_driver);
330 if (retval)
331 platform_driver_unregister(&arche_platform_device_driver);
333 return retval;
335 module_init(arche_init);
337 static void __exit arche_exit(void)
339 platform_driver_unregister(&arche_apb_ctrl_device_driver);
340 platform_driver_unregister(&arche_platform_device_driver);
342 module_exit(arche_exit);
344 MODULE_LICENSE("GPL");
345 MODULE_AUTHOR("Vaibhav Hiremath <vaibhav.hiremath@linaro.org>");
346 MODULE_DESCRIPTION("Arche Platform Driver");