summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJurijs Soloveckis <jurijs.soloveckis@stericsson.com>2011-10-17 10:21:00 +0200
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-05-22 11:03:24 +0200
commit8d9b2a925c726ad702580ced887eeb4f41f37370 (patch)
tree251f9b49a0e3225aeaf741d7fd5cb769db4e53be
parent22e8d8ce6d22656af59b4324a99bd6735de7f613 (diff)
ARM: u8500: Add control for modem and ape trace
SD-card, mipi34 and mipi60 IFs can be configured for modem or ape trace, using u-boot cmd prompt. STM drv is controlled via kernel environment vars: Example: stm.microsd=[none|modem|ape], or stm.mipi34=[none|modem|ape], or stm.mipi60=[none|modem|ape] If trace set to ape, use stm.stm_ter=N to init STM_TER reg with decimal value N (default: N=0). ST-Ericsson ID: 349677 ST-Ericsson Linux next: N/A ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ie04e4c004417c4542259e3074f1fa2fd4f00ce6d Depends-On: I7bbcf263b83338d7b05413dd9dc0ac2ec4880601 Signed-off-by: Jurijs Soloveckis <jurijs.soloveckis@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/34160 Reviewed-by: QATOOLS Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com>
-rw-r--r--arch/arm/mach-ux500/board-mop500-regulators.c1
-rw-r--r--arch/arm/mach-ux500/board-mop500-stm.c277
-rw-r--r--drivers/misc/stm.c60
-rw-r--r--include/trace/stm.h5
4 files changed, 326 insertions, 17 deletions
diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c
index 52426a42578..df34f6be694 100644
--- a/arch/arm/mach-ux500/board-mop500-regulators.c
+++ b/arch/arm/mach-ux500/board-mop500-regulators.c
@@ -63,6 +63,7 @@ static struct regulator_consumer_supply ab8500_vaux2_consumers[] = {
};
static struct regulator_consumer_supply ab8500_vaux3_consumers[] = {
+ REGULATOR_SUPPLY("v-SD-STM", "stm"),
/* External MMC slot power */
REGULATOR_SUPPLY("vmmc", "sdi0"),
};
diff --git a/arch/arm/mach-ux500/board-mop500-stm.c b/arch/arm/mach-ux500/board-mop500-stm.c
index 20d3f9a546b..d38595b11b2 100644
--- a/arch/arm/mach-ux500/board-mop500-stm.c
+++ b/arch/arm/mach-ux500/board-mop500-stm.c
@@ -13,13 +13,27 @@
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/gpio/nomadik.h>
+#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/regulator/consumer.h>
+
+#include <asm/mach-types.h>
#include <plat/pincfg.h>
#include <mach/devices.h>
-#include <linux/mfd/dbx500-prcmu.h>
#include <asm/io.h>
#include <trace/stm.h>
#include "pins-db8500.h"
+#define HREFV60_SDMMC_EN_GPIO 169
+#define HREFV60_SDMMC_1V8_3V_GPIO 5
+
+#define STM_DEVICE (&u8500_stm_device.dev)
+#define STM_ERR(msg) dev_err(STM_DEVICE, msg)
+#define STM_WARN(msg) dev_warn(STM_DEVICE, msg)
+
+static struct regulator *regulator_aux3;
+static enum stm_connection_type
+ stm_current_connection = STM_STE_INVALID_CONNECTION;
+
static pin_cfg_t mop500_stm_mipi34_pins[] = {
GPIO70_STMAPE_CLK | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP,
GPIO71_STMAPE_DAT3 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP,
@@ -40,6 +54,15 @@ static pin_cfg_t mop500_stm_mipi60_pins[] = {
GPIO159_STMAPE_DAT0,
};
+static pin_cfg_t mop500_stm_ape_microsd_pins[] = {
+ GPIO23_MS_CLK | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP,
+ GPIO24_MS_BS | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP,
+ GPIO25_MS_DAT0 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP,
+ GPIO26_MS_DAT1 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP,
+ GPIO27_MS_DAT2 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP,
+ GPIO28_MS_DAT3 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP,
+};
+
static pin_cfg_t mop500_ske_pins[] = {
GPIO153_KP_I7 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP,
GPIO154_KP_I6 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP,
@@ -59,35 +82,211 @@ static pin_cfg_t mop500_ske_pins[] = {
GPIO168_KP_O0 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW,
};
+static pin_cfg_t mop500_stm_modem_microsd_pins[] = {
+ GPIO18_GPIO | PIN_OUTPUT_LOW,
+ GPIO19_GPIO | PIN_OUTPUT_HIGH,
+ GPIO20_GPIO | PIN_OUTPUT_HIGH,
+ GPIO22_GPIO | PIN_INPUT_PULLUP,
+ GPIO23_STMMOD_CLK | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP,
+ GPIO24_UARTMOD_RXD | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP,
+ GPIO25_STMMOD_DAT0 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP,
+ GPIO26_STMMOD_DAT1 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP,
+ GPIO27_STMMOD_DAT2 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP,
+ GPIO28_STMMOD_DAT3 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP,
+};
+
+/* sdi0 (removable MMC/SD/SDIO cards) */
+static pin_cfg_t mop500_sdi0_pins[] = {
+ GPIO18_MC0_CMDDIR | PIN_OUTPUT_HIGH,
+ GPIO19_MC0_DAT0DIR | PIN_OUTPUT_HIGH,
+ GPIO20_MC0_DAT2DIR | PIN_OUTPUT_HIGH,
+
+ GPIO22_MC0_FBCLK | PIN_INPUT_NOPULL,
+ GPIO23_MC0_CLK | PIN_OUTPUT_LOW,
+ GPIO24_MC0_CMD | PIN_INPUT_PULLUP,
+ GPIO25_MC0_DAT0 | PIN_INPUT_PULLUP,
+ GPIO26_MC0_DAT1 | PIN_INPUT_PULLUP,
+ GPIO27_MC0_DAT2 | PIN_INPUT_PULLUP,
+ GPIO28_MC0_DAT3 | PIN_INPUT_PULLUP,
+};
+
static int stm_ste_disable_ape_on_mipi60(void)
{
int retval;
retval = nmk_config_pins_sleep(ARRAY_AND_SIZE(mop500_stm_mipi60_pins));
if (retval)
- pr_err("STM: Failed to disable MIPI60\n");
+ STM_ERR("Failed to disable MIPI60\n");
else {
retval = nmk_config_pins(ARRAY_AND_SIZE(mop500_ske_pins));
if (retval)
- pr_err("STM: Failed to enable SKE gpio\n");
+ STM_ERR("Failed to enable SKE gpio\n");
}
return retval;
}
-/*
- * Manage STM output pins connection (MIP34/MIPI60 connectors)
- */
+static int stm_enable_ape_microsd(void)
+{
+ int retval;
+
+ /*
+ * Configure STM APE on GPIO23,GPIO28,GPIO27,GPIO26,GPIO25
+ * On HREF board an external SD buffer exist (ST6G3244ME)
+ * to perform level conversion from 1.8v to 3.3V on SD card signals
+ * When STM is redirected on micro SD connector GPIO18,GP19,GPIO20
+ * are configured in standard GPIO mode and are used to configure
+ * direction on external SD buffer ST6G3244ME.
+ */
+
+ retval = nmk_config_pins(ARRAY_AND_SIZE(mop500_stm_ape_microsd_pins));
+ if (retval)
+ STM_ERR("Failed to enable STM APE on MICRO SD\n");
+
+ /* Enable altC1 on GPIO23-28 (STMAPE) */
+ prcmu_enable_stm_ape();
+
+ return retval;
+}
+
+static int stm_disable_ape_microsd(void)
+{
+ int retval;
+
+ /* Disable altC1 on GPIO23-28 (STMAPE) */
+ prcmu_disable_stm_ape();
+
+ /* Reconfigure GPIO for SD */
+ retval = nmk_config_pins_sleep(ARRAY_AND_SIZE(mop500_sdi0_pins));
+ if (retval)
+ STM_ERR("Failed to disable STM APE on MICRO SD "
+ "and to reconfigure GPIO for SD\n");
+
+ return retval;
+}
+
+static int stm_enable_modem_microsd(void)
+{
+ int retval;
+
+ /*
+ * Configure STM APE on GPIO23,GPIO28,GPIO27,GPIO26,GPIO25
+ * On HREF board an external SD buffer exist (ST6G3244ME)
+ * to perform level conversion from 1.8v to 3.3V on SD card
+ * signals. When STM is redirected on micro SD connector
+ * GPIO18,GP19,GPIO20 are configured in standard GPIO mode
+ * and are used to configure direction on external SD buffer
+ * ST6G3244ME.
+ */
+
+ retval = nmk_config_pins(ARRAY_AND_SIZE(mop500_stm_modem_microsd_pins));
+ if (retval)
+ STM_ERR("Failed to enable STM MODEM on MICRO SD\n");
+
+ return retval;
+}
+
+static int stm_disable_modem_microsd(void)
+{
+ int retval;
+
+ /* Reconfigure GPIO for SD */
+ retval = nmk_config_pins_sleep(ARRAY_AND_SIZE(mop500_sdi0_pins));
+ if (retval)
+ STM_ERR("Failed to disable STM MODEM on MICRO SD "
+ "and to reconfigure GPIO for SD\n");
+
+ return retval;
+}
+
+/* Enable or disable micro sd card buffers on HREF */
+static void control_level_shifter_for_microsd(int gpio_dir)
+{
+ int gpio[2];
+
+ if (machine_is_hrefv60()) {
+ gpio[0] = HREFV60_SDMMC_EN_GPIO;
+ gpio[1] = HREFV60_SDMMC_1V8_3V_GPIO;
+ } else {
+ gpio[0] = MOP500_EGPIO(17);
+ gpio[1] = MOP500_EGPIO(18);
+ }
+
+ /* Select the default 2.9V and enable / disable level shifter */
+ gpio_direction_output(gpio[1], 0);
+ gpio_direction_output(gpio[0], gpio_dir);
+}
+
+/* Enable micro sd card buffers on HREF */
+static int enable_level_shifter_for_microsd(void)
+{
+ control_level_shifter_for_microsd(1);
+ STM_WARN("Level Shifter for SD card connector on.\n");
+ return 0;
+}
+
+/* Disable micro sd card buffers on HREF */
+static int disable_level_shifter_for_microsd(void)
+{
+ control_level_shifter_for_microsd(0);
+ STM_WARN("Level Shifter for SD card connector off.\n");
+ return 0;
+}
+
+/* Enable VAUX3 to power on buffer on STM MICRO SD cable */
+static int enable_vaux3_for_microsd_cable(void)
+{
+ int error;
+
+ regulator_aux3 = regulator_get(&u8500_stm_device.dev, "v-SD-STM");
+
+ if (IS_ERR(regulator_aux3)) {
+ error = PTR_ERR(regulator_aux3);
+ STM_ERR("Failed to get regulator, supply: v-SD-STM\n");
+ return error;
+ }
+
+ error = regulator_enable(regulator_aux3);
+
+ if (error) {
+ STM_ERR("Unable to enable regulator on SD card connector\n");
+ return error;
+ }
+
+ STM_WARN("Regulator on SD card connector power on.\n");
+ return error;
+}
+
+/* Disable VAUX3 to power off buffer on STM MICRO SD cable */
+static int disable_vaux3_for_microsd_cable(void)
+{
+ int error = 0;
+
+ error = regulator_disable(regulator_aux3);
+
+ if (regulator_aux3)
+ regulator_put(regulator_aux3);
+
+ STM_WARN("Regulator for stm on SD card connector power off.\n");
+
+ return error;
+
+}
+
static int stm_ste_connection(enum stm_connection_type con_type)
{
int retval = -EINVAL;
+ /* Check if connection type has been changed */
+ if (con_type == stm_current_connection)
+ return 0;
+
if (con_type != STM_DISCONNECT) {
/* Always enable MIPI34 GPIO pins */
retval = nmk_config_pins(
ARRAY_AND_SIZE(mop500_stm_mipi34_pins));
if (retval) {
- pr_err("STM: Failed to enable MIPI34\n");
- return retval;
+ STM_ERR("Failed to enable MIPI34\n");
+ goto stm_ste_connection_error;
}
}
@@ -111,12 +310,40 @@ static int stm_ste_connection(enum stm_connection_type con_type)
/* Enable APE on MIPI60 */
retval = nmk_config_pins_sleep(ARRAY_AND_SIZE(mop500_ske_pins));
if (retval)
- pr_err("STM: Failed to disable SKE GPIO\n");
+ STM_ERR("Failed to disable SKE GPIO\n");
else {
retval = nmk_config_pins(
ARRAY_AND_SIZE(mop500_stm_mipi60_pins));
if (retval)
- pr_err("STM: Failed to enable MIPI60\n");
+ STM_ERR("Failed to enable MIPI60\n");
+ }
+ break;
+
+ case STM_STE_MODEM_ON_MICROSD:
+ /* Disable APE on micro SD */
+ retval = stm_disable_ape_microsd();
+ /* Enable modem on micro SD */
+ if (!retval)
+ retval = stm_enable_modem_microsd();
+ /* Enable SD card buffer and regulator on href */
+ if (!retval && (stm_current_connection
+ != STM_STE_APE_ON_MICROSD)) {
+ enable_level_shifter_for_microsd();
+ enable_vaux3_for_microsd_cable();
+ }
+ break;
+
+ case STM_STE_APE_ON_MICROSD:
+ /* Disable modem on micro SD */
+ retval = stm_disable_modem_microsd();
+ /* Enable ape on micro SD */
+ if (!retval)
+ retval = stm_enable_ape_microsd();
+ /* Enable SD card buffer and regulator on href */
+ if (!retval && (stm_current_connection
+ != STM_STE_MODEM_ON_MICROSD)) {
+ enable_level_shifter_for_microsd();
+ enable_vaux3_for_microsd_cable();
}
break;
@@ -124,15 +351,39 @@ static int stm_ste_connection(enum stm_connection_type con_type)
retval = nmk_config_pins_sleep(
ARRAY_AND_SIZE(mop500_stm_mipi34_pins));
if (retval)
- pr_err("STM: Failed to disable MIPI34\n");
+ STM_ERR("Failed to disable MIPI34\n");
retval = stm_ste_disable_ape_on_mipi60();
+ if (retval)
+ STM_ERR("Failed to disable MIPI60\n");
+
+ retval = stm_disable_modem_microsd();
+ if (retval)
+ STM_ERR("Failed to disable modem on microsd\n");
+
+ retval = stm_disable_ape_microsd();
+ if (retval)
+ STM_ERR("Failed to disable ape on microsd\n");
break;
default:
- pr_err("STM: bad connection type\n");
- break;
+ STM_ERR("Bad connection type\n");
+ goto stm_ste_connection_error;
+ }
+
+ /* Disable power for microsd */
+ if ((stm_current_connection == STM_STE_MODEM_ON_MICROSD)
+ || (stm_current_connection == STM_STE_APE_ON_MICROSD)) {
+ if ((con_type != STM_STE_MODEM_ON_MICROSD)
+ && (con_type != STM_STE_APE_ON_MICROSD)) {
+ disable_vaux3_for_microsd_cable();
+ disable_level_shifter_for_microsd();
+ }
}
+
+ stm_current_connection = con_type;
+
+stm_ste_connection_error:
return retval;
}
diff --git a/drivers/misc/stm.c b/drivers/misc/stm.c
index a05b2d14573..53c47c1693a 100644
--- a/drivers/misc/stm.c
+++ b/drivers/misc/stm.c
@@ -73,6 +73,33 @@ static u64 stm_printk_buf[1024/sizeof(u64)];
static arch_spinlock_t stm_buf_lock =
(arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
+static char *mipi60 = "none";
+module_param(mipi60, charp, S_IRUGO);
+MODULE_PARM_DESC(mipi60, "STM Trace to output on probe2 of mipi60 "
+ "('none' or 'ape' or 'modem')");
+
+static char *mipi34 = "none";
+module_param(mipi34, charp, S_IRUGO);
+MODULE_PARM_DESC(mipi34, "STM Trace to output on mipi34 "
+ "('none' or 'ape' or 'modem')");
+
+static char *microsd = "none";
+module_param(microsd, charp, S_IRUGO);
+MODULE_PARM_DESC(microsd, "STM Trace to output on SD card connector "
+ "('none' or 'ape' or 'modem')");
+
+static unsigned int stm_ter;
+module_param(stm_ter, uint, 0);
+MODULE_PARM_DESC(stm_ter, "Value for STM_TER (trace control register). "
+ "Should be set by user as environment variable stm.stm_ter");
+
+#define IS_APE_ON_MIPI34 (mipi34 && !strcmp(mipi34, "ape"))
+#define IS_APE_ON_MIPI60 (mipi60 && !strcmp(mipi60, "ape"))
+#define IS_APE_ON_MICROSD (microsd && !strcmp(microsd, "ape"))
+#define IS_MODEM_ON_MICROSD (microsd && !strcmp(microsd, "modem"))
+
+static int stm_connection_set(void *data, u64 val);
+
int stm_alloc_channel(int offset)
{
int channel;
@@ -251,6 +278,7 @@ EXPORT_SYMBOL(stm_trace_buffer_onchannel);
static int stm_open(struct inode *inode, struct file *file)
{
struct channel_data *channel_data;
+ int retval = 0;
channel_data = kzalloc(sizeof(struct channel_data), GFP_KERNEL);
if (channel_data == NULL)
@@ -260,7 +288,19 @@ static int stm_open(struct inode *inode, struct file *file)
channel_data->numero = -1; /* Channel not yet allocated */
file->private_data = channel_data;
- return 0;
+ /*
+ * Check if microsd is selected as trace interface
+ * and enable corresponding pins muxing.
+ */
+ if (IS_MODEM_ON_MICROSD)
+ retval = stm_connection_set(NULL, STM_STE_MODEM_ON_MICROSD);
+ else if (IS_APE_ON_MICROSD)
+ retval = stm_connection_set(NULL, STM_STE_APE_ON_MICROSD);
+
+ if (retval)
+ pr_alert("stm_open: failed to connect STM output\n");
+
+ return retval;
}
static int stm_release(struct inode *inode, struct file *file)
@@ -338,6 +378,11 @@ static void stm_enable_src(unsigned int v)
cr_val = readl(STM_CR);
cr_val &= ~STM_CLOCK_MASK;
writel(cr_val|(stm_clockdiv<<STM_CLOCK_SHIFT), STM_CR);
+ /*
+ * If the kernel argument stm_ter has been set by the boot loader
+ * all calls to stm_enable_src will be ignored
+ */
+ v = stm_ter ? stm_ter : v;
writel(v, STM_TER);
spin_unlock(&lock);
}
@@ -594,6 +639,13 @@ static int __devinit stm_probe(struct platform_device *pdev)
set_bit(CONFIG_STM_TRACE_BPRINTK_CHANNEL, stm.ch_bitmap);
#endif
+ /* Check kernel's environment parameters first */
+ if (IS_APE_ON_MIPI34)
+ stm_connection = STM_STE_APE_ON_MIPI34_NONE_ON_MIPI60;
+ else if (IS_APE_ON_MIPI60)
+ stm_connection = STM_STE_MODEM_ON_MIPI34_APE_ON_MIPI60;
+
+ /* Apply parameters to driver */
if (stm.pdata->stm_connection) {
retval = stm.pdata->stm_connection(stm_connection);
if (retval) {
@@ -661,11 +713,13 @@ static int stm_connection_show(void *data, u64 *val)
static int stm_connection_set(void *data, u64 val)
{
+ int retval = 0;
+
if (stm.pdata->stm_connection) {
stm_connection = val;
- stm.pdata->stm_connection(val);
+ retval = stm.pdata->stm_connection(val);
}
- return 0;
+ return retval;
}
DEFINE_SIMPLE_ATTRIBUTE(stm_connection_fops, stm_connection_show,
diff --git a/include/trace/stm.h b/include/trace/stm.h
index 72e9136c25e..3cf11143c0e 100644
--- a/include/trace/stm.h
+++ b/include/trace/stm.h
@@ -64,7 +64,10 @@ enum stm_connection_type {
STM_DEFAULT_CONNECTION = 1,
STM_STE_MODEM_ON_MIPI34_NONE_ON_MIPI60 = 2,
STM_STE_APE_ON_MIPI34_NONE_ON_MIPI60 = 3,
- STM_STE_MODEM_ON_MIPI34_APE_ON_MIPI60 = 4
+ STM_STE_MODEM_ON_MIPI34_APE_ON_MIPI60 = 4,
+ STM_STE_MODEM_ON_MICROSD = 5,
+ STM_STE_APE_ON_MICROSD = 6,
+ STM_STE_INVALID_CONNECTION = 0xff
};
#ifdef __KERNEL__