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 | 46 | ||||
-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 | 208 |
5 files changed, 291 insertions, 1 deletions
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 398af59d7e3e..0bd7b41592be 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -66,6 +66,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" + endif config TEGRA_IOVMM_GART diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 22e59f357a92..8872cd54337f 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -13,6 +13,7 @@ obj-y += fuse.o obj-y += tegra_i2s_audio.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_ARCH_TEGRA_2x_SOC) += clock.o diff --git a/arch/arm/mach-tegra/board-ventana.c b/arch/arm/mach-tegra/board-ventana.c index 82e3a22efa3e..60948ad9dba4 100644 --- a/arch/arm/mach-tegra/board-ventana.c +++ b/arch/arm/mach-tegra/board-ventana.c @@ -33,6 +33,7 @@ #include <linux/gpio.h> #include <linux/gpio_keys.h> #include <linux/input.h> +#include <linux/usb/android_composite.h> #include <mach/clk.h> #include <mach/iomap.h> @@ -49,6 +50,7 @@ #include "board-ventana.h" #include "devices.h" #include "gpio-names.h" +#include "fuse.h" static struct plat_serial8250_port debug_uart_platform_data[] = { { @@ -80,6 +82,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_i2c_platform_data ventana_i2c1_platform_data = { .adapter_nr = 0, .bus_count = 1, @@ -165,6 +204,7 @@ static struct platform_device ventana_keys_device = { static struct platform_device *ventana_devices[] __initdata = { &tegra_otg_device, + &androidusb_device, &debug_uart, &pmu_device, &tegra_udc_device, @@ -204,12 +244,16 @@ static int __init ventana_touch_init(void) static void __init tegra_ventana_init(void) { - tegra_common_init(); + char serial[20]; + tegra_common_init(); tegra_clk_init_from_table(ventana_clk_init_table); ventana_pinmux_init(); + snprintf(serial, sizeof(serial), "%llx", tegra_chip_uid()); + andusb_plat.serial_number = kstrdup(serial, GFP_KERNEL); platform_add_devices(ventana_devices, ARRAY_SIZE(ventana_devices)); + ventana_sdhci_init(); ventana_i2c_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..29e3119b0edd --- /dev/null +++ b/arch/arm/mach-tegra/tegra_fiq_debugger.c @@ -0,0 +1,208 @@ +/* + * 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> + +#include <mach/legacy_irq.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); +} |