blob: c2f0776f04f4f0c9ae766b3e26262ceadf2c6cdd [file] [log] [blame]
Vaibhav Hiremath5a781782015-12-16 16:29:19 +05301/*
2 * Arche Platform driver to control APB.
3 *
4 * Copyright 2014-2015 Google Inc.
5 * Copyright 2014-2015 Linaro Ltd.
6 *
7 * Released under the GPLv2 only.
8 */
9
Vaibhav Hiremath5a781782015-12-16 16:29:19 +053010#include <linux/clk.h>
Viresh Kumar3b858df2016-01-11 11:29:17 +053011#include <linux/delay.h>
12#include <linux/gpio.h>
13#include <linux/interrupt.h>
Vaibhav Hiremath5a781782015-12-16 16:29:19 +053014#include <linux/of_gpio.h>
15#include <linux/of_irq.h>
Viresh Kumar3b858df2016-01-11 11:29:17 +053016#include <linux/module.h>
Vaibhav Hiremath5a781782015-12-16 16:29:19 +053017#include <linux/pinctrl/consumer.h>
Viresh Kumar3b858df2016-01-11 11:29:17 +053018#include <linux/platform_device.h>
19#include <linux/pm.h>
20#include <linux/regulator/consumer.h>
21#include <linux/spinlock.h>
Greg Kroah-Hartman1e5dd1f2015-12-30 13:38:33 -080022#include "arche_platform.h"
Vaibhav Hiremath5a781782015-12-16 16:29:19 +053023
Vaibhav Hiremath5a781782015-12-16 16:29:19 +053024
25struct arche_apb_ctrl_drvdata {
26 /* Control GPIO signals to and from AP <=> AP Bridges */
Vaibhav Hiremath5a781782015-12-16 16:29:19 +053027 int resetn_gpio;
28 int boot_ret_gpio;
29 int pwroff_gpio;
30 int wake_in_gpio;
31 int wake_out_gpio;
32 int pwrdn_gpio;
33
Vaibhav Hirematha821adb2016-02-13 02:04:02 +053034 enum arche_platform_state state;
Vaibhav Hiremathaf3aae12016-02-13 02:04:14 +053035 bool init_disabled;
Vaibhav Hiremath5a781782015-12-16 16:29:19 +053036
37 struct regulator *vcore;
38 struct regulator *vio;
39
40 unsigned int clk_en_gpio;
41 struct clk *clk;
42
43 struct pinctrl *pinctrl;
44 struct pinctrl_state *pin_default;
Vaibhav Hiremath5a781782015-12-16 16:29:19 +053045};
46
47/*
48 * Note that these low level api's are active high
49 */
Vaibhav Hiremathf1e9cbd2016-01-11 17:41:23 +053050static inline void deassert_reset(unsigned int gpio)
Vaibhav Hiremath5a781782015-12-16 16:29:19 +053051{
52 gpio_set_value(gpio, 1);
Vaibhav Hiremathf6d6f5b2016-02-09 22:09:16 +053053 msleep(500);
Vaibhav Hiremath5a781782015-12-16 16:29:19 +053054}
55
Vaibhav Hiremathf1e9cbd2016-01-11 17:41:23 +053056static inline void assert_reset(unsigned int gpio)
Vaibhav Hiremath5a781782015-12-16 16:29:19 +053057{
58 gpio_set_value(gpio, 0);
59}
60
Vaibhav Hiremath5a781782015-12-16 16:29:19 +053061/*
62 * Note: Please do not modify the below sequence, as it is as per the spec
63 */
Vaibhav Hiremath80a057a2016-02-13 02:04:15 +053064static int coldboot_seq(struct platform_device *pdev)
Vaibhav Hiremath5a781782015-12-16 16:29:19 +053065{
66 struct device *dev = &pdev->dev;
Vaibhav Hiremath6961e042016-02-13 02:04:12 +053067 struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
Vaibhav Hiremath5a781782015-12-16 16:29:19 +053068 int ret;
69
Vaibhav Hiremathc5e7cba2016-02-22 17:27:26 +053070 if (apb->init_disabled ||
71 apb->state == ARCHE_PLATFORM_STATE_ACTIVE)
Vaibhav Hiremathaf3aae12016-02-13 02:04:14 +053072 return 0;
73
Vaibhav Hiremath5a781782015-12-16 16:29:19 +053074 /* Hold APB in reset state */
Vaibhav Hiremath6ceed512016-02-13 02:04:09 +053075 assert_reset(apb->resetn_gpio);
Vaibhav Hiremath5a781782015-12-16 16:29:19 +053076
77 /* Enable power to APB */
Viresh Kumardcf77c32016-01-11 11:29:12 +053078 if (!IS_ERR(apb->vcore)) {
Vaibhav Hiremath5a781782015-12-16 16:29:19 +053079 ret = regulator_enable(apb->vcore);
80 if (ret) {
81 dev_err(dev, "failed to enable core regulator\n");
82 return ret;
83 }
84 }
Vaibhav Hiremathaa187d32016-01-14 02:06:47 +053085
Viresh Kumardcf77c32016-01-11 11:29:12 +053086 if (!IS_ERR(apb->vio)) {
Vaibhav Hiremath5a781782015-12-16 16:29:19 +053087 ret = regulator_enable(apb->vio);
88 if (ret) {
89 dev_err(dev, "failed to enable IO regulator\n");
Vaibhav Hiremath6ceed512016-02-13 02:04:09 +053090 return ret;
Vaibhav Hiremath5a781782015-12-16 16:29:19 +053091 }
92 }
93
Vaibhav Hiremath5a781782015-12-16 16:29:19 +053094 gpio_set_value(apb->boot_ret_gpio, 0);
Vaibhav Hiremathaa187d32016-01-14 02:06:47 +053095
96 /* On DB3 clock was not mandatory */
Vaibhav Hiremath6ceed512016-02-13 02:04:09 +053097 if (gpio_is_valid(apb->clk_en_gpio))
98 gpio_set_value(apb->clk_en_gpio, 1);
Vaibhav Hiremathaa187d32016-01-14 02:06:47 +053099
100 usleep_range(100, 200);
Vaibhav Hiremath5a781782015-12-16 16:29:19 +0530101
Vaibhav Hiremath6ceed512016-02-13 02:04:09 +0530102 /* deassert reset to APB : Active-low signal */
103 deassert_reset(apb->resetn_gpio);
104
105 apb->state = ARCHE_PLATFORM_STATE_ACTIVE;
106
Viresh Kumard2584322016-01-11 11:29:15 +0530107 return 0;
Vaibhav Hiremath5a781782015-12-16 16:29:19 +0530108}
109
Vaibhav Hiremath80a057a2016-02-13 02:04:15 +0530110static int fw_flashing_seq(struct platform_device *pdev)
Vaibhav Hiremath33d76292016-02-13 02:04:13 +0530111{
112 struct device *dev = &pdev->dev;
113 struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
114 int ret;
115
Vaibhav Hiremathc5e7cba2016-02-22 17:27:26 +0530116 if (apb->init_disabled ||
117 apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING)
Vaibhav Hiremathaf3aae12016-02-13 02:04:14 +0530118 return 0;
119
Vaibhav Hiremath33d76292016-02-13 02:04:13 +0530120 ret = regulator_enable(apb->vcore);
121 if (ret) {
122 dev_err(dev, "failed to enable core regulator\n");
123 return ret;
124 }
125
126 ret = regulator_enable(apb->vio);
127 if (ret) {
128 dev_err(dev, "failed to enable IO regulator\n");
129 return ret;
130 }
131
132 /* for flashing device should be in reset state */
133 assert_reset(apb->resetn_gpio);
134 apb->state = ARCHE_PLATFORM_STATE_FW_FLASHING;
135
136 return 0;
137}
138
Vaibhav Hiremath80a057a2016-02-13 02:04:15 +0530139static int standby_boot_seq(struct platform_device *pdev)
Vaibhav Hiremath33d76292016-02-13 02:04:13 +0530140{
141 struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
142
Vaibhav Hiremathaf3aae12016-02-13 02:04:14 +0530143 if (apb->init_disabled)
144 return 0;
145
Vaibhav Hiremathc5e7cba2016-02-22 17:27:26 +0530146 /* Even if it is in OFF state, then we do not want to change the state */
147 if (apb->state == ARCHE_PLATFORM_STATE_STANDBY ||
148 apb->state == ARCHE_PLATFORM_STATE_OFF)
Vaibhav Hiremath33d76292016-02-13 02:04:13 +0530149 return 0;
150
151 /*
152 * As per WDM spec, do nothing
153 *
154 * Pasted from WDM spec,
155 * - A falling edge on POWEROFF_L is detected (a)
156 * - WDM enters standby mode, but no output signals are changed
157 * */
158
159 /* TODO: POWEROFF_L is input to WDM module */
160 apb->state = ARCHE_PLATFORM_STATE_STANDBY;
161 return 0;
162}
163
Vaibhav Hiremath80a057a2016-02-13 02:04:15 +0530164static void poweroff_seq(struct platform_device *pdev)
Vaibhav Hiremath5667ab12016-02-13 02:04:10 +0530165{
Vaibhav Hiremath6961e042016-02-13 02:04:12 +0530166 struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
167
Vaibhav Hiremathc5e7cba2016-02-22 17:27:26 +0530168 if (apb->init_disabled || apb->state == ARCHE_PLATFORM_STATE_OFF)
Vaibhav Hiremathaf3aae12016-02-13 02:04:14 +0530169 return;
170
Vaibhav Hiremath5667ab12016-02-13 02:04:10 +0530171 /* disable the clock */
172 if (gpio_is_valid(apb->clk_en_gpio))
173 gpio_set_value(apb->clk_en_gpio, 0);
174
175 if (!IS_ERR(apb->vcore) && regulator_is_enabled(apb->vcore) > 0)
176 regulator_disable(apb->vcore);
177
178 if (!IS_ERR(apb->vio) && regulator_is_enabled(apb->vio) > 0)
179 regulator_disable(apb->vio);
180
181 /* As part of exit, put APB back in reset state */
182 assert_reset(apb->resetn_gpio);
183 apb->state = ARCHE_PLATFORM_STATE_OFF;
184
185 /* TODO: May have to send an event to SVC about this exit */
186}
187
Vaibhav Hiremath65fd5a52016-02-13 02:04:16 +0530188int apb_ctrl_coldboot(struct device *dev)
189{
190 return coldboot_seq(to_platform_device(dev));
191}
192
193int apb_ctrl_fw_flashing(struct device *dev)
194{
195 return fw_flashing_seq(to_platform_device(dev));
196}
197
198int apb_ctrl_standby_boot(struct device *dev)
199{
200 return standby_boot_seq(to_platform_device(dev));
201}
202
203void apb_ctrl_poweroff(struct device *dev)
204{
205 poweroff_seq(to_platform_device(dev));
206}
207
Vaibhav Hiremath33d76292016-02-13 02:04:13 +0530208static ssize_t state_store(struct device *dev,
209 struct device_attribute *attr, const char *buf, size_t count)
210{
211 struct platform_device *pdev = to_platform_device(dev);
212 struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
213 int ret = 0;
Vaibhav Hiremathaf3aae12016-02-13 02:04:14 +0530214 bool is_disabled;
Vaibhav Hiremath33d76292016-02-13 02:04:13 +0530215
216 if (sysfs_streq(buf, "off")) {
217 if (apb->state == ARCHE_PLATFORM_STATE_OFF)
218 return count;
219
Vaibhav Hiremath80a057a2016-02-13 02:04:15 +0530220 poweroff_seq(pdev);
Vaibhav Hiremath33d76292016-02-13 02:04:13 +0530221 } else if (sysfs_streq(buf, "active")) {
222 if (apb->state == ARCHE_PLATFORM_STATE_ACTIVE)
223 return count;
224
Vaibhav Hiremath80a057a2016-02-13 02:04:15 +0530225 poweroff_seq(pdev);
Vaibhav Hiremathaf3aae12016-02-13 02:04:14 +0530226 is_disabled = apb->init_disabled;
227 apb->init_disabled = false;
Vaibhav Hiremath80a057a2016-02-13 02:04:15 +0530228 ret = coldboot_seq(pdev);
Vaibhav Hiremathaf3aae12016-02-13 02:04:14 +0530229 if (ret)
230 apb->init_disabled = is_disabled;
Vaibhav Hiremath33d76292016-02-13 02:04:13 +0530231 } else if (sysfs_streq(buf, "standby")) {
232 if (apb->state == ARCHE_PLATFORM_STATE_STANDBY)
233 return count;
234
Vaibhav Hiremath80a057a2016-02-13 02:04:15 +0530235 ret = standby_boot_seq(pdev);
Vaibhav Hiremath33d76292016-02-13 02:04:13 +0530236 } else if (sysfs_streq(buf, "fw_flashing")) {
237 if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING)
238 return count;
239
240 /* First we want to make sure we power off everything
241 * and then enter FW flashing state */
Vaibhav Hiremath80a057a2016-02-13 02:04:15 +0530242 poweroff_seq(pdev);
243 ret = fw_flashing_seq(pdev);
Vaibhav Hiremath33d76292016-02-13 02:04:13 +0530244 } else {
245 dev_err(dev, "unknown state\n");
246 ret = -EINVAL;
247 }
248
249 return ret ? ret : count;
250}
251
252static ssize_t state_show(struct device *dev,
253 struct device_attribute *attr, char *buf)
254{
255 struct arche_apb_ctrl_drvdata *apb = dev_get_drvdata(dev);
256
257 switch (apb->state) {
258 case ARCHE_PLATFORM_STATE_OFF:
Vaibhav Hiremathaf3aae12016-02-13 02:04:14 +0530259 return sprintf(buf, "off%s\n",
260 apb->init_disabled ? ",disabled" : "");
Vaibhav Hiremath33d76292016-02-13 02:04:13 +0530261 case ARCHE_PLATFORM_STATE_ACTIVE:
262 return sprintf(buf, "active\n");
263 case ARCHE_PLATFORM_STATE_STANDBY:
264 return sprintf(buf, "standby\n");
265 case ARCHE_PLATFORM_STATE_FW_FLASHING:
266 return sprintf(buf, "fw_flashing\n");
267 default:
268 return sprintf(buf, "unknown state\n");
269 }
270}
271
272static DEVICE_ATTR_RW(state);
273
Vaibhav Hiremath5a781782015-12-16 16:29:19 +0530274static int apb_ctrl_get_devtree_data(struct platform_device *pdev,
275 struct arche_apb_ctrl_drvdata *apb)
276{
277 struct device *dev = &pdev->dev;
278 struct device_node *np = dev->of_node;
Vaibhav Hiremath6ceed512016-02-13 02:04:09 +0530279 int ret;
Vaibhav Hiremath5a781782015-12-16 16:29:19 +0530280
Vaibhav Hiremath5a781782015-12-16 16:29:19 +0530281 apb->resetn_gpio = of_get_named_gpio(np, "reset-gpios", 0);
Viresh Kumar7541c1a2016-01-11 11:29:10 +0530282 if (apb->resetn_gpio < 0) {
Vaibhav Hiremath5a781782015-12-16 16:29:19 +0530283 dev_err(dev, "failed to get reset gpio\n");
284 return apb->resetn_gpio;
285 }
Vaibhav Hiremath6ceed512016-02-13 02:04:09 +0530286 ret = devm_gpio_request_one(dev, apb->resetn_gpio,
287 GPIOF_OUT_INIT_LOW, "apb-reset");
288 if (ret) {
289 dev_err(dev, "Failed requesting reset gpio %d\n",
290 apb->resetn_gpio);
291 return ret;
292 }
Vaibhav Hiremath5a781782015-12-16 16:29:19 +0530293
294 apb->boot_ret_gpio = of_get_named_gpio(np, "boot-ret-gpios", 0);
Viresh Kumar7541c1a2016-01-11 11:29:10 +0530295 if (apb->boot_ret_gpio < 0) {
Vaibhav Hiremath5a781782015-12-16 16:29:19 +0530296 dev_err(dev, "failed to get boot retention gpio\n");
297 return apb->boot_ret_gpio;
298 }
Vaibhav Hiremath6ceed512016-02-13 02:04:09 +0530299 ret = devm_gpio_request_one(dev, apb->boot_ret_gpio,
300 GPIOF_OUT_INIT_LOW, "boot retention");
301 if (ret) {
302 dev_err(dev, "Failed requesting bootret gpio %d\n",
303 apb->boot_ret_gpio);
304 return ret;
305 }
Vaibhav Hiremath5a781782015-12-16 16:29:19 +0530306
307 /* It's not mandatory to support power management interface */
308 apb->pwroff_gpio = of_get_named_gpio(np, "pwr-off-gpios", 0);
Viresh Kumar7541c1a2016-01-11 11:29:10 +0530309 if (apb->pwroff_gpio < 0) {
Viresh Kumardb0cff52016-01-11 11:29:13 +0530310 dev_err(dev, "failed to get power off gpio\n");
Vaibhav Hiremath5a781782015-12-16 16:29:19 +0530311 return apb->pwroff_gpio;
312 }
Vaibhav Hiremath6ceed512016-02-13 02:04:09 +0530313 ret = devm_gpio_request_one(dev, apb->pwroff_gpio,
314 GPIOF_IN, "pwroff_n");
315 if (ret) {
316 dev_err(dev, "Failed requesting pwroff_n gpio %d\n",
317 apb->pwroff_gpio);
318 return ret;
319 }
Vaibhav Hiremath5a781782015-12-16 16:29:19 +0530320
321 /* Do not make clock mandatory as of now (for DB3) */
322 apb->clk_en_gpio = of_get_named_gpio(np, "clock-en-gpio", 0);
Vaibhav Hiremath6ceed512016-02-13 02:04:09 +0530323 if (apb->clk_en_gpio < 0) {
Viresh Kumardb0cff52016-01-11 11:29:13 +0530324 dev_warn(dev, "failed to get clock en gpio\n");
Vaibhav Hiremath6ceed512016-02-13 02:04:09 +0530325 } else if (gpio_is_valid(apb->clk_en_gpio)) {
326 ret = devm_gpio_request_one(dev, apb->clk_en_gpio,
327 GPIOF_OUT_INIT_LOW, "apb_clk_en");
328 if (ret) {
329 dev_warn(dev, "Failed requesting APB clock en gpio %d\n",
330 apb->clk_en_gpio);
331 return ret;
332 }
333 }
Vaibhav Hiremath5a781782015-12-16 16:29:19 +0530334
335 apb->pwrdn_gpio = of_get_named_gpio(np, "pwr-down-gpios", 0);
Viresh Kumar7541c1a2016-01-11 11:29:10 +0530336 if (apb->pwrdn_gpio < 0)
Viresh Kumardb0cff52016-01-11 11:29:13 +0530337 dev_warn(dev, "failed to get power down gpio\n");
Vaibhav Hiremath5a781782015-12-16 16:29:19 +0530338
339 /* Regulators are optional, as we may have fixed supply coming in */
340 apb->vcore = devm_regulator_get(dev, "vcore");
Viresh Kumardcf77c32016-01-11 11:29:12 +0530341 if (IS_ERR(apb->vcore))
Viresh Kumardb0cff52016-01-11 11:29:13 +0530342 dev_warn(dev, "no core regulator found\n");
Vaibhav Hiremath5a781782015-12-16 16:29:19 +0530343
344 apb->vio = devm_regulator_get(dev, "vio");
Viresh Kumardcf77c32016-01-11 11:29:12 +0530345 if (IS_ERR(apb->vio))
Viresh Kumardb0cff52016-01-11 11:29:13 +0530346 dev_warn(dev, "no IO regulator found\n");
Vaibhav Hiremath5a781782015-12-16 16:29:19 +0530347
348 apb->pinctrl = devm_pinctrl_get(&pdev->dev);
349 if (IS_ERR(apb->pinctrl)) {
350 dev_err(&pdev->dev, "could not get pinctrl handle\n");
351 return PTR_ERR(apb->pinctrl);
352 }
353 apb->pin_default = pinctrl_lookup_state(apb->pinctrl, "default");
354 if (IS_ERR(apb->pin_default)) {
355 dev_err(&pdev->dev, "could not get default pin state\n");
356 return PTR_ERR(apb->pin_default);
357 }
358
359 return 0;
360}
361
Greg Kroah-Hartman1e5dd1f2015-12-30 13:38:33 -0800362int arche_apb_ctrl_probe(struct platform_device *pdev)
Vaibhav Hiremath5a781782015-12-16 16:29:19 +0530363{
364 int ret;
365 struct arche_apb_ctrl_drvdata *apb;
366 struct device *dev = &pdev->dev;
367
368 apb = devm_kzalloc(&pdev->dev, sizeof(*apb), GFP_KERNEL);
369 if (!apb)
370 return -ENOMEM;
371
372 ret = apb_ctrl_get_devtree_data(pdev, apb);
373 if (ret) {
374 dev_err(dev, "failed to get apb devicetree data %d\n", ret);
375 return ret;
376 }
377
Vaibhav Hiremathf2222a42016-02-13 02:04:11 +0530378 /* Initially set APB to OFF state */
379 apb->state = ARCHE_PLATFORM_STATE_OFF;
Vaibhav Hiremathaf3aae12016-02-13 02:04:14 +0530380 /* Check whether device needs to be enabled on boot */
381 if (of_property_read_bool(pdev->dev.of_node, "ara,init-disable"))
382 apb->init_disabled = true;
Vaibhav Hiremathf2222a42016-02-13 02:04:11 +0530383
Vaibhav Hiremath6961e042016-02-13 02:04:12 +0530384 platform_set_drvdata(pdev, apb);
385
Vaibhav Hiremath33d76292016-02-13 02:04:13 +0530386 /* Create sysfs interface to allow user to change state dynamically */
387 ret = device_create_file(dev, &dev_attr_state);
388 if (ret) {
389 dev_err(dev, "failed to create state file in sysfs\n");
390 return ret;
391 }
392
Vaibhav Hiremath5a781782015-12-16 16:29:19 +0530393 dev_info(&pdev->dev, "Device registered successfully\n");
394 return 0;
Vaibhav Hiremath5a781782015-12-16 16:29:19 +0530395}
396
Greg Kroah-Hartman1e5dd1f2015-12-30 13:38:33 -0800397int arche_apb_ctrl_remove(struct platform_device *pdev)
Vaibhav Hiremath5a781782015-12-16 16:29:19 +0530398{
Vaibhav Hiremath33d76292016-02-13 02:04:13 +0530399 device_remove_file(&pdev->dev, &dev_attr_state);
Vaibhav Hiremath80a057a2016-02-13 02:04:15 +0530400 poweroff_seq(pdev);
Vaibhav Hiremath5a781782015-12-16 16:29:19 +0530401 platform_set_drvdata(pdev, NULL);
402
403 return 0;
404}
405
406static int arche_apb_ctrl_suspend(struct device *dev)
407{
408 /*
Viresh Kumar3b538c32016-01-11 11:29:08 +0530409 * If timing profile permits, we may shutdown bridge
Vaibhav Hiremath5a781782015-12-16 16:29:19 +0530410 * completely
411 *
412 * TODO: sequence ??
413 *
414 * Also, need to make sure we meet precondition for unipro suspend
415 * Precondition: Definition ???
416 */
417 return 0;
418}
419
420static int arche_apb_ctrl_resume(struct device *dev)
421{
422 /*
423 * Atleast for ES2 we have to meet the delay requirement between
424 * unipro switch and AP bridge init, depending on whether bridge is in
425 * OFF state or standby state.
426 *
427 * Based on whether bridge is in standby or OFF state we may have to
428 * assert multiple signals. Please refer to WDM spec, for more info.
429 *
430 */
431 return 0;
432}
433
Greg Kroah-Hartman1e5dd1f2015-12-30 13:38:33 -0800434SIMPLE_DEV_PM_OPS(arche_apb_ctrl_pm_ops,
435 arche_apb_ctrl_suspend,
436 arche_apb_ctrl_resume);