aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/omap_hsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/omap_hsi.c')
-rwxr-xr-x[-rw-r--r--]arch/arm/mach-omap2/omap_hsi.c191
1 files changed, 140 insertions, 51 deletions
diff --git a/arch/arm/mach-omap2/omap_hsi.c b/arch/arm/mach-omap2/omap_hsi.c
index ce8fa54..8b330cd 100644..100755
--- a/arch/arm/mach-omap2/omap_hsi.c
+++ b/arch/arm/mach-omap2/omap_hsi.c
@@ -25,8 +25,6 @@
#include <linux/notifier.h>
#include <linux/hsi_driver_if.h>
-#include <asm/clkdev.h>
-
#include <plat/omap_hsi.h>
#include <plat/omap_hwmod.h>
#include <plat/omap_device.h>
@@ -35,6 +33,8 @@
#include "clock.h"
#include "mux.h"
#include "control.h"
+#include "pm.h"
+#include "dvfs.h"
static int omap_hsi_wakeup_enable(int hsi_port);
static int omap_hsi_wakeup_disable(int hsi_port);
@@ -42,8 +42,6 @@ static int omap_hsi_wakeup_disable(int hsi_port);
#define OMAP_HSI_PLATFORM_DEVICE_NAME "omap_hsi.0"
#define OMAP_HSI_HWMOD_NAME "hsi"
#define OMAP_HSI_HWMOD_CLASSNAME "hsi"
-#define OMAP_HSI_PADCONF_CAWAKE_PIN "usbb1_ulpitll_clk.hsi1_cawake"
-#define OMAP_HSI_PADCONF_CAWAKE_MODE OMAP_MUX_MODE1
#define OMAP_MUX_MODE_MASK 0x7
@@ -85,8 +83,9 @@ static int omap_mux_disable_wakeup(const char *muxname)
*/
-static struct port_ctx hsi_port_ctx[] = {
+static struct hsi_port_ctx omap_hsi_port_ctx[] = {
[0] = {
+ .port_number = 1,
.hst.mode = HSI_MODE_FRAME,
.hst.flow = HSI_FLOW_SYNCHRONIZED,
.hst.frame_size = HSI_FRAMESIZE_DEFAULT,
@@ -101,24 +100,28 @@ static struct port_ctx hsi_port_ctx[] = {
.hsr.counters = HSI_COUNTERS_FT_DEFAULT |
HSI_COUNTERS_TB_DEFAULT |
HSI_COUNTERS_FB_DEFAULT,
+ .cawake_padconf_name = "usbb1_ulpitll_clk.hsi1_cawake",
+ .cawake_padconf_hsi_mode = OMAP_MUX_MODE1,
},
};
-static struct ctrl_ctx hsi_ctx = {
+static struct hsi_ctrl_ctx omap_hsi_ctrl_ctx = {
.sysconfig = 0,
.gdd_gcr = 0,
.dll = 0,
- .pctx = hsi_port_ctx,
+ .pctx = omap_hsi_port_ctx,
};
static struct hsi_platform_data omap_hsi_platform_data = {
- .num_ports = ARRAY_SIZE(hsi_port_ctx),
+ .num_ports = ARRAY_SIZE(omap_hsi_port_ctx),
.hsi_gdd_chan_count = HSI_HSI_DMA_CHANNEL_MAX,
.default_hsi_fclk = HSI_DEFAULT_FCLK,
- .ctx = &hsi_ctx,
+ .fifo_mapping_strategy = HSI_FIFO_MAPPING_ALL_PORT1,
+ .ctx = &omap_hsi_ctrl_ctx,
.device_enable = omap_device_enable,
.device_idle = omap_device_idle,
.device_shutdown = omap_device_shutdown,
+ .device_scale = omap_device_scale,
.wakeup_enable = omap_hsi_wakeup_enable,
.wakeup_disable = omap_hsi_wakeup_disable,
.wakeup_is_from_hsi = omap_hsi_is_io_wakeup_from_hsi,
@@ -167,23 +170,49 @@ static struct hsi_dev *hsi_get_hsi_controller_data(struct platform_device *pd)
}
/**
+* hsi_get_hsi_port_ctx_data - Returns a pointer on the port context
+*
+* @hsi_port - port number to obtain context. Range [1, 2]
+*
+* Return value :* If success: pointer on the HSI port context requested
+* * else NULL
+*/
+static struct hsi_port_ctx *hsi_get_hsi_port_ctx_data(int hsi_port)
+{
+ int i;
+
+ for (i = 0; i < omap_hsi_platform_data.num_ports; i++)
+ if (omap_hsi_platform_data.ctx->pctx[i].port_number == hsi_port)
+ return &omap_hsi_platform_data.ctx->pctx[i];
+
+ return NULL;
+}
+
+/**
* omap_hsi_is_io_pad_hsi - Indicates if IO Pad has been muxed for HSI CAWAKE
*
+* @hsi_port - port number to check for HSI muxing. Range [1, 2]
+*
* Return value :* 0 if CAWAKE Padconf has not been found or CAWAKE not muxed for
* CAWAKE
* * else 1
*/
-static int omap_hsi_is_io_pad_hsi(void)
+static int omap_hsi_is_io_pad_hsi(int hsi_port)
{
+ struct hsi_port_ctx *port_ctx;
u16 val;
+ port_ctx = hsi_get_hsi_port_ctx_data(hsi_port);
+ if (!port_ctx)
+ return 0;
+
/* Check for IO pad */
- val = omap_mux_read_signal(OMAP_HSI_PADCONF_CAWAKE_PIN);
+ val = omap_mux_read_signal(port_ctx->cawake_padconf_name);
if (val == -ENODEV)
return 0;
/* Continue only if CAWAKE is muxed */
- if ((val & OMAP_MUX_MODE_MASK) != OMAP_HSI_PADCONF_CAWAKE_MODE)
+ if ((val & OMAP_MUX_MODE_MASK) != port_ctx->cawake_padconf_hsi_mode)
return 0;
return 1;
@@ -192,49 +221,66 @@ static int omap_hsi_is_io_pad_hsi(void)
/**
* omap_hsi_is_io_wakeup_from_hsi - Indicates an IO wakeup from HSI CAWAKE
*
-* Return value :* 0 if CAWAKE Padconf has not been found or no IOWAKEUP event
-* occured for CAWAKE
-* * else 1
-* TODO : return value should indicate the HSI port which has awaken
+* @hsi_port - returns port number which triggered wakeup. Range [1, 2].
+* Only valid if return value is 1 (HSI wakeup detected)
+*
+* Return value :* false if CAWAKE Padconf has not been found or no IOWAKEUP event
+* occured for CAWAKE.
+* * true if HSI wakeup detected on port *hsi_port
*/
-int omap_hsi_is_io_wakeup_from_hsi(void)
+bool omap_hsi_is_io_wakeup_from_hsi(int *hsi_port)
{
+ struct hsi_port_ctx *port_ctx;
u16 val;
+ int i;
+
+ for (i = 0; i < omap_hsi_platform_data.num_ports; i++) {
+ port_ctx = &omap_hsi_platform_data.ctx->pctx[i];
/* Check for IO pad wakeup */
- val = omap_mux_read_signal(OMAP_HSI_PADCONF_CAWAKE_PIN);
+ val = omap_mux_read_signal(port_ctx->cawake_padconf_name);
if (val == -ENODEV)
- return 0;
+ continue;
/* Continue only if CAWAKE is muxed */
- if ((val & OMAP_MUX_MODE_MASK) != OMAP_HSI_PADCONF_CAWAKE_MODE)
- return 0;
+ if ((val & OMAP_MUX_MODE_MASK) !=
+ port_ctx->cawake_padconf_hsi_mode)
+ continue;
+
+ if (val & OMAP44XX_PADCONF_WAKEUPEVENT0) {
+ *hsi_port = port_ctx->port_number;
+ return true;
+ }
+ }
- if (val & OMAP44XX_PADCONF_WAKEUPEVENT0)
- return 1;
+ *hsi_port = 0;
- return 0;
+ return false;
}
/**
* omap_hsi_wakeup_enable - Enable HSI wakeup feature from RET/OFF mode
*
* @hsi_port - reference to the HSI port onto which enable wakeup feature.
+* Range [1, 2]
*
* Return value :* 0 if CAWAKE has been configured to wakeup platform
* * -ENODEV if CAWAKE is not muxed on padconf
*/
static int omap_hsi_wakeup_enable(int hsi_port)
{
+ struct hsi_port_ctx *port_ctx;
int ret = -ENODEV;
- if (omap_hsi_is_io_pad_hsi())
- ret = omap_mux_enable_wakeup(OMAP_HSI_PADCONF_CAWAKE_PIN);
- else
- pr_debug("Trying to enable HSI IO wakeup on non HSI board\n");
-
+ if (omap_hsi_is_io_pad_hsi(hsi_port)) {
+ port_ctx = hsi_get_hsi_port_ctx_data(hsi_port);
+ ret = omap_mux_enable_wakeup(port_ctx->cawake_padconf_name);
+ omap4_trigger_ioctrl();
+ } else {
+ pr_debug("HSI port %d not muxed, failed to enable IO wakeup\n",
+ hsi_port);
+ }
- /* TODO: handle hsi_port param and use it to find the correct Pad */
return ret;
}
@@ -242,21 +288,24 @@ static int omap_hsi_wakeup_enable(int hsi_port)
* omap_hsi_wakeup_disable - Disable HSI wakeup feature from RET/OFF mode
*
* @hsi_port - reference to the HSI port onto which disable wakeup feature.
+* Range [1, 2]
*
* Return value :* 0 if CAWAKE has been configured to not wakeup platform
* * -ENODEV if CAWAKE is not muxed on padconf
*/
static int omap_hsi_wakeup_disable(int hsi_port)
{
+ struct hsi_port_ctx *port_ctx;
int ret = -ENODEV;
- if (omap_hsi_is_io_pad_hsi())
- ret = omap_mux_disable_wakeup(OMAP_HSI_PADCONF_CAWAKE_PIN);
- else
- pr_debug("Trying to disable HSI IO wakeup on non HSI board\n");
-
-
- /* TODO: handle hsi_port param and use it to find the correct Pad */
+ if (omap_hsi_is_io_pad_hsi(hsi_port)) {
+ port_ctx = hsi_get_hsi_port_ctx_data(hsi_port);
+ ret = omap_mux_disable_wakeup(port_ctx->cawake_padconf_name);
+ omap4_trigger_ioctrl();
+ } else {
+ pr_debug("HSI port %d not muxed, failed to disable IO wakeup\n",
+ hsi_port);
+ }
return ret;
}
@@ -264,6 +313,9 @@ static int omap_hsi_wakeup_disable(int hsi_port)
/**
* omap_hsi_prepare_suspend - Prepare HSI for suspend mode
*
+* @hsi_port - reference to the HSI port. Range [1, 2]
+* @dev_may_wakeup - value of sysfs flag indicating device wakeup capability
+*
* Return value :* 0 if CAWAKE padconf has been configured properly
* * -ENODEV if CAWAKE is not muxed on padconf.
*
@@ -281,42 +333,79 @@ int omap_hsi_prepare_suspend(int hsi_port, bool dev_may_wakeup)
}
/**
+* omap_hsi_io_wakeup_check - Check if IO wakeup is from HSI and schedule HSI
+* processing tasklet
+*
+* Return value : * 0 if HSI tasklet scheduled.
+* * negative value else.
+*/
+int omap_hsi_io_wakeup_check(void)
+{
+ int hsi_port, ret = -1;
+
+ /* Modem HSI wakeup */
+ if (omap_hsi_is_io_wakeup_from_hsi(&hsi_port))
+ ret = omap_hsi_wakeup(hsi_port);
+
+ return ret;
+}
+
+/**
* omap_hsi_wakeup - Prepare HSI for wakeup from suspend mode (RET/OFF)
*
-* Return value : 1 if IO wakeup source is HSI
-* 0 if IO wakeup source is not HSI.
+* @hsi_port - reference to the HSI port which triggered wakeup.
+* Range [1, 2]
+*
+* Return value : * 0 if HSI tasklet scheduled.
+* * negative value else.
*/
int omap_hsi_wakeup(int hsi_port)
{
static struct platform_device *pdev;
static struct hsi_dev *hsi_ctrl;
+ int i;
if (!pdev) {
- pdev = hsi_get_hsi_platform_device();
+ pdev = hsi_get_hsi_platform_device();
if (!pdev)
- return -ENODEV;
-}
+ return -ENODEV;
+ }
if (!device_may_wakeup(&pdev->dev)) {
- dev_info(&pdev->dev, "Modem not allowed to wakeup platform");
+ dev_info(&pdev->dev, "Modem not allowed to wakeup platform\n");
return -EPERM;
}
if (!hsi_ctrl) {
- hsi_ctrl = hsi_get_hsi_controller_data(pdev);
- if (!hsi_ctrl)
- return -ENODEV;
+ hsi_ctrl = hsi_get_hsi_controller_data(pdev);
+ if (!hsi_ctrl)
+ return -ENODEV;
}
- dev_dbg(hsi_ctrl->dev, "Modem wakeup detected from HSI CAWAKE Pad");
+ for (i = 0; i < omap_hsi_platform_data.num_ports; i++) {
+ if (omap_hsi_platform_data.ctx->pctx[i].port_number == hsi_port)
+ break;
+ }
+
+ if (i == omap_hsi_platform_data.num_ports)
+ return -ENODEV;
+
+
+ /* Check no other interrupt handler has already scheduled the tasklet */
+ if (test_and_set_bit(HSI_FLAGS_TASKLET_LOCK,
+ &hsi_ctrl->hsi_port[i].flags))
+ return -EBUSY;
+
+ dev_dbg(hsi_ctrl->dev, "Modem wakeup detected from HSI CAWAKE Pad port "
+ "%d\n", hsi_port);
/* CAWAKE falling or rising edge detected */
- hsi_ctrl->hsi_port->cawake_off_event = true;
- tasklet_hi_schedule(&hsi_ctrl->hsi_port->hsi_tasklet);
+ hsi_ctrl->hsi_port[i].cawake_off_event = true;
+ tasklet_hi_schedule(&hsi_ctrl->hsi_port[i].hsi_tasklet);
/* Disable interrupt until Bottom Half has cleared */
/* the IRQ status register */
- disable_irq_nosync(hsi_ctrl->hsi_port->irq);
+ disable_irq_nosync(hsi_ctrl->hsi_port[i].irq);
return 0;
}
@@ -376,7 +465,7 @@ static void __init omap_4430hsi_pad_conf(void)
/* hsi1_acready */
omap_mux_init_signal("usbb1_ulpitll_nxt.hsi1_acready", \
OMAP_PIN_OUTPUT | \
- OMAP_PIN_OFF_OUTPUT_LOW);
+ OMAP_OFF_EN);
/* hsi1_acwake */
omap_mux_init_signal("usbb1_ulpitll_dat0.hsi1_acwake", \
OMAP_PIN_OUTPUT | \