diff options
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r-- | arch/arm/mach-tegra/Kconfig | 7 | ||||
-rw-r--r-- | arch/arm/mach-tegra/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-ventana.c | 42 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/tegra_fiq_debugger.h | 30 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra_fiq_debugger.c | 206 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra_i2s_audio.c | 17 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra_spdif_audio.c | 9 |
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) { |