davinci updates queued for 2.6.34
cover davinci updates queued for 2.6.34
Here's a set of DaVinci updates for review.
Apologies for the large series, I've been meaning to send these in smaller batches, but hd lots to queue up from over the holidays.
Pending any review comments, these will be submitted to Linus during the next merge window.
Kevin
Chaithrika U S (1):
davinci: clock: Check CLK_PSC flag before disabling PSC
Nageswari Srinivasan (2):
davinci: add support for CDCE949 clock synthesizer
davinci: add CDCE949 support on DM6467 EVM
Sandeep Paulraj (1):
DaVinci: DM365: Changing default queue for DM365.
Sekhar Nori (17):
davinci: da8xx/omapl1: add support for the second sysconfig module
davinci: move PLL wait time values to clock.h
davinci: move DDR2 controller defines to memory.h
davinci: move PSC register definitions from psc.c to psc.h
davinci: make it possible to include clock.h and psc.h in assembly
code
davinci: cpuidle: move mapping of DDR2 controller registers out of
driver
davinci: da850/omap-l138: unlock PLL registers during init
davinci: da850/omap-l138: create static map for SRAM
davinci: explain CLOCK_TICK_RATE of 27MHz in include/mach/timex.h
davinci: board-dm646x-evm.c: arrange related code together
davinci: add support for DM6467T EVM
davinci: clock framework: remove spinlock usage
davinci: make /proc/davinci_clocks display multi-rooted clock tree
davinci: move /proc/davinci_clocks to debugfs
davinci: add power management support
davinci: da850/omap-l138: add support for SoC suspend
davinci: da850/omap-l138 EVM: register for suspend support
Sriramakrishnan (3):
TI Davinci EMAC : Re-use driver for other platforms. TI Davinci EMAC : add platform specific interrupt enable/disable
logic.
TI Davinci EMAC : Abstract Buffer address translation logic.
Sudhakar Rajashekhara (11):
davinci: da850/omap-l138: Modify NOR partition info
davinci: da850/omap-l138: Enable 4-bit ecc
davinci: Correct return value of edma_alloc_channel api
davinci: Keep count of channel controllers on a platform
davinci: Fix edma_alloc_channel api for EDMA_CHANNEL_ANY case
davinci: build list of unused EDMA events dynamically
davinci: support for EDMA resource sharing
davinci: da8xx/omap-l1xx: Add EDMA platform data for da850/omap-l138
davinci: da830/omapl137: Specify reserved channels/slots
davinci: da850/omapl138: Specify reserved channels/slots
davinci: dm646x: Specify reserved EDMA channel/slots for DM646x
arch/arm/mach-davinci/Kconfig | 4 + arch/arm/mach-davinci/Makefile | 3 +- arch/arm/mach-davinci/board-da830-evm.c | 4 +- arch/arm/mach-davinci/board-da850-evm.c | 34 +++- arch/arm/mach-davinci/board-dm646x-evm.c | 143 +++++++++---- arch/arm/mach-davinci/cdce949.c | 289 ++++++++++++++++++++++++++ arch/arm/mach-davinci/clock.c | 143 +++++-------- arch/arm/mach-davinci/clock.h | 29 ++- arch/arm/mach-davinci/common.c | 2 +- arch/arm/mach-davinci/cpuidle.c | 38 +--- arch/arm/mach-davinci/da830.c | 10 +- arch/arm/mach-davinci/da850.c | 86 +++++++-- arch/arm/mach-davinci/devices-da8xx.c | 210 +++++++++++++++++-- arch/arm/mach-davinci/dm355.c | 12 +- arch/arm/mach-davinci/dm365.c | 6 +- arch/arm/mach-davinci/dm644x.c | 18 +-- arch/arm/mach-davinci/dm646x.c | 44 +++-- arch/arm/mach-davinci/dma.c | 101 ++++++++-- arch/arm/mach-davinci/include/mach/cdce949.h | 19 ++ arch/arm/mach-davinci/include/mach/cpuidle.h | 1 + arch/arm/mach-davinci/include/mach/da8xx.h | 18 ++- arch/arm/mach-davinci/include/mach/dm365.h | 2 +- arch/arm/mach-davinci/include/mach/dm644x.h | 2 +- arch/arm/mach-davinci/include/mach/dm646x.h | 4 +- arch/arm/mach-davinci/include/mach/edma.h | 4 +- arch/arm/mach-davinci/include/mach/emac.h | 36 ---- arch/arm/mach-davinci/include/mach/memory.h | 5 + arch/arm/mach-davinci/include/mach/mux.h | 1 + arch/arm/mach-davinci/include/mach/pm.h | 54 +++++ arch/arm/mach-davinci/include/mach/psc.h | 15 ++ arch/arm/mach-davinci/include/mach/timex.h | 7 +- arch/arm/mach-davinci/pm.c | 158 ++++++++++++++ arch/arm/mach-davinci/psc.c | 17 +- arch/arm/mach-davinci/sleep.S | 224 ++++++++++++++++++++ drivers/net/Kconfig | 2 +- drivers/net/davinci_emac.c | 55 ++++-- include/linux/davinci_emac.h | 39 ++++ 37 files changed, 1494 insertions(+), 345 deletions(-) create mode 100644 arch/arm/mach-davinci/cdce949.c create mode 100644 arch/arm/mach-davinci/include/mach/cdce949.h delete mode 100644 arch/arm/mach-davinci/include/mach/emac.h create mode 100644 arch/arm/mach-davinci/include/mach/pm.h create mode 100644 arch/arm/mach-davinci/pm.c create mode 100644 arch/arm/mach-davinci/sleep.S create mode 100644 include/linux/davinci_emac.h
PATCH 1/35 davinci: da8xx/omapl1: add support for the second sysconfig module
From: Sekhar Nori <[email protected]>
OMAP-L138 adds a second SYSCFG region having useful functionality like deep sleep, pull up/down control and SATA clock stop.
This patch makes provision for accessing registers from second SYSCFG region in da8xx code.
Note that OMAP-L137 has a single SYSCFG region.
--- arch/arm/mach-davinci/board-da830-evm.c | 4 ++-- arch/arm/mach-davinci/board-da850-evm.c | 2 +- arch/arm/mach-davinci/da830.c | 8 ++++---- arch/arm/mach-davinci/da850.c | 20 ++++++++++++-------- arch/arm/mach-davinci/devices-da8xx.c | 3 ++- arch/arm/mach-davinci/include/mach/da8xx.h | 10 +++++++--- 6 files changed, 28 insertions(+), 19 deletions(-)
arch/arm/mach-davinci/board-da830-evm.c +2 -2
@@ -112,7 +112,7 @@ static __init void da830_evm_usb_init(void)* Set up USB clock/mode in the CFGCHIP2 register. * FYI: CFGCHIP2 is 0x0000ef00 initially. */ - cfgchip2 =__raw_readl (DA8XX_SYSCFG_VIRT (DA8XX_CFGCHIP2_REG )); + cfgchip2 =__raw_readl (DA8XX_SYSCFG0_VIRT (DA8XX_CFGCHIP2_REG ));/* USB2.0 PHY reference clock is 24 MHz */ cfgchip2 &= ~CFGCHIP2_REFFREQ ;
@@ -139,7 +139,7 @@ static __init void da830_evm_usb_init(void) cfgchip2 |=CFGCHIP2_SESENDEN |CFGCHIP2_VBDTCTEN ;#endif -__raw_writel (cfgchip2,DA8XX_SYSCFG_VIRT (DA8XX_CFGCHIP2_REG )); +__raw_writel (cfgchip2,DA8XX_SYSCFG0_VIRT (DA8XX_CFGCHIP2_REG ));/* USB_REFCLKIN is not used. */ ret =davinci_cfg_reg (DA830_USB0_DRVVBUS );
arch/arm/mach-davinci/board-da850-evm.c +1 -1
@@ -537,7 +537,7 @@ static int __init da850_evm_config_emac(void)if (!machine_is_davinci_da850_evm ())return 0 ; - cfg_chip3_base =DA8XX_SYSCFG_VIRT (DA8XX_CFGCHIP3_REG ); + cfg_chip3_base =DA8XX_SYSCFG0_VIRT (DA8XX_CFGCHIP3_REG ); val =__raw_readl (cfg_chip3_base);
arch/arm/mach-davinci/da830.c +4 -4
@@ -1208,13 +1208,13 @@ static struct davinci_soc_info davinci_soc_info_da830 = {void __init da830_init (void ) { - da8xx_syscfg_base =ioremap (DA8XX_SYSCFG_BASE ,SZ_4K ); -if (WARN (!da8xx_syscfg_base,"Unable to map syscfg module" )) + da8xx_syscfg0_base =ioremap (DA8XX_SYSCFG0_BASE ,SZ_4K ); +if (WARN (!da8xx_syscfg0_base,"Unable to map syscfg0 module" ))return ; davinci_soc_info_da830.jtag_id_base = -DA8XX_SYSCFG_VIRT (DA8XX_JTAG_ID_REG ); - davinci_soc_info_da830.pinmux_base =DA8XX_SYSCFG_VIRT (0x120 ); +DA8XX_SYSCFG0_VIRT (DA8XX_JTAG_ID_REG ); + davinci_soc_info_da830.pinmux_base =DA8XX_SYSCFG0_VIRT (0x120 );davinci_common_init (&davinci_soc_info_da830); }
arch/arm/mach-davinci/da850.c +12 -8
@@ -838,12 +838,12 @@ static void da850_set_async3_src(int pllnum) } } - v =__raw_readl (DA8XX_SYSCFG_VIRT (DA8XX_CFGCHIP3_REG )); + v =__raw_readl (DA8XX_SYSCFG0_VIRT (DA8XX_CFGCHIP3_REG ));if (pllnum) v |=CFGCHIP3_ASYNC3_CLKSRC ;else v &= ~CFGCHIP3_ASYNC3_CLKSRC ; -__raw_writel (v,DA8XX_SYSCFG_VIRT (DA8XX_CFGCHIP3_REG )); +__raw_writel (v,DA8XX_SYSCFG0_VIRT (DA8XX_CFGCHIP3_REG )); }#ifdef CONFIG_CPU_FREQ
@@ -996,9 +996,9 @@ static int da850_set_pll0rate(struct clk *clk, unsigned long index) postdiv = opp->postdiv;/* Unlock writing to PLL registers */ - v =__raw_readl (DA8XX_SYSCFG_VIRT (DA8XX_CFGCHIP0_REG )); + v =__raw_readl (DA8XX_SYSCFG0_VIRT (DA8XX_CFGCHIP0_REG )); v &= ~CFGCHIP0_PLL_MASTER_LOCK ; -__raw_writel (v,DA8XX_SYSCFG_VIRT (DA8XX_CFGCHIP0_REG )); +__raw_writel (v,DA8XX_SYSCFG0_VIRT (DA8XX_CFGCHIP0_REG )); ret =davinci_set_pllrate (pll, prediv, mult, postdiv);if (WARN_ON (ret))
@@ -1053,13 +1053,17 @@ static struct davinci_soc_info davinci_soc_info_da850 = {void __init da850_init (void ) { - da8xx_syscfg_base =ioremap (DA8XX_SYSCFG_BASE ,SZ_4K ); -if (WARN (!da8xx_syscfg_base,"Unable to map syscfg module" )) + da8xx_syscfg0_base =ioremap (DA8XX_SYSCFG0_BASE ,SZ_4K ); +if (WARN (!da8xx_syscfg0_base,"Unable to map syscfg0 module" )) +return ; + + da8xx_syscfg1_base =ioremap (DA8XX_SYSCFG1_BASE ,SZ_4K ); +if (WARN (!da8xx_syscfg1_base,"Unable to map syscfg1 module" ))return ; davinci_soc_info_da850.jtag_id_base = -DA8XX_SYSCFG_VIRT (DA8XX_JTAG_ID_REG ); - davinci_soc_info_da850.pinmux_base =DA8XX_SYSCFG_VIRT (0x120 ); +DA8XX_SYSCFG0_VIRT (DA8XX_JTAG_ID_REG ); + davinci_soc_info_da850.pinmux_base =DA8XX_SYSCFG0_VIRT (0x120 );davinci_common_init (&davinci_soc_info_da850);
arch/arm/mach-davinci/devices-da8xx.c +2 -1
@@ -42,7 +42,8 @@#define DA8XX_MDIO_REG_OFFSET 0x4000#define DA8XX_EMAC_CTRL_RAM_SIZE SZ_8K -void __iomem *da8xx_syscfg_base; +void __iomem *da8xx_syscfg0_base; +void __iomem *da8xx_syscfg1_base;static struct plat_serial8250_port da8xx_serial_pdata[] = { {
arch/arm/mach-davinci/include/mach/da8xx.h +7 -3
@@ -21,7 +21,8 @@#include <mach/mmc.h> #include <mach/usb.h> -extern void __iomem *da8xx_syscfg_base; +extern void __iomem *da8xx_syscfg0_base; +extern void __iomem *da8xx_syscfg1_base;/* * The cp_intc interrupt controller for the da8xx isn't in the same
@@ -34,13 +35,16 @@ extern void __iomem *da8xx_syscfg_base;#define DA8XX_CP_INTC_SIZE SZ_8K#define DA8XX_CP_INTC_VIRT (IO_VIRT - DA8XX_CP_INTC_SIZE - SZ_4K) -#define DA8XX_SYSCFG_BASE (IO_PHYS + 0x14000) -#define DA8XX_SYSCFG_VIRT (x) (da8xx_syscfg_base + (x)) +#define DA8XX_SYSCFG0_BASE (IO_PHYS + 0x14000) +#define DA8XX_SYSCFG0_VIRT (x) (da8xx_syscfg0_base + (x))#define DA8XX_JTAG_ID_REG 0x18#define DA8XX_CFGCHIP0_REG 0x17c#define DA8XX_CFGCHIP2_REG 0x184#define DA8XX_CFGCHIP3_REG 0x188 +#define DA8XX_SYSCFG1_BASE (IO_PHYS + 0x22C000) +#define DA8XX_SYSCFG1_VIRT (x) (da8xx_syscfg1_base + (x)) +#define DA8XX_PSC0_BASE 0x01c10000#define DA8XX_PLL0_BASE 0x01c11000#define DA8XX_TIMER64P0_BASE 0x01c20000
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 2/35 davinci: move PLL wait time values to clock.h
From: Sekhar Nori <[email protected]>
As suspend support is added, the code supporting the suspend operation needs to bypass PLLs and needs to access the same wait time values as the PLL code in clock.c.
To facilitate this, move the PLL wait times to clock.h where they can be accessed by suspend code.
--- arch/arm/mach-davinci/clock.c | 15 +++------------ arch/arm/mach-davinci/clock.h | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 12 deletions(-)
arch/arm/mach-davinci/clock.c +3 -12
@@ -376,7 +376,7 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv, locktime = ((2000 * prediv) /100 ); prediv = (prediv -1 ) |PLLDIV_EN ; }else { - locktime =20 ; + locktime =PLL_LOCK_TIME ; }if (postdiv) postdiv = (postdiv -1 ) |PLLDIV_EN ;
@@ -389,12 +389,7 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv, ctrl &= ~(PLLCTL_PLLENSRC |PLLCTL_PLLEN );__raw_writel (ctrl, pll->base +PLLCTL ); -/* -* Wait for 4 OSCIN/CLKIN cycles to ensure that the PLLC has switched -* to bypass mode. Delay of 1us ensures we are good for all > 4MHz -* OSCIN/CLKIN inputs. Typically the input is ~25MHz. -*/ -udelay (1 ); +udelay (PLL_BYPASS_TIME );/* Reset and enable PLL */ ctrl &= ~(PLLCTL_PLLRST |PLLCTL_PLLDIS );
@@ -408,11 +403,7 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,if (pll->flags &PLL_HAS_POSTDIV )__raw_writel (postdiv, pll->base +POSTDIV ); -/* -* Wait for PLL to reset properly, OMAP-L138 datasheet says -* 'min' time = 125ns -*/ -udelay (1 ); +udelay (PLL_RESET_TIME );/* Bring PLL out of reset */ ctrl |=PLLCTL_PLLRST ;
arch/arm/mach-davinci/clock.h +15 -0
@@ -53,6 +53,21 @@#define PLLDIV_EN BIT(15)#define PLLDIV_RATIO_MASK 0x1f +/* +* OMAP-L138 system reference guide recommends a wait for 4 OSCIN/CLKIN +* cycles to ensure that the PLLC has switched to bypass mode. Delay of 1us +* ensures we are good for all > 4MHz OSCIN/CLKIN inputs. Typically the input +* is ~25MHz. Units are micro seconds. +*/ +#define PLL_BYPASS_TIME 1 +/* From OMAP-L138 datasheet table 6-4. Units are micro seconds */ +#define PLL_RESET_TIME 1 +/* +* From OMAP-L138 datasheet table 6-4; assuming prediv = 1, sqrt(pllm) = 4 +* Units are micro seconds. +*/ +#define PLL_LOCK_TIME 20 +struct pll_data {u32 phys_base;void __iomem *base;
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 3/35 davinci: move DDR2 controller defines to memory.h
From: Sekhar Nori <[email protected]>
Move defintions of DDR2 controller registers to memory.h from cpuidle.c. The motivation behind the change is to be able to use these defintions in assembly code that puts DDR2 in self-refresh and enables the SoC to enter suspend state.
--- arch/arm/mach-davinci/cpuidle.c | 5 +---- arch/arm/mach-davinci/include/mach/memory.h | 4 ++++ 2 files changed, 5 insertions(+), 4 deletions(-)
arch/arm/mach-davinci/cpuidle.c +1 -4
@@ -19,6 +19,7 @@#include <asm/proc-fns.h> #include <mach/cpuidle.h> +#include <mach/memory.h> #define DAVINCI_CPUIDLE_MAX_STATES 2
@@ -39,10 +40,6 @@ static struct cpuidle_driver davinci_idle_driver = { static DEFINE_PER_CPU(struct cpuidle_device, davinci_cpuidle_device);static void __iomem *ddr2_reg_base; -#define DDR2_SDRCR_OFFSET 0xc -#define DDR2_SRPD_BIT BIT(23) -#define DDR2_LPMODEN_BIT BIT(31) -static void davinci_save_ddr_power (int enter,bool pdown) {u32 val;
arch/arm/mach-davinci/include/mach/memory.h +4 -0
@@ -31,6 +31,10 @@#define PHYS_OFFSET DAVINCI_DDR_BASE#endif +#define DDR2_SDRCR_OFFSET 0xc +#define DDR2_SRPD_BIT BIT(23) +#define DDR2_LPMODEN_BIT BIT(31) +/* * Increase size of DMA-consistent memory region */
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 4/35 davinci: move PSC register definitions from psc.c to psc.h
From: Sekhar Nori <[email protected]>
The motivation behind the change is to use the same definitions in the assembly code responsible for suspending the SoC, a part of which is to clock gate the DDR2 clock.
Note that the assembly code cannot invoke the C function meant for this. The main reason being that stack in DDR2 cannot be accessed while DDR2 clock is being clock gated.
--- arch/arm/mach-davinci/include/mach/psc.h | 11 +++++++++++ arch/arm/mach-davinci/psc.c | 11 ----------- 2 files changed, 11 insertions(+), 11 deletions(-)
arch/arm/mach-davinci/include/mach/psc.h +11 -0
@@ -180,6 +180,17 @@#define DA8XX_LPSC1_CR_P3_SS 26#define DA8XX_LPSC1_L3_CBA_RAM 31 +/* PSC register offsets */ +#define EPCPR 0x070 +#define PTCMD 0x120 +#define PTSTAT 0x128 +#define PDSTAT 0x200 +#define PDCTL1 0x304 +#define MDSTAT 0x800 +#define MDCTL 0xA00 + +#define MDSTAT_STATE_MASK 0x1f +extern int davinci_psc_is_clk_active (unsigned int ctlr,unsigned int id);extern void davinci_psc_config (unsigned int domain,unsigned int ctlr,unsigned int id,char enable);
arch/arm/mach-davinci/psc.c +0 -11
@@ -25,17 +25,6 @@#include <mach/cputype.h> #include <mach/psc.h> -/* PSC register offsets */ -#define EPCPR 0x070 -#define PTCMD 0x120 -#define PTSTAT 0x128 -#define PDSTAT 0x200 -#define PDCTL1 0x304 -#define MDSTAT 0x800 -#define MDCTL 0xA00 - -#define MDSTAT_STATE_MASK 0x1f -/* Return nonzero iff the domain's clock is active */ int __init davinci_psc_is_clk_active (unsigned int ctlr,unsigned int id) {
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 5/35 davinci: make it possible to include clock.h and psc.h in assembly code
From: Sekhar Nori <[email protected]>
psc.h contains register defines for PSC module which need to be accessed in assembly code which helps the DA850/OMAP-L138 SoC go to sleep. Shutting down DDR clock using PSC is a part of the sleep procedure.
Also, the PLL related hardware definitions in clock.h are needed in assembly code to bypass the DDR2 PLL.
--- arch/arm/mach-davinci/clock.h | 10 +++++++--- arch/arm/mach-davinci/include/mach/psc.h | 4 ++++ 2 files changed, 11 insertions(+), 3 deletions(-)
arch/arm/mach-davinci/clock.h +7 -3
@@ -12,9 +12,6 @@#ifndef __ARCH_ARM_DAVINCI_CLOCK_H#define __ARCH_ARM_DAVINCI_CLOCK_H -#include <linux/list.h> -#include <asm/clkdev.h> -#define DAVINCI_PLL1_BASE 0x01c40800#define DAVINCI_PLL2_BASE 0x01c40c00#define MAX_PLL 2
@@ -68,6 +65,11 @@*/ #define PLL_LOCK_TIME 20 +#ifndef __ASSEMBLER__ + +#include <linux/list.h> +#include <asm/clkdev.h> + struct pll_data { u32 phys_base; void __iomem *base;
@@ -124,3 +126,5 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,extern struct platform_device davinci_wdt_device;#endif + +#endif
arch/arm/mach-davinci/include/mach/psc.h +4 -0
@@ -191,8 +191,12 @@#define MDSTAT_STATE_MASK 0x1f +#ifndef __ASSEMBLER__ +extern int davinci_psc_is_clk_active (unsigned int ctlr,unsigned int id);extern void davinci_psc_config (unsigned int domain,unsigned int ctlr,unsigned int id,char enable); +#endif +#endif /* __ASM_ARCH_PSC_H */
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 6/35 davinci: cpuidle: move mapping of DDR2 controller registers out of driver
From: Sekhar Nori <[email protected]>
When suspend is supported, both cpuidle and suspend code need to work on DDR2 registers. Instead of mapping the DDR2 registers twice, do it once outside of cpuidle driver and let cpuidle driver get the virtual base address of DDR2 registers.
--- arch/arm/mach-davinci/cpuidle.c | 33 +++---------------------- arch/arm/mach-davinci/devices-da8xx.c | 16 +++++++++++- arch/arm/mach-davinci/include/mach/cpuidle.h | 1 + arch/arm/mach-davinci/include/mach/da8xx.h | 1 + 4 files changed, 21 insertions(+), 30 deletions(-)
arch/arm/mach-davinci/cpuidle.c +4 -29
@@ -106,8 +106,6 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev)int ret;struct cpuidle_device *device;struct davinci_cpuidle_config *pdata = pdev->dev.platform_data; -struct resource *ddr2_regs; -resource_size_t len; device = &per_cpu (davinci_cpuidle_device,smp_processor_id ());
@@ -116,28 +114,12 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev)return -ENOENT ; } - ddr2_regs =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); -if (!ddr2_regs) { -dev_err (&pdev->dev,"cannot get DDR2 controller register base" ); -return -ENODEV ; - } - - len =resource_size (ddr2_regs); - - ddr2_regs =request_mem_region (ddr2_regs->start, len, ddr2_regs->name); -if (!ddr2_regs) -return -EBUSY ; - - ddr2_reg_base =ioremap (ddr2_regs->start, len); -if (!ddr2_reg_base) { - ret = -ENOMEM ; - goto ioremap_fail; - } + ddr2_reg_base = pdata->ddr2_ctlr_base; ret =cpuidle_register_driver (&davinci_idle_driver);if (ret) {dev_err (&pdev->dev,"failed to register driver\n" ); - goto driver_register_fail; +return ret; }/* Wait for interrupt state */
@@ -164,18 +146,11 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev) ret =cpuidle_register_device (device);if (ret) {dev_err (&pdev->dev,"failed to register device\n" ); - goto device_register_fail; +cpuidle_unregister_driver (&davinci_idle_driver); +return ret; }return 0 ; - -device_register_fail: -cpuidle_unregister_driver (&davinci_idle_driver); -driver_register_fail: -iounmap (ddr2_reg_base); -ioremap_fail: -release_mem_region (ddr2_regs->start, len); -return ret; }static struct platform_driver davinci_cpuidle_driver = {
arch/arm/mach-davinci/devices-da8xx.c +15 -1
@@ -489,6 +489,19 @@ int da8xx_register_rtc(void)return platform_device_register (&da8xx_rtc_device); } +static void __iomem *da8xx_ddr2_ctlr_base; +void __iomem *__init da8xx_get_mem_ctlr (void ) +{ +if (da8xx_ddr2_ctlr_base) +return da8xx_ddr2_ctlr_base; + + da8xx_ddr2_ctlr_base =ioremap (DA8XX_DDR2_CTL_BASE ,SZ_32K ); +if (!da8xx_ddr2_ctlr_base) +pr_warning ("%s: Unable to map DDR2 controller" , __func__); + +return da8xx_ddr2_ctlr_base; +} +static struct resource da8xx_cpuidle_resources[] = { { .start =DA8XX_DDR2_CTL_BASE ,
@@ -514,6 +527,7 @@ static struct platform_device da8xx_cpuidle_device = {int __init da8xx_register_cpuidle (void ) { + da8xx_cpuidle_pdata.ddr2_ctlr_base =da8xx_get_mem_ctlr (); +return platform_device_register (&da8xx_cpuidle_device); } -
arch/arm/mach-davinci/include/mach/cpuidle.h +1 -0
@@ -12,6 +12,7 @@struct davinci_cpuidle_config {u32 ddr2_pdown; +void __iomem *ddr2_ctlr_base; };#endif
arch/arm/mach-davinci/include/mach/da8xx.h +1 -0
@@ -94,6 +94,7 @@ void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata);int da8xx_register_rtc (void );int da850_register_cpufreq (void );int da8xx_register_cpuidle (void ); +void __iomem *__init da8xx_get_mem_ctlr (void );extern struct platform_device da8xx_serial_device;extern struct emac_platform_data da8xx_emac_pdata;
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 7/35 davinci: da850/omap-l138: unlock PLL registers during init
From: Sekhar Nori <[email protected]>
On omap-l1 devices the PLL registers can be locked from writes. Currently the cpufreq rate setting code unlocks PLL0 before the write actually happens. With suspend support getting added PLL1 registers need be be unlocked as well.
To facilitate this, unlock both PLLs during the init time itself.
This also obviates the need to unlock PLL registers for each CPUFreq transtition.
--- arch/arm/mach-davinci/da850.c | 19 +++++++++++++------ 1 files changed, 13 insertions(+), 6 deletions(-)
arch/arm/mach-davinci/da850.c +13 -6
@@ -40,6 +40,7 @@#define DA850_REF_FREQ 24000000#define CFGCHIP3_ASYNC3_CLKSRC BIT(4) +#define CFGCHIP3_PLL1_MASTER_LOCK BIT(5)#define CFGCHIP0_PLL_MASTER_LOCK BIT(4)static int da850_set_armrate (struct clk *clk,unsigned long rate);
@@ -987,7 +988,6 @@ static int da850_set_pll0rate(struct clk *clk, unsigned long index)unsigned int prediv, mult, postdiv;struct da850_opp *opp;struct pll_data *pll = clk->pll_data; -unsigned int v;int ret; opp = (struct da850_opp *) da850_freq_table[index].index;
@@ -995,11 +995,6 @@ static int da850_set_pll0rate(struct clk *clk, unsigned long index) mult = opp->mult; postdiv = opp->postdiv; -/* Unlock writing to PLL registers */ - v =__raw_readl (DA8XX_SYSCFG0_VIRT (DA8XX_CFGCHIP0_REG )); - v &= ~CFGCHIP0_PLL_MASTER_LOCK ; -__raw_writel (v,DA8XX_SYSCFG0_VIRT (DA8XX_CFGCHIP0_REG )); - ret =davinci_set_pllrate (pll, prediv, mult, postdiv);if (WARN_ON (ret))return ret;
@@ -1053,6 +1048,8 @@ static struct davinci_soc_info davinci_soc_info_da850 = {void __init da850_init (void ) { +unsigned int v; + da8xx_syscfg0_base =ioremap (DA8XX_SYSCFG0_BASE ,SZ_4K );if (WARN (!da8xx_syscfg0_base,"Unable to map syscfg0 module" ))return ;
@@ -1075,4 +1072,14 @@ void __init da850_init(void)* be any noticible change even in non-DVFS use cases. */ da850_set_async3_src (1 ); + +/* Unlock writing to PLL0 registers */ + v =__raw_readl (DA8XX_SYSCFG0_VIRT (DA8XX_CFGCHIP0_REG )); + v &= ~CFGCHIP0_PLL_MASTER_LOCK ; +__raw_writel (v,DA8XX_SYSCFG0_VIRT (DA8XX_CFGCHIP0_REG )); + +/* Unlock writing to PLL1 registers */ + v =__raw_readl (DA8XX_SYSCFG0_VIRT (DA8XX_CFGCHIP3_REG )); + v &= ~CFGCHIP3_PLL1_MASTER_LOCK ; +__raw_writel (v,DA8XX_SYSCFG0_VIRT (DA8XX_CFGCHIP3_REG )); }
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 8/35 davinci: da850/omap-l138: create static map for SRAM
From: Sekhar Nori <[email protected]>
Create static map for internal SRAM and populate SRAM base and size in soc_info structure to allow SRAM allocation functions from arch/arm/mach-davinci/sram.c to work.
On DA850 SRAM is used for suspend-to-RAM implementation in places where DDR2 cannot be accessed as its clocks are stopped.
--- arch/arm/mach-davinci/da850.c | 8 ++++++++ arch/arm/mach-davinci/include/mach/da8xx.h | 1 + 2 files changed, 9 insertions(+), 0 deletions(-)
arch/arm/mach-davinci/da850.c +8 -0
@@ -771,6 +771,12 @@ static struct map_desc da850_io_desc[] = { .length = DA8XX_CP_INTC_SIZE, .type =MT_DEVICE }, + { + .virtual = SRAM_VIRT, + .pfn = __phys_to_pfn(DA8XX_ARM_RAM_BASE), + .length = SZ_8K, + .type =MT_DEVICE + }, }; static void __iomem *da850_psc_bases[] = {
@@ -1044,6 +1050,8 @@ static struct davinci_soc_info davinci_soc_info_da850 = { .gpio_irq = IRQ_DA8XX_GPIO0, .serial_dev = &da8xx_serial_device, .emac_pdata = &da8xx_emac_pdata, + .sram_dma = DA8XX_ARM_RAM_BASE, + .sram_len = SZ_8K, };void __init da850_init (void )
arch/arm/mach-davinci/include/mach/da8xx.h +1 -0
@@ -57,6 +57,7 @@ extern void __iomem *da8xx_syscfg1_base;#define DA8XX_AEMIF_CS3_BASE 0x62000000#define DA8XX_AEMIF_CTL_BASE 0x68000000#define DA8XX_DDR2_CTL_BASE 0xb0000000 +#define DA8XX_ARM_RAM_BASE 0xffff0000#define PINMUX0 0x00#define PINMUX1 0x04
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 9/35 davinci: explain CLOCK_TICK_RATE of 27MHz in include/mach/timex.h
From: Sekhar Nori <[email protected]>
Leave a comment explaining the constant value of 27Mhz used in include/mach/timex.h for all DaVinci platforms. Many of the platforms actually run at 24MHz timer frequency (Eg. EVMs of DM355, DM365 and OMAP-L1).
The comment also serves as a porting alert.
--- arch/arm/mach-davinci/include/mach/timex.h | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletions(-)
arch/arm/mach-davinci/include/mach/timex.h +6 -1
@@ -11,7 +11,12 @@#ifndef __ASM_ARCH_TIMEX_H#define __ASM_ARCH_TIMEX_H -/* The source frequency for the timers is the 27MHz clock */ +/* +* Alert: Not all timers of the DaVinci family run at a frequency of 27MHz, +* but we should be fine as long as CLOCK_TICK_RATE or LATCH (see include/ +* linux/jiffies.h) are not used directly in code. Currently none of the +* code relevant to DaVinci platform depends on these values directly. +*/ #define CLOCK_TICK_RATE 27000000#endif /* __ASM_ARCH_TIMEX_H__ */
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 10/35 davinci: board-dm646x-evm.c: arrange related code together
From: Sekhar Nori <[email protected]>
Currently all the #defines and static variables in the board-dm646x-evm.c file are located right at the start of the file because of which the related code is not together - making reading the code difficult.
This patch moves around the code keeping related code together.
--- arch/arm/mach-davinci/board-dm646x-evm.c | 90 +++++++++++++++--------------- 1 files changed, 45 insertions(+), 45 deletions(-)
arch/arm/mach-davinci/board-dm646x-evm.c +45 -45
@@ -40,53 +40,8 @@#include <mach/i2c.h> #include <mach/nand.h> -#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710 ) || \ - defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE ) -#define HAS_ATA 1 -#else -#define HAS_ATA 0 -#endif - -#define DAVINCI_ASYNC_EMIF_CONTROL_BASE 0x20008000 -#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE 0x42000000 -#define NAND_BLOCK_SIZE SZ_128K -/* CPLD Register 0 bits to control ATA */ -#define DM646X_EVM_ATA_RST BIT(0) -#define DM646X_EVM_ATA_PWD BIT(1) - -#define DM646X_EVM_PHY_MASK (0x2) -#define DM646X_EVM_MDIO_FREQUENCY (2200000)/* PHY bus frequency */ - -#define VIDCLKCTL_OFFSET (DAVINCI_SYSTEM_MODULE_BASE + 0x38) -#define VSCLKDIS_OFFSET (DAVINCI_SYSTEM_MODULE_BASE + 0x6c) -#define VCH2CLK_MASK (BIT_MASK(10) | BIT_MASK(9) | BIT_MASK(8)) -#define VCH2CLK_SYSCLK8 (BIT(9)) -#define VCH2CLK_AUXCLK (BIT(9) | BIT(8)) -#define VCH3CLK_MASK (BIT_MASK(14) | BIT_MASK(13) | BIT_MASK(12)) -#define VCH3CLK_SYSCLK8 (BIT(13)) -#define VCH3CLK_AUXCLK (BIT(14) | BIT(13)) - -#define VIDCH2CLK (BIT(10)) -#define VIDCH3CLK (BIT(11)) -#define VIDCH1CLK (BIT(4)) -#define TVP7002_INPUT (BIT(4)) -#define TVP5147_INPUT (~BIT(4)) -#define VPIF_INPUT_ONE_CHANNEL (BIT(5)) -#define VPIF_INPUT_TWO_CHANNEL (~BIT(5)) -#define TVP5147_CH0 "tvp514x-0" -#define TVP5147_CH1 "tvp514x-1" - -static void __iomem *vpif_vidclkctl_reg; -static void __iomem *vpif_vsclkdis_reg; -/* spin lock for updating above registers */ -static spinlock_t vpif_reg_lock; - -static struct davinci_uart_config uart_config__initdata = { - .enabled_uarts = (1 <<0 ), -}; -/* Note: We are setting first partition as 'bootloader' constituting UBL, U-Boot * and U-Boot environment this avoids dependency on any particular combination * of UBL, U-Boot or flashing tools etc.
@@ -120,6 +75,9 @@ static struct davinci_nand_pdata davinci_nand_data = { .options = 0, }; +#define DAVINCI_ASYNC_EMIF_CONTROL_BASE 0x20008000 +#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE 0x42000000 +static struct resource davinci_nand_resources[] = { { .start =DAVINCI_ASYNC_EMIF_DATA_CE0_BASE ,
@@ -144,6 +102,17 @@ static struct platform_device davinci_nand_device = { }, }; +#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710 ) || \ + defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE ) +#define HAS_ATA 1 +#else +#define HAS_ATA 0 +#endif + +/* CPLD Register 0 bits to control ATA */ +#define DM646X_EVM_ATA_RST BIT(0) +#define DM646X_EVM_ATA_PWD BIT(1) +/* CPLD Register 0 Client: used for I/O Control */ static int cpld_reg0_probe (struct i2c_client *client,const struct i2c_device_id *id)
@@ -424,6 +393,30 @@ static struct davinci_i2c_platform_data i2c_pdata = { .bus_delay = 0 /* usec */, }; +#define VIDCLKCTL_OFFSET (DAVINCI_SYSTEM_MODULE_BASE + 0x38) +#define VSCLKDIS_OFFSET (DAVINCI_SYSTEM_MODULE_BASE + 0x6c) +#define VCH2CLK_MASK (BIT_MASK(10) | BIT_MASK(9) | BIT_MASK(8)) +#define VCH2CLK_SYSCLK8 (BIT(9)) +#define VCH2CLK_AUXCLK (BIT(9) | BIT(8)) +#define VCH3CLK_MASK (BIT_MASK(14) | BIT_MASK(13) | BIT_MASK(12)) +#define VCH3CLK_SYSCLK8 (BIT(13)) +#define VCH3CLK_AUXCLK (BIT(14) | BIT(13)) + +#define VIDCH2CLK (BIT(10)) +#define VIDCH3CLK (BIT(11)) +#define VIDCH1CLK (BIT(4)) +#define TVP7002_INPUT (BIT(4)) +#define TVP5147_INPUT (~BIT(4)) +#define VPIF_INPUT_ONE_CHANNEL (BIT(5)) +#define VPIF_INPUT_TWO_CHANNEL (~BIT(5)) +#define TVP5147_CH0 "tvp514x-0" +#define TVP5147_CH1 "tvp514x-1" + +static void __iomem *vpif_vidclkctl_reg; +static void __iomem *vpif_vsclkdis_reg; +/* spin lock for updating above registers */ +static spinlock_t vpif_reg_lock; +static int set_vpif_clock (int mux_mode,int hd) {unsigned long flags;
@@ -690,6 +683,13 @@ static void __init davinci_map_io(void)dm646x_init (); } +static struct davinci_uart_config uart_config__initdata = { + .enabled_uarts = (1 <<0 ), +}; + +#define DM646X_EVM_PHY_MASK (0x2) +#define DM646X_EVM_MDIO_FREQUENCY (2200000)/* PHY bus frequency */ +static __init void evm_init (void ) {struct davinci_soc_info *soc_info = &davinci_soc_info;
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 11/35 davinci: add support for DM6467T EVM
From: Sekhar Nori <[email protected]>
DM6467T (T for Turbo) is a newer and faster DM6467 part from TI. The new part supports 1080p video and has the ARM running at 495MHz. More SoC information:
http://focus.ti.com/docs/prod/folders/print/tms320dm6467t.html
Spectrum Digital, Inc has a new EVM for this part. It is _mostly_ same as the older DM6467 EVM except for a 33MHz crystal input and THS8200 video encoder for 1080p support.
The meat of this patch is dedicated to initializing the crystal frequency from EVM board file.
Additional notes:
I did consider some alternative ways to make the crystal input board specific including - (1) having board code initialize the crystal frequency using the first member of soc_info->cpu_clks array (2) introducing a new ref_clk_rate member in soc_info structure.
But, the current way seems to be the simplest and least intruding considering that both the clock array and SoC info structure are actually private to the SoC file. Also the fact that davinci_common_init() initializes both the soc_info and clocks in one go.
--- arch/arm/mach-davinci/Kconfig | 4 ++++ arch/arm/mach-davinci/board-dm646x-evm.c | 24 ++++++++++++++++++++++++ arch/arm/mach-davinci/dm646x.c | 3 +-- arch/arm/mach-davinci/include/mach/dm646x.h | 2 ++ 4 files changed, 31 insertions(+), 2 deletions(-)
arch/arm/mach-davinci/Kconfig +4 -0
@@ -91,10 +91,14 @@ config MACH_DAVINCI_DM6467_EVM bool "TI DM6467 EVM" default ARCH_DAVINCI_DM646x depends on ARCH_DAVINCI_DM646x + select MACH_DAVINCI_DM6467TEVM help Configure this option to specify the whether the board used for development is a DM6467 EVM +config MACH_DAVINCI_DM6467TEVM + bool + config MACH_DAVINCI_DM365_EVM bool "TI DM365 EVM" default ARCH_DAVINCI_DM365
arch/arm/mach-davinci/board-dm646x-evm.c +24 -0
@@ -30,6 +30,7 @@#include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> +#include <linux/clk.h> #include <asm/mach-types.h> #include <asm/mach/arch.h>
@@ -40,6 +41,8 @@#include <mach/i2c.h> #include <mach/nand.h> +#include "clock.h" +#define NAND_BLOCK_SIZE SZ_128K/* Note: We are setting first partition as 'bootloader' constituting UBL, U-Boot
@@ -713,6 +716,17 @@ static __init void davinci_dm646x_evm_irq_init(void)davinci_irq_init (); } +#define DM646X_EVM_REF_FREQ 27000000 +#define DM6467T_EVM_REF_FREQ 33000000 + +void __init dm646x_board_setup_refclk (struct clk *clk) +{ +if (machine_is_davinci_dm6467tevm ()) + clk->rate =DM6467T_EVM_REF_FREQ ; +else + clk->rate =DM646X_EVM_REF_FREQ ; +} +MACHINE_START (DAVINCI_DM6467_EVM ,"DaVinci DM646x EVM" ) .phys_io = IO_PHYS, .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
@@ -723,3 +737,13 @@ MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM") .init_machine = evm_init, MACHINE_END +MACHINE_START (DAVINCI_DM6467TEVM ,"DaVinci DM6467T EVM" ) + .phys_io = IO_PHYS, + .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, + .boot_params = (0x80000100), + .map_io = davinci_map_io, + .init_irq = davinci_dm646x_evm_irq_init, + .timer = &davinci_timer, + .init_machine = evm_init, +MACHINE_END +
arch/arm/mach-davinci/dm646x.c +1 -2
@@ -42,7 +42,6 @@/* * Device specific clocks */ -#define DM646X_REF_FREQ 27000000#define DM646X_AUX_FREQ 24000000static struct pll_data pll1_data = {
@@ -57,7 +56,6 @@ static struct pll_data pll2_data = {static struct clk ref_clk = { .name ="ref_clk" , - .rate =DM646X_REF_FREQ , };static struct clk aux_clkin = {
@@ -925,6 +923,7 @@ void dm646x_setup_vpif(struct vpif_display_config *display_config,void __init dm646x_init (void ) { +dm646x_board_setup_refclk (&ref_clk);davinci_common_init (&davinci_soc_info_dm646x); }
arch/arm/mach-davinci/include/mach/dm646x.h +2 -0
@@ -16,6 +16,7 @@#include <mach/asp.h> #include <linux/i2c.h> #include <linux/videodev2.h> +#include <linux/clk.h> #define DM646X_EMAC_BASE (0x01C80000)#define DM646X_EMAC_CNTRL_OFFSET (0x0000)
@@ -30,6 +31,7 @@ void __init dm646x_init(void);void __init dm646x_init_ide (void );void __init dm646x_init_mcasp0 (struct snd_platform_data *pdata);void __init dm646x_init_mcasp1 (struct snd_platform_data *pdata); +void __init dm646x_board_setup_refclk (struct clk *clk);void dm646x_video_init (void );
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 12/35 davinci: clock framework: remove spinlock usage
From: Sekhar Nori <[email protected]>
Currently, the spinlock in DaVinci clock framework is being used to:
1) Protect clock structure variables usecount and rate against concurrent modification.
2) Protect against simultaneous PSC enables/disables ie. serialize davinci_psc_config().
3) Serialize clk_set_rate():
i. Prevent simultaneous setting of clock rates
ii. Ensure clock list remains sane during rate
propagation (also in clk_set_parent).
Remove the spinlock usage in clock framework by:
1) Making clock rate and usecount as atomic variables.
2) Making davinci_psc_config() protect itself instead of relying on serialization by caller.
3) (i) Allowing the clk->set_rate to serialize itself. There should be no need to serialize all clock rate settings. Currently the only user of rate setting is cpufreq driver on DA850. cpufreq naturally serializes the calls to set CPU rate. Also, there appears no need to lock IRQs during CPU rate transtitions. If required, IRQs can be locked in the actual set_rate function.
3) (ii) Use the mutex already in place for serialzing clock list manipulation for serializing clock rate propagation as well.
Apart from the general benefit of reducing locking granurlarity, the main motivation behind this change is to enable usage of clock framework for off-chip clock synthesizers. One such synthesizer, CDCE949, is present on DM6467 EVM. Access to the synthesizer happens through I2C bus - accessing which can lead to CPU sleep. Having IRQs locked in clk_set_rate prevents the clk->set_rate function from sleeping.
--- arch/arm/mach-davinci/board-dm646x-evm.c | 4 +- arch/arm/mach-davinci/clock.c | 74 ++++++++++++----------------- arch/arm/mach-davinci/clock.h | 4 +- arch/arm/mach-davinci/da830.c | 2 +- arch/arm/mach-davinci/da850.c | 4 +- arch/arm/mach-davinci/dm355.c | 4 +- arch/arm/mach-davinci/dm365.c | 4 +- arch/arm/mach-davinci/dm644x.c | 8 ++-- arch/arm/mach-davinci/dm646x.c | 8 ++-- arch/arm/mach-davinci/psc.c | 6 ++ 10 files changed, 56 insertions(+), 62 deletions(-)
arch/arm/mach-davinci/board-dm646x-evm.c +2 -2
@@ -722,9 +722,9 @@ static __init void davinci_dm646x_evm_irq_init(void)void __init dm646x_board_setup_refclk (struct clk *clk) {if (machine_is_davinci_dm6467tevm ()) - clk->rate =DM6467T_EVM_REF_FREQ ; +atomic_set (&clk->rate,DM6467T_EVM_REF_FREQ );else - clk->rate =DM646X_EVM_REF_FREQ ; +atomic_set (&clk->rate,DM646X_EVM_REF_FREQ ); }MACHINE_START (DAVINCI_DM6467_EVM ,"DaVinci DM646x EVM" )
arch/arm/mach-davinci/clock.c +31 -43
244 lines not on this page · raw message
arch/arm/mach-davinci/clock.h +2 -2
@@ -84,8 +84,8 @@ struct clk {struct list_head node;struct module *owner;const char *name; -unsigned long rate; -u8 usecount; +atomic_t rate; +atomic_t usecount;u8 lpsc;u8 gpsc;u32 flags;
arch/arm/mach-davinci/da830.c +1 -1
@@ -43,7 +43,7 @@ static struct pll_data pll0_data = {static struct clk ref_clk = { .name ="ref_clk" , - .rate =DA830_REF_FREQ , + .rate =ATOMIC_INIT (DA830_REF_FREQ ), };static struct clk pll0_clk = {
arch/arm/mach-davinci/da850.c +2 -2
@@ -55,7 +55,7 @@ static struct pll_data pll0_data = {static struct clk ref_clk = { .name ="ref_clk" , - .rate =DA850_REF_FREQ , + .rate =ATOMIC_INIT (DA850_REF_FREQ ), };static struct clk pll0_clk = {
@@ -1025,7 +1025,7 @@ static int da850_set_pll0rate(struct clk *clk, unsigned long armrate)static int da850_round_armrate (struct clk *clk,unsigned long rate) { -return clk->rate; +return atomic_read (&clk->rate); }#endif
arch/arm/mach-davinci/dm355.c +2 -2
@@ -55,7 +55,7 @@ static struct pll_data pll2_data = {static struct clk ref_clk = { .name ="ref_clk" ,/* FIXME -- crystal rate is board-specific */ - .rate =DM355_REF_FREQ , + .rate =ATOMIC_INIT (DM355_REF_FREQ ), };static struct clk pll1_clk = {
@@ -314,7 +314,7 @@ static struct clk timer2_clk = { .name = "timer2", .parent = &pll1_aux_clk, .lpsc = DAVINCI_LPSC_TIMER2, - .usecount = 1, /* REVISIT: why cant' this be disabled? */ + .usecount = ATOMIC_INIT(1), /* REVISIT: why cant' this be disabled? */ };static struct clk timer3_clk = {
arch/arm/mach-davinci/dm365.c +2 -2
@@ -52,7 +52,7 @@ static struct pll_data pll2_data = {static struct clk ref_clk = { .name ="ref_clk" , - .rate =DM365_REF_FREQ , + .rate =ATOMIC_INIT (DM365_REF_FREQ ), };static struct clk pll1_clk = {
@@ -358,7 +358,7 @@ static struct clk timer2_clk = { .name = "timer2", .parent = &pll1_aux_clk, .lpsc = DAVINCI_LPSC_TIMER2, - .usecount = 1, + .usecount = ATOMIC_INIT(1), };static struct clk timer3_clk = {
arch/arm/mach-davinci/dm644x.c +4 -4
@@ -47,7 +47,7 @@ static struct pll_data pll2_data = {static struct clk ref_clk = { .name ="ref_clk" , - .rate =DM644X_REF_FREQ , + .rate =ATOMIC_INIT (DM644X_REF_FREQ ), };static struct clk pll1_clk = {
@@ -131,7 +131,7 @@ static struct clk dsp_clk = { .parent = &pll1_sysclk1, .lpsc = DAVINCI_LPSC_GEM, .flags = PSC_DSP, - .usecount = 1, /* REVISIT how to disable? */ + .usecount = ATOMIC_INIT(1), /* REVISIT how to disable? */ };static struct clk arm_clk = {
@@ -146,7 +146,7 @@ static struct clk vicp_clk = { .parent = &pll1_sysclk2, .lpsc = DAVINCI_LPSC_IMCOP, .flags = PSC_DSP, - .usecount = 1, /* REVISIT how to disable? */ + .usecount = ATOMIC_INIT(1), /* REVISIT how to disable? */ };static struct clk vpss_master_clk = {
@@ -274,7 +274,7 @@ static struct clk timer2_clk = { .name = "timer2", .parent = &pll1_aux_clk, .lpsc = DAVINCI_LPSC_TIMER2, - .usecount = 1, /* REVISIT: why cant' this be disabled? */ + .usecount = ATOMIC_INIT(1), /* REVISIT: why cant' this be disabled? */ };struct davinci_clk dm644x_clks[] = {
arch/arm/mach-davinci/dm646x.c +4 -4
@@ -60,7 +60,7 @@ static struct clk ref_clk = {static struct clk aux_clkin = { .name ="aux_clkin" , - .rate =DM646X_AUX_FREQ , + .rate =ATOMIC_INIT (DM646X_AUX_FREQ ), };static struct clk pll1_clk = {
@@ -158,7 +158,7 @@ static struct clk dsp_clk = { .parent = &pll1_sysclk1, .lpsc = DM646X_LPSC_C64X_CPU, .flags = PSC_DSP, - .usecount = 1, /* REVISIT how to disable? */ + .usecount = ATOMIC_INIT(1), /* REVISIT how to disable? */ };static struct clk arm_clk = {
@@ -262,14 +262,14 @@ static struct clk pwm0_clk = { .name = "pwm0", .parent = &pll1_sysclk3, .lpsc = DM646X_LPSC_PWM0, - .usecount = 1, /* REVIST: disabling hangs system */ + .usecount = ATOMIC_INIT(1), /* REVIST: disabling hangs system */ };static struct clk pwm1_clk = { .name ="pwm1" , .parent = &pll1_sysclk3, .lpsc =DM646X_LPSC_PWM1 , - .usecount =1 ,/* REVIST: disabling hangs system */ + .usecount =ATOMIC_INIT (1 ),/* REVIST: disabling hangs system */ };static struct clk timer0_clk = {
arch/arm/mach-davinci/psc.c +6 -0
@@ -21,6 +21,7 @@#include <linux/kernel.h> #include <linux/init.h> #include <linux/io.h> +#include <linux/spinlock.h> #include <mach/cputype.h> #include <mach/psc.h>
@@ -53,6 +54,9 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr,void __iomem *psc_base;struct davinci_soc_info *soc_info = &davinci_soc_info;u32 next_state = enable ?0x3 :0x2 ;/* 0x3 enables, 0x2 disables */ +/* Protect against simultaneous enable/disable of PSCs */ +DEFINE_SPINLOCK (lock); +unsigned long flags;if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) { pr_warning("PSC: Bad psc data: 0x%x[%d]\n",
@@ -62,6 +66,7 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr, psc_base = soc_info->psc_bases[ctlr]; +spin_lock_irqsave (&lock, flags); mdctl =__raw_readl (psc_base +MDCTL +4 * id); mdctl &= ~MDSTAT_STATE_MASK ; mdctl |= next_state;
@@ -100,4 +105,5 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr,do { mdstat =__raw_readl (psc_base +MDSTAT +4 * id); }while (!((mdstat &MDSTAT_STATE_MASK ) == next_state)); +spin_unlock_irqrestore (&lock, flags); }
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 13/35 davinci: make /proc/davinci_clocks display multi-rooted clock tree
From: Sekhar Nori <[email protected]>
This patch modifies clock dump to take care of clock tress rooted at multiple oscillators. Current code assumes the entire tree is rooted on a single oscillator. When using off-chip clock synthesizers, some of the clocks can be obtained from a different on-board oscillator.
--- arch/arm/mach-davinci/clock.c | 11 +++++++---- 1 files changed, 7 insertions(+), 4 deletions(-)
arch/arm/mach-davinci/clock.c +7 -4
@@ -504,12 +504,15 @@ dump_clock(struct seq_file *s, unsigned nest, struct clk *parent)static int davinci_ck_show (struct seq_file *m,void *v) { -/* Show clock tree; we know the main oscillator is first. -* We trust nonzero usecounts equate to PSC enables... +struct clk *clk; + +/* +* Show clock tree; We trust nonzero usecounts equate to PSC enables... */ mutex_lock (&clocks_mutex); -if (!list_empty (&clocks)) - dump_clock(m, 0, list_first_entry(&clocks, struct clk, node)); +list_for_each_entry (clk, &clocks, node) +if (!clk->parent) +dump_clock (m,0 , clk);mutex_unlock (&clocks_mutex);return 0 ;
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 14/35 davinci: move /proc/davinci_clocks to debugfs
From: Sekhar Nori <[email protected]>
Move /proc/davinci_clocks to /sys/kernel/debug/davinci_clocks (debugfs).
debugfs is more suited for this since the clock dump is debug information.
--- arch/arm/mach-davinci/clock.c | 42 ++++++++++------------------------------ 1 files changed, 11 insertions(+), 31 deletions(-)
arch/arm/mach-davinci/clock.c +11 -31
@@ -446,24 +446,10 @@ int __init davinci_clk_init(struct davinci_clk *clocks)return 0 ; } -#ifdef CONFIG_PROC_FS -#include <linux/proc_fs.h> -#include <linux/seq_file.h> - -static void *davinci_ck_start (struct seq_file *m,loff_t *pos) -{ -return *pos <1 ? (void *)1 :NULL ; -} - -static void *davinci_ck_next (struct seq_file *m,void *v,loff_t *pos) -{ - ++*pos; -return NULL ; -} +#ifdef CONFIG_DEBUG_FS -static void davinci_ck_stop (struct seq_file *m,void *v) -{ -} +#include <linux/debugfs.h> +#include <linux/seq_file.h> #define CLKNAME_MAX 10/* longest clock name */ #define NEST_DELTA 2
@@ -518,30 +504,24 @@ static int davinci_ck_show(struct seq_file *m, void *v) return 0; } -static const struct seq_operations davinci_ck_op = { - .start = davinci_ck_start, - .next = davinci_ck_next, - .stop = davinci_ck_stop, - .show = davinci_ck_show -}; -static int davinci_ck_open (struct inode *inode,struct file *file) { -return seq_open (file, &davinci_ck_op); +return single_open (file, davinci_ck_show,NULL ); } -static const struct file_operations proc_davinci_ck_operations = { +static const struct file_operations davinci_ck_operations = { .open = davinci_ck_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = single_release, }; -static int __init davinci_ck_proc_init (void ) +static int __init davinci_clk_debugfs_init (void ) { -proc_create ("davinci_clocks" ,0 ,NULL , &proc_davinci_ck_operations); +debugfs_create_file ("davinci_clocks" ,S_IFREG |S_IRUGO ,NULL ,NULL , + &davinci_ck_operations);return 0 ; } -__initcall (davinci_ck_proc_init); -#endif /* CONFIG_DEBUG_PROC_FS */ +device_initcall (davinci_clk_debugfs_init); +#endif /* CONFIG_DEBUG_FS */
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 15/35 davinci: da850/omap-l138: Modify NOR partition info
From: Sudhakar Rajashekhara <[email protected]>
On DA850/OMAP-L138, NOR flash partition was starting from offset ZERO erasing the UBL and u-boot when the complete NOR is erased. This patch moves the start of the partition to 512K, after the bootloaders and u-boot env variables.
This patch also creates a new partition on NOR Flash to store Linux kernel image.
--- arch/arm/mach-davinci/board-da850-evm.c | 14 +++++++++++++- 1 files changed, 13 insertions(+), 1 deletions(-)
arch/arm/mach-davinci/board-da850-evm.c +13 -1
@@ -46,8 +46,20 @@static struct mtd_partition da850_evm_norflash_partition[] = { { - .name ="NOR filesystem" , + .name ="bootloaders + env" , .offset =0 , + .size =SZ_512K , + .mask_flags =MTD_WRITEABLE , + }, + { + .name ="kernel" , + .offset =MTDPART_OFS_APPEND , + .size =SZ_2M , + .mask_flags =0 , + }, + { + .name ="filesystem" , + .offset =MTDPART_OFS_APPEND , .size =MTDPART_SIZ_FULL , .mask_flags =0 , },
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 16/35 davinci: da850/omap-l138: Enable 4-bit ecc
From: Sudhakar Rajashekhara <[email protected]>
This patch initializes the platform data to enable 4-bit ecc support on DA850/OMAP-L138.
--- arch/arm/mach-davinci/board-da850-evm.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
arch/arm/mach-davinci/board-da850-evm.c +1 -0
@@ -131,6 +131,7 @@ static struct davinci_nand_pdata da850_evm_nandflash_data = { .parts = da850_evm_nandflash_partition, .nr_parts = ARRAY_SIZE(da850_evm_nandflash_partition), .ecc_mode = NAND_ECC_HW, + .ecc_bits = 4, .options = NAND_USE_FLASH_BBT, };
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 17/35 TI Davinci EMAC : Re-use driver for other platforms.
From: Sriramakrishnan <[email protected]>
The davinci EMAC peripheral is also available on other TI platforms -notably TI AM3517 SoC. This patch modifies the config option and the platform structure header files so that the driver can be reused on non-davinci platforms as well.
--- arch/arm/mach-davinci/common.c | 2 +- arch/arm/mach-davinci/include/mach/da8xx.h | 2 +- arch/arm/mach-davinci/include/mach/dm365.h | 2 +- arch/arm/mach-davinci/include/mach/dm644x.h | 2 +- arch/arm/mach-davinci/include/mach/dm646x.h | 2 +- arch/arm/mach-davinci/include/mach/emac.h | 36 --------------------------- drivers/net/Kconfig | 2 +- drivers/net/davinci_emac.c | 3 +- include/linux/davinci_emac.h | 36 +++++++++++++++++++++++++++ 9 files changed, 43 insertions(+), 44 deletions(-) delete mode 100644 arch/arm/mach-davinci/include/mach/emac.h create mode 100644 include/linux/davinci_emac.h
arch/arm/mach-davinci/common.c +1 -1
@@ -11,13 +11,13 @@#include <linux/module.h> #include <linux/io.h> #include <linux/etherdevice.h> +#include <linux/davinci_emac.h> #include <asm/tlb.h> #include <asm/mach/map.h> #include <mach/common.h> #include <mach/cputype.h> -#include <mach/emac.h> #include "clock.h"
arch/arm/mach-davinci/include/mach/da8xx.h +1 -1
@@ -13,10 +13,10 @@#include <video/da8xx-fb.h> +#include <linux/davinci_emac.h> #include <mach/serial.h> #include <mach/edma.h> #include <mach/i2c.h> -#include <mach/emac.h> #include <mach/asp.h> #include <mach/mmc.h> #include <mach/usb.h>
arch/arm/mach-davinci/include/mach/dm365.h +1 -1
@@ -14,8 +14,8 @@#define __ASM_ARCH_DM665_H#include <linux/platform_device.h> +#include <linux/davinci_emac.h> #include <mach/hardware.h> -#include <mach/emac.h> #include <mach/asp.h> #include <mach/keyscan.h>
arch/arm/mach-davinci/include/mach/dm644x.h +1 -1
@@ -22,8 +22,8 @@#ifndef __ASM_ARCH_DM644X_H#define __ASM_ARCH_DM644X_H +#include <linux/davinci_emac.h> #include <mach/hardware.h> -#include <mach/emac.h> #include <mach/asp.h> #include <media/davinci/vpfe_capture.h>
arch/arm/mach-davinci/include/mach/dm646x.h +1 -1
@@ -12,11 +12,11 @@#define __ASM_ARCH_DM646X_H#include <mach/hardware.h> -#include <mach/emac.h> #include <mach/asp.h> #include <linux/i2c.h> #include <linux/videodev2.h> #include <linux/clk.h> +#include <linux/davinci_emac.h> #define DM646X_EMAC_BASE (0x01C80000)#define DM646X_EMAC_CNTRL_OFFSET (0x0000)
arch/arm/mach-davinci/include/mach/emac.h deleted +0 -36
@@ -1,36 +0,0 @@ -/* -* TI DaVinci EMAC platform support -* -* Author: Kevin Hilman, Deep Root Systems, LLC -* -* 2007 (c) Deep Root Systems, LLC. This file is licensed under -* the terms of the GNU General Public License version 2. This program -* is licensed "as is" without any warranty of any kind, whether express -* or implied. -*/ -#ifndef _MACH_DAVINCI_EMAC_H -#define _MACH_DAVINCI_EMAC_H - -#include <linux/if_ether.h> -#include <linux/memory.h> - -struct emac_platform_data { -char mac_addr[ETH_ALEN ]; -u32 ctrl_reg_offset; -u32 ctrl_mod_reg_offset; -u32 ctrl_ram_offset; -u32 mdio_reg_offset; -u32 ctrl_ram_size; -u32 phy_mask; -u32 mdio_max_freq; -u8 rmii_en; -u8 version; -}; - -enum { -EMAC_VERSION_1 ,/* DM644x */ -EMAC_VERSION_2 ,/* DM646x */ -}; - -void davinci_get_mac_addr (struct memory_accessor *mem_acc,void *context); -#endif
drivers/net/Kconfig +1 -1
@@ -920,7 +920,7 @@ config NET_NETX config TI_DAVINCI_EMAC tristate "TI DaVinci EMAC Support" - depends on ARM && ARCH_DAVINCI + depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) select PHYLIB help This driver supports TI's DaVinci Ethernet .
drivers/net/davinci_emac.c +1 -2
@@ -62,12 +62,11 @@#include <linux/bitops.h> #include <linux/io.h> #include <linux/uaccess.h> +#include <linux/davinci_emac.h> #include <asm/irq.h> #include <asm/page.h> -#include <mach/emac.h> -static int debug_level;module_param (debug_level, int,0 );MODULE_PARM_DESC (debug_level,"DaVinci EMAC debug level (NETIF_MSG bits)" );
include/linux/davinci_emac.h new file +36 -0
@@ -0,0 +1,36 @@ +/* +* TI DaVinci EMAC platform support +* +* Author: Kevin Hilman, Deep Root Systems, LLC +* +* 2007 (c) Deep Root Systems, LLC. This file is licensed under +* the terms of the GNU General Public License version 2. This program +* is licensed "as is" without any warranty of any kind, whether express +* or implied. +*/ +#ifndef _LINUX_DAVINCI_EMAC_H +#define _LINUX_DAVINCI_EMAC_H + +#include <linux/if_ether.h> +#include <linux/memory.h> + +struct emac_platform_data { +char mac_addr[ETH_ALEN ]; +u32 ctrl_reg_offset; +u32 ctrl_mod_reg_offset; +u32 ctrl_ram_offset; +u32 mdio_reg_offset; +u32 ctrl_ram_size; +u32 phy_mask; +u32 mdio_max_freq; +u8 rmii_en; +u8 version; +}; + +enum { +EMAC_VERSION_1 ,/* DM644x */ +EMAC_VERSION_2 ,/* DM646x */ +}; + +void davinci_get_mac_addr (struct memory_accessor *mem_acc,void *context); +#endif
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 18/35 TI Davinci EMAC : add platform specific interrupt enable/disable logic.
From: Sriramakrishnan <[email protected]>
On certain SOCs, the EMAC controller is interfaced with a wrapper logic for handling interrupts. This patch implements a platform specific hook to cater to platforms that require custom interrupt handling logic
--- drivers/net/davinci_emac.c | 11 +++++++++++ include/linux/davinci_emac.h | 2 ++ 2 files changed, 13 insertions(+), 0 deletions(-)
drivers/net/davinci_emac.c +11 -0
@@ -487,6 +487,9 @@ struct emac_priv {struct mii_bus *mii_bus;struct phy_device *phydev;spinlock_t lock; +/*platform specific members*/ +void (*int_enable) (void ); +void (*int_disable) (void ); };/* clock frequency for EMAC */
@@ -1001,6 +1004,8 @@ static void emac_int_disable(struct emac_priv *priv)emac_ctrl_write (EMAC_DM646X_CMRXINTEN ,0x0 );emac_ctrl_write (EMAC_DM646X_CMTXINTEN ,0x0 );/* NOTE: Rx Threshold and Misc interrupts are not disabled */ +if (priv->int_disable) + priv->int_disable ();local_irq_restore (flags);
@@ -1020,6 +1025,9 @@ static void emac_int_disable(struct emac_priv *priv)static void emac_int_enable (struct emac_priv *priv) {if (priv->version ==EMAC_VERSION_2 ) { +if (priv->int_enable) + priv->int_enable (); +emac_ctrl_write (EMAC_DM646X_CMRXINTEN ,0xff );emac_ctrl_write (EMAC_DM646X_CMTXINTEN ,0xff );
@@ -2659,6 +2667,9 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) priv->phy_mask = pdata->phy_mask; priv->rmii_en = pdata->rmii_en; priv->version = pdata->version; + priv->int_enable = pdata->interrupt_enable; + priv->int_disable = pdata->interrupt_disable; + emac_dev = &ndev->dev;/* Get EMAC platform data */ res =platform_get_resource (pdev,IORESOURCE_MEM ,0 );
include/linux/davinci_emac.h +2 -0
@@ -25,6 +25,8 @@ struct emac_platform_data {u32 mdio_max_freq;u8 rmii_en;u8 version; +void (*interrupt_enable) (void ); +void (*interrupt_disable) (void ); };enum {
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 19/35 TI Davinci EMAC : Abstract Buffer address translation logic.
From: Sriramakrishnan <[email protected]>
When programming the DMA engine, the next pointers must be programmed with physical address as seen from the DMA master address space. This address may be different from physical address of the buffer RAM area. This patch abstracts the buffer address translation logic.
--- drivers/net/davinci_emac.c | 41 ++++++++++++++++++++++++----------------- include/linux/davinci_emac.h | 1 + 2 files changed, 25 insertions(+), 17 deletions(-)
drivers/net/davinci_emac.c +24 -17
@@ -464,6 +464,7 @@ struct emac_priv {void __iomem *ctrl_base;void __iomem *emac_ctrl_ram;u32 ctrl_ram_size; +u32 hw_ram_addr;struct emac_txch *txch[EMAC_DEF_MAX_TX_CH ];struct emac_rxch *rxch[EMAC_DEF_MAX_RX_CH ];u32 link;/* 1=link on, 0=link off */
@@ -497,11 +498,9 @@ static struct clk *emac_clk;static unsigned long emac_bus_frequency;static unsigned long mdio_max_freq; -/* EMAC internal utility function */ -static inline u32 emac_virt_to_phys (void __iomem *addr) -{ -return (u32 __force )io_v2p (addr); -} +#define emac_virt_to_phys (addr, priv) \ + (((u32 __force)(addr) - (u32 __force)(priv->emac_ctrl_ram)) \ + + priv->hw_ram_addr)/* Cache macros - Packet buffers would be from skb pool which is cached */ #define EMAC_VIRT_NOCACHE (addr) (addr)
@@ -1309,7 +1308,7 @@ static int emac_tx_bdproc(struct emac_priv *priv, u32 ch, u32 budget) curr_bd = txch->active_queue_head;if (NULL == curr_bd) {emac_write (EMAC_TXCP (ch), -emac_virt_to_phys (txch->last_hw_bdprocessed)); +emac_virt_to_phys (txch->last_hw_bdprocessed, priv)); txch->no_active_pkts++;spin_unlock_irqrestore (&priv->tx_lock, flags);return 0 ;
@@ -1319,7 +1318,7 @@ static int emac_tx_bdproc(struct emac_priv *priv, u32 ch, u32 budget)while ((curr_bd) && ((frame_status &EMAC_CPPI_OWNERSHIP_BIT ) ==0 ) && (pkts_processed < budget)) { -emac_write (EMAC_TXCP (ch),emac_virt_to_phys (curr_bd)); +emac_write (EMAC_TXCP (ch),emac_virt_to_phys (curr_bd, priv)); txch->active_queue_head = curr_bd->next;if (frame_status &EMAC_CPPI_EOQ_BIT ) {if (curr_bd->next) {/* misqueued packet */
@@ -1406,7 +1405,7 @@ static int emac_send(struct emac_priv *priv, struct emac_netpktobj *pkt, u32 ch) txch->active_queue_tail = curr_bd;if (1 != txch->queue_active) {emac_write (EMAC_TXHDP (ch), -emac_virt_to_phys (curr_bd)); +emac_virt_to_phys (curr_bd, priv)); txch->queue_active =1 ; } ++txch->queue_reinit;
@@ -1418,10 +1417,11 @@ static int emac_send(struct emac_priv *priv, struct emac_netpktobj *pkt, u32 ch) tail_bd->next = curr_bd; txch->active_queue_tail = curr_bd; tail_bd =EMAC_VIRT_NOCACHE (tail_bd); - tail_bd->h_next = (int )emac_virt_to_phys (curr_bd); + tail_bd->h_next = (int )emac_virt_to_phys (curr_bd, priv); frame_status = tail_bd->mode;if (frame_status &EMAC_CPPI_EOQ_BIT ) { -emac_write (EMAC_TXHDP (ch),emac_virt_to_phys (curr_bd)); +emac_write (EMAC_TXHDP (ch), +emac_virt_to_phys (curr_bd, priv)); frame_status &= ~(EMAC_CPPI_EOQ_BIT ); tail_bd->mode = frame_status; ++txch->end_of_queue_add;
@@ -1611,7 +1611,8 @@ static int emac_init_rxch(struct emac_priv *priv, u32 ch, char *param) }/* populate the hardware descriptor */ - curr_bd->h_next =emac_virt_to_phys (rxch->active_queue_head); + curr_bd->h_next =emac_virt_to_phys (rxch->active_queue_head, + priv);/* FIXME buff_ptr = dma_map_single(... data_ptr ...) */ curr_bd->buff_ptr =virt_to_phys (curr_bd->data_ptr); curr_bd->off_b_len = rxch->buf_size;
@@ -1886,7 +1887,7 @@ static void emac_addbd_to_rx_queue(struct emac_priv *priv, u32 ch, rxch->active_queue_tail = curr_bd;if (0 != rxch->queue_active) {emac_write (EMAC_RXHDP (ch), -emac_virt_to_phys (rxch->active_queue_head)); +emac_virt_to_phys (rxch->active_queue_head, priv)); rxch->queue_active =1 ; } }else {
@@ -1897,11 +1898,11 @@ static void emac_addbd_to_rx_queue(struct emac_priv *priv, u32 ch, rxch->active_queue_tail = curr_bd; tail_bd->next = curr_bd; tail_bd =EMAC_VIRT_NOCACHE (tail_bd); - tail_bd->h_next =emac_virt_to_phys (curr_bd); + tail_bd->h_next =emac_virt_to_phys (curr_bd, priv); frame_status = tail_bd->mode;if (frame_status &EMAC_CPPI_EOQ_BIT ) {emac_write (EMAC_RXHDP (ch), -emac_virt_to_phys (curr_bd)); +emac_virt_to_phys (curr_bd, priv)); frame_status &= ~(EMAC_CPPI_EOQ_BIT ); tail_bd->mode = frame_status; ++rxch->end_of_queue_add;
@@ -1994,7 +1995,7 @@ static int emac_rx_bdproc(struct emac_priv *priv, u32 ch, u32 budget) curr_pkt->num_bufs =1 ; curr_pkt->pkt_length = (frame_status &EMAC_RX_BD_PKT_LENGTH_MASK ); -emac_write (EMAC_RXCP (ch),emac_virt_to_phys (curr_bd)); +emac_write (EMAC_RXCP (ch),emac_virt_to_phys (curr_bd, priv)); ++rxch->processed_bd; last_bd = curr_bd; curr_bd = last_bd->next;
@@ -2005,7 +2006,7 @@ static int emac_rx_bdproc(struct emac_priv *priv, u32 ch, u32 budget)if (curr_bd) { ++rxch->mis_queued_packets;emac_write (EMAC_RXHDP (ch), -emac_virt_to_phys (curr_bd)); +emac_virt_to_phys (curr_bd, priv)); }else { ++rxch->end_of_queue; rxch->queue_active =0 ;
@@ -2106,7 +2107,7 @@ static int emac_hw_enable(struct emac_priv *priv)emac_write (EMAC_RXINTMASKSET ,BIT (ch)); rxch->queue_active =1 ;emac_write (EMAC_RXHDP (ch), -emac_virt_to_phys (rxch->active_queue_head)); +emac_virt_to_phys (rxch->active_queue_head, priv)); }/* Enable MII */
@@ -2702,6 +2703,12 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) priv->ctrl_ram_size = pdata->ctrl_ram_size; priv->emac_ctrl_ram = priv->remap_addr + pdata->ctrl_ram_offset; +if (pdata->hw_ram_addr) + priv->hw_ram_addr = pdata->hw_ram_addr; +else + priv->hw_ram_addr = (u32 __force )res->start + + pdata->ctrl_ram_offset; + res =platform_get_resource (pdev,IORESOURCE_IRQ ,0 );if (!res) {dev_err (emac_dev,"DaVinci EMAC: Error getting irq res\n" );
include/linux/davinci_emac.h +1 -0
@@ -19,6 +19,7 @@ struct emac_platform_data {u32 ctrl_reg_offset;u32 ctrl_mod_reg_offset;u32 ctrl_ram_offset; +u32 hw_ram_addr;u32 mdio_reg_offset;u32 ctrl_ram_size;u32 phy_mask;
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 20/35 davinci: clock: Check CLK_PSC flag before disabling PSC
From: Chaithrika U S <[email protected]>
Some modules do not have PSC to control their clocks. The 'lpsc' field in the clk structure is 0 for such clocks.
In the clock disable function check for CLK PSC flag before disabling the PSC. If this is not taken care of then it may so happen that module controlled by LPSC 0 is erroneously disabled.
--- arch/arm/mach-davinci/clock.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
arch/arm/mach-davinci/clock.c +2 -1
@@ -49,7 +49,8 @@ static void __clk_disable(struct clk *clk) {if (WARN_ON (atomic_read (&clk->usecount) ==0 ))return ; -if (atomic_dec_and_test (&clk->usecount) && !(clk->flags &CLK_PLL )) +if (atomic_dec_and_test (&clk->usecount) && !(clk->flags &CLK_PLL ) + && (clk->flags &CLK_PSC ))davinci_psc_config (psc_domain (clk), clk->gpsc, clk->lpsc,0 );if (clk->parent)__clk_disable (clk->parent);
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 21/35 DaVinci: DM365: Changing default queue for DM365.
From: Sandeep Paulraj <[email protected]>
In DM365 Q0, Q1 and Q2 are used by codecs. LSP drivers should use Q3.
This patch changes the default queue for DM365.
--- arch/arm/mach-davinci/dm365.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/arm/mach-davinci/dm365.c +1 -1
@@ -754,7 +754,7 @@ static struct edma_soc_info dm365_edma_info[] = { .n_cc = 1, .queue_tc_mapping = dm365_queue_tc_mapping, .queue_priority_mapping = dm365_queue_priority_mapping, - .default_queue = EVENTQ_2, + .default_queue = EVENTQ_3, }, };
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 22/35 davinci: add power management support
From: Sekhar Nori <[email protected]>
This patch adds core power management (suspend-to-RAM) support for DaVinci SoCs.
The code depends on the the "deepsleep" feature to suspend the SoC and saves power by gating the input clock.
The wakeup can be based on an external event as supported by the SoC.
Assembly code (in sleep.S) is added to aid gating DDR2 clocks. Code doing this work should not be accessing DDR2. The assembly code is relocated to SRAM by the code in pm.c
The support has been validated on DA850/OMAP-L138 only though the code is (hopefully) generic enough that other SoCs supporting deepsleep feature simply requires SoC specific code to start using this driver.
Note that all the device drivers don't support suspend/resume still and are being worked on.
--- arch/arm/mach-davinci/Makefile | 1 + arch/arm/mach-davinci/include/mach/memory.h | 1 + arch/arm/mach-davinci/include/mach/pm.h | 54 +++++++ arch/arm/mach-davinci/pm.c | 158 +++++++++++++++++++ arch/arm/mach-davinci/sleep.S | 224 +++++++++++++++++++++++++++ 5 files changed, 438 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/include/mach/pm.h create mode 100644 arch/arm/mach-davinci/pm.c create mode 100644 arch/arm/mach-davinci/sleep.S
arch/arm/mach-davinci/Makefile +1 -0
@@ -34,3 +34,4 @@ obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o # Power Management obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o +obj-$(CONFIG_SUSPEND) += pm.o sleep.o
arch/arm/mach-davinci/include/mach/memory.h +1 -0
@@ -33,6 +33,7 @@#define DDR2_SDRCR_OFFSET 0xc#define DDR2_SRPD_BIT BIT(23) +#define DDR2_MCLKSTOPEN_BIT BIT(30)#define DDR2_LPMODEN_BIT BIT(31)/*
arch/arm/mach-davinci/include/mach/pm.h new file +54 -0
54 lines not on this page · raw message
arch/arm/mach-davinci/pm.c new file +158 -0
158 lines not on this page · raw message
arch/arm/mach-davinci/sleep.S new file +224 -0
224 lines not on this page · raw message
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 23/35 davinci: da850/omap-l138: add support for SoC suspend
From: Sekhar Nori <[email protected]>
This patch adds support for registering for suspend-to-RAM functionality on da850/omap-l138 SoCs.
da850 supports wakeup based on external event and RTC alarm.
Currently only RTC alarm based wakeup is supported. Support for wakeup based on external event will be added as later improvements.
For scheduling an alarm event on RTC some useful code is present in Documentation/rtc.txt
--- arch/arm/mach-davinci/da850.c | 39 ++++++++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/da8xx.h | 4 +++ arch/arm/mach-davinci/include/mach/mux.h | 1 + 3 files changed, 44 insertions(+), 0 deletions(-)
arch/arm/mach-davinci/da850.c +39 -0
@@ -26,6 +26,7 @@#include <mach/time.h> #include <mach/da8xx.h> #include <mach/cpufreq.h> +#include <mach/pm.h> #include "clock.h" #include "mux.h"
@@ -536,6 +537,7 @@ static const struct mux_config da850_pins[] = { MUX_CFG(DA850, GPIO2_15, 5, 0, 15, 8, false) MUX_CFG(DA850, GPIO4_0, 10, 28, 15, 8, false) MUX_CFG(DA850, GPIO4_1, 10, 24, 15, 8, false) + MUX_CFG(DA850, RTC_ALARM, 0, 28, 15, 2, false)#endif };
@@ -1029,6 +1031,43 @@ static int da850_round_armrate(struct clk *clk, unsigned long rate) }#endif +int da850_register_pm (struct platform_device *pdev) +{ +int ret; +struct davinci_pm_config *pdata = pdev->dev.platform_data; + + ret =davinci_cfg_reg (DA850_RTC_ALARM ); +if (ret) +return ret; + + pdata->ddr2_ctlr_base =da8xx_get_mem_ctlr (); + pdata->deepsleep_reg =DA8XX_SYSCFG1_VIRT (DA8XX_DEEPSLEEP_REG ); + pdata->ddrpsc_num =DA8XX_LPSC1_EMIF3C ; + + pdata->cpupll_reg_base =ioremap (DA8XX_PLL0_BASE ,SZ_4K ); +if (!pdata->cpupll_reg_base) +return -ENOMEM ; + + pdata->ddrpll_reg_base =ioremap (DA8XX_PLL1_BASE ,SZ_4K ); +if (!pdata->ddrpll_reg_base) { + ret = -ENOMEM ; + goto no_ddrpll_mem; + } + + pdata->ddrpsc_reg_base =ioremap (DA8XX_PSC1_BASE ,SZ_4K ); +if (!pdata->ddrpsc_reg_base) { + ret = -ENOMEM ; + goto no_ddrpsc_mem; + } + +return platform_device_register (pdev); + +no_ddrpsc_mem: +iounmap (pdata->ddrpll_reg_base); +no_ddrpll_mem: +iounmap (pdata->cpupll_reg_base); +return ret; +}static struct davinci_soc_info davinci_soc_info_da850 = { .io_desc = da850_io_desc,
arch/arm/mach-davinci/include/mach/da8xx.h +4 -0
@@ -20,6 +20,7 @@#include <mach/asp.h> #include <mach/mmc.h> #include <mach/usb.h> +#include <mach/pm.h> extern void __iomem *da8xx_syscfg0_base;extern void __iomem *da8xx_syscfg1_base;
@@ -44,6 +45,7 @@ extern void __iomem *da8xx_syscfg1_base;#define DA8XX_SYSCFG1_BASE (IO_PHYS + 0x22C000)#define DA8XX_SYSCFG1_VIRT (x) (da8xx_syscfg1_base + (x)) +#define DA8XX_DEEPSLEEP_REG 0x8#define DA8XX_PSC0_BASE 0x01c10000#define DA8XX_PLL0_BASE 0x01c11000
@@ -52,6 +54,7 @@ extern void __iomem *da8xx_syscfg1_base;#define DA8XX_GPIO_BASE 0x01e26000#define DA8XX_PSC1_BASE 0x01e27000#define DA8XX_LCD_CNTRL_BASE 0x01e13000 +#define DA8XX_PLL1_BASE 0x01e1a000#define DA8XX_MMCSD0_BASE 0x01c40000#define DA8XX_AEMIF_CS2_BASE 0x60000000#define DA8XX_AEMIF_CS3_BASE 0x62000000
@@ -96,6 +99,7 @@ int da8xx_register_rtc(void);int da850_register_cpufreq (void );int da8xx_register_cpuidle (void );void __iomem *__init da8xx_get_mem_ctlr (void ); +int da850_register_pm (struct platform_device *pdev);extern struct platform_device da8xx_serial_device;extern struct emac_platform_data da8xx_emac_pdata;
arch/arm/mach-davinci/include/mach/mux.h +1 -0
@@ -899,6 +899,7 @@ enum davinci_da850_index {DA850_GPIO2_15 ,DA850_GPIO4_0 ,DA850_GPIO4_1 , + DA850_RTC_ALARM, };#ifdef CONFIG_DAVINCI_MUX
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 24/35 davinci: da850/omap-l138 EVM: register for suspend support
From: Sekhar Nori <[email protected]>
--- arch/arm/mach-davinci/board-da850-evm.c | 17 +++++++++++++++++ 1 files changed, 17 insertions(+), 0 deletions(-)
arch/arm/mach-davinci/board-da850-evm.c +17 -0
@@ -89,6 +89,18 @@ static struct platform_device da850_evm_norflash_device = { .resource = da850_evm_norflash_resource, }; +static struct davinci_pm_config da850_pm_pdata = { + .sleepcount =128 , +}; + +static struct platform_device da850_pm_device = { + .name ="pm-davinci" , + .dev = { + .platform_data = &da850_pm_pdata, + }, + .id =-1 , +}; +/* DA850/OMAP-L138 EVM includes a 512 MByte large-page NAND flash * (128K blocks). It may be used instead of the (default) SPI flash * to boot, using TI's tools to install the secondary boot loader
@@ -709,6 +721,11 @@ static __init void da850_evm_init(void)if (ret)pr_warning ("da850_evm_init: cpuidle registration failed: %d\n" , ret); + + ret =da850_register_pm (&da850_pm_device); +if (ret) +pr_warning ("da850_evm_init: suspend registration failed: %d\n" , + ret); }#ifdef CONFIG_SERIAL_8250_CONSOLE
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 25/35 davinci: add support for CDCE949 clock synthesizer
From: Nageswari Srinivasan <[email protected]>
This patch adds support for TI's CDCE949 - a clock synthesizer with 4 PLLs and 9 outputs.
It is used on DM6467 EVM. On the EVM, it generates clocks required for VPIF, TSIF and Audio modules.
This patch adds it as part of the DaVinci clock framework.
Testing:
The various frequency outputs on Y1 have been tested using a out-of-tree VPIF video driver supporting HD video. The register values for Y5 frequency outputs have been derived from TSIF driver sources in MontaVista LSP kernel, but actual output has not been tested for lack of TSIF driver which actually works on the latest kernel.
--- arch/arm/mach-davinci/cdce949.c | 289 ++++++++++++++++++++++++++ arch/arm/mach-davinci/include/mach/cdce949.h | 19 ++ 2 files changed, 308 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-davinci/cdce949.c create mode 100644 arch/arm/mach-davinci/include/mach/cdce949.h
arch/arm/mach-davinci/cdce949.c new file +289 -0
@@ -0,0 +1,289 @@ +/* +* TI CDCE949 clock synthesizer driver +* +* Note: This implementation assumes an input of 27MHz to the CDCE. +* This is by no means constrained by CDCE hardware although the datasheet +* does use this as an example for all illustrations and more importantly: +* that is the crystal input on boards it is currently used on. +* +* Copyright (C) 2009 Texas Instruments Incorporated. http://www.ti.com/ +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +*/ +#include <linux/kernel.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/i2c.h> + +#include <mach/clock.h> + +#include "clock.h" + +static struct i2c_client *cdce_i2c_client; + +/* CDCE register descriptor */ +struct cdce_reg { +u8 addr; +u8 val; +}; + +/* Per-Output (Y1, Y2 etc.) frequency descriptor */ +struct cdce_freq { +/* Frequency in KHz */ +unsigned long frequency; +/* +* List of registers to program to obtain a particular frequency. +* 0x0 in register address and value is the end of list marker. +*/ +struct cdce_reg *reglist; +}; + +#define CDCE_FREQ_TABLE_ENTRY (line, out) \ +{ \ + .reglist = cdce_y ##line## _ ##out, \ + .frequency = out, \ +} + +/* List of CDCE outputs */ +struct cdce_output { +/* List of frequencies on this output */ +struct cdce_freq *freq_table; +/* Number of possible frequencies */ +int size; +}; + +/* +* Finding out the values to program into CDCE949 registers for a particular +* frequency output is not a simple calculation. Have a look at the datasheet +* for the details. There is desktop software available to help users with +* the calculations. Here, we just depend on the output of that software +* (or hand calculations) instead trying to runtime calculate the register +* values and inflicting misery on ourselves. +*/ +static struct cdce_reg cdce_y1_148500[] = { + {0x13 ,0x00 }, +/* program PLL1_0 multiplier */ + {0x18 ,0xaf }, + {0x19 ,0x50 }, + {0x1a ,0x02 }, + {0x1b ,0xc9 }, +/* program PLL1_11 multiplier */ + {0x1c ,0x00 }, + {0x1d ,0x40 }, + {0x1e ,0x02 }, + {0x1f ,0xc9 }, +/* output state selection */ + {0x15 ,0x00 }, + {0x14 ,0xef }, +/* switch MUX to PLL1 output */ + {0x14 ,0x6f }, + {0x16 ,0x06 }, +/* set P2DIV divider, P3DIV and input crystal */ + {0x17 ,0x06 }, + {0x01 ,0x00 }, + {0x05 ,0x48 }, + {0x02 ,0x80 }, +/* enable and disable PLL */ + {0x02 ,0xbc }, + {0x03 ,0x01 }, + { }, +}; + +static struct cdce_reg cdce_y1_74250[] = { + {0x13 ,0x00 }, + {0x18 ,0xaf }, + {0x19 ,0x50 }, + {0x1a ,0x02 }, + {0x1b ,0xc9 }, + {0x1c ,0x00 }, + {0x1d ,0x40 }, + {0x1e ,0x02 }, + {0x1f ,0xc9 }, +/* output state selection */ + {0x15 ,0x00 }, + {0x14 ,0xef }, +/* switch MUX to PLL1 output */ + {0x14 ,0x6f }, + {0x16 ,0x06 }, +/* set P2DIV divider, P3DIV and input crystal */ + {0x17 ,0x06 }, + {0x01 ,0x00 }, + {0x05 ,0x48 }, + {0x02 ,0x80 }, +/* enable and disable PLL */ + {0x02 ,0xbc }, + {0x03 ,0x02 }, + { }, +}; + +static struct cdce_reg cdce_y1_27000[] = { + {0x13 ,0x00 }, + {0x18 ,0x00 }, + {0x19 ,0x40 }, + {0x1a ,0x02 }, + {0x1b ,0x08 }, + {0x1c ,0x00 }, + {0x1d ,0x40 }, + {0x1e ,0x02 }, + {0x1f ,0x08 }, + {0x15 ,0x02 }, + {0x14 ,0xed }, + {0x16 ,0x01 }, + {0x17 ,0x01 }, + {0x01 ,0x00 }, + {0x05 ,0x50 }, + {0x02 ,0xb4 }, + {0x03 ,0x01 }, + { }, +}; + +static struct cdce_freq cdce_y1_freqs[] = { +CDCE_FREQ_TABLE_ENTRY (1 ,148500 ), +CDCE_FREQ_TABLE_ENTRY (1 ,74250 ), +CDCE_FREQ_TABLE_ENTRY (1 ,27000 ), +}; + +static struct cdce_reg cdce_y5_13500[] = { + {0x27 ,0x08 }, + {0x28 ,0x00 }, + {0x29 ,0x40 }, + {0x2a ,0x02 }, + {0x2b ,0x08 }, + {0x24 ,0x6f }, + { }, +}; + +static struct cdce_reg cdce_y5_16875[] = { + {0x27 ,0x08 }, + {0x28 ,0x9f }, + {0x29 ,0xb0 }, + {0x2a ,0x02 }, + {0x2b ,0x89 }, + {0x24 ,0x6f }, + { }, +}; + +static struct cdce_reg cdce_y5_27000[] = { + {0x27 ,0x04 }, + {0x28 ,0x00 }, + {0x29 ,0x40 }, + {0x2a ,0x02 }, + {0x2b ,0x08 }, + {0x24 ,0x6f }, + { }, +}; +static struct cdce_reg cdce_y5_54000[] = { + {0x27 ,0x04 }, + {0x28 ,0xff }, + {0x29 ,0x80 }, + {0x2a ,0x02 }, + {0x2b ,0x07 }, + {0x24 ,0x6f }, + { }, +}; + +static struct cdce_reg cdce_y5_81000[] = { + {0x27 ,0x02 }, + {0x28 ,0xbf }, + {0x29 ,0xa0 }, + {0x2a ,0x03 }, + {0x2b ,0x0a }, + {0x24 ,0x6f }, + { }, +}; + +static struct cdce_freq cdce_y5_freqs[] = { +CDCE_FREQ_TABLE_ENTRY (5 ,13500 ), +CDCE_FREQ_TABLE_ENTRY (5 ,16875 ), +CDCE_FREQ_TABLE_ENTRY (5 ,27000 ), +CDCE_FREQ_TABLE_ENTRY (5 ,54000 ), +CDCE_FREQ_TABLE_ENTRY (5 ,81000 ), +}; + + +static struct cdce_output output_list[] = { + [1 ] = { cdce_y1_freqs,ARRAY_SIZE (cdce_y1_freqs) }, + [5 ] = { cdce_y5_freqs,ARRAY_SIZE (cdce_y5_freqs) }, +}; + +int cdce_set_rate (struct clk *clk,unsigned long rate) +{ +int i, ret =0 ; +struct cdce_freq *freq_table = output_list[clk->lpsc].freq_table; +struct cdce_reg *regs =NULL ; + +if (!cdce_i2c_client) +return -ENODEV ; + +if (!freq_table) +return -EINVAL ; + +for (i =0 ; i < output_list[clk->lpsc].size; i++) { +if (freq_table[i].frequency == rate /1000 ) { + regs = freq_table[i].reglist; +break ; + } + } + +if (!regs) +return -EINVAL ; + +for (i =0 ; regs[i].addr; i++) { + ret =i2c_smbus_write_byte_data (cdce_i2c_client, + regs[i].addr |0x80 , regs[i].val); +if (ret) +return ret; + } + +atomic_set (&clk->rate, rate); + +return 0 ; +} + +static int cdce_probe (struct i2c_client *client, +const struct i2c_device_id *id) +{ + cdce_i2c_client = client; +return 0 ; +} + +static int __devexit cdce_remove(struct i2c_client *client) +{ + cdce_i2c_client =NULL ; +return 0 ; +} + +static const struct i2c_device_id cdce_id[] = { + {"cdce949" ,0 }, + {}, +}; +MODULE_DEVICE_TABLE (i2c, cdce_id); + +static struct i2c_driver cdce_driver = { + .driver = { + .owner =THIS_MODULE , + .name ="cdce949" , + }, + .probe = cdce_probe, + .remove =__devexit_p (cdce_remove), + .id_table = cdce_id, +}; + +static int __init cdce_init (void ) +{ +return i2c_add_driver (&cdce_driver); +} +subsys_initcall (cdce_init); + +static void __exit cdce_exit(void) +{ +i2c_del_driver (&cdce_driver); +} +module_exit (cdce_exit); + +MODULE_AUTHOR ("Texas Instruments" ); +MODULE_DESCRIPTION ("CDCE949 clock synthesizer driver" ); +MODULE_LICENSE ("GPL v2" );
arch/arm/mach-davinci/include/mach/cdce949.h new file +19 -0
@@ -0,0 +1,19 @@ +/* +* TI CDCE949 off-chip clock synthesizer support +* +* 2009 (C) Texas Instruments, Inc. http://www.ti.com/ +* +* This file is licensed under the terms of the GNU General Public License +* version 2. This program is licensed "as is" without any warranty of any +* kind, whether express or implied. +*/ +#ifndef _MACH_DAVINCI_CDCE949_H +#define _MACH_DAVINCI_CDCE949_H + +#include <linux/clk.h> + +#include <mach/clock.h> + +int cdce_set_rate (struct clk *clk,unsigned long rate); + +#endif
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 26/35 davinci: add CDCE949 support on DM6467 EVM
From: Nageswari Srinivasan <[email protected]>
This patch adds the CDCE949 reference oscillator to the davinci clock list.
On the DM6467T EVM, the CDCE949 is responsible for generating the pixel clock for display. On the DM6467 EVM, this pixel clock was being obtained from an internal source. This is not possible on the DM6467T EVM because of the presence of a 33MHz oscillator.
The TSIF module also requires the CDCE949 to generate the data clocks.
The actual clock definitions will be added by patches adding support for DM6467T VPIF and TSIF. This patch mearly lays the foundation for that work.
--- arch/arm/mach-davinci/Makefile | 2 +- arch/arm/mach-davinci/board-dm646x-evm.c | 31 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletions(-)
arch/arm/mach-davinci/Makefile +1 -1
@@ -26,7 +26,7 @@ obj-$(CONFIG_MACH_SFFSDR) += board-sffsdr.o obj-$(CONFIG_MACH_NEUROS_OSD2) += board-neuros-osd2.o obj-$(CONFIG_MACH_DAVINCI_DM355_EVM) += board-dm355-evm.o obj-$(CONFIG_MACH_DM355_LEOPARD) += board-dm355-leopard.o -obj-$(CONFIG_MACH_DAVINCI_DM6467_EVM) += board-dm646x-evm.o +obj-$(CONFIG_MACH_DAVINCI_DM6467_EVM) += board-dm646x-evm.o cdce949.o obj-$(CONFIG_MACH_DAVINCI_DM365_EVM) += board-dm365-evm.o obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o
arch/arm/mach-davinci/board-dm646x-evm.c +31 -0
@@ -40,6 +40,8 @@#include <mach/serial.h> #include <mach/i2c.h> #include <mach/nand.h> +#include <mach/clock.h> +#include <mach/cdce949.h> #include "clock.h"
@@ -389,6 +391,9 @@ static struct i2c_board_info __initdata i2c_info[] = { {I2C_BOARD_INFO ("cpld_video" ,0x3b ), }, + { + I2C_BOARD_INFO("cdce949", 0x6c), + }, }; static struct davinci_i2c_platform_data i2c_pdata = {
@@ -681,9 +686,35 @@ static void __init evm_init_i2c(void)evm_init_video (); } +#define CDCE949_XIN_RATE 27000000 + +/* CDCE949 support - "lpsc" field is overridden to work as clock number */ +static struct clk cdce_clk_in = { + .name ="cdce_xin" , + .rate =ATOMIC_INIT (CDCE949_XIN_RATE ), +}; + +static struct davinci_clk cdce_clks[] = { +CLK (NULL ,"xin" , &cdce_clk_in), +CLK (NULL ,NULL ,NULL ), +}; + +static void __init cdce_clk_init (void ) +{ +struct davinci_clk *c; +struct clk *clk; + +for (c = cdce_clks; c->lk.clk; c++) { + clk = c->lk.clk; +clkdev_add (&c->lk); +clk_register (clk); + } +} +static void __init davinci_map_io (void ) {dm646x_init (); +cdce_clk_init (); }static struct davinci_uart_config uart_config__initdata = {
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 27/35 davinci: Correct return value of edma_alloc_channel api
From: Sudhakar Rajashekhara <[email protected]>
Currently, edma_alloc_channel api is returning the channel number without prepending the controller on which the channel was allocated. So, if a channel is allocated on 2nd controller, calls subsequent to edma_alloc_channel would never know that channel was allocated on the 2nd controller, and continue to operate on 1st controller, resulting in edma failure. This patch fixes this issue.
--- arch/arm/mach-davinci/dma.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/arm/mach-davinci/dma.c +1 -1
@@ -642,7 +642,7 @@ int edma_alloc_channel(int channel,map_dmach_queue (ctlr, channel, eventq_no); -return channel; +return EDMA_CTLR_CHAN (ctlr, channel); }EXPORT_SYMBOL (edma_alloc_channel);
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 28/35 davinci: Keep count of channel controllers on a platform
From: Sudhakar Rajashekhara <[email protected]>
Some architectures have only one channel controller, but the edma_alloc_channel api loops twice to findout the free channel available in EDMA_CHANNEL_ANY case. A new variable has been introduced to keep count of number of channel controllers being used on a particular architecture.
--- arch/arm/mach-davinci/dma.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
arch/arm/mach-davinci/dma.c +3 -1
@@ -243,6 +243,7 @@ struct edma { };static struct edma *edma_info[EDMA_MAX_CC ]; +static int arch_num_cc;/* dummy param set used to (re)initialize parameter RAM slots */ static const struct edmacc_param dummy_paramset = {
@@ -602,7 +603,7 @@ int edma_alloc_channel(int channel, }if (channel <0 ) { -for (i =0 ; i <EDMA_MAX_CC ; i++) { +for (i =0 ; i < arch_num_cc; i++) { channel =0 ;for (;;) { channel = find_next_bit(edma_info[i]->
@@ -1467,6 +1468,7 @@ static int __init edma_probe(struct platform_device *pdev)edma_write_array2 (j,EDMA_DRAE , i,1 ,0x0 );edma_write_array (j,EDMA_QRAE , i,0x0 ); } + arch_num_cc++; }if (tc_errs_handled) {
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 29/35 davinci: Fix edma_alloc_channel api for EDMA_CHANNEL_ANY case
From: Sudhakar Rajashekhara <[email protected]>
Though edma_alloc_channel api was looping through the available channel controllers in EDMA_CHANNEL_ANY case, it was never returning the channel for 2nd channel controller, if 1st channel controller had no free channels. This issue has been fixed with this patch.
--- arch/arm/mach-davinci/dma.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-)
arch/arm/mach-davinci/dma.c +4 -2
@@ -595,7 +595,7 @@ int edma_alloc_channel(int channel,void *data, enum dma_event_q eventq_no) { - unsigned i, done, ctlr = 0; + unsigned i, done = 0, ctlr = 0;if (channel >=0 ) { ctlr =EDMA_CTLR (channel);
@@ -611,7 +611,7 @@ int edma_alloc_channel(int channel, edma_info[i]->num_channels, channel);if (channel == edma_info[i]->num_channels) -return -ENOMEM ; +break ;if (!test_and_set_bit (channel, edma_info[i]->edma_inuse)) { done =1 ;
@@ -623,6 +623,8 @@ int edma_alloc_channel(int channel,if (done)break ; } +if (!done) +return -ENOMEM ; }else if (channel >= edma_info[ctlr]->num_channels) {return -EINVAL ; }else if (test_and_set_bit (channel, edma_info[ctlr]->edma_inuse)) {
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 30/35 davinci: build list of unused EDMA events dynamically
From: Sudhakar Rajashekhara <[email protected]>
Currently, the edma_noevent list is passed from platform data. But on some architectures, there will be many EDMA channels which will not be used at all. This patch scans all the platform devices and then builds a list of events which are not being used. The unused event list will be used to allocate EDMA channels in case of EDMA_CHANNEL_ANY usage instead of the edma_noevent being used earlier for this purpose.
This patch is based on David Brownells's suggestion at
http://article.gmane.org/gmane.linux.davinci/15176.
--- arch/arm/mach-davinci/devices-da8xx.c | 6 --- arch/arm/mach-davinci/dm355.c | 8 ---- arch/arm/mach-davinci/dm644x.c | 10 ----- arch/arm/mach-davinci/dm646x.c | 9 ----- arch/arm/mach-davinci/dma.c | 55 ++++++++++++++++++++++------ arch/arm/mach-davinci/include/mach/edma.h | 2 - 6 files changed, 43 insertions(+), 47 deletions(-)
arch/arm/mach-davinci/devices-da8xx.c +0 -6
@@ -83,11 +83,6 @@ struct platform_device da8xx_serial_device = { }, }; -static const s8 da8xx_dma_chan_no_event[] = { -20 ,21 , --1 -}; -static const s8 da8xx_queue_tc_mapping[][2 ] = {/* {event queue no, TC no} */ {0 ,0 },
@@ -109,7 +104,6 @@ static struct edma_soc_info da8xx_edma_info[] = { .n_slot = 128, .n_tc = 2, .n_cc = 1, - .noevent = da8xx_dma_chan_no_event, .queue_tc_mapping = da8xx_queue_tc_mapping, .queue_priority_mapping = da8xx_queue_priority_mapping, },
arch/arm/mach-davinci/dm355.c +0 -8
@@ -564,13 +564,6 @@ static u8 dm355_default_priorities[DAVINCI_N_AINTC_IRQ] = {/*----------------------------------------------------------------------*/ -static const s8 dma_chan_dm355_no_event[] = { -12 ,13 ,24 ,56 ,57 , -58 ,59 ,60 ,61 ,62 , -63 , --1 -}; -static const s8 queue_tc_mapping[][2 ] = {/* {event queue no, TC no} */
@@ -594,7 +587,6 @@ static struct edma_soc_info dm355_edma_info[] = { .n_slot = 128, .n_tc = 2, .n_cc = 1, - .noevent = dma_chan_dm355_no_event, .queue_tc_mapping = queue_tc_mapping, .queue_priority_mapping = queue_priority_mapping, },
arch/arm/mach-davinci/dm644x.c +0 -10
@@ -479,15 +479,6 @@ static u8 dm644x_default_priorities[DAVINCI_N_AINTC_IRQ] = {/*----------------------------------------------------------------------*/ -static const s8 dma_chan_dm644x_no_event[] = { -0 ,1 ,12 ,13 ,14 , -15 ,25 ,30 ,31 ,45 , -46 ,47 ,55 ,56 ,57 , -58 ,59 ,60 ,61 ,62 , -63 , --1 -}; -static const s8 queue_tc_mapping[][2 ] = {/* {event queue no, TC no} */
@@ -511,7 +502,6 @@ static struct edma_soc_info dm644x_edma_info[] = { .n_slot = 128, .n_tc = 2, .n_cc = 1, - .noevent = dma_chan_dm644x_no_event, .queue_tc_mapping = queue_tc_mapping, .queue_priority_mapping = queue_priority_mapping, },
arch/arm/mach-davinci/dm646x.c +0 -9
@@ -511,14 +511,6 @@ static u8 dm646x_default_priorities[DAVINCI_N_AINTC_IRQ] = {/*----------------------------------------------------------------------*/ -static const s8 dma_chan_dm646x_no_event[] = { -0 ,1 ,2 ,3 ,13 , -14 ,15 ,24 ,25 ,26 , -27 ,30 ,31 ,54 ,55 , -56 , --1 -}; -/* Four Transfer Controllers on DM646x */ static const s8 dm646x_queue_tc_mapping[][2 ] = {
@@ -547,7 +539,6 @@ static struct edma_soc_info dm646x_edma_info[] = { .n_slot = 512, .n_tc = 4, .n_cc = 1, - .noevent = dma_chan_dm646x_no_event, .queue_tc_mapping = dm646x_queue_tc_mapping, .queue_priority_mapping = dm646x_queue_priority_mapping, },
arch/arm/mach-davinci/dma.c +43 -12
100 lines not on this page · raw message
arch/arm/mach-davinci/include/mach/edma.h +0 -2
@@ -280,8 +280,6 @@ struct edma_soc_info {unsigned n_cc;enum dma_event_q default_queue; -/* list of channels with no even trigger; terminated by "-1" */ -const s8 *noevent;const s8 (*queue_tc_mapping)[2 ];const s8 (*queue_priority_mapping)[2 ]; };
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 31/35 davinci: support for EDMA resource sharing
From: Sudhakar Rajashekhara <[email protected]>
Current EDMA driver is not taking care of EDMA channels/slots which are allocated from other processor, say DSP. If a channel/slot is allocated from DSP, the existing EDMA driver can still allocate the same resource on ARM.
This patch enables the user to pass the channel/slots reserved for DSP as platform data. EDMA driver scans this list during probe and prepares a bitmap of channel/slots which can be used on ARM side.
--- arch/arm/mach-davinci/dma.c | 36 ++++++++++++++++++++++++++++- arch/arm/mach-davinci/include/mach/edma.h | 2 + 2 files changed, 37 insertions(+), 1 deletions(-)
arch/arm/mach-davinci/dma.c +35 -1
@@ -206,6 +206,18 @@ static inline void edma_parm_or(unsigned ctlr, int offset, int param_no,edma_or (ctlr,EDMA_PARM + offset + (param_no <<5 ), or); } +static inline void set_bits (int offset,int len,unsigned long *p) +{ +for (; len >0 ; len--) +set_bit (offset + (len -1 ), p); +} + +static inline void clear_bits (int offset,int len,unsigned long *p) +{ +for (; len >0 ; len--) +clear_bit (offset + (len -1 ), p); +} +/*****************************************************************************/ /* actual number of DMA channels and slots on this silicon */
@@ -1379,8 +1391,10 @@ static int __init edma_probe(struct platform_device *pdev)struct edma_soc_info *info = pdev->dev.platform_data;const s8 (*queue_priority_mapping)[2 ];const s8 (*queue_tc_mapping)[2 ]; -int i, j, found =0 ; +int i, j, off, ln, found =0 ;int status =-1 ; +const s16 (*rsv_chans)[2 ]; +const s16 (*rsv_slots)[2 ];int irq[EDMA_MAX_CC ] = {0 ,0 };int err_irq[EDMA_MAX_CC ] = {0 ,0 };struct resource *r[EDMA_MAX_CC ] = {NULL };
@@ -1447,6 +1461,26 @@ static int __init edma_probe(struct platform_device *pdev)memset (edma_info[j]->edma_unused,0xff ,sizeof (edma_info[j]->edma_unused)); +/* Clear the reserved channels in unused list */ + rsv_chans = info[j].rsv_chans; +if (rsv_chans) { +for (i =0 ; rsv_chans[i][0 ] !=-1 ; i++) { + off = rsv_chans[i][0 ]; + ln = rsv_chans[i][1 ]; +clear_bits (off, ln, edma_info[j]->edma_unused); + } + } + +/* Set the reserved channels/slots in inuse list */ + rsv_slots = info[j].rsv_slots; +if (rsv_slots) { +for (i =0 ; rsv_slots[i][0 ] !=-1 ; i++) { + off = rsv_slots[i][0 ]; + ln = rsv_slots[i][1 ]; +set_bits (off, ln, edma_info[j]->edma_inuse); + } + } +sprintf (irq_name,"edma%d" , j); irq[j] =platform_get_irq_byname (pdev, irq_name); edma_info[j]->irq_res_start = irq[j];
arch/arm/mach-davinci/include/mach/edma.h +2 -0
@@ -280,6 +280,8 @@ struct edma_soc_info {unsigned n_cc;enum dma_event_q default_queue; +const s16 (*rsv_chans)[2 ]; +const s16 (*rsv_slots)[2 ];const s8 (*queue_tc_mapping)[2 ];const s8 (*queue_priority_mapping)[2 ]; };
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 32/35 davinci: da8xx/omap-l1xx: Add EDMA platform data for da850/omap-l138
From: Sudhakar Rajashekhara <[email protected]>
Currently da850/omap-l138 supports only one channel controller instance of EDMA though EDMA driver as such supports multiple channel controller instances. This patch adds platform data for the 2nd EDMA channel controller. As, the platform data differ between da830/omap-l137 and da850/omap-l138, existing code has been re-shuffled to accommodate this.
--- arch/arm/mach-davinci/devices-da8xx.c | 121 +++++++++++++++++++++++++++++++-- 1 files changed, 114 insertions(+), 7 deletions(-)
arch/arm/mach-davinci/devices-da8xx.c +114 -7
@@ -24,8 +24,10 @@#include "clock.h" #define DA8XX_TPCC_BASE 0x01c00000 +#define DA850_TPCC1_BASE 0x01e30000#define DA8XX_TPTC0_BASE 0x01c08000#define DA8XX_TPTC1_BASE 0x01c08400 +#define DA850_TPTC2_BASE 0x01e38000#define DA8XX_WDOG_BASE 0x01c21000/* DA8XX_TIMER64P1_BASE */ #define DA8XX_I2C0_BASE 0x01c22000#define DA8XX_RTC_BASE 0x01C23000
@@ -97,7 +99,31 @@ static const s8 da8xx_queue_priority_mapping[][2] = { {-1, -1} }; -static struct edma_soc_info da8xx_edma_info[] = { +static const s8 da850_queue_tc_mapping[][2 ] = { +/* {event queue no, TC no} */ + {0 ,0 }, + {-1 ,-1 } +}; + +static const s8 da850_queue_priority_mapping[][2 ] = { +/* {event queue no, Priority} */ + {0 ,3 }, + {-1 ,-1 } +}; + +static struct edma_soc_info da830_edma_info[] = { + { + .n_channel =32 , + .n_region =4 , + .n_slot =128 , + .n_tc =2 , + .n_cc =1 , + .queue_tc_mapping = da8xx_queue_tc_mapping, + .queue_priority_mapping = da8xx_queue_priority_mapping, + }, +}; + +static struct edma_soc_info da850_edma_info[] = { { .n_channel =32 , .n_region =4 ,
@@ -107,9 +133,49 @@ static struct edma_soc_info da8xx_edma_info[] = { .queue_tc_mapping = da8xx_queue_tc_mapping, .queue_priority_mapping = da8xx_queue_priority_mapping, }, + { + .n_channel = 32, + .n_region = 4, + .n_slot = 128, + .n_tc = 1, + .n_cc = 1, + .queue_tc_mapping = da850_queue_tc_mapping, + .queue_priority_mapping = da850_queue_priority_mapping, + }, +}; + +static struct resource da830_edma_resources[] = { + { + .name ="edma_cc0" , + .start =DA8XX_TPCC_BASE , + .end =DA8XX_TPCC_BASE +SZ_32K -1 , + .flags =IORESOURCE_MEM , + }, + { + .name ="edma_tc0" , + .start =DA8XX_TPTC0_BASE , + .end =DA8XX_TPTC0_BASE +SZ_1K -1 , + .flags =IORESOURCE_MEM , + }, + { + .name ="edma_tc1" , + .start =DA8XX_TPTC1_BASE , + .end =DA8XX_TPTC1_BASE +SZ_1K -1 , + .flags =IORESOURCE_MEM , + }, + { + .name ="edma0" , + .start =IRQ_DA8XX_CCINT0 , + .flags =IORESOURCE_IRQ , + }, + { + .name ="edma0_err" , + .start =IRQ_DA8XX_CCERRINT , + .flags =IORESOURCE_IRQ , + }, }; -static struct resource da8xx_edma_resources[] = { +static struct resource da850_edma_resources[] = { { .name ="edma_cc0" , .start =DA8XX_TPCC_BASE ,
@@ -129,6 +195,18 @@ static struct resource da8xx_edma_resources[] = { .flags = IORESOURCE_MEM, }, { + .name = "edma_cc1", + .start = DA850_TPCC1_BASE, + .end = DA850_TPCC1_BASE + SZ_32K - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "edma_tc2", + .start = DA850_TPTC2_BASE, + .end = DA850_TPTC2_BASE + SZ_1K - 1, + .flags = IORESOURCE_MEM, + }, + { .name = "edma0", .start = IRQ_DA8XX_CCINT0, .flags = IORESOURCE_IRQ,
@@ -138,21 +216,50 @@ static struct resource da8xx_edma_resources[] = { .start = IRQ_DA8XX_CCERRINT, .flags = IORESOURCE_IRQ, }, + { + .name = "edma1", + .start = IRQ_DA850_CCINT1, + .flags = IORESOURCE_IRQ, + }, + { + .name = "edma1_err", + .start = IRQ_DA850_CCERRINT1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device da830_edma_device = { + .name ="edma" , + .id =-1 , + .dev = { + .platform_data = da830_edma_info, + }, + .num_resources =ARRAY_SIZE (da830_edma_resources), + .resource = da830_edma_resources, }; -static struct platform_device da8xx_edma_device = { +static struct platform_device da850_edma_device = { .name ="edma" , .id =-1 , .dev = { - .platform_data = da8xx_edma_info, + .platform_data = da850_edma_info, }, - .num_resources =ARRAY_SIZE (da8xx_edma_resources), - .resource = da8xx_edma_resources, + .num_resources =ARRAY_SIZE (da850_edma_resources), + .resource = da850_edma_resources, };int __init da8xx_register_edma (void ) { -return platform_device_register (&da8xx_edma_device); +struct platform_device *pdev; + +if (cpu_is_davinci_da830 ()) + pdev = &da830_edma_device; +else if (cpu_is_davinci_da850 ()) + pdev = &da850_edma_device; +else +return -ENODEV ; + +return platform_device_register (pdev); } static struct resource da8xx_i2c_resources0[] = {
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 33/35 davinci: da830/omapl137: Specify reserved channels/slots
From: Sudhakar Rajashekhara <[email protected]>
Pass reserved EDMA channel/slots as platform data for da830/omap-l137.
--- arch/arm/mach-davinci/devices-da8xx.c | 25 +++++++++++++++++++++++++ 1 files changed, 25 insertions(+), 0 deletions(-)
arch/arm/mach-davinci/devices-da8xx.c +25 -0
@@ -111,6 +111,29 @@ static const s8 da850_queue_priority_mapping[][2] = { {-1, -1} }; +/* +* The following EDMA channels/slots are not being used by drivers (for +* example: Timer, GPIO, UART events etc) on da830/omap-l137, hence they +* are being reserved for codecs on the DSP side. +*/ +static const s16 da830_dma_rsv_chans[][2 ] = { +/* (offset, number) */ + {8 ,2 }, + {12 ,2 }, + {24 ,4 }, + {30 ,2 }, + {-1 ,-1 } +}; + +static const s16 da830_dma_rsv_slots[][2 ] = { +/* (offset, number) */ + {8 ,2 }, + {12 ,2 }, + {24 ,4 }, + {30 ,26 }, + {-1 ,-1 } +}; +static struct edma_soc_info da830_edma_info[] = { { .n_channel =32 ,
@@ -118,6 +141,8 @@ static struct edma_soc_info da830_edma_info[] = { .n_slot = 128, .n_tc = 2, .n_cc = 1, + .rsv_chans = da830_dma_rsv_chans, + .rsv_slots = da830_dma_rsv_slots, .queue_tc_mapping = da8xx_queue_tc_mapping, .queue_priority_mapping = da8xx_queue_priority_mapping, },
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 34/35 davinci: da850/omapl138: Specify reserved channels/slots
From: Sudhakar Rajashekhara <[email protected]>
Pass reserved EDMA channel/slots as platform data for da850/omap-l138.
--- arch/arm/mach-davinci/devices-da8xx.c | 39 +++++++++++++++++++++++++++++++++ 1 files changed, 39 insertions(+), 0 deletions(-)
arch/arm/mach-davinci/devices-da8xx.c +39 -0
@@ -134,6 +134,41 @@ static const s16 da830_dma_rsv_slots[][2] = { {-1, -1} }; +/* +* The following EDMA channels/slots are not being used by drivers (for +* example: Timer, GPIO, UART events etc) on da850/omap-l138, hence they +* are being reserved for codecs on the DSP side. +*/ +static const s16 da850_dma0_rsv_chans[][2 ] = { +/* (offset, number) */ + {8 ,6 }, + {24 ,4 }, + {30 ,2 }, + {-1 ,-1 } +}; + +static const s16 da850_dma0_rsv_slots[][2 ] = { +/* (offset, number) */ + {8 ,6 }, + {24 ,4 }, + {30 ,50 }, + {-1 ,-1 } +}; + +static const s16 da850_dma1_rsv_chans[][2 ] = { +/* (offset, number) */ + {0 ,28 }, + {30 ,2 }, + {-1 ,-1 } +}; + +static const s16 da850_dma1_rsv_slots[][2 ] = { +/* (offset, number) */ + {0 ,28 }, + {30 ,90 }, + {-1 ,-1 } +}; +static struct edma_soc_info da830_edma_info[] = { { .n_channel =32 ,
@@ -155,6 +190,8 @@ static struct edma_soc_info da850_edma_info[] = { .n_slot = 128, .n_tc = 2, .n_cc = 1, + .rsv_chans = da850_dma0_rsv_chans, + .rsv_slots = da850_dma0_rsv_slots, .queue_tc_mapping = da8xx_queue_tc_mapping, .queue_priority_mapping = da8xx_queue_priority_mapping, },
@@ -164,6 +201,8 @@ static struct edma_soc_info da850_edma_info[] = { .n_slot = 128, .n_tc = 1, .n_cc = 1, + .rsv_chans = da850_dma1_rsv_chans, + .rsv_slots = da850_dma1_rsv_slots, .queue_tc_mapping = da850_queue_tc_mapping, .queue_priority_mapping = da850_queue_priority_mapping, },
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 35/35 davinci: dm646x: Specify reserved EDMA channel/slots for DM646x
From: Sudhakar Rajashekhara <[email protected]>
Pass reserved EDMA channel/slots as platform data for dm646x.
--- arch/arm/mach-davinci/dm646x.c | 28 ++++++++++++++++++++++++++++ 1 files changed, 28 insertions(+), 0 deletions(-)
arch/arm/mach-davinci/dm646x.c +28 -0
@@ -511,6 +511,32 @@ static u8 dm646x_default_priorities[DAVINCI_N_AINTC_IRQ] = {/*----------------------------------------------------------------------*/ +/* +* The following EDMA channels/slots are not being used by drivers (for +* example: Timer, GPIO, UART events etc) on dm646x, hence they are being +* reserved for codecs on the DSP side. +*/ +static const s16 dm646x_dma_rsv_chans[][2 ] = { +/* (offset, number) */ + {0 ,4 }, + {13 ,3 }, + {24 ,4 }, + {30 ,2 }, + {54 ,3 }, + {-1 ,-1 } +}; + +static const s16 dm646x_dma_rsv_slots[][2 ] = { +/* (offset, number) */ + {0 ,4 }, + {13 ,3 }, + {24 ,4 }, + {30 ,2 }, + {54 ,3 }, + {128 ,384 }, + {-1 ,-1 } +}; +/* Four Transfer Controllers on DM646x */ static const s8 dm646x_queue_tc_mapping[][2 ] = {
@@ -539,6 +565,8 @@ static struct edma_soc_info dm646x_edma_info[] = { .n_slot = 512, .n_tc = 4, .n_cc = 1, + .rsv_chans = dm646x_dma_rsv_chans, + .rsv_slots = dm646x_dma_rsv_slots, .queue_tc_mapping = dm646x_queue_tc_mapping, .queue_priority_mapping = dm646x_queue_priority_mapping, },
Signature · 1 line
1.6.6.rc2.1.g42108
PATCH 12/35 davinci: clock framework: remove spinlock usage
In reply to Kevin HilmanQuoted 34 lines · Kevin Hilman
From: Sekhar Nori <[email protected]>
Currently, the spinlock in DaVinci clock framework is being used to:
1) Protect clock structure variables usecount and rate against concurrent modification.
2) Protect against simultaneous PSC enables/disables ie. serialize
davinci_psc_config().3) Serialize
clk_set_rate():
i. Prevent simultaneous setting of clock rates
ii. Ensure clock list remains sane during rate
propagation (also inclk_set_parent).Remove the spinlock usage in clock framework by:
1) Making clock rate and usecount as atomic variables.
2) Making
davinci_psc_config()protect itself instead of relying on serialization by caller.3) (i) Allowing the
clk->set_rateto serialize itself. There should be no need to serialize all clock rate settings. Currently the only user of rate setting is cpufreq driver on DA850. cpufreq naturally serializes the calls to set CPU rate. Also, there appears no need to lock IRQs during CPU rate transtitions. If required, IRQs can be locked in the actualset_ratefunction.3) (ii) Use the mutex already in place for serialzing clock list manipulation for serializing clock rate propagation as well.
Quoted 7 lines
Apart from the general benefit of reducing locking granurlarity, the main motivation behind this change is to enable usage of clock framework for off-chip clock synthesizers. One such synthesizer, CDCE949, is present on DM6467 EVM. Access to the synthesizer happens through I2C bus - accessing which can lead to CPU sleep. Having IRQs locked in
clk_set_rateprevents theclk->set_ratefunction from sleeping.
This patch is extremely bogus. Just because something is called 'atomic' does not make it so.
atomic_set()..atomic_read() are NOT atomic. They are just plain write and read of the underlying atomic value - the former is intended for one-time initialization, and the latter is intended for debugging.
arch/arm/mach-davinci/clock.c static void __clk_enable(struct clk *clk) · line 45
Quoted 8 lines
arch/arm/mach-davinci/clock.c +2
-1@@ -41,15 +40,16 @@ static void __clk_enable(struct clk *clk) {if (clk->parent)__clk_enable (clk->parent); -if (clk->usecount++ ==0 && (clk->flags &CLK_PSC )) +if (atomic_read (&clk->usecount) ==0 && (clk->flags &CLK_PSC ))davinci_psc_config (psc_domain (clk), clk->gpsc, clk->lpsc,1 ); +atomic_inc (&clk->usecount);
This is wrong on two levels. Firstly, consider a simultaneous clk_enable and clk_disable.
CPU0 CPU1__clk_disable
atomic_dec_and_test(&clk->usecount) -> true
__clk_enable atomic_read(&clk->usecount) returns zero davinci_psc_config(..., 1); atomic_inc(&clk->usecount);
davinci_psc_config(..., 0);
The result is that we now have the situation where the usecount is nonzero but the clock is disabled.
Similar bogosities can arise when an already enabled clock tries to be simultaneously enabled for a second time and disabled.
Secondly, davinci_psc_config() does a lot of read-modify-writing. With the spinlock gone, what's the protection against simultaneous r-m-w on these registers?
arch/arm/mach-davinci/clock.c unsigned long clk_get_rate(struct clk *clk) · line 83
Quoted 6 lines
arch/arm/mach-davinci/clock.c +1
-1@@ -88,7 +80,7 @@ unsigned long clk_get_rate(struct clk *clk)if (clk ==NULL ||IS_ERR (clk))return -EINVAL ; -return clk->rate; +return atomic_read (&clk->rate);
atomic here doesn't make clk->rate magically right. This is precisely equivalent to reading clk->rate directly.
Quoted 5 lines
arch/arm/mach-davinci/clock.c +0
-1int clk_set_rate (struct clk *clk,unsigned long rate) { -unsigned long flags;int ret = -EINVAL ;
arch/arm/mach-davinci/clock.c static void propagate_rate(struct clk *root) · line 122
Quoted 10 lines
arch/arm/mach-davinci/clock.c +1
-2if (clk ==NULL ||IS_ERR (clk))return ret; -spin_lock_irqsave (&clockfw_lock, flags);if (clk->set_rate) ret = clk->set_rate (clk, rate);if (ret ==0 ) {if (clk->recalc) - clk->rate = clk->recalc (clk); +atomic_set (&clk->rate, clk->recalc (clk));
This atomic_set does nothing to protect you from races. You might as well be writing directly to clk->rate.
PATCH 12/35 davinci: clock framework: remove spinlock usage
Quoted 43 lines · Russell King - ARM Linux
Quoted 34 lines · Kevin Hilman
From: Sekhar Nori <[email protected]>
Currently, the spinlock in DaVinci clock framework is being used to:
1) Protect clock structure variables usecount and rate against concurrent modification.
2) Protect against simultaneous PSC enables/disables ie. serialize
davinci_psc_config().3) Serialize
clk_set_rate():
i. Prevent simultaneous setting of clock rates
ii. Ensure clock list remains sane during rate
propagation (also inclk_set_parent).Remove the spinlock usage in clock framework by:
1) Making clock rate and usecount as atomic variables.
2) Making
davinci_psc_config()protect itself instead of relying on serialization by caller.3) (i) Allowing the
clk->set_rateto serialize itself. There should be no need to serialize all clock rate settings. Currently the only user of rate setting is cpufreq driver on DA850. cpufreq naturally serializes the calls to set CPU rate. Also, there appears no need to lock IRQs during CPU rate transtitions. If required, IRQs can be locked in the actualset_ratefunction.3) (ii) Use the mutex already in place for serialzing clock list manipulation for serializing clock rate propagation as well.
Quoted 7 lines
Apart from the general benefit of reducing locking granurlarity, the main motivation behind this change is to enable usage of clock framework for off-chip clock synthesizers. One such synthesizer, CDCE949, is present on DM6467 EVM. Access to the synthesizer happens through I2C bus - accessing which can lead to CPU sleep. Having IRQs locked in
clk_set_rateprevents theclk->set_ratefunction from sleeping.
Quoted 2 lines
This patch is extremely bogus. Just because something is called 'atomic' does not make it so.
Russell,
Thanks for the feedback. I'll drop this patch while we rework this in a different way.
Thanks,
Kevin
Quoted 65 lines
atomic_set()..atomic_read() are NOT atomic. They are just plain write and read of the underlying atomic value - the former is intended for one-time initialization, and the latter is intended for debugging.
arch/arm/mach-davinci/clock.c static void __clk_enable(struct clk *clk) · line 45
Quoted 8 lines
arch/arm/mach-davinci/clock.c +2
-1@@ -41,15 +40,16 @@ static void __clk_enable(struct clk *clk) {if (clk->parent)__clk_enable (clk->parent); -if (clk->usecount++ ==0 && (clk->flags &CLK_PSC )) +if (atomic_read (&clk->usecount) ==0 && (clk->flags &CLK_PSC ))davinci_psc_config (psc_domain (clk), clk->gpsc, clk->lpsc,1 ); +atomic_inc (&clk->usecount);This is wrong on two levels. Firstly, consider a simultaneous
clk_enableandclk_disable.CPU0 CPU1
__clk_disable
atomic_dec_and_test(&clk->usecount)-> true__clk_enable atomic_read(&clk->usecount) returns zero davinci_psc_config(..., 1); atomic_inc(&clk->usecount);
davinci_psc_config(..., 0);The result is that we now have the situation where the usecount is nonzero but the clock is disabled.
Similar bogosities can arise when an already enabled clock tries to be simultaneously enabled for a second time and disabled.
Secondly,
davinci_psc_config()does a lot of read-modify-writing. With the spinlock gone, what's the protection against simultaneous r-m-w on these registers?arch/arm/mach-davinci/clock.c unsigned long clk_get_rate(struct clk *clk) · line 83
Quoted 6 lines
arch/arm/mach-davinci/clock.c +1
-1@@ -88,7 +80,7 @@ unsigned long clk_get_rate(struct clk *clk)if (clk ==NULL ||IS_ERR (clk))return -EINVAL ; -return clk->rate; +return atomic_read (&clk->rate);atomic here doesn't make
clk->ratemagically right. This is precisely equivalent to readingclk->ratedirectly.Quoted 5 lines
arch/arm/mach-davinci/clock.c +0
-1int clk_set_rate (struct clk *clk,unsigned long rate) { -unsigned long flags;int ret = -EINVAL ;arch/arm/mach-davinci/clock.c static void propagate_rate(struct clk *root) · line 122
Quoted 10 lines
arch/arm/mach-davinci/clock.c +1
-2if (clk ==NULL ||IS_ERR (clk))return ret; -spin_lock_irqsave (&clockfw_lock, flags);if (clk->set_rate) ret = clk->set_rate (clk, rate);if (ret ==0 ) {if (clk->recalc) - clk->rate = clk->recalc (clk); +atomic_set (&clk->rate, clk->recalc (clk));This
atomic_setdoes nothing to protect you from races. You might as well be writing directly toclk->rate.
cover davinci updates queued for 2.6.34
In reply to Kevin HilmanQuoted 5 lines · Kevin Hilman
Apologies for the large series, I've been meaning to send these in smaller batches, but hd lots to queue up from over the holidays.
Pending any review comments, these will be submitted to Linus during the next merge window.
Nothing specific on this series.
However, while looking at adding a standard clkdev_add_table() to replace all those clks_register() implementations found in various machine files (and open-coded versions of the same) I'm wondering why davinci wraps the clk_lookup structure without adding anything to it.
Could davinci get rid of this seemingly useless wrapping (presumably copied from OMAP) and so be able to switch over to use clkdev_add_table() instead?
cover davinci updates queued for 2.6.34
Quoted 7 lines · Russell King - ARM Linux
Quoted 5 lines · Kevin Hilman
Apologies for the large series, I've been meaning to send these in smaller batches, but hd lots to queue up from over the holidays.
Pending any review comments, these will be submitted to Linus during the next merge window.
Quoted 6 lines
Nothing specific on this series.
However, while looking at adding a standard
clkdev_add_table()to replace all thoseclks_register()implementations found in various machine files (and open-coded versions of the same) I'm wondering why davinci wraps theclk_lookupstructure without adding anything to it.
It's no longer needed. In initial implementation, I had some extra fields like in OMAP, but then dropped them.
Quoted 3 lines
Could davinci get rid of this seemingly useless wrapping (presumably copied from OMAP) and so be able to switch over to use
clkdev_add_table()instead?
Yes, I'll drop the wrapping.
Thanks for the reviews,
Kevin