ARM: cpu topology: Add debugfs interface for cpu_power
[cmplus.git] / arch / arm / mach-omap2 / omap_hsi.c
blob3597e4cabec5b0ef9293bd22a052092586164b2c
1 /*
2 * arch/arm/mach-omap2/hsi.c
4 * HSI device definition
6 * Copyright (C) 2011 Texas Instruments, Inc.
7 * Original Author: Sebastien JAN <s-jan@ti.com>
9 * This package is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
13 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17 #include <linux/device.h>
18 #include <linux/platform_device.h>
19 #include <linux/err.h>
20 #include <linux/clk.h>
21 #include <linux/io.h>
22 #include <linux/gpio.h>
23 #include <linux/irq.h>
24 #include <linux/jiffies.h>
25 #include <linux/notifier.h>
26 #include <linux/hsi_driver_if.h>
28 #include <plat/omap_hsi.h>
29 #include <plat/omap_hwmod.h>
30 #include <plat/omap_device.h>
32 #include <../drivers/omap_hsi/hsi_driver.h>
33 #include "clock.h"
34 #include "mux.h"
35 #include "control.h"
36 #include "pm.h"
37 #include "dvfs.h"
39 static int omap_hsi_wakeup_enable(int hsi_port);
40 static int omap_hsi_wakeup_disable(int hsi_port);
41 #define OMAP_HSI_PLATFORM_DEVICE_DRIVER_NAME "omap_hsi"
42 #define OMAP_HSI_PLATFORM_DEVICE_NAME "omap_hsi.0"
43 #define OMAP_HSI_HWMOD_NAME "hsi"
44 #define OMAP_HSI_HWMOD_CLASSNAME "hsi"
47 #define OMAP_MUX_MODE_MASK 0x7
50 /* Hack till correct hwmod-mux api gets used */
51 #define CA_WAKE_MUX_REG (0x4a1000C2)
52 #define OMAP44XX_PADCONF_WAKEUPENABLE0 (1 << 14)
53 #define OMAP44XX_PADCONF_WAKEUPEVENT0 (1 << 15)
55 static int omap_mux_read_signal(const char *muxname)
57 u16 val = 0;
58 val = omap_readw(CA_WAKE_MUX_REG);
59 return val;
62 static int omap_mux_enable_wakeup(const char *muxname)
64 u16 val = 0;
65 val = omap_readw(CA_WAKE_MUX_REG);
66 val |= OMAP44XX_PADCONF_WAKEUPENABLE0;
67 omap_writew(val, CA_WAKE_MUX_REG);
68 return 0;
71 static int omap_mux_disable_wakeup(const char *muxname)
73 u16 val = 0;
74 val = omap_readw(CA_WAKE_MUX_REG);
75 val &= ~OMAP44XX_PADCONF_WAKEUPENABLE0;
76 omap_writew(val, CA_WAKE_MUX_REG);
77 return 0;
81 * NOTE: We abuse a little bit the struct port_ctx to use it also for
82 * initialization.
86 static struct hsi_port_ctx omap_hsi_port_ctx[] = {
87 [0] = {
88 .port_number = 1,
89 .hst.mode = HSI_MODE_FRAME,
90 .hst.flow = HSI_FLOW_SYNCHRONIZED,
91 .hst.frame_size = HSI_FRAMESIZE_DEFAULT,
92 .hst.divisor = HSI_DIVISOR_DEFAULT,
93 .hst.channels = HSI_CHANNELS_DEFAULT,
94 .hst.arb_mode = HSI_ARBMODE_ROUNDROBIN,
95 .hsr.mode = HSI_MODE_FRAME,
96 .hsr.flow = HSI_FLOW_SYNCHRONIZED,
97 .hsr.frame_size = HSI_FRAMESIZE_DEFAULT,
98 .hsr.channels = HSI_CHANNELS_DEFAULT,
99 .hsr.divisor = HSI_DIVISOR_DEFAULT,
100 .hsr.counters = HSI_COUNTERS_FT_DEFAULT |
101 HSI_COUNTERS_TB_DEFAULT |
102 HSI_COUNTERS_FB_DEFAULT,
103 .cawake_padconf_name = "usbb1_ulpitll_clk.hsi1_cawake",
104 .cawake_padconf_hsi_mode = OMAP_MUX_MODE1,
108 static struct hsi_ctrl_ctx omap_hsi_ctrl_ctx = {
109 .sysconfig = 0,
110 .gdd_gcr = 0,
111 .dll = 0,
112 .pctx = omap_hsi_port_ctx,
115 static struct hsi_platform_data omap_hsi_platform_data = {
116 .num_ports = ARRAY_SIZE(omap_hsi_port_ctx),
117 .hsi_gdd_chan_count = HSI_HSI_DMA_CHANNEL_MAX,
118 .default_hsi_fclk = HSI_DEFAULT_FCLK,
119 .fifo_mapping_strategy = HSI_FIFO_MAPPING_ALL_PORT1,
120 .ctx = &omap_hsi_ctrl_ctx,
121 .device_enable = omap_device_enable,
122 .device_idle = omap_device_idle,
123 .device_shutdown = omap_device_shutdown,
124 .device_scale = omap_device_scale,
125 .wakeup_enable = omap_hsi_wakeup_enable,
126 .wakeup_disable = omap_hsi_wakeup_disable,
127 .wakeup_is_from_hsi = omap_hsi_is_io_wakeup_from_hsi,
128 .board_suspend = omap_hsi_prepare_suspend,
132 static u32 omap_hsi_configure_errata(void)
134 u32 errata = 0;
136 if (cpu_is_omap44xx()) {
137 SET_HSI_ERRATA(errata, HSI_ERRATUM_i696_SW_RESET_FSM_STUCK);
138 SET_HSI_ERRATA(errata, HSI_ERRATUM_ixxx_3WIRES_NO_SWAKEUP);
139 SET_HSI_ERRATA(errata, HSI_ERRATUM_i702_PM_HSI_SWAKEUP);
142 return errata;
145 static struct platform_device *hsi_get_hsi_platform_device(void)
147 struct device *dev;
148 struct platform_device *pdev;
150 /* HSI_TODO: handle platform device id (or port) (0/1) */
151 dev = bus_find_device_by_name(&platform_bus_type, NULL,
152 OMAP_HSI_PLATFORM_DEVICE_NAME);
153 if (!dev) {
154 pr_debug("Could not find platform device %s\n",
155 OMAP_HSI_PLATFORM_DEVICE_NAME);
156 return 0;
159 if (!dev->driver) {
160 /* Could not find driver for platform device. */
161 return 0;
164 pdev = to_platform_device(dev);
166 return pdev;
169 static struct hsi_dev *hsi_get_hsi_controller_data(struct platform_device *pd)
171 struct hsi_dev *hsi_ctrl;
173 if (!pd)
174 return 0;
176 hsi_ctrl = (struct hsi_dev *) platform_get_drvdata(pd);
177 if (!hsi_ctrl) {
178 pr_err("Could not find HSI controller data\n");
179 return 0;
182 return hsi_ctrl;
186 * hsi_get_hsi_port_ctx_data - Returns a pointer on the port context
188 * @hsi_port - port number to obtain context. Range [1, 2]
190 * Return value :* If success: pointer on the HSI port context requested
191 * * else NULL
193 static struct hsi_port_ctx *hsi_get_hsi_port_ctx_data(int hsi_port)
195 int i;
197 for (i = 0; i < omap_hsi_platform_data.num_ports; i++)
198 if (omap_hsi_platform_data.ctx->pctx[i].port_number == hsi_port)
199 return &omap_hsi_platform_data.ctx->pctx[i];
201 return NULL;
205 * omap_hsi_is_io_pad_hsi - Indicates if IO Pad has been muxed for HSI CAWAKE
207 * @hsi_port - port number to check for HSI muxing. Range [1, 2]
209 * Return value :* 0 if CAWAKE Padconf has not been found or CAWAKE not muxed for
210 * CAWAKE
211 * * else 1
213 static int omap_hsi_is_io_pad_hsi(int hsi_port)
215 struct hsi_port_ctx *port_ctx;
216 u16 val;
218 port_ctx = hsi_get_hsi_port_ctx_data(hsi_port);
219 if (!port_ctx)
220 return 0;
222 /* Check for IO pad */
223 val = omap_mux_read_signal(port_ctx->cawake_padconf_name);
224 if (val == -ENODEV)
225 return 0;
227 /* Continue only if CAWAKE is muxed */
228 if ((val & OMAP_MUX_MODE_MASK) != port_ctx->cawake_padconf_hsi_mode)
229 return 0;
231 return 1;
235 * omap_hsi_is_io_wakeup_from_hsi - Indicates an IO wakeup from HSI CAWAKE
237 * @hsi_port - returns port number which triggered wakeup. Range [1, 2].
238 * Only valid if return value is 1 (HSI wakeup detected)
240 * Return value :* false if CAWAKE Padconf has not been found or no IOWAKEUP event
241 * occured for CAWAKE.
242 * * true if HSI wakeup detected on port *hsi_port
244 bool omap_hsi_is_io_wakeup_from_hsi(int *hsi_port)
246 struct hsi_port_ctx *port_ctx;
247 u16 val;
248 int i;
250 for (i = 0; i < omap_hsi_platform_data.num_ports; i++) {
251 port_ctx = &omap_hsi_platform_data.ctx->pctx[i];
253 /* Check for IO pad wakeup */
254 val = omap_mux_read_signal(port_ctx->cawake_padconf_name);
255 if (val == -ENODEV)
256 continue;
258 /* Continue only if CAWAKE is muxed */
259 if ((val & OMAP_MUX_MODE_MASK) !=
260 port_ctx->cawake_padconf_hsi_mode)
261 continue;
263 if (val & OMAP44XX_PADCONF_WAKEUPEVENT0) {
264 *hsi_port = port_ctx->port_number;
265 return true;
269 *hsi_port = 0;
271 return false;
275 * omap_hsi_wakeup_enable - Enable HSI wakeup feature from RET/OFF mode
277 * @hsi_port - reference to the HSI port onto which enable wakeup feature.
278 * Range [1, 2]
280 * Return value :* 0 if CAWAKE has been configured to wakeup platform
281 * * -ENODEV if CAWAKE is not muxed on padconf
283 static int omap_hsi_wakeup_enable(int hsi_port)
285 struct hsi_port_ctx *port_ctx;
286 int ret = -ENODEV;
288 if (omap_hsi_is_io_pad_hsi(hsi_port)) {
289 port_ctx = hsi_get_hsi_port_ctx_data(hsi_port);
290 ret = omap_mux_enable_wakeup(port_ctx->cawake_padconf_name);
291 omap4_trigger_ioctrl();
292 } else {
293 pr_debug("HSI port %d not muxed, failed to enable IO wakeup\n",
294 hsi_port);
297 return ret;
301 * omap_hsi_wakeup_disable - Disable HSI wakeup feature from RET/OFF mode
303 * @hsi_port - reference to the HSI port onto which disable wakeup feature.
304 * Range [1, 2]
306 * Return value :* 0 if CAWAKE has been configured to not wakeup platform
307 * * -ENODEV if CAWAKE is not muxed on padconf
309 static int omap_hsi_wakeup_disable(int hsi_port)
311 struct hsi_port_ctx *port_ctx;
312 int ret = -ENODEV;
314 if (omap_hsi_is_io_pad_hsi(hsi_port)) {
315 port_ctx = hsi_get_hsi_port_ctx_data(hsi_port);
316 ret = omap_mux_disable_wakeup(port_ctx->cawake_padconf_name);
317 omap4_trigger_ioctrl();
318 } else {
319 pr_debug("HSI port %d not muxed, failed to disable IO wakeup\n",
320 hsi_port);
323 return ret;
327 * omap_hsi_prepare_suspend - Prepare HSI for suspend mode
329 * @hsi_port - reference to the HSI port. Range [1, 2]
330 * @dev_may_wakeup - value of sysfs flag indicating device wakeup capability
332 * Return value :* 0 if CAWAKE padconf has been configured properly
333 * * -ENODEV if CAWAKE is not muxed on padconf.
336 int omap_hsi_prepare_suspend(int hsi_port, bool dev_may_wakeup)
338 int ret;
340 if (dev_may_wakeup)
341 ret = omap_hsi_wakeup_enable(hsi_port);
342 else
343 ret = omap_hsi_wakeup_disable(hsi_port);
345 return ret;
349 * omap_hsi_io_wakeup_check - Check if IO wakeup is from HSI and schedule HSI
350 * processing tasklet
352 * Return value : * 0 if HSI tasklet scheduled.
353 * * negative value else.
355 int omap_hsi_io_wakeup_check(void)
357 int hsi_port, ret = -1;
359 /* Modem HSI wakeup */
360 if (omap_hsi_is_io_wakeup_from_hsi(&hsi_port))
361 ret = omap_hsi_wakeup(hsi_port);
363 return ret;
367 * omap_hsi_wakeup - Prepare HSI for wakeup from suspend mode (RET/OFF)
369 * @hsi_port - reference to the HSI port which triggered wakeup.
370 * Range [1, 2]
372 * Return value : * 0 if HSI tasklet scheduled.
373 * * negative value else.
375 int omap_hsi_wakeup(int hsi_port)
377 static struct platform_device *pdev;
378 static struct hsi_dev *hsi_ctrl;
379 int i;
381 if (!pdev) {
382 pdev = hsi_get_hsi_platform_device();
383 if (!pdev)
384 return -ENODEV;
387 if (!device_may_wakeup(&pdev->dev)) {
388 dev_info(&pdev->dev, "Modem not allowed to wakeup platform\n");
389 return -EPERM;
392 if (!hsi_ctrl) {
393 hsi_ctrl = hsi_get_hsi_controller_data(pdev);
394 if (!hsi_ctrl)
395 return -ENODEV;
398 for (i = 0; i < omap_hsi_platform_data.num_ports; i++) {
399 if (omap_hsi_platform_data.ctx->pctx[i].port_number == hsi_port)
400 break;
403 if (i == omap_hsi_platform_data.num_ports)
404 return -ENODEV;
407 /* Check no other interrupt handler has already scheduled the tasklet */
408 if (test_and_set_bit(HSI_FLAGS_TASKLET_LOCK,
409 &hsi_ctrl->hsi_port[i].flags))
410 return -EBUSY;
412 dev_dbg(hsi_ctrl->dev, "Modem wakeup detected from HSI CAWAKE Pad port "
413 "%d\n", hsi_port);
415 /* CAWAKE falling or rising edge detected */
416 hsi_ctrl->hsi_port[i].cawake_off_event = true;
417 tasklet_hi_schedule(&hsi_ctrl->hsi_port[i].hsi_tasklet);
419 /* Disable interrupt until Bottom Half has cleared */
420 /* the IRQ status register */
421 disable_irq_nosync(hsi_ctrl->hsi_port[i].irq);
423 return 0;
426 /* HSI_TODO : This requires some fine tuning & completion of
427 * activate/deactivate latency values
429 static struct omap_device_pm_latency omap_hsi_latency[] = {
430 [0] = {
431 .deactivate_func = omap_device_idle_hwmods,
432 .activate_func = omap_device_enable_hwmods,
433 .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
437 /* HSI device registration */
438 static int __init omap_hsi_register(struct omap_hwmod *oh, void *user)
440 struct omap_device *od;
441 struct hsi_platform_data *pdata = &omap_hsi_platform_data;
443 if (!oh) {
444 pr_err("Could not look up %s omap_hwmod\n",
445 OMAP_HSI_HWMOD_NAME);
446 return -EEXIST;
449 omap_hsi_platform_data.errata = omap_hsi_configure_errata();
451 od = omap_device_build(OMAP_HSI_PLATFORM_DEVICE_DRIVER_NAME, 0, oh,
452 pdata, sizeof(*pdata), omap_hsi_latency,
453 ARRAY_SIZE(omap_hsi_latency), false);
454 WARN(IS_ERR(od), "Can't build omap_device for %s:%s.\n",
455 OMAP_HSI_PLATFORM_DEVICE_DRIVER_NAME, oh->name);
457 pr_info("HSI: device registered as omap_hwmod: %s\n", oh->name);
458 return 0;
461 static void __init omap_4430hsi_pad_conf(void)
464 * HSI pad conf: hsi1_ca/ac_wake/flag/data/ready
465 * Also configure gpio_92/95/157/187 used by modem
467 /* hsi1_cawake */
468 omap_mux_init_signal("usbb1_ulpitll_clk.hsi1_cawake", \
469 OMAP_PIN_INPUT_PULLDOWN | \
470 OMAP_PIN_OFF_NONE | \
471 OMAP_PIN_OFF_WAKEUPENABLE);
472 /* hsi1_caflag */
473 omap_mux_init_signal("usbb1_ulpitll_dir.hsi1_caflag", \
474 OMAP_PIN_INPUT | \
475 OMAP_PIN_OFF_NONE);
476 /* hsi1_cadata */
477 omap_mux_init_signal("usbb1_ulpitll_stp.hsi1_cadata", \
478 OMAP_PIN_INPUT | \
479 OMAP_PIN_OFF_NONE);
480 /* hsi1_acready */
481 omap_mux_init_signal("usbb1_ulpitll_nxt.hsi1_acready", \
482 OMAP_PIN_OUTPUT | \
483 OMAP_OFF_EN);
484 /* hsi1_acwake */
485 omap_mux_init_signal("usbb1_ulpitll_dat0.hsi1_acwake", \
486 OMAP_PIN_OUTPUT | \
487 OMAP_OFF_EN);
488 /* hsi1_acdata */
489 omap_mux_init_signal("usbb1_ulpitll_dat1.hsi1_acdata", \
490 OMAP_PIN_OUTPUT | \
491 OMAP_OFF_EN);
492 /* hsi1_acflag */
493 omap_mux_init_signal("usbb1_ulpitll_dat2.hsi1_acflag", \
494 OMAP_PIN_OUTPUT | \
495 OMAP_OFF_EN);
496 /* hsi1_caready */
497 omap_mux_init_signal("usbb1_ulpitll_dat3.hsi1_caready", \
498 OMAP_PIN_INPUT | \
499 OMAP_PIN_OFF_NONE);
500 /* gpio_92 */
501 omap_mux_init_signal("usbb1_ulpitll_dat4.gpio_92", \
502 OMAP_PULL_ENA);
503 /* gpio_95 */
504 omap_mux_init_signal("usbb1_ulpitll_dat7.gpio_95", \
505 OMAP_PIN_INPUT_PULLDOWN | \
506 OMAP_PIN_OFF_NONE);
507 /* gpio_157 */
508 omap_mux_init_signal("usbb2_ulpitll_clk.gpio_157", \
509 OMAP_PIN_OUTPUT | \
510 OMAP_PIN_OFF_NONE);
511 /* gpio_187 */
512 omap_mux_init_signal("sys_boot3.gpio_187", \
513 OMAP_PIN_OUTPUT | \
514 OMAP_PIN_OFF_NONE);
517 int __init omap_hsi_dev_init(void)
519 /* Keep this for genericity, although there is only one hwmod for HSI */
520 return omap_hwmod_for_each_by_class(OMAP_HSI_HWMOD_CLASSNAME,
521 omap_hsi_register, NULL);
523 postcore_initcall(omap_hsi_dev_init);
525 /* HSI devices registration */
526 int __init omap_hsi_init(void)
528 omap_4430hsi_pad_conf();
529 return 0;