Updates for Tegra support in 2.6.39
Subsystems (3)
v4 cover Updates for Tegra support in 2.6.39
This is a repost of the same series with the suspend and idle support dropped for now while the necessary changes to the gic, l2x0, and init notifiers are discussed. If there are no further comments, I will push these to tegra/for-next.
arch/arm/configs/tegra_defconfig | 123 +++++++++++ arch/arm/mach-tegra/Makefile | 1 + arch/arm/mach-tegra/board.h | 2 + arch/arm/mach-tegra/common.c | 17 ++- arch/arm/mach-tegra/cpu-tegra.c | 75 ++++++-- arch/arm/mach-tegra/dma.c | 198 ++++++++++-------- arch/arm/mach-tegra/gpio.c | 1 + arch/arm/mach-tegra/include/mach/debug-macro.S | 25 +-- arch/arm/mach-tegra/include/mach/iomap.h | 69 +++++- arch/arm/mach-tegra/include/mach/irqs.h | 14 +- arch/arm/mach-tegra/include/mach/legacy_irq.h | 4 + arch/arm/mach-tegra/include/mach/pinmux-t2.h | 10 + arch/arm/mach-tegra/include/mach/powergate.h | 40 ++++ arch/arm/mach-tegra/include/mach/suspend.h | 38 ++++ arch/arm/mach-tegra/include/mach/system.h | 10 +- arch/arm/mach-tegra/include/mach/uncompress.h | 18 +-- arch/arm/mach-tegra/irq.c | 186 ++++++++--------- arch/arm/mach-tegra/legacy_irq.c | 109 ++++++++++- arch/arm/mach-tegra/pinmux-t2-tables.c | 26 ++- arch/arm/mach-tegra/powergate.c | 212 +++++++++++++++++++ arch/arm/mach-tegra/tegra2_clocks.c | 264 ++++++++++++++++++++++-- arch/arm/mach-tegra/timer.c | 61 ++++++- 22 files changed, 1212 insertions(+), 291 deletions(-)
PATCH v4 1/15 ARM: tegra: Centralize macros to define debug uart base
--- arch/arm/mach-tegra/include/mach/debug-macro.S | 25 ++++------------------- arch/arm/mach-tegra/include/mach/iomap.h | 14 +++++++++++++ arch/arm/mach-tegra/include/mach/uncompress.h | 18 +--------------- 3 files changed, 21 insertions(+), 36 deletions(-)
arch/arm/mach-tegra/include/mach/debug-macro.S +5 -20
@@ -19,30 +19,15 @@ */ #include <mach/io.h> +#include <mach/iomap.h> .macro addruart, rp, rv ldr \rp, =IO_APB_PHYS @ physical ldr \rv, =IO_APB_VIRT @ virtual -#if defined(CONFIG_TEGRA_DEBUG_UART_NONE) -#error "A debug UART must be selected in the kernel config to use DEBUG_LL" -#elif defined(CONFIG_TEGRA_DEBUG_UARTA) - orr \rp, \rp, #0x6000 - orr \rv, \rv, #0x6000 -#elif defined(CONFIG_TEGRA_DEBUG_UARTB) - orr \rp, \rp, #0x6000 - orr \rp, \rp, #0x40 - orr \rv, \rv, #0x6000 - orr \rv, \rv, #0x40 -#elif defined(CONFIG_TEGRA_DEBUG_UARTC) - orr \rp, \rp, #0x6200 - orr \rv, \rv, #0x6200 -#elif defined(CONFIG_TEGRA_DEBUG_UARTD) - orr \rp, \rp, #0x6300 - orr \rv, \rv, #0x6300 -#elif defined(CONFIG_TEGRA_DEBUG_UARTE) - orr \rp, \rp, #0x6400 - orr \rv, \rv, #0x6400 -#endif + orr \rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF) + orr \rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF00) + orr \rv, \rv, #(TEGRA_DEBUG_UART_BASE & 0xFF) + orr \rv, \rv, #(TEGRA_DEBUG_UART_BASE & 0xFF00) .endm #define UART_SHIFT 2
arch/arm/mach-tegra/include/mach/iomap.h +14 -0
@@ -221,4 +221,18 @@#define TEGRA_SDMMC4_BASE 0xC8000600#define TEGRA_SDMMC4_SIZE SZ_512 +#if defined(CONFIG_TEGRA_DEBUG_UART_NONE ) +# define TEGRA_DEBUG_UART_BASE 0 +#elif defined(CONFIG_TEGRA_DEBUG_UARTA ) +# define TEGRA_DEBUG_UART_BASE TEGRA_UARTA_BASE +#elif defined(CONFIG_TEGRA_DEBUG_UARTB ) +# define TEGRA_DEBUG_UART_BASE TEGRA_UARTB_BASE +#elif defined(CONFIG_TEGRA_DEBUG_UARTC ) +# define TEGRA_DEBUG_UART_BASE TEGRA_UARTC_BASE +#elif defined(CONFIG_TEGRA_DEBUG_UARTD ) +# define TEGRA_DEBUG_UART_BASE TEGRA_UARTD_BASE +#elif defined(CONFIG_TEGRA_DEBUG_UARTE ) +# define TEGRA_DEBUG_UART_BASE TEGRA_UARTE_BASE +#endif +#endif
arch/arm/mach-tegra/include/mach/uncompress.h +2 -16
@@ -26,23 +26,9 @@#include <mach/iomap.h> -#if defined(CONFIG_TEGRA_DEBUG_UARTA ) -#define DEBUG_UART_BASE TEGRA_UARTA_BASE -#elif defined(CONFIG_TEGRA_DEBUG_UARTB ) -#define DEBUG_UART_BASE TEGRA_UARTB_BASE -#elif defined(CONFIG_TEGRA_DEBUG_UARTC ) -#define DEBUG_UART_BASE TEGRA_UARTC_BASE -#elif defined(CONFIG_TEGRA_DEBUG_UARTD ) -#define DEBUG_UART_BASE TEGRA_UARTD_BASE -#elif defined(CONFIG_TEGRA_DEBUG_UARTE ) -#define DEBUG_UART_BASE TEGRA_UARTE_BASE -#else -#define DEBUG_UART_BASE NULL -#endif -static void putc (int c) { -volatile u8 *uart = (volatile u8 *)DEBUG_UART_BASE ; +volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE ;int shift =2 ;if (uart ==NULL )
@@ -59,7 +45,7 @@ static inline void flush(void)static inline void arch_decomp_setup (void ) { -volatile u8 *uart = (volatile u8 *)DEBUG_UART_BASE ; +volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE ;int shift =2 ;if (uart ==NULL )
Signature · 1 line
1.7.3.1
PATCH v4 2/15 ARM: tegra: Add api to control internal powergating
In reply to Colin Cross--- arch/arm/mach-tegra/Makefile | 1 + arch/arm/mach-tegra/include/mach/powergate.h | 40 +++++ arch/arm/mach-tegra/powergate.c | 212 ++++++++++++++++++++++++++ 3 files changed, 253 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-tegra/include/mach/powergate.h create mode 100644 arch/arm/mach-tegra/powergate.c
arch/arm/mach-tegra/Makefile +1 -0
@@ -5,6 +5,7 @@ obj-y += clock.o obj-y += timer.o obj-y += gpio.o obj-y += pinmux.o +obj-y += powergate.o obj-y += fuse.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clock.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o
arch/arm/mach-tegra/include/mach/powergate.h new file +40 -0
@@ -0,0 +1,40 @@ +/* +* drivers/regulator/tegra-regulator.c +* +* Copyright (c) 2010 Google, Inc +* +* Author: +* Colin Cross <[email protected]> +* +* 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_POWERGATE_H_ +#define _MACH_TEGRA_POWERGATE_H_ + +#define TEGRA_POWERGATE_CPU 0 +#define TEGRA_POWERGATE_3D 1 +#define TEGRA_POWERGATE_VENC 2 +#define TEGRA_POWERGATE_PCIE 3 +#define TEGRA_POWERGATE_VDEC 4 +#define TEGRA_POWERGATE_L2 5 +#define TEGRA_POWERGATE_MPE 6 +#define TEGRA_NUM_POWERGATE 7 + +int tegra_powergate_power_on (int id); +int tegra_powergate_power_off (int id); +bool tegra_powergate_is_powered (int id); +int tegra_powergate_remove_clamping (int id); + +/* Must be called with clk disabled, and returns with clk enabled */ +int tegra_powergate_sequence_power_up (int id,struct clk *clk); + +#endif /* _MACH_TEGRA_POWERGATE_H_ */
arch/arm/mach-tegra/powergate.c new file +212 -0
212 lines not on this page · raw message
Signature · 1 line
1.7.3.1
PATCH v4 3/15 ARM: tegra: irqs: Update irq list
In reply to Colin CrossFixes typo in INT_CPU1_PMU_INTR (original fix from Will Deacon) Adds board irqs
--- arch/arm/mach-tegra/include/mach/irqs.h | 14 +++++++++++--- 1 files changed, 11 insertions(+), 3 deletions(-)
arch/arm/mach-tegra/include/mach/irqs.h +11 -3
@@ -88,7 +88,7 @@#define INT_SYS_STATS_MON (INT_SEC_BASE + 22)#define INT_GPIO5 (INT_SEC_BASE + 23)#define INT_CPU0_PMU_INTR (INT_SEC_BASE + 24) -#define INT_CPU2_PMU_INTR (INT_SEC_BASE + 25) +#define INT_CPU1_PMU_INTR (INT_SEC_BASE + 25)#define INT_SEC_RES_26 (INT_SEC_BASE + 26)#define INT_S_LINK1 (INT_SEC_BASE + 27)#define INT_APB_DMA_COP (INT_SEC_BASE + 28)
@@ -166,10 +166,18 @@#define INT_QUAD_RES_30 (INT_QUAD_BASE + 30)#define INT_QUAD_RES_31 (INT_QUAD_BASE + 31) -#define INT_GPIO_BASE (INT_QUAD_BASE + 32) +#define INT_MAIN_NR (INT_QUAD_BASE + 32 - INT_PRI_BASE) + +#define INT_GPIO_BASE (INT_PRI_BASE + INT_MAIN_NR) +#define INT_GPIO_NR (28 * 8) -#define NR_IRQS (INT_GPIO_BASE + INT_GPIO_NR) +#define TEGRA_NR_IRQS (INT_GPIO_BASE + INT_GPIO_NR) + +#define INT_BOARD_BASE TEGRA_NR_IRQS +#define NR_BOARD_IRQS 32 + +#define NR_IRQS (INT_BOARD_BASE + NR_BOARD_IRQS)#endif #endif
Signature · 1 line
1.7.3.1
PATCH v4 4/15 ARM: tegra: Add prototypes for subsystem suspend functions
In reply to Colin Cross--- arch/arm/mach-tegra/dma.c | 1 + arch/arm/mach-tegra/gpio.c | 1 + arch/arm/mach-tegra/include/mach/suspend.h | 38 ++++++++++++++++++++++++++++ arch/arm/mach-tegra/irq.c | 1 + arch/arm/mach-tegra/pinmux-t2-tables.c | 1 + arch/arm/mach-tegra/tegra2_clocks.c | 1 + arch/arm/mach-tegra/timer.c | 1 + 7 files changed, 44 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-tegra/include/mach/suspend.h
arch/arm/mach-tegra/dma.c +1 -0
@@ -30,6 +30,7 @@#include <mach/dma.h> #include <mach/irqs.h> #include <mach/iomap.h> +#include <mach/suspend.h> #define APB_DMA_GEN 0x000#define GEN_ENABLE (1<<31)
arch/arm/mach-tegra/gpio.c +1 -0
@@ -25,6 +25,7 @@#include <linux/gpio.h> #include <mach/iomap.h> +#include <mach/suspend.h> #define GPIO_BANK (x) ((x) >> 5)#define GPIO_PORT (x) (((x) >> 3) & 0x3)
arch/arm/mach-tegra/include/mach/suspend.h new file +38 -0
@@ -0,0 +1,38 @@ +/* +* arch/arm/mach-tegra/include/mach/suspend.h +* +* Copyright (C) 2010 Google, Inc. +* +* Author: +* Colin Cross <[email protected]> +* +* 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_SUSPEND_H_ +#define _MACH_TEGRA_SUSPEND_H_ + +void tegra_pinmux_suspend (void ); +void tegra_irq_suspend (void ); +void tegra_gpio_suspend (void ); +void tegra_clk_suspend (void ); +void tegra_dma_suspend (void ); +void tegra_timer_suspend (void ); + +void tegra_pinmux_resume (void ); +void tegra_irq_resume (void ); +void tegra_gpio_resume (void ); +void tegra_clk_resume (void ); +void tegra_dma_resume (void ); +void tegra_timer_resume (void ); + +#endif /* _MACH_TEGRA_SUSPEND_H_ */
arch/arm/mach-tegra/irq.c +1 -0
@@ -26,6 +26,7 @@#include <asm/hardware/gic.h> #include <mach/iomap.h> +#include <mach/suspend.h> #include "board.h"
arch/arm/mach-tegra/pinmux-t2-tables.c +1 -0
@@ -29,6 +29,7 @@#include <mach/iomap.h> #include <mach/pinmux.h> +#include <mach/suspend.h> #define DRIVE_PINGROUP (pg_name, r) \ [TEGRA_DRIVE_PINGROUP_ ## pg_name] = { \
arch/arm/mach-tegra/tegra2_clocks.c +1 -0
@@ -27,6 +27,7 @@#include <linux/clkdev.h> #include <mach/iomap.h> +#include <mach/suspend.h> #include "clock.h" #include "fuse.h"
arch/arm/mach-tegra/timer.c +1 -0
@@ -33,6 +33,7 @@#include <mach/iomap.h> #include <mach/irqs.h> +#include <mach/suspend.h> #include "board.h" #include "clock.h"
Signature · 1 line
1.7.3.1
PATCH v4 5/15 ARM: tegra: clock: Suspend fixes, and add new clocks
In reply to Colin CrossSave and restore pll and osc state during suspend
Add digital audio clocks
Update clk dev associations
Correct max clock frequencies
Add pll_p as additional cpu clock state
Add values to plld table
Fix register offset for sdmmc4 clock
Add blink timer to tegra2_clocks
--- arch/arm/mach-tegra/tegra2_clocks.c | 263 ++++++++++++++++++++++++++++++++--- 1 files changed, 244 insertions(+), 19 deletions(-)
arch/arm/mach-tegra/tegra2_clocks.c +244 -19
@@ -52,7 +52,7 @@#define OSC_CTRL_OSC_FREQ_19_2MHZ (1<<30)#define OSC_CTRL_OSC_FREQ_12MHZ (2<<30)#define OSC_CTRL_OSC_FREQ_26MHZ (3<<30) -#define OSC_CTRL_MASK 0x3f2 +#define OSC_CTRL_MASK (0x3f2 | OSC_CTRL_OSC_FREQ_MASK)#define OSC_FREQ_DET 0x58#define OSC_FREQ_DET_TRIG (1<<31)
@@ -135,12 +135,29 @@#define BUS_CLK_DISABLE (1<<3)#define BUS_CLK_DIV_MASK 0x3 +#define PMC_CTRL 0x0 +#define PMC_CTRL_BLINK_ENB (1 << 7) + +#define PMC_DPD_PADS_ORIDE 0x1c +#define PMC_DPD_PADS_ORIDE_BLINK_ENB (1 << 20) + +#define PMC_BLINK_TIMER_DATA_ON_SHIFT 0 +#define PMC_BLINK_TIMER_DATA_ON_MASK 0x7fff +#define PMC_BLINK_TIMER_ENB (1 << 15) +#define PMC_BLINK_TIMER_DATA_OFF_SHIFT 16 +#define PMC_BLINK_TIMER_DATA_OFF_MASK 0xffff +static void __iomem *reg_clk_base =IO_ADDRESS (TEGRA_CLK_RESET_BASE ); +static void __iomem *reg_pmc_base =IO_ADDRESS (TEGRA_PMC_BASE );#define clk_writel (value, reg) \ __raw_writel(value, (u32)reg_clk_base + (reg))#define clk_readl (reg) \ __raw_readl((u32)reg_clk_base + (reg)) +#define pmc_writel (value, reg) \ + __raw_writel(value, (u32)reg_pmc_base + (reg)) +#define pmc_readl (reg) \ + __raw_readl((u32)reg_pmc_base + (reg))unsigned long clk_measure_input_freq (void ) {
@@ -358,6 +375,9 @@ static int tegra2_cpu_clk_set_rate(struct clk *c, unsigned long rate)return ret; } +if (rate == c->backup->rate) + goto out; + ret =clk_set_rate_locked (c->main, rate);if (ret) {pr_err ("Failed to change cpu pll to %lu\n" , rate);
@@ -370,6 +390,7 @@ static int tegra2_cpu_clk_set_rate(struct clk *c, unsigned long rate)return ret; } +out:return 0 ; }
@@ -429,6 +450,87 @@ static struct clk_ops tegra_bus_ops = { .set_rate = tegra2_bus_clk_set_rate, }; +/* Blink output functions */ + +static void tegra2_blink_clk_init (struct clk *c) +{ +u32 val; + + val =pmc_readl (PMC_CTRL ); + c->state = (val &PMC_CTRL_BLINK_ENB ) ?ON :OFF ; + c->mul =1 ; + val =pmc_readl (c->reg); + +if (val &PMC_BLINK_TIMER_ENB ) { +unsigned int on_off; + + on_off = (val >>PMC_BLINK_TIMER_DATA_ON_SHIFT ) & +PMC_BLINK_TIMER_DATA_ON_MASK ; + val >>=PMC_BLINK_TIMER_DATA_OFF_SHIFT ; + val &=PMC_BLINK_TIMER_DATA_OFF_MASK ; + on_off += val; +/* each tick in the blink timer is 4 32KHz clocks */ + c->div = on_off *4 ; + }else { + c->div =1 ; + } +} + +static int tegra2_blink_clk_enable (struct clk *c) +{ +u32 val; + + val =pmc_readl (PMC_DPD_PADS_ORIDE ); +pmc_writel (val |PMC_DPD_PADS_ORIDE_BLINK_ENB ,PMC_DPD_PADS_ORIDE ); + + val =pmc_readl (PMC_CTRL ); +pmc_writel (val |PMC_CTRL_BLINK_ENB ,PMC_CTRL ); + +return 0 ; +} + +static void tegra2_blink_clk_disable (struct clk *c) +{ +u32 val; + + val =pmc_readl (PMC_CTRL ); +pmc_writel (val & ~PMC_CTRL_BLINK_ENB ,PMC_CTRL ); + + val =pmc_readl (PMC_DPD_PADS_ORIDE ); +pmc_writel (val & ~PMC_DPD_PADS_ORIDE_BLINK_ENB ,PMC_DPD_PADS_ORIDE ); +} + +static int tegra2_blink_clk_set_rate (struct clk *c,unsigned long rate) +{ +if (rate >= c->parent->rate) { + c->div =1 ; +pmc_writel (0 , c->reg); + }else { +unsigned int on_off; +u32 val; + + on_off =DIV_ROUND_UP (c->parent->rate /8 , rate); + c->div = on_off *8 ; + + val = (on_off &PMC_BLINK_TIMER_DATA_ON_MASK ) << +PMC_BLINK_TIMER_DATA_ON_SHIFT ; + on_off &=PMC_BLINK_TIMER_DATA_OFF_MASK ; + on_off <<=PMC_BLINK_TIMER_DATA_OFF_SHIFT ; + val |= on_off; + val |=PMC_BLINK_TIMER_ENB ; +pmc_writel (val, c->reg); + } + +return 0 ; +} + +static struct clk_ops tegra_blink_clk_ops = { + .init = &tegra2_blink_clk_init, + .enable = &tegra2_blink_clk_enable, + .disable = &tegra2_blink_clk_disable, + .set_rate = &tegra2_blink_clk_set_rate, +}; +/* PLL Functions */ static int tegra2_pll_clk_wait_for_lock (struct clk *c) {
@@ -929,6 +1031,7 @@ static struct clk_ops tegra_clk_double_ops = { .set_rate = &tegra2_clk_double_set_rate, }; +/* Audio sync clock ops */ static void tegra2_audio_sync_clk_init (struct clk *c) {int source;
@@ -1007,6 +1110,37 @@ static struct clk_ops tegra_audio_sync_clk_ops = { .set_parent = tegra2_audio_sync_clk_set_parent, }; +/* cdev1 and cdev2 (dap_mclk1 and dap_mclk2) ops */ + +static void tegra2_cdev_clk_init (struct clk *c) +{ +/* We could un-tristate the cdev1 or cdev2 pingroup here; this is +* currently done in the pinmux code. */ + c->state =ON ; +if (!(clk_readl (CLK_OUT_ENB +PERIPH_CLK_TO_ENB_REG (c)) & +PERIPH_CLK_TO_ENB_BIT (c))) + c->state =OFF ; +} + +static int tegra2_cdev_clk_enable (struct clk *c) +{ +clk_writel (PERIPH_CLK_TO_ENB_BIT (c), +CLK_OUT_ENB_SET +PERIPH_CLK_TO_ENB_SET_REG (c)); +return 0 ; +} + +static void tegra2_cdev_clk_disable (struct clk *c) +{ +clk_writel (PERIPH_CLK_TO_ENB_BIT (c), +CLK_OUT_ENB_CLR +PERIPH_CLK_TO_ENB_SET_REG (c)); +} + +static struct clk_ops tegra_cdev_clk_ops = { + .init = &tegra2_cdev_clk_init, + .enable = &tegra2_cdev_clk_enable, + .disable = &tegra2_cdev_clk_disable, +}; +/* Clock definitions */ static struct clk tegra_clk_32k = { .name ="clk_32k" ,
@@ -1227,10 +1361,21 @@ static struct clk tegra_pll_a_out0 = { };static struct clk_pll_table tegra_pll_d_table[] = { + {12000000 ,216000000 ,216 ,12 ,1 ,4 }, + {13000000 ,216000000 ,216 ,13 ,1 ,4 }, + {19200000 ,216000000 ,135 ,12 ,1 ,3 }, + {26000000 ,216000000 ,216 ,26 ,1 ,4 }, + + {12000000 ,594000000 ,594 ,12 ,1 ,8 }, + {13000000 ,594000000 ,594 ,13 ,1 ,8 }, + {19200000 ,594000000 ,495 ,16 ,1 ,8 }, + {26000000 ,594000000 ,594 ,26 ,1 ,8 }, + {12000000 ,1000000000 ,1000 ,12 ,1 ,12 }, {13000000 ,1000000000 ,1000 ,13 ,1 ,12 }, {19200000 ,1000000000 ,625 ,12 ,1 ,8 }, {26000000 ,1000000000 ,1000 ,26 ,1 ,12 }, + {0 ,0 ,0 ,0 ,0 ,0 }, };
@@ -1372,6 +1517,24 @@ static struct clk tegra_clk_d = { .max_rate = 52000000, }; +/* dap_mclk1, belongs to the cdev1 pingroup. */ +static struct clk tegra_dev1_clk = { + .name ="clk_dev1" , + .ops = &tegra_cdev_clk_ops, + .clk_num =94 , + .rate =26000000 , + .max_rate =26000000 , +}; + +/* dap_mclk2, belongs to the cdev2 pingroup. */ +static struct clk tegra_dev2_clk = { + .name ="clk_dev2" , + .ops = &tegra_cdev_clk_ops, + .clk_num =93 , + .rate =26000000 , + .max_rate =26000000 , +}; +/* initialized before peripheral clocks */ static struct clk_mux_sel mux_audio_sync_clk[8 +1 ]; static const struct audio_sources {
@@ -1486,7 +1649,7 @@ static struct clk tegra_clk_virtual_cpu = { .name = "cpu", .parent = &tegra_clk_cclk, .main = &tegra_pll_x, - .backup = &tegra_clk_m, + .backup = &tegra_pll_p, .ops = &tegra_cpu_ops, .max_rate = 1000000000, .dvfs = &tegra_dvfs_virtual_cpu_dvfs,
@@ -1512,6 +1675,14 @@ static struct clk tegra_clk_pclk = { .max_rate = 108000000, }; +static struct clk tegra_clk_blink = { + .name ="blink" , + .parent = &tegra_clk_32k, + .reg =0x40 , + .ops = &tegra_blink_clk_ops, + .max_rate =32768 , +}; +static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = { { .input = &tegra_pll_m, .value =0 }, { .input = &tegra_pll_c, .value =1 },
@@ -1626,7 +1797,7 @@ struct clk tegra_periph_clks[] = {PERIPH_CLK ("sdmmc1" ,"sdhci-tegra.0" ,NULL ,14 ,0x150 ,52000000 , mux_pllp_pllc_pllm_clkm,MUX |DIV_U71 ),/* scales with voltage */ PERIPH_CLK ("sdmmc2" ,"sdhci-tegra.1" ,NULL ,9 ,0x154 ,52000000 , mux_pllp_pllc_pllm_clkm,MUX |DIV_U71 ),/* scales with voltage */ PERIPH_CLK ("sdmmc3" ,"sdhci-tegra.2" ,NULL ,69 ,0x1bc ,52000000 , mux_pllp_pllc_pllm_clkm,MUX |DIV_U71 ),/* scales with voltage */ -PERIPH_CLK ("sdmmc4" ,"sdhci-tegra.3" ,NULL ,15 ,0x160 ,52000000 , mux_pllp_pllc_pllm_clkm,MUX |DIV_U71 ),/* scales with voltage */ +PERIPH_CLK ("sdmmc4" ,"sdhci-tegra.3" ,NULL ,15 ,0x164 ,52000000 , mux_pllp_pllc_pllm_clkm,MUX |DIV_U71 ),/* scales with voltage */ PERIPH_CLK ("vde" ,"vde" ,NULL ,61 ,0x1c8 ,250000000 , mux_pllp_pllc_pllm_clkm,MUX |DIV_U71 ),/* scales with voltage and process_id */ PERIPH_CLK("csite", "csite", NULL, 73, 0x1d4, 144000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* max rate ??? *//* FIXME: what is la? */
@@ -1642,34 +1813,34 @@ struct clk tegra_periph_clks[] = {PERIPH_CLK ("i2c2_i2c" ,"tegra-i2c.1" ,"i2c" ,0 ,0 ,72000000 , mux_pllp_out3,0 ),PERIPH_CLK ("i2c3_i2c" ,"tegra-i2c.2" ,"i2c" ,0 ,0 ,72000000 , mux_pllp_out3,0 ),PERIPH_CLK ("dvc_i2c" ,"tegra-i2c.3" ,"i2c" ,0 ,0 ,72000000 , mux_pllp_out3,0 ), -PERIPH_CLK ("uarta" ,"uart.0" ,NULL ,6 ,0x178 ,216000000 , mux_pllp_pllc_pllm_clkm,MUX ), -PERIPH_CLK ("uartb" ,"uart.1" ,NULL ,7 ,0x17c ,216000000 , mux_pllp_pllc_pllm_clkm,MUX ), -PERIPH_CLK ("uartc" ,"uart.2" ,NULL ,55 ,0x1a0 ,216000000 , mux_pllp_pllc_pllm_clkm,MUX ), -PERIPH_CLK ("uartd" ,"uart.3" ,NULL ,65 ,0x1c0 ,216000000 , mux_pllp_pllc_pllm_clkm,MUX ), -PERIPH_CLK ("uarte" ,"uart.4" ,NULL ,66 ,0x1c4 ,216000000 , mux_pllp_pllc_pllm_clkm,MUX ), +PERIPH_CLK ("uarta" ,"uart.0" ,NULL ,6 ,0x178 ,600000000 , mux_pllp_pllc_pllm_clkm,MUX ), +PERIPH_CLK ("uartb" ,"uart.1" ,NULL ,7 ,0x17c ,600000000 , mux_pllp_pllc_pllm_clkm,MUX ), +PERIPH_CLK ("uartc" ,"uart.2" ,NULL ,55 ,0x1a0 ,600000000 , mux_pllp_pllc_pllm_clkm,MUX ), +PERIPH_CLK ("uartd" ,"uart.3" ,NULL ,65 ,0x1c0 ,600000000 , mux_pllp_pllc_pllm_clkm,MUX ), +PERIPH_CLK ("uarte" ,"uart.4" ,NULL ,66 ,0x1c4 ,600000000 , mux_pllp_pllc_pllm_clkm,MUX ),PERIPH_CLK ("3d" ,"3d" ,NULL ,24 ,0x158 ,300000000 , mux_pllm_pllc_pllp_plla,MUX |DIV_U71 |PERIPH_MANUAL_RESET ),/* scales with voltage and process_id */ PERIPH_CLK ("2d" ,"2d" ,NULL ,21 ,0x15c ,300000000 , mux_pllm_pllc_pllp_plla,MUX |DIV_U71 ),/* scales with voltage and process_id */ /* FIXME: vi and vi_sensor share an enable */ -PERIPH_CLK ("vi" ,"vi" ,NULL ,20 ,0x148 ,150000000 , mux_pllm_pllc_pllp_plla,MUX |DIV_U71 ),/* scales with voltage and process_id */ -PERIPH_CLK ("vi_sensor" ,"vi_sensor" ,NULL ,20 ,0x1a8 ,150000000 , mux_pllm_pllc_pllp_plla,MUX |DIV_U71 |PERIPH_NO_RESET ),/* scales with voltage and process_id */ +PERIPH_CLK ("vi" ,"tegra_camera" ,"vi" ,20 ,0x148 ,150000000 , mux_pllm_pllc_pllp_plla,MUX |DIV_U71 ),/* scales with voltage and process_id */ +PERIPH_CLK ("vi_sensor" ,"tegra_camera" ,"vi_sensor" ,20 ,0x1a8 ,150000000 , mux_pllm_pllc_pllp_plla,MUX |DIV_U71 |PERIPH_NO_RESET ),/* scales with voltage and process_id */ PERIPH_CLK ("epp" ,"epp" ,NULL ,19 ,0x16c ,300000000 , mux_pllm_pllc_pllp_plla,MUX |DIV_U71 ),/* scales with voltage and process_id */ PERIPH_CLK ("mpe" ,"mpe" ,NULL ,60 ,0x170 ,250000000 , mux_pllm_pllc_pllp_plla,MUX |DIV_U71 ),/* scales with voltage and process_id */ PERIPH_CLK ("host1x" ,"host1x" ,NULL ,28 ,0x180 ,166000000 , mux_pllm_pllc_pllp_plla,MUX |DIV_U71 ),/* scales with voltage and process_id */ /* FIXME: cve and tvo share an enable */ PERIPH_CLK ("cve" ,"cve" ,NULL ,49 ,0x140 ,250000000 , mux_pllp_plld_pllc_clkm,MUX |DIV_U71 ),/* requires min voltage */ PERIPH_CLK ("tvo" ,"tvo" ,NULL ,49 ,0x188 ,250000000 , mux_pllp_plld_pllc_clkm,MUX |DIV_U71 ),/* requires min voltage */ -PERIPH_CLK ("hdmi" ,"hdmi" ,NULL ,51 ,0x18c ,148500000 , mux_pllp_plld_pllc_clkm,MUX |DIV_U71 ),/* requires min voltage */ +PERIPH_CLK ("hdmi" ,"hdmi" ,NULL ,51 ,0x18c ,600000000 , mux_pllp_plld_pllc_clkm,MUX |DIV_U71 ),/* requires min voltage */ PERIPH_CLK ("tvdac" ,"tvdac" ,NULL ,53 ,0x194 ,250000000 , mux_pllp_plld_pllc_clkm,MUX |DIV_U71 ),/* requires min voltage */ -PERIPH_CLK ("disp1" ,"tegrafb.0" ,NULL ,27 ,0x138 ,190000000 , mux_pllp_plld_pllc_clkm,MUX |DIV_U71 ),/* scales with voltage and process_id */ -PERIPH_CLK ("disp2" ,"tegrafb.1" ,NULL ,26 ,0x13c ,190000000 , mux_pllp_plld_pllc_clkm,MUX |DIV_U71 ),/* scales with voltage and process_id */ +PERIPH_CLK ("disp1" ,"tegradc.0" ,NULL ,27 ,0x138 ,600000000 , mux_pllp_plld_pllc_clkm,MUX |DIV_U71 ),/* scales with voltage and process_id */ +PERIPH_CLK ("disp2" ,"tegradc.1" ,NULL ,26 ,0x13c ,600000000 , mux_pllp_plld_pllc_clkm,MUX |DIV_U71 ),/* scales with voltage and process_id */ PERIPH_CLK ("usbd" ,"fsl-tegra-udc" ,NULL ,22 ,0 ,480000000 , mux_clk_m,0 ),/* requires min voltage */ PERIPH_CLK ("usb2" ,"tegra-ehci.1" ,NULL ,58 ,0 ,480000000 , mux_clk_m,0 ),/* requires min voltage */ PERIPH_CLK ("usb3" ,"tegra-ehci.2" ,NULL ,59 ,0 ,480000000 , mux_clk_m,0 ),/* requires min voltage */ PERIPH_CLK ("emc" ,"emc" ,NULL ,57 ,0x19c ,800000000 , mux_pllm_pllc_pllp_clkm,MUX |DIV_U71 |PERIPH_EMC_ENB ),PERIPH_CLK ("dsi" ,"dsi" ,NULL ,48 ,0 ,500000000 , mux_plld,0 ),/* scales with voltage */ -PERIPH_CLK ("csi" ,"csi" ,NULL ,52 ,0 ,72000000 , mux_pllp_out3,0 ), -PERIPH_CLK ("isp" ,"isp" ,NULL ,23 ,0 ,150000000 , mux_clk_m,0 ),/* same frequency as VI */ -PERIPH_CLK ("csus" ,"csus" ,NULL ,92 ,0 ,150000000 , mux_clk_m,PERIPH_NO_RESET ), +PERIPH_CLK ("csi" ,"tegra_camera" ,"csi" ,52 ,0 ,72000000 , mux_pllp_out3,0 ), +PERIPH_CLK ("isp" ,"tegra_camera" ,"isp" ,23 ,0 ,150000000 , mux_clk_m,0 ),/* same frequency as VI */ +PERIPH_CLK ("csus" ,"tegra_camera" ,"csus" ,92 ,0 ,150000000 , mux_clk_m,PERIPH_NO_RESET ),PERIPH_CLK ("pex" ,NULL ,"pex" ,70 ,0 ,26000000 , mux_clk_m,PERIPH_MANUAL_RESET ),PERIPH_CLK ("afi" ,NULL ,"afi" ,72 ,0 ,26000000 , mux_clk_m,PERIPH_MANUAL_RESET ), PERIPH_CLK("pcie_xclk", NULL, "pcie_xclk", 74, 0, 26000000, mux_clk_m, PERIPH_MANUAL_RESET),
@@ -1694,9 +1865,15 @@ struct clk_duplicate tegra_clk_duplicates[] = {CLK_DUPLICATE ("uartc" ,"tegra_uart.2" ,NULL ),CLK_DUPLICATE ("uartd" ,"tegra_uart.3" ,NULL ),CLK_DUPLICATE ("uarte" ,"tegra_uart.4" ,NULL ), -CLK_DUPLICATE ("host1x" ,"tegrafb.0" ,"host1x" ), -CLK_DUPLICATE ("host1x" ,"tegrafb.1" ,"host1x" ), +CLK_DUPLICATE ("usbd" ,"utmip-pad" ,NULL ),CLK_DUPLICATE ("usbd" ,"tegra-ehci.0" ,NULL ), +CLK_DUPLICATE ("usbd" ,"tegra-otg" ,NULL ), +CLK_DUPLICATE ("hdmi" ,"tegradc.0" ,"hdmi" ), +CLK_DUPLICATE ("hdmi" ,"tegradc.1" ,"hdmi" ), +CLK_DUPLICATE ("pwm" ,"tegra_pwm.0" ,NULL ), +CLK_DUPLICATE ("pwm" ,"tegra_pwm.1" ,NULL ), +CLK_DUPLICATE ("pwm" ,"tegra_pwm.2" ,NULL ), + CLK_DUPLICATE("pwm", "tegra_pwm.3", NULL), };#define CLK (dev, con, ck) \
@@ -1732,7 +1909,10 @@ struct clk_lookup tegra_clk_lookups[] = {CLK (NULL ,"hclk" , &tegra_clk_hclk),CLK (NULL ,"pclk" , &tegra_clk_pclk),CLK (NULL ,"clk_d" , &tegra_clk_d), +CLK (NULL ,"clk_dev1" , &tegra_dev1_clk), +CLK (NULL ,"clk_dev2" , &tegra_dev2_clk),CLK (NULL ,"cpu" , &tegra_clk_virtual_cpu), + CLK(NULL, "blink", &tegra_clk_blink), };void __init tegra2_init_clocks (void )
@@ -1775,14 +1955,34 @@ void __init tegra2_init_clocks(void)#ifdef CONFIG_PM static u32 clk_rst_suspend[RST_DEVICES_NUM +CLK_OUT_ENB_NUM + -PERIPH_CLK_SOURCE_NUM +3 ]; +PERIPH_CLK_SOURCE_NUM +19 ];void tegra_clk_suspend (void ) {unsigned long off, i; +u32 pllx_misc;u32 *ctx = clk_rst_suspend; *ctx++ =clk_readl (OSC_CTRL ) &OSC_CTRL_MASK ; + *ctx++ =clk_readl (tegra_pll_p.reg +PLL_BASE ); + *ctx++ =clk_readl (tegra_pll_p.reg +PLL_MISC (&tegra_pll_p)); + *ctx++ =clk_readl (tegra_pll_c.reg +PLL_BASE ); + *ctx++ =clk_readl (tegra_pll_c.reg +PLL_MISC (&tegra_pll_c)); + *ctx++ =clk_readl (tegra_pll_a.reg +PLL_BASE ); + *ctx++ =clk_readl (tegra_pll_a.reg +PLL_MISC (&tegra_pll_a)); + + *ctx++ =clk_readl (tegra_pll_m_out1.reg); + *ctx++ =clk_readl (tegra_pll_p_out1.reg); + *ctx++ =clk_readl (tegra_pll_p_out3.reg); + *ctx++ =clk_readl (tegra_pll_a_out0.reg); + *ctx++ =clk_readl (tegra_pll_c_out1.reg); + + *ctx++ =clk_readl (tegra_clk_cclk.reg); + *ctx++ =clk_readl (tegra_clk_cclk.reg +SUPER_CLK_DIVIDER ); + + *ctx++ =clk_readl (tegra_clk_sclk.reg); + *ctx++ =clk_readl (tegra_clk_sclk.reg +SUPER_CLK_DIVIDER ); + *ctx++ =clk_readl (tegra_clk_pclk.reg);for (off =PERIPH_CLK_SOURCE_I2S1 ; off <=PERIPH_CLK_SOURCE_OSC ; off +=4 ) {
@@ -1801,6 +2001,10 @@ void tegra_clk_suspend(void) *ctx++ =clk_readl (MISC_CLK_ENB ); *ctx++ =clk_readl (CLK_MASK_ARM ); + + pllx_misc =clk_readl (tegra_pll_x.reg +PLL_MISC (&tegra_pll_x)); + pllx_misc &= ~PLL_MISC_LOCK_ENABLE (&tegra_pll_x); +clk_writel (pllx_misc, tegra_pll_x.reg +PLL_MISC (&tegra_pll_x)); }void tegra_clk_resume (void )
@@ -1813,6 +2017,27 @@ void tegra_clk_resume(void) val |= *ctx++;clk_writel (val,OSC_CTRL ); +clk_writel (*ctx++, tegra_pll_p.reg +PLL_BASE ); +clk_writel (*ctx++, tegra_pll_p.reg +PLL_MISC (&tegra_pll_p)); +clk_writel (*ctx++, tegra_pll_c.reg +PLL_BASE ); +clk_writel (*ctx++, tegra_pll_c.reg +PLL_MISC (&tegra_pll_c)); +clk_writel (*ctx++, tegra_pll_a.reg +PLL_BASE ); +clk_writel (*ctx++, tegra_pll_a.reg +PLL_MISC (&tegra_pll_a)); +udelay (300 ); + +clk_writel (*ctx++, tegra_pll_m_out1.reg); +clk_writel (*ctx++, tegra_pll_p_out1.reg); +clk_writel (*ctx++, tegra_pll_p_out3.reg); +clk_writel (*ctx++, tegra_pll_a_out0.reg); +clk_writel (*ctx++, tegra_pll_c_out1.reg); + +clk_writel (*ctx++, tegra_clk_cclk.reg); +clk_writel (*ctx++, tegra_clk_cclk.reg +SUPER_CLK_DIVIDER ); + +clk_writel (*ctx++, tegra_clk_sclk.reg); +clk_writel (*ctx++, tegra_clk_sclk.reg +SUPER_CLK_DIVIDER ); +clk_writel (*ctx++, tegra_clk_pclk.reg); +/* enable all clocks before configuring clock sources */ clk_writel (0xbffffff9ul ,CLK_OUT_ENB );clk_writel (0xfefffff7ul ,CLK_OUT_ENB +4 );
Signature · 1 line
1.7.3.1
PATCH v4 6/15 ARM: tegra: pinmux: Add missing drive pingroups and fix suspend
In reply to Colin CrossFrom: Gary King <[email protected]>
Adds missing drive pingroups, saves all drive pingroups in suspend, and restores the pinmux registers in the proper order.
--- arch/arm/mach-tegra/include/mach/pinmux-t2.h | 10 ++++++++++ arch/arm/mach-tegra/pinmux-t2-tables.c | 25 +++++++++++++++++++++---- 2 files changed, 31 insertions(+), 4 deletions(-)
arch/arm/mach-tegra/include/mach/pinmux-t2.h +10 -0
@@ -167,6 +167,16 @@ enum tegra_drive_pingroup {TEGRA_DRIVE_PINGROUP_XM2D ,TEGRA_DRIVE_PINGROUP_XM2CLK ,TEGRA_DRIVE_PINGROUP_MEMCOMP , +TEGRA_DRIVE_PINGROUP_SDIO1 , +TEGRA_DRIVE_PINGROUP_CRT , +TEGRA_DRIVE_PINGROUP_DDC , +TEGRA_DRIVE_PINGROUP_GMA , +TEGRA_DRIVE_PINGROUP_GMB , +TEGRA_DRIVE_PINGROUP_GMC , +TEGRA_DRIVE_PINGROUP_GMD , +TEGRA_DRIVE_PINGROUP_GME , +TEGRA_DRIVE_PINGROUP_OWR , +TEGRA_DRIVE_PINGROUP_UAD , TEGRA_MAX_DRIVE_PINGROUP, };
arch/arm/mach-tegra/pinmux-t2-tables.c +21 -4
@@ -66,6 +66,16 @@ const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVEDRIVE_PINGROUP (XM2D ,0x8cc ),DRIVE_PINGROUP (XM2CLK ,0x8d0 ),DRIVE_PINGROUP (MEMCOMP ,0x8d4 ), +DRIVE_PINGROUP (SDIO1 ,0x8e0 ), +DRIVE_PINGROUP (CRT ,0x8ec ), +DRIVE_PINGROUP (DDC ,0x8f0 ), +DRIVE_PINGROUP (GMA ,0x8f4 ), +DRIVE_PINGROUP (GMB ,0x8f8 ), +DRIVE_PINGROUP (GMC ,0x8fc ), +DRIVE_PINGROUP (GMD ,0x900 ), +DRIVE_PINGROUP (GME ,0x904 ), +DRIVE_PINGROUP (OWR ,0x908 ), + DRIVE_PINGROUP(UAD, 0x90c), }; #define PINGROUP(pg_name, vdd, f0, f1, f2, f3, f_safe, \
@@ -217,7 +227,8 @@ const struct tegra_pingroup_desc tegra_soc_pingroups[TEGRA_MAX_PINGROUP] = {#define PULLUPDOWN_REG_NUM 5static u32 pinmux_reg[TRISTATE_REG_NUM +PIN_MUX_CTL_REG_NUM + -PULLUPDOWN_REG_NUM ]; +PULLUPDOWN_REG_NUM + +ARRAY_SIZE (tegra_soc_drive_pingroups)];static inline unsigned long pg_readl (unsigned long offset) {
@@ -234,14 +245,17 @@ void tegra_pinmux_suspend(void)unsigned int i;u32 *ctx = pinmux_reg; -for (i =0 ; i <TRISTATE_REG_NUM ; i++) - *ctx++ =pg_readl (TRISTATE_REG_A + i*4 ); -for (i =0 ; i <PIN_MUX_CTL_REG_NUM ; i++) *ctx++ =pg_readl (PIN_MUX_CTL_REG_A + i*4 );for (i =0 ; i <PULLUPDOWN_REG_NUM ; i++) *ctx++ =pg_readl (PULLUPDOWN_REG_A + i*4 ); + +for (i =0 ; i <TRISTATE_REG_NUM ; i++) + *ctx++ =pg_readl (TRISTATE_REG_A + i*4 ); + +for (i =0 ; i <ARRAY_SIZE (tegra_soc_drive_pingroups); i++) + *ctx++ =pg_readl (tegra_soc_drive_pingroups[i].reg); }void tegra_pinmux_resume (void )
@@ -257,5 +271,8 @@ void tegra_pinmux_resume(void)for (i =0 ; i <TRISTATE_REG_NUM ; i++)pg_writel (*ctx++,TRISTATE_REG_A + i*4 ); + +for (i =0 ; i <ARRAY_SIZE (tegra_soc_drive_pingroups); i++) + pg_writel(*ctx++, tegra_soc_drive_pingroups[i].reg); }#endif
Signature · 1 line
1.7.3.1
PATCH v4 7/15 ARM: tegra: timer: Add idle and suspend support to timers
In reply to Colin CrossImplement read_persistent_clock by reading the Tegra RTC registers that stay running during suspend.
Save and restore the timer configuration register in suspend.
--- arch/arm/mach-tegra/timer.c | 60 +++++++++++++++++++++++++++++++++++++++++- 1 files changed, 58 insertions(+), 2 deletions(-)
arch/arm/mach-tegra/timer.c +58 -2
@@ -38,6 +38,10 @@#include "board.h" #include "clock.h" +#define RTC_SECONDS 0x08 +#define RTC_SHADOW_SECONDS 0x0c +#define RTC_MILLISECONDS 0x10 +#define TIMERUS_CNTR_1US 0x10#define TIMERUS_USEC_CFG 0x14#define TIMERUS_CNTR_FREEZE 0x4c
@@ -50,9 +54,11 @@#define TIMER_PTV 0x0#define TIMER_PCR 0x4 -struct tegra_timer ; -static void __iomem *timer_reg_base =IO_ADDRESS (TEGRA_TMR1_BASE ); +static void __iomem *rtc_base =IO_ADDRESS (TEGRA_RTC_BASE ); + +static struct timespec persistent_ts; +static u64 persistent_ms, last_persistent_ms;#define timer_writel (value, reg) \ __raw_writel(value, (u32)timer_reg_base + (reg))
@@ -133,6 +139,42 @@ static void notrace tegra_update_sched_clock(void)update_sched_clock (&cd, cyc, (u32 )~0 ); } +/* +* tegra_rtc_read - Reads the Tegra RTC registers +* Care must be taken that this funciton is not called while the +* tegra_rtc driver could be executing to avoid race conditions +* on the RTC shadow register +*/ +u64 tegra_rtc_read_ms (void ) +{ +u32 ms =readl (rtc_base +RTC_MILLISECONDS ); +u32 s =readl (rtc_base +RTC_SHADOW_SECONDS ); +return (u64 )s *MSEC_PER_SEC + ms; +} + +/* +* read_persistent_clock - Return time from a persistent clock. +* +* Reads the time from a source which isn't disabled during PM, the +* 32k sync timer. Convert the cycles elapsed since last read into +* nsecs and adds to a monotonically increasing timespec. +* Care must be taken that this funciton is not called while the +* tegra_rtc driver could be executing to avoid race conditions +* on the RTC shadow register +*/ +void read_persistent_clock (struct timespec *ts) +{ +u64 delta; +struct timespec *tsp = &persistent_ts; + + last_persistent_ms = persistent_ms; + persistent_ms =tegra_rtc_read_ms (); + delta = persistent_ms - last_persistent_ms; + +timespec_add_ns (tsp, delta *NSEC_PER_MSEC ); + *ts = *tsp; +} +static irqreturn_t tegra_timer_interrupt (int irq,void *dev_id) {struct clock_event_device *evt = (struct clock_event_device *)dev_id;
@@ -204,3 +246,17 @@ static void __init tegra_init_timer(void)struct sys_timer tegra_timer = { .init = tegra_init_timer, }; + +#ifdef CONFIG_PM +static u32 usec_config; + +void tegra_timer_suspend (void ) +{ + usec_config =timer_readl (TIMERUS_USEC_CFG ); +} + +void tegra_timer_resume (void ) +{ +timer_writel (usec_config,TIMERUS_USEC_CFG ); +} +#endif
Signature · 1 line
1.7.3.1
PATCH v4 8/15 ARM: tegra: irq: Add support for suspend wake sources
In reply to Colin Cross--- arch/arm/mach-tegra/include/mach/legacy_irq.h | 4 + arch/arm/mach-tegra/irq.c | 176 +++++++++++-------------- arch/arm/mach-tegra/legacy_irq.c | 109 +++++++++++++++- 3 files changed, 184 insertions(+), 105 deletions(-)
arch/arm/mach-tegra/include/mach/legacy_irq.h +4 -0
@@ -27,5 +27,9 @@ int tegra_legacy_force_irq_status(unsigned int irq);void tegra_legacy_select_fiq (unsigned int irq,bool fiq);unsigned long tegra_legacy_vfiq (int nr);unsigned long tegra_legacy_class (int nr); +int tegra_legacy_irq_set_wake (int irq,int enable); +void tegra_legacy_irq_set_lp1_wake_mask (void ); +void tegra_legacy_irq_restore_mask (void ); +void tegra_init_legacy_irq (void );#endif
arch/arm/mach-tegra/irq.c +75 -101
222 lines not on this page · raw message
arch/arm/mach-tegra/legacy_irq.c +105 -4
131 lines not on this page · raw message
Signature · 1 line
1.7.3.1
PATCH v4 9/15 ARM: tegra: irq: Implement retrigger
In reply to Colin Cross--- arch/arm/mach-tegra/irq.c | 17 ++++++++++++++++- 1 files changed, 16 insertions(+), 1 deletions(-)
arch/arm/mach-tegra/irq.c +16 -1
@@ -48,6 +48,7 @@ static u32 tegra_lp0_wake_level_any;static void (*tegra_gic_mask_irq)(struct irq_data *d);static void (*tegra_gic_unmask_irq)(struct irq_data *d); +static void (*tegra_gic_ack_irq)(struct irq_data *d);/* ensures that sufficient time is passed for a register write to * serialize into the 32KHz domain */
@@ -112,10 +113,24 @@ static void tegra_unmask(struct irq_data *d)tegra_legacy_unmask_irq (d->irq); } +static void tegra_ack (struct irq_data *d) +{ +tegra_legacy_force_irq_clr (d->irq); +tegra_gic_ack_irq (d); +} + +static int tegra_retrigger (struct irq_data *d) +{ +tegra_legacy_force_irq_set (d->irq); +return 1 ; +} +static struct irq_chip tegra_irq = { .name ="PPI" , + .irq_ack = tegra_ack, .irq_mask = tegra_mask, .irq_unmask = tegra_unmask, + .irq_retrigger = tegra_retrigger, };void __init tegra_init_irq (void )
@@ -132,7 +147,7 @@ void __init tegra_init_irq(void) gic =get_irq_chip (29 ); tegra_gic_unmask_irq = gic->irq_unmask; tegra_gic_mask_irq = gic->irq_mask; - tegra_irq.irq_ack = gic->irq_ack; + tegra_gic_ack_irq = gic->irq_ack;#ifdef CONFIG_SMP tegra_irq.irq_set_affinity = gic->irq_set_affinity;#endif
Signature · 1 line
1.7.3.1
PATCH v4 10/15 ARM: tegra: iomap: Add missing devices, fix use of SZ_8, SZ_64
In reply to Colin CrossFrom: Gary King <[email protected]>
Adds gart, hdmi, avp, host1x, and pwm controllers to mach/iomap.h There is no SZ_8 or SZ_64, replace them with constants
--- arch/arm/mach-tegra/include/mach/iomap.h | 55 ++++++++++++++++++++++++------ 1 files changed, 44 insertions(+), 11 deletions(-)
arch/arm/mach-tegra/include/mach/iomap.h +44 -11
@@ -26,6 +26,9 @@#define TEGRA_IRAM_BASE 0x40000000#define TEGRA_IRAM_SIZE SZ_256K +#define TEGRA_HOST1X_BASE 0x50000000 +#define TEGRA_HOST1X_SIZE 0x24000 +#define TEGRA_ARM_PERIF_BASE 0x50040000#define TEGRA_ARM_PERIF_SIZE SZ_8K
@@ -35,38 +38,56 @@#define TEGRA_ARM_INT_DIST_BASE 0x50041000#define TEGRA_ARM_INT_DIST_SIZE SZ_4K +#define TEGRA_MPE_BASE 0x54040000 +#define TEGRA_MPE_SIZE SZ_256K + +#define TEGRA_VI_BASE 0x54080000 +#define TEGRA_VI_SIZE SZ_256K + +#define TEGRA_ISP_BASE 0x54100000 +#define TEGRA_ISP_SIZE SZ_256K +#define TEGRA_DISPLAY_BASE 0x54200000#define TEGRA_DISPLAY_SIZE SZ_256K#define TEGRA_DISPLAY2_BASE 0x54240000#define TEGRA_DISPLAY2_SIZE SZ_256K +#define TEGRA_HDMI_BASE 0x54280000 +#define TEGRA_HDMI_SIZE SZ_256K + +#define TEGRA_GART_BASE 0x58000000 +#define TEGRA_GART_SIZE SZ_32M + +#define TEGRA_RES_SEMA_BASE 0x60001000 +#define TEGRA_RES_SEMA_SIZE SZ_4K +#define TEGRA_PRIMARY_ICTLR_BASE 0x60004000 -#define TEGRA_PRIMARY_ICTLR_SIZE SZ_64 +#define TEGRA_PRIMARY_ICTLR_SIZE 64#define TEGRA_SECONDARY_ICTLR_BASE 0x60004100 -#define TEGRA_SECONDARY_ICTLR_SIZE SZ_64 +#define TEGRA_SECONDARY_ICTLR_SIZE 64#define TEGRA_TERTIARY_ICTLR_BASE 0x60004200 -#define TEGRA_TERTIARY_ICTLR_SIZE SZ_64 +#define TEGRA_TERTIARY_ICTLR_SIZE 64#define TEGRA_QUATERNARY_ICTLR_BASE 0x60004300 -#define TEGRA_QUATERNARY_ICTLR_SIZE SZ_64 +#define TEGRA_QUATERNARY_ICTLR_SIZE 64#define TEGRA_TMR1_BASE 0x60005000 -#define TEGRA_TMR1_SIZE SZ_8 +#define TEGRA_TMR1_SIZE 8#define TEGRA_TMR2_BASE 0x60005008 -#define TEGRA_TMR2_SIZE SZ_8 +#define TEGRA_TMR2_SIZE 8#define TEGRA_TMRUS_BASE 0x60005010 -#define TEGRA_TMRUS_SIZE SZ_64 +#define TEGRA_TMRUS_SIZE 64#define TEGRA_TMR3_BASE 0x60005050 -#define TEGRA_TMR3_SIZE SZ_8 +#define TEGRA_TMR3_SIZE 8#define TEGRA_TMR4_BASE 0x60005058 -#define TEGRA_TMR4_SIZE SZ_8 +#define TEGRA_TMR4_SIZE 8#define TEGRA_CLK_RESET_BASE 0x60006000#define TEGRA_CLK_RESET_SIZE SZ_4K
@@ -114,10 +135,10 @@#define TEGRA_I2S2_SIZE SZ_256#define TEGRA_UARTA_BASE 0x70006000 -#define TEGRA_UARTA_SIZE SZ_64 +#define TEGRA_UARTA_SIZE 64#define TEGRA_UARTB_BASE 0x70006040 -#define TEGRA_UARTB_SIZE SZ_64 +#define TEGRA_UARTB_SIZE 64#define TEGRA_UARTC_BASE 0x70006200#define TEGRA_UARTC_SIZE SZ_256
@@ -140,6 +161,18 @@#define TEGRA_PWFM_BASE 0x7000A000#define TEGRA_PWFM_SIZE SZ_256 +#define TEGRA_PWFM0_BASE 0x7000A000 +#define TEGRA_PWFM0_SIZE 4 + +#define TEGRA_PWFM1_BASE 0x7000A010 +#define TEGRA_PWFM1_SIZE 4 + +#define TEGRA_PWFM2_BASE 0x7000A020 +#define TEGRA_PWFM2_SIZE 4 + +#define TEGRA_PWFM3_BASE 0x7000A030 +#define TEGRA_PWFM3_SIZE 4 +#define TEGRA_MIPI_BASE 0x7000B000#define TEGRA_MIPI_SIZE SZ_256
Signature · 1 line
1.7.3.1
RE: [PATCH v4 10/15] ARM: tegra: iomap: Add missing devices, fix use of SZ_8, SZ_64
Colin Cross wrote at Wednesday, February 09, 2011 11:43 PM:
Quoted 5 lines
From: Gary King <[email protected]>
Adds gart, hdmi, avp, host1x, and pwm controllers to
mach/iomap.hThere is noSZ_8orSZ_64, replace them with constants
Can't we add those SZ_* constants?
Signature · 1 line
nvpublic
Re: [PATCH v4 10/15] ARM: tegra: iomap: Add missing devices, fix use of SZ_8, SZ_64
Quoted 8 lines · Stephen Warren
Colin Cross wrote at Wednesday, February 09, 2011 11:43 PM:
Quoted 5 lines
From: Gary King <[email protected]>
Adds gart, hdmi, avp, host1x, and pwm controllers to
mach/iomap.hThere is noSZ_8orSZ_64, replace them with constantsCan't we add those SZ_* constants?
Sure, you already added SZ_64, and nothing depends on the SZ_8 defines right now, so I'll drop that part of the change and send a patch that completes the SZ_* defines.
PATCH v4 11/15 ARM: tegra: cpufreq: Disable cpufreq during suspend
In reply to Colin CrossOn Tegra, calling clk_set_rate on the CPU clock may call into the regulator API. If the regulator driver that controls the CPU voltage rail has been suspended, this can lead to attempted communication with a hardware block that has already been turned off.
Adds a SUSPEND_PREPARE notification hook to drop the frequency to the lowest possible during suspend.
Also adds 216MHz (off of PLLP) as the lowest CPU frequency, which allows PLLX to be turned off.
--- arch/arm/mach-tegra/cpu-tegra.c | 75 +++++++++++++++++++++++++++++++-------- 1 files changed, 60 insertions(+), 15 deletions(-)
arch/arm/mach-tegra/cpu-tegra.c +60 -15
@@ -28,6 +28,7 @@#include <linux/err.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/suspend.h> #include <asm/system.h>
@@ -36,14 +37,15 @@/* Frequency table index must be sequential starting at 0 */ static struct cpufreq_frequency_table freq_table[] = { - {0 ,312000 }, - {1 ,456000 }, - {2 ,608000 }, - {3 ,760000 }, - {4 ,816000 }, - {5 ,912000 }, - {6 ,1000000 }, - {7 ,CPUFREQ_TABLE_END }, + {0 ,216000 }, + {1 ,312000 }, + {2 ,456000 }, + {3 ,608000 }, + {4 ,760000 }, + {5 ,816000 }, + {6 ,912000 }, + {7 ,1000000 }, + {8 ,CPUFREQ_TABLE_END }, };#define NUM_CPUS 2
@@ -51,6 +53,8 @@ static struct cpufreq_frequency_table freq_table[] = {static struct clk *cpu_clk;static unsigned long target_cpu_speed[NUM_CPUS ]; +static DEFINE_MUTEX (tegra_cpu_lock); +static bool is_suspended;int tegra_verify_speed (struct cpufreq_policy *policy) {
@@ -68,16 +72,11 @@ unsigned int tegra_getspeed(unsigned int cpu)return rate; } -static int tegra_update_cpu_speed (void ) +static int tegra_update_cpu_speed (unsigned long rate) { -int i; -unsigned long rate =0 ;int ret =0 ;struct cpufreq_freqs freqs; -for_each_online_cpu (i) - rate =max (rate, target_cpu_speed[i]); - freqs.old =tegra_getspeed (0 ); freqs.new = rate;
@@ -105,12 +104,30 @@ static int tegra_update_cpu_speed(void)return 0 ; } +static unsigned long tegra_cpu_highest_speed (void ) +{ +unsigned long rate =0 ; +int i; + +for_each_online_cpu (i) + rate =max (rate, target_cpu_speed[i]); +return rate; +} +static int tegra_target (struct cpufreq_policy *policy,unsigned int target_freq,unsigned int relation) {int idx;unsigned int freq; +int ret =0 ; + +mutex_lock (&tegra_cpu_lock); + +if (is_suspended) { + ret = -EBUSY ; + goto out; + }cpufreq_frequency_table_target (policy, freq_table, target_freq, relation, &idx);
@@ -119,9 +136,34 @@ static int tegra_target(struct cpufreq_policy *policy, target_cpu_speed[policy->cpu] = freq; -return tegra_update_cpu_speed (); + ret =tegra_update_cpu_speed (tegra_cpu_highest_speed ()); + +out: +mutex_unlock (&tegra_cpu_lock); +return ret; } +static int tegra_pm_notify (struct notifier_block *nb,unsigned long event, +void *dummy) +{ +mutex_lock (&tegra_cpu_lock); +if (event ==PM_SUSPEND_PREPARE ) { + is_suspended = true; +pr_info ("Tegra cpufreq suspend: setting frequency to %d kHz\n" , + freq_table[0 ].frequency); +tegra_update_cpu_speed (freq_table[0 ].frequency); + }else if (event ==PM_POST_SUSPEND ) { + is_suspended = false; + } +mutex_unlock (&tegra_cpu_lock); + +return NOTIFY_OK ; +} + +static struct notifier_block tegra_cpu_pm_notifier = { + .notifier_call = tegra_pm_notify, +}; +static int tegra_cpu_init (struct cpufreq_policy *policy) {if (policy->cpu >=NUM_CPUS )
@@ -142,6 +184,9 @@ static int tegra_cpu_init(struct cpufreq_policy *policy) policy->shared_type =CPUFREQ_SHARED_TYPE_ALL ;cpumask_copy (policy->related_cpus, cpu_possible_mask); +if (policy->cpu ==0 ) +register_pm_notifier (&tegra_cpu_pm_notifier); +return 0 ; }
Signature · 1 line
1.7.3.1
PATCH v4 12/15 ARM: tegra: Allow overriding arch_reset
In reply to Colin Cross--- arch/arm/mach-tegra/board.h | 2 ++ arch/arm/mach-tegra/common.c | 13 +++++++++++++ arch/arm/mach-tegra/include/mach/system.h | 10 ++-------- 3 files changed, 17 insertions(+), 8 deletions(-)
arch/arm/mach-tegra/board.h +2 -0
@@ -23,6 +23,8 @@#include <linux/types.h> +void tegra_assert_system_reset (char mode,const char *cmd); +void __init tegra_common_init (void );void __init tegra_map_common_io (void );void __init tegra_init_irq (void );
arch/arm/mach-tegra/common.c +13 -0
@@ -26,11 +26,24 @@#include <mach/iomap.h> #include <mach/dma.h> +#include <mach/system.h> #include "board.h" #include "clock.h" #include "fuse.h" +void (*arch_reset)(char mode,const char *cmd) = tegra_assert_system_reset; + +void tegra_assert_system_reset (char mode,const char *cmd) +{ +void __iomem *reset =IO_ADDRESS (TEGRA_CLK_RESET_BASE +0x04 ); +u32 reg; + + reg =readl (reset); + reg |=0x04 ; +writel (reg, reset); +} +static __initdata struct tegra_clk_init_table common_clk_init_table[] = {/* name parent rate enabled */ {"clk_m" ,NULL ,0 , true },
arch/arm/mach-tegra/include/mach/system.h +2 -8
@@ -24,16 +24,10 @@#include <mach/hardware.h> #include <mach/iomap.h> -static inline void arch_idle (void ) -{ -} +extern void (*arch_reset)(char mode,const char *cmd); -static inline void arch_reset (char mode,const char *cmd) +static inline void arch_idle (void ) { -void __iomem *reset =IO_ADDRESS (TEGRA_CLK_RESET_BASE +0x04 ); -u32 reg =readl (reset); - reg |=0x04 ; -writel (reg, reset); }#endif
Signature · 1 line
1.7.3.1
PATCH v4 13/15 ARM: tegra: dma: Fix critical data corruption bugs
In reply to Colin CrossSometimes, due to high interrupt latency in the continuous mode of DMA transfer, the half buffer complete interrupt is handled after DMA has transferred the full buffer. When this is detected, stop DMA immediately and restart with the next buffer if the next buffer is ready.
originally fixed by Victor(Weiguo) Pan <[email protected]>
In place of using the simple spin_lock()/spi_unlock() in the interrupt thread, using the spin_lock_irqsave() and spin_unlock_irqrestore(). The lock is shared between the normal process context and interrupt context.
originally fixed by Laxman Dewangan (ldewangan at nvidia.com)
The use of shadow registers caused memory corruption at physical address 0 because the enable bit was not shadowed, and assuming it needed to be set would enable an unconfigured dma block. Most of the register accesses don't need to know the previous state of the registers, and the few places that do need to modify only a few bits in the registers are the same ones that were sometimes incorrectly setting the enable bit. This patch convert tegra_dma_update_hardware to set the entire register, and the other users to read-modify-write, and drops the shadow registers completely.
Also fixes missing locking in tegra_dma_allocate_channel
--- arch/arm/mach-tegra/dma.c | 197 +++++++++++++++++++++++++-------------------- 1 files changed, 108 insertions(+), 89 deletions(-)
arch/arm/mach-tegra/dma.c +108 -89
@@ -121,17 +121,13 @@ struct tegra_dma_channel {void __iomem *addr;int mode;int irq; - -/* Register shadow */ -u32 csr; -u32 ahb_seq; -u32 ahb_ptr; -u32 apb_seq; -u32 apb_ptr; +int req_transfer_count; };#define NV_DMA_MAX_CHANNELS 32 +static DEFINE_MUTEX (tegra_dma_lock); + static DECLARE_BITMAP(channel_usage, NV_DMA_MAX_CHANNELS);static struct tegra_dma_channel dma_channels[NV_DMA_MAX_CHANNELS ];
@@ -139,7 +135,6 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch, struct tegra_dma_req *req);static void tegra_dma_update_hw_partial (struct tegra_dma_channel *ch,struct tegra_dma_req *req); -static void tegra_dma_init_hw (struct tegra_dma_channel *ch);static void tegra_dma_stop (struct tegra_dma_channel *ch);void tegra_dma_flush (struct tegra_dma_channel *ch)
@@ -151,6 +146,9 @@ void tegra_dma_dequeue(struct tegra_dma_channel *ch) {struct tegra_dma_req *req; +if (tegra_dma_is_empty (ch)) +return ; + req =list_entry (ch->list.next,typeof (*req), node);tegra_dma_dequeue_req (ch, req);
@@ -159,10 +157,10 @@ void tegra_dma_dequeue(struct tegra_dma_channel *ch)void tegra_dma_stop (struct tegra_dma_channel *ch) { -unsigned int csr; -unsigned int status; +u32 csr; +u32 status; - csr = ch->csr; + csr =readl (ch->addr +APB_DMA_CHAN_CSR ); csr &= ~CSR_IE_EOC ;writel (csr, ch->addr +APB_DMA_CHAN_CSR );
@@ -176,19 +174,16 @@ void tegra_dma_stop(struct tegra_dma_channel *ch)int tegra_dma_cancel (struct tegra_dma_channel *ch) { -unsigned int csr; +u32 csr;unsigned long irq_flags;spin_lock_irqsave (&ch->lock, irq_flags);while (!list_empty (&ch->list))list_del (ch->list.next); - csr = ch->csr; + csr =readl (ch->addr +APB_DMA_CHAN_CSR ); csr &= ~CSR_REQ_SEL_MASK ; csr |=CSR_REQ_SEL_INVALID ; - -/* Set the enable as that is not shadowed */ - csr |=CSR_ENB ;writel (csr, ch->addr +APB_DMA_CHAN_CSR );tegra_dma_stop (ch);
@@ -230,18 +225,15 @@ int tegra_dma_dequeue_req(struct tegra_dma_channel *ch,* - Finally stop or program the DMA to the next buffer in the * list. */ - csr = ch->csr; + csr =readl (ch->addr +APB_DMA_CHAN_CSR ); csr &= ~CSR_REQ_SEL_MASK ; csr |=CSR_REQ_SEL_INVALID ; - -/* Set the enable as that is not shadowed */ - csr |=CSR_ENB ;writel (csr, ch->addr +APB_DMA_CHAN_CSR );/* Get the transfer count */ status =readl (ch->addr +APB_DMA_CHAN_STA ); to_transfer = (status &STA_COUNT_MASK ) >>STA_COUNT_SHIFT ; - req_transfer_count = (ch->csr &CSR_WCOUNT_MASK ) >>CSR_WCOUNT_SHIFT ; + req_transfer_count = ch->req_transfer_count; req_transfer_count +=1 ; to_transfer +=1 ;
@@ -349,7 +341,9 @@ EXPORT_SYMBOL(tegra_dma_enqueue_req);struct tegra_dma_channel *tegra_dma_allocate_channel (int mode) {int channel; -struct tegra_dma_channel *ch; +struct tegra_dma_channel *ch =NULL ; + +mutex_lock (&tegra_dma_lock);/* first channel is the shared channel */ if (mode &TEGRA_DMA_SHARED ) {
@@ -358,11 +352,14 @@ struct tegra_dma_channel *tegra_dma_allocate_channel(int mode) channel =find_first_zero_bit (channel_usage,ARRAY_SIZE (dma_channels));if (channel >=ARRAY_SIZE (dma_channels)) -return NULL ; + goto out; }__set_bit (channel, channel_usage); ch = &dma_channels[channel]; ch->mode = mode; + +out: +mutex_unlock (&tegra_dma_lock);return ch; }EXPORT_SYMBOL (tegra_dma_allocate_channel);
@@ -372,22 +369,27 @@ void tegra_dma_free_channel(struct tegra_dma_channel *ch)if (ch->mode &TEGRA_DMA_SHARED )return ;tegra_dma_cancel (ch); +mutex_lock (&tegra_dma_lock);__clear_bit (ch->id, channel_usage); +mutex_unlock (&tegra_dma_lock); }EXPORT_SYMBOL (tegra_dma_free_channel);static void tegra_dma_update_hw_partial (struct tegra_dma_channel *ch,struct tegra_dma_req *req) { +u32 apb_ptr; +u32 ahb_ptr; +if (req->to_memory) { - ch->apb_ptr = req->source_addr; - ch->ahb_ptr = req->dest_addr; + apb_ptr = req->source_addr; + ahb_ptr = req->dest_addr; }else { - ch->apb_ptr = req->dest_addr; - ch->ahb_ptr = req->source_addr; + apb_ptr = req->dest_addr; + ahb_ptr = req->source_addr; } -writel (ch->apb_ptr, ch->addr +APB_DMA_CHAN_APB_PTR ); -writel (ch->ahb_ptr, ch->addr +APB_DMA_CHAN_AHB_PTR ); +writel (apb_ptr, ch->addr +APB_DMA_CHAN_APB_PTR ); +writel (ahb_ptr, ch->addr +APB_DMA_CHAN_AHB_PTR ); req->status =TEGRA_DMA_REQ_INFLIGHT ;return ;
@@ -401,38 +403,39 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch,int ahb_bus_width;int apb_bus_width;int index; -unsigned long csr; +u32 ahb_seq; +u32 apb_seq; +u32 ahb_ptr; +u32 apb_ptr; +u32 csr; + + csr =CSR_IE_EOC |CSR_FLOW ; + ahb_seq =AHB_SEQ_INTR_ENB |AHB_SEQ_BURST_1 ; + apb_seq =0 ; - ch->csr |=CSR_FLOW ; - ch->csr &= ~CSR_REQ_SEL_MASK ; - ch->csr |= req->req_sel <<CSR_REQ_SEL_SHIFT ; - ch->ahb_seq &= ~AHB_SEQ_BURST_MASK ; - ch->ahb_seq |=AHB_SEQ_BURST_1 ; + csr |= req->req_sel <<CSR_REQ_SEL_SHIFT ;/* One shot mode is always single buffered, * continuous mode is always double buffered * */ if (ch->mode &TEGRA_DMA_MODE_ONESHOT ) { - ch->csr |=CSR_ONCE ; - ch->ahb_seq &= ~AHB_SEQ_DBL_BUF ; - ch->csr &= ~CSR_WCOUNT_MASK ; - ch->csr |= ((req->size>>2 ) -1 ) <<CSR_WCOUNT_SHIFT ; + csr |=CSR_ONCE ; + ch->req_transfer_count = (req->size >>2 ) -1 ; }else { - ch->csr &= ~CSR_ONCE ; - ch->ahb_seq |=AHB_SEQ_DBL_BUF ; + ahb_seq |=AHB_SEQ_DBL_BUF ;/* In double buffered mode, we set the size to half the * requested size and interrupt when half the buffer * is full */ - ch->csr &= ~CSR_WCOUNT_MASK ; - ch->csr |= ((req->size>>3 ) -1 ) <<CSR_WCOUNT_SHIFT ; + ch->req_transfer_count = (req->size >>3 ) -1 ; } + csr |= ch->req_transfer_count <<CSR_WCOUNT_SHIFT ; +if (req->to_memory) { - ch->csr &= ~CSR_DIR ; - ch->apb_ptr = req->source_addr; - ch->ahb_ptr = req->dest_addr; + apb_ptr = req->source_addr; + ahb_ptr = req->dest_addr; apb_addr_wrap = req->source_wrap; ahb_addr_wrap = req->dest_wrap;
@@ -440,9 +443,9 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch, ahb_bus_width = req->dest_bus_width; }else { - ch->csr |=CSR_DIR ; - ch->apb_ptr = req->dest_addr; - ch->ahb_ptr = req->source_addr; + csr |=CSR_DIR ; + apb_ptr = req->dest_addr; + ahb_ptr = req->source_addr; apb_addr_wrap = req->dest_wrap; ahb_addr_wrap = req->source_wrap;
@@ -461,8 +464,7 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch, index++; }while (index <ARRAY_SIZE (apb_addr_wrap_table));BUG_ON (index ==ARRAY_SIZE (apb_addr_wrap_table)); - ch->apb_seq &= ~APB_SEQ_WRAP_MASK ; - ch->apb_seq |= index <<APB_SEQ_WRAP_SHIFT ; + apb_seq |= index <<APB_SEQ_WRAP_SHIFT ;/* set address wrap for AHB size */ index =0 ;
@@ -472,55 +474,42 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch, index++; }while (index <ARRAY_SIZE (ahb_addr_wrap_table));BUG_ON (index ==ARRAY_SIZE (ahb_addr_wrap_table)); - ch->ahb_seq &= ~AHB_SEQ_WRAP_MASK ; - ch->ahb_seq |= index <<AHB_SEQ_WRAP_SHIFT ; + ahb_seq |= index <<AHB_SEQ_WRAP_SHIFT ;for (index =0 ; index <ARRAY_SIZE (bus_width_table); index++) {if (bus_width_table[index] == ahb_bus_width)break ; }BUG_ON (index ==ARRAY_SIZE (bus_width_table)); - ch->ahb_seq &= ~AHB_SEQ_BUS_WIDTH_MASK ; - ch->ahb_seq |= index <<AHB_SEQ_BUS_WIDTH_SHIFT ; + ahb_seq |= index <<AHB_SEQ_BUS_WIDTH_SHIFT ;for (index =0 ; index <ARRAY_SIZE (bus_width_table); index++) {if (bus_width_table[index] == apb_bus_width)break ; }BUG_ON (index ==ARRAY_SIZE (bus_width_table)); - ch->apb_seq &= ~APB_SEQ_BUS_WIDTH_MASK ; - ch->apb_seq |= index <<APB_SEQ_BUS_WIDTH_SHIFT ; - - ch->csr |=CSR_IE_EOC ; + apb_seq |= index <<APB_SEQ_BUS_WIDTH_SHIFT ; -/* update hw registers with the shadow */ -writel (ch->csr, ch->addr +APB_DMA_CHAN_CSR ); -writel (ch->apb_seq, ch->addr +APB_DMA_CHAN_APB_SEQ ); -writel (ch->apb_ptr, ch->addr +APB_DMA_CHAN_APB_PTR ); -writel (ch->ahb_seq, ch->addr +APB_DMA_CHAN_AHB_SEQ ); -writel (ch->ahb_ptr, ch->addr +APB_DMA_CHAN_AHB_PTR ); +writel (csr, ch->addr +APB_DMA_CHAN_CSR ); +writel (apb_seq, ch->addr +APB_DMA_CHAN_APB_SEQ ); +writel (apb_ptr, ch->addr +APB_DMA_CHAN_APB_PTR ); +writel (ahb_seq, ch->addr +APB_DMA_CHAN_AHB_SEQ ); +writel (ahb_ptr, ch->addr +APB_DMA_CHAN_AHB_PTR ); - csr = ch->csr |CSR_ENB ; + csr |=CSR_ENB ;writel (csr, ch->addr +APB_DMA_CHAN_CSR ); req->status =TEGRA_DMA_REQ_INFLIGHT ; } -static void tegra_dma_init_hw (struct tegra_dma_channel *ch) -{ -/* One shot with an interrupt to CPU after transfer */ - ch->csr =CSR_ONCE |CSR_IE_EOC ; - ch->ahb_seq =AHB_SEQ_BUS_WIDTH_32 |AHB_SEQ_INTR_ENB ; - ch->apb_seq =APB_SEQ_BUS_WIDTH_32 |1 <<APB_SEQ_WRAP_SHIFT ; -} -static void handle_oneshot_dma (struct tegra_dma_channel *ch) {struct tegra_dma_req *req; +unsigned long irq_flags; -spin_lock (&ch->lock); +spin_lock_irqsave (&ch->lock, irq_flags);if (list_empty (&ch->list)) { -spin_unlock (&ch->lock); +spin_unlock_irqrestore (&ch->lock, irq_flags);return ; }
@@ -528,8 +517,7 @@ static void handle_oneshot_dma(struct tegra_dma_channel *ch)if (req) {int bytes_transferred; - bytes_transferred = - (ch->csr &CSR_WCOUNT_MASK ) >>CSR_WCOUNT_SHIFT ; + bytes_transferred = ch->req_transfer_count; bytes_transferred +=1 ; bytes_transferred <<=2 ;
@@ -537,12 +525,12 @@ static void handle_oneshot_dma(struct tegra_dma_channel *ch) req->bytes_transferred = bytes_transferred; req->status =TEGRA_DMA_REQ_SUCCESS ; -spin_unlock (&ch->lock); +spin_unlock_irqrestore (&ch->lock, irq_flags);/* Callback should be called without any lock */ pr_debug ("%s: transferred %d bytes\n" , __func__, req->bytes_transferred); req->complete (req); -spin_lock (&ch->lock); +spin_lock_irqsave (&ch->lock, irq_flags); }if (!list_empty (&ch->list)) {
@@ -552,22 +540,55 @@ static void handle_oneshot_dma(struct tegra_dma_channel *ch)if (req->status !=TEGRA_DMA_REQ_INFLIGHT )tegra_dma_update_hw (ch, req); } -spin_unlock (&ch->lock); +spin_unlock_irqrestore (&ch->lock, irq_flags); }static void handle_continuous_dma (struct tegra_dma_channel *ch) {struct tegra_dma_req *req; +unsigned long irq_flags; -spin_lock (&ch->lock); +spin_lock_irqsave (&ch->lock, irq_flags);if (list_empty (&ch->list)) { -spin_unlock (&ch->lock); +spin_unlock_irqrestore (&ch->lock, irq_flags);return ; } req =list_entry (ch->list.next,typeof (*req), node);if (req) {if (req->buffer_status ==TEGRA_DMA_REQ_BUF_STATUS_EMPTY ) { +bool is_dma_ping_complete; + is_dma_ping_complete = (readl (ch->addr +APB_DMA_CHAN_STA ) + &STA_PING_PONG ) ? true : false; +if (req->to_memory) + is_dma_ping_complete = !is_dma_ping_complete; +/* Out of sync - Release current buffer */ +if (!is_dma_ping_complete) { +int bytes_transferred; + + bytes_transferred = ch->req_transfer_count; + bytes_transferred +=1 ; + bytes_transferred <<=3 ; + req->buffer_status =TEGRA_DMA_REQ_BUF_STATUS_FULL ; + req->bytes_transferred = bytes_transferred; + req->status =TEGRA_DMA_REQ_SUCCESS ; +tegra_dma_stop (ch); + +if (!list_is_last (&req->node, &ch->list)) { +struct tegra_dma_req *next_req; + + next_req =list_entry (req->node.next, +typeof (*next_req), node); +tegra_dma_update_hw (ch, next_req); + } + +list_del (&req->node); + +/* DMA lock is NOT held when callbak is called */ +spin_unlock_irqrestore (&ch->lock, irq_flags); + req->complete (req); +return ; + }/* Load the next request into the hardware, if available * */ if (!list_is_last (&req->node, &ch->list)) {
@@ -580,7 +601,7 @@ static void handle_continuous_dma(struct tegra_dma_channel *ch) req->buffer_status =TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL ; req->status =TEGRA_DMA_REQ_SUCCESS ;/* DMA lock is NOT held when callback is called */ -spin_unlock (&ch->lock); +spin_unlock_irqrestore (&ch->lock, irq_flags);if (likely (req->threshold)) req->threshold (req);return ;
@@ -591,8 +612,7 @@ static void handle_continuous_dma(struct tegra_dma_channel *ch)* the second interrupt */ int bytes_transferred; - bytes_transferred = - (ch->csr &CSR_WCOUNT_MASK ) >>CSR_WCOUNT_SHIFT ; + bytes_transferred = ch->req_transfer_count; bytes_transferred +=1 ; bytes_transferred <<=3 ;
@@ -602,7 +622,7 @@ static void handle_continuous_dma(struct tegra_dma_channel *ch)list_del (&req->node);/* DMA lock is NOT held when callbak is called */ -spin_unlock (&ch->lock); +spin_unlock_irqrestore (&ch->lock, irq_flags); req->complete (req);return ;
@@ -610,7 +630,7 @@ static void handle_continuous_dma(struct tegra_dma_channel *ch)BUG (); } } -spin_unlock (&ch->lock); +spin_unlock_irqrestore (&ch->lock, irq_flags); }static irqreturn_t dma_isr (int irq,void *data)
@@ -674,7 +694,6 @@ int __init tegra_dma_init(void)spin_lock_init (&ch->lock);INIT_LIST_HEAD (&ch->list); -tegra_dma_init_hw (ch); irq =INT_APB_DMA_CH0 + i; ret = request_threaded_irq(irq, dma_isr, dma_thread_fn, 0,
Signature · 1 line
1.7.3.1
PATCH v4 14/15 ARM: tegra: add tegra_defconfig
In reply to Colin CrossFrom: Olof Johansson <[email protected]>
Adding one single defconfig for the tegra family of boards, to over time cover the superset of supported platform and drivers.
--- arch/arm/configs/tegra_defconfig | 123 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 123 insertions(+), 0 deletions(-) create mode 100644 arch/arm/configs/tegra_defconfig
arch/arm/configs/tegra_defconfig new file +123 -0
@@ -0,0 +1,123 @@ +CONFIG_EXPERIMENTAL=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_EMBEDDED=y +# CONFIG_SYSCTL_SYSCALL is not set +# CONFIG_ELF_CORE is not set +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_ARCH_TEGRA=y +CONFIG_MACH_HARMONY=y +CONFIG_TEGRA_DEBUG_UARTD=y +CONFIG_ARM_ERRATA_742230=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_SMP=y +CONFIG_NR_CPUS=2 +CONFIG_PREEMPT=y +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +CONFIG_HIGHMEM=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_VFP=y +CONFIG_PM=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_INET_ESP=y +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +CONFIG_IPV6=y +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_IPV6_TUNNEL=y +CONFIG_IPV6_MULTIPLE_TABLES=y +# CONFIG_WIRELESS is not set +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_MISC_DEVICES=y +CONFIG_AD525X_DPOT=y +CONFIG_AD525X_DPOT_I2C=y +CONFIG_ICS932S401=y +CONFIG_APDS9802ALS=y +CONFIG_ISL29003=y +CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_WLAN is not set +# CONFIG_INPUT is not set +# CONFIG_SERIO is not set +# CONFIG_VT is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +# CONFIG_HWMON is not set +# CONFIG_MFD_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +# CONFIG_DNOTIFY is not set +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_PRINTK_TIME=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_KERNEL=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_SCHEDSTATS=y +CONFIG_TIMER_STATS=y +CONFIG_DEBUG_SLAB=y +# CONFIG_DEBUG_PREEMPT is not set +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_SPINLOCK_SLEEP=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_VM=y +CONFIG_DEBUG_SG=y +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +CONFIG_DEBUG_LL=y +CONFIG_EARLY_PRINTK=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_TWOFISH=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y
Signature · 1 line
1.7.3.1
PATCH v4 15/15 ARM: tegra: Use writel_relaxed in tegra_init_cache
In reply to Colin Cross--- arch/arm/mach-tegra/common.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
arch/arm/mach-tegra/common.c +2 -2
@@ -63,8 +63,8 @@ void __init tegra_init_cache(void)#ifdef CONFIG_CACHE_L2X0 void __iomem *p =IO_ADDRESS (TEGRA_ARM_PERIF_BASE ) +0x3000 ; -writel (0x331 , p +L2X0_TAG_LATENCY_CTRL ); -writel (0x441 , p +L2X0_DATA_LATENCY_CTRL ); +writel_relaxed (0x331 , p +L2X0_TAG_LATENCY_CTRL ); +writel_relaxed (0x441 , p +L2X0_DATA_LATENCY_CTRL );l2x0_init (p,0x6C080001 ,0x8200c3fe );#endif
Signature · 1 line
1.7.3.1
v4 cover Updates for Tegra support in 2.6.39
In reply to Colin CrossQuoted 28 lines · Colin Cross
This is a repost of the same series with the suspend and idle support dropped for now while the necessary changes to the gic, l2x0, and init notifiers are discussed. ?If there are no further comments, I will push these to tegra/for-next.
?arch/arm/configs/tegra_defconfig ? ? ? ? ? ? ? | ?123 +++++++++++ ?arch/arm/mach-tegra/Makefile ? ? ? ? ? ? ? ? ? | ? ?1 + ?arch/arm/mach-tegra/board.h ? ? ? ? ? ? ? ? ? ?| ? ?2 + ?arch/arm/mach-tegra/common.c ? ? ? ? ? ? ? ? ? | ? 17 ++- ?arch/arm/mach-tegra/cpu-tegra.c ? ? ? ? ? ? ? ?| ? 75 ++++++-- ?arch/arm/mach-tegra/dma.c ? ? ? ? ? ? ? ? ? ? ?| ?198 ++++++++++-------- ?arch/arm/mach-tegra/gpio.c ? ? ? ? ? ? ? ? ? ? | ? ?1 + ?arch/arm/mach-tegra/include/mach/debug-macro.S | ? 25 +-- ?arch/arm/mach-tegra/include/mach/iomap.h ? ? ? | ? 69 +++++- ?arch/arm/mach-tegra/include/mach/irqs.h ? ? ? ?| ? 14 +- ?arch/arm/mach-tegra/include/mach/legacy_irq.h ?| ? ?4 + ?arch/arm/mach-tegra/include/mach/pinmux-t2.h ? | ? 10 + ?arch/arm/mach-tegra/include/mach/powergate.h ? | ? 40 ++++ ?arch/arm/mach-tegra/include/mach/suspend.h ? ? | ? 38 ++++ ?arch/arm/mach-tegra/include/mach/system.h ? ? ?| ? 10 +- ?arch/arm/mach-tegra/include/mach/uncompress.h ?| ? 18 +-- ?arch/arm/mach-tegra/irq.c ? ? ? ? ? ? ? ? ? ? ?| ?186 ++++++++--------- ?arch/arm/mach-tegra/legacy_irq.c ? ? ? ? ? ? ? | ?109 ++++++++++- ?arch/arm/mach-tegra/pinmux-t2-tables.c ? ? ? ? | ? 26 ++- ?arch/arm/mach-tegra/powergate.c ? ? ? ? ? ? ? ?| ?212 +++++++++++++++++++ ?arch/arm/mach-tegra/tegra2_clocks.c ? ? ? ? ? ?| ?264 ++++++++++++++++++++++-- ?arch/arm/mach-tegra/timer.c ? ? ? ? ? ? ? ? ? ?| ? 61 ++++++-
Quoted 2 lines
?22 files changed, 1212 insertions(+), 291 deletions(-)
I pushed this patch set to tegra/for-next, with minor fixups from Stephen Warren.