summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r--arch/arm/mach-tegra/Kconfig7
-rw-r--r--arch/arm/mach-tegra/Makefile1
-rw-r--r--arch/arm/mach-tegra/board-ventana.c42
-rw-r--r--arch/arm/mach-tegra/include/mach/tegra_fiq_debugger.h30
-rw-r--r--arch/arm/mach-tegra/tegra_fiq_debugger.c206
-rw-r--r--arch/arm/mach-tegra/tegra_i2s_audio.c17
-rw-r--r--arch/arm/mach-tegra/tegra_spdif_audio.c9
7 files changed, 312 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index d376c8e22e16..89065de81742 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -209,6 +209,13 @@ config TEGRA_PWM
help
Enable support for the Tegra PWM controller(s).
+config TEGRA_FIQ_DEBUGGER
+ bool "Enable the FIQ serial debugger on Tegra"
+ default y
+ select FIQ_DEBUGGER
+ help
+ Enables the FIQ serial debugger on Tegra"
+
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 79a62f3058ef..7e2bdfbe876f 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -38,6 +38,7 @@ obj-y += mc.o
obj-$(CONFIG_TEGRA_STAT_MON) += tegra2_statmon.o
obj-$(CONFIG_USB_SUPPORT) += usb_phy.o
obj-$(CONFIG_FIQ) += fiq.o
+obj-$(CONFIG_TEGRA_FIQ_DEBUGGER) += tegra_fiq_debugger.o
obj-$(CONFIG_TEGRA_PWM) += pwm.o
obj-$(CONFIG_TEGRA_ARB_SEMAPHORE) += arb_sema.o
diff --git a/arch/arm/mach-tegra/board-ventana.c b/arch/arm/mach-tegra/board-ventana.c
index 845494baf9e5..89a27cb229e9 100644
--- a/arch/arm/mach-tegra/board-ventana.c
+++ b/arch/arm/mach-tegra/board-ventana.c
@@ -34,6 +34,7 @@
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/platform_data/tegra_usb.h>
+#include <linux/usb/android_composite.h>
#include <linux/mfd/tps6586x.h>
#include <linux/memblock.h>
#include <linux/i2c/atmel_mxt_ts.h>
@@ -59,6 +60,7 @@
#include "board-ventana.h"
#include "devices.h"
#include "gpio-names.h"
+#include "fuse.h"
#include "wakeups-t2.h"
#include "pm.h"
@@ -135,6 +137,43 @@ static __initdata struct tegra_clk_init_table ventana_clk_init_table[] = {
{ NULL, NULL, 0, 0},
};
+static char *usb_functions[] = { "mtp" };
+static char *usb_functions_adb[] = { "mtp", "adb" };
+
+static struct android_usb_product usb_products[] = {
+ {
+ .product_id = 0x7102,
+ .num_functions = ARRAY_SIZE(usb_functions),
+ .functions = usb_functions,
+ },
+ {
+ .product_id = 0x7100,
+ .num_functions = ARRAY_SIZE(usb_functions_adb),
+ .functions = usb_functions_adb,
+ },
+};
+
+/* standard android USB platform data */
+static struct android_usb_platform_data andusb_plat = {
+ .vendor_id = 0x0955,
+ .product_id = 0x7100,
+ .manufacturer_name = "NVIDIA",
+ .product_name = "Ventana",
+ .serial_number = NULL,
+ .num_products = ARRAY_SIZE(usb_products),
+ .products = usb_products,
+ .num_functions = ARRAY_SIZE(usb_functions_adb),
+ .functions = usb_functions_adb,
+};
+
+static struct platform_device androidusb_device = {
+ .name = "android_usb",
+ .id = -1,
+ .dev = {
+ .platform_data = &andusb_plat,
+ },
+};
+
static struct tegra_ulpi_config ventana_ehci2_ulpi_phy_config = {
.reset_gpio = TEGRA_GPIO_PV1,
.clk = "cdev2",
@@ -546,9 +585,12 @@ static void __init tegra_ventana_init(void)
ventana_pinmux_init();
ventana_i2c_init();
ventana_uart_init();
+ snprintf(serial, sizeof(serial), "%llx", tegra_chip_uid());
+ andusb_plat.serial_number = kstrdup(serial, GFP_KERNEL);
tegra_ehci2_device.dev.platform_data
= &ventana_ehci2_ulpi_platform_data;
platform_add_devices(ventana_devices, ARRAY_SIZE(ventana_devices));
+
ventana_sdhci_init();
ventana_charge_init();
ventana_regulator_init();
diff --git a/arch/arm/mach-tegra/include/mach/tegra_fiq_debugger.h b/arch/arm/mach-tegra/include/mach/tegra_fiq_debugger.h
new file mode 100644
index 000000000000..4d1a0b54f2ae
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/tegra_fiq_debugger.h
@@ -0,0 +1,30 @@
+/*
+ * linux/arch/arm/mach-tegra/include/mach/tegra_fiq_debugger.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that 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.
+ *
+ */
+
+#ifndef __MACH_TEGRA_FIQ_DEBUGGER_H
+#define __MACH_TEGRA_FIQ_DEBUGGER_H
+
+#ifdef CONFIG_TEGRA_FIQ_DEBUGGER
+void tegra_serial_debug_init(unsigned int base, int irq,
+ struct clk *clk, int signal_irq, int wakeup_irq);
+#else
+static inline void tegra_serial_debug_init(unsigned int base, int irq,
+ struct clk *clk, int signal_irq, int wakeup_irq)
+{
+}
+#endif
+
+#endif
diff --git a/arch/arm/mach-tegra/tegra_fiq_debugger.c b/arch/arm/mach-tegra/tegra_fiq_debugger.c
new file mode 100644
index 000000000000..2a19a214acb5
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra_fiq_debugger.c
@@ -0,0 +1,206 @@
+/*
+ * arch/arm/mach-tegra/fiq_debugger.c
+ *
+ * Serial Debugger Interface for Tegra
+ *
+ * Copyright (C) 2008 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that 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.
+ */
+
+#include <stdarg.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/serial_reg.h>
+#include <linux/slab.h>
+#include <linux/stacktrace.h>
+#include <asm/fiq_debugger.h>
+#include <mach/tegra_fiq_debugger.h>
+#include <mach/system.h>
+#include <mach/fiq.h>
+
+#include <linux/uaccess.h>
+
+struct tegra_fiq_debugger {
+ struct fiq_debugger_pdata pdata;
+ void __iomem *debug_port_base;
+ bool break_seen;
+};
+
+static inline void tegra_write(struct tegra_fiq_debugger *t,
+ unsigned int val, unsigned int off)
+{
+ __raw_writeb(val, t->debug_port_base + off * 4);
+}
+
+static inline unsigned int tegra_read(struct tegra_fiq_debugger *t,
+ unsigned int off)
+{
+ return __raw_readb(t->debug_port_base + off * 4);
+}
+
+static inline unsigned int tegra_read_lsr(struct tegra_fiq_debugger *t)
+{
+ unsigned int lsr;
+
+ lsr = tegra_read(t, UART_LSR);
+ if (lsr & UART_LSR_BI)
+ t->break_seen = true;
+
+ return lsr;
+}
+
+static int debug_port_init(struct platform_device *pdev)
+{
+ struct tegra_fiq_debugger *t;
+ t = container_of(dev_get_platdata(&pdev->dev), typeof(*t), pdata);
+
+ if (tegra_read(t, UART_LSR) & UART_LSR_DR)
+ (void)tegra_read(t, UART_RX);
+ /* enable rx and lsr interrupt */
+ tegra_write(t, UART_IER_RLSI | UART_IER_RDI, UART_IER);
+ /* interrupt on every character */
+ tegra_write(t, 0, UART_IIR);
+
+ return 0;
+}
+
+static int debug_getc(struct platform_device *pdev)
+{
+ unsigned int lsr;
+ struct tegra_fiq_debugger *t;
+ t = container_of(dev_get_platdata(&pdev->dev), typeof(*t), pdata);
+
+ lsr = tegra_read_lsr(t);
+
+ if (lsr & UART_LSR_BI || t->break_seen) {
+ t->break_seen = false;
+ return FIQ_DEBUGGER_BREAK;
+ }
+
+ if (lsr & UART_LSR_DR)
+ return tegra_read(t, UART_RX);
+
+ return FIQ_DEBUGGER_NO_CHAR;
+}
+
+static void debug_putc(struct platform_device *pdev, unsigned int c)
+{
+ struct tegra_fiq_debugger *t;
+ t = container_of(dev_get_platdata(&pdev->dev), typeof(*t), pdata);
+
+ while (!(tegra_read_lsr(t) & UART_LSR_THRE))
+ cpu_relax();
+
+ tegra_write(t, c, UART_TX);
+}
+
+static void debug_flush(struct platform_device *pdev)
+{
+ struct tegra_fiq_debugger *t;
+ t = container_of(dev_get_platdata(&pdev->dev), typeof(*t), pdata);
+
+ while (!(tegra_read_lsr(t) & UART_LSR_TEMT))
+ cpu_relax();
+}
+
+static void fiq_enable(struct platform_device *pdev, unsigned int irq, bool on)
+{
+ if (on)
+ tegra_fiq_enable(irq);
+ else
+ tegra_fiq_disable(irq);
+}
+
+static int tegra_fiq_debugger_id;
+
+void tegra_serial_debug_init(unsigned int base, int irq,
+ struct clk *clk, int signal_irq, int wakeup_irq)
+{
+ struct tegra_fiq_debugger *t;
+ struct platform_device *pdev;
+ struct resource *res;
+ int res_count;
+
+ t = kzalloc(sizeof(struct tegra_fiq_debugger), GFP_KERNEL);
+ if (!t) {
+ pr_err("Failed to allocate for fiq debugger\n");
+ return;
+ }
+
+ t->pdata.uart_init = debug_port_init;
+ t->pdata.uart_getc = debug_getc;
+ t->pdata.uart_putc = debug_putc;
+ t->pdata.uart_flush = debug_flush;
+ t->pdata.fiq_enable = fiq_enable;
+
+ t->debug_port_base = ioremap(base, PAGE_SIZE);
+ if (!t->debug_port_base) {
+ pr_err("Failed to ioremap for fiq debugger\n");
+ goto out1;
+ }
+
+ res = kzalloc(sizeof(struct resource) * 3, GFP_KERNEL);
+ if (!res) {
+ pr_err("Failed to alloc fiq debugger resources\n");
+ goto out2;
+ }
+
+ pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
+ if (!pdev) {
+ pr_err("Failed to alloc fiq debugger platform device\n");
+ goto out3;
+ };
+
+ res[0].flags = IORESOURCE_IRQ;
+ res[0].start = irq;
+ res[0].end = irq;
+ res[0].name = "fiq";
+
+ res[1].flags = IORESOURCE_IRQ;
+ res[1].start = signal_irq;
+ res[1].end = signal_irq;
+ res[1].name = "signal";
+ res_count = 2;
+
+ if (wakeup_irq >= 0) {
+ res[2].flags = IORESOURCE_IRQ;
+ res[2].start = wakeup_irq;
+ res[2].end = wakeup_irq;
+ res[2].name = "wakeup";
+ res_count++;
+ }
+
+ pdev->name = "fiq_debugger";
+ pdev->id = tegra_fiq_debugger_id++;
+ pdev->dev.platform_data = &t->pdata;
+ pdev->resource = res;
+ pdev->num_resources = res_count;
+
+ if (platform_device_register(pdev)) {
+ pr_err("Failed to register fiq debugger\n");
+ goto out4;
+ }
+
+ return;
+
+out4:
+ kfree(pdev);
+out3:
+ kfree(res);
+out2:
+ iounmap(t->debug_port_base);
+out1:
+ kfree(t);
+}
diff --git a/arch/arm/mach-tegra/tegra_i2s_audio.c b/arch/arm/mach-tegra/tegra_i2s_audio.c
index 1368d173a2ba..fc790066694a 100644
--- a/arch/arm/mach-tegra/tegra_i2s_audio.c
+++ b/arch/arm/mach-tegra/tegra_i2s_audio.c
@@ -44,6 +44,7 @@
#include <linux/io.h>
#include <linux/ktime.h>
#include <linux/sysfs.h>
+#include <linux/wakelock.h>
#include <linux/delay.h>
#include <linux/tegra_audio.h>
#include <linux/pm.h>
@@ -89,6 +90,8 @@ struct audio_stream {
spinlock_t dma_req_lock;
struct work_struct allow_suspend_work;
+ struct wake_lock wake_lock;
+ char wake_lock_name[100];
};
/* per i2s controller */
@@ -199,6 +202,7 @@ static inline void prevent_suspend(struct audio_stream *as)
{
pr_debug("%s\n", __func__);
cancel_work_sync(&as->allow_suspend_work);
+ wake_lock(&as->wake_lock);
}
static void allow_suspend_worker(struct work_struct *w)
@@ -206,6 +210,7 @@ static void allow_suspend_worker(struct work_struct *w)
struct audio_stream *as = container_of(w,
struct audio_stream, allow_suspend_work);
pr_debug("%s\n", __func__);
+ wake_unlock(&as->wake_lock);
}
static inline void allow_suspend(struct audio_stream *as)
@@ -1822,6 +1827,12 @@ static int tegra_audio_probe(struct platform_device *pdev)
INIT_WORK(&state->out.allow_suspend_work, allow_suspend_worker);
+ snprintf(state->out.wake_lock_name,
+ sizeof(state->out.wake_lock_name),
+ "i2s.%d-audio-out", state->pdev->id);
+ wake_lock_init(&state->out.wake_lock, WAKE_LOCK_SUSPEND,
+ state->out.wake_lock_name);
+
rc = setup_misc_device(&state->misc_out,
&tegra_audio_out_fops,
"audio%d_out", state->pdev->id);
@@ -1858,6 +1869,12 @@ static int tegra_audio_probe(struct platform_device *pdev)
INIT_WORK(&state->in.allow_suspend_work, allow_suspend_worker);
+ snprintf(state->in.wake_lock_name,
+ sizeof(state->in.wake_lock_name),
+ "i2s.%d-audio-in", state->pdev->id);
+ wake_lock_init(&state->in.wake_lock, WAKE_LOCK_SUSPEND,
+ state->in.wake_lock_name);
+
rc = setup_misc_device(&state->misc_in,
&tegra_audio_in_fops,
"audio%d_in", state->pdev->id);
diff --git a/arch/arm/mach-tegra/tegra_spdif_audio.c b/arch/arm/mach-tegra/tegra_spdif_audio.c
index c23ebdf2fe1f..3765633606cd 100644
--- a/arch/arm/mach-tegra/tegra_spdif_audio.c
+++ b/arch/arm/mach-tegra/tegra_spdif_audio.c
@@ -43,6 +43,7 @@
#include <linux/io.h>
#include <linux/ktime.h>
#include <linux/sysfs.h>
+#include <linux/wakelock.h>
#include <linux/delay.h>
#include <linux/tegra_audio.h>
#include <linux/pm.h>
@@ -83,6 +84,8 @@ struct audio_stream {
spinlock_t dma_req_lock;
struct work_struct allow_suspend_work;
+ struct wake_lock wake_lock;
+ char wake_lock_name[100];
};
struct audio_driver_state {
@@ -147,6 +150,7 @@ static inline void prevent_suspend(struct audio_stream *as)
{
pr_debug("%s\n", __func__);
cancel_work_sync(&as->allow_suspend_work);
+ wake_lock(&as->wake_lock);
}
static void allow_suspend_worker(struct work_struct *w)
@@ -154,6 +158,7 @@ static void allow_suspend_worker(struct work_struct *w)
struct audio_stream *as = container_of(w,
struct audio_stream, allow_suspend_work);
pr_debug("%s\n", __func__);
+ wake_unlock(&as->wake_lock);
}
static inline void allow_suspend(struct audio_stream *as)
@@ -1104,6 +1109,10 @@ static int tegra_spdif_probe(struct platform_device *pdev)
return rc;
INIT_WORK(&state->out.allow_suspend_work, allow_suspend_worker);
+ snprintf(state->out.wake_lock_name, sizeof(state->out.wake_lock_name),
+ "tegra-audio-spdif");
+ wake_lock_init(&state->out.wake_lock, WAKE_LOCK_SUSPEND,
+ state->out.wake_lock_name);
if (request_irq(state->irq, spdif_interrupt,
IRQF_DISABLED, state->pdev->name, state) < 0) {