summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/configs/tegra3_android_defconfig6
-rw-r--r--arch/arm/configs/tegra_android_defconfig2
-rw-r--r--arch/arm/configs/tegra_p1852_gnu_linux_defconfig1
-rw-r--r--arch/arm/mach-tegra/Kconfig10
-rw-r--r--arch/arm/mach-tegra/Makefile1
-rw-r--r--arch/arm/mach-tegra/baseband-xmm-power.c118
-rw-r--r--arch/arm/mach-tegra/baseband-xmm-power.h3
-rw-r--r--arch/arm/mach-tegra/board-aruba-power.c1
-rw-r--r--arch/arm/mach-tegra/board-cardhu-pm298-power-rails.c4
-rw-r--r--arch/arm/mach-tegra/board-cardhu-pm299-power-rails.c4
-rw-r--r--arch/arm/mach-tegra/board-cardhu-power.c4
-rw-r--r--arch/arm/mach-tegra/board-cardhu-sdhci.c1
-rw-r--r--arch/arm/mach-tegra/board-enterprise-baseband.c62
-rw-r--r--arch/arm/mach-tegra/board-enterprise-power.c4
-rw-r--r--arch/arm/mach-tegra/board-enterprise.c3
-rw-r--r--arch/arm/mach-tegra/board-kai-kbc.c7
-rw-r--r--arch/arm/mach-tegra/board-kai-panel.c13
-rw-r--r--arch/arm/mach-tegra/board-kai-pinmux.c5
-rw-r--r--arch/arm/mach-tegra/board-kai-power.c3
-rw-r--r--arch/arm/mach-tegra/board-kai-sdhci.c4
-rw-r--r--arch/arm/mach-tegra/board-kai-sensors.c7
-rw-r--r--arch/arm/mach-tegra/board-kai.c16
-rw-r--r--arch/arm/mach-tegra/board-p1852-pinmux.c53
-rw-r--r--arch/arm/mach-tegra/board-p1852.c36
-rw-r--r--arch/arm/mach-tegra/board-ventana-panel.c8
-rw-r--r--arch/arm/mach-tegra/board-ventana-power.c13
-rw-r--r--arch/arm/mach-tegra/board-ventana-sdhci.c13
-rw-r--r--arch/arm/mach-tegra/board-ventana-sensors.c41
-rw-r--r--arch/arm/mach-tegra/board-ventana.c19
-rw-r--r--arch/arm/mach-tegra/board-whistler-baseband.c60
-rw-r--r--arch/arm/mach-tegra/board-whistler-power.c1
-rw-r--r--arch/arm/mach-tegra/board-whistler-sdhci.c1
-rw-r--r--arch/arm/mach-tegra/board-whistler.c2
-rw-r--r--arch/arm/mach-tegra/cpu-tegra3.c9
-rw-r--r--arch/arm/mach-tegra/devices.c5
-rw-r--r--arch/arm/mach-tegra/devices.h1
-rw-r--r--arch/arm/mach-tegra/include/mach/dc.h1
-rw-r--r--arch/arm/mach-tegra/include/mach/sdhci.h8
-rw-r--r--arch/arm/mach-tegra/include/mach/tegra_p1852_pdata.h1
-rw-r--r--arch/arm/mach-tegra/p852/board-p852.h1
-rw-r--r--arch/arm/mach-tegra/pcie.c58
-rw-r--r--arch/arm/mach-tegra/pinmux-t3-tables.c29
-rw-r--r--arch/arm/mach-tegra/pm-irq.c1
-rw-r--r--arch/arm/mach-tegra/pm-irq.h2
-rw-r--r--arch/arm/mach-tegra/tegra2_usb_phy.c192
-rw-r--r--arch/arm/mach-tegra/tegra3_dvfs.c4
-rw-r--r--arch/arm/mach-tegra/tegra3_usb_phy.c141
-rw-r--r--arch/arm/mach-tegra/tegra_usb_phy.h1
-rw-r--r--arch/arm/mach-tegra/usb_phy.c68
-rw-r--r--arch/arm/mach-tegra/wakeups-t2.c57
-rw-r--r--arch/arm/mach-tegra/wakeups-t2.h62
-rw-r--r--arch/arm/mach-tegra/wakeups-t3.c57
-rw-r--r--arch/arm/mach-tegra/wakeups-t3.h76
-rw-r--r--arch/arm/mach-tegra/wakeups.c85
-rw-r--r--arch/arm/mach-tegra/wakeups.h29
-rw-r--r--drivers/crypto/tegra-se.c9
-rw-r--r--drivers/gpio/Kconfig9
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-rc5t583.c180
-rw-r--r--drivers/gpio/gpio-tps65910.c152
-rw-r--r--drivers/media/video/tegra/ad5816.c11
-rw-r--r--drivers/media/video/tegra/nvavp/Kconfig11
-rw-r--r--drivers/media/video/tegra/nvavp/nvavp_dev.c515
-rw-r--r--drivers/media/video/tegra/ov2710.c162
-rw-r--r--drivers/media/video/tegra/sh532u.c2
-rw-r--r--drivers/mfd/Kconfig1
-rw-r--r--drivers/mfd/rc5t583.c47
-rw-r--r--drivers/mfd/tps65910-irq.c34
-rw-r--r--drivers/mfd/tps65910.c218
-rw-r--r--drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.c2
-rw-r--r--drivers/regulator/Kconfig10
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/rc5t583-regulator.c363
-rw-r--r--drivers/regulator/tps62360-regulator.c286
-rw-r--r--drivers/regulator/tps65910-regulator.c88
-rw-r--r--drivers/rtc/rtc-tps80031.c49
-rw-r--r--drivers/tty/serial/tegra_hsuart.c13
-rw-r--r--drivers/usb/host/ehci-tegra.c13
-rw-r--r--drivers/usb/otg/tegra-otg.c8
-rw-r--r--drivers/video/tegra/Kconfig9
-rw-r--r--drivers/video/tegra/dc/dc.c17
-rw-r--r--drivers/video/tegra/dc/dc_config.h6
-rw-r--r--drivers/video/tegra/dc/dsi.c6
-rw-r--r--drivers/video/tegra/dc/ext/dev.c31
-rw-r--r--drivers/video/tegra/dc/nvsd.c5
-rw-r--r--drivers/video/tegra/host/Makefile1
-rw-r--r--drivers/video/tegra/host/bus_client.c55
-rw-r--r--drivers/video/tegra/host/bus_client.h4
-rw-r--r--drivers/video/tegra/host/dev.c16
-rw-r--r--drivers/video/tegra/host/dsi/Makefile7
-rw-r--r--drivers/video/tegra/host/dsi/dsi.c83
-rw-r--r--drivers/video/tegra/host/gr3d/gr3d_t30.c2
-rw-r--r--drivers/video/tegra/host/nvhost_acm.c12
-rw-r--r--drivers/video/tegra/host/nvhost_syncpt.h5
-rw-r--r--drivers/video/tegra/nvmap/nvmap_ioctl.c2
-rw-r--r--include/linux/mfd/rc5t583.h78
-rw-r--r--include/linux/mfd/tps65910.h49
-rw-r--r--include/linux/mfd/tps80031.h1
-rw-r--r--include/linux/of.h2
-rw-r--r--include/linux/pm_qos_params.h2
-rw-r--r--include/linux/regulator/tps62360.h2
-rw-r--r--include/linux/tegra_audio.h2
-rw-r--r--include/media/ad5816.h12
-rw-r--r--include/media/ov2710.h11
-rw-r--r--include/video/tegra_dc_ext.h8
-rw-r--r--sound/soc/codecs/rt5639.c24
-rw-r--r--sound/soc/codecs/rt5640.c23
-rw-r--r--sound/soc/tegra/tegra30_i2s.c4
-rw-r--r--sound/soc/tegra/tegra_p1852.c3
109 files changed, 2956 insertions, 1125 deletions
diff --git a/arch/arm/configs/tegra3_android_defconfig b/arch/arm/configs/tegra3_android_defconfig
index 2b4aee13812b..50da47699f9f 100644
--- a/arch/arm/configs/tegra3_android_defconfig
+++ b/arch/arm/configs/tegra3_android_defconfig
@@ -292,6 +292,7 @@ CONFIG_SPI_TEGRA=y
CONFIG_SPI_SLAVE_TEGRA=y
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_RC5T583=y
CONFIG_POWER_SUPPLY=y
CONFIG_BATTERY_BQ20Z75=y
CONFIG_BATTERY_BQ27x00=y
@@ -307,6 +308,7 @@ CONFIG_MFD_TPS6586X=y
CONFIG_MFD_TPS65910=y
CONFIG_MFD_MAX77663=y
CONFIG_MFD_TPS6591X=y
+CONFIG_MFD_RC5T583=y
CONFIG_MFD_TPS80031=y
CONFIG_GPADC_TPS80031=y
CONFIG_MFD_RICOH583=y
@@ -317,6 +319,7 @@ CONFIG_REGULATOR_GPIO=y
CONFIG_REGULATOR_USERSPACE_CONSUMER=y
CONFIG_REGULATOR_MAX8973=y
CONFIG_REGULATOR_MAX77663=y
+CONFIG_REGULATOR_RC5T583=y
CONFIG_REGULATOR_TPS6586X=y
CONFIG_REGULATOR_TPS65910=y
CONFIG_REGULATOR_TPS62360=y
@@ -332,6 +335,7 @@ CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
# CONFIG_TEGRA_AVP is not set
# CONFIG_TEGRA_MEDIASERVER is not set
CONFIG_TEGRA_NVAVP=y
+CONFIG_TEGRA_NVAVP_AUDIO=y
CONFIG_VIDEO_OV5650=y
CONFIG_VIDEO_OV5640=y
CONFIG_VIDEO_OV9726=y
@@ -441,7 +445,7 @@ CONFIG_EFI_PARTITION=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
-CONFIG_MAGIC_SYSRQ=y
+# CONFIG_MAGIC_SYSRQ is not set
CONFIG_DEBUG_SECTION_MISMATCH=y
CONFIG_DEBUG_FS=y
CONFIG_LOCKUP_DETECTOR=y
diff --git a/arch/arm/configs/tegra_android_defconfig b/arch/arm/configs/tegra_android_defconfig
index a129a8ee5a10..3cb78ad0741e 100644
--- a/arch/arm/configs/tegra_android_defconfig
+++ b/arch/arm/configs/tegra_android_defconfig
@@ -371,7 +371,6 @@ CONFIG_EFI_PARTITION=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
-CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_LOCKUP_DETECTOR=y
# CONFIG_DETECT_HUNG_TASK is not set
@@ -384,3 +383,4 @@ CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_TWOFISH=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_DEV_TEGRA_AES=y
+# CONFIG_MAGIC_SYSRQ is not set
diff --git a/arch/arm/configs/tegra_p1852_gnu_linux_defconfig b/arch/arm/configs/tegra_p1852_gnu_linux_defconfig
index 6a98b5b8fb49..243eaffccec3 100644
--- a/arch/arm/configs/tegra_p1852_gnu_linux_defconfig
+++ b/arch/arm/configs/tegra_p1852_gnu_linux_defconfig
@@ -31,6 +31,7 @@ CONFIG_ARCH_TEGRA_3x_SOC=y
CONFIG_TEGRA_PCI=y
CONFIG_MACH_P1852=y
CONFIG_TEGRA_PWM=y
+CONFIG_TEGRA_P1852_TDM=y
# CONFIG_TEGRA_CPU_DVFS is not set
CONFIG_TEGRA_CLOCK_DEBUG_WRITE=y
# CONFIG_TEGRA_MC_EARLY_ACK is not set
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 82306bc4aff5..c11ea97941a2 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -24,6 +24,7 @@ config ARCH_TEGRA_2x_SOC
select ARM_ERRATA_716044
select ARM_ERRATA_764369 if SMP
select ARCH_HAS_SUSPEND_PAGETABLE
+ select NVMAP_CACHE_MAINT_BY_SET_WAYS
help
Support for NVIDIA Tegra AP20 and T20 processors, based on the
ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@@ -51,6 +52,7 @@ config ARCH_TEGRA_3x_SOC
select TEGRA_LP2_ARM_TWD if HAVE_ARM_TWD && !TEGRA_RAIL_OFF_MULTIPLE_CPUS
select CPA
select ARCH_HAS_SUSPEND_PAGETABLE
+ select NVMAP_CACHE_MAINT_BY_SET_WAYS
help
Support for NVIDIA Tegra 3 family of SoCs, based upon the
ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@@ -254,6 +256,14 @@ config TEGRA_FIQ_DEBUGGER
help
Enables the FIQ serial debugger on Tegra
+config TEGRA_P1852_TDM
+ bool "Enable TDM mode for P1852 SKUs"
+ default n
+ depends on MACH_P1852
+ help
+ Enables TDM mode driver for P1852 SKUs. If this
+ is not defined then I2S mode is selected by default.
+
config TEGRA_CARDHU_DSI
bool "Support DSI panel on Cardhu"
depends on MACH_CARDHU
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 3153203c6efc..9acb8305a175 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra3_emc.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += wakeups-t2.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += wakeups-t3.o
+obj-y += wakeups.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pm-t2.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += pm-t3.o
diff --git a/arch/arm/mach-tegra/baseband-xmm-power.c b/arch/arm/mach-tegra/baseband-xmm-power.c
index 4da5d412cf41..30aba86f02f1 100644
--- a/arch/arm/mach-tegra/baseband-xmm-power.c
+++ b/arch/arm/mach-tegra/baseband-xmm-power.c
@@ -187,10 +187,36 @@ static int baseband_modem_power_on(struct baseband_power_platform_data *data)
/* set IPC_HSIC_ACTIVE active */
gpio_set_value(data->modem.xmm.ipc_hsic_active, 1);
+ /* wait 20 ms */
+ mdelay(20);
+
/* reset / power on sequence */
- msleep(40);
+ mdelay(40);
gpio_set_value(data->modem.xmm.bb_rst, 1);
mdelay(1);
+
+ gpio_set_value(data->modem.xmm.bb_on, 1);
+ udelay(70);
+ gpio_set_value(data->modem.xmm.bb_on, 0);
+
+ return 0;
+}
+
+/* this function can sleep, do not call in atomic context */
+static int baseband_modem_power_on_async(
+ struct baseband_power_platform_data *data)
+{
+ /* set IPC_HSIC_ACTIVE active */
+ gpio_set_value(data->modem.xmm.ipc_hsic_active, 1);
+
+ /* wait 20 ms */
+ msleep(20);
+
+ /* reset / power on sequence */
+ msleep(40);
+ gpio_set_value(data->modem.xmm.bb_rst, 1);
+ usleep_range(1000, 2000);
+
gpio_set_value(data->modem.xmm.bb_on, 1);
udelay(70);
gpio_set_value(data->modem.xmm.bb_on, 0);
@@ -251,8 +277,9 @@ static int xmm_power_on(struct platform_device *device)
if (pdata->hsic_register)
data->hsic_device = pdata->hsic_register();
/* turn on modem */
- pr_debug("%s call baseband_modem_power_on\n", __func__);
- baseband_modem_power_on(pdata);
+ pr_debug("%s call baseband_modem_power_on_async\n",
+ __func__);
+ baseband_modem_power_on_async(pdata);
}
}
ret = enable_irq_wake(gpio_to_irq(pdata->modem.xmm.ipc_ap_wake));
@@ -302,11 +329,12 @@ static int xmm_power_off(struct platform_device *device)
gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0);
/* wait 20 ms */
- mdelay(20);
+ msleep(20);
/* drive bb_rst low */
gpio_set_value(pdata->modem.xmm.bb_rst, 0);
- mdelay(1);
+ /* sleep 1ms */
+ usleep_range(1000, 2000);
baseband_xmm_powerstate = BBXMM_PS_UNINIT;
modem_sleep_flag = false;
@@ -484,6 +512,7 @@ EXPORT_SYMBOL_GPL(baseband_xmm_set_power_status);
irqreturn_t xmm_power_ipc_ap_wake_irq(int irq, void *dev_id)
{
struct baseband_power_platform_data *data = xmm_power_drv_data.pdata;
+ struct xmm_power_data *drv = &xmm_power_drv_data;
int value;
value = gpio_get_value(data->modem.xmm.ipc_ap_wake);
@@ -521,6 +550,12 @@ irqreturn_t xmm_power_ipc_ap_wake_irq(int irq, void *dev_id)
/* modem wakeup part */
if (!value) {
pr_debug("%s - falling\n", __func__);
+ if (drv->hostwake == 0) {
+ /* AP L2 to L0 wakeup */
+ pr_debug("received wakeup ap l2->l0\n");
+ drv->hostwake = 1;
+ wake_up_interruptible(&drv->bb_wait);
+ }
/* First check it a CP ack or CP wake */
value = gpio_get_value(data->modem.xmm.ipc_bb_wake);
if (value) {
@@ -528,6 +563,7 @@ irqreturn_t xmm_power_ipc_ap_wake_irq(int irq, void *dev_id)
ipc_ap_wake_state = IPC_AP_WAKE_L;
return IRQ_HANDLED;
}
+
spin_lock(&xmm_lock);
wakeup_pending = true;
if (system_suspending) {
@@ -593,19 +629,19 @@ static void xmm_power_init1_work(struct work_struct *work)
}
/* wait 100 ms */
- mdelay(100);
+ msleep(100);
/* set IPC_HSIC_ACTIVE low */
gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0);
/* wait 10 ms */
- mdelay(10);
+ usleep_range(10000, 11000);
/* set IPC_HSIC_ACTIVE high */
gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 1);
/* wait 20 ms */
- mdelay(20);
+ msleep(20);
pr_debug("%s }\n", __func__);
}
@@ -654,9 +690,11 @@ static void xmm_power_autopm_resume(struct work_struct *work)
static void xmm_power_L2_resume(void)
{
struct baseband_power_platform_data *pdata = xmm_power_drv_data.pdata;
+ struct xmm_power_data *drv = &xmm_power_drv_data;
int value;
- int delay = 10000; /* maxmum delay in msec */
+ int delay = 1000; /* maxmum delay in msec */
unsigned long flags;
+ int ret, rcount = 0;
pr_debug("%s\n", __func__);
@@ -680,22 +718,30 @@ static void xmm_power_L2_resume(void)
pr_info("AP L2->L0\n");
value = gpio_get_value(pdata->modem.xmm.ipc_ap_wake);
if (value) {
- pr_debug("waiting for host wakeup from CP...\n");
+ drv->hostwake = 0;
/* wake bb */
gpio_set_value(pdata->modem.xmm.ipc_bb_wake, 1);
- do {
- mdelay(1);
- value = gpio_get_value(
- pdata->modem.xmm.ipc_ap_wake);
- delay--;
- } while ((value) && (delay));
- if (delay)
- pr_debug("gpio host wakeup low <-\n");
- else
+retry:
+ /* wait for cp */
+ pr_debug("waiting for host wakeup from CP...\n");
+ ret = wait_event_interruptible_timeout(drv->bb_wait,
+ drv->hostwake == 1, msecs_to_jiffies(delay));
+ if (ret == 0) {
pr_info("!!AP L2->L0 Failed\n");
- } else {
+ return;
+ }
+ if (ret == -ERESTARTSYS) {
+ if (rcount >= 5) {
+ pr_info("!!AP L2->L0 Failed\n");
+ return;
+ }
+ pr_debug("%s: caught signal\n", __func__);
+ rcount++;
+ goto retry;
+ }
+ pr_debug("Get gpio host wakeup low <-\n");
+ } else
pr_info("CP already ready\n");
- }
}
}
@@ -723,7 +769,7 @@ static void xmm_power_reset_on(struct baseband_power_platform_data *pdata)
gpio_set_value(pdata->modem.xmm.bb_rst, 0);
msleep(40);
gpio_set_value(pdata->modem.xmm.bb_rst, 1);
- mdelay(1);
+ usleep_range(1000, 2000);
gpio_set_value(pdata->modem.xmm.bb_on, 1);
udelay(70);
gpio_set_value(pdata->modem.xmm.bb_on, 0);
@@ -778,6 +824,7 @@ static void xmm_power_work_func(struct work_struct *work)
* software directly.
*/
break;
+
case BBXMM_WORK_INIT_FLASHLESS_PM_STEP1:
pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_STEP1\n");
pr_info("%s: flashless is not supported here\n", __func__);
@@ -915,6 +962,10 @@ static int xmm_power_driver_probe(struct platform_device *device)
/* save platform data */
xmm_power_drv_data.pdata = pdata;
+ /* init wait queue */
+ xmm_power_drv_data.hostwake = 1;
+ init_waitqueue_head(&xmm_power_drv_data.bb_wait);
+
/* create device file */
err = device_create_file(dev, &dev_attr_xmm_onoff);
if (err < 0) {
@@ -1041,7 +1092,7 @@ static int xmm_power_driver_handle_resume(
struct baseband_power_platform_data *pdata)
{
int value;
- int delay = 1000; /* maxmum delay in msec */
+ unsigned long timeout;
unsigned long flags;
pr_debug("%s\n", __func__);
@@ -1064,29 +1115,30 @@ static int xmm_power_driver_handle_resume(
value = gpio_get_value(pdata->modem.xmm.ipc_ap_wake);
if (value) {
pr_info("AP L3 -> L0\n");
- pr_debug("waiting for host wakeup...\n");
/* wake bb */
gpio_set_value(pdata->modem.xmm.ipc_bb_wake, 1);
+
+ /* Wait for max 1 sec */
+ timeout = jiffies + HZ;
+ pr_debug("Current: %lu: timeout %lu\n", jiffies, timeout);
do {
- mdelay(1);
+ udelay(100);
value = gpio_get_value(pdata->modem.xmm.ipc_ap_wake);
- delay--;
- } while ((value) && (delay));
- if (delay)
+ if (!value)
+ break;
+ } while (time_before(jiffies, timeout));
+ if (!value)
pr_debug("gpio host wakeup low <-\n");
else
pr_info("!!AP L3->L0 Failed\n");
-
- } else {
+ } else
pr_info("CP L3 -> L0\n");
- }
+
reenable_autosuspend = true;
return 0;
-
}
-
#ifdef CONFIG_PM
static int xmm_power_driver_suspend(struct device *dev)
{
diff --git a/arch/arm/mach-tegra/baseband-xmm-power.h b/arch/arm/mach-tegra/baseband-xmm-power.h
index 1f08e3b6900c..69140891319d 100644
--- a/arch/arm/mach-tegra/baseband-xmm-power.h
+++ b/arch/arm/mach-tegra/baseband-xmm-power.h
@@ -84,6 +84,9 @@ struct xmm_power_data {
struct baseband_power_platform_data *pdata;
struct work_struct work;
struct platform_device *hsic_device;
+ wait_queue_head_t bb_wait;
+ /* host wakeup gpio state*/
+ unsigned int hostwake;
};
enum baseband_xmm_powerstate_t {
diff --git a/arch/arm/mach-tegra/board-aruba-power.c b/arch/arm/mach-tegra/board-aruba-power.c
index 4391f6f19b51..b72b82fc144a 100644
--- a/arch/arm/mach-tegra/board-aruba-power.c
+++ b/arch/arm/mach-tegra/board-aruba-power.c
@@ -26,7 +26,6 @@
#include "pm.h"
#include "board.h"
-#include "wakeups-t3.h"
static int ac_online(void)
{
diff --git a/arch/arm/mach-tegra/board-cardhu-pm298-power-rails.c b/arch/arm/mach-tegra/board-cardhu-pm298-power-rails.c
index f0dc8afa56fe..9168d9719b7c 100644
--- a/arch/arm/mach-tegra/board-cardhu-pm298-power-rails.c
+++ b/arch/arm/mach-tegra/board-cardhu-pm298-power-rails.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-cardhu-pm298-power-rails.c
*
- * Copyright (C) 2011 NVIDIA, Inc.
+ * Copyright (C) 2011-2012, NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -37,7 +37,6 @@
#include "board.h"
#include "board-cardhu.h"
#include "pm.h"
-#include "wakeups-t3.h"
#define PMC_CTRL 0x0
#define PMC_CTRL_INTR_LOW BIT(17)
@@ -676,7 +675,6 @@ static struct platform_device *fixed_reg_devs_pm269[] = {
int __init cardhu_pm298_gpio_switch_regulator_init(void)
{
- int i;
struct board_info board_info;
struct platform_device **fixed_reg_devs;
int nfixreg_devs;
diff --git a/arch/arm/mach-tegra/board-cardhu-pm299-power-rails.c b/arch/arm/mach-tegra/board-cardhu-pm299-power-rails.c
index 6d4db73b6ecd..32f07599fea4 100644
--- a/arch/arm/mach-tegra/board-cardhu-pm299-power-rails.c
+++ b/arch/arm/mach-tegra/board-cardhu-pm299-power-rails.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-cardhu-pm299-power-rails.c
*
- * Copyright (C) 2011 NVIDIA, Inc.
+ * Copyright (C) 2011-2012, NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -37,7 +37,6 @@
#include "gpio-names.h"
#include "board.h"
#include "board-cardhu.h"
-#include "wakeups-t3.h"
#define PMC_CTRL 0x0
#define PMC_CTRL_INTR_LOW (1 << 17)
@@ -666,7 +665,6 @@ static struct platform_device *fixed_reg_devs_pm269[] = {
int __init cardhu_pm299_gpio_switch_regulator_init(void)
{
- int i;
struct board_info board_info;
struct platform_device **fixed_reg_devs;
int nfixreg_devs;
diff --git a/arch/arm/mach-tegra/board-cardhu-power.c b/arch/arm/mach-tegra/board-cardhu-power.c
index 61b5a15ed5c7..d517d8266204 100644
--- a/arch/arm/mach-tegra/board-cardhu-power.c
+++ b/arch/arm/mach-tegra/board-cardhu-power.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-cardhu-power.c
*
- * Copyright (C) 2011-2012 NVIDIA, Inc.
+ * Copyright (C) 2011-2012, NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -42,7 +42,6 @@
#include "board.h"
#include "board-cardhu.h"
#include "pm.h"
-#include "wakeups-t3.h"
#include "tegra3_tsensor.h"
#define PMC_CTRL 0x0
@@ -994,7 +993,6 @@ static struct platform_device *fixed_reg_devs_e1291_a04[] = {
int __init cardhu_fixed_regulator_init(void)
{
- int i;
struct board_info board_info;
struct board_info pmu_board_info;
struct board_info display_board_info;
diff --git a/arch/arm/mach-tegra/board-cardhu-sdhci.c b/arch/arm/mach-tegra/board-cardhu-sdhci.c
index cb0684bcc742..d8be9fe6747f 100644
--- a/arch/arm/mach-tegra/board-cardhu-sdhci.c
+++ b/arch/arm/mach-tegra/board-cardhu-sdhci.c
@@ -145,6 +145,7 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = {
.embedded_sdio = &embedded_sdio_data2,
#endif
.built_in = 0,
+ .ocr_mask = MMC_OCR_1V8_MASK,
},
#ifndef CONFIG_MMC_EMBEDDED_SDIO
.pm_flags = MMC_PM_KEEP_POWER,
diff --git a/arch/arm/mach-tegra/board-enterprise-baseband.c b/arch/arm/mach-tegra/board-enterprise-baseband.c
index 9143103fd036..f2c94fda7727 100644
--- a/arch/arm/mach-tegra/board-enterprise-baseband.c
+++ b/arch/arm/mach-tegra/board-enterprise-baseband.c
@@ -69,11 +69,14 @@ static struct gpio modem_gpios[] = {
static void baseband_phy_init(void);
static void baseband_phy_on(void);
-static void baseband_phy_off(void);
+static void baseband_pre_phy_off(void);
+static void baseband_post_phy_off(void);
+static bool ap2mdm_ack_gpio_off = false;
static struct tegra_usb_phy_platform_ops ulpi_null_plat_ops = {
.init = baseband_phy_init,
- .pre_phy_off = baseband_phy_off,
+ .pre_phy_off = baseband_pre_phy_off,
+ .post_phy_off = baseband_post_phy_off,
.post_phy_on = baseband_phy_on,
};
@@ -133,16 +136,65 @@ static void baseband_phy_init(void)
pr_info("%s\n", __func__);
}
-static void baseband_phy_off(void)
+static inline void null_phy_set_tristate(bool enable)
+{
+ int tristate = (enable) ? TEGRA_TRI_TRISTATE : TEGRA_TRI_NORMAL;
+
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA0, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA1, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA2, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA3, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA4, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA5, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA6, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA7, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_NXT, tristate);
+
+ if (enable)
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DIR, tristate);
+}
+
+
+static void baseband_post_phy_off(void)
+{
+ null_phy_set_tristate(true);
+}
+
+
+static void baseband_pre_phy_off(void)
{
/* set AP2MDM_ACK2 high */
gpio_set_value(AP2MDM_ACK2, 1);
+ ap2mdm_ack_gpio_off = true;
}
static void baseband_phy_on(void)
{
- /* set AP2MDM_ACK2 low */
- gpio_set_value(AP2MDM_ACK2, 0);
+ if (ap2mdm_ack_gpio_off) {
+
+ /* driving linestate using GPIO */
+ gpio_set_value(ULPI_D0, 0);
+ gpio_set_value(ULPI_D1, 0);
+
+ /* remove ULPI tristate */
+ null_phy_set_tristate(false);
+
+ gpio_set_value(AP2MDM_ACK2, 0);
+
+ if (gpio_is_valid(MDM2AP_ACK2)) {
+ int retry = 20000;
+ while (retry) {
+ /* poll phy_restore_gpio high */
+ if (gpio_get_value(MDM2AP_ACK2))
+ break;
+ retry--;
+ }
+
+ if (retry == 0)
+ pr_info("phy_restore_gpio timeout\n");
+ }
+ ap2mdm_ack_gpio_off = false;
+ }
}
static void baseband_start(void)
diff --git a/arch/arm/mach-tegra/board-enterprise-power.c b/arch/arm/mach-tegra/board-enterprise-power.c
index c7598ab56139..f32365d808a7 100644
--- a/arch/arm/mach-tegra/board-enterprise-power.c
+++ b/arch/arm/mach-tegra/board-enterprise-power.c
@@ -44,7 +44,6 @@
#include "board.h"
#include "board-enterprise.h"
#include "pm.h"
-#include "wakeups-t3.h"
#include "tegra3_tsensor.h"
#define PMC_CTRL 0x0
@@ -298,6 +297,7 @@ static struct tps80031_rtc_platform_data rtc_data = {
.tm_min = 2,
.tm_sec = 3,
},
+ .msecure_gpio = TEGRA_GPIO_PF7,
};
int battery_charger_init(void *board_data)
@@ -746,6 +746,8 @@ int __init enterprise_regulator_init(void)
battery_gauge_data.battery_present = 0;
}
+ tegra_gpio_enable(TEGRA_GPIO_PF7);
+
if (board_info.fab < BOARD_FAB_A03) {
tps_platform.num_subdevs = ARRAY_SIZE(tps80031_devs_a02);
tps_platform.subdevs = tps80031_devs_a02;
diff --git a/arch/arm/mach-tegra/board-enterprise.c b/arch/arm/mach-tegra/board-enterprise.c
index d92ac57dd054..e23a9a468081 100644
--- a/arch/arm/mach-tegra/board-enterprise.c
+++ b/arch/arm/mach-tegra/board-enterprise.c
@@ -684,7 +684,8 @@ static struct tegra_usb_platform_data tegra_udc_pdata = {
.phy_intf = TEGRA_USB_PHY_INTF_UTMI,
.op_mode = TEGRA_USB_OPMODE_DEVICE,
.u_data.dev = {
- .vbus_pmu_irq = 0,
+ .vbus_pmu_irq = ENT_TPS80031_IRQ_BASE +
+ TPS80031_INT_VBUS_DET,
.vbus_gpio = -1,
.charging_supported = false,
.remote_wakeup_supported = false,
diff --git a/arch/arm/mach-tegra/board-kai-kbc.c b/arch/arm/mach-tegra/board-kai-kbc.c
index 928e5de707c9..e55383a1028b 100644
--- a/arch/arm/mach-tegra/board-kai-kbc.c
+++ b/arch/arm/mach-tegra/board-kai-kbc.c
@@ -90,13 +90,6 @@ int __init kai_keys_init(void)
pr_info("Registering gpio keys\n");
- /* Enable gpio mode for other pins */
- for (i = 0; i < kai_keys_platform_data.nbuttons; i++) {
- if (kai_keys_platform_data.buttons[i].gpio < 0)
- continue;
- tegra_gpio_enable(kai_keys_platform_data.buttons[i].gpio);
- }
-
platform_device_register(&kai_keys_device);
return 0;
diff --git a/arch/arm/mach-tegra/board-kai-panel.c b/arch/arm/mach-tegra/board-kai-panel.c
index 4073afe2fc8d..45333840ffb7 100644
--- a/arch/arm/mach-tegra/board-kai-panel.c
+++ b/arch/arm/mach-tegra/board-kai-panel.c
@@ -111,8 +111,6 @@ static int kai_backlight_init(struct device *dev)
if (WARN_ON(ARRAY_SIZE(kai_bl_output_measured) != 256))
pr_err("bl_output array does not have 256 elements\n");
- tegra_gpio_disable(kai_bl_pwm);
-
ret = gpio_request(kai_bl_enb, "backlight_enb");
if (ret < 0)
return ret;
@@ -120,8 +118,6 @@ static int kai_backlight_init(struct device *dev)
ret = gpio_direction_output(kai_bl_enb, 1);
if (ret < 0)
gpio_free(kai_bl_enb);
- else
- tegra_gpio_enable(kai_bl_enb);
return ret;
};
@@ -132,7 +128,6 @@ static void kai_backlight_exit(struct device *dev)
/*ret = gpio_request(kai_bl_enb, "backlight_enb");*/
gpio_set_value(kai_bl_enb, 0);
gpio_free(kai_bl_enb);
- tegra_gpio_disable(kai_bl_enb);
return;
}
@@ -654,35 +649,27 @@ int __init kai_panel_init(void)
#endif
gpio_request(kai_lvds_avdd_en, "lvds_avdd_en");
gpio_direction_output(kai_lvds_avdd_en, 1);
- tegra_gpio_enable(kai_lvds_avdd_en);
gpio_request(kai_lvds_stdby, "lvds_stdby");
gpio_direction_output(kai_lvds_stdby, 1);
- tegra_gpio_enable(kai_lvds_stdby);
gpio_request(kai_lvds_rst, "lvds_rst");
gpio_direction_output(kai_lvds_rst, 1);
- tegra_gpio_enable(kai_lvds_rst);
if (board_info.fab == BOARD_FAB_A00) {
gpio_request(kai_lvds_rs_a00, "lvds_rs");
gpio_direction_output(kai_lvds_rs_a00, 0);
- tegra_gpio_enable(kai_lvds_rs_a00);
} else {
gpio_request(kai_lvds_rs, "lvds_rs");
gpio_direction_output(kai_lvds_rs, 0);
- tegra_gpio_enable(kai_lvds_rs);
}
gpio_request(kai_lvds_lr, "lvds_lr");
gpio_direction_output(kai_lvds_lr, 1);
- tegra_gpio_enable(kai_lvds_lr);
gpio_request(kai_lvds_shutdown, "lvds_shutdown");
gpio_direction_output(kai_lvds_shutdown, 1);
- tegra_gpio_enable(kai_lvds_shutdown);
- tegra_gpio_enable(kai_hdmi_hpd);
gpio_request(kai_hdmi_hpd, "hdmi_hpd");
gpio_direction_input(kai_hdmi_hpd);
diff --git a/arch/arm/mach-tegra/board-kai-pinmux.c b/arch/arm/mach-tegra/board-kai-pinmux.c
index fa750f15ca7e..be11d4ef6698 100644
--- a/arch/arm/mach-tegra/board-kai-pinmux.c
+++ b/arch/arm/mach-tegra/board-kai-pinmux.c
@@ -449,13 +449,9 @@ static __initdata struct tegra_pingroup_config unused_pins_lowpower[] = {
static void __init kai_pinmux_audio_init(void)
{
- tegra_gpio_enable(TEGRA_GPIO_CDC_IRQ);
gpio_request(TEGRA_GPIO_CDC_IRQ, "rt5640");
gpio_direction_input(TEGRA_GPIO_CDC_IRQ);
- tegra_gpio_enable(TEGRA_GPIO_HP_DET);
- tegra_gpio_enable(TEGRA_GPIO_INT_MIC_EN);
- tegra_gpio_enable(TEGRA_GPIO_EXT_MIC_EN);
}
/* We are disabling this code for now. */
@@ -551,7 +547,6 @@ static void set_unused_pin_gpio(struct gpio_init_pin_info *lpm_pin_info,
gpio_free(pin_info->gpio_nr);
continue;
}
- tegra_gpio_enable(pin_info->gpio_nr);
}
}
diff --git a/arch/arm/mach-tegra/board-kai-power.c b/arch/arm/mach-tegra/board-kai-power.c
index e89b2bd2246d..cc3b35608c98 100644
--- a/arch/arm/mach-tegra/board-kai-power.c
+++ b/arch/arm/mach-tegra/board-kai-power.c
@@ -40,7 +40,6 @@
#include "board.h"
#include "board-kai.h"
#include "pm.h"
-#include "wakeups-t3.h"
#include "tegra3_tsensor.h"
#define PMC_CTRL 0x0
@@ -567,8 +566,6 @@ static int __init kai_fixed_regulator_init(void)
fixed_reg_devs[i]->dev.platform_data;
gpio_nr = fixed_reg_pdata->gpio;
- if (gpio_nr < TEGRA_NR_GPIOS)
- tegra_gpio_enable(gpio_nr);
}
return platform_add_devices(fixed_reg_devs, nfixreg_devs);
diff --git a/arch/arm/mach-tegra/board-kai-sdhci.c b/arch/arm/mach-tegra/board-kai-sdhci.c
index 8d1d4a9bd4a8..0fa39ccf475d 100644
--- a/arch/arm/mach-tegra/board-kai-sdhci.c
+++ b/arch/arm/mach-tegra/board-kai-sdhci.c
@@ -106,6 +106,7 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = {
.mmc_data = {
.register_status_notify = kai_wifi_status_register,
.built_in = 0,
+ .ocr_mask = MMC_OCR_1V8_MASK,
},
#ifndef CONFIG_MMC_EMBEDDED_SDIO
.pm_flags = MMC_PM_KEEP_POWER,
@@ -243,9 +244,6 @@ static int __init kai_wifi_init(void)
if (rc)
pr_err("WLAN_IRQ gpio request failed:%d\n", rc);
- tegra_gpio_enable(KAI_WLAN_EN);
- tegra_gpio_enable(KAI_WLAN_IRQ);
-
rc = gpio_direction_output(KAI_WLAN_EN, 0);
if (rc)
pr_err("WLAN_EN gpio direction configuration failed:%d\n", rc);
diff --git a/arch/arm/mach-tegra/board-kai-sensors.c b/arch/arm/mach-tegra/board-kai-sensors.c
index 9564aaf0cfde..c545b2d0d786 100644
--- a/arch/arm/mach-tegra/board-kai-sensors.c
+++ b/arch/arm/mach-tegra/board-kai-sensors.c
@@ -135,9 +135,6 @@ static int kai_nct1008_init(void)
pr_err("%s: set gpio to input failed\n", __func__);
gpio_free(KAI_TEMP_ALERT_GPIO);
}
- else
- tegra_gpio_enable(KAI_TEMP_ALERT_GPIO);
-
return ret;
}
@@ -158,7 +155,6 @@ static int kai_camera_init(void)
{
int ret;
- tegra_gpio_enable(CAM2_POWER_DWN_GPIO);
ret = gpio_request(CAM2_POWER_DWN_GPIO, "cam2_power_en");
if (ret < 0) {
pr_err("%s: gpio_request failed for gpio %s\n",
@@ -168,7 +164,6 @@ static int kai_camera_init(void)
gpio_direction_output(CAM2_POWER_DWN_GPIO, 1);
mdelay(10);
- tegra_gpio_enable(CAM2_RST_GPIO);
ret = gpio_request(CAM2_RST_GPIO, "cam2_reset");
if (ret < 0) {
pr_err("%s: gpio_request failed for gpio %s\n",
@@ -314,7 +309,6 @@ static void mpuirq_init(void)
#if (MPU_GYRO_TYPE == MPU_TYPE_MPU3050)
#if MPU_ACCEL_IRQ_GPIO
/* ACCEL-IRQ assignment */
- tegra_gpio_enable(MPU_ACCEL_IRQ_GPIO);
ret = gpio_request(MPU_ACCEL_IRQ_GPIO, MPU_ACCEL_NAME);
if (ret < 0) {
pr_err("%s: gpio_request failed %d\n", __func__, ret);
@@ -331,7 +325,6 @@ static void mpuirq_init(void)
#endif
/* MPU-IRQ assignment */
- tegra_gpio_enable(MPU_GYRO_IRQ_GPIO);
ret = gpio_request(MPU_GYRO_IRQ_GPIO, MPU_GYRO_NAME);
if (ret < 0) {
pr_err("%s: gpio_request failed %d\n", __func__, ret);
diff --git a/arch/arm/mach-tegra/board-kai.c b/arch/arm/mach-tegra/board-kai.c
index 193d68632d52..86374cf27271 100644
--- a/arch/arm/mach-tegra/board-kai.c
+++ b/arch/arm/mach-tegra/board-kai.c
@@ -108,7 +108,6 @@ static noinline void __init kai_bt_st(void)
platform_device_register(&wl128x_device);
platform_device_register(&btwilink_device);
- tegra_gpio_enable(TEGRA_GPIO_PU0);
}
static struct resource kai_bluesleep_resources[] = {
@@ -620,9 +619,6 @@ static int __init kai_touch_init(void)
{
int touch_id;
- tegra_gpio_enable(KAI_TS_ID1);
- tegra_gpio_enable(KAI_TS_ID2);
-
gpio_request(KAI_TS_ID1, "touch-id1");
gpio_direction_input(KAI_TS_ID1);
@@ -764,10 +760,6 @@ static void kai_modem_init(void)
{
int ret;
- tegra_gpio_enable(TEGRA_GPIO_W_DISABLE);
- tegra_gpio_enable(TEGRA_GPIO_MODEM_RSVD1);
- tegra_gpio_enable(TEGRA_GPIO_MODEM_RSVD2);
-
ret = gpio_request(TEGRA_GPIO_W_DISABLE, "w_disable_gpio");
if (ret < 0)
pr_err("%s: gpio_request failed for gpio %d\n",
@@ -813,13 +805,6 @@ static void kai_audio_init(void)
}
}
-static void kai_nfc_init(void)
-{
- tegra_gpio_enable(TEGRA_GPIO_PX0);
- tegra_gpio_enable(TEGRA_GPIO_PS7);
- tegra_gpio_enable(TEGRA_GPIO_PR3);
-}
-
static void __init tegra_kai_init(void)
{
tegra_thermal_init(&thermal_data);
@@ -843,7 +828,6 @@ static void __init tegra_kai_init(void)
kai_panel_init();
kai_bt_st();
kai_tegra_setup_tibluesleep();
- kai_nfc_init();
kai_sensors_init();
kai_pins_state_init();
kai_emc_init();
diff --git a/arch/arm/mach-tegra/board-p1852-pinmux.c b/arch/arm/mach-tegra/board-p1852-pinmux.c
index 1503c80c8269..9133c7daa972 100644
--- a/arch/arm/mach-tegra/board-p1852-pinmux.c
+++ b/arch/arm/mach-tegra/board-p1852-pinmux.c
@@ -63,14 +63,21 @@
/* !!!FIXME!!!! Update drive strength with characterized value */
static __initdata struct tegra_drive_pingroup_config p1852_drive_pinmux[] = {
- SET_DRIVE(DAP2, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
+ /* ATC1 CFG */
+ SET_DRIVE(AT1, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
+ /* ATC2 CFG */
+ SET_DRIVE(AT2, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
+ /* ATC3 CFG */
+ SET_DRIVE(AT3, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
+ /* ATC4 CFG */
+ SET_DRIVE(AT4, DISABLE, DISABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
/* All I2C pins are driven to maximum drive strength */
/* GEN1 I2C */
SET_DRIVE(DBG, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
/* GEN2 I2C */
- SET_DRIVE(AT5, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
+ SET_DRIVE(AT5, DISABLE, ENABLE, DIV_1, 12, 30, FASTEST, FASTEST),
/* DDC I2C */
SET_DRIVE(DDC, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
@@ -83,6 +90,48 @@ static __initdata struct tegra_drive_pingroup_config p1852_drive_pinmux[] = {
SET_DRIVE(GMF, DISABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
SET_DRIVE(GMG, DISABLE, ENABLE, DIV_1, 15, 6, SLOWEST, SLOWEST),
SET_DRIVE(GMH, DISABLE, ENABLE, DIV_1, 12, 6, SLOWEST, SLOWEST),
+
+ /* LCD */
+ SET_DRIVE(LCD1, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
+ SET_DRIVE(LCD2, DISABLE, ENABLE, DIV_1, 2, 2, FASTEST, FASTEST),
+
+ /* DAP2 */
+ SET_DRIVE(DAP2, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
+ /* DAP4 */
+ SET_DRIVE(DAP4, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
+ /* DBG */
+ SET_DRIVE(DBG, ENABLE, ENABLE, DIV_1, 20, 0, SLOWEST, SLOWEST),
+ /* SPI */
+ SET_DRIVE(SPI, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
+ /* UAA */
+ SET_DRIVE(UAA, DISABLE, DISABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
+ /* UART2 */
+ SET_DRIVE(UART2, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
+ /* UART3 */
+ SET_DRIVE(UART3, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
+ /* GME */
+ SET_DRIVE(GME, DISABLE, ENABLE, DIV_1, 1, 4, SLOWEST, SLOWEST),
+ /* GMF */
+ SET_DRIVE(GMF, DISABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
+ /* GMG */
+ SET_DRIVE(GMG, DISABLE, ENABLE, DIV_1, 3, 0, SLOWEST, SLOWEST),
+ /* GMH */
+ SET_DRIVE(GMH, DISABLE, ENABLE, DIV_1, 0, 12, SLOWEST, SLOWEST),
+
+ /* I2S/TDM */
+#ifdef CONFIG_TEGRA_MODS
+ SET_DRIVE(DAP1, ENABLE, ENABLE, DIV_1, 20, 20, SLOWEST, SLOWEST),
+ SET_DRIVE(DAP3, ENABLE, ENABLE, DIV_1, 20, 20, SLOWEST, SLOWEST),
+#else
+ SET_DRIVE(DAP1, ENABLE, ENABLE, DIV_1, 3, 3, SLOWEST, SLOWEST),
+ SET_DRIVE(DAP3, ENABLE, ENABLE, DIV_1, 3, 3, SLOWEST, SLOWEST),
+#endif
+
+ /* SPI */
+ SET_DRIVE(UAD, DISABLE, ENABLE, DIV_1, 4, 1, SLOWEST, SLOWEST),
+ SET_DRIVE(UAB, DISABLE, ENABLE, DIV_1, 4, 1, SLOWEST, SLOWEST),
+ SET_DRIVE(SDIO3, DISABLE, ENABLE, DIV_8, 4, 1, FASTEST, FASTEST),
+
};
#define DEFAULT_PINMUX(_pingroup, _mux, _pupd, _tri, _io) \
diff --git a/arch/arm/mach-tegra/board-p1852.c b/arch/arm/mach-tegra/board-p1852.c
index 71c12756539d..eebbb24a9871 100644
--- a/arch/arm/mach-tegra/board-p1852.c
+++ b/arch/arm/mach-tegra/board-p1852.c
@@ -200,12 +200,14 @@ static void __init p1852_uart_init(void)
ARRAY_SIZE(p1852_uart_devices));
}
-static struct tegra_p1852_platform_data p1852_audio_pdata = {
+#if defined(CONFIG_TEGRA_P1852_TDM)
+static struct tegra_p1852_platform_data p1852_audio_tdm_pdata = {
.codec_info[0] = {
.codec_dai_name = "dit-hifi",
.cpu_dai_name = "tegra30-i2s.0",
.codec_name = "spdif-dit.0",
.name = "tegra-i2s-1",
+ .pcm_driver = "tegra-tdm-pcm-audio",
.i2s_format = format_tdm,
.master = 1,
.num_slots = 4,
@@ -218,6 +220,7 @@ static struct tegra_p1852_platform_data p1852_audio_pdata = {
.cpu_dai_name = "tegra30-i2s.4",
.codec_name = "spdif-dit.1",
.name = "tegra-i2s-2",
+ .pcm_driver = "tegra-tdm-pcm-audio",
.i2s_format = format_tdm,
.master = 1,
.num_slots = 8,
@@ -225,9 +228,29 @@ static struct tegra_p1852_platform_data p1852_audio_pdata = {
.tx_mask = 0xff,
.rx_mask = 0xff,
},
-
};
-
+#else
+static struct tegra_p1852_platform_data p1852_audio_i2s_pdata = {
+ .codec_info[0] = {
+ .codec_dai_name = "dit-hifi",
+ .cpu_dai_name = "tegra30-i2s.0",
+ .codec_name = "spdif-dit.0",
+ .name = "tegra-i2s-1",
+ .pcm_driver = "tegra-pcm-audio",
+ .i2s_format = format_i2s,
+ .master = 1,
+ },
+ .codec_info[1] = {
+ .codec_dai_name = "dit-hifi",
+ .cpu_dai_name = "tegra30-i2s.4",
+ .codec_name = "spdif-dit.1",
+ .name = "tegra-i2s-2",
+ .pcm_driver = "tegra-pcm-audio",
+ .i2s_format = format_i2s,
+ .master = 0,
+ },
+};
+#endif
static struct platform_device generic_codec_1 = {
.name = "spdif-dit",
.id = 0,
@@ -241,13 +264,18 @@ static struct platform_device tegra_snd_p1852 = {
.name = "tegra-snd-p1852",
.id = 0,
.dev = {
- .platform_data = &p1852_audio_pdata,
+#if defined(CONFIG_TEGRA_P1852_TDM)
+ .platform_data = &p1852_audio_tdm_pdata,
+#else
+ .platform_data = &p1852_audio_i2s_pdata,
+#endif
},
};
static void p1852_i2s_audio_init(void)
{
platform_device_register(&tegra_pcm_device);
+ platform_device_register(&tegra_tdm_pcm_device);
platform_device_register(&generic_codec_1);
platform_device_register(&generic_codec_2);
platform_device_register(&tegra_i2s_device0);
diff --git a/arch/arm/mach-tegra/board-ventana-panel.c b/arch/arm/mach-tegra/board-ventana-panel.c
index f396557411b8..e848441ef7e0 100644
--- a/arch/arm/mach-tegra/board-ventana-panel.c
+++ b/arch/arm/mach-tegra/board-ventana-panel.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-ventana-panel.c
*
- * Copyright (c) 2010-2012, NVIDIA Corporation.
+ * Copyright (c) 2010-2012 NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -63,8 +63,6 @@ static int ventana_backlight_init(struct device *dev) {
ret = gpio_direction_output(ventana_bl_enb, 1);
if (ret < 0)
gpio_free(ventana_bl_enb);
- else
- tegra_gpio_enable(ventana_bl_enb);
return ret;
};
@@ -72,7 +70,6 @@ static int ventana_backlight_init(struct device *dev) {
static void ventana_backlight_exit(struct device *dev) {
gpio_set_value(ventana_bl_enb, 0);
gpio_free(ventana_bl_enb);
- tegra_gpio_disable(ventana_bl_enb);
}
static int ventana_backlight_notify(struct device *unused, int brightness)
@@ -392,13 +389,10 @@ int __init ventana_panel_init(void)
gpio_request(ventana_lvds_shutdown, "lvds_shdn");
gpio_direction_output(ventana_lvds_shutdown, 1);
- tegra_gpio_enable(ventana_lvds_shutdown);
- tegra_gpio_enable(ventana_hdmi_enb);
gpio_request(ventana_hdmi_enb, "hdmi_5v_en");
gpio_direction_output(ventana_hdmi_enb, 1);
- tegra_gpio_enable(ventana_hdmi_hpd);
gpio_request(ventana_hdmi_hpd, "hdmi_hpd");
gpio_direction_input(ventana_hdmi_hpd);
diff --git a/arch/arm/mach-tegra/board-ventana-power.c b/arch/arm/mach-tegra/board-ventana-power.c
index 2acfdfed28e4..aa6f4be203ad 100644
--- a/arch/arm/mach-tegra/board-ventana-power.c
+++ b/arch/arm/mach-tegra/board-ventana-power.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2012 NVIDIA, Inc.
+ * Copyright (C) 2010-2012 NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -34,7 +34,6 @@
#include "gpio-names.h"
#include "fuse.h"
#include "pm.h"
-#include "wakeups-t2.h"
#include "board.h"
#include "board-ventana.h"
@@ -47,7 +46,6 @@ int __init ventana_charge_init(void)
{
gpio_request(CHARGING_DISABLE, "chg_disable");
gpio_direction_output(CHARGING_DISABLE, 0);
- tegra_gpio_enable(CHARGING_DISABLE);
return 0;
}
@@ -255,14 +253,6 @@ static struct platform_device *fixed_voltage_regulators[] __initdata = {
int __init ventana_fixed_voltage_regulator_init(void)
{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(fixed_voltage_regulators); ++i) {
- struct fixed_voltage_config *fixed_voltage_regulators_pdata =
- fixed_voltage_regulators[i]->dev.platform_data;
- if (fixed_voltage_regulators_pdata->gpio < TEGRA_NR_GPIOS)
- tegra_gpio_enable(fixed_voltage_regulators_pdata->gpio);
- }
return platform_add_devices(fixed_voltage_regulators,
ARRAY_SIZE(fixed_voltage_regulators));
}
@@ -317,7 +307,6 @@ static struct platform_device ventana_charger_device = {
int __init ventana_charger_init(void)
{
- tegra_gpio_enable(AC_PRESENT_GPIO);
platform_device_register(&ventana_charger_device);
return 0;
}
diff --git a/arch/arm/mach-tegra/board-ventana-sdhci.c b/arch/arm/mach-tegra/board-ventana-sdhci.c
index 188335ac98c5..9d426aadff79 100644
--- a/arch/arm/mach-tegra/board-ventana-sdhci.c
+++ b/arch/arm/mach-tegra/board-ventana-sdhci.c
@@ -1,7 +1,6 @@
/*
- * arch/arm/mach-tegra/board-harmony-sdhci.c
- *
* Copyright (C) 2010 Google, Inc.
+ * Copyright (C) 2010-2012 NVIDIA Corporation.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -132,6 +131,7 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data0 = {
.embedded_sdio = &embedded_sdio_data0,
#endif
.built_in = 0,
+ .ocr_mask = MMC_OCR_1V8_MASK,
},
#ifndef CONFIG_MMC_EMBEDDED_SDIO
.pm_flags = MMC_PM_KEEP_POWER,
@@ -257,10 +257,6 @@ static int __init ventana_wifi_init(void)
gpio_request(VENTANA_WLAN_RST, "wlan_rst");
gpio_request(VENTANA_WLAN_WOW, "bcmsdh_sdmmc");
- tegra_gpio_enable(VENTANA_WLAN_PWR);
- tegra_gpio_enable(VENTANA_WLAN_RST);
- tegra_gpio_enable(VENTANA_WLAN_WOW);
-
gpio_direction_output(VENTANA_WLAN_PWR, 0);
gpio_direction_output(VENTANA_WLAN_RST, 0);
gpio_direction_input(VENTANA_WLAN_WOW);
@@ -274,11 +270,6 @@ static int __init ventana_wifi_init(void)
}
int __init ventana_sdhci_init(void)
{
- tegra_gpio_enable(tegra_sdhci_platform_data2.power_gpio);
- tegra_gpio_enable(tegra_sdhci_platform_data2.cd_gpio);
- tegra_gpio_enable(tegra_sdhci_platform_data2.wp_gpio);
- tegra_gpio_enable(tegra_sdhci_platform_data3.power_gpio);
-
platform_device_register(&tegra_sdhci_device3);
platform_device_register(&tegra_sdhci_device2);
platform_device_register(&tegra_sdhci_device0);
diff --git a/arch/arm/mach-tegra/board-ventana-sensors.c b/arch/arm/mach-tegra/board-ventana-sensors.c
index 574bdb25fc2a..be7c179dfad9 100644
--- a/arch/arm/mach-tegra/board-ventana-sensors.c
+++ b/arch/arm/mach-tegra/board-ventana-sensors.c
@@ -186,7 +186,6 @@ static struct ssl3250a_platform_data ventana_ssl3250a_pdata = {
static void ventana_isl29018_init(void)
{
- tegra_gpio_enable(ISL29018_IRQ_GPIO);
gpio_request(ISL29018_IRQ_GPIO, "isl29018");
gpio_direction_input(ISL29018_IRQ_GPIO);
}
@@ -194,7 +193,6 @@ static void ventana_isl29018_init(void)
#ifdef CONFIG_SENSORS_AK8975
static void ventana_akm8975_init(void)
{
- tegra_gpio_enable(AKM8975_IRQ_GPIO);
gpio_request(AKM8975_IRQ_GPIO, "akm8975");
gpio_direction_input(AKM8975_IRQ_GPIO);
}
@@ -202,7 +200,6 @@ static void ventana_akm8975_init(void)
static void ventana_nct1008_init(void)
{
- tegra_gpio_enable(NCT1008_THERM2_GPIO);
gpio_request(NCT1008_THERM2_GPIO, "temp_alert");
gpio_direction_input(NCT1008_THERM2_GPIO);
}
@@ -379,7 +376,6 @@ static void mpuirq_init(void)
#if (MPU_GYRO_TYPE == MPU_TYPE_MPU3050)
#if MPU_ACCEL_IRQ_GPIO
/* ACCEL-IRQ assignment */
- tegra_gpio_enable(MPU_ACCEL_IRQ_GPIO);
ret = gpio_request(MPU_ACCEL_IRQ_GPIO, MPU_ACCEL_NAME);
if (ret < 0) {
pr_err("%s: gpio_request failed %d\n", __func__, ret);
@@ -396,7 +392,6 @@ static void mpuirq_init(void)
#endif
/* MPU-IRQ assignment */
- tegra_gpio_enable(MPU_GYRO_IRQ_GPIO);
ret = gpio_request(MPU_GYRO_IRQ_GPIO, MPU_GYRO_NAME);
if (ret < 0) {
pr_err("%s: gpio_request failed %d\n", __func__, ret);
@@ -465,37 +460,35 @@ int __init ventana_sensors_init(void)
struct tegra_camera_gpios {
const char *name;
int gpio;
- bool tegra_internal_gpio;
int enabled;
};
-#define TEGRA_CAMERA_GPIO(_name, _gpio, _tegra_internal_gpio, _enabled) \
+#define TEGRA_CAMERA_GPIO(_name, _gpio, _enabled) \
{ \
.name = _name, \
.gpio = _gpio, \
- .tegra_internal_gpio = _tegra_internal_gpio, \
.enabled = _enabled, \
}
static struct tegra_camera_gpios ventana_camera_gpio_keys[] = {
- [0] = TEGRA_CAMERA_GPIO("camera_power_en", CAMERA_POWER_GPIO, true, 1),
- [1] = TEGRA_CAMERA_GPIO("camera_csi_sel", CAMERA_CSI_MUX_SEL_GPIO, true, 0),
- [2] = TEGRA_CAMERA_GPIO("torch_gpio_act", CAMERA_FLASH_ACT_GPIO, true, 0),
+ [0] = TEGRA_CAMERA_GPIO("camera_power_en", CAMERA_POWER_GPIO, 1),
+ [1] = TEGRA_CAMERA_GPIO("camera_csi_sel", CAMERA_CSI_MUX_SEL_GPIO, 0),
+ [2] = TEGRA_CAMERA_GPIO("torch_gpio_act", CAMERA_FLASH_ACT_GPIO, 0),
- [3] = TEGRA_CAMERA_GPIO("en_avdd_csi", AVDD_DSI_CSI_ENB_GPIO, false, 1),
- [4] = TEGRA_CAMERA_GPIO("cam_i2c_mux_rst_lo", CAM_I2C_MUX_RST_GPIO, false, 1),
+ [3] = TEGRA_CAMERA_GPIO("en_avdd_csi", AVDD_DSI_CSI_ENB_GPIO, 1),
+ [4] = TEGRA_CAMERA_GPIO("cam_i2c_mux_rst_lo", CAM_I2C_MUX_RST_GPIO, 1),
- [5] = TEGRA_CAMERA_GPIO("cam2_af_pwdn_lo", CAM2_AF_PWR_DN_L_GPIO, false, 0),
- [6] = TEGRA_CAMERA_GPIO("cam2_pwdn", CAM2_PWR_DN_GPIO, false, 0),
- [7] = TEGRA_CAMERA_GPIO("cam2_rst_lo", CAM2_RST_L_GPIO, false, 1),
+ [5] = TEGRA_CAMERA_GPIO("cam2_af_pwdn_lo", CAM2_AF_PWR_DN_L_GPIO, 0),
+ [6] = TEGRA_CAMERA_GPIO("cam2_pwdn", CAM2_PWR_DN_GPIO, 0),
+ [7] = TEGRA_CAMERA_GPIO("cam2_rst_lo", CAM2_RST_L_GPIO, 1),
- [8] = TEGRA_CAMERA_GPIO("cam3_af_pwdn_lo", CAM3_AF_PWR_DN_L_GPIO, false, 0),
- [9] = TEGRA_CAMERA_GPIO("cam3_pwdn", CAM3_PWR_DN_GPIO, false, 0),
- [10] = TEGRA_CAMERA_GPIO("cam3_rst_lo", CAM3_RST_L_GPIO, false, 1),
+ [8] = TEGRA_CAMERA_GPIO("cam3_af_pwdn_lo", CAM3_AF_PWR_DN_L_GPIO, 0),
+ [9] = TEGRA_CAMERA_GPIO("cam3_pwdn", CAM3_PWR_DN_GPIO, 0),
+ [10] = TEGRA_CAMERA_GPIO("cam3_rst_lo", CAM3_RST_L_GPIO, 1),
- [11] = TEGRA_CAMERA_GPIO("cam1_af_pwdn_lo", CAM1_AF_PWR_DN_L_GPIO, false, 0),
- [12] = TEGRA_CAMERA_GPIO("cam1_pwdn", CAM1_PWR_DN_GPIO, false, 0),
- [13] = TEGRA_CAMERA_GPIO("cam1_rst_lo", CAM1_RST_L_GPIO, false, 1),
+ [11] = TEGRA_CAMERA_GPIO("cam1_af_pwdn_lo", CAM1_AF_PWR_DN_L_GPIO, 0),
+ [12] = TEGRA_CAMERA_GPIO("cam1_pwdn", CAM1_PWR_DN_GPIO, 0),
+ [13] = TEGRA_CAMERA_GPIO("cam1_rst_lo", CAM1_RST_L_GPIO, 1),
};
int __init ventana_camera_late_init(void)
@@ -522,10 +515,6 @@ int __init ventana_camera_late_init(void)
i2c_new_device(i2c_get_adapter(3), ventana_i2c3_board_info_tca6416);
for (i = 0; i < ARRAY_SIZE(ventana_camera_gpio_keys); i++) {
-
- if (ventana_camera_gpio_keys[i].tegra_internal_gpio)
- tegra_gpio_enable(ventana_camera_gpio_keys[i].gpio);
-
ret = gpio_request(ventana_camera_gpio_keys[i].gpio,
ventana_camera_gpio_keys[i].name);
if (ret < 0) {
diff --git a/arch/arm/mach-tegra/board-ventana.c b/arch/arm/mach-tegra/board-ventana.c
index 779ffdba0f65..942ca44e2a13 100644
--- a/arch/arm/mach-tegra/board-ventana.c
+++ b/arch/arm/mach-tegra/board-ventana.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-ventana.c
*
- * Copyright (c) 2010-2011, NVIDIA Corporation.
+ * Copyright (c) 2010-2011 NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -119,8 +119,6 @@ static struct platform_device ventana_bluesleep_device = {
static void __init ventana_setup_bluesleep(void)
{
platform_device_register(&ventana_bluesleep_device);
- tegra_gpio_enable(TEGRA_GPIO_PU6);
- tegra_gpio_enable(TEGRA_GPIO_PU1);
return;
}
@@ -326,7 +324,8 @@ static int ventana_wakeup_key(void)
unsigned long status =
readl(IO_ADDRESS(TEGRA_PMC_BASE) + PMC_WAKE_STATUS);
- return status & TEGRA_WAKE_GPIO_PV2 ? KEY_POWER : KEY_RESERVED;
+ return (status & (1 << TEGRA_WAKE_GPIO_PV2)) ?
+ KEY_POWER : KEY_RESERVED;
}
static struct gpio_keys_platform_data ventana_keys_platform_data = {
@@ -342,14 +341,6 @@ static struct platform_device ventana_keys_device = {
.platform_data = &ventana_keys_platform_data,
},
};
-
-static void ventana_keys_init(void)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(ventana_keys); i++)
- tegra_gpio_enable(ventana_keys[i].gpio);
-}
#endif
static struct platform_device tegra_camera = {
@@ -625,10 +616,6 @@ static void __init tegra_ventana_init(void)
ventana_touch_init_panjit();
}
-#ifdef CONFIG_KEYBOARD_GPIO
- ventana_keys_init();
-#endif
-
ventana_usb_init();
ventana_gps_init();
ventana_panel_init();
diff --git a/arch/arm/mach-tegra/board-whistler-baseband.c b/arch/arm/mach-tegra/board-whistler-baseband.c
index eb50fb2f8237..b602cd3f44c1 100644
--- a/arch/arm/mach-tegra/board-whistler-baseband.c
+++ b/arch/arm/mach-tegra/board-whistler-baseband.c
@@ -26,8 +26,9 @@
static void baseband_phy_init(void);
static void baseband_phy_on(void);
-static void baseband_phy_off(void);
-
+static void baseband_pre_phy_off(void);
+static void baseband_post_phy_off(void);
+static bool ap2mdm_ack_gpio_off = false;
static struct wake_lock mdm_wake_lock;
static struct gpio modem_gpios[] = {
@@ -58,13 +59,14 @@ static __initdata struct tegra_pingroup_config whistler_null_ulpi_pinmux[] = {
static struct tegra_usb_phy_platform_ops ulpi_null_plat_ops = {
.init = baseband_phy_init,
- .pre_phy_off = baseband_phy_off,
+ .pre_phy_off = baseband_pre_phy_off,
+ .post_phy_off = baseband_post_phy_off,
.post_phy_on = baseband_phy_on,
};
static struct tegra_usb_platform_data tegra_ehci2_ulpi_null_pdata = {
.port_otg = false,
- .has_hostpc = true,
+ .has_hostpc = false,
.phy_intf = TEGRA_USB_PHY_INTF_ULPI_NULL,
.op_mode = TEGRA_USB_OPMODE_HOST,
.u_data.host = {
@@ -105,6 +107,15 @@ static irqreturn_t mdm_start_thread(int irq, void *data)
return IRQ_HANDLED;
}
+static inline void null_phy_set_tristate(bool enable)
+{
+ int tristate = (enable) ? TEGRA_TRI_TRISTATE : TEGRA_TRI_NORMAL;
+
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_UDA, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAA, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAB, tristate);
+}
+
static void baseband_phy_init(void)
{
static bool phy_init;
@@ -117,18 +128,51 @@ static void baseband_phy_init(void)
pr_info("%s\n", __func__);
}
-static void baseband_phy_off(void)
+static void baseband_pre_phy_off(void)
{
/* set AP2MDM_ACK2 high */
gpio_set_value(AP2MDM_ACK2, 1);
+ ap2mdm_ack_gpio_off = true;
+}
+
+static void baseband_post_phy_off(void)
+{
+ null_phy_set_tristate(true);
}
-static void baseband_phy_on (void)
+static void baseband_phy_on(void)
{
- /* set AP2MDM_ACK2 low */
- gpio_set_value(AP2MDM_ACK2, 0);
+ if (ap2mdm_ack_gpio_off) {
+
+ /* driving linestate using GPIO */
+ gpio_set_value(ULPI_D0, 0);
+ gpio_set_value(ULPI_D1, 0);
+
+ /* driving DIR high */
+ gpio_set_value(ULPI_DIR, 1);
+
+ /* remove ULPI tristate */
+ null_phy_set_tristate(false);
+
+ gpio_set_value(AP2MDM_ACK2, 0);
+
+ if (gpio_is_valid(MDM2AP_ACK2)) {
+ int retry = 20000;
+ while (retry) {
+ /* poll phy_restore_gpio high */
+ if (gpio_get_value(MDM2AP_ACK2))
+ break;
+ retry--;
+ }
+
+ if (retry == 0)
+ pr_info("phy_restore_gpio timeout\n");
+ }
+ ap2mdm_ack_gpio_off = false;
+ }
}
+
static void baseband_start(void)
{
/*
diff --git a/arch/arm/mach-tegra/board-whistler-power.c b/arch/arm/mach-tegra/board-whistler-power.c
index a0eb6686b0db..67663252e0d9 100644
--- a/arch/arm/mach-tegra/board-whistler-power.c
+++ b/arch/arm/mach-tegra/board-whistler-power.c
@@ -31,7 +31,6 @@
#include "gpio-names.h"
#include "fuse.h"
#include "pm.h"
-#include "wakeups-t2.h"
#include "board.h"
#define PMC_CTRL 0x0
diff --git a/arch/arm/mach-tegra/board-whistler-sdhci.c b/arch/arm/mach-tegra/board-whistler-sdhci.c
index 2d2a9c8c01f8..491688052858 100644
--- a/arch/arm/mach-tegra/board-whistler-sdhci.c
+++ b/arch/arm/mach-tegra/board-whistler-sdhci.c
@@ -168,6 +168,7 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data1 = {
.embedded_sdio = &embedded_sdio_data1,
#endif
.built_in = 0,
+ .ocr_mask = MMC_OCR_1V8_MASK,
},
#ifndef CONFIG_MMC_EMBEDDED_SDIO
.pm_flags = MMC_PM_KEEP_POWER,
diff --git a/arch/arm/mach-tegra/board-whistler.c b/arch/arm/mach-tegra/board-whistler.c
index 874ef18900e7..6156c8a8e51d 100644
--- a/arch/arm/mach-tegra/board-whistler.c
+++ b/arch/arm/mach-tegra/board-whistler.c
@@ -441,7 +441,7 @@ static struct tegra_usb_platform_data tegra_udc_pdata = {
.phy_intf = TEGRA_USB_PHY_INTF_UTMI,
.op_mode = TEGRA_USB_OPMODE_DEVICE,
.u_data.dev = {
- .vbus_pmu_irq = 0,
+ .vbus_pmu_irq = MAX8907C_INT_BASE + MAX8907C_IRQ_VCHG_DC_R,
.vbus_gpio = -1,
.charging_supported = false,
.remote_wakeup_supported = false,
diff --git a/arch/arm/mach-tegra/cpu-tegra3.c b/arch/arm/mach-tegra/cpu-tegra3.c
index 86a0b1364b3d..5b9ac4f770a2 100644
--- a/arch/arm/mach-tegra/cpu-tegra3.c
+++ b/arch/arm/mach-tegra/cpu-tegra3.c
@@ -230,7 +230,8 @@ static void tegra_auto_hotplug_work_func(struct work_struct *work)
cpu = tegra_get_slowest_cpu_n();
if (cpu < nr_cpu_ids) {
up = false;
- } else if (!is_lp_cluster() && !no_lp) {
+ } else if (!is_lp_cluster() && !no_lp &&
+ !pm_qos_request(PM_QOS_MIN_ONLINE_CPUS)) {
if(!clk_set_parent(cpu_clk, cpu_lp_clk)) {
hp_stats_update(CONFIG_NR_CPUS, true);
hp_stats_update(0, false);
@@ -299,10 +300,10 @@ static int min_cpus_notify(struct notifier_block *nb, unsigned long n, void *p)
{
mutex_lock(tegra3_cpu_lock);
- if ((n >= 2) && is_lp_cluster()) {
+ if ((n >= 1) && is_lp_cluster()) {
/* make sure cpu rate is within g-mode range before switching */
- unsigned int speed = max(
- tegra_getspeed(0), clk_get_min_rate(cpu_g_clk) / 1000);
+ unsigned int speed = max((unsigned long)tegra_getspeed(0),
+ clk_get_min_rate(cpu_g_clk) / 1000);
tegra_update_cpu_speed(speed);
if (!clk_set_parent(cpu_clk, cpu_g_clk)) {
diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c
index 377772ff4291..44afd0e63fe4 100644
--- a/arch/arm/mach-tegra/devices.c
+++ b/arch/arm/mach-tegra/devices.c
@@ -1166,6 +1166,11 @@ struct platform_device tegra_pcm_device = {
.id = -1,
};
+struct platform_device tegra_tdm_pcm_device = {
+ .name = "tegra-tdm-pcm-audio",
+ .id = -1,
+};
+
static struct resource w1_resources[] = {
[0] = {
.start = INT_OWR,
diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h
index 97a0c53ccfce..3d0734d1c688 100644
--- a/arch/arm/mach-tegra/devices.h
+++ b/arch/arm/mach-tegra/devices.h
@@ -69,6 +69,7 @@ extern struct platform_device spdif_dit_device;
extern struct platform_device bluetooth_dit_device;
extern struct platform_device baseband_dit_device;
extern struct platform_device tegra_pcm_device;
+extern struct platform_device tegra_tdm_pcm_device;
extern struct platform_device tegra_w1_device;
extern struct platform_device tegra_udc_device;
extern struct platform_device tegra_ehci1_device;
diff --git a/arch/arm/mach-tegra/include/mach/dc.h b/arch/arm/mach-tegra/include/mach/dc.h
index 71f1be769507..87af9441c28c 100644
--- a/arch/arm/mach-tegra/include/mach/dc.h
+++ b/arch/arm/mach-tegra/include/mach/dc.h
@@ -551,7 +551,6 @@ struct tegra_dc_pwm_params {
void tegra_dc_config_pwm(struct tegra_dc *dc, struct tegra_dc_pwm_params *cfg);
int tegra_dsi_send_panel_short_cmd(struct tegra_dc *dc, u8 *pdata, u8 data_len);
-void tegra_dc_host_trigger(struct tegra_dc *dc);
int tegra_dc_update_csc(struct tegra_dc *dc, int win_index);
diff --git a/arch/arm/mach-tegra/include/mach/sdhci.h b/arch/arm/mach-tegra/include/mach/sdhci.h
index 5dc8cd2ddf76..e307506eb40b 100644
--- a/arch/arm/mach-tegra/include/mach/sdhci.h
+++ b/arch/arm/mach-tegra/include/mach/sdhci.h
@@ -20,6 +20,14 @@
#include <linux/mmc/host.h>
#include <asm/mach/mmc.h>
+/*
+ * MMC_OCR_1V8_MASK will be used in board sdhci file
+ * Example for cardhu it will be used in board-cardhu-sdhci.c
+ * for built_in = 0 devices enabling ocr_mask to MMC_OCR_1V8_MASK
+ * sets the voltage to 1.8V
+ */
+#define MMC_OCR_1V8_MASK 0x8
+
struct tegra_sdhci_platform_data {
int cd_gpio;
int wp_gpio;
diff --git a/arch/arm/mach-tegra/include/mach/tegra_p1852_pdata.h b/arch/arm/mach-tegra/include/mach/tegra_p1852_pdata.h
index 6bea4e50b915..501d815b881b 100644
--- a/arch/arm/mach-tegra/include/mach/tegra_p1852_pdata.h
+++ b/arch/arm/mach-tegra/include/mach/tegra_p1852_pdata.h
@@ -35,6 +35,7 @@ struct codec_info_s {
char *cpu_dai_name;
char *codec_name; /* Name of the Codec Driver */
char *name; /* Name of the Codec-Dai-Link */
+ char *pcm_driver; /* Name of the PCM driver */
enum i2s_data_format i2s_format;
int master; /* Codec is Master or Slave */
/* TDM format setttings */
diff --git a/arch/arm/mach-tegra/p852/board-p852.h b/arch/arm/mach-tegra/p852/board-p852.h
index bb43febb4a2c..8e8f1444029c 100644
--- a/arch/arm/mach-tegra/p852/board-p852.h
+++ b/arch/arm/mach-tegra/p852/board-p852.h
@@ -55,7 +55,6 @@
#include "../pm.h"
#include "../devices.h"
#include "../gpio-names.h"
-#include "../wakeups-t2.h"
#define P852_SKU3 0x030000UL
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c
index 80a9a121f193..68e0fda385ae 100644
--- a/arch/arm/mach-tegra/pcie.c
+++ b/arch/arm/mach-tegra/pcie.c
@@ -36,6 +36,8 @@
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
+#include <linux/workqueue.h>
+#include <linux/gpio.h>
#include <asm/sizes.h>
#include <asm/mach/pci.h>
@@ -308,6 +310,7 @@ struct tegra_pcie_port {
char mem_space_name[16];
char prefetch_space_name[20];
struct resource res[3];
+ struct pci_bus* bus;
};
struct tegra_pcie_info {
@@ -319,6 +322,7 @@ struct tegra_pcie_info {
struct resource res_mmio;
int power_rails_enabled;
int pcie_power_enabled;
+ struct work_struct hotplug_detect;
struct regulator *regulator_hvdd;
struct regulator *regulator_pexio;
@@ -333,8 +337,6 @@ struct tegra_pcie_info {
#define pmc_readl(reg) \
__raw_readl((u32)reg_pmc_base + (reg))
-static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
-
static struct tegra_pcie_info tegra_pcie = {
.res_mmio = {
.name = "PCI IO",
@@ -620,6 +622,31 @@ static struct hw_pci tegra_pcie_hw = {
.map_irq = tegra_pcie_map_irq,
};
+static void work_hotplug_handler(struct work_struct *work)
+{
+ struct tegra_pcie_info *pcie_driver =
+ container_of(work, struct tegra_pcie_info, hotplug_detect);
+ int val;
+
+ if (pcie_driver->plat_data->gpio == -1)
+ return;
+ val = gpio_get_value(pcie_driver->plat_data->gpio);
+ if (val == 0) {
+ pr_info("Pcie Dock Connected but hotplug functionality not supported yet\n");
+ } else {
+ struct pci_dev *dev = NULL;
+
+ pr_info("Pcie Dock DisConnected\n");
+ for_each_pci_dev(dev)
+ pci_stop_bus_device(dev);
+ }
+}
+
+static irqreturn_t gpio_pcie_detect_isr(int irq, void *arg)
+{
+ schedule_work(&tegra_pcie.hotplug_detect);
+ return IRQ_HANDLED;
+}
static irqreturn_t tegra_pcie_isr(int irq, void *arg)
{
@@ -1169,6 +1196,8 @@ static int tegra_pcie_init(void)
pcibios_min_mem = 0x03000000ul;
pcibios_min_io = 0x10000000ul;
#endif
+
+ INIT_WORK(&tegra_pcie.hotplug_detect, work_hotplug_handler);
err = tegra_pcie_get_resources();
if (err)
return err;
@@ -1184,11 +1213,36 @@ static int tegra_pcie_init(void)
}
tegra_pcie.pcie_power_enabled = 1;
+ if (tegra_pcie.plat_data->use_dock_detect) {
+ unsigned int irq;
+
+ pr_info("acquiring dock_detect = %d\n",
+ tegra_pcie.plat_data->gpio);
+ gpio_request(tegra_pcie.plat_data->gpio, "pcie_dock_detect");
+ gpio_direction_input(tegra_pcie.plat_data->gpio);
+ irq = gpio_to_irq(tegra_pcie.plat_data->gpio);
+ if (irq < 0) {
+ pr_err("Unable to get irq number for dock_detect\n");
+ goto err_irq;
+ }
+ err = request_irq(irq,
+ gpio_pcie_detect_isr,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "pcie_dock_detect",
+ (void *)tegra_pcie.plat_data);
+ if (err < 0) {
+ pr_err("Unable to claim irq number for dock_detect\n");
+ goto err_irq;
+ }
+ }
+
if (tegra_pcie.num_ports)
pci_common_init(&tegra_pcie_hw);
else
err = tegra_pcie_power_off();
+err_irq:
+
return err;
}
diff --git a/arch/arm/mach-tegra/pinmux-t3-tables.c b/arch/arm/mach-tegra/pinmux-t3-tables.c
index 5e50fede625d..90dbf757b909 100644
--- a/arch/arm/mach-tegra/pinmux-t3-tables.c
+++ b/arch/arm/mach-tegra/pinmux-t3-tables.c
@@ -3,7 +3,7 @@
*
* Common pinmux configurations for Tegra 3 SoCs
*
- * Copyright (C) 2010-2011 NVIDIA Corporation
+ * Copyright (C) 2010-2012 NVIDIA Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -64,11 +64,16 @@
const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE_PINGROUP] = {
DEFAULT_DRIVE_PINGROUP(AO1, 0x868),
DEFAULT_DRIVE_PINGROUP(AO2, 0x86c),
- DEFAULT_DRIVE_PINGROUP(AT1, 0x870),
- DEFAULT_DRIVE_PINGROUP(AT2, 0x874),
- DEFAULT_DRIVE_PINGROUP(AT3, 0x878),
- DEFAULT_DRIVE_PINGROUP(AT4, 0x87c),
- DEFAULT_DRIVE_PINGROUP(AT5, 0x880),
+ SET_DRIVE_PINGROUP(AT1, 0x870, 14, 0x1f, 19, 0x1f,
+ 24, 0x3, 28, 0x3),
+ SET_DRIVE_PINGROUP(AT2, 0x874, 14, 0x1f, 19, 0x1f,
+ 24, 0x3, 28, 0x3),
+ SET_DRIVE_PINGROUP(AT3, 0x878, 14, 0x1f, 19, 0x1f,
+ 28, 0x3, 30, 0x3),
+ SET_DRIVE_PINGROUP(AT4, 0x87c, 14, 0x1f, 19, 0x1f,
+ 28, 0x3, 30, 0x3),
+ SET_DRIVE_PINGROUP(AT5, 0x880, 14, 0x1f, 19, 0x1f,
+ 28, 0x3, 30, 0x3),
DEFAULT_DRIVE_PINGROUP(CDEV1, 0x884),
DEFAULT_DRIVE_PINGROUP(CDEV2, 0x888),
DEFAULT_DRIVE_PINGROUP(CSUS, 0x88c),
@@ -101,10 +106,14 @@ const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE
24, 0xf, 28, 0xf),
SET_DRIVE_PINGROUP(GMD, 0x90c, 14, 0x1f, 19, 0x1f,
24, 0xf, 28, 0xf),
- DEFAULT_DRIVE_PINGROUP(GME, 0x910),
- DEFAULT_DRIVE_PINGROUP(GMF, 0x914),
- DEFAULT_DRIVE_PINGROUP(GMG, 0x918),
- DEFAULT_DRIVE_PINGROUP(GMH, 0x91c),
+ SET_DRIVE_PINGROUP(GME, 0x910, 14, 0x1f, 19, 0x1f,
+ 28, 0x3, 30, 0x3),
+ SET_DRIVE_PINGROUP(GMF, 0x914, 14, 0x1f, 19, 0x1f,
+ 28, 0x3, 30, 0x3),
+ SET_DRIVE_PINGROUP(GMG, 0x918, 14, 0x1f, 19, 0x1f,
+ 28, 0x3, 30, 0x3),
+ SET_DRIVE_PINGROUP(GMH, 0x91c, 14, 0x1f, 19, 0x1f,
+ 28, 0x3, 30, 0x3),
DEFAULT_DRIVE_PINGROUP(OWR, 0x920),
DEFAULT_DRIVE_PINGROUP(UAD, 0x924),
DEFAULT_DRIVE_PINGROUP(GPV, 0x928),
diff --git a/arch/arm/mach-tegra/pm-irq.c b/arch/arm/mach-tegra/pm-irq.c
index 57d21361ca14..9b205f86f8b9 100644
--- a/arch/arm/mach-tegra/pm-irq.c
+++ b/arch/arm/mach-tegra/pm-irq.c
@@ -29,6 +29,7 @@
#include <mach/iomap.h>
#include "pm-irq.h"
+#include "wakeups.h"
#define PMC_CTRL 0x0
#define PMC_CTRL_LATCH_WAKEUPS (1 << 5)
diff --git a/arch/arm/mach-tegra/pm-irq.h b/arch/arm/mach-tegra/pm-irq.h
index 8e87b4bba246..639bfe9c4cc9 100644
--- a/arch/arm/mach-tegra/pm-irq.h
+++ b/arch/arm/mach-tegra/pm-irq.h
@@ -22,8 +22,6 @@
int tegra_pm_irq_set_wake(int irq, int enable);
int tegra_pm_irq_set_wake_type(int irq, int flow_type);
bool tegra_pm_irq_lp0_allowed(void);
-int tegra_irq_to_wake(int irq);
-int tegra_wake_to_irq(int wake);
#else
static inline int tegra_pm_irq_set_wake_type(int irq, int flow_type)
{
diff --git a/arch/arm/mach-tegra/tegra2_usb_phy.c b/arch/arm/mach-tegra/tegra2_usb_phy.c
index 819721c49a29..7b18333cc77c 100644
--- a/arch/arm/mach-tegra/tegra2_usb_phy.c
+++ b/arch/arm/mach-tegra/tegra2_usb_phy.c
@@ -1545,6 +1545,189 @@ static int ulpi_link_phy_resume(struct tegra_usb_phy *phy)
return status;
}
+
+static int ulpi_null_phy_power_off(struct tegra_usb_phy *phy)
+{
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ if (!phy->phy_clk_on) {
+ DBG("%s(%d) inst:[%d] phy clk is already off\n", __func__,
+ __LINE__, phy->inst);
+ return 0;
+ }
+
+ phy->phy_clk_on = false;
+ phy->hw_accessible = false;
+
+ return 0;
+}
+
+static int ulpi_null_phy_irq(struct tegra_usb_phy *phy)
+{
+ usb_phy_fence_read(phy);
+ return IRQ_HANDLED;
+}
+
+static int ulpi_null_phy_lp0_resume(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ val = readl(base + USB_USBCMD);
+ val |= USB_USBCMD_RESET;
+ writel(val, base + USB_USBCMD);
+
+ if (usb_phy_reg_status_wait(base + USB_USBCMD,
+ USB_USBCMD_RESET, 0, 2500) < 0) {
+ pr_err("%s: timeout waiting for reset\n", __func__);
+ }
+
+ val = readl(base + USB_USBMODE_REG_OFFSET);
+ val &= ~USB_USBMODE_MASK;
+ val |= USB_USBMODE_HOST;
+ writel(val, base + USB_USBMODE_REG_OFFSET);
+
+ val = readl(base + USB_USBCMD);
+ val |= USB_USBCMD_RS;
+ writel(val, base + USB_USBCMD);
+ if (usb_phy_reg_status_wait(base + USB_USBCMD, USB_USBCMD_RS,
+ USB_USBCMD_RS, 2000)) {
+ pr_err("%s: timeout waiting for USB_USBCMD_RS\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ /* Enable Port Power */
+ val = readl(base + USB_PORTSC);
+ val |= USB_PORTSC_PP;
+ writel(val, base + USB_PORTSC);
+ udelay(10);
+
+ /* disable ULPI pinmux bypass */
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val &= ~ULPI_OUTPUT_PINMUX_BYP;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+
+ return 0;
+}
+
+static int ulpi_null_phy_power_on(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+ struct tegra_ulpi_config *config = &phy->pdata->u_cfg.ulpi;
+ static bool cold_boot = true;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ if (phy->phy_clk_on) {
+ DBG("%s(%d) inst:[%d] phy clk is already On\n", __func__,
+ __LINE__, phy->inst);
+ return 0;
+ }
+
+ val = readl(base + USB_SUSP_CTRL);
+ val |= UHSIC_RESET;
+ writel(val, base + USB_SUSP_CTRL);
+
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+
+ val = readl(base + USB_SUSP_CTRL);
+ val |= ULPI_PHY_ENABLE;
+ writel(val, base + USB_SUSP_CTRL);
+ udelay(10);
+
+ /* set timming parameters */
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_SHADOW_CLK_LOOPBACK_EN;
+ val |= ULPI_SHADOW_CLK_SEL;
+ val |= ULPI_LBK_PAD_EN;
+ val |= ULPI_SHADOW_CLK_DELAY(config->shadow_clk_delay);
+ val |= ULPI_CLOCK_OUT_DELAY(config->clock_out_delay);
+ val |= ULPI_LBK_PAD_E_INPUT_OR;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+
+ writel(0, base + ULPI_TIMING_CTRL_1);
+ udelay(10);
+
+ /* start internal 60MHz clock */
+ val = readl(base + ULPIS2S_CTRL);
+ val |= ULPIS2S_ENA;
+ val |= ULPIS2S_SUPPORT_DISCONNECT;
+ val |= ULPIS2S_SPARE((phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST) ? 3 : 1);
+ val |= ULPIS2S_PLLU_MASTER_BLASTER60;
+ writel(val, base + ULPIS2S_CTRL);
+
+ /* select ULPI_CORE_CLK_SEL to SHADOW_CLK */
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_CORE_CLK_SEL;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+ udelay(10);
+
+ /* enable ULPI null phy clock - can't set the trimmers before this */
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_CLK_OUT_ENA;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+ udelay(10);
+
+ if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
+ USB_PHY_CLK_VALID, 2500)) {
+ pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ /* set ULPI trimmers */
+ ulpi_set_trimmer(phy);
+
+ if (cold_boot) {
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_CLK_PADOUT_ENA;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+ cold_boot = false;
+ } else {
+ if (!readl(base + USB_ASYNCLISTADDR))
+ ulpi_null_phy_lp0_resume(phy);
+ }
+ udelay(10);
+
+ phy->phy_clk_on = true;
+ phy->hw_accessible = true;
+
+ return 0;
+}
+
+
+static int ulpi_null_phy_pre_resume(struct tegra_usb_phy *phy, bool remote_wakeup)
+{
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ usb_phy_wait_for_sof(phy);
+ return 0;
+}
+
+static int ulpi_null_phy_resume(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ if (!readl(base + USB_ASYNCLISTADDR)) {
+ /* enable ULPI CLK output pad */
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_CLK_PADOUT_ENA;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+
+ /* enable ULPI pinmux bypass */
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_OUTPUT_PINMUX_BYP;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+ udelay(5);
+ }
+
+ return 0;
+}
+
+
+
static struct tegra_usb_phy_ops utmi_phy_ops = {
.open = utmi_phy_open,
.close = utmi_phy_close,
@@ -1578,7 +1761,14 @@ static struct tegra_usb_phy_ops ulpi_link_phy_ops = {
.resume = ulpi_link_phy_resume,
};
-static struct tegra_usb_phy_ops ulpi_null_phy_ops;
+static struct tegra_usb_phy_ops ulpi_null_phy_ops = {
+ .irq = ulpi_null_phy_irq,
+ .power_on = ulpi_null_phy_power_on,
+ .power_off = ulpi_null_phy_power_off,
+ .pre_resume = ulpi_null_phy_pre_resume,
+ .resume = ulpi_null_phy_resume,
+};
+
static struct tegra_usb_phy_ops icusb_phy_ops;
diff --git a/arch/arm/mach-tegra/tegra3_dvfs.c b/arch/arm/mach-tegra/tegra3_dvfs.c
index 657a6cfd6510..f36bfa774577 100644
--- a/arch/arm/mach-tegra/tegra3_dvfs.c
+++ b/arch/arm/mach-tegra/tegra3_dvfs.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/tegra3_dvfs.c
*
- * Copyright (C) 2010-2011 NVIDIA Corporation.
+ * Copyright (C) 2010-2012, NVIDIA Corporation.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -783,8 +783,6 @@ static void core_cap_update(void)
static void core_cap_enable(bool enable)
{
- int i;
-
if (enable)
tegra3_core_cap.refcnt++;
else if (tegra3_core_cap.refcnt)
diff --git a/arch/arm/mach-tegra/tegra3_usb_phy.c b/arch/arm/mach-tegra/tegra3_usb_phy.c
index 5b3e51974d3b..8ada255cad55 100644
--- a/arch/arm/mach-tegra/tegra3_usb_phy.c
+++ b/arch/arm/mach-tegra/tegra3_usb_phy.c
@@ -888,6 +888,7 @@ static void uhsic_powerup_pmc_wake_detect(struct tegra_usb_phy *phy)
mdelay(1);
}
+#ifdef KERNEL_WARNING
static void usb_phy_power_down_pmc(void)
{
unsigned long val;
@@ -931,6 +932,7 @@ static void usb_phy_power_down_pmc(void)
UHSIC_MASTER_ENABLE_P0;
writel(val, pmc_base + PMC_SLEEP_CFG);
}
+#endif
static int usb_phy_bringup_host_controller(struct tegra_usb_phy *phy)
{
@@ -1142,10 +1144,6 @@ static void utmi_phy_close(struct tegra_usb_phy *phy)
writel(val, base + USB_SUSP_CTRL);
}
- val = readl(base + USB_PORTSC);
- val |= USB_PORTSC_WKCN;
- writel(val, base + USB_PORTSC);
-
clk_put(phy->utmi_pad_clk);
}
@@ -1341,16 +1339,20 @@ static int utmi_phy_pre_resume(struct tegra_usb_phy *phy, bool remote_wakeup)
unsigned int inst = phy->inst;
DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
-
- val = (readl(base + HOSTPC1_DEVLC) >> 25) &
+ phy->port_speed = (readl(base + HOSTPC1_DEVLC) >> 25) &
HOSTPC1_DEVLC_PSPD_MASK;
- if (val == USB_PHY_PORT_SPEED_HIGH) {
+
+ if (phy->port_speed == USB_PHY_PORT_SPEED_HIGH) {
/* Disable interrupts */
writel(0, base + USB_USBINTR);
/* Clear the run bit to stop SOFs - 2LS WAR */
val = readl(base + USB_USBCMD);
val &= ~USB_USBCMD_RS;
writel(val, base + USB_USBCMD);
+ if (usb_phy_reg_status_wait(base + USB_USBSTS, USB_USBSTS_HCH,
+ USB_USBSTS_HCH, 2000)) {
+ pr_err("%s: timeout waiting for USB_USBSTS_HCH\n", __func__);
+ }
}
val = readl(pmc_base + PMC_SLEEP_CFG);
@@ -1388,6 +1390,21 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy)
val |= UTMIP_PD_CHRG;
writel(val, base + UTMIP_BAT_CHRG_CFG0);
} else {
+ phy->port_speed = (readl(base + HOSTPC1_DEVLC) >> 25) &
+ HOSTPC1_DEVLC_PSPD_MASK;
+
+ /* Disable interrupts */
+ writel(0, base + USB_USBINTR);
+
+ /* Clear the run bit to stop SOFs - 2LS WAR */
+ val = readl(base + USB_USBCMD);
+ val &= ~USB_USBCMD_RS;
+ writel(val, base + USB_USBCMD);
+
+ if (usb_phy_reg_status_wait(base + USB_USBSTS, USB_USBSTS_HCH,
+ USB_USBSTS_HCH, 2000)) {
+ pr_err("%s: timeout waiting for USB_USBSTS_HCH\n", __func__);
+ }
utmip_setup_pmc_wake_detect(phy);
}
@@ -1409,9 +1426,6 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy)
utmi_phy_pad_power_off(phy);
- phy->port_speed = (readl(base + HOSTPC1_DEVLC) >> 25) &
- HOSTPC1_DEVLC_PSPD_MASK;
-
if (phy->pdata->u_data.host.hot_plug) {
bool enable_hotplug = true;
/* if it is OTG port then make sure to enable hot-plug feature
@@ -1776,7 +1790,7 @@ static int uhsic_phy_power_on(struct tegra_usb_phy *phy)
DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
- utmip_powerup_pmc_wake_detect(phy);
+ uhsic_powerup_pmc_wake_detect(phy);
if (phy->phy_clk_on) {
DBG("%s(%d) inst:[%d] phy clk is already On\n",
@@ -1897,7 +1911,7 @@ static int uhsic_phy_power_off(struct tegra_usb_phy *phy)
writel(val, base + USB_SUSP_CTRL);
udelay(30);
- utmip_powerdown_pmc_wake_detect(phy);
+ uhsic_powerdown_pmc_wake_detect(phy);
phy->phy_clk_on = false;
phy->hw_accessible = false;
@@ -2153,31 +2167,6 @@ static void ulpi_set_host(void __iomem *base)
}
-
-static inline void null_phy_set_tristate(bool enable)
-{
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- int tristate = (enable) ? TEGRA_TRI_TRISTATE : TEGRA_TRI_NORMAL;
- DBG("%s(%d) inst:[%s] FIXME enable pin group +++\n", __func__,
- __LINE__, enable ? "TRISTATE" : "NORMAL");
-
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA0, tristate);
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA1, tristate);
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA2, tristate);
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA3, tristate);
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA4, tristate);
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA5, tristate);
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA6, tristate);
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA7, tristate);
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_NXT, tristate);
-
- if (enable)
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DIR, tristate);
-#endif
-
-}
-
-
static int ulpi_null_phy_power_off(struct tegra_usb_phy *phy)
{
DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
@@ -2188,8 +2177,6 @@ static int ulpi_null_phy_power_off(struct tegra_usb_phy *phy)
return 0;
}
- null_phy_set_tristate(true);
-
phy->phy_clk_on = false;
phy->hw_accessible = false;
@@ -2241,6 +2228,52 @@ static int ulpi_null_phy_cmd_reset(struct tegra_usb_phy *phy)
return 0;
}
+static int ulpi_null_phy_lp0_resume(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ ulpi_null_phy_init(phy);
+
+ val = readl(base + USB_USBCMD);
+ val |= USB_CMD_RESET;
+ writel(val, base + USB_USBCMD);
+
+ if (usb_phy_reg_status_wait(base + USB_USBCMD,
+ USB_CMD_RESET, 0, 2500) < 0) {
+ pr_err("%s: timeout waiting for reset\n", __func__);
+ }
+
+ val = readl(base + USB_USBMODE);
+ val &= ~USB_USBMODE_MASK;
+ val |= USB_USBMODE_HOST;
+ writel(val, base + USB_USBMODE);
+
+ ulpi_null_phy_cmd_reset(phy);
+
+ val = readl(base + USB_USBCMD);
+ val |= USB_USBCMD_RS;
+ writel(val, base + USB_USBCMD);
+ if (usb_phy_reg_status_wait(base + USB_USBCMD, USB_USBCMD_RS,
+ USB_USBCMD_RS, 2000)) {
+ pr_err("%s: timeout waiting for USB_USBCMD_RS\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ /* Enable Port Power */
+ val = readl(base + USB_PORTSC);
+ val |= USB_PORTSC_PP;
+ writel(val, base + USB_PORTSC);
+ udelay(10);
+
+ /* disable ULPI pinmux bypass */
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val &= ~ULPI_OUTPUT_PINMUX_BYP;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+
+ return 0;
+}
+
static int ulpi_null_phy_power_on(struct tegra_usb_phy *phy)
{
unsigned long val;
@@ -2334,6 +2367,9 @@ static int ulpi_null_phy_power_on(struct tegra_usb_phy *phy)
val |= ULPI_CLK_PADOUT_ENA;
writel(val, base + ULPI_TIMING_CTRL_0);
cold_boot = false;
+ } else {
+ if (!readl(base + USB_ASYNCLISTADDR))
+ ulpi_null_phy_lp0_resume(phy);
}
udelay(10);
@@ -2352,6 +2388,32 @@ int ulpi_null_phy_pre_resume(struct tegra_usb_phy *phy, bool remote_wakeup)
return 0;
}
+static int ulpi_null_phy_resume(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ if (!readl(base + USB_ASYNCLISTADDR)) {
+ /* enable ULPI CLK output pad */
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_CLK_PADOUT_ENA;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+
+ /* enable ULPI pinmux bypass */
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_OUTPUT_PINMUX_BYP;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+ udelay(5);
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+ /* remove DIR tristate */
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DIR, TEGRA_TRI_NORMAL);
+#endif
+ }
+ return 0;
+}
+
+
+
static struct tegra_usb_phy_ops utmi_phy_ops = {
.open = utmi_phy_open,
.close = utmi_phy_close,
@@ -2382,6 +2444,7 @@ static struct tegra_usb_phy_ops ulpi_null_phy_ops = {
.power_on = ulpi_null_phy_power_on,
.power_off = ulpi_null_phy_power_off,
.pre_resume = ulpi_null_phy_pre_resume,
+ .resume = ulpi_null_phy_resume,
.reset = ulpi_null_phy_cmd_reset,
};
diff --git a/arch/arm/mach-tegra/tegra_usb_phy.h b/arch/arm/mach-tegra/tegra_usb_phy.h
index 36b88db94f52..0375b5aac812 100644
--- a/arch/arm/mach-tegra/tegra_usb_phy.h
+++ b/arch/arm/mach-tegra/tegra_usb_phy.h
@@ -89,6 +89,7 @@ struct tegra_usb_phy {
void __iomem *regs;
int inst;
bool phy_clk_on;
+ bool ctrl_clk_on; /* used only for pmu irq */
bool phy_power_on;
bool remote_wakeup;
bool hw_accessible;
diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c
index 6f568fd2cd29..bfb9abae2c94 100644
--- a/arch/arm/mach-tegra/usb_phy.c
+++ b/arch/arm/mach-tegra/usb_phy.c
@@ -131,15 +131,25 @@ int tegra_usb_phy_init_ops(struct tegra_usb_phy *phy)
static irqreturn_t usb_phy_dev_vbus_pmu_irq_thr(int irq, void *pdata)
{
- /* FIXME : Need to enable pmu vbus handling */
+ struct tegra_usb_phy *phy = pdata;
- return IRQ_NONE;
+ /* clk is disabled during phy power off and not here*/
+ if (!phy->ctrl_clk_on) {
+ clk_enable(phy->ctrlr_clk);
+ phy->ctrl_clk_on = true;
+ }
+
+ return IRQ_HANDLED;
}
static void tegra_usb_phy_release_clocks(struct tegra_usb_phy *phy)
{
clk_put(phy->emc_clk);
clk_put(phy->sys_clk);
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST)
+ if (phy->pdata->u_data.host.hot_plug ||
+ phy->pdata->u_data.host.remote_wakeup_supported)
+ clk_disable(phy->ctrlr_clk);
clk_put(phy->ctrlr_clk);
clk_disable(phy->pllu_clk);
clk_put(phy->pllu_clk);
@@ -164,6 +174,11 @@ static int tegra_usb_phy_get_clocks(struct tegra_usb_phy *phy)
goto fail_ctrlr_clk;
}
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST)
+ if (phy->pdata->u_data.host.hot_plug ||
+ phy->pdata->u_data.host.remote_wakeup_supported)
+ clk_enable(phy->ctrlr_clk);
+
phy->sys_clk = clk_get(&phy->pdev->dev, "sclk");
if (IS_ERR(phy->sys_clk)) {
dev_err(&phy->pdev->dev, "Can't get sclk clock\n");
@@ -273,6 +288,8 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct platform_device *pdev)
phy->inst);
goto fail_init;
}
+ } else {
+ clk_enable(phy->ctrlr_clk);
}
} else {
if (phy->pdata->u_data.host.vbus_reg) {
@@ -365,6 +382,8 @@ void tegra_usb_phy_close(struct tegra_usb_phy *phy)
if (phy->pdata->op_mode == TEGRA_USB_OPMODE_DEVICE) {
if (phy->pdata->u_data.dev.vbus_pmu_irq)
free_irq(phy->pdata->u_data.dev.vbus_pmu_irq, phy);
+ else
+ clk_disable(phy->ctrlr_clk);
} else {
usb_host_vbus_enable(phy, false);
@@ -379,8 +398,6 @@ void tegra_usb_phy_close(struct tegra_usb_phy *phy)
}
}
- tegra_usb_phy_release_clocks(phy);
-
if (phy->vdd_reg) {
regulator_disable(phy->vdd_reg);
regulator_put(phy->vdd_reg);
@@ -392,6 +409,8 @@ void tegra_usb_phy_close(struct tegra_usb_phy *phy)
if (phy->pdata->ops && phy->pdata->ops->close)
phy->pdata->ops->close();
+ tegra_usb_phy_release_clocks(phy);
+
kfree(phy->pdata);
kfree(phy);
}
@@ -439,7 +458,19 @@ int tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
clk_disable(phy->emc_clk);
clk_disable(phy->sys_clk);
- clk_disable(phy->ctrlr_clk);
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST) {
+ if (!phy->pdata->u_data.host.hot_plug &&
+ !phy->pdata->u_data.host.remote_wakeup_supported)
+ clk_disable(phy->ctrlr_clk);
+ } else {
+ /* In device mode clock is turned on by pmu irq handler
+ * if pmu irq is not available clocks will not be turned off/on
+ */
+ if (phy->pdata->u_data.dev.vbus_pmu_irq) {
+ clk_disable(phy->ctrlr_clk);
+ phy->ctrl_clk_on = false;
+ }
+ }
phy->phy_power_on = false;
@@ -455,7 +486,20 @@ int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
if (phy->phy_power_on)
return status;
- clk_enable(phy->ctrlr_clk);
+ /* In device mode clock is turned on by pmu irq handler
+ * if pmu irq is not available clocks will not be turned off/on
+ */
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST) {
+ if (!phy->pdata->u_data.host.hot_plug &&
+ !phy->pdata->u_data.host.remote_wakeup_supported)
+ clk_enable(phy->ctrlr_clk);
+ } else {
+ if (phy->pdata->u_data.dev.vbus_pmu_irq &&
+ !phy->ctrl_clk_on) {
+ clk_enable(phy->ctrlr_clk);
+ phy->ctrl_clk_on = true;
+ }
+ }
clk_enable(phy->sys_clk);
clk_enable(phy->emc_clk);
@@ -506,11 +550,7 @@ int tegra_usb_phy_suspend(struct tegra_usb_phy *phy)
err = phy->ops->suspend(phy);
if (!err && phy->pdata->u_data.host.power_off_on_suspend) {
- if (phy->pdata->ops && phy->pdata->ops->pre_phy_off)
- phy->pdata->ops->pre_phy_off();
- err = phy->ops->power_off(phy);
- if (phy->pdata->ops && phy->pdata->ops->post_phy_off)
- phy->pdata->ops->post_phy_off();
+ tegra_usb_phy_power_off(phy);
}
return err;
@@ -550,11 +590,7 @@ int tegra_usb_phy_resume(struct tegra_usb_phy *phy)
DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
if (phy->pdata->u_data.host.power_off_on_suspend) {
- if (phy->pdata->ops && phy->pdata->ops->pre_phy_on)
- phy->pdata->ops->pre_phy_on();
- err = phy->ops->power_on(phy);
- if (phy->pdata->ops && phy->pdata->ops->post_phy_on)
- phy->pdata->ops->post_phy_on();
+ tegra_usb_phy_power_on(phy);
}
if (!err && phy->ops && phy->ops->resume)
diff --git a/arch/arm/mach-tegra/wakeups-t2.c b/arch/arm/mach-tegra/wakeups-t2.c
index 7c5d12ac60d4..8079e6820145 100644
--- a/arch/arm/mach-tegra/wakeups-t2.c
+++ b/arch/arm/mach-tegra/wakeups-t2.c
@@ -22,8 +22,9 @@
#include <mach/gpio.h>
#include "gpio-names.h"
+#include "wakeups.h"
-static int tegra_wake_event_irq[] = {
+static int tegra_wake_event_irq_t2[] = {
[0] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PO5),
[1] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PV3),
[2] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PL1),
@@ -57,55 +58,5 @@ static int tegra_wake_event_irq[] = {
[30] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PN2),
};
-int tegra_irq_to_wake(int irq)
-{
- int i;
- int wake_irq;
- int search_gpio;
- static int last_wake = -1;
-
- /* Two level wake irq search for gpio based wakeups -
- * 1. check for GPIO irq(based on tegra_wake_event_irq table)
- * e.g. for a board, wake7 based on GPIO PU6 and irq==358 done first
- * 2. check for gpio bank irq assuming search for GPIO irq
- * preceded this search.
- * e.g. in this step check for gpio bank irq GPIO6 irq==119
- */
- for (i = 0; i < ARRAY_SIZE(tegra_wake_event_irq); i++) {
- /* return if step 1 matches */
- if (tegra_wake_event_irq[i] == irq) {
- pr_info("Wake%d for irq=%d\n", i, irq);
- last_wake = i;
- return i;
- }
-
- /* step 2 below uses saved last_wake from step 1
- * in previous call */
- search_gpio = irq_to_gpio(
- tegra_wake_event_irq[i]);
- if (search_gpio < 0)
- continue;
- wake_irq = tegra_gpio_get_bank_int_nr(search_gpio);
- if (wake_irq < 0)
- continue;
- if ((last_wake == i) &&
- (wake_irq == irq)) {
- pr_info("gpio bank wake found: wake%d for irq=%d\n",
- i, irq);
- return i;
- }
- }
-
- return -EINVAL;
-}
-
-int tegra_wake_to_irq(int wake)
-{
- if (wake < 0)
- return -EINVAL;
-
- if (wake >= ARRAY_SIZE(tegra_wake_event_irq))
- return -EINVAL;
-
- return tegra_wake_event_irq[wake];
-}
+int *tegra_wake_event_irq = tegra_wake_event_irq_t2;
+unsigned int tegra_wake_event_irq_size = ARRAY_SIZE(tegra_wake_event_irq_t2);
diff --git a/arch/arm/mach-tegra/wakeups-t2.h b/arch/arm/mach-tegra/wakeups-t2.h
index eb193c0aaf9e..955b351a71fa 100644
--- a/arch/arm/mach-tegra/wakeups-t2.h
+++ b/arch/arm/mach-tegra/wakeups-t2.h
@@ -30,36 +30,36 @@
int tegra_irq_to_wake(int irq);
int tegra_wake_to_irq(int wake);
-#define TEGRA_WAKE_GPIO_PO5 (1 << 0)
-#define TEGRA_WAKE_GPIO_PV3 (1 << 1)
-#define TEGRA_WAKE_GPIO_PL1 (1 << 2)
-#define TEGRA_WAKE_GPIO_PB6 (1 << 3)
-#define TEGRA_WAKE_GPIO_PN7 (1 << 4)
-#define TEGRA_WAKE_GPIO_PA0 (1 << 5)
-#define TEGRA_WAKE_GPIO_PU5 (1 << 6)
-#define TEGRA_WAKE_GPIO_PU6 (1 << 7)
-#define TEGRA_WAKE_GPIO_PC7 (1 << 8)
-#define TEGRA_WAKE_GPIO_PS2 (1 << 9)
-#define TEGRA_WAKE_GPIO_PAA1 (1 << 10)
-#define TEGRA_WAKE_GPIO_PW3 (1 << 11)
-#define TEGRA_WAKE_GPIO_PW2 (1 << 12)
-#define TEGRA_WAKE_GPIO_PY6 (1 << 13)
-#define TEGRA_WAKE_GPIO_PV6 (1 << 14)
-#define TEGRA_WAKE_GPIO_PJ7 (1 << 15)
-#define TEGRA_WAKE_RTC_ALARM (1 << 16)
-#define TEGRA_WAKE_KBC_EVENT (1 << 17)
-#define TEGRA_WAKE_PWR_INT (1 << 18)
-#define TEGRA_WAKE_USB1_VBUS (1 << 19)
-#define TEGRA_WAKE_USB3_VBUS (1 << 20)
-#define TEGRA_WAKE_USB1_ID (1 << 21)
-#define TEGRA_WAKE_USB3_ID (1 << 22)
-#define TEGRA_WAKE_GPIO_PI5 (1 << 23)
-#define TEGRA_WAKE_GPIO_PV2 (1 << 24)
-#define TEGRA_WAKE_GPIO_PS4 (1 << 25)
-#define TEGRA_WAKE_GPIO_PS5 (1 << 26)
-#define TEGRA_WAKE_GPIO_PS0 (1 << 27)
-#define TEGRA_WAKE_GPIO_PQ6 (1 << 28)
-#define TEGRA_WAKE_GPIO_PQ7 (1 << 29)
-#define TEGRA_WAKE_GPIO_PN2 (1 << 30)
+#define TEGRA_WAKE_GPIO_PO5 0
+#define TEGRA_WAKE_GPIO_PV3 1
+#define TEGRA_WAKE_GPIO_PL1 2
+#define TEGRA_WAKE_GPIO_PB6 3
+#define TEGRA_WAKE_GPIO_PN7 4
+#define TEGRA_WAKE_GPIO_PA0 5
+#define TEGRA_WAKE_GPIO_PU5 6
+#define TEGRA_WAKE_GPIO_PU6 7
+#define TEGRA_WAKE_GPIO_PC7 8
+#define TEGRA_WAKE_GPIO_PS2 9
+#define TEGRA_WAKE_GPIO_PAA1 10
+#define TEGRA_WAKE_GPIO_PW3 11
+#define TEGRA_WAKE_GPIO_PW2 12
+#define TEGRA_WAKE_GPIO_PY6 13
+#define TEGRA_WAKE_GPIO_PV6 14
+#define TEGRA_WAKE_GPIO_PJ7 15
+#define TEGRA_WAKE_RTC_ALARM 16
+#define TEGRA_WAKE_KBC_EVENT 17
+#define TEGRA_WAKE_PWR_INT 18
+#define TEGRA_WAKE_USB1_VBUS 19
+#define TEGRA_WAKE_USB3_VBUS 20
+#define TEGRA_WAKE_USB1_ID 21
+#define TEGRA_WAKE_USB3_ID 22
+#define TEGRA_WAKE_GPIO_PI5 23
+#define TEGRA_WAKE_GPIO_PV2 24
+#define TEGRA_WAKE_GPIO_PS4 25
+#define TEGRA_WAKE_GPIO_PS5 26
+#define TEGRA_WAKE_GPIO_PS0 27
+#define TEGRA_WAKE_GPIO_PQ6 28
+#define TEGRA_WAKE_GPIO_PQ7 29
+#define TEGRA_WAKE_GPIO_PN2 30
#endif
diff --git a/arch/arm/mach-tegra/wakeups-t3.c b/arch/arm/mach-tegra/wakeups-t3.c
index 823736204362..33dfb12f7211 100644
--- a/arch/arm/mach-tegra/wakeups-t3.c
+++ b/arch/arm/mach-tegra/wakeups-t3.c
@@ -22,8 +22,9 @@
#include <mach/gpio.h>
#include "gpio-names.h"
+#include "wakeups.h"
-static int tegra_wake_event_irq[] = {
+static int tegra_wake_event_irq_t3[] = {
TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PO5), /* wake0 */
TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PV1), /* wake1 */
TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PL1), /* wake2 */
@@ -68,55 +69,5 @@ static int tegra_wake_event_irq[] = {
INT_USB3, /* TEGRA_USB3_UTMIP, */ /* wake41 */
};
-int tegra_irq_to_wake(int irq)
-{
- int i;
- int wake_irq;
- int search_gpio;
- static int last_wake = -1;
-
- /* Two level wake irq search for gpio based wakeups -
- * 1. check for GPIO irq(based on tegra_wake_event_irq table)
- * e.g. for a board, wake7 based on GPIO PU6 and irq==390 done first
- * 2. check for gpio bank irq assuming search for GPIO irq
- * preceded this search.
- * e.g. in this step check for gpio bank irq GPIO6 irq==119
- */
- for (i = 0; i < ARRAY_SIZE(tegra_wake_event_irq); i++) {
- /* return if step 1 matches */
- if (tegra_wake_event_irq[i] == irq) {
- pr_info("Wake%d for irq=%d\n", i, irq);
- last_wake = i;
- return i;
- }
-
- /* step 2 below uses saved last_wake from step 1
- * in previous call */
- search_gpio = irq_to_gpio(
- tegra_wake_event_irq[i]);
- if (search_gpio < 0)
- continue;
- wake_irq = tegra_gpio_get_bank_int_nr(search_gpio);
- if (wake_irq < 0)
- continue;
- if ((last_wake == i) &&
- (wake_irq == irq)) {
- pr_info("gpio bank wake found: wake%d for irq=%d\n",
- i, irq);
- return i;
- }
- }
-
- return -EINVAL;
-}
-
-int tegra_wake_to_irq(int wake)
-{
- if (wake < 0)
- return -EINVAL;
-
- if (wake >= ARRAY_SIZE(tegra_wake_event_irq))
- return -EINVAL;
-
- return tegra_wake_event_irq[wake];
-}
+int *tegra_wake_event_irq = tegra_wake_event_irq_t3;
+unsigned int tegra_wake_event_irq_size = ARRAY_SIZE(tegra_wake_event_irq_t3);
diff --git a/arch/arm/mach-tegra/wakeups-t3.h b/arch/arm/mach-tegra/wakeups-t3.h
index f811d8939387..6c051270cc93 100644
--- a/arch/arm/mach-tegra/wakeups-t3.h
+++ b/arch/arm/mach-tegra/wakeups-t3.h
@@ -27,45 +27,45 @@
#error "Tegra 3 wakeup sources valid only for CONFIG_ARCH_TEGRA_3x_SOC"
#endif
-#define TEGRA_WAKE_GPIO_PO5 (1ull << 0)
-#define TEGRA_WAKE_GPIO_PV1 (1ull << 1)
-#define TEGRA_WAKE_GPIO_PL1 (1ull << 2)
-#define TEGRA_WAKE_GPIO_PB6 (1ull << 3)
-#define TEGRA_WAKE_GPIO_PN7 (1ull << 4)
-#define TEGRA_WAKE_GPIO_PBB6 (1ull << 5)
-#define TEGRA_WAKE_GPIO_PU5 (1ull << 6)
-#define TEGRA_WAKE_GPIO_PU6 (1ull << 7)
-#define TEGRA_WAKE_GPIO_PC7 (1ull << 8)
-#define TEGRA_WAKE_GPIO_PS2 (1ull << 9)
-#define TEGRA_WAKE_GPIO_PAA1 (1ull << 10)
-#define TEGRA_WAKE_GPIO_PW3 (1ull << 11)
-#define TEGRA_WAKE_GPIO_PW2 (1ull << 12)
-#define TEGRA_WAKE_GPIO_PY6 (1ull << 13)
-#define TEGRA_WAKE_GPIO_PDD3 (1ull << 14)
-#define TEGRA_WAKE_GPIO_PJ2 (1ull << 15)
-#define TEGRA_WAKE_RTC_ALARM (1ull << 16)
-#define TEGRA_WAKE_KBC_EVENT (1ull << 17)
-#define TEGRA_WAKE_PWR_INT (1ull << 18)
-#define TEGRA_WAKE_USB1_VBUS (1ull << 19)
-#define TEGRA_WAKE_USB2_VBUS (1ull << 20)
-#define TEGRA_WAKE_USB1_ID (1ull << 21)
-#define TEGRA_WAKE_USB2_ID (1ull << 22)
-#define TEGRA_WAKE_GPIO_PI5 (1ull << 23)
-#define TEGRA_WAKE_GPIO_PV0 (1ull << 24)
-#define TEGRA_WAKE_GPIO_PS4 (1ull << 25)
-#define TEGRA_WAKE_GPIO_PS5 (1ull << 26)
-#define TEGRA_WAKE_GPIO_PS0 (1ull << 27)
-#define TEGRA_WAKE_GPIO_PS6 (1ull << 28)
-#define TEGRA_WAKE_GPIO_PS7 (1ull << 29)
-#define TEGRA_WAKE_GPIO_PN2 (1ull << 30)
+#define TEGRA_WAKE_GPIO_PO5 0
+#define TEGRA_WAKE_GPIO_PV1 1
+#define TEGRA_WAKE_GPIO_PL1 2
+#define TEGRA_WAKE_GPIO_PB6 3
+#define TEGRA_WAKE_GPIO_PN7 4
+#define TEGRA_WAKE_GPIO_PBB6 5
+#define TEGRA_WAKE_GPIO_PU5 6
+#define TEGRA_WAKE_GPIO_PU6 7
+#define TEGRA_WAKE_GPIO_PC7 8
+#define TEGRA_WAKE_GPIO_PS2 9
+#define TEGRA_WAKE_GPIO_PAA1 10
+#define TEGRA_WAKE_GPIO_PW3 11
+#define TEGRA_WAKE_GPIO_PW2 12
+#define TEGRA_WAKE_GPIO_PY6 13
+#define TEGRA_WAKE_GPIO_PDD3 14
+#define TEGRA_WAKE_GPIO_PJ2 15
+#define TEGRA_WAKE_RTC_ALARM 16
+#define TEGRA_WAKE_KBC_EVENT 17
+#define TEGRA_WAKE_PWR_INT 18
+#define TEGRA_WAKE_USB1_VBUS 19
+#define TEGRA_WAKE_USB2_VBUS 20
+#define TEGRA_WAKE_USB1_ID 21
+#define TEGRA_WAKE_USB2_ID 22
+#define TEGRA_WAKE_GPIO_PI5 23
+#define TEGRA_WAKE_GPIO_PV0 24
+#define TEGRA_WAKE_GPIO_PS4 25
+#define TEGRA_WAKE_GPIO_PS5 26
+#define TEGRA_WAKE_GPIO_PS0 27
+#define TEGRA_WAKE_GPIO_PS6 28
+#define TEGRA_WAKE_GPIO_PS7 29
+#define TEGRA_WAKE_GPIO_PN2 30
/* bit 31 is unused */
-#define TEGRA_WAKE_GPIO_PO4 (1ull << 32)
-#define TEGRA_WAKE_GPIO_PJ0 (1ull << 33)
-#define TEGRA_WAKE_GPIO_PK2 (1ull << 34)
-#define TEGRA_WAKE_GPIO_PI6 (1ull << 35)
-#define TEGRA_WAKE_GPIO_PBB1 (1ull << 36)
-#define TEGRA_WAKE_USB3_ID (1ull << 37)
-#define TEGRA_WAKE_USB3_VBUS (1ull << 38)
+#define TEGRA_WAKE_GPIO_PO4 32
+#define TEGRA_WAKE_GPIO_PJ0 33
+#define TEGRA_WAKE_GPIO_PK2 34
+#define TEGRA_WAKE_GPIO_PI6 35
+#define TEGRA_WAKE_GPIO_PBB1 36
+#define TEGRA_WAKE_USB3_ID 37
+#define TEGRA_WAKE_USB3_VBUS 38
#endif
diff --git a/arch/arm/mach-tegra/wakeups.c b/arch/arm/mach-tegra/wakeups.c
new file mode 100644
index 000000000000..d53563cf22ba
--- /dev/null
+++ b/arch/arm/mach-tegra/wakeups.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+
+#include <mach/iomap.h>
+#include <mach/irqs.h>
+#include <mach/gpio.h>
+
+#include "gpio-names.h"
+#include "wakeups.h"
+
+extern int *tegra_wake_event_irq;
+extern unsigned int tegra_wake_event_irq_size;
+
+int tegra_irq_to_wake(int irq)
+{
+ int i;
+ int wake_irq;
+ int search_gpio;
+ static int last_wake = -1;
+
+ /* Two level wake irq search for gpio based wakeups -
+ * 1. check for GPIO irq(based on tegra_wake_event_irq table)
+ * e.g. for a board, wake7 based on GPIO PU6 and irq==390 done first
+ * 2. check for gpio bank irq assuming search for GPIO irq
+ * preceded this search.
+ * e.g. in this step check for gpio bank irq GPIO6 irq==119
+ */
+ for (i = 0; i < tegra_wake_event_irq_size; i++) {
+ /* return if step 1 matches */
+ if (tegra_wake_event_irq[i] == irq) {
+ pr_info("Wake%d for irq=%d\n", i, irq);
+ last_wake = i;
+ return i;
+ }
+
+ /* step 2 below uses saved last_wake from step 1
+ * in previous call */
+ search_gpio = irq_to_gpio(
+ tegra_wake_event_irq[i]);
+ if (search_gpio < 0)
+ continue;
+ wake_irq = tegra_gpio_get_bank_int_nr(search_gpio);
+ if (wake_irq < 0)
+ continue;
+ if ((last_wake == i) &&
+ (wake_irq == irq)) {
+ pr_info("gpio bank wake found: wake%d for irq=%d\n",
+ i, irq);
+ return i;
+ }
+ }
+
+ return -EINVAL;
+}
+
+int tegra_wake_to_irq(int wake)
+{
+ if (wake < 0)
+ return -EINVAL;
+
+ if (wake >= tegra_wake_event_irq_size)
+ return -EINVAL;
+
+ return tegra_wake_event_irq[wake];
+}
+
diff --git a/arch/arm/mach-tegra/wakeups.h b/arch/arm/mach-tegra/wakeups.h
new file mode 100644
index 000000000000..ab113649d534
--- /dev/null
+++ b/arch/arm/mach-tegra/wakeups.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __WAKEUPS_H_
+#define __WAKEUPS_H_
+
+/*
+ * given irq number returns wake source index or negative value for error
+ */
+int tegra_irq_to_wake(int irq);
+/*
+ * given wake source index, returns irq number or negative value for error
+ */
+int tegra_wake_to_irq(int wake);
+
+#endif /* end __WAKEUPS_H_ */
diff --git a/drivers/crypto/tegra-se.c b/drivers/crypto/tegra-se.c
index 3d2e9187b949..83324162a09f 100644
--- a/drivers/crypto/tegra-se.c
+++ b/drivers/crypto/tegra-se.c
@@ -622,9 +622,12 @@ static int tegra_se_count_sgs(struct scatterlist *sl, u32 total_bytes)
return 0;
do {
- total_bytes -= min(sl[i].length, total_bytes);
+ if (!sl->length)
+ return 0;
+ total_bytes -= min(sl->length, total_bytes);
i++;
- } while (total_bytes);
+ sl = sg_next(sl);
+ } while (total_bytes && sl);
return i;
}
@@ -846,7 +849,7 @@ static int tegra_se_aes_queue_req(struct ablkcipher_request *req)
bool idle = true;
int err = 0;
- if (!req->nbytes)
+ if (!tegra_se_count_sgs(req->src, req->nbytes))
return -EINVAL;
spin_lock_irqsave(&se_dev->lock, flags);
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index d539efd96d4b..9b304f254f98 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -271,6 +271,15 @@ config GPIO_PCF857X
This driver provides an in-kernel interface to those GPIOs using
platform-neutral GPIO calls.
+config GPIO_RC5T583
+ bool "RICOH RC5T583 GPIO"
+ depends on MFD_RC5T583
+ help
+ Select this option to enable GPIO driver for the Ricoh RC5T583
+ chip family.
+ This driver provides the support for driving/reading the gpio pins
+ of RC5T583 device through standard gpio library.
+
config GPIO_SX150X
bool "Semtech SX150x I2C GPIO expander"
depends on I2C=y
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 9588948c96f0..4ef6785f446b 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o
obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o
obj-$(CONFIG_GPIO_PCH) += gpio-pch.o
obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
+obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o
obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o
obj-$(CONFIG_GPIO_PLAT_SAMSUNG) += gpio-plat-samsung.o
diff --git a/drivers/gpio/gpio-rc5t583.c b/drivers/gpio/gpio-rc5t583.c
new file mode 100644
index 000000000000..08428bf17718
--- /dev/null
+++ b/drivers/gpio/gpio-rc5t583.c
@@ -0,0 +1,180 @@
+/*
+ * GPIO driver for RICOH583 power management chip.
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ * Author: Laxman dewangan <ldewangan@nvidia.com>
+ *
+ * Based on code
+ * Copyright (C) 2011 RICOH COMPANY,LTD
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/mfd/rc5t583.h>
+
+struct rc5t583_gpio {
+ struct gpio_chip gpio_chip;
+ struct rc5t583 *rc5t583;
+};
+
+static inline struct rc5t583_gpio *to_rc5t583_gpio(struct gpio_chip *chip)
+{
+ return container_of(chip, struct rc5t583_gpio, gpio_chip);
+}
+
+static int rc5t583_gpio_get(struct gpio_chip *gc, unsigned int offset)
+{
+ struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc);
+ struct device *parent = rc5t583_gpio->rc5t583->dev;
+ uint8_t val = 0;
+ int ret;
+
+ ret = rc5t583_read(parent, RC5T583_GPIO_MON_IOIN, &val);
+ if (ret < 0)
+ return ret;
+
+ return !!(val & BIT(offset));
+}
+
+static void rc5t583_gpio_set(struct gpio_chip *gc, unsigned int offset, int val)
+{
+ struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc);
+ struct device *parent = rc5t583_gpio->rc5t583->dev;
+ if (val)
+ rc5t583_set_bits(parent, RC5T583_GPIO_IOOUT, BIT(offset));
+ else
+ rc5t583_clear_bits(parent, RC5T583_GPIO_IOOUT, BIT(offset));
+}
+
+static int rc5t583_gpio_dir_input(struct gpio_chip *gc, unsigned int offset)
+{
+ struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc);
+ struct device *parent = rc5t583_gpio->rc5t583->dev;
+ int ret;
+
+ ret = rc5t583_clear_bits(parent, RC5T583_GPIO_IOSEL, BIT(offset));
+ if (ret < 0)
+ return ret;
+
+ /* Set pin to gpio mode */
+ return rc5t583_clear_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset));
+}
+
+static int rc5t583_gpio_dir_output(struct gpio_chip *gc, unsigned offset,
+ int value)
+{
+ struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc);
+ struct device *parent = rc5t583_gpio->rc5t583->dev;
+ int ret;
+
+ rc5t583_gpio_set(gc, offset, value);
+ ret = rc5t583_set_bits(parent, RC5T583_GPIO_IOSEL, BIT(offset));
+ if (ret < 0)
+ return ret;
+
+ /* Set pin to gpio mode */
+ return rc5t583_clear_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset));
+}
+
+static int rc5t583_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+ struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc);
+
+ if ((offset >= 0) && (offset < 8))
+ return rc5t583_gpio->rc5t583->irq_base +
+ RC5T583_IRQ_GPIO0 + offset;
+ return -EINVAL;
+}
+
+static void rc5t583_gpio_free(struct gpio_chip *gc, unsigned offset)
+{
+ struct rc5t583_gpio *rc5t583_gpio = to_rc5t583_gpio(gc);
+ struct device *parent = rc5t583_gpio->rc5t583->dev;
+
+ rc5t583_set_bits(parent, RC5T583_GPIO_PGSEL, BIT(offset));
+}
+
+static int __devinit rc5t583_gpio_probe(struct platform_device *pdev)
+{
+ struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
+ struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev);
+ struct rc5t583_gpio *rc5t583_gpio;
+
+ rc5t583_gpio = devm_kzalloc(&pdev->dev, sizeof(*rc5t583_gpio),
+ GFP_KERNEL);
+ if (!rc5t583_gpio) {
+ dev_warn(&pdev->dev, "Mem allocation for rc5t583_gpio failed");
+ return -ENOMEM;
+ }
+
+ rc5t583_gpio->gpio_chip.label = "gpio-rc5t583",
+ rc5t583_gpio->gpio_chip.owner = THIS_MODULE,
+ rc5t583_gpio->gpio_chip.free = rc5t583_gpio_free,
+ rc5t583_gpio->gpio_chip.direction_input = rc5t583_gpio_dir_input,
+ rc5t583_gpio->gpio_chip.direction_output = rc5t583_gpio_dir_output,
+ rc5t583_gpio->gpio_chip.set = rc5t583_gpio_set,
+ rc5t583_gpio->gpio_chip.get = rc5t583_gpio_get,
+ rc5t583_gpio->gpio_chip.to_irq = rc5t583_gpio_to_irq,
+ rc5t583_gpio->gpio_chip.ngpio = RC5T583_MAX_GPIO,
+ rc5t583_gpio->gpio_chip.can_sleep = 1,
+ rc5t583_gpio->gpio_chip.dev = &pdev->dev;
+ rc5t583_gpio->gpio_chip.base = -1;
+ rc5t583_gpio->rc5t583 = rc5t583;
+
+ if (pdata && pdata->gpio_base)
+ rc5t583_gpio->gpio_chip.base = pdata->gpio_base;
+
+ platform_set_drvdata(pdev, rc5t583_gpio);
+
+ return gpiochip_add(&rc5t583_gpio->gpio_chip);
+}
+
+static int __devexit rc5t583_gpio_remove(struct platform_device *pdev)
+{
+ struct rc5t583_gpio *rc5t583_gpio = platform_get_drvdata(pdev);
+
+ return gpiochip_remove(&rc5t583_gpio->gpio_chip);
+}
+
+static struct platform_driver rc5t583_gpio_driver = {
+ .driver = {
+ .name = "rc5t583-gpio",
+ .owner = THIS_MODULE,
+ },
+ .probe = rc5t583_gpio_probe,
+ .remove = __devexit_p(rc5t583_gpio_remove),
+};
+
+static int __init rc5t583_gpio_init(void)
+{
+ return platform_driver_register(&rc5t583_gpio_driver);
+}
+subsys_initcall(rc5t583_gpio_init);
+
+static void __exit rc5t583_gpio_exit(void)
+{
+ platform_driver_unregister(&rc5t583_gpio_driver);
+}
+module_exit(rc5t583_gpio_exit);
+
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_DESCRIPTION("GPIO interface for RC5T583");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:rc5t583-gpio");
diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c
index 7eef648a3351..af6dc837ffca 100644
--- a/drivers/gpio/gpio-tps65910.c
+++ b/drivers/gpio/gpio-tps65910.c
@@ -18,14 +18,26 @@
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
+#include <linux/platform_device.h>
#include <linux/mfd/tps65910.h>
+struct tps65910_gpio {
+ struct gpio_chip gpio_chip;
+ struct tps65910 *tps65910;
+};
+
+static inline struct tps65910_gpio *to_tps65910_gpio(struct gpio_chip *chip)
+{
+ return container_of(chip, struct tps65910_gpio, gpio_chip);
+}
+
static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset)
{
- struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
- uint8_t val;
+ struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc);
+ struct tps65910 *tps65910 = tps65910_gpio->tps65910;
+ unsigned int val;
- tps65910->read(tps65910, TPS65910_GPIO0 + offset, 1, &val);
+ tps65910_reg_read(tps65910, TPS65910_GPIO0 + offset, &val);
if (val & GPIO_STS_MASK)
return 1;
@@ -36,83 +48,135 @@ static int tps65910_gpio_get(struct gpio_chip *gc, unsigned offset)
static void tps65910_gpio_set(struct gpio_chip *gc, unsigned offset,
int value)
{
- struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
+ struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc);
+ struct tps65910 *tps65910 = tps65910_gpio->tps65910;
if (value)
- tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset,
+ tps65910_reg_set_bits(tps65910, TPS65910_GPIO0 + offset,
GPIO_SET_MASK);
else
- tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset,
+ tps65910_reg_clear_bits(tps65910, TPS65910_GPIO0 + offset,
GPIO_SET_MASK);
}
static int tps65910_gpio_output(struct gpio_chip *gc, unsigned offset,
int value)
{
- struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
+ struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc);
+ struct tps65910 *tps65910 = tps65910_gpio->tps65910;
/* Set the initial value */
tps65910_gpio_set(gc, offset, value);
- return tps65910_set_bits(tps65910, TPS65910_GPIO0 + offset,
+ return tps65910_reg_set_bits(tps65910, TPS65910_GPIO0 + offset,
GPIO_CFG_MASK);
}
static int tps65910_gpio_input(struct gpio_chip *gc, unsigned offset)
{
- struct tps65910 *tps65910 = container_of(gc, struct tps65910, gpio);
+ struct tps65910_gpio *tps65910_gpio = to_tps65910_gpio(gc);
+ struct tps65910 *tps65910 = tps65910_gpio->tps65910;
- return tps65910_clear_bits(tps65910, TPS65910_GPIO0 + offset,
+ return tps65910_reg_clear_bits(tps65910, TPS65910_GPIO0 + offset,
GPIO_CFG_MASK);
}
-void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base)
+static int __devinit tps65910_gpio_probe(struct platform_device *pdev)
{
+ struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
+ struct tps65910_board *pdata = dev_get_platdata(tps65910->dev);
+ struct tps65910_gpio *tps65910_gpio;
int ret;
- struct tps65910_board *board_data;
+ int i;
+
+ tps65910_gpio = devm_kzalloc(&pdev->dev,
+ sizeof(*tps65910_gpio), GFP_KERNEL);
+ if (!tps65910_gpio) {
+ dev_err(&pdev->dev, "Could not allocate tps65910_gpio\n");
+ return -ENOMEM;
+ }
- if (!gpio_base)
- return;
+ tps65910_gpio->tps65910 = tps65910;
- tps65910->gpio.owner = THIS_MODULE;
- tps65910->gpio.label = tps65910->i2c_client->name;
- tps65910->gpio.dev = tps65910->dev;
- tps65910->gpio.base = gpio_base;
+ tps65910_gpio->gpio_chip.owner = THIS_MODULE;
+ tps65910_gpio->gpio_chip.label = tps65910->i2c_client->name;
switch(tps65910_chip_id(tps65910)) {
case TPS65910:
- tps65910->gpio.ngpio = TPS65910_NUM_GPIO;
+ tps65910_gpio->gpio_chip.ngpio = TPS65910_NUM_GPIO;
break;
case TPS65911:
- tps65910->gpio.ngpio = TPS65911_NUM_GPIO;
+ tps65910_gpio->gpio_chip.ngpio = TPS65911_NUM_GPIO;
break;
default:
- return;
+ return -EINVAL;
}
- tps65910->gpio.can_sleep = 1;
-
- tps65910->gpio.direction_input = tps65910_gpio_input;
- tps65910->gpio.direction_output = tps65910_gpio_output;
- tps65910->gpio.set = tps65910_gpio_set;
- tps65910->gpio.get = tps65910_gpio_get;
-
- /* Configure sleep control for gpios */
- board_data = dev_get_platdata(tps65910->dev);
- if (board_data) {
- int i;
- for (i = 0; i < tps65910->gpio.ngpio; ++i) {
- if (board_data->en_gpio_sleep[i]) {
- ret = tps65910_set_bits(tps65910,
- TPS65910_GPIO0 + i, GPIO_SLEEP_MASK);
- if (ret < 0)
- dev_warn(tps65910->dev,
- "GPIO Sleep setting failed\n");
- }
- }
+ tps65910_gpio->gpio_chip.can_sleep = 1;
+ tps65910_gpio->gpio_chip.direction_input = tps65910_gpio_input;
+ tps65910_gpio->gpio_chip.direction_output = tps65910_gpio_output;
+ tps65910_gpio->gpio_chip.set = tps65910_gpio_set;
+ tps65910_gpio->gpio_chip.get = tps65910_gpio_get;
+ tps65910_gpio->gpio_chip.dev = &pdev->dev;
+ if (pdata && pdata->gpio_base)
+ tps65910_gpio->gpio_chip.base = pdata->gpio_base;
+ else
+ tps65910_gpio->gpio_chip.base = -1;
+
+ if (!pdata)
+ goto skip_init;
+
+ /* Configure sleep control for gpios if provided */
+ for (i = 0; i < tps65910_gpio->gpio_chip.ngpio; ++i) {
+ if (!pdata->en_gpio_sleep[i])
+ continue;
+
+ ret = tps65910_reg_set_bits(tps65910,
+ TPS65910_GPIO0 + i, GPIO_SLEEP_MASK);
+ if (ret < 0)
+ dev_warn(tps65910->dev,
+ "GPIO Sleep setting failed with err %d\n", ret);
+ }
+
+skip_init:
+ ret = gpiochip_add(&tps65910_gpio->gpio_chip);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
+ return ret;
}
- ret = gpiochip_add(&tps65910->gpio);
+ platform_set_drvdata(pdev, tps65910_gpio);
- if (ret)
- dev_warn(tps65910->dev, "GPIO registration failed: %d\n", ret);
+ return ret;
}
+
+static int __devexit tps65910_gpio_remove(struct platform_device *pdev)
+{
+ struct tps65910_gpio *tps65910_gpio = platform_get_drvdata(pdev);
+
+ return gpiochip_remove(&tps65910_gpio->gpio_chip);
+}
+
+static struct platform_driver tps65910_gpio_driver = {
+ .driver.name = "tps65910-gpio",
+ .driver.owner = THIS_MODULE,
+ .probe = tps65910_gpio_probe,
+ .remove = __devexit_p(tps65910_gpio_remove),
+};
+
+static int __init tps65910_gpio_init(void)
+{
+ return platform_driver_register(&tps65910_gpio_driver);
+}
+subsys_initcall(tps65910_gpio_init);
+
+static void __exit tps65910_gpio_exit(void)
+{
+ platform_driver_unregister(&tps65910_gpio_driver);
+}
+module_exit(tps65910_gpio_exit);
+
+MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
+MODULE_AUTHOR("Jorge Eduardo Candelaria jedu@slimlogic.co.uk>");
+MODULE_DESCRIPTION("GPIO interface for TPS65910/TPS6511 PMICs");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:tps65910-gpio");
diff --git a/drivers/media/video/tegra/ad5816.c b/drivers/media/video/tegra/ad5816.c
index d95368f43cf6..ed113b3a187c 100644
--- a/drivers/media/video/tegra/ad5816.c
+++ b/drivers/media/video/tegra/ad5816.c
@@ -249,9 +249,8 @@ static int ad5816_i2c_wr16(struct ad5816_info *info, u8 reg, u16 val)
return 0;
}
-static int ad5816_gpio_wr(struct ad5816_info *info,
- enum ad5816_gpio_types i,
- int val) /* val: 0=deassert, 1=assert */
+static int ad5816_gpio_wr(struct ad5816_info *info, ad5816_gpio_types i,
+ int val) /* val: 0=deassert, 1=assert */
{
int err = -EINVAL;
if (info->gpio[i].valid) {
@@ -370,8 +369,7 @@ static void ad5816_gpio_init(struct ad5816_info *info)
}
}
-static int ad5816_vreg_dis(struct ad5816_info *info,
- enum ad5816_vreg i)
+static int ad5816_vreg_dis(struct ad5816_info *info, ad5816_vreg i)
{
int err = 0;
if (info->vreg[i].vreg_flag && (info->vreg[i].vreg != NULL)) {
@@ -396,8 +394,7 @@ static int ad5816_vreg_dis_all(struct ad5816_info *info)
return err;
}
-static int ad5816_vreg_en(struct ad5816_info *info,
- enum ad5816_vreg i)
+static int ad5816_vreg_en(struct ad5816_info *info, ad5816_vreg i)
{
int err = 0;
if (!info->vreg[i].vreg_flag && (info->vreg[i].vreg != NULL)) {
diff --git a/drivers/media/video/tegra/nvavp/Kconfig b/drivers/media/video/tegra/nvavp/Kconfig
index 2d3af3f79fb3..294253a0de49 100644
--- a/drivers/media/video/tegra/nvavp/Kconfig
+++ b/drivers/media/video/tegra/nvavp/Kconfig
@@ -8,3 +8,14 @@ config TEGRA_NVAVP
/dev/tegra_avpchannel.
If unsure, say N
+
+config TEGRA_NVAVP_AUDIO
+ bool "Enable Audio Channel support for Tegra NVAVP driver"
+ depends on TEGRA_NVAVP
+ default n
+ help
+ Enables support for the push-buffer mechanism based driver for the Tegra
+ audio multimedia framework. Exports the Tegra nvavp interface on device node
+ /dev/tegra_audio_avpchannel.
+
+ If unsure, say N
diff --git a/drivers/media/video/tegra/nvavp/nvavp_dev.c b/drivers/media/video/tegra/nvavp/nvavp_dev.c
index 012f50b7a5f4..b695aa16af59 100644
--- a/drivers/media/video/tegra/nvavp/nvavp_dev.c
+++ b/drivers/media/video/tegra/nvavp/nvavp_dev.c
@@ -72,6 +72,34 @@
/* AVP behavior params */
#define NVAVP_OS_IDLE_TIMEOUT 100 /* milli-seconds */
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+/* Two control channels: Audio and Video channels */
+#define NVAVP_NUM_CHANNELS 2
+
+#define NVAVP_AUDIO_CHANNEL 1
+
+#define IS_AUDIO_CHANNEL_ID(channel_id) (channel_id == NVAVP_AUDIO_CHANNEL ? 1: 0)
+#else
+#define NVAVP_NUM_CHANNELS 1
+#endif
+
+/* Channel ID 0 represents the Video channel control area */
+#define NVAVP_VIDEO_CHANNEL 0
+/* Channel ID 1 represents the Audio channel control area */
+
+#define IS_VIDEO_CHANNEL_ID(channel_id) (channel_id == NVAVP_VIDEO_CHANNEL ? 1: 0)
+
+
+struct nvavp_channel {
+ struct mutex pushbuffer_lock;
+ struct nvmap_handle_ref *pushbuf_handle;
+ unsigned long pushbuf_phys;
+ u8 *pushbuf_data;
+ u32 pushbuf_index;
+ u32 pushbuf_fence;
+ struct nv_e276_control *os_control;
+};
+
struct nvavp_info {
u32 clk_enabled;
struct clk *bsev_clk;
@@ -88,8 +116,10 @@ struct nvavp_info {
struct mutex open_lock;
int refcount;
- int initialized;
-
+ int video_initialized;
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ int audio_initialized;
+#endif
struct work_struct clock_disable_work;
/* os information */
@@ -101,22 +131,19 @@ struct nvavp_info {
/* client for driver allocations, persistent */
struct nvmap_client *nvmap;
- struct mutex pushbuffer_lock;
- struct nvmap_handle_ref *pushbuf_handle;
- unsigned long pushbuf_phys;
- u8 *pushbuf_data;
- u32 pushbuf_index;
- u32 pushbuf_fence;
bool pending;
- struct nv_e276_control *os_control;
+ struct nvavp_channel channel_info[NVAVP_NUM_CHANNELS];
struct nvhost_syncpt *nvhost_syncpt;
u32 syncpt_id;
u32 syncpt_value;
struct nvhost_device *nvhost_dev;
- struct miscdevice misc_dev;
+ struct miscdevice video_misc_dev;
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ struct miscdevice audio_misc_dev;
+#endif
atomic_t clock_stay_on_refcount;
};
@@ -128,8 +155,77 @@ struct nvavp_clientctx {
int num_relocs;
struct nvavp_info *nvavp;
int clock_stay_on;
+ int channel_id;
};
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+static int nvavp_get_audio_init_status(struct nvavp_info *nvavp)
+{
+ return nvavp->audio_initialized;
+}
+
+static void nvavp_set_audio_init_status(struct nvavp_info *nvavp, int status)
+{
+ nvavp->audio_initialized = status;
+}
+#endif
+
+static void nvavp_set_video_init_status(struct nvavp_info *nvavp, int status)
+{
+ nvavp->video_initialized = status;
+}
+
+static int nvavp_get_video_init_status(struct nvavp_info *nvavp)
+{
+ return nvavp->video_initialized;
+}
+
+static struct nvavp_channel *nvavp_get_channel_info(struct nvavp_info *nvavp, int channel_id)
+{
+ return &nvavp->channel_info[channel_id];
+}
+
+static void nvavp_set_channel_control_area(struct nvavp_info *nvavp, int channel_id)
+{
+ struct nv_e276_control *control;
+ struct nvavp_os_info *os = &nvavp->os_info;
+ u32 temp;
+ void *ptr;
+ struct nvavp_channel *channel_info;
+
+ ptr = os->data + os->control_offset + (sizeof(struct nv_e276_control) * channel_id);
+
+ channel_info = nvavp_get_channel_info(nvavp, channel_id);
+ channel_info->os_control = (struct nv_e276_control *)ptr;
+
+ control = channel_info->os_control;
+
+ /* init get and put pointers */
+ writel(0x0, &control->put);
+ writel(0x0, &control->get);
+
+ pr_debug("nvavp_set_channel_control_area for channel_id (%d):\
+ control->put (0x%x) control->get (0x%x)\n",
+ channel_id, &control->put, &control->get);
+
+ /* enable avp VDE clock control and disable iram clock gating */
+ writel(0x0, &control->idle_clk_enable);
+ writel(0x0, &control->iram_clk_gating);
+
+ /* enable avp idle timeout interrupt */
+ writel(0x1, &control->idle_notify_enable);
+ writel(NVAVP_OS_IDLE_TIMEOUT, &control->idle_notify_delay);
+
+ /* init dma start and end pointers */
+ writel(channel_info->pushbuf_phys, &control->dma_start);
+ writel((channel_info->pushbuf_phys + NVAVP_PUSHBUFFER_SIZE),
+ &control->dma_end);
+
+ writel(0x00, &channel_info->pushbuf_index);
+ temp = NVAVP_PUSHBUFFER_SIZE - NVAVP_PUSHBUFFER_MIN_UPDATE_SPACE;
+ writel(temp, &channel_info->pushbuf_fence);
+}
+
static struct clk *nvavp_clk_get(struct nvavp_info *nvavp, int id)
{
if (!nvavp)
@@ -175,7 +271,8 @@ static void nvavp_clks_disable(struct nvavp_info *nvavp)
static u32 nvavp_check_idle(struct nvavp_info *nvavp)
{
- struct nv_e276_control *control = nvavp->os_control;
+ struct nvavp_channel *channel_info = nvavp_get_channel_info(nvavp, NVAVP_VIDEO_CHANNEL);
+ struct nv_e276_control *control = channel_info->os_control;
return ((control->put == control->get)
&& (!atomic_read(&nvavp->clock_stay_on_refcount))) ? 1 : 0;
}
@@ -183,18 +280,20 @@ static u32 nvavp_check_idle(struct nvavp_info *nvavp)
static void clock_disable_handler(struct work_struct *work)
{
struct nvavp_info *nvavp;
+ struct nvavp_channel *channel_info;
nvavp = container_of(work, struct nvavp_info,
clock_disable_work);
+ channel_info = nvavp_get_channel_info(nvavp, NVAVP_VIDEO_CHANNEL);
- mutex_lock(&nvavp->pushbuffer_lock);
+ mutex_lock(&channel_info->pushbuffer_lock);
mutex_lock(&nvavp->open_lock);
if (nvavp_check_idle(nvavp) && nvavp->pending) {
nvavp->pending = false;
nvavp_clks_disable(nvavp);
}
mutex_unlock(&nvavp->open_lock);
- mutex_unlock(&nvavp->pushbuffer_lock);
+ mutex_unlock(&channel_info->pushbuffer_lock);
}
static int nvavp_service(struct nvavp_info *nvavp)
@@ -212,6 +311,10 @@ static int nvavp_service(struct nvavp_info *nvavp)
if (inbox & NVE276_OS_INTERRUPT_VIDEO_IDLE)
schedule_work(&nvavp->clock_disable_work);
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ if (inbox & NVE276_OS_INTERRUPT_AUDIO_IDLE)
+ pr_debug("nvavp_service NVE276_OS_INTERRUPT_AUDIO_IDLE\n");
+#endif
if (inbox & NVE276_OS_INTERRUPT_DEBUG_STRING) {
/* Should only occur with debug AVP OS builds */
debug_print = os->data;
@@ -337,99 +440,91 @@ static int nvavp_reset_vde(struct nvavp_info *nvavp)
return 0;
}
-static int nvavp_pushbuffer_alloc(struct nvavp_info *nvavp)
+static int nvavp_pushbuffer_alloc(struct nvavp_info *nvavp, int channel_id)
{
int ret = 0;
- nvavp->pushbuf_handle = nvmap_alloc(nvavp->nvmap, NVAVP_PUSHBUFFER_SIZE,
- SZ_1M, NVMAP_HANDLE_UNCACHEABLE, 0);
- if (IS_ERR(nvavp->pushbuf_handle)) {
+ struct nvavp_channel *channel_info = nvavp_get_channel_info(
+ nvavp, channel_id);
+
+ channel_info->pushbuf_handle = nvmap_alloc(nvavp->nvmap,
+ NVAVP_PUSHBUFFER_SIZE,
+ SZ_1M, NVMAP_HANDLE_UNCACHEABLE,
+ 0);
+ if (IS_ERR(channel_info->pushbuf_handle)) {
dev_err(&nvavp->nvhost_dev->dev,
"cannot create pushbuffer handle\n");
- ret = PTR_ERR(nvavp->pushbuf_handle);
+ ret = PTR_ERR(channel_info->pushbuf_handle);
goto err_pushbuf_alloc;
}
- nvavp->pushbuf_data = (u8 *)nvmap_mmap(nvavp->pushbuf_handle);
- if (!nvavp->pushbuf_data) {
+ channel_info->pushbuf_data = (u8 *)nvmap_mmap(
+ channel_info->pushbuf_handle);
+
+ if (!channel_info->pushbuf_data) {
dev_err(&nvavp->nvhost_dev->dev,
"cannot map pushbuffer handle\n");
ret = -ENOMEM;
goto err_pushbuf_mmap;
}
- nvavp->pushbuf_phys = nvmap_pin(nvavp->nvmap, nvavp->pushbuf_handle);
- if (IS_ERR((void *)nvavp->pushbuf_phys)) {
+ channel_info->pushbuf_phys = nvmap_pin(nvavp->nvmap,
+ channel_info->pushbuf_handle);
+ if (IS_ERR((void *)channel_info->pushbuf_phys)) {
dev_err(&nvavp->nvhost_dev->dev,
"cannot pin pushbuffer handle\n");
- ret = PTR_ERR((void *)nvavp->pushbuf_phys);
+ ret = PTR_ERR((void *)channel_info->pushbuf_phys);
goto err_pushbuf_pin;
}
- memset(nvavp->pushbuf_data, 0, NVAVP_PUSHBUFFER_SIZE);
+ memset(channel_info->pushbuf_data, 0, NVAVP_PUSHBUFFER_SIZE);
return 0;
err_pushbuf_pin:
- nvmap_munmap(nvavp->pushbuf_handle, nvavp->pushbuf_data);
+ nvmap_munmap(channel_info->pushbuf_handle, channel_info->pushbuf_data);
err_pushbuf_mmap:
- nvmap_free(nvavp->nvmap, nvavp->pushbuf_handle);
+ nvmap_free(nvavp->nvmap, channel_info->pushbuf_handle);
err_pushbuf_alloc:
return ret;
}
static void nvavp_pushbuffer_free(struct nvavp_info *nvavp)
{
- nvmap_unpin(nvavp->nvmap, nvavp->pushbuf_handle);
- nvmap_munmap(nvavp->pushbuf_handle, nvavp->pushbuf_data);
- nvmap_free(nvavp->nvmap, nvavp->pushbuf_handle);
+ int channel_id;
+
+ for (channel_id = 0; channel_id < NVAVP_NUM_CHANNELS; channel_id++) {
+ if (nvavp->channel_info[channel_id].pushbuf_data) {
+ nvmap_unpin(nvavp->nvmap,
+ nvavp->channel_info[channel_id].pushbuf_handle);
+ nvmap_munmap(
+ nvavp->channel_info[channel_id].pushbuf_handle,
+ nvavp->channel_info[channel_id].pushbuf_data);
+ nvmap_free(nvavp->nvmap,
+ nvavp->channel_info[channel_id].pushbuf_handle);
+ }
+ }
}
+
static int nvavp_pushbuffer_init(struct nvavp_info *nvavp)
{
- void *ptr;
- struct nvavp_os_info *os = &nvavp->os_info;
- struct nv_e276_control *control;
- u32 temp;
- int ret;
+ int ret, channel_id;
- ret = nvavp_pushbuffer_alloc(nvavp);
- if (ret) {
- dev_err(&nvavp->nvhost_dev->dev,
- "unable to alloc pushbuffer\n");
- return ret;
- }
-
- ptr = os->data;
- ptr += os->control_offset;
- nvavp->os_control = (struct nv_e276_control *)ptr;
-
- control = nvavp->os_control;
- memset(control, 0, sizeof(struct nvavp_os_info));
-
- /* init get and put pointers */
- writel(0x0, &control->put);
- writel(0x0, &control->get);
-
- /* enable avp VDE clock control and disable iram clock gating */
- writel(0x0, &control->idle_clk_enable);
- writel(0x0, &control->iram_clk_gating);
-
- /* enable avp idle timeout interrupt */
- writel(0x1, &control->idle_notify_enable);
- writel(NVAVP_OS_IDLE_TIMEOUT, &control->idle_notify_delay);
-
- /* init dma start and end pointers */
- writel(nvavp->pushbuf_phys, &control->dma_start);
- writel((nvavp->pushbuf_phys + NVAVP_PUSHBUFFER_SIZE),
- &control->dma_end);
-
- writel(0x00, &nvavp->pushbuf_index);
- temp = NVAVP_PUSHBUFFER_SIZE - NVAVP_PUSHBUFFER_MIN_UPDATE_SPACE;
- writel(temp, &nvavp->pushbuf_fence);
-
- nvavp->syncpt_id = NVSYNCPT_AVP_0;
- nvavp->syncpt_value = nvhost_syncpt_read(nvavp->nvhost_syncpt,
- nvavp->syncpt_id);
+ for (channel_id = 0; channel_id < NVAVP_NUM_CHANNELS; channel_id++) {
+ ret = nvavp_pushbuffer_alloc(nvavp, channel_id);
+ if (ret) {
+ dev_err(&nvavp->nvhost_dev->dev,
+ "unable to alloc pushbuffer\n");
+ return ret;
+ }
+ nvavp_set_channel_control_area(nvavp, channel_id);
+ if (IS_VIDEO_CHANNEL_ID(channel_id)) {
+ nvavp->syncpt_id = NVSYNCPT_AVP_0;
+ nvavp->syncpt_value = nvhost_syncpt_read(
+ nvavp->nvhost_syncpt,
+ nvavp->syncpt_id);
+ }
+ }
return 0;
}
@@ -440,37 +535,47 @@ static void nvavp_pushbuffer_deinit(struct nvavp_info *nvavp)
static int nvavp_pushbuffer_update(struct nvavp_info *nvavp, u32 phys_addr,
u32 gather_count, struct nvavp_syncpt *syncpt,
- u32 ext_ucode_flag)
+ u32 ext_ucode_flag, int channel_id)
{
- struct nv_e276_control *control = nvavp->os_control;
+ struct nvavp_channel *channel_info;
+ struct nv_e276_control *control;
u32 gather_cmd, setucode_cmd, sync = 0;
u32 wordcount = 0;
u32 index, value = -1;
- mutex_lock(&nvavp->pushbuffer_lock);
+ channel_info = nvavp_get_channel_info(nvavp, channel_id);
+
+ control = channel_info->os_control;
+ pr_debug("nvavp_pushbuffer_update for channel_id (%d):\
+ control->put (0x%x) control->get (0x%x)\n",
+ channel_id, &control->put, &control->get);
+
+ mutex_lock(&channel_info->pushbuffer_lock);
/* check for pushbuffer wrapping */
- if (nvavp->pushbuf_index >= nvavp->pushbuf_fence)
- nvavp->pushbuf_index = 0;
+ if (channel_info->pushbuf_index >= channel_info->pushbuf_fence)
+ channel_info->pushbuf_index = 0;
if (!ext_ucode_flag) {
setucode_cmd =
NVE26E_CH_OPCODE_INCR(NVE276_SET_MICROCODE_A, 3);
- index = wordcount + nvavp->pushbuf_index;
- writel(setucode_cmd, (nvavp->pushbuf_data + index));
+ index = wordcount + channel_info->pushbuf_index;
+ writel(setucode_cmd, (channel_info->pushbuf_data + index));
wordcount += sizeof(u32);
- index = wordcount + nvavp->pushbuf_index;
- writel(0, (nvavp->pushbuf_data + index));
+ index = wordcount + channel_info->pushbuf_index;
+ writel(0, (channel_info->pushbuf_data + index));
wordcount += sizeof(u32);
- index = wordcount + nvavp->pushbuf_index;
- writel(nvavp->ucode_info.phys, (nvavp->pushbuf_data + index));
+ index = wordcount + channel_info->pushbuf_index;
+ writel(nvavp->ucode_info.phys,
+ (channel_info->pushbuf_data + index));
wordcount += sizeof(u32);
- index = wordcount + nvavp->pushbuf_index;
- writel(nvavp->ucode_info.size, (nvavp->pushbuf_data + index));
+ index = wordcount + channel_info->pushbuf_index;
+ writel(nvavp->ucode_info.size,
+ (channel_info->pushbuf_data + index));
wordcount += sizeof(u32);
}
@@ -485,44 +590,58 @@ static int nvavp_pushbuffer_update(struct nvavp_info *nvavp, u32 phys_addr,
}
/* write commands out */
- index = wordcount + nvavp->pushbuf_index;
- writel(gather_cmd, (nvavp->pushbuf_data + index));
+ index = wordcount + channel_info->pushbuf_index;
+ writel(gather_cmd, (channel_info->pushbuf_data + index));
wordcount += sizeof(u32);
- index = wordcount + nvavp->pushbuf_index;
- writel(phys_addr, (nvavp->pushbuf_data + index));
+ index = wordcount + channel_info->pushbuf_index;
+ writel(phys_addr, (channel_info->pushbuf_data + index));
wordcount += sizeof(u32);
if (syncpt) {
- index = wordcount + nvavp->pushbuf_index;
- writel(sync, (nvavp->pushbuf_data + index));
+ index = wordcount + channel_info->pushbuf_index;
+ writel(sync, (channel_info->pushbuf_data + index));
wordcount += sizeof(u32);
}
/* enable clocks to VDE/BSEV */
- mutex_lock(&nvavp->open_lock);
- if (!nvavp->pending) {
- nvavp_clks_enable(nvavp);
- nvavp->pending = true;
+ if (IS_VIDEO_CHANNEL_ID(channel_id)) {
+ mutex_lock(&nvavp->open_lock);
+ if (!nvavp->pending) {
+ nvavp_clks_enable(nvavp);
+ nvavp->pending = true;
+ }
+ mutex_unlock(&nvavp->open_lock);
}
- mutex_unlock(&nvavp->open_lock);
/* update put pointer */
- nvavp->pushbuf_index = (nvavp->pushbuf_index + wordcount) &
+ channel_info->pushbuf_index = (channel_info->pushbuf_index + wordcount)&
(NVAVP_PUSHBUFFER_SIZE - 1);
- writel(nvavp->pushbuf_index, &control->put);
+
+ writel(channel_info->pushbuf_index, &control->put);
wmb();
/* wake up avp */
- writel(0xA0000001, NVAVP_OS_OUTBOX);
+ if (IS_VIDEO_CHANNEL_ID(channel_id)) {
+ pr_debug("Wake up Video Channel\n");
+ writel(0xA0000001, NVAVP_OS_OUTBOX);
+ }
+ else {
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ if (IS_AUDIO_CHANNEL_ID(channel_id)) {
+ pr_debug("Wake up Audio Channel\n");
+ writel(0xA0000002, NVAVP_OS_OUTBOX);
+ }
+#endif
+ }
/* Fill out fence struct */
if (syncpt) {
syncpt->id = nvavp->syncpt_id;
syncpt->value = value;
}
- mutex_unlock(&nvavp->pushbuffer_lock);
+ mutex_unlock(&channel_info->pushbuffer_lock);
return 0;
}
@@ -547,14 +666,14 @@ static int nvavp_load_ucode(struct nvavp_info *nvavp)
sprintf(fw_ucode_file, "nvavp_vid_ucode.bin");
ret = request_firmware(&nvavp_ucode_fw, fw_ucode_file,
- nvavp->misc_dev.this_device);
+ nvavp->video_misc_dev.this_device);
if (ret) {
/* Try alternative version */
sprintf(fw_ucode_file, "nvavp_vid_ucode_alt.bin");
ret = request_firmware(&nvavp_ucode_fw,
fw_ucode_file,
- nvavp->misc_dev.this_device);
+ nvavp->video_misc_dev.this_device);
if (ret) {
dev_err(&nvavp->nvhost_dev->dev,
@@ -652,7 +771,7 @@ static int nvavp_load_os(struct nvavp_info *nvavp, char *fw_os_file)
if (!os_info->os_bin) {
ret = request_firmware(&nvavp_os_fw, fw_os_file,
- nvavp->misc_dev.this_device);
+ nvavp->video_misc_dev.this_device);
if (ret) {
dev_err(&nvavp->nvhost_dev->dev,
"cannot read os firmware '%s'\n", fw_os_file);
@@ -717,14 +836,28 @@ err_req_fw:
return ret;
}
-static int nvavp_init(struct nvavp_info *nvavp)
+
+static int nvavp_os_init(struct nvavp_info *nvavp)
{
char fw_os_file[32];
int ret = 0;
+ int video_initialized, audio_initialized = 0;
- if (nvavp->initialized)
+ video_initialized = nvavp_get_video_init_status(nvavp);
+
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ audio_initialized = nvavp_get_audio_init_status(nvavp);
+#endif
+ pr_debug("video_initialized(%d) audio_initialized(%d)\n",
+ video_initialized, audio_initialized);
+
+ /* Video and Audio both are initialized */
+ if (video_initialized || audio_initialized)
return ret;
+ /* Video or Audio both are uninitialized */
+ pr_debug("video_initialized == audio_initialized (%d)\n",
+ nvavp->video_initialized);
#if defined(CONFIG_TEGRA_AVP_KERNEL_ON_MMU) /* Tegra2 with AVP MMU */
/* paddr is any address returned from nvmap_pin */
/* vaddr is AVP_KERNEL_VIRT_BASE */
@@ -768,7 +901,6 @@ static int nvavp_init(struct nvavp_info *nvavp)
nvavp->os_info.reset_addr = nvavp->os_info.phys;
nvavp->os_info.data = ioremap(nvavp->os_info.phys, SZ_1M);
#endif
-
ret = nvavp_load_os(nvavp, fw_os_file);
if (ret) {
dev_err(&nvavp->nvhost_dev->dev,
@@ -782,21 +914,45 @@ static int nvavp_init(struct nvavp_info *nvavp)
"unable to init pushbuffer\n");
goto err_exit;
}
+ tegra_init_legacy_irq_cop();
+ enable_irq(nvavp->mbox_from_avp_pend_irq);
+err_exit:
+ return ret;
+}
- ret = nvavp_load_ucode(nvavp);
+static int nvavp_init(struct nvavp_info *nvavp, int channel_id)
+{
+ int ret = 0;
+
+ ret = nvavp_os_init(nvavp);
if (ret) {
dev_err(&nvavp->nvhost_dev->dev,
- "unable to load ucode\n");
- goto err_exit;
+ "unable to load os firmware and allocate buffers\n");
}
- tegra_init_legacy_irq_cop();
+ if (IS_VIDEO_CHANNEL_ID(channel_id) &&
+ (!nvavp_get_video_init_status(nvavp)) ) {
+ pr_debug("nvavp_init : channel_ID (%d)\n", channel_id);
+ ret = nvavp_load_ucode(nvavp);
+ if (ret) {
+ dev_err(&nvavp->nvhost_dev->dev,
+ "unable to load ucode\n");
+ goto err_exit;
+ }
- nvavp_reset_vde(nvavp);
- nvavp_reset_avp(nvavp, nvavp->os_info.reset_addr);
- enable_irq(nvavp->mbox_from_avp_pend_irq);
+ nvavp_reset_vde(nvavp);
+ nvavp_reset_avp(nvavp, nvavp->os_info.reset_addr);
- nvavp->initialized = 1;
+ nvavp_set_video_init_status(nvavp, 1);
+ }
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ if (IS_AUDIO_CHANNEL_ID(channel_id) &&
+ (!nvavp_get_audio_init_status(nvavp))) {
+ pr_debug("nvavp_init : channel_ID (%d)\n", channel_id);
+ nvavp_reset_avp(nvavp, nvavp->os_info.reset_addr);
+ nvavp_set_audio_init_status(nvavp, 1);
+ }
+#endif
err_exit:
return ret;
@@ -804,22 +960,48 @@ err_exit:
static void nvavp_uninit(struct nvavp_info *nvavp)
{
- if (!nvavp->initialized)
+ int video_initialized, audio_initialized = 0;
+
+ video_initialized = nvavp_get_video_init_status(nvavp);
+
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ audio_initialized = nvavp_get_audio_init_status(nvavp);
+#endif
+
+ pr_debug("nvavp_uninit video_initialized(%d) audio_initialized(%d)\n",
+ video_initialized, audio_initialized);
+
+ /* Video and Audio both are uninitialized */
+ if (!video_initialized && !audio_initialized)
return;
- disable_irq(nvavp->mbox_from_avp_pend_irq);
+ if (video_initialized) {
+ pr_debug("nvavp_uninit nvavp->video_initialized\n");
+ cancel_work_sync(&nvavp->clock_disable_work);
- cancel_work_sync(&nvavp->clock_disable_work);
+ nvavp_halt_vde(nvavp);
- nvavp_pushbuffer_deinit(nvavp);
+ clk_disable(nvavp->sclk);
+ clk_disable(nvavp->emc_clk);
- nvavp_halt_vde(nvavp);
- nvavp_halt_avp(nvavp);
+ nvavp_set_video_init_status(nvavp, 0);
+ video_initialized = 0;
+ }
- clk_disable(nvavp->sclk);
- clk_disable(nvavp->emc_clk);
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ if (audio_initialized) {
+ nvavp_set_audio_init_status(nvavp, 0);
+ audio_initialized = 0;
+ }
+#endif
- nvavp->initialized = 0;
+ /* Video and Audio both becomes uninitialized */
+ if (video_initialized == audio_initialized) {
+ pr_debug("nvavp_uninit both channels unitialized\n");
+ disable_irq(nvavp->mbox_from_avp_pend_irq);
+ nvavp_pushbuffer_deinit(nvavp);
+ nvavp_halt_avp(nvavp);
+ }
}
static int nvavp_set_clock_ioctl(struct file *filp, unsigned int cmd,
@@ -1010,7 +1192,8 @@ static int nvavp_pushbuffer_submit_ioctl(struct file *filp, unsigned int cmd,
ret = nvavp_pushbuffer_update(nvavp,
(phys_addr + hdr.cmdbuf.offset),
hdr.cmdbuf.words, &syncpt,
- (hdr.flags & NVAVP_UCODE_EXT));
+ (hdr.flags & NVAVP_UCODE_EXT),
+ clientctx->channel_id);
if (copy_to_user((void __user *)user_hdr->syncpt, &syncpt,
sizeof(struct nvavp_syncpt))) {
@@ -1021,7 +1204,8 @@ static int nvavp_pushbuffer_submit_ioctl(struct file *filp, unsigned int cmd,
ret = nvavp_pushbuffer_update(nvavp,
(phys_addr + hdr.cmdbuf.offset),
hdr.cmdbuf.words, NULL,
- (hdr.flags & NVAVP_UCODE_EXT));
+ (hdr.flags & NVAVP_UCODE_EXT),
+ clientctx->channel_id);
}
err_reloc_info:
@@ -1075,7 +1259,7 @@ static int nvavp_force_clock_stay_on_ioctl(struct file *filp, unsigned int cmd,
return 0;
}
-static int tegra_nvavp_open(struct inode *inode, struct file *filp)
+static int tegra_nvavp_open(struct inode *inode, struct file *filp, int channel_id)
{
struct miscdevice *miscdev = filp->private_data;
struct nvavp_info *nvavp = dev_get_drvdata(miscdev->parent);
@@ -1092,8 +1276,11 @@ static int tegra_nvavp_open(struct inode *inode, struct file *filp)
mutex_lock(&nvavp->open_lock);
- if (!nvavp->refcount)
- ret = nvavp_init(nvavp);
+ pr_debug("tegra_nvavp_open channel_id (%d)\n", channel_id);
+
+ clientctx->channel_id = channel_id;
+
+ ret = nvavp_init(nvavp, channel_id);
if (!ret)
nvavp->refcount++;
@@ -1109,6 +1296,20 @@ static int tegra_nvavp_open(struct inode *inode, struct file *filp)
return ret;
}
+static int tegra_nvavp_video_open(struct inode *inode, struct file *filp)
+{
+ pr_debug("tegra_nvavp_video_open NVAVP_VIDEO_CHANNEL\n");
+ return tegra_nvavp_open(inode, filp, NVAVP_VIDEO_CHANNEL);
+}
+
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+static int tegra_nvavp_audio_open(struct inode *inode, struct file *filp)
+{
+ pr_debug("tegra_nvavp_audio_open NVAVP_AUDIO_CHANNEL\n");
+ return tegra_nvavp_open(inode, filp, NVAVP_AUDIO_CHANNEL);
+}
+#endif
+
static int tegra_nvavp_release(struct inode *inode, struct file *filp)
{
struct nvavp_clientctx *clientctx = filp->private_data;
@@ -1181,13 +1382,22 @@ static long tegra_nvavp_ioctl(struct file *filp, unsigned int cmd,
return ret;
}
-static const struct file_operations tegra_nvavp_fops = {
+static const struct file_operations tegra_video_nvavp_fops = {
.owner = THIS_MODULE,
- .open = tegra_nvavp_open,
+ .open = tegra_nvavp_video_open,
.release = tegra_nvavp_release,
.unlocked_ioctl = tegra_nvavp_ioctl,
};
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+static const struct file_operations tegra_audio_nvavp_fops = {
+ .owner = THIS_MODULE,
+ .open = tegra_nvavp_audio_open,
+ .release = tegra_nvavp_release,
+ .unlocked_ioctl = tegra_nvavp_ioctl,
+};
+#endif
+
static int tegra_nvavp_probe(struct nvhost_device *ndev,
struct nvhost_device_id *id_table)
{
@@ -1195,7 +1405,7 @@ static int tegra_nvavp_probe(struct nvhost_device *ndev,
int irq;
unsigned int heap_mask;
u32 iovmm_addr;
- int ret = 0;
+ int ret = 0, channel_id;
irq = nvhost_get_irq_byname(ndev, "mbox_from_nvavp_pending");
if (irq < 0) {
@@ -1306,7 +1516,9 @@ static int tegra_nvavp_probe(struct nvhost_device *ndev,
nvavp->mbox_from_avp_pend_irq = irq;
mutex_init(&nvavp->open_lock);
- mutex_init(&nvavp->pushbuffer_lock);
+
+ for (channel_id = 0; channel_id < NVAVP_NUM_CHANNELS; channel_id++)
+ mutex_init(&nvavp->channel_info[channel_id].pushbuffer_lock);
/* TODO DO NOT USE NVAVP DEVICE */
nvavp->cop_clk = clk_get(&ndev->dev, "cop");
@@ -1349,18 +1561,32 @@ static int tegra_nvavp_probe(struct nvhost_device *ndev,
INIT_WORK(&nvavp->clock_disable_work, clock_disable_handler);
- nvavp->misc_dev.minor = MISC_DYNAMIC_MINOR;
- nvavp->misc_dev.name = "tegra_avpchannel";
- nvavp->misc_dev.fops = &tegra_nvavp_fops;
- nvavp->misc_dev.mode = S_IRWXUGO;
- nvavp->misc_dev.parent = &ndev->dev;
+ nvavp->video_misc_dev.minor = MISC_DYNAMIC_MINOR;
+ nvavp->video_misc_dev.name = "tegra_avpchannel";
+ nvavp->video_misc_dev.fops = &tegra_video_nvavp_fops;
+ nvavp->video_misc_dev.mode = S_IRWXUGO;
+ nvavp->video_misc_dev.parent = &ndev->dev;
- ret = misc_register(&nvavp->misc_dev);
+ ret = misc_register(&nvavp->video_misc_dev);
if (ret) {
dev_err(&ndev->dev, "unable to register misc device!\n");
goto err_misc_reg;
}
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ nvavp->audio_misc_dev.minor = MISC_DYNAMIC_MINOR;
+ nvavp->audio_misc_dev.name = "tegra_audio_avpchannel";
+ nvavp->audio_misc_dev.fops = &tegra_audio_nvavp_fops;
+ nvavp->audio_misc_dev.mode = S_IRWXUGO;
+ nvavp->audio_misc_dev.parent = &ndev->dev;
+
+ ret = misc_register(&nvavp->audio_misc_dev);
+ if (ret) {
+ dev_err(&ndev->dev, "unable to register misc device!\n");
+ goto err_audio_misc_reg;
+ }
+#endif
+
ret = request_irq(irq, nvavp_mbox_pending_isr, 0,
TEGRA_NVAVP_NAME, nvavp);
if (ret) {
@@ -1375,7 +1601,11 @@ static int tegra_nvavp_probe(struct nvhost_device *ndev,
return 0;
err_req_irq_pend:
- misc_deregister(&nvavp->misc_dev);
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ misc_deregister(&nvavp->audio_misc_dev);
+err_audio_misc_reg:
+#endif
+ misc_deregister(&nvavp->video_misc_dev);
err_misc_reg:
clk_put(nvavp->emc_clk);
err_get_emc_clk:
@@ -1421,8 +1651,11 @@ static int tegra_nvavp_remove(struct nvhost_device *ndev)
nvavp_unload_ucode(nvavp);
nvavp_unload_os(nvavp);
- misc_deregister(&nvavp->misc_dev);
+ misc_deregister(&nvavp->video_misc_dev);
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ misc_deregister(&nvavp->audio_misc_dev);
+#endif
clk_put(nvavp->bsev_clk);
clk_put(nvavp->vde_clk);
clk_put(nvavp->cop_clk);
@@ -1463,7 +1696,7 @@ static int tegra_nvavp_resume(struct nvhost_device *ndev)
mutex_lock(&nvavp->open_lock);
if (nvavp->refcount)
- nvavp_init(nvavp);
+ nvavp_init(nvavp, NVAVP_VIDEO_CHANNEL);
mutex_unlock(&nvavp->open_lock);
diff --git a/drivers/media/video/tegra/ov2710.c b/drivers/media/video/tegra/ov2710.c
index 5e8eaa123124..293cb8932dfb 100644
--- a/drivers/media/video/tegra/ov2710.c
+++ b/drivers/media/video/tegra/ov2710.c
@@ -21,6 +21,8 @@
#include <linux/uaccess.h>
#include <media/ov2710.h>
+#define SIZEOF_I2C_TRANSBUF 32
+
struct ov2710_reg {
u16 addr;
u16 val;
@@ -30,6 +32,7 @@ struct ov2710_info {
int mode;
struct i2c_client *i2c_client;
struct ov2710_platform_data *pdata;
+ u8 i2c_trans_buf[SIZEOF_I2C_TRANSBUF];
};
#define OV2710_TABLE_WAIT_MS 0
@@ -152,7 +155,7 @@ static struct ov2710_reg mode_1920x1080[] = {
{0x3704, 0x44},
{0x3801, 0xd2},
- {0x3503, 0x17},
+ {0x3503, 0x33},
{0x3500, 0x00},
{0x3501, 0x00},
{0x3502, 0x00},
@@ -283,7 +286,7 @@ static struct ov2710_reg mode_1280x720[] = {
{0x3704, 0x40},
{0x3801, 0xbc},
- {0x3503, 0x17},
+ {0x3503, 0x33},
{0x3500, 0x00},
{0x3501, 0x00},
{0x3502, 0x00},
@@ -400,14 +403,39 @@ static int ov2710_write_reg(struct i2c_client *client, u16 addr, u8 val)
return err;
}
-static int ov2710_write_table(struct i2c_client *client,
+static int ov2710_write_bulk_reg(struct i2c_client *client, u8 *data, int len)
+{
+ int err;
+ struct i2c_msg msg;
+
+ if (!client->adapter)
+ return -ENODEV;
+
+ msg.addr = client->addr;
+ msg.flags = 0;
+ msg.len = len;
+ msg.buf = data;
+
+ err = i2c_transfer(client->adapter, &msg, 1);
+ if (err == 1)
+ return 0;
+
+ pr_err("ov2710: i2c bulk transfer failed at %x\n",
+ (int)data[0] << 8 | data[1]);
+
+ return err;
+}
+
+static int ov2710_write_table(struct ov2710_info *info,
const struct ov2710_reg table[],
const struct ov2710_reg override_list[],
int num_override_regs)
{
int err;
- const struct ov2710_reg *next;
- int i;
+ const struct ov2710_reg *next, *n_next;
+ u8 *b_ptr = info->i2c_trans_buf;
+ unsigned int buf_filled = 0;
+ unsigned int i;
u16 val;
for (next = table; next->addr != OV2710_TABLE_END; next++) {
@@ -416,9 +444,7 @@ static int ov2710_write_table(struct i2c_client *client,
continue;
}
-
val = next->val;
-
/* When an override list is passed in, replace the reg */
/* value to write if the reg is in the list */
if (override_list) {
@@ -430,9 +456,28 @@ static int ov2710_write_table(struct i2c_client *client,
}
}
- err = ov2710_write_reg(client, next->addr, val);
+ if (!buf_filled) {
+ b_ptr = info->i2c_trans_buf;
+ *b_ptr++ = next->addr >> 8;
+ *b_ptr++ = next->addr & 0xff;
+ buf_filled = 2;
+ }
+ *b_ptr++ = val;
+ buf_filled++;
+
+ n_next = next + 1;
+ if (n_next->addr != OV2710_TABLE_END &&
+ n_next->addr != OV2710_TABLE_WAIT_MS &&
+ buf_filled < SIZEOF_I2C_TRANSBUF &&
+ n_next->addr == next->addr + 1) {
+ continue;
+ }
+
+ err = ov2710_write_bulk_reg(info->i2c_client,
+ info->i2c_trans_buf, buf_filled);
if (err)
return err;
+ buf_filled = 0;
}
return 0;
}
@@ -463,7 +508,7 @@ static int ov2710_set_mode(struct ov2710_info *info, struct ov2710_mode *mode)
ov2710_get_coarse_time_regs(reg_list + 2, mode->coarse_time);
ov2710_get_gain_reg(reg_list + 5, mode->gain);
- err = ov2710_write_table(info->i2c_client, mode_table[sensor_mode],
+ err = ov2710_write_table(info, mode_table[sensor_mode],
reg_list, 6);
if (err)
return err;
@@ -474,51 +519,37 @@ static int ov2710_set_mode(struct ov2710_info *info, struct ov2710_mode *mode)
static int ov2710_set_frame_length(struct ov2710_info *info, u32 frame_length)
{
- struct ov2710_reg reg_list[2];
- int i = 0;
int ret;
+ struct ov2710_reg reg_list[2];
+ u8 *b_ptr = info->i2c_trans_buf;
ov2710_get_frame_length_regs(reg_list, frame_length);
- for (i = 0; i < 2; i++) {
- ret = ov2710_write_reg(info->i2c_client, reg_list[i].addr,
- reg_list[i].val);
- if (ret)
- return ret;
- }
+ *b_ptr++ = reg_list[0].addr >> 8;
+ *b_ptr++ = reg_list[0].addr & 0xff;
+ *b_ptr++ = reg_list[0].val & 0xff;
+ *b_ptr++ = reg_list[1].val & 0xff;
+ ret = ov2710_write_bulk_reg(info->i2c_client, info->i2c_trans_buf, 4);
- return 0;
+ return ret;
}
static int ov2710_set_coarse_time(struct ov2710_info *info, u32 coarse_time)
{
int ret;
-
struct ov2710_reg reg_list[3];
- int i = 0;
+ u8 *b_ptr = info->i2c_trans_buf;
ov2710_get_coarse_time_regs(reg_list, coarse_time);
- ret = ov2710_write_reg(info->i2c_client, 0x3212, 0x01);
- if (ret)
- return ret;
-
- for (i = 0; i < 3; i++) {
- ret = ov2710_write_reg(info->i2c_client, reg_list[i].addr,
- reg_list[i].val);
- if (ret)
- return ret;
- }
-
- ret = ov2710_write_reg(info->i2c_client, 0x3212, 0x11);
- if (ret)
- return ret;
+ *b_ptr++ = reg_list[0].addr >> 8;
+ *b_ptr++ = reg_list[0].addr & 0xff;
+ *b_ptr++ = reg_list[0].val & 0xff;
+ *b_ptr++ = reg_list[1].val & 0xff;
+ *b_ptr++ = reg_list[2].val & 0xff;
+ ret = ov2710_write_bulk_reg(info->i2c_client, info->i2c_trans_buf, 5);
- ret = ov2710_write_reg(info->i2c_client, 0x3212, 0xa1);
- if (ret)
- return ret;
-
- return 0;
+ return ret;
}
static int ov2710_set_gain(struct ov2710_info *info, u16 gain)
@@ -533,6 +564,48 @@ static int ov2710_set_gain(struct ov2710_info *info, u16 gain)
return ret;
}
+static int ov2710_set_group_hold(struct ov2710_info *info, struct ov2710_ae *ae)
+{
+ int ret;
+ int count = 0;
+ bool groupHoldEnabled = false;
+
+ if (ae->gain_enable)
+ count++;
+ if (ae->coarse_time_enable)
+ count++;
+ if (ae->frame_length_enable)
+ count++;
+ if (count >= 2)
+ groupHoldEnabled = true;
+
+ if (groupHoldEnabled) {
+ ret = ov2710_write_reg(info->i2c_client, 0x3212, 0x01);
+ if (ret)
+ return ret;
+ }
+
+ if (ae->gain_enable)
+ ov2710_set_gain(info, ae->gain);
+ if (ae->coarse_time_enable)
+ ov2710_set_coarse_time(info, ae->coarse_time);
+ if (ae->frame_length_enable)
+ ov2710_set_frame_length(info, ae->frame_length);
+
+ if (groupHoldEnabled) {
+ ret = ov2710_write_reg(info->i2c_client, 0x3212, 0x11);
+ if (ret)
+ return ret;
+
+ ret = ov2710_write_reg(info->i2c_client, 0x3212, 0xa1);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+
static int ov2710_get_status(struct ov2710_info *info, u8 *status)
{
int err;
@@ -567,6 +640,17 @@ static long ov2710_ioctl(struct file *file,
return ov2710_set_coarse_time(info, (u32)arg);
case OV2710_IOCTL_SET_GAIN:
return ov2710_set_gain(info, (u16)arg);
+ case OV2710_IOCTL_SET_GROUP_HOLD:
+ {
+ struct ov2710_ae ae;
+ if (copy_from_user(&ae,
+ (const void __user *)arg,
+ sizeof(struct ov2710_ae))) {
+ pr_info("%s %d\n", __func__, __LINE__);
+ return -EFAULT;
+ }
+ return ov2710_set_group_hold(info, &ae);
+ }
case OV2710_IOCTL_GET_STATUS:
{
u8 status;
diff --git a/drivers/media/video/tegra/sh532u.c b/drivers/media/video/tegra/sh532u.c
index f41b44ce9530..4c7ef5aeaeab 100644
--- a/drivers/media/video/tegra/sh532u.c
+++ b/drivers/media/video/tegra/sh532u.c
@@ -532,7 +532,7 @@ static int sh532u_vreg_init(struct sh532u_info *info)
else
dev_info(&info->i2c_client->dev,
"%s no regulator found for %s. "
- "This board may not have an"
+ "This board may not have an "
"independent %s regulator.\n",
__func__, info->vreg[j].vreg_name,
info->vreg[j].vreg_name);
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index f89c3eedee36..a4931c756205 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -175,7 +175,6 @@ config MFD_TPS65910
bool "TPS65910 Power Management chip"
depends on I2C=y && GPIOLIB
select MFD_CORE
- select GPIO_TPS65910
select REGMAP_I2C
help
if you say yes here you get support for the TPS65910 series of
diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c
index 99ef944c621d..cdc1df7fa0e9 100644
--- a/drivers/mfd/rc5t583.c
+++ b/drivers/mfd/rc5t583.c
@@ -75,49 +75,12 @@ static struct deepsleep_control_data deepsleep_data[] = {
(RC5T583_EXT_PWRREQ1_CONTROL | RC5T583_EXT_PWRREQ2_CONTROL)
static struct mfd_cell rc5t583_subdevs[] = {
+ {.name = "rc5t583-gpio",},
{.name = "rc5t583-regulator",},
{.name = "rc5t583-rtc", },
{.name = "rc5t583-key", }
};
-int rc5t583_write(struct device *dev, uint8_t reg, uint8_t val)
-{
- struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
- return regmap_write(rc5t583->regmap, reg, val);
-}
-
-int rc5t583_read(struct device *dev, uint8_t reg, uint8_t *val)
-{
- struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
- unsigned int ival;
- int ret;
- ret = regmap_read(rc5t583->regmap, reg, &ival);
- if (!ret)
- *val = (uint8_t)ival;
- return ret;
-}
-
-int rc5t583_set_bits(struct device *dev, unsigned int reg,
- unsigned int bit_mask)
-{
- struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
- return regmap_update_bits(rc5t583->regmap, reg, bit_mask, bit_mask);
-}
-
-int rc5t583_clear_bits(struct device *dev, unsigned int reg,
- unsigned int bit_mask)
-{
- struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
- return regmap_update_bits(rc5t583->regmap, reg, bit_mask, 0);
-}
-
-int rc5t583_update(struct device *dev, unsigned int reg,
- unsigned int val, unsigned int mask)
-{
- struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
- return regmap_update_bits(rc5t583->regmap, reg, mask, val);
-}
-
static int __rc5t583_set_ext_pwrreq1_control(struct device *dev,
int id, int ext_pwr, int slots)
{
@@ -197,6 +160,7 @@ int rc5t583_ext_power_req_config(struct device *dev, int ds_id,
ds_id, ext_pwr_req);
return 0;
}
+EXPORT_SYMBOL(rc5t583_ext_power_req_config);
static int rc5t583_clear_ext_power_req(struct rc5t583 *rc5t583,
struct rc5t583_platform_data *pdata)
@@ -304,7 +268,7 @@ static int __devinit rc5t583_i2c_probe(struct i2c_client *i2c,
rc5t583->dev = &i2c->dev;
i2c_set_clientdata(i2c, rc5t583);
- rc5t583->regmap = regmap_init_i2c(i2c, &rc5t583_regmap_config);
+ rc5t583->regmap = devm_regmap_init_i2c(i2c, &rc5t583_regmap_config);
if (IS_ERR(rc5t583->regmap)) {
ret = PTR_ERR(rc5t583->regmap);
dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret);
@@ -313,7 +277,7 @@ static int __devinit rc5t583_i2c_probe(struct i2c_client *i2c,
ret = rc5t583_clear_ext_power_req(rc5t583, pdata);
if (ret < 0)
- goto err_irq_init;
+ return ret;
if (i2c->irq) {
ret = rc5t583_irq_init(rc5t583, i2c->irq, pdata->irq_base);
@@ -336,8 +300,6 @@ static int __devinit rc5t583_i2c_probe(struct i2c_client *i2c,
err_add_devs:
if (irq_init_success)
rc5t583_irq_exit(rc5t583);
-err_irq_init:
- regmap_exit(rc5t583->regmap);
return ret;
}
@@ -347,7 +309,6 @@ static int __devexit rc5t583_i2c_remove(struct i2c_client *i2c)
mfd_remove_devices(rc5t583->dev);
rc5t583_irq_exit(rc5t583);
- regmap_exit(rc5t583->regmap);
return 0;
}
diff --git a/drivers/mfd/tps65910-irq.c b/drivers/mfd/tps65910-irq.c
index c9ed5c00a621..0f1ff7fbdc74 100644
--- a/drivers/mfd/tps65910-irq.c
+++ b/drivers/mfd/tps65910-irq.c
@@ -41,28 +41,28 @@ static inline int irq_to_tps65910_irq(struct tps65910 *tps65910,
static irqreturn_t tps65910_irq(int irq, void *irq_data)
{
struct tps65910 *tps65910 = irq_data;
+ unsigned int reg;
u32 irq_sts;
u32 irq_mask;
- u8 reg;
int i;
- tps65910->read(tps65910, TPS65910_INT_STS, 1, &reg);
+ tps65910_reg_read(tps65910, TPS65910_INT_STS, &reg);
irq_sts = reg;
- tps65910->read(tps65910, TPS65910_INT_STS2, 1, &reg);
+ tps65910_reg_read(tps65910, TPS65910_INT_STS2, &reg);
irq_sts |= reg << 8;
switch (tps65910_chip_id(tps65910)) {
case TPS65911:
- tps65910->read(tps65910, TPS65910_INT_STS3, 1, &reg);
+ tps65910_reg_read(tps65910, TPS65910_INT_STS3, &reg);
irq_sts |= reg << 16;
}
- tps65910->read(tps65910, TPS65910_INT_MSK, 1, &reg);
+ tps65910_reg_read(tps65910, TPS65910_INT_MSK, &reg);
irq_mask = reg;
- tps65910->read(tps65910, TPS65910_INT_MSK2, 1, &reg);
+ tps65910_reg_read(tps65910, TPS65910_INT_MSK2, &reg);
irq_mask |= reg << 8;
switch (tps65910_chip_id(tps65910)) {
case TPS65911:
- tps65910->read(tps65910, TPS65910_INT_MSK3, 1, &reg);
+ tps65910_reg_read(tps65910, TPS65910_INT_MSK3, &reg);
irq_mask |= reg << 16;
}
@@ -82,13 +82,13 @@ static irqreturn_t tps65910_irq(int irq, void *irq_data)
/* Write the STS register back to clear IRQs we handled */
reg = irq_sts & 0xFF;
irq_sts >>= 8;
- tps65910->write(tps65910, TPS65910_INT_STS, 1, &reg);
+ tps65910_reg_write(tps65910, TPS65910_INT_STS, reg);
reg = irq_sts & 0xFF;
- tps65910->write(tps65910, TPS65910_INT_STS2, 1, &reg);
+ tps65910_reg_write(tps65910, TPS65910_INT_STS2, reg);
switch (tps65910_chip_id(tps65910)) {
case TPS65911:
reg = irq_sts >> 8;
- tps65910->write(tps65910, TPS65910_INT_STS3, 1, &reg);
+ tps65910_reg_write(tps65910, TPS65910_INT_STS3, reg);
}
return IRQ_HANDLED;
@@ -105,27 +105,27 @@ static void tps65910_irq_sync_unlock(struct irq_data *data)
{
struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data);
u32 reg_mask;
- u8 reg;
+ unsigned int reg;
- tps65910->read(tps65910, TPS65910_INT_MSK, 1, &reg);
+ tps65910_reg_read(tps65910, TPS65910_INT_MSK, &reg);
reg_mask = reg;
- tps65910->read(tps65910, TPS65910_INT_MSK2, 1, &reg);
+ tps65910_reg_read(tps65910, TPS65910_INT_MSK2, &reg);
reg_mask |= reg << 8;
switch (tps65910_chip_id(tps65910)) {
case TPS65911:
- tps65910->read(tps65910, TPS65910_INT_MSK3, 1, &reg);
+ tps65910_reg_read(tps65910, TPS65910_INT_MSK3, &reg);
reg_mask |= reg << 16;
}
if (tps65910->irq_mask != reg_mask) {
reg = tps65910->irq_mask & 0xFF;
- tps65910->write(tps65910, TPS65910_INT_MSK, 1, &reg);
+ tps65910_reg_write(tps65910, TPS65910_INT_MSK, reg);
reg = tps65910->irq_mask >> 8 & 0xFF;
- tps65910->write(tps65910, TPS65910_INT_MSK2, 1, &reg);
+ tps65910_reg_write(tps65910, TPS65910_INT_MSK2, reg);
switch (tps65910_chip_id(tps65910)) {
case TPS65911:
reg = tps65910->irq_mask >> 16;
- tps65910->write(tps65910, TPS65910_INT_MSK3, 1, &reg);
+ tps65910_reg_write(tps65910, TPS65910_INT_MSK3, reg);
}
}
mutex_unlock(&tps65910->irq_lock);
diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
index 1c4f53efee74..18b30cf45e5b 100644
--- a/drivers/mfd/tps65910.c
+++ b/drivers/mfd/tps65910.c
@@ -19,13 +19,16 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/i2c.h>
-#include <linux/gpio.h>
#include <linux/mfd/core.h>
#include <linux/regmap.h>
#include <linux/mfd/tps65910.h>
+#include <linux/of_device.h>
static struct mfd_cell tps65910s[] = {
{
+ .name = "tps65910-gpio",
+ },
+ {
.name = "tps65910-pmic",
},
{
@@ -37,30 +40,6 @@ static struct mfd_cell tps65910s[] = {
};
-static int tps65910_i2c_read(struct tps65910 *tps65910, u8 reg,
- int bytes, void *dest)
-{
- return regmap_bulk_read(tps65910->regmap, reg, dest, bytes);
-}
-
-static int tps65910_i2c_write(struct tps65910 *tps65910, u8 reg,
- int bytes, void *src)
-{
- return regmap_bulk_write(tps65910->regmap, reg, src, bytes);
-}
-
-int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask)
-{
- return regmap_update_bits(tps65910->regmap, reg, mask, mask);
-}
-EXPORT_SYMBOL_GPL(tps65910_set_bits);
-
-int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask)
-{
- return regmap_update_bits(tps65910->regmap, reg, mask, 0);
-}
-EXPORT_SYMBOL_GPL(tps65910_clear_bits);
-
static bool is_volatile_reg(struct device *dev, unsigned int reg)
{
struct tps65910 *tps65910 = dev_get_drvdata(dev);
@@ -81,84 +60,212 @@ static bool is_volatile_reg(struct device *dev, unsigned int reg)
return true;
}
-static const struct regmap_config rc5t583_regmap_config = {
+static const struct regmap_config tps65910_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.volatile_reg = is_volatile_reg,
- .max_register = TPS65910_MAX_REGISTER,
- .num_reg_defaults_raw = TPS65910_MAX_REGISTER,
+ .max_register = TPS65910_MAX_REGISTER - 1,
.cache_type = REGCACHE_RBTREE,
};
-static int tps65910_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int __devinit tps65910_sleepinit(struct tps65910 *tps65910,
+ struct tps65910_board *pmic_pdata)
+{
+ struct device *dev = NULL;
+ int ret = 0;
+
+ dev = tps65910->dev;
+
+ if (!pmic_pdata->en_dev_slp)
+ return 0;
+
+ /* enabling SLEEP device state */
+ ret = tps65910_reg_set_bits(tps65910, TPS65910_DEVCTRL,
+ DEVCTRL_DEV_SLP_MASK);
+ if (ret < 0) {
+ dev_err(dev, "set dev_slp failed: %d\n", ret);
+ goto err_sleep_init;
+ }
+
+ /* Return if there is no sleep keepon data. */
+ if (!pmic_pdata->slp_keepon)
+ return 0;
+
+ if (pmic_pdata->slp_keepon->therm_keepon) {
+ ret = tps65910_reg_set_bits(tps65910,
+ TPS65910_SLEEP_KEEP_RES_ON,
+ SLEEP_KEEP_RES_ON_THERM_KEEPON_MASK);
+ if (ret < 0) {
+ dev_err(dev, "set therm_keepon failed: %d\n", ret);
+ goto disable_dev_slp;
+ }
+ }
+
+ if (pmic_pdata->slp_keepon->clkout32k_keepon) {
+ ret = tps65910_reg_set_bits(tps65910,
+ TPS65910_SLEEP_KEEP_RES_ON,
+ SLEEP_KEEP_RES_ON_CLKOUT32K_KEEPON_MASK);
+ if (ret < 0) {
+ dev_err(dev, "set clkout32k_keepon failed: %d\n", ret);
+ goto disable_dev_slp;
+ }
+ }
+
+ if (pmic_pdata->slp_keepon->i2chs_keepon) {
+ ret = tps65910_reg_set_bits(tps65910,
+ TPS65910_SLEEP_KEEP_RES_ON,
+ SLEEP_KEEP_RES_ON_I2CHS_KEEPON_MASK);
+ if (ret < 0) {
+ dev_err(dev, "set i2chs_keepon failed: %d\n", ret);
+ goto disable_dev_slp;
+ }
+ }
+
+ return 0;
+
+disable_dev_slp:
+ tps65910_reg_clear_bits(tps65910, TPS65910_DEVCTRL,
+ DEVCTRL_DEV_SLP_MASK);
+
+err_sleep_init:
+ return ret;
+}
+
+#ifdef CONFIG_OF
+static struct of_device_id tps65910_of_match[] = {
+ { .compatible = "ti,tps65910", .data = (void *)TPS65910},
+ { .compatible = "ti,tps65911", .data = (void *)TPS65911},
+ { },
+};
+MODULE_DEVICE_TABLE(of, tps65910_of_match);
+
+static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
+ int *chip_id)
+{
+ struct device_node *np = client->dev.of_node;
+ struct tps65910_board *board_info;
+ unsigned int prop;
+ const struct of_device_id *match;
+ unsigned int prop_array[TPS6591X_MAX_NUM_GPIO];
+ int ret = 0;
+ int idx;
+
+ match = of_match_device(tps65910_of_match, &client->dev);
+ if (!match) {
+ dev_err(&client->dev, "Failed to find matching dt id\n");
+ return NULL;
+ }
+
+ *chip_id = (int)match->data;
+
+ board_info = devm_kzalloc(&client->dev, sizeof(*board_info),
+ GFP_KERNEL);
+ if (!board_info) {
+ dev_err(&client->dev, "Failed to allocate pdata\n");
+ return NULL;
+ }
+
+ ret = of_property_read_u32(np, "ti,vmbch-threshold", &prop);
+ if (!ret)
+ board_info->vmbch_threshold = prop;
+ else if (*chip_id == TPS65911)
+ dev_warn(&client->dev, "VMBCH-Threshold not specified");
+
+ ret = of_property_read_u32(np, "ti,vmbch2-threshold", &prop);
+ if (!ret)
+ board_info->vmbch2_threshold = prop;
+ else if (*chip_id == TPS65911)
+ dev_warn(&client->dev, "VMBCH2-Threshold not specified");
+
+ ret = of_property_read_u32_array(np, "ti,en-gpio-sleep",
+ prop_array, TPS6591X_MAX_NUM_GPIO);
+ if (!ret)
+ for (idx = 0; idx < ARRAY_SIZE(prop_array); idx++)
+ board_info->en_gpio_sleep[idx] = (prop_array[idx] != 0);
+ else if (ret != -EINVAL) {
+ dev_err(&client->dev,
+ "error reading property ti,en-gpio-sleep: %d\n.", ret);
+ return NULL;
+ }
+
+
+ board_info->irq = client->irq;
+ board_info->irq_base = -1;
+ board_info->gpio_base = -1;
+
+ return board_info;
+}
+#else
+static inline
+struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
+ int *chip_id)
+{
+ return NULL;
+}
+#endif
+
+static __devinit int tps65910_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct tps65910 *tps65910;
struct tps65910_board *pmic_plat_data;
struct tps65910_platform_data *init_data;
int ret = 0;
+ int chip_id = id->driver_data;
pmic_plat_data = dev_get_platdata(&i2c->dev);
+
+ if (!pmic_plat_data && i2c->dev.of_node)
+ pmic_plat_data = tps65910_parse_dt(i2c, &chip_id);
+
if (!pmic_plat_data)
return -EINVAL;
- init_data = kzalloc(sizeof(struct tps65910_platform_data), GFP_KERNEL);
+ init_data = devm_kzalloc(&i2c->dev, sizeof(*init_data), GFP_KERNEL);
if (init_data == NULL)
return -ENOMEM;
- tps65910 = kzalloc(sizeof(struct tps65910), GFP_KERNEL);
- if (tps65910 == NULL) {
- kfree(init_data);
+ tps65910 = devm_kzalloc(&i2c->dev, sizeof(*tps65910), GFP_KERNEL);
+ if (tps65910 == NULL)
return -ENOMEM;
- }
i2c_set_clientdata(i2c, tps65910);
tps65910->dev = &i2c->dev;
tps65910->i2c_client = i2c;
- tps65910->id = id->driver_data;
- tps65910->read = tps65910_i2c_read;
- tps65910->write = tps65910_i2c_write;
+ tps65910->id = chip_id;
mutex_init(&tps65910->io_mutex);
- tps65910->regmap = regmap_init_i2c(i2c, &rc5t583_regmap_config);
+ tps65910->regmap = devm_regmap_init_i2c(i2c, &tps65910_regmap_config);
if (IS_ERR(tps65910->regmap)) {
ret = PTR_ERR(tps65910->regmap);
dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret);
- goto regmap_err;
+ return ret;
}
ret = mfd_add_devices(tps65910->dev, -1,
tps65910s, ARRAY_SIZE(tps65910s),
NULL, 0);
- if (ret < 0)
- goto err;
+ if (ret < 0) {
+ dev_err(&i2c->dev, "mfd_add_devices failed: %d\n", ret);
+ return ret;
+ }
init_data->irq = pmic_plat_data->irq;
init_data->irq_base = pmic_plat_data->irq_base;
- tps65910_gpio_init(tps65910, pmic_plat_data->gpio_base);
-
tps65910_irq_init(tps65910, init_data->irq, init_data);
- kfree(init_data);
- return ret;
+ tps65910_sleepinit(tps65910, pmic_plat_data);
-err:
- regmap_exit(tps65910->regmap);
-regmap_err:
- kfree(tps65910);
- kfree(init_data);
return ret;
}
-static int tps65910_i2c_remove(struct i2c_client *i2c)
+static __devexit int tps65910_i2c_remove(struct i2c_client *i2c)
{
struct tps65910 *tps65910 = i2c_get_clientdata(i2c);
tps65910_irq_exit(tps65910);
mfd_remove_devices(tps65910->dev);
- regmap_exit(tps65910->regmap);
- kfree(tps65910);
return 0;
}
@@ -175,9 +282,10 @@ static struct i2c_driver tps65910_i2c_driver = {
.driver = {
.name = "tps65910",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(tps65910_of_match),
},
.probe = tps65910_i2c_probe,
- .remove = tps65910_i2c_remove,
+ .remove = __devexit_p(tps65910_i2c_remove),
.id_table = tps65910_i2c_id,
};
diff --git a/drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.c b/drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.c
index ed44cdefe43b..8a60be2298c8 100644
--- a/drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.c
+++ b/drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.c
@@ -1082,7 +1082,7 @@ woal_cfg80211_assoc(moal_private * priv, void *sme)
goto done;
}
- if (channel) {
+ if (mode == MLAN_BSS_MODE_IBSS && channel) {
/* Get the secondary channel offset */
req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg));
if (req == NULL) {
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 67093e3f1cd7..28c58a1c19b1 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -257,6 +257,16 @@ config REGULATOR_AB3100
AB3100 analog baseband dealing with power regulators
for the system.
+config REGULATOR_RC5T583
+ tristate "RICOH RC5T583 Power regulators"
+ depends on MFD_RC5T583
+ help
+ Select this option to enable the power regulator of RICOH
+ PMIC RC5T583.
+ This driver supports the control of different power rails of device
+ through regulator interface. The device supports multiple DCDC/LDO
+ outputs which can be controlled by i2c communication.
+
config REGULATOR_TPS6105X
tristate "TI TPS6105X Power regulators"
depends on TPS6105X
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 7642d39fb8d3..a25ff34afcbc 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
+obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o
diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c
new file mode 100644
index 000000000000..81a03b281fa0
--- /dev/null
+++ b/drivers/regulator/rc5t583-regulator.c
@@ -0,0 +1,363 @@
+/*
+ * Regulator driver for RICOH RC5T583 power management chip.
+ *
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved.
+ * Author: Laxman dewangan <ldewangan@nvidia.com>
+ *
+ * based on code
+ * Copyright (C) 2011 RICOH COMPANY,LTD
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/gpio.h>
+#include <linux/mfd/rc5t583.h>
+
+struct rc5t583_regulator_info {
+ int deepsleep_id;
+
+ /* Regulator register address.*/
+ uint8_t reg_en_reg;
+ uint8_t en_bit;
+ uint8_t reg_disc_reg;
+ uint8_t disc_bit;
+ uint8_t vout_reg;
+ uint8_t vout_mask;
+ uint8_t deepsleep_reg;
+
+ /* Chip constraints on regulator behavior */
+ int min_uV;
+ int max_uV;
+ int step_uV;
+
+ /* Regulator specific turn-on delay and voltage settling time*/
+ int enable_uv_per_us;
+ int change_uv_per_us;
+
+ /* Used by regulator core */
+ struct regulator_desc desc;
+};
+
+struct rc5t583_regulator {
+ struct rc5t583_regulator_info *reg_info;
+
+ /* Devices */
+ struct device *dev;
+ struct rc5t583 *mfd;
+ struct regulator_dev *rdev;
+};
+
+static int rc5t583_reg_is_enabled(struct regulator_dev *rdev)
+{
+ struct rc5t583_regulator *reg = rdev_get_drvdata(rdev);
+ struct rc5t583_regulator_info *ri = reg->reg_info;
+ uint8_t control;
+ int ret;
+
+ ret = rc5t583_read(reg->mfd->dev, ri->reg_en_reg, &control);
+ if (ret < 0) {
+ dev_err(&rdev->dev,
+ "Error in reading the control register 0x%02x\n",
+ ri->reg_en_reg);
+ return ret;
+ }
+ return !!(control & BIT(ri->en_bit));
+}
+
+static int rc5t583_reg_enable(struct regulator_dev *rdev)
+{
+ struct rc5t583_regulator *reg = rdev_get_drvdata(rdev);
+ struct rc5t583_regulator_info *ri = reg->reg_info;
+ int ret;
+
+ ret = rc5t583_set_bits(reg->mfd->dev, ri->reg_en_reg,
+ (1 << ri->en_bit));
+ if (ret < 0) {
+ dev_err(&rdev->dev,
+ "Error in setting bit of STATE register 0x%02x\n",
+ ri->reg_en_reg);
+ return ret;
+ }
+ return ret;
+}
+
+static int rc5t583_reg_disable(struct regulator_dev *rdev)
+{
+ struct rc5t583_regulator *reg = rdev_get_drvdata(rdev);
+ struct rc5t583_regulator_info *ri = reg->reg_info;
+ int ret;
+
+ ret = rc5t583_clear_bits(reg->mfd->dev, ri->reg_en_reg,
+ (1 << ri->en_bit));
+ if (ret < 0)
+ dev_err(&rdev->dev,
+ "Error in clearing bit of STATE register 0x%02x\n",
+ ri->reg_en_reg);
+
+ return ret;
+}
+
+static int rc5t583_list_voltage(struct regulator_dev *rdev, unsigned selector)
+{
+ struct rc5t583_regulator *reg = rdev_get_drvdata(rdev);
+ struct rc5t583_regulator_info *ri = reg->reg_info;
+ return ri->min_uV + (ri->step_uV * selector);
+}
+
+static int rc5t583_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned int selector)
+{
+ struct rc5t583_regulator *reg = rdev_get_drvdata(rdev);
+ struct rc5t583_regulator_info *ri = reg->reg_info;
+ int ret;
+ if (selector >= rdev->desc->n_voltages) {
+ dev_err(&rdev->dev, "Invalid selector 0x%02x\n", selector);
+ return -EINVAL;
+ }
+
+ ret = rc5t583_update(reg->mfd->dev, ri->vout_reg,
+ selector, ri->vout_mask);
+ if (ret < 0)
+ dev_err(&rdev->dev,
+ "Error in update voltage register 0x%02x\n", ri->vout_reg);
+ return ret;
+}
+
+static int rc5t583_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct rc5t583_regulator *reg = rdev_get_drvdata(rdev);
+ struct rc5t583_regulator_info *ri = reg->reg_info;
+ uint8_t vsel;
+ int ret;
+ ret = rc5t583_read(reg->mfd->dev, ri->vout_reg, &vsel);
+ if (ret < 0) {
+ dev_err(&rdev->dev,
+ "Error in reading voltage register 0x%02x\n", ri->vout_reg);
+ return ret;
+ }
+ return vsel & ri->vout_mask;
+}
+
+static int rc5t583_regulator_enable_time(struct regulator_dev *rdev)
+{
+ struct rc5t583_regulator *reg = rdev_get_drvdata(rdev);
+ int vsel = rc5t583_get_voltage_sel(rdev);
+ int curr_uV = rc5t583_list_voltage(rdev, vsel);
+ return DIV_ROUND_UP(curr_uV, reg->reg_info->enable_uv_per_us);
+}
+
+static int rc5t583_set_voltage_time_sel(struct regulator_dev *rdev,
+ unsigned int old_selector, unsigned int new_selector)
+{
+ struct rc5t583_regulator *reg = rdev_get_drvdata(rdev);
+ int old_uV, new_uV;
+ old_uV = rc5t583_list_voltage(rdev, old_selector);
+
+ if (old_uV < 0)
+ return old_uV;
+
+ new_uV = rc5t583_list_voltage(rdev, new_selector);
+ if (new_uV < 0)
+ return new_uV;
+
+ return DIV_ROUND_UP(abs(old_uV - new_uV),
+ reg->reg_info->change_uv_per_us);
+}
+
+
+static struct regulator_ops rc5t583_ops = {
+ .is_enabled = rc5t583_reg_is_enabled,
+ .enable = rc5t583_reg_enable,
+ .disable = rc5t583_reg_disable,
+ .enable_time = rc5t583_regulator_enable_time,
+ .get_voltage_sel = rc5t583_get_voltage_sel,
+ .set_voltage_sel = rc5t583_set_voltage_sel,
+ .list_voltage = rc5t583_list_voltage,
+ .set_voltage_time_sel = rc5t583_set_voltage_time_sel,
+};
+
+#define RC5T583_REG(_id, _en_reg, _en_bit, _disc_reg, _disc_bit, _vout_reg, \
+ _vout_mask, _ds_reg, _min_mv, _max_mv, _step_uV, _enable_mv) \
+{ \
+ .reg_en_reg = RC5T583_REG_##_en_reg, \
+ .en_bit = _en_bit, \
+ .reg_disc_reg = RC5T583_REG_##_disc_reg, \
+ .disc_bit = _disc_bit, \
+ .vout_reg = RC5T583_REG_##_vout_reg, \
+ .vout_mask = _vout_mask, \
+ .deepsleep_reg = RC5T583_REG_##_ds_reg, \
+ .min_uV = _min_mv * 1000, \
+ .max_uV = _max_mv * 1000, \
+ .step_uV = _step_uV, \
+ .enable_uv_per_us = _enable_mv * 1000, \
+ .change_uv_per_us = 40 * 1000, \
+ .deepsleep_id = RC5T583_DS_##_id, \
+ .desc = { \
+ .name = "rc5t583-regulator-"#_id, \
+ .id = RC5T583_REGULATOR_##_id, \
+ .n_voltages = (_max_mv - _min_mv) * 1000 / _step_uV + 1, \
+ .ops = &rc5t583_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ }, \
+}
+
+static struct rc5t583_regulator_info rc5t583_reg_info[RC5T583_REGULATOR_MAX] = {
+ RC5T583_REG(DC0, DC0CTL, 0, DC0CTL, 1, DC0DAC, 0x7F, DC0DAC_DS,
+ 700, 1500, 12500, 4),
+ RC5T583_REG(DC1, DC1CTL, 0, DC1CTL, 1, DC1DAC, 0x7F, DC1DAC_DS,
+ 700, 1500, 12500, 14),
+ RC5T583_REG(DC2, DC2CTL, 0, DC2CTL, 1, DC2DAC, 0x7F, DC2DAC_DS,
+ 900, 2400, 12500, 14),
+ RC5T583_REG(DC3, DC3CTL, 0, DC3CTL, 1, DC3DAC, 0x7F, DC3DAC_DS,
+ 900, 2400, 12500, 14),
+ RC5T583_REG(LDO0, LDOEN2, 0, LDODIS2, 0, LDO0DAC, 0x7F, LDO0DAC_DS,
+ 900, 3400, 25000, 160),
+ RC5T583_REG(LDO1, LDOEN2, 1, LDODIS2, 1, LDO1DAC, 0x7F, LDO1DAC_DS,
+ 900, 3400, 25000, 160),
+ RC5T583_REG(LDO2, LDOEN2, 2, LDODIS2, 2, LDO2DAC, 0x7F, LDO2DAC_DS,
+ 900, 3400, 25000, 160),
+ RC5T583_REG(LDO3, LDOEN2, 3, LDODIS2, 3, LDO3DAC, 0x7F, LDO3DAC_DS,
+ 900, 3400, 25000, 160),
+ RC5T583_REG(LDO4, LDOEN2, 4, LDODIS2, 4, LDO4DAC, 0x3F, LDO4DAC_DS,
+ 750, 1500, 12500, 133),
+ RC5T583_REG(LDO5, LDOEN2, 5, LDODIS2, 5, LDO5DAC, 0x7F, LDO5DAC_DS,
+ 900, 3400, 25000, 267),
+ RC5T583_REG(LDO6, LDOEN2, 6, LDODIS2, 6, LDO6DAC, 0x7F, LDO6DAC_DS,
+ 900, 3400, 25000, 133),
+ RC5T583_REG(LDO7, LDOEN2, 7, LDODIS2, 7, LDO7DAC, 0x7F, LDO7DAC_DS,
+ 900, 3400, 25000, 233),
+ RC5T583_REG(LDO8, LDOEN1, 0, LDODIS1, 0, LDO8DAC, 0x7F, LDO8DAC_DS,
+ 900, 3400, 25000, 233),
+ RC5T583_REG(LDO9, LDOEN1, 1, LDODIS1, 1, LDO9DAC, 0x7F, LDO9DAC_DS,
+ 900, 3400, 25000, 133),
+};
+
+static int __devinit rc5t583_regulator_probe(struct platform_device *pdev)
+{
+ struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
+ struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev);
+ struct regulator_init_data *reg_data;
+ struct rc5t583_regulator *reg = NULL;
+ struct rc5t583_regulator *regs;
+ struct regulator_dev *rdev;
+ struct rc5t583_regulator_info *ri;
+ int ret;
+ int id;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "No platform data, exiting...\n");
+ return -ENODEV;
+ }
+
+ regs = devm_kzalloc(&pdev->dev, RC5T583_REGULATOR_MAX *
+ sizeof(struct rc5t583_regulator), GFP_KERNEL);
+ if (!regs) {
+ dev_err(&pdev->dev, "Memory allocation failed exiting..\n");
+ return -ENOMEM;
+ }
+
+
+ for (id = 0; id < RC5T583_REGULATOR_MAX; ++id) {
+ reg_data = pdata->reg_init_data[id];
+
+ /* No need to register if there is no regulator data */
+ if (!reg_data)
+ continue;
+
+ reg = &regs[id];
+ ri = &rc5t583_reg_info[id];
+ reg->reg_info = ri;
+ reg->mfd = rc5t583;
+ reg->dev = &pdev->dev;
+
+ if (ri->deepsleep_id == RC5T583_DS_NONE)
+ goto skip_ext_pwr_config;
+
+ ret = rc5t583_ext_power_req_config(rc5t583->dev,
+ ri->deepsleep_id,
+ pdata->regulator_ext_pwr_control[id],
+ pdata->regulator_deepsleep_slot[id]);
+ /*
+ * Configuring external control is not a major issue,
+ * just give warning.
+ */
+ if (ret < 0)
+ dev_warn(&pdev->dev,
+ "Failed to configure ext control %d\n", id);
+
+skip_ext_pwr_config:
+ rdev = regulator_register(&ri->desc, &pdev->dev, reg_data, reg);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "Failed to register regulator %s\n",
+ ri->desc.name);
+ ret = PTR_ERR(rdev);
+ goto clean_exit;
+ }
+ reg->rdev = rdev;
+ }
+ platform_set_drvdata(pdev, regs);
+ return 0;
+
+clean_exit:
+ while (--id >= 0)
+ regulator_unregister(regs[id].rdev);
+
+ return ret;
+}
+
+static int __devexit rc5t583_regulator_remove(struct platform_device *pdev)
+{
+ struct rc5t583_regulator *regs = platform_get_drvdata(pdev);
+ int id;
+
+ for (id = 0; id < RC5T583_REGULATOR_MAX; ++id)
+ regulator_unregister(regs[id].rdev);
+ return 0;
+}
+
+static struct platform_driver rc5t583_regulator_driver = {
+ .driver = {
+ .name = "rc5t583-regulator",
+ .owner = THIS_MODULE,
+ },
+ .probe = rc5t583_regulator_probe,
+ .remove = __devexit_p(rc5t583_regulator_remove),
+};
+
+static int __init rc5t583_regulator_init(void)
+{
+ return platform_driver_register(&rc5t583_regulator_driver);
+}
+subsys_initcall(rc5t583_regulator_init);
+
+static void __exit rc5t583_regulator_exit(void)
+{
+ platform_driver_unregister(&rc5t583_regulator_driver);
+}
+module_exit(rc5t583_regulator_exit);
+
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_DESCRIPTION("RC5T583 regulator driver");
+MODULE_ALIAS("platform:rc5t583-regulator");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c
index 7eaf08275376..7db148202436 100644
--- a/drivers/regulator/tps62360-regulator.c
+++ b/drivers/regulator/tps62360-regulator.c
@@ -1,7 +1,7 @@
/*
* tps62360.c -- TI tps62360
*
- * Driver for processor core supply tps62360 and tps62361B
+ * Driver for processor core supply tps62360, tps62361B, tps62362 and tps62363.
*
* Copyright (c) 2012, NVIDIA Corporation.
*
@@ -46,20 +46,20 @@
#define REG_RAMPCTRL 6
#define REG_CHIPID 8
-enum chips {TPS62360, TPS62361};
+#define FORCE_PWM_ENABLE BIT(7)
-#define TPS62360_BASE_VOLTAGE 770
+enum chips {TPS62360, TPS62361, TPS62362, TPS62363};
+
+#define TPS62360_BASE_VOLTAGE 770000
#define TPS62360_N_VOLTAGES 64
-#define TPS62361_BASE_VOLTAGE 500
+#define TPS62361_BASE_VOLTAGE 500000
#define TPS62361_N_VOLTAGES 128
/* tps 62360 chip information */
struct tps62360_chip {
- const char *name;
struct device *dev;
struct regulator_desc desc;
- struct i2c_client *client;
struct regulator_dev *rdev;
struct regmap *regmap;
int chip_id;
@@ -68,12 +68,12 @@ struct tps62360_chip {
int voltage_base;
u8 voltage_reg_mask;
bool en_internal_pulldn;
- bool en_force_pwm;
bool en_discharge;
bool valid_gpios;
int lru_index[4];
int curr_vset_vsel[4];
int curr_vset_id;
+ int change_uv_per_us;
};
/*
@@ -99,6 +99,7 @@ static bool find_voltage_set_register(struct tps62360_chip *tps,
bool found = false;
int new_vset_reg = tps->lru_index[3];
int found_index = 3;
+
for (i = 0; i < 4; ++i) {
if (tps->curr_vset_vsel[tps->lru_index[i]] == req_vsel) {
new_vset_reg = tps->lru_index[i];
@@ -117,7 +118,7 @@ update_lru_index:
return found;
}
-static int tps62360_dcdc_get_voltage(struct regulator_dev *dev)
+static int tps62360_dcdc_get_voltage_sel(struct regulator_dev *dev)
{
struct tps62360_chip *tps = rdev_get_drvdata(dev);
int vsel;
@@ -126,12 +127,12 @@ static int tps62360_dcdc_get_voltage(struct regulator_dev *dev)
ret = regmap_read(tps->regmap, REG_VSET0 + tps->curr_vset_id, &data);
if (ret < 0) {
- dev_err(tps->dev, "%s: Error in reading register %d\n",
- __func__, REG_VSET0 + tps->curr_vset_id);
+ dev_err(tps->dev, "%s(): register %d read failed with err %d\n",
+ __func__, REG_VSET0 + tps->curr_vset_id, ret);
return ret;
}
vsel = (int)data & tps->voltage_reg_mask;
- return (tps->voltage_base + vsel * 10) * 1000;
+ return vsel;
}
static int tps62360_dcdc_set_voltage(struct regulator_dev *dev,
@@ -143,17 +144,13 @@ static int tps62360_dcdc_set_voltage(struct regulator_dev *dev,
bool found = false;
int new_vset_id = tps->curr_vset_id;
- if (max_uV < min_uV)
- return -EINVAL;
-
- if (min_uV >
- ((tps->voltage_base + (tps->desc.n_voltages - 1) * 10) * 1000))
+ if ((max_uV < min_uV) || (max_uV < tps->voltage_base))
return -EINVAL;
- if (max_uV < tps->voltage_base * 1000)
+ if (min_uV > (tps->voltage_base + (tps->desc.n_voltages - 1) * 10000))
return -EINVAL;
- vsel = DIV_ROUND_UP(min_uV - (tps->voltage_base * 1000), 10000);
+ vsel = DIV_ROUND_UP(min_uV - tps->voltage_base, 10000);
if (selector)
*selector = (vsel & tps->voltage_reg_mask);
@@ -168,8 +165,9 @@ static int tps62360_dcdc_set_voltage(struct regulator_dev *dev,
ret = regmap_update_bits(tps->regmap, REG_VSET0 + new_vset_id,
tps->voltage_reg_mask, vsel);
if (ret < 0) {
- dev_err(tps->dev, "%s: Error in updating register %d\n",
- __func__, REG_VSET0 + new_vset_id);
+ dev_err(tps->dev,
+ "%s(): register %d update failed with err %d\n",
+ __func__, REG_VSET0 + new_vset_id, ret);
return ret;
}
tps->curr_vset_id = new_vset_id;
@@ -178,8 +176,7 @@ static int tps62360_dcdc_set_voltage(struct regulator_dev *dev,
/* Select proper VSET register vio gpios */
if (tps->valid_gpios) {
- gpio_set_value_cansleep(tps->vsel0_gpio,
- new_vset_id & 0x1);
+ gpio_set_value_cansleep(tps->vsel0_gpio, new_vset_id & 0x1);
gpio_set_value_cansleep(tps->vsel1_gpio,
(new_vset_id >> 1) & 0x1);
}
@@ -191,82 +188,146 @@ static int tps62360_dcdc_list_voltage(struct regulator_dev *dev,
{
struct tps62360_chip *tps = rdev_get_drvdata(dev);
- if ((selector < 0) || (selector >= tps->desc.n_voltages))
+ if (selector >= tps->desc.n_voltages)
return -EINVAL;
- return (tps->voltage_base + selector * 10) * 1000;
+
+ return tps->voltage_base + selector * 10000;
}
-static struct regulator_ops tps62360_dcdc_ops = {
- .get_voltage = tps62360_dcdc_get_voltage,
- .set_voltage = tps62360_dcdc_set_voltage,
- .list_voltage = tps62360_dcdc_list_voltage,
-};
+static int tps62360_set_voltage_time_sel(struct regulator_dev *rdev,
+ unsigned int old_selector, unsigned int new_selector)
+{
+ struct tps62360_chip *tps = rdev_get_drvdata(rdev);
+ int old_uV, new_uV;
-static int tps62360_init_force_pwm(struct tps62360_chip *tps,
- struct tps62360_regulator_platform_data *pdata,
- int vset_id)
+ old_uV = tps62360_dcdc_list_voltage(rdev, old_selector);
+ if (old_uV < 0)
+ return old_uV;
+
+ new_uV = tps62360_dcdc_list_voltage(rdev, new_selector);
+ if (new_uV < 0)
+ return new_uV;
+
+ return DIV_ROUND_UP(abs(old_uV - new_uV), tps->change_uv_per_us);
+}
+
+static int tps62360_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
+ struct tps62360_chip *tps = rdev_get_drvdata(rdev);
+ int i;
+ int val;
+ int ret;
+
+ /* Enable force PWM mode in FAST mode only. */
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ val = FORCE_PWM_ENABLE;
+ break;
+
+ case REGULATOR_MODE_NORMAL:
+ val = 0;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if (!tps->valid_gpios) {
+ ret = regmap_update_bits(tps->regmap,
+ REG_VSET0 + tps->curr_vset_id, FORCE_PWM_ENABLE, val);
+ if (ret < 0)
+ dev_err(tps->dev,
+ "%s(): register %d update failed with err %d\n",
+ __func__, REG_VSET0 + tps->curr_vset_id, ret);
+ return ret;
+ }
+
+ /* If gpios are valid then all register set need to be control */
+ for (i = 0; i < 4; ++i) {
+ ret = regmap_update_bits(tps->regmap,
+ REG_VSET0 + i, FORCE_PWM_ENABLE, val);
+ if (ret < 0) {
+ dev_err(tps->dev,
+ "%s(): register %d update failed with err %d\n",
+ __func__, REG_VSET0 + i, ret);
+ return ret;
+ }
+ }
+ return ret;
+}
+
+static unsigned int tps62360_get_mode(struct regulator_dev *rdev)
+{
+ struct tps62360_chip *tps = rdev_get_drvdata(rdev);
unsigned int data;
int ret;
- ret = regmap_read(tps->regmap, REG_VSET0 + vset_id, &data);
+
+ ret = regmap_read(tps->regmap, REG_VSET0 + tps->curr_vset_id, &data);
if (ret < 0) {
- dev_err(tps->dev, "%s() fails in writing reg %d\n",
- __func__, REG_VSET0 + vset_id);
+ dev_err(tps->dev, "%s(): register %d read failed with err %d\n",
+ __func__, REG_VSET0 + tps->curr_vset_id, ret);
return ret;
}
- tps->curr_vset_vsel[vset_id] = data & tps->voltage_reg_mask;
- if (pdata->en_force_pwm)
- data |= BIT(7);
- else
- data &= ~BIT(7);
- ret = regmap_write(tps->regmap, REG_VSET0 + vset_id, data);
- if (ret < 0)
- dev_err(tps->dev, "%s() fails in writing reg %d\n",
- __func__, REG_VSET0 + vset_id);
- return ret;
+ return (data & FORCE_PWM_ENABLE) ?
+ REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
}
-static int tps62360_init_dcdc(struct tps62360_chip *tps,
+static struct regulator_ops tps62360_dcdc_ops = {
+ .get_voltage_sel = tps62360_dcdc_get_voltage_sel,
+ .set_voltage = tps62360_dcdc_set_voltage,
+ .list_voltage = tps62360_dcdc_list_voltage,
+ .set_voltage_time_sel = tps62360_set_voltage_time_sel,
+ .set_mode = tps62360_set_mode,
+ .get_mode = tps62360_get_mode,
+};
+
+static int __devinit tps62360_init_dcdc(struct tps62360_chip *tps,
struct tps62360_regulator_platform_data *pdata)
{
int ret;
- int i;
+ unsigned int ramp_ctrl;
- /* Initailize internal pull up/down control */
+ /* Initialize internal pull up/down control */
if (tps->en_internal_pulldn)
ret = regmap_write(tps->regmap, REG_CONTROL, 0xE0);
else
ret = regmap_write(tps->regmap, REG_CONTROL, 0x0);
if (ret < 0) {
- dev_err(tps->dev, "%s() fails in writing reg %d\n",
- __func__, REG_CONTROL);
+ dev_err(tps->dev,
+ "%s(): register %d write failed with err %d\n",
+ __func__, REG_CONTROL, ret);
return ret;
}
- /* Initailize force PWM mode */
- if (tps->valid_gpios) {
- for (i = 0; i < 4; ++i) {
- ret = tps62360_init_force_pwm(tps, pdata, i);
- if (ret < 0)
- return ret;
- }
- } else {
- ret = tps62360_init_force_pwm(tps, pdata, tps->curr_vset_id);
- if (ret < 0)
- return ret;
- }
-
/* Reset output discharge path to reduce power consumption */
ret = regmap_update_bits(tps->regmap, REG_RAMPCTRL, BIT(2), 0);
- if (ret < 0)
- dev_err(tps->dev, "%s() fails in updating reg %d\n",
- __func__, REG_RAMPCTRL);
+ if (ret < 0) {
+ dev_err(tps->dev,
+ "%s(): register %d update failed with err %d\n",
+ __func__, REG_RAMPCTRL, ret);
+ return ret;
+ }
+
+ /* Get ramp value from ramp control register */
+ ret = regmap_read(tps->regmap, REG_RAMPCTRL, &ramp_ctrl);
+ if (ret < 0) {
+ dev_err(tps->dev,
+ "%s(): register %d read failed with err %d\n",
+ __func__, REG_RAMPCTRL, ret);
+ return ret;
+ }
+ ramp_ctrl = (ramp_ctrl >> 4) & 0x7;
+
+ /* ramp mV/us = 32/(2^ramp_ctrl) */
+ tps->change_uv_per_us = DIV_ROUND_UP(32000, BIT(ramp_ctrl));
return ret;
}
static const struct regmap_config tps62360_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = REG_CHIPID,
+ .cache_type = REGCACHE_RBTREE,
};
static int __devinit tps62360_probe(struct i2c_client *client,
@@ -280,42 +341,52 @@ static int __devinit tps62360_probe(struct i2c_client *client,
pdata = client->dev.platform_data;
if (!pdata) {
- dev_err(&client->dev, "%s() Err: Platform data not found\n",
+ dev_err(&client->dev, "%s(): Platform data not found\n",
__func__);
return -EIO;
}
tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
if (!tps) {
- dev_err(&client->dev, "%s() Err: Memory allocation fails\n",
+ dev_err(&client->dev, "%s(): Memory allocation failed\n",
__func__);
return -ENOMEM;
}
- tps->en_force_pwm = pdata->en_force_pwm;
tps->en_discharge = pdata->en_discharge;
tps->en_internal_pulldn = pdata->en_internal_pulldn;
tps->vsel0_gpio = pdata->vsel0_gpio;
tps->vsel1_gpio = pdata->vsel1_gpio;
- tps->client = client;
tps->dev = &client->dev;
- tps->name = id->name;
- tps->voltage_base = (id->driver_data == TPS62360) ?
- TPS62360_BASE_VOLTAGE : TPS62361_BASE_VOLTAGE;
- tps->voltage_reg_mask = (id->driver_data == TPS62360) ? 0x3F : 0x7F;
+
+ switch (id->driver_data) {
+ case TPS62360:
+ case TPS62362:
+ tps->voltage_base = TPS62360_BASE_VOLTAGE;
+ tps->voltage_reg_mask = 0x3F;
+ tps->desc.n_voltages = TPS62360_N_VOLTAGES;
+ break;
+ case TPS62361:
+ case TPS62363:
+ tps->voltage_base = TPS62361_BASE_VOLTAGE;
+ tps->voltage_reg_mask = 0x7F;
+ tps->desc.n_voltages = TPS62361_N_VOLTAGES;
+ break;
+ default:
+ return -ENODEV;
+ }
tps->desc.name = id->name;
tps->desc.id = 0;
- tps->desc.n_voltages = (id->driver_data == TPS62360) ?
- TPS62360_N_VOLTAGES : TPS62361_N_VOLTAGES;
tps->desc.ops = &tps62360_dcdc_ops;
tps->desc.type = REGULATOR_VOLTAGE;
tps->desc.owner = THIS_MODULE;
- tps->regmap = regmap_init_i2c(client, &tps62360_regmap_config);
+ tps->regmap = devm_regmap_init_i2c(client, &tps62360_regmap_config);
if (IS_ERR(tps->regmap)) {
ret = PTR_ERR(tps->regmap);
- dev_err(&client->dev, "%s() Err: Failed to allocate register"
- "map: %d\n", __func__, ret);
+ dev_err(&client->dev,
+ "%s(): regmap allocation failed with err %d\n",
+ __func__, ret);
return ret;
}
i2c_set_clientdata(client, tps);
@@ -326,35 +397,26 @@ static int __devinit tps62360_probe(struct i2c_client *client,
tps->valid_gpios = false;
if (gpio_is_valid(tps->vsel0_gpio) && gpio_is_valid(tps->vsel1_gpio)) {
- ret = gpio_request(tps->vsel0_gpio, "tps62360-vsel0");
+ int gpio_flags;
+ gpio_flags = (pdata->vsel0_def_state) ?
+ GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+ ret = gpio_request_one(tps->vsel0_gpio,
+ gpio_flags, "tps62360-vsel0");
if (ret) {
dev_err(&client->dev,
- "Err: Could not obtain vsel0 GPIO %d: %d\n",
- tps->vsel0_gpio, ret);
- goto err_gpio0;
- }
- ret = gpio_direction_output(tps->vsel0_gpio,
- pdata->vsel0_def_state);
- if (ret) {
- dev_err(&client->dev, "Err: Could not set direction of"
- "vsel0 GPIO %d: %d\n", tps->vsel0_gpio, ret);
- gpio_free(tps->vsel0_gpio);
+ "%s(): Could not obtain vsel0 GPIO %d: %d\n",
+ __func__, tps->vsel0_gpio, ret);
goto err_gpio0;
}
- ret = gpio_request(tps->vsel1_gpio, "tps62360-vsel1");
+ gpio_flags = (pdata->vsel1_def_state) ?
+ GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+ ret = gpio_request_one(tps->vsel1_gpio,
+ gpio_flags, "tps62360-vsel1");
if (ret) {
dev_err(&client->dev,
- "Err: Could not obtain vsel1 GPIO %d: %d\n",
- tps->vsel1_gpio, ret);
- goto err_gpio1;
- }
- ret = gpio_direction_output(tps->vsel1_gpio,
- pdata->vsel1_def_state);
- if (ret) {
- dev_err(&client->dev, "Err: Could not set direction of"
- "vsel1 GPIO %d: %d\n", tps->vsel1_gpio, ret);
- gpio_free(tps->vsel1_gpio);
+ "%s(): Could not obtain vsel1 GPIO %d: %d\n",
+ __func__, tps->vsel1_gpio, ret);
goto err_gpio1;
}
tps->valid_gpios = true;
@@ -371,7 +433,7 @@ static int __devinit tps62360_probe(struct i2c_client *client,
ret = tps62360_init_dcdc(tps, pdata);
if (ret < 0) {
- dev_err(tps->dev, "%s() Err: Init fails with = %d\n",
+ dev_err(tps->dev, "%s(): Init failed with err = %d\n",
__func__, ret);
goto err_init;
}
@@ -380,8 +442,9 @@ static int __devinit tps62360_probe(struct i2c_client *client,
rdev = regulator_register(&tps->desc, &client->dev,
&pdata->reg_init_data, tps);
if (IS_ERR(rdev)) {
- dev_err(tps->dev, "%s() Err: Failed to register %s\n",
- __func__, id->name);
+ dev_err(tps->dev,
+ "%s(): regulator register failed with err %s\n",
+ __func__, id->name);
ret = PTR_ERR(rdev);
goto err_init;
}
@@ -396,7 +459,6 @@ err_gpio1:
if (gpio_is_valid(tps->vsel0_gpio))
gpio_free(tps->vsel0_gpio);
err_gpio0:
- regmap_exit(tps->regmap);
return ret;
}
@@ -417,7 +479,6 @@ static int __devexit tps62360_remove(struct i2c_client *client)
gpio_free(tps->vsel0_gpio);
regulator_unregister(tps->rdev);
- regmap_exit(tps->regmap);
return 0;
}
@@ -432,13 +493,16 @@ static void tps62360_shutdown(struct i2c_client *client)
/* Configure the output discharge path */
st = regmap_update_bits(tps->regmap, REG_RAMPCTRL, BIT(2), BIT(2));
if (st < 0)
- dev_err(tps->dev, "%s() fails in updating reg %d\n",
- __func__, REG_RAMPCTRL);
+ dev_err(tps->dev,
+ "%s(): register %d update failed with err %d\n",
+ __func__, REG_RAMPCTRL, st);
}
static const struct i2c_device_id tps62360_id[] = {
{.name = "tps62360", .driver_data = TPS62360},
{.name = "tps62361", .driver_data = TPS62361},
+ {.name = "tps62362", .driver_data = TPS62362},
+ {.name = "tps62363", .driver_data = TPS62363},
{},
};
@@ -468,5 +532,5 @@ static void __exit tps62360_cleanup(void)
module_exit(tps62360_cleanup);
MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
-MODULE_DESCRIPTION("TPS62360 voltage regulator driver");
+MODULE_DESCRIPTION("TPS6236x voltage regulator driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c
index fe2f1a8412b7..a2fef3880065 100644
--- a/drivers/regulator/tps65910-regulator.c
+++ b/drivers/regulator/tps65910-regulator.c
@@ -331,21 +331,16 @@ struct tps65910_reg {
static inline int tps65910_read(struct tps65910_reg *pmic, u8 reg)
{
- u8 val;
+ unsigned int val;
int err;
- err = pmic->mfd->read(pmic->mfd, reg, 1, &val);
+ err = tps65910_reg_read(pmic->mfd, reg, &val);
if (err)
return err;
return val;
}
-static inline int tps65910_write(struct tps65910_reg *pmic, u8 reg, u8 val)
-{
- return pmic->mfd->write(pmic->mfd, reg, 1, &val);
-}
-
static int tps65910_modify_bits(struct tps65910_reg *pmic, u8 reg,
u8 set_mask, u8 clear_mask)
{
@@ -362,7 +357,7 @@ static int tps65910_modify_bits(struct tps65910_reg *pmic, u8 reg,
data &= ~clear_mask;
data |= set_mask;
- err = tps65910_write(pmic, reg, data);
+ err = tps65910_reg_write(pmic->mfd, reg, data);
if (err)
dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg);
@@ -371,7 +366,7 @@ out:
return err;
}
-static int tps65910_reg_read(struct tps65910_reg *pmic, u8 reg)
+static int tps65910_reg_read_locked(struct tps65910_reg *pmic, u8 reg)
{
int data;
@@ -385,13 +380,13 @@ static int tps65910_reg_read(struct tps65910_reg *pmic, u8 reg)
return data;
}
-static int tps65910_reg_write(struct tps65910_reg *pmic, u8 reg, u8 val)
+static int tps65910_reg_write_locked(struct tps65910_reg *pmic, u8 reg, u8 val)
{
int err;
mutex_lock(&pmic->mutex);
- err = tps65910_write(pmic, reg, val);
+ err = tps65910_reg_write(pmic->mfd, reg, val);
if (err < 0)
dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg);
@@ -476,7 +471,7 @@ static int tps65910_is_enabled(struct regulator_dev *dev)
if (reg < 0)
return reg;
- value = tps65910_reg_read(pmic, reg);
+ value = tps65910_reg_read_locked(pmic, reg);
if (value < 0)
return value;
@@ -493,7 +488,7 @@ static int tps65910_enable(struct regulator_dev *dev)
if (reg < 0)
return reg;
- return tps65910_set_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED);
+ return tps65910_reg_set_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED);
}
static int tps65910_disable(struct regulator_dev *dev)
@@ -506,7 +501,7 @@ static int tps65910_disable(struct regulator_dev *dev)
if (reg < 0)
return reg;
- return tps65910_clear_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED);
+ return tps65910_reg_clear_bits(mfd, reg, TPS65910_SUPPLY_STATE_ENABLED);
}
static int tps65910_enable_time(struct regulator_dev *dev)
@@ -532,9 +527,9 @@ static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode)
LDO_ST_MODE_BIT);
case REGULATOR_MODE_IDLE:
value = LDO_ST_ON_BIT | LDO_ST_MODE_BIT;
- return tps65910_set_bits(mfd, reg, value);
+ return tps65910_reg_set_bits(mfd, reg, value);
case REGULATOR_MODE_STANDBY:
- return tps65910_clear_bits(mfd, reg, LDO_ST_ON_BIT);
+ return tps65910_reg_clear_bits(mfd, reg, LDO_ST_ON_BIT);
}
return -EINVAL;
@@ -549,7 +544,7 @@ static unsigned int tps65910_get_mode(struct regulator_dev *dev)
if (reg < 0)
return reg;
- value = tps65910_reg_read(pmic, reg);
+ value = tps65910_reg_read_locked(pmic, reg);
if (value < 0)
return value;
@@ -569,28 +564,28 @@ static int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev)
switch (id) {
case TPS65910_REG_VDD1:
- opvsel = tps65910_reg_read(pmic, TPS65910_VDD1_OP);
- mult = tps65910_reg_read(pmic, TPS65910_VDD1);
+ opvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD1_OP);
+ mult = tps65910_reg_read_locked(pmic, TPS65910_VDD1);
mult = (mult & VDD1_VGAIN_SEL_MASK) >> VDD1_VGAIN_SEL_SHIFT;
- srvsel = tps65910_reg_read(pmic, TPS65910_VDD1_SR);
+ srvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD1_SR);
sr = opvsel & VDD1_OP_CMD_MASK;
opvsel &= VDD1_OP_SEL_MASK;
srvsel &= VDD1_SR_SEL_MASK;
vselmax = 75;
break;
case TPS65910_REG_VDD2:
- opvsel = tps65910_reg_read(pmic, TPS65910_VDD2_OP);
- mult = tps65910_reg_read(pmic, TPS65910_VDD2);
+ opvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD2_OP);
+ mult = tps65910_reg_read_locked(pmic, TPS65910_VDD2);
mult = (mult & VDD2_VGAIN_SEL_MASK) >> VDD2_VGAIN_SEL_SHIFT;
- srvsel = tps65910_reg_read(pmic, TPS65910_VDD2_SR);
+ srvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD2_SR);
sr = opvsel & VDD2_OP_CMD_MASK;
opvsel &= VDD2_OP_SEL_MASK;
srvsel &= VDD2_SR_SEL_MASK;
vselmax = 75;
break;
case TPS65911_REG_VDDCTRL:
- opvsel = tps65910_reg_read(pmic, TPS65911_VDDCTRL_OP);
- srvsel = tps65910_reg_read(pmic, TPS65911_VDDCTRL_SR);
+ opvsel = tps65910_reg_read_locked(pmic, TPS65911_VDDCTRL_OP);
+ srvsel = tps65910_reg_read_locked(pmic, TPS65911_VDDCTRL_SR);
sr = opvsel & VDDCTRL_OP_CMD_MASK;
opvsel &= VDDCTRL_OP_SEL_MASK;
srvsel &= VDDCTRL_SR_SEL_MASK;
@@ -630,7 +625,7 @@ static int tps65910_get_voltage(struct regulator_dev *dev)
if (reg < 0)
return reg;
- value = tps65910_reg_read(pmic, reg);
+ value = tps65910_reg_read_locked(pmic, reg);
if (value < 0)
return value;
@@ -669,7 +664,7 @@ static int tps65911_get_voltage(struct regulator_dev *dev)
reg = pmic->get_ctrl_reg(id);
- value = tps65910_reg_read(pmic, reg);
+ value = tps65910_reg_read_locked(pmic, reg);
switch (id) {
case TPS65911_REG_LDO1:
@@ -728,7 +723,7 @@ static int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev,
tps65910_modify_bits(pmic, TPS65910_VDD1,
(dcdc_mult << VDD1_VGAIN_SEL_SHIFT),
VDD1_VGAIN_SEL_MASK);
- tps65910_reg_write(pmic, TPS65910_VDD1_OP, vsel);
+ tps65910_reg_write_locked(pmic, TPS65910_VDD1_OP, vsel);
break;
case TPS65910_REG_VDD2:
dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1;
@@ -739,11 +734,11 @@ static int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev,
tps65910_modify_bits(pmic, TPS65910_VDD2,
(dcdc_mult << VDD2_VGAIN_SEL_SHIFT),
VDD1_VGAIN_SEL_MASK);
- tps65910_reg_write(pmic, TPS65910_VDD2_OP, vsel);
+ tps65910_reg_write_locked(pmic, TPS65910_VDD2_OP, vsel);
break;
case TPS65911_REG_VDDCTRL:
vsel = selector + 3;
- tps65910_reg_write(pmic, TPS65911_VDDCTRL_OP, vsel);
+ tps65910_reg_write_locked(pmic, TPS65911_VDDCTRL_OP, vsel);
}
return 0;
@@ -994,10 +989,10 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic,
/* External EN1 control */
if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN1)
- ret = tps65910_set_bits(mfd,
+ ret = tps65910_reg_set_bits(mfd,
TPS65910_EN1_LDO_ASS + regoffs, bit_pos);
else
- ret = tps65910_clear_bits(mfd,
+ ret = tps65910_reg_clear_bits(mfd,
TPS65910_EN1_LDO_ASS + regoffs, bit_pos);
if (ret < 0) {
dev_err(mfd->dev,
@@ -1007,10 +1002,10 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic,
/* External EN2 control */
if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN2)
- ret = tps65910_set_bits(mfd,
+ ret = tps65910_reg_set_bits(mfd,
TPS65910_EN2_LDO_ASS + regoffs, bit_pos);
else
- ret = tps65910_clear_bits(mfd,
+ ret = tps65910_reg_clear_bits(mfd,
TPS65910_EN2_LDO_ASS + regoffs, bit_pos);
if (ret < 0) {
dev_err(mfd->dev,
@@ -1022,10 +1017,10 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic,
if ((tps65910_chip_id(mfd) == TPS65910) &&
(id >= TPS65910_REG_VDIG1)) {
if (ext_sleep_config & TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3)
- ret = tps65910_set_bits(mfd,
+ ret = tps65910_reg_set_bits(mfd,
TPS65910_EN3_LDO_ASS + regoffs, bit_pos);
else
- ret = tps65910_clear_bits(mfd,
+ ret = tps65910_reg_clear_bits(mfd,
TPS65910_EN3_LDO_ASS + regoffs, bit_pos);
if (ret < 0) {
dev_err(mfd->dev,
@@ -1037,10 +1032,10 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic,
/* Return if no external control is selected */
if (!(ext_sleep_config & EXT_SLEEP_CONTROL)) {
/* Clear all sleep controls */
- ret = tps65910_clear_bits(mfd,
+ ret = tps65910_reg_clear_bits(mfd,
TPS65910_SLEEP_KEEP_LDO_ON + regoffs, bit_pos);
if (!ret)
- ret = tps65910_clear_bits(mfd,
+ ret = tps65910_reg_clear_bits(mfd,
TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos);
if (ret < 0)
dev_err(mfd->dev,
@@ -1059,32 +1054,33 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic,
(tps65910_chip_id(mfd) == TPS65911))) {
int op_reg_add = pmic->get_ctrl_reg(id) + 1;
int sr_reg_add = pmic->get_ctrl_reg(id) + 2;
- int opvsel = tps65910_reg_read(pmic, op_reg_add);
- int srvsel = tps65910_reg_read(pmic, sr_reg_add);
+ int opvsel = tps65910_reg_read_locked(pmic, op_reg_add);
+ int srvsel = tps65910_reg_read_locked(pmic, sr_reg_add);
if (opvsel & VDD1_OP_CMD_MASK) {
u8 reg_val = srvsel & VDD1_OP_SEL_MASK;
- ret = tps65910_reg_write(pmic, op_reg_add, reg_val);
+ ret = tps65910_reg_write_locked(pmic, op_reg_add,
+ reg_val);
if (ret < 0) {
dev_err(mfd->dev,
"Error in configuring op register\n");
return ret;
}
}
- ret = tps65910_reg_write(pmic, sr_reg_add, 0);
+ ret = tps65910_reg_write_locked(pmic, sr_reg_add, 0);
if (ret < 0) {
dev_err(mfd->dev, "Error in settting sr register\n");
return ret;
}
}
- ret = tps65910_clear_bits(mfd,
+ ret = tps65910_reg_clear_bits(mfd,
TPS65910_SLEEP_KEEP_LDO_ON + regoffs, bit_pos);
if (!ret) {
if (ext_sleep_config & TPS65911_SLEEP_CONTROL_EXT_INPUT_SLEEP)
- ret = tps65910_set_bits(mfd,
+ ret = tps65910_reg_set_bits(mfd,
TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos);
else
- ret = tps65910_clear_bits(mfd,
+ ret = tps65910_reg_clear_bits(mfd,
TPS65910_SLEEP_SET_LDO_OFF + regoffs, bit_pos);
}
if (ret < 0)
@@ -1117,7 +1113,7 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, pmic);
/* Give control of all register to control port */
- tps65910_set_bits(pmic->mfd, TPS65910_DEVCTRL,
+ tps65910_reg_set_bits(pmic->mfd, TPS65910_DEVCTRL,
DEVCTRL_SR_CTL_I2C_SEL_MASK);
switch(tps65910_chip_id(tps65910)) {
diff --git a/drivers/rtc/rtc-tps80031.c b/drivers/rtc/rtc-tps80031.c
index 70d6734a5708..b2b9d04171c5 100644
--- a/drivers/rtc/rtc-tps80031.c
+++ b/drivers/rtc/rtc-tps80031.c
@@ -31,6 +31,7 @@
#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/slab.h>
+#include <linux/gpio.h>
#define RTC_CTRL 0x10
#define RTC_STATUS 0x11
@@ -65,8 +66,25 @@ struct tps80031_rtc {
int irq;
struct rtc_device *rtc;
u8 alarm_irq_enabled;
+ int msecure_gpio;
};
+static inline void tps80031_enable_rtc_write(struct device *dev)
+{
+ struct tps80031_rtc *rtc = dev_get_drvdata(dev);
+
+ if (rtc->msecure_gpio >= 0)
+ gpio_set_value(rtc->msecure_gpio, 1);
+}
+
+static inline void tps80031_disable_rtc_write(struct device *dev)
+{
+ struct tps80031_rtc *rtc = dev_get_drvdata(dev);
+
+ if (rtc->msecure_gpio >= 0)
+ gpio_set_value(rtc->msecure_gpio, 0);
+}
+
static int tps80031_read_regs(struct device *dev, int reg, int len,
uint8_t *val)
{
@@ -93,13 +111,16 @@ static int tps80031_write_regs(struct device *dev, int reg, int len,
uint8_t *val)
{
int ret;
+
+ tps80031_enable_rtc_write(dev);
ret = tps80031_writes(dev->parent, 1, reg, len, val);
if (ret < 0) {
+ tps80031_disable_rtc_write(dev);
dev_err(dev->parent, "failed writing reg: %d\n", reg);
WARN_ON(1);
return ret;
}
-
+ tps80031_disable_rtc_write(dev);
return 0;
}
@@ -150,18 +171,24 @@ static int tps80031_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int tps80031_rtc_stop(struct device *dev)
{
int err;
+
+ tps80031_enable_rtc_write(dev);
err = tps80031_clr_bits(dev->parent, 1, RTC_CTRL, STOP_RTC);
if (err < 0)
dev_err(dev->parent, "failed to stop RTC. err: %d\n", err);
+ tps80031_disable_rtc_write(dev);
return err;
}
static int tps80031_rtc_start(struct device *dev)
{
int err;
+
+ tps80031_enable_rtc_write(dev);
err = tps80031_set_bits(dev->parent, 1, RTC_CTRL, STOP_RTC);
if (err < 0)
dev_err(dev->parent, "failed to start RTC. err: %d\n", err);
+ tps80031_disable_rtc_write(dev);
return err;
}
@@ -262,7 +289,9 @@ static int tps80031_rtc_alarm_irq_enable(struct device *dev,
if (rtc->alarm_irq_enabled)
return 0;
+ tps80031_enable_rtc_write(dev);
err = tps80031_set_bits(p, 1, RTC_INT, ENABLE_ALARM_INT);
+ tps80031_disable_rtc_write(dev);
if (err < 0) {
dev_err(p, "failed to set ALRM int. err: %d\n", err);
return err;
@@ -271,7 +300,9 @@ static int tps80031_rtc_alarm_irq_enable(struct device *dev,
} else {
if(!rtc->alarm_irq_enabled)
return 0;
+ tps80031_enable_rtc_write(dev);
err = tps80031_clr_bits(p, 1, RTC_INT, ENABLE_ALARM_INT);
+ tps80031_disable_rtc_write(dev);
if (err < 0) {
dev_err(p, "failed to clear ALRM int. err: %d\n", err);
return err;
@@ -303,8 +334,10 @@ static irqreturn_t tps80031_rtc_irq(int irq, void *data)
return -EBUSY;
}
+ tps80031_enable_rtc_write(dev);
err = tps80031_force_update(dev->parent, 1, RTC_STATUS,
ALARM_INT_STATUS, ALARM_INT_STATUS);
+ tps80031_disable_rtc_write(dev);
if (err) {
dev_err(dev->parent, "unable to set Alarm INT\n");
return -EBUSY;
@@ -335,8 +368,19 @@ static int __devinit tps80031_rtc_probe(struct platform_device *pdev)
if (pdata->irq < 0)
dev_err(&pdev->dev, "no IRQ specified, wakeup is disabled\n");
+ rtc->msecure_gpio = -1;
+ if (gpio_is_valid(pdata->msecure_gpio)) {
+ err = gpio_request(pdata->msecure_gpio, "tps80031 msecure");
+ if (err == 0) {
+ rtc->msecure_gpio = pdata->msecure_gpio;
+ gpio_direction_output(rtc->msecure_gpio, 0);
+ } else
+ dev_warn(&pdev->dev, "could not get msecure GPIO\n");
+ }
+
rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
&tps80031_rtc_ops, THIS_MODULE);
+ dev_set_drvdata(&pdev->dev, rtc);
if (IS_ERR(rtc->rtc)) {
err = PTR_ERR(rtc->rtc);
@@ -379,7 +423,9 @@ static int __devinit tps80031_rtc_probe(struct platform_device *pdev)
return -EBUSY;
}
+ tps80031_enable_rtc_write(&pdev->dev);
err = tps80031_set_bits(pdev->dev.parent, 1, RTC_INT, ENABLE_ALARM_INT);
+ tps80031_disable_rtc_write(&pdev->dev);
if (err) {
dev_err(&pdev->dev, "unable to program Interrupt Mask reg\n");
err = -EBUSY;
@@ -388,7 +434,6 @@ static int __devinit tps80031_rtc_probe(struct platform_device *pdev)
} else
rtc->alarm_irq_enabled = 1;
- dev_set_drvdata(&pdev->dev, rtc);
if (pdata && (pdata->irq >= 0)) {
rtc->irq = pdata->irq;
err = request_threaded_irq(pdata->irq, NULL, tps80031_rtc_irq,
diff --git a/drivers/tty/serial/tegra_hsuart.c b/drivers/tty/serial/tegra_hsuart.c
index 8b65e20c4d3e..484e228dc044 100644
--- a/drivers/tty/serial/tegra_hsuart.c
+++ b/drivers/tty/serial/tegra_hsuart.c
@@ -1263,6 +1263,12 @@ static void tegra_set_termios(struct uart_port *u, struct ktermios *termios,
if (t->rts_active)
set_rts(t, false);
+ /* Clear all interrupts as configuration is going to be change */
+ uart_writeb(t, t->ier_shadow | UART_IER_RDI, UART_IER);
+ uart_readb(t, UART_IER);
+ uart_writeb(t, 0, UART_IER);
+ uart_readb(t, UART_IER);
+
/* Parity */
lcr = t->lcr_shadow;
lcr &= ~UART_LCR_PARITY;
@@ -1335,6 +1341,13 @@ static void tegra_set_termios(struct uart_port *u, struct ktermios *termios,
/* update the port timeout based on new settings */
uart_update_timeout(u, termios->c_cflag, baud);
+ /* Make sure all write has completed */
+ uart_readb(t, UART_IER);
+
+ /* Reenable interrupt */
+ uart_writeb(t, t->ier_shadow, UART_IER);
+ uart_readb(t, UART_IER);
+
spin_unlock_irqrestore(&u->lock, flags);
dev_vdbg(t->uport.dev, "-tegra_set_termios\n");
return;
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index c5fa8160bffe..98f3d5106a38 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -224,7 +224,7 @@ static int tegra_ehci_hub_control(
status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1];
/* Ensure the port PORT_SUSPEND and PORT_RESUME has cleared */
if (handshake(ehci, status_reg, (PORT_SUSPEND | PORT_RESUME), 0, 25000)) {
- pr_err("%s: timeout waiting for SUSPEND to clear\n", __func__);
+ EHCI_DBG("%s: timeout waiting for SUSPEND to clear\n", __func__);
}
tegra_usb_phy_post_resume(tegra->phy);
tegra->port_resuming = 0;
@@ -241,6 +241,11 @@ static int tegra_ehci_hub_control(
if (wValue == USB_PORT_FEAT_SUSPEND) {
tegra_usb_phy_pre_resume(tegra->phy, false);
tegra->port_resuming = 1;
+ } else if (wValue == USB_PORT_FEAT_ENABLE) {
+ u32 temp;
+ temp = ehci_readl(ehci, &ehci->regs->port_status[0]) & ~PORT_RWC_BITS;
+ ehci_writel(ehci, temp & ~PORT_PE, &ehci->regs->port_status[0]);
+ return retval;
}
break;
}
@@ -264,6 +269,12 @@ static int tegra_ehci_hub_control(
tegra_usb_phy_port_power(tegra->phy);
}
break;
+ case ClearPortFeature:
+ if (wValue == USB_PORT_FEAT_SUSPEND) {
+ /* tegra USB controller needs 25 ms to resume the port */
+ ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25);
+ }
+ break;
}
}
diff --git a/drivers/usb/otg/tegra-otg.c b/drivers/usb/otg/tegra-otg.c
index 4c590076f73e..b5106faf68bd 100644
--- a/drivers/usb/otg/tegra-otg.c
+++ b/drivers/usb/otg/tegra-otg.c
@@ -375,10 +375,8 @@ static ssize_t store_host_en(struct device *dev, struct device_attribute *attr,
unsigned long host;
int err;
- err = kstrtoul(buf, 10, &host);
- if (err < 0) {
- return err;
- }
+ if (sscanf(buf, "%d", &host) != 1 || host < 0 || host > 1)
+ return -EINVAL;
if (host) {
enable_interrupt(tegra, false);
@@ -474,6 +472,8 @@ static int tegra_otg_probe(struct platform_device *pdev)
goto err_irq;
}
+ clk_disable(tegra->clk);
+
return 0;
err_irq:
diff --git a/drivers/video/tegra/Kconfig b/drivers/video/tegra/Kconfig
index 59e27788680d..15c2acfa8cc7 100644
--- a/drivers/video/tegra/Kconfig
+++ b/drivers/video/tegra/Kconfig
@@ -102,6 +102,15 @@ config NVMAP_PAGE_POOL_SIZE
hex
default 0x0
+config NVMAP_CACHE_MAINT_BY_SET_WAYS
+ bool "Enalbe cache maintenance by set/ways"
+ depends on TEGRA_NVMAP
+ help
+ Say Y here to reduce cache maintenance overhead by MVA.
+ This helps in reducing cache maintenance overhead in the systems,
+ where inner cache includes only L1. For the systems, where inner cache
+ includes L1 and L2, keep this option disabled.
+
config NVMAP_VPR
bool "Enable VPR Heap."
depends on TEGRA_NVMAP
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index df54578a5b5a..5c960f9e45c0 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -2146,23 +2146,6 @@ static void tegra_dc_vblank(struct work_struct *work)
}
}
-/* Must acquire dc lock and dc one-shot lock before invoking this function.
- * Acquire dc one-shot lock first and then dc lock. */
-void tegra_dc_host_trigger(struct tegra_dc *dc)
-{
- /* We release the lock here to prevent deadlock between
- * cancel_delayed_work_sync and one-shot work. */
- mutex_unlock(&dc->lock);
-
- cancel_delayed_work_sync(&dc->one_shot_work);
- mutex_lock(&dc->lock);
-
- schedule_delayed_work(&dc->one_shot_work,
- msecs_to_jiffies(dc->one_shot_delay_ms));
- tegra_dc_program_bandwidth(dc);
- tegra_dc_writel(dc, NC_HOST_TRIG, DC_CMD_STATE_CONTROL);
-}
-
static void tegra_dc_one_shot_worker(struct work_struct *work)
{
struct tegra_dc *dc = container_of(
diff --git a/drivers/video/tegra/dc/dc_config.h b/drivers/video/tegra/dc/dc_config.h
index f513cd06dc45..314cd11e77f9 100644
--- a/drivers/video/tegra/dc/dc_config.h
+++ b/drivers/video/tegra/dc/dc_config.h
@@ -129,13 +129,13 @@ enum tegra_dc_feature_option {
};
struct tegra_dc_feature_entry {
- int window_index;
- enum tegra_dc_feature_option option;
+ u32 window_index;
+ u32 option;
long arg[ENTRY_SIZE];
};
struct tegra_dc_feature {
- unsigned num_entries;
+ u32 num_entries;
struct tegra_dc_feature_entry *entries;
};
diff --git a/drivers/video/tegra/dc/dsi.c b/drivers/video/tegra/dc/dsi.c
index e402c416b779..6624a8e8f52c 100644
--- a/drivers/video/tegra/dc/dsi.c
+++ b/drivers/video/tegra/dc/dsi.c
@@ -1625,7 +1625,7 @@ static void tegra_dsi_pad_calibration(struct tegra_dc_dsi_data *dsi)
tegra_vi_csi_writel(val, CSI_CIL_PAD_CONFIG);
}
-static void tegra_dsi_panelB_enable()
+static void tegra_dsi_panelB_enable(void)
{
unsigned int val;
@@ -2751,8 +2751,8 @@ static int tegra_dc_dsi_cp_info(struct tegra_dc_dsi_data *dsi,
struct tegra_dsi_out *p_dsi)
{
struct tegra_dsi_cmd *p_init_cmd;
- struct tegra_dsi_cmd *p_early_suspend_cmd;
- struct tegra_dsi_cmd *p_late_resume_cmd;
+ struct tegra_dsi_cmd *p_early_suspend_cmd = NULL;
+ struct tegra_dsi_cmd *p_late_resume_cmd = NULL;
struct tegra_dsi_cmd *p_suspend_cmd;
int err;
diff --git a/drivers/video/tegra/dc/ext/dev.c b/drivers/video/tegra/dc/ext/dev.c
index c349a4720d2e..a8de7a7a26e0 100644
--- a/drivers/video/tegra/dc/ext/dev.c
+++ b/drivers/video/tegra/dc/ext/dev.c
@@ -708,6 +708,21 @@ static int tegra_dc_ext_get_status(struct tegra_dc_ext_user *user,
return 0;
}
+static int tegra_dc_ext_get_feature(struct tegra_dc_ext_user *user,
+ struct tegra_dc_ext_feature *feature)
+{
+ struct tegra_dc *dc = user->ext->dc;
+ struct tegra_dc_feature *table = dc->feature;
+
+ if (dc->enabled && feature->entries) {
+ feature->length = table->num_entries;
+ memcpy(feature->entries, table->entries, table->num_entries *
+ sizeof(struct tegra_dc_feature_entry));
+ }
+
+ return 0;
+}
+
static long tegra_dc_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
@@ -805,6 +820,22 @@ static long tegra_dc_ioctl(struct file *filp, unsigned int cmd,
return tegra_dc_ext_set_lut(user, &args);
}
+ case TEGRA_DC_EXT_GET_FEATURES:
+ {
+ struct tegra_dc_ext_feature args;
+ int ret;
+
+ if (copy_from_user(&args, user_arg, sizeof(args)))
+ return -EFAULT;
+
+ ret = tegra_dc_ext_get_feature(user, &args);
+
+ if (copy_to_user(user_arg, &args, sizeof(args)))
+ return -EFAULT;
+
+ return ret;
+ }
+
default:
return -EINVAL;
}
diff --git a/drivers/video/tegra/dc/nvsd.c b/drivers/video/tegra/dc/nvsd.c
index 65d518759243..860dd8dab1fd 100644
--- a/drivers/video/tegra/dc/nvsd.c
+++ b/drivers/video/tegra/dc/nvsd.c
@@ -378,7 +378,10 @@ void nvsd_init(struct tegra_dc *dc, struct tegra_dc_sd_settings *settings)
val = tegra_dc_readl(dc, DC_DISP_SD_CONTROL);
if (val & SD_ENABLE_NORMAL)
- i = tegra_dc_readl(dc, DC_DISP_SD_HW_K_VALUES);
+ if (settings->phase_in_adjustments)
+ i = tegra_dc_readl(dc, DC_DISP_SD_MAN_K_VALUES);
+ else
+ i = tegra_dc_readl(dc, DC_DISP_SD_HW_K_VALUES);
else
i = 0; /* 0 values for RGB = 1.0, i.e. non-affected */
diff --git a/drivers/video/tegra/host/Makefile b/drivers/video/tegra/host/Makefile
index d47c97571286..f228a3ad0396 100644
--- a/drivers/video/tegra/host/Makefile
+++ b/drivers/video/tegra/host/Makefile
@@ -17,7 +17,6 @@ obj-$(CONFIG_TEGRA_GRHOST) += gr3d/
obj-$(CONFIG_TEGRA_GRHOST) += host1x/
obj-$(CONFIG_TEGRA_GRHOST) += t20/
obj-$(CONFIG_TEGRA_GRHOST) += t30/
-obj-$(CONFIG_TEGRA_GRHOST) += dsi/
obj-$(CONFIG_TEGRA_GRHOST) += gr2d/
obj-$(CONFIG_TEGRA_GRHOST) += isp/
obj-$(CONFIG_TEGRA_GRHOST) += vi/
diff --git a/drivers/video/tegra/host/bus_client.c b/drivers/video/tegra/host/bus_client.c
index 87aa9c64d363..6bfce9a3cb2a 100644
--- a/drivers/video/tegra/host/bus_client.c
+++ b/drivers/video/tegra/host/bus_client.c
@@ -50,10 +50,28 @@
#include "nvhost_job.h"
#include "nvhost_hwctx.h"
-void nvhost_read_module_regs(struct nvhost_device *ndev,
+static int validate_reg(struct nvhost_device *ndev, u32 offset, int count)
+{
+ struct resource *r = nvhost_get_resource(ndev, IORESOURCE_MEM, 0);
+ int err = 0;
+
+ if (offset + 4 * count > resource_size(r)
+ || (offset + 4 * count < offset))
+ err = -EPERM;
+
+ return err;
+}
+
+int nvhost_read_module_regs(struct nvhost_device *ndev,
u32 offset, int count, u32 *values)
{
void __iomem *p = ndev->aperture + offset;
+ int err;
+
+ /* verify offset */
+ err = validate_reg(ndev, offset, count);
+ if (err)
+ return err;
nvhost_module_busy(ndev);
while (count--) {
@@ -62,12 +80,20 @@ void nvhost_read_module_regs(struct nvhost_device *ndev,
}
rmb();
nvhost_module_idle(ndev);
+
+ return 0;
}
-void nvhost_write_module_regs(struct nvhost_device *ndev,
+int nvhost_write_module_regs(struct nvhost_device *ndev,
u32 offset, int count, const u32 *values)
{
void __iomem *p = ndev->aperture + offset;
+ int err;
+
+ /* verify offset */
+ err = validate_reg(ndev, offset, count);
+ if (err)
+ return err;
nvhost_module_busy(ndev);
while (count--) {
@@ -76,6 +102,8 @@ void nvhost_write_module_regs(struct nvhost_device *ndev,
}
wmb();
nvhost_module_idle(ndev);
+
+ return 0;
}
struct nvhost_channel_userctx {
@@ -140,7 +168,9 @@ static int nvhost_channelopen(struct inode *inode, struct file *filp)
priv->priority = NVHOST_PRIORITY_MEDIUM;
priv->clientid = atomic_add_return(1,
&nvhost_get_host(ch->dev)->clientid);
- priv->timeout = MAX_STUCK_CHECK_COUNT * SYNCPT_CHECK_PERIOD;
+ priv->timeout =
+ jiffies_to_msecs(MAX_STUCK_CHECK_COUNT * SYNCPT_CHECK_PERIOD);
+
return 0;
fail:
nvhost_channelrelease(inode, filp);
@@ -149,14 +179,17 @@ fail:
static int set_submit(struct nvhost_channel_userctx *ctx)
{
- struct device *device = &ctx->ch->dev->dev;
+ struct nvhost_device *ndev = ctx->ch->dev;
+ struct nvhost_master *host = nvhost_get_host(ndev);
/* submit should have at least 1 cmdbuf */
- if (!ctx->hdr.num_cmdbufs)
+ if (!ctx->hdr.num_cmdbufs ||
+ !nvhost_syncpt_is_valid(&host->syncpt,
+ ctx->hdr.syncpt_id))
return -EIO;
if (!ctx->nvmap) {
- dev_err(device, "no nvmap context set\n");
+ dev_err(&ndev->dev, "no nvmap context set\n");
return -EFAULT;
}
@@ -182,6 +215,11 @@ static void reset_submit(struct nvhost_channel_userctx *ctx)
ctx->hdr.num_relocs = 0;
ctx->num_relocshifts = 0;
ctx->hdr.num_waitchks = 0;
+
+ if (ctx->job) {
+ nvhost_job_put(ctx->job);
+ ctx->job = NULL;
+ }
}
static ssize_t nvhost_channelwrite(struct file *filp, const char __user *buf,
@@ -367,11 +405,10 @@ static long nvhost_channelctl(struct file *filp,
if ((_IOC_TYPE(cmd) != NVHOST_IOCTL_MAGIC) ||
(_IOC_NR(cmd) == 0) ||
- (_IOC_NR(cmd) > NVHOST_IOCTL_CHANNEL_LAST))
+ (_IOC_NR(cmd) > NVHOST_IOCTL_CHANNEL_LAST) ||
+ (_IOC_SIZE(cmd) > NVHOST_IOCTL_CHANNEL_MAX_ARG_SIZE))
return -EFAULT;
- BUG_ON(_IOC_SIZE(cmd) > NVHOST_IOCTL_CHANNEL_MAX_ARG_SIZE);
-
if (_IOC_DIR(cmd) & _IOC_WRITE) {
if (copy_from_user(buf, (void __user *)arg, _IOC_SIZE(cmd)))
return -EFAULT;
diff --git a/drivers/video/tegra/host/bus_client.h b/drivers/video/tegra/host/bus_client.h
index adc3a704ea5d..e95ea0bc3401 100644
--- a/drivers/video/tegra/host/bus_client.h
+++ b/drivers/video/tegra/host/bus_client.h
@@ -24,10 +24,10 @@
#include <linux/types.h>
struct nvhost_device;
-void nvhost_read_module_regs(struct nvhost_device *ndev,
+int nvhost_read_module_regs(struct nvhost_device *ndev,
u32 offset, int count, u32 *values);
-void nvhost_write_module_regs(struct nvhost_device *ndev,
+int nvhost_write_module_regs(struct nvhost_device *ndev,
u32 offset, int count, const u32 *values);
int nvhost_client_user_init(struct nvhost_device *dev);
diff --git a/drivers/video/tegra/host/dev.c b/drivers/video/tegra/host/dev.c
index ca73528fbeeb..2c05fbfb7477 100644
--- a/drivers/video/tegra/host/dev.c
+++ b/drivers/video/tegra/host/dev.c
@@ -205,6 +205,7 @@ static int nvhost_ioctl_ctrl_module_regrdwr(struct nvhost_ctrl_userctx *ctx,
return -EINVAL;
while (num_offsets--) {
+ int err;
int remaining = args->block_size >> 2;
u32 offs;
if (get_user(offs, offsets))
@@ -216,17 +217,21 @@ static int nvhost_ioctl_ctrl_module_regrdwr(struct nvhost_ctrl_userctx *ctx,
if (copy_from_user(vals, values,
batch*sizeof(u32)))
return -EFAULT;
- nvhost_write_module_regs(ndev,
+ err = nvhost_write_module_regs(ndev,
offs, batch, vals);
+ if (err)
+ return err;
} else {
- nvhost_read_module_regs(ndev,
+ err = nvhost_read_module_regs(ndev,
offs, batch, vals);
+ if (err)
+ return err;
if (copy_to_user(values, vals,
batch*sizeof(u32)))
return -EFAULT;
}
remaining -= batch;
- offs += batch;
+ offs += batch*sizeof(u32);
values += batch;
}
}
@@ -250,11 +255,10 @@ static long nvhost_ctrlctl(struct file *filp,
if ((_IOC_TYPE(cmd) != NVHOST_IOCTL_MAGIC) ||
(_IOC_NR(cmd) == 0) ||
- (_IOC_NR(cmd) > NVHOST_IOCTL_CTRL_LAST))
+ (_IOC_NR(cmd) > NVHOST_IOCTL_CTRL_LAST) ||
+ (_IOC_SIZE(cmd) > NVHOST_IOCTL_CTRL_MAX_ARG_SIZE))
return -EFAULT;
- BUG_ON(_IOC_SIZE(cmd) > NVHOST_IOCTL_CTRL_MAX_ARG_SIZE);
-
if (_IOC_DIR(cmd) & _IOC_WRITE) {
if (copy_from_user(buf, (void __user *)arg, _IOC_SIZE(cmd)))
return -EFAULT;
diff --git a/drivers/video/tegra/host/dsi/Makefile b/drivers/video/tegra/host/dsi/Makefile
deleted file mode 100644
index eb94d3ec4928..000000000000
--- a/drivers/video/tegra/host/dsi/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-GCOV_PROFILE := y
-EXTRA_CFLAGS += -Idrivers/video/tegra/host
-
-nvhost-dsi-objs = \
- dsi.o
-
-obj-$(CONFIG_TEGRA_GRHOST) += nvhost-dsi.o
diff --git a/drivers/video/tegra/host/dsi/dsi.c b/drivers/video/tegra/host/dsi/dsi.c
deleted file mode 100644
index 87da8a6f1b8a..000000000000
--- a/drivers/video/tegra/host/dsi/dsi.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * drivers/video/tegra/host/dsi/dsi.c
- *
- * Tegra Graphics DSI
- *
- * Copyright (c) 2012, NVIDIA Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "dev.h"
-#include "bus_client.h"
-
-static int dsi_probe(struct nvhost_device *dev,
- struct nvhost_device_id *id_table)
-{
- return nvhost_client_device_init(dev);
-}
-
-static int __exit dsi_remove(struct nvhost_device *dev)
-{
- /* Add clean-up */
- return 0;
-}
-
-static int dsi_suspend(struct nvhost_device *dev, pm_message_t state)
-{
- return nvhost_client_device_suspend(dev);
-}
-
-static int dsi_resume(struct nvhost_device *dev)
-{
- dev_info(&dev->dev, "resuming\n");
- return 0;
-}
-
-struct nvhost_device *dsi_device;
-
-static struct nvhost_driver dsi_driver = {
- .probe = dsi_probe,
- .remove = __exit_p(dsi_remove),
-#ifdef CONFIG_PM
- .suspend = dsi_suspend,
- .resume = dsi_resume,
-#endif
- .driver = {
- .owner = THIS_MODULE,
- .name = "dsi",
- }
-};
-
-static int __init dsi_init(void)
-{
- int err;
-
- dsi_device = nvhost_get_device("dsi");
- if (!dsi_device)
- return -ENXIO;
-
- err = nvhost_device_register(dsi_device);
- if (err)
- return err;
-
- return nvhost_driver_register(&dsi_driver);
-}
-
-static void __exit dsi_exit(void)
-{
- nvhost_driver_unregister(&dsi_driver);
-}
-
-module_init(dsi_init);
-module_exit(dsi_exit);
diff --git a/drivers/video/tegra/host/gr3d/gr3d_t30.c b/drivers/video/tegra/host/gr3d/gr3d_t30.c
index 57f4c779eff8..4bc7c9f92bb5 100644
--- a/drivers/video/tegra/host/gr3d/gr3d_t30.c
+++ b/drivers/video/tegra/host/gr3d/gr3d_t30.c
@@ -427,6 +427,8 @@ struct nvhost_hwctx_handler *nvhost_gr3d_t30_ctxhandler_init(
setup_save(p, save_ptr);
+ nvmap_munmap(p->save_buf, save_ptr);
+
p->h.alloc = ctx3d_alloc_v1;
p->h.save_push = save_push_v1;
p->h.save_service = NULL;
diff --git a/drivers/video/tegra/host/nvhost_acm.c b/drivers/video/tegra/host/nvhost_acm.c
index 6d96bd023d81..dfd84328307b 100644
--- a/drivers/video/tegra/host/nvhost_acm.c
+++ b/drivers/video/tegra/host/nvhost_acm.c
@@ -134,7 +134,11 @@ static void to_state_running_locked(struct nvhost_device *dev)
for (i = 0; i < dev->num_clks; i++) {
int err = clk_enable(dev->clk[i]);
- BUG_ON(err);
+ if (err) {
+ dev_err(&dev->dev, "Cannot turn on clock %s",
+ dev->clocks[i].name);
+ return;
+ }
}
if (prev_state == NVHOST_POWER_STATE_POWERGATED
@@ -369,7 +373,11 @@ int nvhost_module_init(struct nvhost_device *dev)
snprintf(devname, MAX_DEVID_LENGTH, "tegra_%s", dev->name);
c = clk_get_sys(devname, dev->clocks[i].name);
- BUG_ON(IS_ERR_OR_NULL(c));
+ if (IS_ERR_OR_NULL(c)) {
+ dev_err(&dev->dev, "Cannot get clock %s\n",
+ dev->clocks[i].name);
+ continue;
+ }
rate = clk_round_rate(c, rate);
clk_enable(c);
diff --git a/drivers/video/tegra/host/nvhost_syncpt.h b/drivers/video/tegra/host/nvhost_syncpt.h
index b58921bffa9c..fcc9fce72071 100644
--- a/drivers/video/tegra/host/nvhost_syncpt.h
+++ b/drivers/video/tegra/host/nvhost_syncpt.h
@@ -140,6 +140,11 @@ int nvhost_syncpt_patch_wait(struct nvhost_syncpt *sp, void *patch_addr);
void nvhost_syncpt_debug(struct nvhost_syncpt *sp);
+static inline int nvhost_syncpt_is_valid(struct nvhost_syncpt *sp, u32 id)
+{
+ return id != NVSYNCPT_INVALID && id < sp->nb_pts;
+}
+
int nvhost_mutex_try_lock(struct nvhost_syncpt *sp, int idx);
void nvhost_mutex_unlock(struct nvhost_syncpt *sp, int idx);
diff --git a/drivers/video/tegra/nvmap/nvmap_ioctl.c b/drivers/video/tegra/nvmap/nvmap_ioctl.c
index 14787154523f..7a10231982c1 100644
--- a/drivers/video/tegra/nvmap/nvmap_ioctl.c
+++ b/drivers/video/tegra/nvmap/nvmap_ioctl.c
@@ -540,6 +540,7 @@ static bool fast_cache_maint(struct nvmap_client *client, struct nvmap_handle *h
{
int ret = false;
+#if defined(CONFIG_NVMAP_CACHE_MAINT_BY_SET_WAYS)
if ((op == NVMAP_CACHE_OP_INV) ||
((end - start) < FLUSH_CLEAN_BY_SET_WAY_THRESHOLD))
goto out;
@@ -559,6 +560,7 @@ static bool fast_cache_maint(struct nvmap_client *client, struct nvmap_handle *h
}
ret = true;
out:
+#endif
return ret;
}
diff --git a/include/linux/mfd/rc5t583.h b/include/linux/mfd/rc5t583.h
index a2c61609d21d..3661c59aa1e9 100644
--- a/include/linux/mfd/rc5t583.h
+++ b/include/linux/mfd/rc5t583.h
@@ -26,6 +26,7 @@
#include <linux/mutex.h>
#include <linux/types.h>
+#include <linux/regmap.h>
#define RC5T583_MAX_REGS 0xF8
@@ -249,6 +250,26 @@ enum {
RC5T583_EXT_PWRREQ2_CONTROL = 0x2,
};
+enum {
+ RC5T583_REGULATOR_DC0,
+ RC5T583_REGULATOR_DC1,
+ RC5T583_REGULATOR_DC2,
+ RC5T583_REGULATOR_DC3,
+ RC5T583_REGULATOR_LDO0,
+ RC5T583_REGULATOR_LDO1,
+ RC5T583_REGULATOR_LDO2,
+ RC5T583_REGULATOR_LDO3,
+ RC5T583_REGULATOR_LDO4,
+ RC5T583_REGULATOR_LDO5,
+ RC5T583_REGULATOR_LDO6,
+ RC5T583_REGULATOR_LDO7,
+ RC5T583_REGULATOR_LDO8,
+ RC5T583_REGULATOR_LDO9,
+
+ /* Should be last entry */
+ RC5T583_REGULATOR_MAX,
+};
+
struct rc5t583 {
struct device *dev;
struct regmap *regmap;
@@ -271,22 +292,63 @@ struct rc5t583 {
* rc5t583_platform_data: Platform data for ricoh rc5t583 pmu.
* The board specific data is provided through this structure.
* @irq_base: Irq base number on which this device registers their interrupts.
+ * @gpio_base: GPIO base from which gpio of this device will start.
* @enable_shutdown: Enable shutdown through the input pin "shutdown".
+ * @regulator_deepsleep_slot: The slot number on which device goes to sleep
+ * in device sleep mode.
+ * @regulator_ext_pwr_control: External power request regulator control. The
+ * regulator output enable/disable is controlled by the external
+ * power request input state.
+ * @reg_init_data: Regulator init data.
*/
struct rc5t583_platform_data {
int irq_base;
+ int gpio_base;
bool enable_shutdown;
+ int regulator_deepsleep_slot[RC5T583_REGULATOR_MAX];
+ unsigned long regulator_ext_pwr_control[RC5T583_REGULATOR_MAX];
+ struct regulator_init_data *reg_init_data[RC5T583_REGULATOR_MAX];
};
-int rc5t583_write(struct device *dev, u8 reg, uint8_t val);
-int rc5t583_read(struct device *dev, uint8_t reg, uint8_t *val);
-int rc5t583_set_bits(struct device *dev, unsigned int reg,
- unsigned int bit_mask);
-int rc5t583_clear_bits(struct device *dev, unsigned int reg,
- unsigned int bit_mask);
-int rc5t583_update(struct device *dev, unsigned int reg,
- unsigned int val, unsigned int mask);
+static inline int rc5t583_write(struct device *dev, uint8_t reg, uint8_t val)
+{
+ struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+ return regmap_write(rc5t583->regmap, reg, val);
+}
+
+static inline int rc5t583_read(struct device *dev, uint8_t reg, uint8_t *val)
+{
+ struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+ unsigned int ival;
+ int ret;
+ ret = regmap_read(rc5t583->regmap, reg, &ival);
+ if (!ret)
+ *val = (uint8_t)ival;
+ return ret;
+}
+
+static inline int rc5t583_set_bits(struct device *dev, unsigned int reg,
+ unsigned int bit_mask)
+{
+ struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+ return regmap_update_bits(rc5t583->regmap, reg, bit_mask, bit_mask);
+}
+
+static inline int rc5t583_clear_bits(struct device *dev, unsigned int reg,
+ unsigned int bit_mask)
+{
+ struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+ return regmap_update_bits(rc5t583->regmap, reg, bit_mask, 0);
+}
+
+static inline int rc5t583_update(struct device *dev, unsigned int reg,
+ unsigned int val, unsigned int mask)
+{
+ struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+ return regmap_update_bits(rc5t583->regmap, reg, mask, val);
+}
+
int rc5t583_ext_power_req_config(struct device *dev, int deepsleep_id,
int ext_pwr_req, int deepsleep_slot_nr);
int rc5t583_irq_init(struct rc5t583 *rc5t583, int irq, int irq_base);
diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h
index f6021cc9d911..7e4395a2c21b 100644
--- a/include/linux/mfd/tps65910.h
+++ b/include/linux/mfd/tps65910.h
@@ -17,6 +17,9 @@
#ifndef __LINUX_MFD_TPS65910_H
#define __LINUX_MFD_TPS65910_H
+#include <linux/gpio.h>
+#include <linux/regmap.h>
+
/* TPS chip id list */
#define TPS65910 0
#define TPS65911 1
@@ -781,6 +784,18 @@
#define TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3 0x4
#define TPS65911_SLEEP_CONTROL_EXT_INPUT_SLEEP 0x8
+/*
+ * Sleep keepon data: Maintains the state in sleep mode
+ * @therm_keepon: Keep on the thermal monitoring in sleep state.
+ * @clkout32k_keepon: Keep on the 32KHz clock output in sleep state.
+ * @i2chs_keepon: Keep on high speed internal clock in sleep state.
+ */
+struct tps65910_sleep_keepon_data {
+ unsigned therm_keepon:1;
+ unsigned clkout32k_keepon:1;
+ unsigned i2chs_keepon:1;
+};
+
/**
* struct tps65910_board
* Board platform data may be used to initialize regulators.
@@ -792,6 +807,8 @@ struct tps65910_board {
int irq_base;
int vmbch_threshold;
int vmbch2_threshold;
+ bool en_dev_slp;
+ struct tps65910_sleep_keepon_data *slp_keepon;
unsigned long regulator_ext_sleep_control[TPS65910_NUM_REGS];
bool en_gpio_sleep[TPS6591X_MAX_NUM_GPIO];
struct regulator_init_data *tps65910_pmic_init_data[TPS65910_NUM_REGS];
@@ -807,17 +824,12 @@ struct tps65910 {
struct regmap *regmap;
struct mutex io_mutex;
unsigned int id;
- int (*read)(struct tps65910 *tps65910, u8 reg, int size, void *dest);
- int (*write)(struct tps65910 *tps65910, u8 reg, int size, void *src);
/* Client devices */
struct tps65910_pmic *pmic;
struct tps65910_rtc *rtc;
struct tps65910_power *power;
- /* GPIO Handling */
- struct gpio_chip gpio;
-
/* IRQ Handling */
struct mutex irq_lock;
int chip_irq;
@@ -831,9 +843,6 @@ struct tps65910_platform_data {
int irq_base;
};
-int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask);
-int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask);
-void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base);
int tps65910_irq_init(struct tps65910 *tps65910, int irq,
struct tps65910_platform_data *pdata);
int tps65910_irq_exit(struct tps65910 *tps65910);
@@ -843,4 +852,28 @@ static inline int tps65910_chip_id(struct tps65910 *tps65910)
return tps65910->id;
}
+static inline int tps65910_reg_read(struct tps65910 *tps65910, u8 reg,
+ unsigned int *val)
+{
+ return regmap_read(tps65910->regmap, reg, val);
+}
+
+static inline int tps65910_reg_write(struct tps65910 *tps65910, u8 reg,
+ unsigned int val)
+{
+ return regmap_write(tps65910->regmap, reg, val);
+}
+
+static inline int tps65910_reg_set_bits(struct tps65910 *tps65910, u8 reg,
+ u8 mask)
+{
+ return regmap_update_bits(tps65910->regmap, reg, mask, mask);
+}
+
+static inline int tps65910_reg_clear_bits(struct tps65910 *tps65910, u8 reg,
+ u8 mask)
+{
+ return regmap_update_bits(tps65910->regmap, reg, mask, 0);
+}
+
#endif /* __LINUX_MFD_TPS65910_H */
diff --git a/include/linux/mfd/tps80031.h b/include/linux/mfd/tps80031.h
index 9623a873d311..b3b9480ce596 100644
--- a/include/linux/mfd/tps80031.h
+++ b/include/linux/mfd/tps80031.h
@@ -165,6 +165,7 @@ struct tps80031_subdev_info {
struct tps80031_rtc_platform_data {
int irq;
struct rtc_time time;
+ int msecure_gpio;
};
struct tps80031_clk32k_init_data {
diff --git a/include/linux/of.h b/include/linux/of.h
index 9180dc5cb00b..c4b5b52a7515 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -235,6 +235,7 @@ extern void of_attach_node(struct device_node *);
extern void of_detach_node(struct device_node *);
#endif
+#define of_match_ptr(_ptr) (_ptr)
#else /* CONFIG_OF */
static inline bool of_have_populated_dt(void)
@@ -263,6 +264,7 @@ static inline const void *of_get_property(const struct device_node *node,
return NULL;
}
+#define of_match_ptr(_ptr) NULL
#endif /* CONFIG_OF */
static inline int of_property_read_u32(const struct device_node *np,
diff --git a/include/linux/pm_qos_params.h b/include/linux/pm_qos_params.h
index 5a536cbb25b8..be63f01630a3 100644
--- a/include/linux/pm_qos_params.h
+++ b/include/linux/pm_qos_params.h
@@ -28,7 +28,7 @@ enum {
#define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC)
#define PM_QOS_NETWORK_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC)
#define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE 0
-#define PM_QOS_MIN_ONLINE_CPUS_DEFAULT_VALUE 1
+#define PM_QOS_MIN_ONLINE_CPUS_DEFAULT_VALUE 0
#define PM_QOS_MAX_ONLINE_CPUS_DEFAULT_VALUE LONG_MAX
#define PM_QOS_CPU_FREQ_MIN_DEFAULT_VALUE 0
#define PM_QOS_CPU_FREQ_MAX_DEFAULT_VALUE LONG_MAX
diff --git a/include/linux/regulator/tps62360.h b/include/linux/regulator/tps62360.h
index 6a5c1b2c751e..6475cd029c42 100644
--- a/include/linux/regulator/tps62360.h
+++ b/include/linux/regulator/tps62360.h
@@ -32,7 +32,6 @@
* struct tps62360_regulator_platform_data - tps62360 regulator platform data.
*
* @reg_init_data: The regulator init data.
- * @en_force_pwm: Enable force pwm or not.
* @en_discharge: Enable discharge the output capacitor via internal
* register.
* @en_internal_pulldn: internal pull down enable or not.
@@ -45,7 +44,6 @@
*/
struct tps62360_regulator_platform_data {
struct regulator_init_data reg_init_data;
- bool en_force_pwm;
bool en_discharge;
bool en_internal_pulldn;
int vsel0_gpio;
diff --git a/include/linux/tegra_audio.h b/include/linux/tegra_audio.h
index 3975913a5206..ddc9c93498a0 100644
--- a/include/linux/tegra_audio.h
+++ b/include/linux/tegra_audio.h
@@ -76,7 +76,7 @@ struct dam_srate {
#define I2S_MODE_I2S _IOW(TEGRA_AUDIO_MAGIC, 18, unsigned int *)
#ifdef CONFIG_SND_SOC_TEGRA
-extern bool tegra_is_voice_call_active();
+extern bool tegra_is_voice_call_active(void);
#else
static inline bool tegra_is_voice_call_active()
{
diff --git a/include/media/ad5816.h b/include/media/ad5816.h
index bfea25ffaddf..c51417ca472b 100644
--- a/include/media/ad5816.h
+++ b/include/media/ad5816.h
@@ -22,21 +22,19 @@
#include <media/nvc_focus.h>
#include <media/nvc.h>
-typedef enum ad5816_vreg
-{
+typedef enum {
AD5816_VREG_VDD = 0,
AD5816_VREG_VDD_AF,
AD5816_VREG_VDD_I2C
-};
+} ad5816_vreg;
-typedef enum ad5816_gpio_types
-{
+typedef enum {
AD5816_GPIO_RESET = 0,
AD5816_GPIO_I2CMUX,
AD5816_GPIO_GP1,
AD5816_GPIO_GP2,
AD5816_GPIO_GP3
-};
+} ad5816_gpio_types;
struct ad5816_platform_data {
@@ -78,4 +76,4 @@ struct ad5816_pdata_info {
#endif
-/* __AD5816_H__ */ \ No newline at end of file
+/* __AD5816_H__ */
diff --git a/include/media/ov2710.h b/include/media/ov2710.h
index e3d43056d700..aeeaea8849e0 100644
--- a/include/media/ov2710.h
+++ b/include/media/ov2710.h
@@ -27,6 +27,7 @@
#define OV2710_IOCTL_SET_COARSE_TIME _IOW('o', 3, __u32)
#define OV2710_IOCTL_SET_GAIN _IOW('o', 4, __u16)
#define OV2710_IOCTL_GET_STATUS _IOR('o', 5, __u8)
+#define OV2710_IOCTL_SET_GROUP_HOLD _IOW('o', 6, struct ov2710_ae)
struct ov2710_mode {
int xres;
@@ -35,6 +36,16 @@ struct ov2710_mode {
__u32 coarse_time;
__u16 gain;
};
+
+struct ov2710_ae {
+ __u32 frame_length;
+ __u8 frame_length_enable;
+ __u32 coarse_time;
+ __u8 coarse_time_enable;
+ __s32 gain;
+ __u8 gain_enable;
+};
+
#ifdef __KERNEL__
struct ov2710_platform_data {
int (*power_on)(void);
diff --git a/include/video/tegra_dc_ext.h b/include/video/tegra_dc_ext.h
index 76bb34b01af1..8f9d0423f516 100644
--- a/include/video/tegra_dc_ext.h
+++ b/include/video/tegra_dc_ext.h
@@ -211,6 +211,11 @@ struct tegra_dc_ext_status {
__u32 pad[3];
};
+struct tegra_dc_ext_feature {
+ __u32 length;
+ __u32 *entries;
+};
+
#define TEGRA_DC_EXT_SET_NVMAP_FD \
_IOW('D', 0x00, __s32)
@@ -247,6 +252,9 @@ struct tegra_dc_ext_status {
#define TEGRA_DC_EXT_SET_LUT \
_IOW('D', 0x0A, struct tegra_dc_ext_lut)
+#define TEGRA_DC_EXT_GET_FEATURES \
+ _IOW('D', 0x0B, struct tegra_dc_ext_feature)
+
enum tegra_dc_ext_control_output_type {
TEGRA_DC_EXT_DSI,
TEGRA_DC_EXT_LVDS,
diff --git a/sound/soc/codecs/rt5639.c b/sound/soc/codecs/rt5639.c
index c9b14e9f0bc1..13190e21404b 100644
--- a/sound/soc/codecs/rt5639.c
+++ b/sound/soc/codecs/rt5639.c
@@ -105,6 +105,18 @@ static int rt5639_reg_init(struct snd_soc_codec *codec)
}
#endif
+static int rt5639_index_sync(struct snd_soc_codec *codec)
+{
+ int i;
+
+ for (i = 0; i < RT5639_INIT_REG_LEN; i++)
+ if (RT5639_PRIV_INDEX == init_list[i].reg ||
+ RT5639_PRIV_DATA == init_list[i].reg)
+ snd_soc_write(codec, init_list[i].reg,
+ init_list[i].val);
+ return 0;
+}
+
static const u16 rt5639_reg[RT5639_VENDOR_ID2 + 1] = {
[RT5639_RESET] = 0x0008,
[RT5639_SPK_VOL] = 0xc8c8,
@@ -2213,7 +2225,9 @@ static int rt5639_set_bias_level(struct snd_soc_codec *codec,
RT5639_PWR_FV1 | RT5639_PWR_FV2,
RT5639_PWR_FV1 | RT5639_PWR_FV2);
codec->cache_only = false;
+ codec->cache_sync = 1;
snd_soc_cache_sync(codec);
+ rt5639_index_sync(codec);
}
break;
@@ -2311,13 +2325,23 @@ static int rt5639_remove(struct snd_soc_codec *codec)
#ifdef CONFIG_PM
static int rt5639_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
+ rt5639_reset(codec);
rt5639_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static int rt5639_resume(struct snd_soc_codec *codec)
{
+ int ret = 0 ;
+
+ codec->cache_sync = 1;
+ ret = snd_soc_cache_sync(codec);
+ if (ret) {
+ dev_err(codec->dev,"Failed to sync cache: %d\n", ret);
+ return ret;
+ }
rt5639_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
return 0;
}
#else
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 8407c638cf8a..49256e2d151d 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -106,6 +106,18 @@ static int rt5640_reg_init(struct snd_soc_codec *codec)
}
#endif
+static int rt5640_index_sync(struct snd_soc_codec *codec)
+{
+ int i;
+
+ for (i = 0; i < RT5640_INIT_REG_LEN; i++)
+ if (RT5640_PRIV_INDEX == init_list[i].reg ||
+ RT5640_PRIV_DATA == init_list[i].reg)
+ snd_soc_write(codec, init_list[i].reg,
+ init_list[i].val);
+ return 0;
+}
+
static const u16 rt5640_reg[RT5640_VENDOR_ID2 + 1] = {
[RT5640_RESET] = 0x000c,
[RT5640_SPK_VOL] = 0xc8c8,
@@ -2269,7 +2281,9 @@ static int rt5640_set_bias_level(struct snd_soc_codec *codec,
RT5640_PWR_FV1 | RT5640_PWR_FV2,
RT5640_PWR_FV1 | RT5640_PWR_FV2);
codec->cache_only = false;
+ codec->cache_sync = 1;
snd_soc_cache_sync(codec);
+ rt5640_index_sync(codec);
}
break;
@@ -2381,6 +2395,7 @@ static int rt5640_remove(struct snd_soc_codec *codec)
#ifdef CONFIG_PM
static int rt5640_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
+ rt5640_reset(codec);
rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF);
snd_soc_write(codec, RT5640_PWR_ANLG1, 0);
@@ -2389,6 +2404,14 @@ static int rt5640_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int rt5640_resume(struct snd_soc_codec *codec)
{
+ int ret = 0 ;
+
+ codec->cache_sync = 1;
+ ret = snd_soc_cache_sync(codec);
+ if (ret) {
+ dev_err(codec->dev,"Failed to sync cache: %d\n", ret);
+ return ret;
+ }
rt5640_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
index 449359837efb..8be00b840fb5 100644
--- a/sound/soc/tegra/tegra30_i2s.c
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -418,6 +418,10 @@ static int tegra30_i2s_tdm_hw_params(struct snd_pcm_substream *substream,
i2s_client_bits = TEGRA30_AUDIOCIF_BITS_32;
i2s->reg_ctrl |= TEGRA30_I2S_CTRL_BIT_SIZE_32;
break;
+ default:
+ dev_err(dev, "unknown slot_width %d\n",
+ i2s->dsp_config.slot_width);
+ return -EINVAL;
}
val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
diff --git a/sound/soc/tegra/tegra_p1852.c b/sound/soc/tegra/tegra_p1852.c
index 85b4cee30c5f..199bb8046636 100644
--- a/sound/soc/tegra/tegra_p1852.c
+++ b/sound/soc/tegra/tegra_p1852.c
@@ -227,6 +227,9 @@ static __devinit int tegra_p1852_driver_probe(struct platform_device *pdev)
pdata->codec_info[i].codec_dai_name;
tegra_p1852_dai_link[i].name =
pdata->codec_info[i].name;
+ if (pdata->codec_info[i].pcm_driver)
+ tegra_p1852_dai_link[i].platform_name =
+ pdata->codec_info[i].pcm_driver;
}
ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev, card);