From fa59440d0c7b5a2bcdc9e35f25fdac693e54c86a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 23 Apr 2009 10:19:58 +0100 Subject: [ARM] 5470/1: U300 register definitions This adds registers, interrupt numbers and IO mappings for the U300 series platforms core support, including basic block offsets and registers definitions for the system controller. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-u300/include/mach/hardware.h | 5 + arch/arm/mach-u300/include/mach/io.h | 20 + arch/arm/mach-u300/include/mach/irqs.h | 114 +++++ arch/arm/mach-u300/include/mach/syscon.h | 644 ++++++++++++++++++++++++++++ arch/arm/mach-u300/include/mach/u300-regs.h | 187 ++++++++ 5 files changed, 970 insertions(+) create mode 100644 arch/arm/mach-u300/include/mach/hardware.h create mode 100644 arch/arm/mach-u300/include/mach/io.h create mode 100644 arch/arm/mach-u300/include/mach/irqs.h create mode 100644 arch/arm/mach-u300/include/mach/syscon.h create mode 100644 arch/arm/mach-u300/include/mach/u300-regs.h (limited to 'arch/arm/mach-u300') diff --git a/arch/arm/mach-u300/include/mach/hardware.h b/arch/arm/mach-u300/include/mach/hardware.h new file mode 100644 index 00000000000..b99d4ce0ac2 --- /dev/null +++ b/arch/arm/mach-u300/include/mach/hardware.h @@ -0,0 +1,5 @@ +/* + * arch/arm/mach-u300/include/mach/hardware.h + */ +#include +#include diff --git a/arch/arm/mach-u300/include/mach/io.h b/arch/arm/mach-u300/include/mach/io.h new file mode 100644 index 00000000000..5d6b4c13b3a --- /dev/null +++ b/arch/arm/mach-u300/include/mach/io.h @@ -0,0 +1,20 @@ +/* + * + * arch/arm/mach-u300/include/mach/io.h + * + * + * Copyright (C) 2006-2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * Dummy IO map for being able to use writew()/readw(), + * writel()/readw() and similar accessor functions. + * Author: Linus Walleij + */ +#ifndef __MACH_IO_H +#define __MACH_IO_H + +#define IO_SPACE_LIMIT 0xffffffff + +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) + +#endif diff --git a/arch/arm/mach-u300/include/mach/irqs.h b/arch/arm/mach-u300/include/mach/irqs.h new file mode 100644 index 00000000000..a6867b12773 --- /dev/null +++ b/arch/arm/mach-u300/include/mach/irqs.h @@ -0,0 +1,114 @@ +/* + * + * arch/arm/mach-u300/include/mach/irqs.h + * + * + * Copyright (C) 2006-2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * IRQ channel definitions for the U300 platforms. + * Author: Linus Walleij + */ + +#ifndef __MACH_IRQS_H +#define __MACH_IRQS_H + +#define IRQ_U300_INTCON0_START 0 +#define IRQ_U300_INTCON1_START 32 +/* These are on INTCON0 - 30 lines */ +#define IRQ_U300_IRQ0_EXT 0 +#define IRQ_U300_IRQ1_EXT 1 +#define IRQ_U300_DMA 2 +#define IRQ_U300_VIDEO_ENC_0 3 +#define IRQ_U300_VIDEO_ENC_1 4 +#define IRQ_U300_AAIF_RX 5 +#define IRQ_U300_AAIF_TX 6 +#define IRQ_U300_AAIF_VGPIO 7 +#define IRQ_U300_AAIF_WAKEUP 8 +#define IRQ_U300_PCM_I2S0_FRAME 9 +#define IRQ_U300_PCM_I2S0_FIFO 10 +#define IRQ_U300_PCM_I2S1_FRAME 11 +#define IRQ_U300_PCM_I2S1_FIFO 12 +#define IRQ_U300_XGAM_GAMCON 13 +#define IRQ_U300_XGAM_CDI 14 +#define IRQ_U300_XGAM_CDICON 15 +#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330) +/* MMIACC not used on the DB3210 or DB3350 chips */ +#define IRQ_U300_XGAM_MMIACC 16 +#endif +#define IRQ_U300_XGAM_PDI 17 +#define IRQ_U300_XGAM_PDICON 18 +#define IRQ_U300_XGAM_GAMEACC 19 +#define IRQ_U300_XGAM_MCIDCT 20 +#define IRQ_U300_APEX 21 +#define IRQ_U300_UART0 22 +#define IRQ_U300_SPI 23 +#define IRQ_U300_TIMER_APP_OS 24 +#define IRQ_U300_TIMER_APP_DD 25 +#define IRQ_U300_TIMER_APP_GP1 26 +#define IRQ_U300_TIMER_APP_GP2 27 +#define IRQ_U300_TIMER_OS 28 +#define IRQ_U300_TIMER_MS 29 +#define IRQ_U300_KEYPAD_KEYBF 30 +#define IRQ_U300_KEYPAD_KEYBR 31 +/* These are on INTCON1 - 32 lines */ +#define IRQ_U300_GPIO_PORT0 32 +#define IRQ_U300_GPIO_PORT1 33 +#define IRQ_U300_GPIO_PORT2 34 + +#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330) || \ + defined(CONFIG_MACH_U300_BS335) +/* These are for DB3150, DB3200 and DB3350 */ +#define IRQ_U300_WDOG 35 +#define IRQ_U300_EVHIST 36 +#define IRQ_U300_MSPRO 37 +#define IRQ_U300_MMCSD_MCIINTR0 38 +#define IRQ_U300_MMCSD_MCIINTR1 39 +#define IRQ_U300_I2C0 40 +#define IRQ_U300_I2C1 41 +#define IRQ_U300_RTC 42 +#define IRQ_U300_NFIF 43 +#define IRQ_U300_NFIF2 44 +#endif + +/* DB3150 and DB3200 have only 45 IRQs */ +#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330) +#define U300_NR_IRQS 45 +#endif + +/* The DB3350-specific interrupt lines */ +#ifdef CONFIG_MACH_U300_BS335 +#define IRQ_U300_ISP_F0 45 +#define IRQ_U300_ISP_F1 46 +#define IRQ_U300_ISP_F2 47 +#define IRQ_U300_ISP_F3 48 +#define IRQ_U300_ISP_F4 49 +#define IRQ_U300_GPIO_PORT3 50 +#define IRQ_U300_SYSCON_PLL_LOCK 51 +#define IRQ_U300_UART1 52 +#define IRQ_U300_GPIO_PORT4 53 +#define IRQ_U300_GPIO_PORT5 54 +#define IRQ_U300_GPIO_PORT6 55 +#define U300_NR_IRQS 56 +#endif + +/* The DB3210-specific interrupt lines */ +#ifdef CONFIG_MACH_U300_BS365 +#define IRQ_U300_GPIO_PORT3 35 +#define IRQ_U300_GPIO_PORT4 36 +#define IRQ_U300_WDOG 37 +#define IRQ_U300_EVHIST 38 +#define IRQ_U300_MSPRO 39 +#define IRQ_U300_MMCSD_MCIINTR0 40 +#define IRQ_U300_MMCSD_MCIINTR1 41 +#define IRQ_U300_I2C0 42 +#define IRQ_U300_I2C1 43 +#define IRQ_U300_RTC 44 +#define IRQ_U300_NFIF 45 +#define IRQ_U300_NFIF2 46 +#define IRQ_U300_SYSCON_PLL_LOCK 47 +#define U300_NR_IRQS 48 +#endif + +#define NR_IRQS U300_NR_IRQS + +#endif diff --git a/arch/arm/mach-u300/include/mach/syscon.h b/arch/arm/mach-u300/include/mach/syscon.h new file mode 100644 index 00000000000..1c90d1b1ccb --- /dev/null +++ b/arch/arm/mach-u300/include/mach/syscon.h @@ -0,0 +1,644 @@ +/* + * + * arch/arm/mach-u300/include/mach/syscon.h + * + * + * Copyright (C) 2008 ST-Ericsson AB + * + * Author: Rickard Andersson + */ + +#ifndef __MACH_SYSCON_H +#define __MACH_SYSCON_H + +/* + * All register defines for SYSCON registers that concerns individual + * block clocks and reset lines are registered here. This is because + * we don't want any other file to try to fool around with this stuff. + */ + +/* APP side SYSCON registers */ +/* TODO: this is incomplete. Add all from asic_syscon_map.h eventually. */ +/* CLK Control Register 16bit (R/W) */ +#define U300_SYSCON_CCR (0x0000) +#define U300_SYSCON_CCR_I2S1_USE_VCXO (0x0040) +#define U300_SYSCON_CCR_I2S0_USE_VCXO (0x0020) +#define U300_SYSCON_CCR_TURN_VCXO_ON (0x0008) +#define U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK (0x0007) +#define U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER (0x04) +#define U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW (0x03) +#define U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE (0x02) +#define U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH (0x01) +#define U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST (0x00) +/* CLK Status Register 16bit (R/W) */ +#define U300_SYSCON_CSR (0x0004) +#define U300_SYSCON_CSR_PLL208_LOCK_IND (0x0002) +#define U300_SYSCON_CSR_PLL13_LOCK_IND (0x0001) +/* Reset lines for SLOW devices 16bit (R/W) */ +#define U300_SYSCON_RSR (0x0014) +#ifdef CONFIG_MACH_U300_BS335 +#define U300_SYSCON_RSR_PPM_RESET_EN (0x0200) +#endif +#define U300_SYSCON_RSR_ACC_TMR_RESET_EN (0x0100) +#define U300_SYSCON_RSR_APP_TMR_RESET_EN (0x0080) +#define U300_SYSCON_RSR_RTC_RESET_EN (0x0040) +#define U300_SYSCON_RSR_KEYPAD_RESET_EN (0x0020) +#define U300_SYSCON_RSR_GPIO_RESET_EN (0x0010) +#define U300_SYSCON_RSR_EH_RESET_EN (0x0008) +#define U300_SYSCON_RSR_BTR_RESET_EN (0x0004) +#define U300_SYSCON_RSR_UART_RESET_EN (0x0002) +#define U300_SYSCON_RSR_SLOW_BRIDGE_RESET_EN (0x0001) +/* Reset lines for FAST devices 16bit (R/W) */ +#define U300_SYSCON_RFR (0x0018) +#ifdef CONFIG_MACH_U300_BS335 +#define U300_SYSCON_RFR_UART1_RESET_ENABLE (0x0080) +#endif +#define U300_SYSCON_RFR_SPI_RESET_ENABLE (0x0040) +#define U300_SYSCON_RFR_MMC_RESET_ENABLE (0x0020) +#define U300_SYSCON_RFR_PCM_I2S1_RESET_ENABLE (0x0010) +#define U300_SYSCON_RFR_PCM_I2S0_RESET_ENABLE (0x0008) +#define U300_SYSCON_RFR_I2C1_RESET_ENABLE (0x0004) +#define U300_SYSCON_RFR_I2C0_RESET_ENABLE (0x0002) +#define U300_SYSCON_RFR_FAST_BRIDGE_RESET_ENABLE (0x0001) +/* Reset lines for the rest of the peripherals 16bit (R/W) */ +#define U300_SYSCON_RRR (0x001c) +#ifdef CONFIG_MACH_U300_BS335 +#define U300_SYSCON_RRR_CDS_RESET_EN (0x4000) +#define U300_SYSCON_RRR_ISP_RESET_EN (0x2000) +#endif +#define U300_SYSCON_RRR_INTCON_RESET_EN (0x1000) +#define U300_SYSCON_RRR_MSPRO_RESET_EN (0x0800) +#define U300_SYSCON_RRR_XGAM_RESET_EN (0x0100) +#define U300_SYSCON_RRR_XGAM_VC_SYNC_RESET_EN (0x0080) +#define U300_SYSCON_RRR_NANDIF_RESET_EN (0x0040) +#define U300_SYSCON_RRR_EMIF_RESET_EN (0x0020) +#define U300_SYSCON_RRR_DMAC_RESET_EN (0x0010) +#define U300_SYSCON_RRR_CPU_RESET_EN (0x0008) +#define U300_SYSCON_RRR_APEX_RESET_EN (0x0004) +#define U300_SYSCON_RRR_AHB_RESET_EN (0x0002) +#define U300_SYSCON_RRR_AAIF_RESET_EN (0x0001) +/* Clock enable for SLOW peripherals 16bit (R/W) */ +#define U300_SYSCON_CESR (0x0020) +#ifdef CONFIG_MACH_U300_BS335 +#define U300_SYSCON_CESR_PPM_CLK_EN (0x0200) +#endif +#define U300_SYSCON_CESR_ACC_TMR_CLK_EN (0x0100) +#define U300_SYSCON_CESR_APP_TMR_CLK_EN (0x0080) +#define U300_SYSCON_CESR_KEYPAD_CLK_EN (0x0040) +#define U300_SYSCON_CESR_GPIO_CLK_EN (0x0010) +#define U300_SYSCON_CESR_EH_CLK_EN (0x0008) +#define U300_SYSCON_CESR_BTR_CLK_EN (0x0004) +#define U300_SYSCON_CESR_UART_CLK_EN (0x0002) +#define U300_SYSCON_CESR_SLOW_BRIDGE_CLK_EN (0x0001) +/* Clock enable for FAST peripherals 16bit (R/W) */ +#define U300_SYSCON_CEFR (0x0024) +#ifdef CONFIG_MACH_U300_BS335 +#define U300_SYSCON_CEFR_UART1_CLK_EN (0x0200) +#endif +#define U300_SYSCON_CEFR_I2S1_CORE_CLK_EN (0x0100) +#define U300_SYSCON_CEFR_I2S0_CORE_CLK_EN (0x0080) +#define U300_SYSCON_CEFR_SPI_CLK_EN (0x0040) +#define U300_SYSCON_CEFR_MMC_CLK_EN (0x0020) +#define U300_SYSCON_CEFR_I2S1_CLK_EN (0x0010) +#define U300_SYSCON_CEFR_I2S0_CLK_EN (0x0008) +#define U300_SYSCON_CEFR_I2C1_CLK_EN (0x0004) +#define U300_SYSCON_CEFR_I2C0_CLK_EN (0x0002) +#define U300_SYSCON_CEFR_FAST_BRIDGE_CLK_EN (0x0001) +/* Clock enable for the rest of the peripherals 16bit (R/W) */ +#define U300_SYSCON_CERR (0x0028) +#ifdef CONFIG_MACH_U300_BS335 +#define U300_SYSCON_CERR_CDS_CLK_EN (0x2000) +#define U300_SYSCON_CERR_ISP_CLK_EN (0x1000) +#endif +#define U300_SYSCON_CERR_MSPRO_CLK_EN (0x0800) +#define U300_SYSCON_CERR_AHB_SUBSYS_BRIDGE_CLK_EN (0x0400) +#define U300_SYSCON_CERR_SEMI_CLK_EN (0x0200) +#define U300_SYSCON_CERR_XGAM_CLK_EN (0x0100) +#define U300_SYSCON_CERR_VIDEO_ENC_CLK_EN (0x0080) +#define U300_SYSCON_CERR_NANDIF_CLK_EN (0x0040) +#define U300_SYSCON_CERR_EMIF_CLK_EN (0x0020) +#define U300_SYSCON_CERR_DMAC_CLK_EN (0x0010) +#define U300_SYSCON_CERR_CPU_CLK_EN (0x0008) +#define U300_SYSCON_CERR_APEX_CLK_EN (0x0004) +#define U300_SYSCON_CERR_AHB_CLK_EN (0x0002) +#define U300_SYSCON_CERR_AAIF_CLK_EN (0x0001) +/* Single block clock enable 16bit (-/W) */ +#define U300_SYSCON_SBCER (0x002c) +#ifdef CONFIG_MACH_U300_BS335 +#define U300_SYSCON_SBCER_PPM_CLK_EN (0x0009) +#endif +#define U300_SYSCON_SBCER_ACC_TMR_CLK_EN (0x0008) +#define U300_SYSCON_SBCER_APP_TMR_CLK_EN (0x0007) +#define U300_SYSCON_SBCER_KEYPAD_CLK_EN (0x0006) +#define U300_SYSCON_SBCER_GPIO_CLK_EN (0x0004) +#define U300_SYSCON_SBCER_EH_CLK_EN (0x0003) +#define U300_SYSCON_SBCER_BTR_CLK_EN (0x0002) +#define U300_SYSCON_SBCER_UART_CLK_EN (0x0001) +#define U300_SYSCON_SBCER_SLOW_BRIDGE_CLK_EN (0x0000) +#ifdef CONFIG_MACH_U300_BS335 +#define U300_SYSCON_SBCER_UART1_CLK_EN (0x0019) +#endif +#define U300_SYSCON_SBCER_I2S1_CORE_CLK_EN (0x0018) +#define U300_SYSCON_SBCER_I2S0_CORE_CLK_EN (0x0017) +#define U300_SYSCON_SBCER_SPI_CLK_EN (0x0016) +#define U300_SYSCON_SBCER_MMC_CLK_EN (0x0015) +#define U300_SYSCON_SBCER_I2S1_CLK_EN (0x0014) +#define U300_SYSCON_SBCER_I2S0_CLK_EN (0x0013) +#define U300_SYSCON_SBCER_I2C1_CLK_EN (0x0012) +#define U300_SYSCON_SBCER_I2C0_CLK_EN (0x0011) +#define U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN (0x0010) +#ifdef CONFIG_MACH_U300_BS335 +#define U300_SYSCON_SBCER_CDS_CLK_EN (0x002D) +#define U300_SYSCON_SBCER_ISP_CLK_EN (0x002C) +#endif +#define U300_SYSCON_SBCER_MSPRO_CLK_EN (0x002B) +#define U300_SYSCON_SBCER_AHB_SUBSYS_BRIDGE_CLK_EN (0x002A) +#define U300_SYSCON_SBCER_SEMI_CLK_EN (0x0029) +#define U300_SYSCON_SBCER_XGAM_CLK_EN (0x0028) +#define U300_SYSCON_SBCER_VIDEO_ENC_CLK_EN (0x0027) +#define U300_SYSCON_SBCER_NANDIF_CLK_EN (0x0026) +#define U300_SYSCON_SBCER_EMIF_CLK_EN (0x0025) +#define U300_SYSCON_SBCER_DMAC_CLK_EN (0x0024) +#define U300_SYSCON_SBCER_CPU_CLK_EN (0x0023) +#define U300_SYSCON_SBCER_APEX_CLK_EN (0x0022) +#define U300_SYSCON_SBCER_AHB_CLK_EN (0x0021) +#define U300_SYSCON_SBCER_AAIF_CLK_EN (0x0020) +/* Single block clock disable 16bit (-/W) */ +#define U300_SYSCON_SBCDR (0x0030) +/* Same values as above for SBCER */ +/* Clock force SLOW peripherals 16bit (R/W) */ +#define U300_SYSCON_CFSR (0x003c) +#ifdef CONFIG_MACH_U300_BS335 +#define U300_SYSCON_CFSR_PPM_CLK_FORCE_EN (0x0200) +#endif +#define U300_SYSCON_CFSR_ACC_TMR_CLK_FORCE_EN (0x0100) +#define U300_SYSCON_CFSR_APP_TMR_CLK_FORCE_EN (0x0080) +#define U300_SYSCON_CFSR_KEYPAD_CLK_FORCE_EN (0x0020) +#define U300_SYSCON_CFSR_GPIO_CLK_FORCE_EN (0x0010) +#define U300_SYSCON_CFSR_EH_CLK_FORCE_EN (0x0008) +#define U300_SYSCON_CFSR_BTR_CLK_FORCE_EN (0x0004) +#define U300_SYSCON_CFSR_UART_CLK_FORCE_EN (0x0002) +#define U300_SYSCON_CFSR_SLOW_BRIDGE_CLK_FORCE_EN (0x0001) +/* Clock force FAST peripherals 16bit (R/W) */ +#define U300_SYSCON_CFFR (0x40) +/* Values not defined. Define if you want to use them. */ +/* Clock force the rest of the peripherals 16bit (R/W) */ +#define U300_SYSCON_CFRR (0x44) +#ifdef CONFIG_MACH_U300_BS335 +#define U300_SYSCON_CFRR_CDS_CLK_FORCE_EN (0x2000) +#define U300_SYSCON_CFRR_ISP_CLK_FORCE_EN (0x1000) +#endif +#define U300_SYSCON_CFRR_MSPRO_CLK_FORCE_EN (0x0800) +#define U300_SYSCON_CFRR_AHB_SUBSYS_BRIDGE_CLK_FORCE_EN (0x0400) +#define U300_SYSCON_CFRR_SEMI_CLK_FORCE_EN (0x0200) +#define U300_SYSCON_CFRR_XGAM_CLK_FORCE_EN (0x0100) +#define U300_SYSCON_CFRR_VIDEO_ENC_CLK_FORCE_EN (0x0080) +#define U300_SYSCON_CFRR_NANDIF_CLK_FORCE_EN (0x0040) +#define U300_SYSCON_CFRR_EMIF_CLK_FORCE_EN (0x0020) +#define U300_SYSCON_CFRR_DMAC_CLK_FORCE_EN (0x0010) +#define U300_SYSCON_CFRR_CPU_CLK_FORCE_EN (0x0008) +#define U300_SYSCON_CFRR_APEX_CLK_FORCE_EN (0x0004) +#define U300_SYSCON_CFRR_AHB_CLK_FORCE_EN (0x0002) +#define U300_SYSCON_CFRR_AAIF_CLK_FORCE_EN (0x0001) +/* PLL208 Frequency Control 16bit (R/W) */ +#define U300_SYSCON_PFCR (0x48) +#define U300_SYSCON_PFCR_DPLL_MULT_NUM (0x000F) +/* Power Management Control 16bit (R/W) */ +#define U300_SYSCON_PMCR (0x50) +#define U300_SYSCON_PMCR_DCON_ENABLE (0x0002) +#define U300_SYSCON_PMCR_PWR_MGNT_ENABLE (0x0001) +/* + * All other clocking registers moved to clock.c! + */ +/* Reset Out 16bit (R/W) */ +#define U300_SYSCON_RCR (0x6c) +#define U300_SYSCON_RCR_RESOUT0_RST_N_DISABLE (0x0001) +/* EMIF Slew Rate Control 16bit (R/W) */ +#define U300_SYSCON_SRCLR (0x70) +#define U300_SYSCON_SRCLR_MASK (0x03FF) +#define U300_SYSCON_SRCLR_VALUE (0x03FF) +#define U300_SYSCON_SRCLR_EMIF_1_SLRC_5_B (0x0200) +#define U300_SYSCON_SRCLR_EMIF_1_SLRC_5_A (0x0100) +#define U300_SYSCON_SRCLR_EMIF_1_SLRC_4_B (0x0080) +#define U300_SYSCON_SRCLR_EMIF_1_SLRC_4_A (0x0040) +#define U300_SYSCON_SRCLR_EMIF_1_SLRC_3_B (0x0020) +#define U300_SYSCON_SRCLR_EMIF_1_SLRC_3_A (0x0010) +#define U300_SYSCON_SRCLR_EMIF_1_SLRC_2_B (0x0008) +#define U300_SYSCON_SRCLR_EMIF_1_SLRC_2_A (0x0004) +#define U300_SYSCON_SRCLR_EMIF_1_SLRC_1_B (0x0002) +#define U300_SYSCON_SRCLR_EMIF_1_SLRC_1_A (0x0001) +/* EMIF Clock Control Register 16bit (R/W) */ +#define U300_SYSCON_ECCR (0x0078) +#define U300_SYSCON_ECCR_MASK (0x000F) +#define U300_SYSCON_ECCR_EMIF_1_STATIC_CLK_EN_N_DISABLE (0x0008) +#define U300_SYSCON_ECCR_EMIF_1_RET_OUT_CLK_EN_N_DISABLE (0x0004) +#define U300_SYSCON_ECCR_EMIF_MEMCLK_RET_EN_N_DISABLE (0x0002) +#define U300_SYSCON_ECCR_EMIF_SDRCLK_RET_EN_N_DISABLE (0x0001) +/* PAD MUX Control register 1 (LOW) 16bit (R/W) */ +#define U300_SYSCON_PMC1LR (0x007C) +#define U300_SYSCON_PMC1LR_MASK (0xFFFF) +#define U300_SYSCON_PMC1LR_CDI_MASK (0xC000) +#define U300_SYSCON_PMC1LR_CDI_CDI (0x0000) +#define U300_SYSCON_PMC1LR_CDI_EMIF (0x4000) +#define U300_SYSCON_PMC1LR_CDI_GPIO (0x8000) +#define U300_SYSCON_PMC1LR_CDI_WCDMA (0xC000) +#define U300_SYSCON_PMC1LR_PDI_MASK (0x3000) +#define U300_SYSCON_PMC1LR_PDI_PDI (0x0000) +#define U300_SYSCON_PMC1LR_PDI_EGG (0x1000) +#define U300_SYSCON_PMC1LR_PDI_WCDMA (0x3000) +#define U300_SYSCON_PMC1LR_MMCSD_MASK (0x0C00) +#define U300_SYSCON_PMC1LR_MMCSD_MMCSD (0x0000) +#define U300_SYSCON_PMC1LR_MMCSD_MSPRO (0x0400) +#define U300_SYSCON_PMC1LR_MMCSD_DSP (0x0800) +#define U300_SYSCON_PMC1LR_MMCSD_WCDMA (0x0C00) +#define U300_SYSCON_PMC1LR_ETM_MASK (0x0300) +#define U300_SYSCON_PMC1LR_ETM_ACC (0x0000) +#define U300_SYSCON_PMC1LR_ETM_APP (0x0100) +#define U300_SYSCON_PMC1LR_EMIF_1_CS2_MASK (0x00C0) +#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC (0x0000) +#define U300_SYSCON_PMC1LR_EMIF_1_CS2_NFIF (0x0040) +#define U300_SYSCON_PMC1LR_EMIF_1_CS2_SDRAM (0x0080) +#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC_2GB (0x00C0) +#define U300_SYSCON_PMC1LR_EMIF_1_CS1_MASK (0x0030) +#define U300_SYSCON_PMC1LR_EMIF_1_CS1_STATIC (0x0000) +#define U300_SYSCON_PMC1LR_EMIF_1_CS1_NFIF (0x0010) +#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SDRAM (0x0020) +#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SEMI (0x0030) +#define U300_SYSCON_PMC1LR_EMIF_1_CS0_MASK (0x000C) +#define U300_SYSCON_PMC1LR_EMIF_1_CS0_STATIC (0x0000) +#define U300_SYSCON_PMC1LR_EMIF_1_CS0_NFIF (0x0004) +#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SDRAM (0x0008) +#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SEMI (0x000C) +#define U300_SYSCON_PMC1LR_EMIF_1_MASK (0x0003) +#define U300_SYSCON_PMC1LR_EMIF_1_STATIC (0x0000) +#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM0 (0x0001) +#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM1 (0x0002) +#define U300_SYSCON_PMC1LR_EMIF_1 (0x0003) +/* PAD MUX Control register 2 (HIGH) 16bit (R/W) */ +#define U300_SYSCON_PMC1HR (0x007E) +#define U300_SYSCON_PMC1HR_MASK (0xFFFF) +#define U300_SYSCON_PMC1HR_MISC_2_MASK (0xC000) +#define U300_SYSCON_PMC1HR_MISC_2_APP_GPIO (0x0000) +#define U300_SYSCON_PMC1HR_MISC_2_MSPRO (0x4000) +#define U300_SYSCON_PMC1HR_MISC_2_DSP (0x8000) +#define U300_SYSCON_PMC1HR_MISC_2_AAIF (0xC000) +#define U300_SYSCON_PMC1HR_APP_GPIO_2_MASK (0x3000) +#define U300_SYSCON_PMC1HR_APP_GPIO_2_APP_GPIO (0x0000) +#define U300_SYSCON_PMC1HR_APP_GPIO_2_NFIF (0x1000) +#define U300_SYSCON_PMC1HR_APP_GPIO_2_DSP (0x2000) +#define U300_SYSCON_PMC1HR_APP_GPIO_2_AAIF (0x3000) +#define U300_SYSCON_PMC1HR_APP_GPIO_1_MASK (0x0C00) +#define U300_SYSCON_PMC1HR_APP_GPIO_1_APP_GPIO (0x0000) +#define U300_SYSCON_PMC1HR_APP_GPIO_1_MMC (0x0400) +#define U300_SYSCON_PMC1HR_APP_GPIO_1_DSP (0x0800) +#define U300_SYSCON_PMC1HR_APP_GPIO_1_AAIF (0x0C00) +#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK (0x0300) +#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_APP_GPIO (0x0000) +#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI (0x0100) +#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_AAIF (0x0300) +#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK (0x00C0) +#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_APP_GPIO (0x0000) +#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI (0x0040) +#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_AAIF (0x00C0) +#define U300_SYSCON_PMC1HR_APP_SPI_2_MASK (0x0030) +#define U300_SYSCON_PMC1HR_APP_SPI_2_APP_GPIO (0x0000) +#define U300_SYSCON_PMC1HR_APP_SPI_2_SPI (0x0010) +#define U300_SYSCON_PMC1HR_APP_SPI_2_DSP (0x0020) +#define U300_SYSCON_PMC1HR_APP_SPI_2_AAIF (0x0030) +#define U300_SYSCON_PMC1HR_APP_UART0_2_MASK (0x000C) +#define U300_SYSCON_PMC1HR_APP_UART0_2_APP_GPIO (0x0000) +#define U300_SYSCON_PMC1HR_APP_UART0_2_UART0 (0x0004) +#define U300_SYSCON_PMC1HR_APP_UART0_2_NFIF_CS (0x0008) +#define U300_SYSCON_PMC1HR_APP_UART0_2_AAIF (0x000C) +#define U300_SYSCON_PMC1HR_APP_UART0_1_MASK (0x0003) +#define U300_SYSCON_PMC1HR_APP_UART0_1_APP_GPIO (0x0000) +#define U300_SYSCON_PMC1HR_APP_UART0_1_UART0 (0x0001) +#define U300_SYSCON_PMC1HR_APP_UART0_1_AAIF (0x0003) +/* Step one for killing the applications system 16bit (-/W) */ +#define U300_SYSCON_KA1R (0x0080) +#define U300_SYSCON_KA1R_MASK (0xFFFF) +#define U300_SYSCON_KA1R_VALUE (0xFFFF) +/* Step two for killing the application system 16bit (-/W) */ +#define U300_SYSCON_KA2R (0x0084) +#define U300_SYSCON_KA2R_MASK (0xFFFF) +#define U300_SYSCON_KA2R_VALUE (0xFFFF) +/* MMC/MSPRO frequency divider register 0 16bit (R/W) */ +#define U300_SYSCON_MMF0R (0x90) +#define U300_SYSCON_MMF0R_MASK (0x00FF) +#define U300_SYSCON_MMF0R_FREQ_0_HIGH_MASK (0x00F0) +#define U300_SYSCON_MMF0R_FREQ_0_LOW_MASK (0x000F) +/* MMC/MSPRO frequency divider register 1 16bit (R/W) */ +#define U300_SYSCON_MMF1R (0x94) +#define U300_SYSCON_MMF1R_MASK (0x00FF) +#define U300_SYSCON_MMF1R_FREQ_1_HIGH_MASK (0x00F0) +#define U300_SYSCON_MMF1R_FREQ_1_LOW_MASK (0x000F) +/* AAIF control register 16 bit (R/W) */ +#define U300_SYSCON_AAIFCR (0x98) +#define U300_SYSCON_AAIFCR_MASK (0x0003) +#define U300_SYSCON_AAIFCR_AASW_CTRL_MASK (0x0003) +#define U300_SYSCON_AAIFCR_AASW_CTRL_FUNCTIONAL (0x0000) +#define U300_SYSCON_AAIFCR_AASW_CTRL_MONITORING (0x0001) +#define U300_SYSCON_AAIFCR_AASW_CTRL_ACC_TO_EXT (0x0002) +#define U300_SYSCON_AAIFCR_AASW_CTRL_APP_TO_EXT (0x0003) +/* Clock control for the MMC and MSPRO blocks 16bit (R/W) */ +#define U300_SYSCON_MMCR (0x9C) +#define U300_SYSCON_MMCR_MASK (0x0003) +#define U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE (0x0002) +#define U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE (0x0001) + +/* TODO: More SYSCON registers missing */ +#define U300_SYSCON_PMC3R (0x10c) +#define U300_SYSCON_PMC3R_APP_MISC_11_MASK (0xc000) +#define U300_SYSCON_PMC3R_APP_MISC_11_SPI (0x4000) +#define U300_SYSCON_PMC3R_APP_MISC_10_MASK (0x3000) +#define U300_SYSCON_PMC3R_APP_MISC_10_SPI (0x1000) +/* TODO: Missing other configs, I just added the SPI stuff */ + +/* SYS_0_CLK_CONTROL first clock control 16bit (R/W) */ +#define U300_SYSCON_S0CCR (0x120) +#define U300_SYSCON_S0CCR_FIELD_MASK (0x43FF) +#define U300_SYSCON_S0CCR_CLOCK_REQ (0x4000) +#define U300_SYSCON_S0CCR_CLOCK_INV (0x0200) +#define U300_SYSCON_S0CCR_CLOCK_FREQ_MASK (0x01E0) +#define U300_SYSCON_S0CCR_CLOCK_SELECT_MASK (0x001E) +#define U300_SYSCON_S0CCR_CLOCK_ENABLE (0x0001) +#define U300_SYSCON_S0CCR_SEL_MCLK (0x8<<1) +#define U300_SYSCON_S0CCR_SEL_ACC_FSM_CLK (0xA<<1) +#define U300_SYSCON_S0CCR_SEL_PLL60_48_CLK (0xC<<1) +#define U300_SYSCON_S0CCR_SEL_PLL60_60_CLK (0xD<<1) +#define U300_SYSCON_S0CCR_SEL_ACC_PLL208_CLK (0xE<<1) +#define U300_SYSCON_S0CCR_SEL_APP_PLL13_CLK (0x0<<1) +#define U300_SYSCON_S0CCR_SEL_APP_FSM_CLK (0x2<<1) +#define U300_SYSCON_S0CCR_SEL_RTC_CLK (0x4<<1) +#define U300_SYSCON_S0CCR_SEL_APP_PLL208_CLK (0x6<<1) +/* SYS_1_CLK_CONTROL second clock control 16 bit (R/W) */ +#define U300_SYSCON_S1CCR (0x124) +#define U300_SYSCON_S1CCR_FIELD_MASK (0x43FF) +#define U300_SYSCON_S1CCR_CLOCK_REQ (0x4000) +#define U300_SYSCON_S1CCR_CLOCK_INV (0x0200) +#define U300_SYSCON_S1CCR_CLOCK_FREQ_MASK (0x01E0) +#define U300_SYSCON_S1CCR_CLOCK_SELECT_MASK (0x001E) +#define U300_SYSCON_S1CCR_CLOCK_ENABLE (0x0001) +#define U300_SYSCON_S1CCR_SEL_MCLK (0x8<<1) +#define U300_SYSCON_S1CCR_SEL_ACC_FSM_CLK (0xA<<1) +#define U300_SYSCON_S1CCR_SEL_PLL60_48_CLK (0xC<<1) +#define U300_SYSCON_S1CCR_SEL_PLL60_60_CLK (0xD<<1) +#define U300_SYSCON_S1CCR_SEL_ACC_PLL208_CLK (0xE<<1) +#define U300_SYSCON_S1CCR_SEL_ACC_PLL13_CLK (0x0<<1) +#define U300_SYSCON_S1CCR_SEL_APP_FSM_CLK (0x2<<1) +#define U300_SYSCON_S1CCR_SEL_RTC_CLK (0x4<<1) +#define U300_SYSCON_S1CCR_SEL_APP_PLL208_CLK (0x6<<1) +/* SYS_2_CLK_CONTROL third clock contol 16 bit (R/W) */ +#define U300_SYSCON_S2CCR (0x128) +#define U300_SYSCON_S2CCR_FIELD_MASK (0xC3FF) +#define U300_SYSCON_S2CCR_CLK_STEAL (0x8000) +#define U300_SYSCON_S2CCR_CLOCK_REQ (0x4000) +#define U300_SYSCON_S2CCR_CLOCK_INV (0x0200) +#define U300_SYSCON_S2CCR_CLOCK_FREQ_MASK (0x01E0) +#define U300_SYSCON_S2CCR_CLOCK_SELECT_MASK (0x001E) +#define U300_SYSCON_S2CCR_CLOCK_ENABLE (0x0001) +#define U300_SYSCON_S2CCR_SEL_MCLK (0x8<<1) +#define U300_SYSCON_S2CCR_SEL_ACC_FSM_CLK (0xA<<1) +#define U300_SYSCON_S2CCR_SEL_PLL60_48_CLK (0xC<<1) +#define U300_SYSCON_S2CCR_SEL_PLL60_60_CLK (0xD<<1) +#define U300_SYSCON_S2CCR_SEL_ACC_PLL208_CLK (0xE<<1) +#define U300_SYSCON_S2CCR_SEL_ACC_PLL13_CLK (0x0<<1) +#define U300_SYSCON_S2CCR_SEL_APP_FSM_CLK (0x2<<1) +#define U300_SYSCON_S2CCR_SEL_RTC_CLK (0x4<<1) +#define U300_SYSCON_S2CCR_SEL_APP_PLL208_CLK (0x6<<1) +/* SYS_MISC_CONTROL, miscellaneous 16bit (R/W) */ +#define U300_SYSCON_MCR (0x12c) +#define U300_SYSCON_MCR_FIELD_MASK (0x00FF) +#define U300_SYSCON_MCR_PMGEN_CR_4_MASK (0x00C0) +#define U300_SYSCON_MCR_PMGEN_CR_4_GPIO (0x0000) +#define U300_SYSCON_MCR_PMGEN_CR_4_SPI (0x0040) +#define U300_SYSCON_MCR_PMGEN_CR_4_AAIF (0x00C0) +#define U300_SYSCON_MCR_PMGEN_CR_2_MASK (0x0030) +#define U300_SYSCON_MCR_PMGEN_CR_2_GPIO (0x0000) +#define U300_SYSCON_MCR_PMGEN_CR_2_EMIF_1_STATIC (0x0010) +#define U300_SYSCON_MCR_PMGEN_CR_2_DSP (0x0020) +#define U300_SYSCON_MCR_PMGEN_CR_2_AAIF (0x0030) +#define U300_SYSCON_MCR_PMGEN_CR_0_MASK (0x000C) +#define U300_SYSCON_MCR_PMGEN_CR_0_EMIF_1_SDRAM_M1 (0x0000) +#define U300_SYSCON_MCR_PMGEN_CR_0_EMIF_1_SDRAM_M2 (0x0004) +#define U300_SYSCON_MCR_PMGEN_CR_0_EMIF_1_SDRAM_M3 (0x0008) +#define U300_SYSCON_MCR_PMGEN_CR_0_EMIF_0_SDRAM (0x000C) +#define U300_SYSCON_MCR_PM1G_MODE_ENABLE (0x0002) +#define U300_SYSCON_MCR_PMTG5_MODE_ENABLE (0x0001) +/* Clock activity observability register 0 */ +#define U300_SYSCON_C0OAR (0x140) +#define U300_SYSCON_C0OAR_MASK (0xFFFF) +#define U300_SYSCON_C0OAR_VALUE (0xFFFF) +#define U300_SYSCON_C0OAR_BT_H_CLK (0x8000) +#define U300_SYSCON_C0OAR_ASPB_P_CLK (0x4000) +#define U300_SYSCON_C0OAR_APP_SEMI_H_CLK (0x2000) +#define U300_SYSCON_C0OAR_APP_SEMI_CLK (0x1000) +#define U300_SYSCON_C0OAR_APP_MMC_MSPRO_CLK (0x0800) +#define U300_SYSCON_C0OAR_APP_I2S1_CLK (0x0400) +#define U300_SYSCON_C0OAR_APP_I2S0_CLK (0x0200) +#define U300_SYSCON_C0OAR_APP_CPU_CLK (0x0100) +#define U300_SYSCON_C0OAR_APP_52_CLK (0x0080) +#define U300_SYSCON_C0OAR_APP_208_CLK (0x0040) +#define U300_SYSCON_C0OAR_APP_104_CLK (0x0020) +#define U300_SYSCON_C0OAR_APEX_CLK (0x0010) +#define U300_SYSCON_C0OAR_AHPB_M_H_CLK (0x0008) +#define U300_SYSCON_C0OAR_AHB_CLK (0x0004) +#define U300_SYSCON_C0OAR_AFPB_P_CLK (0x0002) +#define U300_SYSCON_C0OAR_AAIF_CLK (0x0001) +/* Clock activity observability register 1 */ +#define U300_SYSCON_C1OAR (0x144) +#define U300_SYSCON_C1OAR_MASK (0x3FFE) +#define U300_SYSCON_C1OAR_VALUE (0x3FFE) +#define U300_SYSCON_C1OAR_NFIF_F_CLK (0x2000) +#define U300_SYSCON_C1OAR_MSPRO_CLK (0x1000) +#define U300_SYSCON_C1OAR_MMC_P_CLK (0x0800) +#define U300_SYSCON_C1OAR_MMC_CLK (0x0400) +#define U300_SYSCON_C1OAR_KP_P_CLK (0x0200) +#define U300_SYSCON_C1OAR_I2C1_P_CLK (0x0100) +#define U300_SYSCON_C1OAR_I2C0_P_CLK (0x0080) +#define U300_SYSCON_C1OAR_GPIO_CLK (0x0040) +#define U300_SYSCON_C1OAR_EMIF_MPMC_CLK (0x0020) +#define U300_SYSCON_C1OAR_EMIF_H_CLK (0x0010) +#define U300_SYSCON_C1OAR_EVHIST_CLK (0x0008) +#define U300_SYSCON_C1OAR_PPM_CLK (0x0004) +#define U300_SYSCON_C1OAR_DMA_CLK (0x0002) +/* Clock activity observability register 2 */ +#define U300_SYSCON_C2OAR (0x148) +#define U300_SYSCON_C2OAR_MASK (0x0FFF) +#define U300_SYSCON_C2OAR_VALUE (0x0FFF) +#define U300_SYSCON_C2OAR_XGAM_CDI_CLK (0x0800) +#define U300_SYSCON_C2OAR_XGAM_CLK (0x0400) +#define U300_SYSCON_C2OAR_VC_H_CLK (0x0200) +#define U300_SYSCON_C2OAR_VC_CLK (0x0100) +#define U300_SYSCON_C2OAR_UA_P_CLK (0x0080) +#define U300_SYSCON_C2OAR_TMR1_CLK (0x0040) +#define U300_SYSCON_C2OAR_TMR0_CLK (0x0020) +#define U300_SYSCON_C2OAR_SPI_P_CLK (0x0010) +#define U300_SYSCON_C2OAR_PCM_I2S1_CORE_CLK (0x0008) +#define U300_SYSCON_C2OAR_PCM_I2S1_CLK (0x0004) +#define U300_SYSCON_C2OAR_PCM_I2S0_CORE_CLK (0x0002) +#define U300_SYSCON_C2OAR_PCM_I2S0_CLK (0x0001) + +/* Chip ID register 16bit (R/-) */ +#define U300_SYSCON_CIDR (0x400) +/* Video IRQ clear 16bit (R/W) */ +#define U300_SYSCON_VICR (0x404) +#define U300_SYSCON_VICR_VIDEO1_IRQ_CLEAR_ENABLE (0x0002) +#define U300_SYSCON_VICR_VIDEO0_IRQ_CLEAR_ENABLE (0x0001) +/* SMCR */ +#define U300_SYSCON_SMCR (0x4d0) +#define U300_SYSCON_SMCR_FIELD_MASK (0x000e) +#define U300_SYSCON_SMCR_SEMI_SREFACK_IND (0x0008) +#define U300_SYSCON_SMCR_SEMI_SREFREQ_ENABLE (0x0004) +#define U300_SYSCON_SMCR_SEMI_EXT_BOOT_MODE_ENABLE (0x0002) +/* CPU_SW_DBGEN Software Debug Enable 16bit (R/W) */ +#define U300_SYSCON_CSDR (0x4f0) +#define U300_SYSCON_CSDR_SW_DEBUG_ENABLE (0x0001) +/* PRINT_CONTROL Print Control 16bit (R/-) */ +#define U300_SYSCON_PCR (0x4f8) +#define U300_SYSCON_PCR_SERV_IND (0x0001) +/* BOOT_CONTROL 16bit (R/-) */ +#define U300_SYSCON_BCR (0x4fc) +#define U300_SYSCON_BCR_ACC_CPU_SUBSYS_VINITHI_IND (0x0400) +#define U300_SYSCON_BCR_APP_CPU_SUBSYS_VINITHI_IND (0x0200) +#define U300_SYSCON_BCR_EXTRA_BOOT_OPTION_MASK (0x01FC) +#define U300_SYSCON_BCR_APP_BOOT_SERV_MASK (0x0003) + + +/* CPU clock defines */ +/** + * CPU high frequency in MHz + */ +#define SYSCON_CPU_CLOCK_HIGH 208 +/** + * CPU medium frequency in MHz + */ +#define SYSCON_CPU_CLOCK_MEDIUM 104 +/** + * CPU low frequency in MHz + */ +#define SYSCON_CPU_CLOCK_LOW 13 + +/* EMIF clock defines */ +/** + * EMIF high frequency in MHz + */ +#define SYSCON_EMIF_CLOCK_HIGH 104 +/** + * EMIF medium frequency in MHz + */ +#define SYSCON_EMIF_CLOCK_MEDIUM 104 +/** + * EMIF low frequency in MHz + */ +#define SYSCON_EMIF_CLOCK_LOW 13 + +/* AHB clock defines */ +/** + * AHB high frequency in MHz + */ +#define SYSCON_AHB_CLOCK_HIGH 52 +/** + * AHB medium frequency in MHz + */ +#define SYSCON_AHB_CLOCK_MEDIUM 52 +/** + * AHB low frequency in MHz + */ +#define SYSCON_AHB_CLOCK_LOW 7 /* i.e 13/2=6.5MHz */ + +enum syscon_busmaster { + SYSCON_BM_DMAC, + SYSCON_BM_XGAM, + SYSCON_BM_VIDEO_ENC +}; + +/* + * Note that this array must match the order of the array "clk_reg" + * in syscon.c + */ +enum syscon_clk { + SYSCON_CLKCONTROL_SLOW_BRIDGE, + SYSCON_CLKCONTROL_UART, + SYSCON_CLKCONTROL_BTR, + SYSCON_CLKCONTROL_EH, + SYSCON_CLKCONTROL_GPIO, + SYSCON_CLKCONTROL_KEYPAD, + SYSCON_CLKCONTROL_APP_TIMER, + SYSCON_CLKCONTROL_ACC_TIMER, + SYSCON_CLKCONTROL_FAST_BRIDGE, + SYSCON_CLKCONTROL_I2C0, + SYSCON_CLKCONTROL_I2C1, + SYSCON_CLKCONTROL_I2S0, + SYSCON_CLKCONTROL_I2S1, + SYSCON_CLKCONTROL_MMC, + SYSCON_CLKCONTROL_SPI, + SYSCON_CLKCONTROL_I2S0_CORE, + SYSCON_CLKCONTROL_I2S1_CORE, + SYSCON_CLKCONTROL_AAIF, + SYSCON_CLKCONTROL_AHB, + SYSCON_CLKCONTROL_APEX, + SYSCON_CLKCONTROL_CPU, + SYSCON_CLKCONTROL_DMA, + SYSCON_CLKCONTROL_EMIF, + SYSCON_CLKCONTROL_NAND_IF, + SYSCON_CLKCONTROL_VIDEO_ENC, + SYSCON_CLKCONTROL_XGAM, + SYSCON_CLKCONTROL_SEMI, + SYSCON_CLKCONTROL_AHB_SUBSYS, + SYSCON_CLKCONTROL_MSPRO +}; + +enum syscon_sysclk_mode { + SYSCON_SYSCLK_DISABLED, + SYSCON_SYSCLK_M_CLK, + SYSCON_SYSCLK_ACC_FSM, + SYSCON_SYSCLK_PLL60_48, + SYSCON_SYSCLK_PLL60_60, + SYSCON_SYSCLK_ACC_PLL208, + SYSCON_SYSCLK_APP_PLL13, + SYSCON_SYSCLK_APP_FSM, + SYSCON_SYSCLK_RTC, + SYSCON_SYSCLK_APP_PLL208 +}; + +enum syscon_sysclk_req { + SYSCON_SYSCLKREQ_DISABLED, + SYSCON_SYSCLKREQ_ACTIVE_LOW +}; + +enum syscon_clk_mode { + SYSCON_CLKMODE_OFF, + SYSCON_CLKMODE_DEFAULT, + SYSCON_CLKMODE_LOW, + SYSCON_CLKMODE_MEDIUM, + SYSCON_CLKMODE_HIGH, + SYSCON_CLKMODE_PERMANENT, + SYSCON_CLKMODE_ON, +}; + +enum syscon_call_mode { + SYSCON_CLKCALL_NOWAIT, + SYSCON_CLKCALL_WAIT, +}; + +int syscon_dc_on(bool keep_power_on); +int syscon_set_busmaster_active_state(enum syscon_busmaster busmaster, + bool active); +bool syscon_get_busmaster_active_state(void); +int syscon_set_sleep_mask(enum syscon_clk, + bool sleep_ctrl); +int syscon_config_sysclk(u32 sysclk, + enum syscon_sysclk_mode sysclkmode, + bool inverse, + u32 divisor, + enum syscon_sysclk_req sysclkreq); +bool syscon_can_turn_off_semi_clock(void); + +/* This function is restricted to core.c */ +int syscon_request_normal_power(bool req); + +/* This function is restricted to be used by platform_speed.c */ +int syscon_speed_request(enum syscon_call_mode wait_mode, + enum syscon_clk_mode req_clk_mode); +#endif /* __MACH_SYSCON_H */ diff --git a/arch/arm/mach-u300/include/mach/u300-regs.h b/arch/arm/mach-u300/include/mach/u300-regs.h new file mode 100644 index 00000000000..88333dfb19f --- /dev/null +++ b/arch/arm/mach-u300/include/mach/u300-regs.h @@ -0,0 +1,187 @@ +/* + * + * arch/arm/mach-u300/include/mach/u300-regs.h + * + * + * Copyright (C) 2006-2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * Basic register address definitions in physical memory and + * some block defintions for core devices like the timer. + * Author: Linus Walleij + */ + +#ifndef __MACH_U300_REGS_H +#define __MACH_U300_REGS_H + +/* + * These are the large blocks of memory allocated for I/O. + * the defines are used for setting up the I/O memory mapping. + */ + +/* NAND Flash CS0 */ +#define U300_NAND_CS0_PHYS_BASE 0x80000000 +#define U300_NAND_CS0_VIRT_BASE 0xff040000 + +/* NFIF */ +#define U300_NAND_IF_PHYS_BASE 0x9f800000 +#define U300_NAND_IF_VIRT_BASE 0xff030000 + +/* AHB Peripherals */ +#define U300_AHB_PER_PHYS_BASE 0xa0000000 +#define U300_AHB_PER_VIRT_BASE 0xff010000 + +/* FAST Peripherals */ +#define U300_FAST_PER_PHYS_BASE 0xc0000000 +#define U300_FAST_PER_VIRT_BASE 0xff020000 + +/* SLOW Peripherals */ +#define U300_SLOW_PER_PHYS_BASE 0xc0010000 +#define U300_SLOW_PER_VIRT_BASE 0xff000000 + +/* Boot ROM */ +#define U300_BOOTROM_PHYS_BASE 0xffff0000 +#define U300_BOOTROM_VIRT_BASE 0xffff0000 + +/* SEMI config base */ +#ifdef CONFIG_MACH_U300_BS335 +#define U300_SEMI_CONFIG_BASE 0x2FFE0000 +#else +#define U300_SEMI_CONFIG_BASE 0x30000000 +#endif + +/* + * All the following peripherals are specified at their PHYSICAL address, + * so if you need to access them (in the kernel), you MUST use the macros + * defined in to map to the IO_ADDRESS_AHB() IO_ADDRESS_FAST() + * etc. + */ + +/* + * AHB peripherals + */ + +/* AHB Peripherals Bridge Controller */ +#define U300_AHB_BRIDGE_BASE (U300_AHB_PER_PHYS_BASE+0x0000) + +/* Vectored Interrupt Controller 0, servicing 32 interrupts */ +#define U300_INTCON0_BASE (U300_AHB_PER_PHYS_BASE+0x1000) +#define U300_INTCON0_VBASE (U300_AHB_PER_VIRT_BASE+0x1000) + +/* Vectored Interrupt Controller 1, servicing 32 interrupts */ +#define U300_INTCON1_BASE (U300_AHB_PER_PHYS_BASE+0x2000) +#define U300_INTCON1_VBASE (U300_AHB_PER_VIRT_BASE+0x2000) + +/* Memory Stick Pro (MSPRO) controller */ +#define U300_MSPRO_BASE (U300_AHB_PER_PHYS_BASE+0x3000) + +/* EMIF Configuration Area */ +#define U300_EMIF_CFG_BASE (U300_AHB_PER_PHYS_BASE+0x4000) + + +/* + * FAST peripherals + */ + +/* FAST bridge control */ +#define U300_FAST_BRIDGE_BASE (U300_FAST_PER_PHYS_BASE+0x0000) + +/* MMC/SD controller */ +#define U300_MMCSD_BASE (U300_FAST_PER_PHYS_BASE+0x1000) + +/* PCM I2S0 controller */ +#define U300_PCM_I2S0_BASE (U300_FAST_PER_PHYS_BASE+0x2000) + +/* PCM I2S1 controller */ +#define U300_PCM_I2S1_BASE (U300_FAST_PER_PHYS_BASE+0x3000) + +/* I2C0 controller */ +#define U300_I2C0_BASE (U300_FAST_PER_PHYS_BASE+0x4000) + +/* I2C1 controller */ +#define U300_I2C1_BASE (U300_FAST_PER_PHYS_BASE+0x5000) + +/* SPI controller */ +#define U300_SPI_BASE (U300_FAST_PER_PHYS_BASE+0x6000) + +#ifdef CONFIG_MACH_U300_BS335 +/* Fast UART1 on U335 only */ +#define U300_UART1_BASE (U300_SLOW_PER_PHYS_BASE+0x7000) +#endif + +/* + * SLOW peripherals + */ + +/* SLOW bridge control */ +#define U300_SLOW_BRIDGE_BASE (U300_SLOW_PER_PHYS_BASE) + +/* SYSCON */ +#define U300_SYSCON_BASE (U300_SLOW_PER_PHYS_BASE+0x1000) +#define U300_SYSCON_VBASE (U300_SLOW_PER_VIRT_BASE+0x1000) + +/* Watchdog */ +#define U300_WDOG_BASE (U300_SLOW_PER_PHYS_BASE+0x2000) + +/* UART0 */ +#define U300_UART0_BASE (U300_SLOW_PER_PHYS_BASE+0x3000) + +/* APP side special timer */ +#define U300_TIMER_APP_BASE (U300_SLOW_PER_PHYS_BASE+0x4000) +#define U300_TIMER_APP_VBASE (U300_SLOW_PER_VIRT_BASE+0x4000) + +/* Keypad */ +#define U300_KEYPAD_BASE (U300_SLOW_PER_PHYS_BASE+0x5000) + +/* GPIO */ +#define U300_GPIO_BASE (U300_SLOW_PER_PHYS_BASE+0x6000) + +/* RTC */ +#define U300_RTC_BASE (U300_SLOW_PER_PHYS_BASE+0x7000) + +/* Bus tracer */ +#define U300_BUSTR_BASE (U300_SLOW_PER_PHYS_BASE+0x8000) + +/* Event handler (hardware queue) */ +#define U300_EVHIST_BASE (U300_SLOW_PER_PHYS_BASE+0x9000) + +/* Genric Timer */ +#define U300_TIMER_BASE (U300_SLOW_PER_PHYS_BASE+0xa000) + +/* PPM */ +#define U300_PPM_BASE (U300_SLOW_PER_PHYS_BASE+0xb000) + + +/* + * REST peripherals + */ + +/* ISP (image signal processor) is only available in U335 */ +#ifdef CONFIG_MACH_U300_BS335 +#define U300_ISP_BASE (0xA0008000) +#endif + +/* DMA Controller base */ +#define U300_DMAC_BASE (0xC0020000) + +/* MSL Base */ +#define U300_MSL_BASE (0xc0022000) + +/* APEX Base */ +#define U300_APEX_BASE (0xc0030000) + +/* Video Encoder Base */ +#ifdef CONFIG_MACH_U300_BS335 +#define U300_VIDEOENC_BASE (0xc0080000) +#else +#define U300_VIDEOENC_BASE (0xc0040000) +#endif + +/* XGAM Base */ +#define U300_XGAM_BASE (0xd0000000) + +/* + * Virtual accessor macros for static devices + */ + + +#endif -- cgit v1.2.3 From bd41b99d4661e775ff152f2842782c43dbb30a59 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 23 Apr 2009 21:15:04 +0100 Subject: [ARM] 5471/2: U300 GPIO and PADMUX support This adds GPIO and PADMUX headers and implementation for the U300 platform. This is an implementation in isolation that depend on later patches in this series to plug into the framework. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-u300/gpio.c | 701 +++++++++++++++++++++++++++++++++ arch/arm/mach-u300/include/mach/gpio.h | 290 ++++++++++++++ arch/arm/mach-u300/padmux.c | 58 +++ arch/arm/mach-u300/padmux.h | 19 + 4 files changed, 1068 insertions(+) create mode 100644 arch/arm/mach-u300/gpio.c create mode 100644 arch/arm/mach-u300/include/mach/gpio.h create mode 100644 arch/arm/mach-u300/padmux.c create mode 100644 arch/arm/mach-u300/padmux.h (limited to 'arch/arm/mach-u300') diff --git a/arch/arm/mach-u300/gpio.c b/arch/arm/mach-u300/gpio.c new file mode 100644 index 00000000000..2d5ae8ecb8c --- /dev/null +++ b/arch/arm/mach-u300/gpio.c @@ -0,0 +1,701 @@ +/* + * + * arch/arm/mach-u300/gpio.c + * + * + * Copyright (C) 2007-2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * U300 GPIO module. + * This can driver either of the two basic GPIO cores + * available in the U300 platforms: + * COH 901 335 - Used in DB3150 (U300 1.0) and DB3200 (U330 1.0) + * COH 901 571/3 - Used in DB3210 (U365 2.0) and DB3350 (U335 1.0) + * Notice that you also have inline macros in + * Author: Linus Walleij + * Author: Jonas Aaberg + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Need access to SYSCON registers for PADmuxing */ +#include + +#include "padmux.h" + +/* Reference to GPIO block clock */ +static struct clk *clk; + +/* Memory resource */ +static struct resource *memres; +static void __iomem *virtbase; + +struct u300_gpio_port { + const char *name; + int irq; + int number; +}; + + +static struct u300_gpio_port gpio_ports[] = { + { + .name = "gpio0", + .number = 0, + }, + { + .name = "gpio1", + .number = 1, + }, + { + .name = "gpio2", + .number = 2, + }, +#ifdef U300_COH901571_3 + { + .name = "gpio3", + .number = 3, + }, + { + .name = "gpio4", + .number = 4, + }, +#ifdef CONFIG_MACH_U300_BS335 + { + .name = "gpio5", + .number = 5, + }, + { + .name = "gpio6", + .number = 6, + }, +#endif +#endif + +}; + + +#ifdef U300_COH901571_3 + +/* Default input value */ +#define DEFAULT_OUTPUT_LOW 0 +#define DEFAULT_OUTPUT_HIGH 1 + +/* GPIO Pull-Up status */ +#define DISABLE_PULL_UP 0 +#define ENABLE_PULL_UP 1 + +#define GPIO_NOT_USED 0 +#define GPIO_IN 1 +#define GPIO_OUT 2 + +struct u300_gpio_configuration_data { + unsigned char pin_usage; + unsigned char default_output_value; + unsigned char pull_up; +}; + +/* Initial configuration */ +const struct u300_gpio_configuration_data +u300_gpio_config[U300_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = { +#ifdef CONFIG_MACH_U300_BS335 + /* Port 0, pins 0-7 */ + { + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_HIGH, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP} + }, + /* Port 1, pins 0-7 */ + { + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_HIGH, DISABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP} + }, + /* Port 2, pins 0-7 */ + { + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP} + }, + /* Port 3, pins 0-7 */ + { + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP} + }, + /* Port 4, pins 0-7 */ + { + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP} + }, + /* Port 5, pins 0-7 */ + { + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP} + }, + /* Port 6, pind 0-7 */ + { + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP} + } +#endif + +#ifdef CONFIG_MACH_U300_BS365 + /* Port 0, pins 0-7 */ + { + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP} + }, + /* Port 1, pins 0-7 */ + { + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_HIGH, DISABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP} + }, + /* Port 2, pins 0-7 */ + { + {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP} + }, + /* Port 3, pins 0-7 */ + { + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP} + }, + /* Port 4, pins 0-7 */ + { + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + /* These 4 pins doesn't exist on DB3210 */ + {GPIO_OUT, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}, + {GPIO_OUT, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP} + } +#endif +}; +#endif + + +/* No users == we can power down GPIO */ +static int gpio_users; + +struct gpio_struct { + int (*callback)(void *); + void *data; + int users; +}; + +static struct gpio_struct gpio_pin[U300_GPIO_MAX]; + +/* + * Let drivers register callback in order to get notified when there is + * an interrupt on the gpio pin + */ +int gpio_register_callback(unsigned gpio, int (*func)(void *arg), void *data) +{ + if (gpio_pin[gpio].callback) + printk(KERN_WARNING "GPIO: %s: WARNING: callback already " \ + "registered for gpio pin#%d\n", __func__, gpio); + gpio_pin[gpio].callback = func; + gpio_pin[gpio].data = data; + + return 0; +} +EXPORT_SYMBOL(gpio_register_callback); + +int gpio_unregister_callback(unsigned gpio) +{ + if (!gpio_pin[gpio].callback) + printk(KERN_WARNING "GPIO: %s: WARNING: callback already " \ + "unregistered for gpio pin#%d\n", __func__, gpio); + gpio_pin[gpio].callback = NULL; + gpio_pin[gpio].data = NULL; + + return 0; +} +EXPORT_SYMBOL(gpio_unregister_callback); + +int gpio_request(unsigned gpio, const char *label) +{ + if (gpio_pin[gpio].users) + return -EINVAL; + else + gpio_pin[gpio].users++; + + gpio_users++; + + return 0; +} +EXPORT_SYMBOL(gpio_request); + +void gpio_free(unsigned gpio) +{ + gpio_users--; + gpio_pin[gpio].users--; + if (unlikely(gpio_pin[gpio].users < 0)) { + printk(KERN_WARNING "GPIO: Warning: gpio#%d release mismatch\n", + gpio); + gpio_pin[gpio].users = 0; + } + + return; +} +EXPORT_SYMBOL(gpio_free); + +/* This returns zero or nonzero */ +int gpio_get_value(unsigned gpio) +{ + return readl(virtbase + U300_GPIO_PXPDIR + + PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING) & (1 << (gpio & 0x07)); +} +EXPORT_SYMBOL(gpio_get_value); + +/* + * We hope that the compiler will optimize away the unused branch + * in case "value" is a constant + */ +void gpio_set_value(unsigned gpio, int value) +{ + u32 val; + unsigned long flags; + + local_irq_save(flags); + if (value) { + /* set */ + val = readl(virtbase + U300_GPIO_PXPDOR + + PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING) + & (1 << (gpio & 0x07)); + writel(val | (1 << (gpio & 0x07)), virtbase + + U300_GPIO_PXPDOR + + PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING); + } else { + /* clear */ + val = readl(virtbase + U300_GPIO_PXPDOR + + PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING) + & (1 << (gpio & 0x07)); + writel(val & ~(1 << (gpio & 0x07)), virtbase + + U300_GPIO_PXPDOR + + PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING); + } + local_irq_restore(flags); +} +EXPORT_SYMBOL(gpio_set_value); + +int gpio_direction_input(unsigned gpio) +{ + unsigned long flags; + u32 val; + + if (gpio > U300_GPIO_MAX) + return -EINVAL; + + local_irq_save(flags); + val = readl(virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) * + U300_GPIO_PORTX_SPACING); + /* Mask out this pin*/ + val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((gpio & 0x07) << 1)); + /* This is not needed since it sets the bits to zero.*/ + /* val |= (U300_GPIO_PXPCR_PIN_MODE_INPUT << (gpio*2)); */ + writel(val, virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) * + U300_GPIO_PORTX_SPACING); + local_irq_restore(flags); + return 0; +} +EXPORT_SYMBOL(gpio_direction_input); + +int gpio_direction_output(unsigned gpio, int value) +{ + unsigned long flags; + u32 val; + + if (gpio > U300_GPIO_MAX) + return -EINVAL; + + local_irq_save(flags); + val = readl(virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) * + U300_GPIO_PORTX_SPACING); + /* Mask out this pin */ + val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((gpio & 0x07) << 1)); + /* + * FIXME: configure for push/pull, open drain or open source per pin + * in setup. The current driver will only support push/pull. + */ + val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL + << ((gpio & 0x07) << 1)); + writel(val, virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) * + U300_GPIO_PORTX_SPACING); + gpio_set_value(gpio, value); + local_irq_restore(flags); + return 0; +} +EXPORT_SYMBOL(gpio_direction_output); + +/* + * Enable an IRQ, edge is rising edge (!= 0) or falling edge (==0). + */ +void enable_irq_on_gpio_pin(unsigned gpio, int edge) +{ + u32 val; + unsigned long flags; + local_irq_save(flags); + + val = readl(virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) * + U300_GPIO_PORTX_SPACING); + val |= (1 << (gpio & 0x07)); + writel(val, virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) * + U300_GPIO_PORTX_SPACING); + val = readl(virtbase + U300_GPIO_PXICR + PIN_TO_PORT(gpio) * + U300_GPIO_PORTX_SPACING); + if (edge) + val |= (1 << (gpio & 0x07)); + else + val &= ~(1 << (gpio & 0x07)); + writel(val, virtbase + U300_GPIO_PXICR + PIN_TO_PORT(gpio) * + U300_GPIO_PORTX_SPACING); + local_irq_restore(flags); +} +EXPORT_SYMBOL(enable_irq_on_gpio_pin); + +void disable_irq_on_gpio_pin(unsigned gpio) +{ + u32 val; + unsigned long flags; + + local_irq_save(flags); + val = readl(virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) * + U300_GPIO_PORTX_SPACING); + val &= ~(1 << (gpio & 0x07)); + writel(val, virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) * + U300_GPIO_PORTX_SPACING); + local_irq_restore(flags); +} +EXPORT_SYMBOL(disable_irq_on_gpio_pin); + +/* Enable (value == 0) or disable (value == 1) internal pullup */ +void gpio_pullup(unsigned gpio, int value) +{ + u32 val; + unsigned long flags; + + local_irq_save(flags); + if (value) { + val = readl(virtbase + U300_GPIO_PXPER + PIN_TO_PORT(gpio) * + U300_GPIO_PORTX_SPACING); + writel(val | (1 << (gpio & 0x07)), virtbase + U300_GPIO_PXPER + + PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING); + } else { + val = readl(virtbase + U300_GPIO_PXPER + PIN_TO_PORT(gpio) * + U300_GPIO_PORTX_SPACING); + writel(val & ~(1 << (gpio & 0x07)), virtbase + U300_GPIO_PXPER + + PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING); + } + local_irq_restore(flags); +} +EXPORT_SYMBOL(gpio_pullup); + +static irqreturn_t gpio_irq_handler(int irq, void *dev_id) +{ + struct u300_gpio_port *port = dev_id; + u32 val; + int pin; + + /* Read event register */ + val = readl(virtbase + U300_GPIO_PXIEV + port->number * + U300_GPIO_PORTX_SPACING); + /* Mask with enable register */ + val &= readl(virtbase + U300_GPIO_PXIEV + port->number * + U300_GPIO_PORTX_SPACING); + /* Mask relevant bits */ + val &= U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK; + /* ACK IRQ (clear event) */ + writel(val, virtbase + U300_GPIO_PXIEV + port->number * + U300_GPIO_PORTX_SPACING); + /* Print message */ + while (val != 0) { + unsigned gpio; + + pin = __ffs(val); + /* mask off this pin */ + val &= ~(1 << pin); + gpio = (port->number << 3) + pin; + + if (gpio_pin[gpio].callback) + (void)gpio_pin[gpio].callback(gpio_pin[gpio].data); + else + printk(KERN_DEBUG "GPIO: Stray GPIO IRQ on line %d\n", + gpio); + } + return IRQ_HANDLED; +} + +static void gpio_set_initial_values(void) +{ +#ifdef U300_COH901571_3 + int i, j; + unsigned long flags; + u32 val; + + /* Write default values to all pins */ + for (i = 0; i < U300_GPIO_NUM_PORTS; i++) { + val = 0; + for (j = 0; j < 8; j++) + val |= (u32) (u300_gpio_config[i][j].default_output_value != DEFAULT_OUTPUT_LOW) << j; + local_irq_save(flags); + writel(val, virtbase + U300_GPIO_PXPDOR + i * U300_GPIO_PORTX_SPACING); + local_irq_restore(flags); + } + + /* + * Put all pins that are set to either 'GPIO_OUT' or 'GPIO_NOT_USED' + * to output and 'GPIO_IN' to input for each port. And initalize + * default value on outputs. + */ + for (i = 0; i < U300_GPIO_NUM_PORTS; i++) { + for (j = 0; j < U300_GPIO_PINS_PER_PORT; j++) { + local_irq_save(flags); + val = readl(virtbase + U300_GPIO_PXPCR + + i * U300_GPIO_PORTX_SPACING); + /* Mask out this pin */ + val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << (j << 1)); + + if (u300_gpio_config[i][j].pin_usage != GPIO_IN) + val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL << (j << 1)); + writel(val, virtbase + U300_GPIO_PXPCR + + i * U300_GPIO_PORTX_SPACING); + local_irq_restore(flags); + } + } + + /* Enable or disable the internal pull-ups in the GPIO ASIC block */ + for (i = 0; i < U300_GPIO_MAX; i++) { + val = 0; + for (j = 0; j < 8; j++) + val |= (u32)((u300_gpio_config[i][j].pull_up == DISABLE_PULL_UP)) << j; + local_irq_save(flags); + writel(val, virtbase + U300_GPIO_PXPER + i * U300_GPIO_PORTX_SPACING); + local_irq_restore(flags); + } +#endif +} + +static int __devinit gpio_probe(struct platform_device *pdev) +{ + u32 val; + int err = 0; + int i; + int num_irqs; + + memset(gpio_pin, 0, sizeof(gpio_pin)); + + /* Get GPIO clock */ + clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(clk)) { + err = PTR_ERR(clk); + printk(KERN_ERR "GPIO: could not get GPIO clock\n"); + goto err_no_clk; + } + err = clk_enable(clk); + if (err) { + printk(KERN_ERR "GPIO: could not enable GPIO clock\n"); + goto err_no_clk_enable; + } + + memres = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!memres) + goto err_no_resource; + + if (request_mem_region(memres->start, memres->end - memres->start, "GPIO Controller") + == NULL) { + err = -ENODEV; + goto err_no_ioregion; + } + + virtbase = ioremap(memres->start, memres->end - memres->start + 1); + if (!virtbase) { + err = -ENOMEM; + goto err_no_ioremap; + } + +#ifdef U300_COH901335 + printk(KERN_INFO "GPIO: Initializing GPIO Controller COH 901 335\n"); + /* Turn on the GPIO block */ + writel(U300_GPIO_CR_BLOCK_CLOCK_ENABLE, virtbase + U300_GPIO_CR); +#endif + +#ifdef U300_COH901571_3 + printk(KERN_INFO "GPIO: Initializing GPIO Controller COH 901 571/3\n"); + val = readl(virtbase + U300_GPIO_CR); + printk(KERN_INFO "GPIO: COH901571/3 block version: %d, " \ + "number of cores: %d\n", + ((val & 0x0000FE00) >> 9), + ((val & 0x000001FC) >> 2)); + writel(U300_GPIO_CR_BLOCK_CLKRQ_ENABLE, virtbase + U300_GPIO_CR); +#endif + + /* Set up some padmuxing here */ +#ifdef CONFIG_MMC + pmx_set_mission_mode_mmc(); +#endif +#ifdef CONFIG_SPI_PL022 + pmx_set_mission_mode_spi(); +#endif + + gpio_set_initial_values(); + + for (num_irqs = 0 ; num_irqs < U300_GPIO_NUM_PORTS; num_irqs++) { + + gpio_ports[num_irqs].irq = + platform_get_irq_byname(pdev, + gpio_ports[num_irqs].name); + + err = request_irq(gpio_ports[num_irqs].irq, + gpio_irq_handler, IRQF_DISABLED, + gpio_ports[num_irqs].name, + &gpio_ports[num_irqs]); + if (err) { + printk(KERN_CRIT "GPIO: Cannot allocate IRQ for %s!\n", + gpio_ports[num_irqs].name); + goto err_no_irq; + } + /* Turns off PortX_irq_force */ + writel(0x0, virtbase + U300_GPIO_PXIFR + + num_irqs * U300_GPIO_PORTX_SPACING); + } + printk(KERN_INFO "GPIO: U300 gpio module loaded\n"); + + return 0; + + err_no_irq: + for (i = 0; i < num_irqs; i++) + free_irq(gpio_ports[i].irq, &gpio_ports[i]); + iounmap(virtbase); + err_no_ioremap: + release_mem_region(memres->start, memres->end - memres->start); + err_no_ioregion: + err_no_resource: + clk_disable(clk); + err_no_clk_enable: + clk_put(clk); + err_no_clk: + printk(KERN_INFO "GPIO: module ERROR:%d\n", err); + return err; +} + +static int __devexit gpio_remove(struct platform_device *pdev) +{ + int i; + + /* Turn off the GPIO block */ + writel(0x00000000U, virtbase + U300_GPIO_CR); + for (i = 0 ; i < U300_GPIO_NUM_PORTS; i++) + free_irq(gpio_ports[i].irq, &gpio_ports[i]); + iounmap(virtbase); + release_mem_region(memres->start, memres->end - memres->start); + clk_disable(clk); + clk_put(clk); + return 0; +} + +static struct platform_driver gpio_driver = { + .driver = { + .name = "u300-gpio", + }, + .probe = gpio_probe, + .remove = __devexit_p(gpio_remove), +}; + + +static int __init u300_gpio_init(void) +{ + return platform_driver_register(&gpio_driver); +} + +static void __exit u300_gpio_exit(void) +{ + platform_driver_unregister(&gpio_driver); +} + +arch_initcall(u300_gpio_init); +module_exit(u300_gpio_exit); + +MODULE_AUTHOR("Linus Walleij "); + +#ifdef U300_COH901571_3 +MODULE_DESCRIPTION("ST-Ericsson AB COH 901 571/3 GPIO driver"); +#endif + +#ifdef U300_COH901335 +MODULE_DESCRIPTION("ST-Ericsson AB COH 901 335 GPIO driver"); +#endif + +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-u300/include/mach/gpio.h b/arch/arm/mach-u300/include/mach/gpio.h new file mode 100644 index 00000000000..c8174128d7e --- /dev/null +++ b/arch/arm/mach-u300/include/mach/gpio.h @@ -0,0 +1,290 @@ +/* + * + * arch/arm/mach-u300/include/mach/gpio.h + * + * + * Copyright (C) 2007-2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * GPIO block resgister definitions and inline macros for + * U300 GPIO COH 901 335 or COH 901 571/3 + * Author: Linus Walleij + */ + +#ifndef __MACH_U300_GPIO_H +#define __MACH_U300_GPIO_H + +#include +#include +#include +#include + +/* Switch type depending on platform/chip variant */ +#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330) +#define U300_COH901335 +#endif +#if defined(CONFIG_MACH_U300_BS365) || defined(CONFIG_MACH_U300_BS335) +#define U300_COH901571_3 +#endif + +/* Get base address for regs here */ +#include "u300-regs.h" +/* IRQ numbers */ +#include "irqs.h" + +/* + * This is the GPIO block definitions. GPIO (General Purpose I/O) can be + * used for anything, and often is. The event/enable etc figures are for + * the lowermost pin (pin 0 on each port), shift this left to match your + * pin if you're gonna use these values. + */ +#ifdef U300_COH901335 +#define U300_GPIO_PORTX_SPACING (0x1C) +/* Port X Pin Data Register 32bit, this is both input and output (R/W) */ +#define U300_GPIO_PXPDIR (0x00) +#define U300_GPIO_PXPDOR (0x00) +/* Port X Pin Config Register 32bit (R/W) */ +#define U300_GPIO_PXPCR (0x04) +#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK (0x0000FFFFUL) +#define U300_GPIO_PXPCR_PIN_MODE_MASK (0x00000003UL) +#define U300_GPIO_PXPCR_PIN_MODE_SHIFT (0x00000002UL) +#define U300_GPIO_PXPCR_PIN_MODE_INPUT (0x00000000UL) +#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL (0x00000001UL) +#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN (0x00000002UL) +#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE (0x00000003UL) +/* Port X Interrupt Event Register 32bit (R/W) */ +#define U300_GPIO_PXIEV (0x08) +#define U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK (0x000000FFUL) +#define U300_GPIO_PXIEV_IRQ_EVENT (0x00000001UL) +/* Port X Interrupt Enable Register 32bit (R/W) */ +#define U300_GPIO_PXIEN (0x0C) +#define U300_GPIO_PXIEN_ALL_IRQ_ENABLE_MASK (0x000000FFUL) +#define U300_GPIO_PXIEN_IRQ_ENABLE (0x00000001UL) +/* Port X Interrupt Force Register 32bit (R/W) */ +#define U300_GPIO_PXIFR (0x10) +#define U300_GPIO_PXIFR_ALL_IRQ_FORCE_MASK (0x000000FFUL) +#define U300_GPIO_PXIFR_IRQ_FORCE (0x00000001UL) +/* Port X Interrupt Config Register 32bit (R/W) */ +#define U300_GPIO_PXICR (0x14) +#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK (0x000000FFUL) +#define U300_GPIO_PXICR_IRQ_CONFIG_MASK (0x00000001UL) +#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE (0x00000000UL) +#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE (0x00000001UL) +/* Port X Pull-up Enable Register 32bit (R/W) */ +#define U300_GPIO_PXPER (0x18) +#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK (0x000000FFUL) +#define U300_GPIO_PXPER_PULL_UP_DISABLE (0x00000001UL) +/* Control Register 32bit (R/W) */ +#define U300_GPIO_CR (0x54) +#define U300_GPIO_CR_BLOCK_CLOCK_ENABLE (0x00000001UL) +/* three ports of 8 bits each = GPIO pins 0..23 */ +#define U300_GPIO_NUM_PORTS 3 +#define U300_GPIO_PINS_PER_PORT 8 +#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS - 1) +#endif + +#ifdef U300_COH901571_3 +/* + * Control Register 32bit (R/W) + * bit 15-9 (mask 0x0000FE00) contains the number of cores. 8*cores + * gives the number of GPIO pins. + * bit 8-2 (mask 0x000001FC) contains the core version ID. + */ +#define U300_GPIO_CR (0x00) +#define U300_GPIO_CR_SYNC_SEL_ENABLE (0x00000002UL) +#define U300_GPIO_CR_BLOCK_CLKRQ_ENABLE (0x00000001UL) +#define U300_GPIO_PORTX_SPACING (0x30) +/* Port X Pin Data INPUT Register 32bit (R/W) */ +#define U300_GPIO_PXPDIR (0x04) +/* Port X Pin Data OUTPUT Register 32bit (R/W) */ +#define U300_GPIO_PXPDOR (0x08) +/* Port X Pin Config Register 32bit (R/W) */ +#define U300_GPIO_PXPCR (0x0C) +#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK (0x0000FFFFUL) +#define U300_GPIO_PXPCR_PIN_MODE_MASK (0x00000003UL) +#define U300_GPIO_PXPCR_PIN_MODE_SHIFT (0x00000002UL) +#define U300_GPIO_PXPCR_PIN_MODE_INPUT (0x00000000UL) +#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL (0x00000001UL) +#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN (0x00000002UL) +#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE (0x00000003UL) +/* Port X Pull-up Enable Register 32bit (R/W) */ +#define U300_GPIO_PXPER (0x10) +#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK (0x000000FFUL) +#define U300_GPIO_PXPER_PULL_UP_DISABLE (0x00000001UL) +/* Port X Interrupt Event Register 32bit (R/W) */ +#define U300_GPIO_PXIEV (0x14) +#define U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK (0x000000FFUL) +#define U300_GPIO_PXIEV_IRQ_EVENT (0x00000001UL) +/* Port X Interrupt Enable Register 32bit (R/W) */ +#define U300_GPIO_PXIEN (0x18) +#define U300_GPIO_PXIEN_ALL_IRQ_ENABLE_MASK (0x000000FFUL) +#define U300_GPIO_PXIEN_IRQ_ENABLE (0x00000001UL) +/* Port X Interrupt Force Register 32bit (R/W) */ +#define U300_GPIO_PXIFR (0x1C) +#define U300_GPIO_PXIFR_ALL_IRQ_FORCE_MASK (0x000000FFUL) +#define U300_GPIO_PXIFR_IRQ_FORCE (0x00000001UL) +/* Port X Interrupt Config Register 32bit (R/W) */ +#define U300_GPIO_PXICR (0x20) +#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK (0x000000FFUL) +#define U300_GPIO_PXICR_IRQ_CONFIG_MASK (0x00000001UL) +#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE (0x00000000UL) +#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE (0x00000001UL) +#ifdef CONFIG_MACH_U300_BS335 +/* seven ports of 8 bits each = GPIO pins 0..55 */ +#define U300_GPIO_NUM_PORTS 7 +#else +/* five ports of 8 bits each = GPIO pins 0..39 */ +#define U300_GPIO_NUM_PORTS 5 +#endif +#define U300_GPIO_PINS_PER_PORT 8 +#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS - 1) +#endif + +/* + * Individual pin assignments for the B26/S26. Notice that the + * actual usage of these pins depends on the PAD MUX settings, that + * is why the same number can potentially appear several times. + * In the reference design each pin is only used for one purpose. + * These were determined by inspecting the B26/S26 schematic: + * 2/1911-ROA 128 1603 + */ +#ifdef CONFIG_MACH_U300_BS2X +#define U300_GPIO_PIN_UART_RX 0 +#define U300_GPIO_PIN_UART_TX 1 +#define U300_GPIO_PIN_GPIO02 2 /* Unrouted */ +#define U300_GPIO_PIN_GPIO03 3 /* Unrouted */ +#define U300_GPIO_PIN_CAM_SLEEP 4 +#define U300_GPIO_PIN_CAM_REG_EN 5 +#define U300_GPIO_PIN_GPIO06 6 /* Unrouted */ +#define U300_GPIO_PIN_GPIO07 7 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO08 8 /* Service point SP2321 */ +#define U300_GPIO_PIN_GPIO09 9 /* Service point SP2322 */ +#define U300_GPIO_PIN_PHFSENSE 10 /* Headphone jack sensing */ +#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */ +#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */ +#define U300_GPIO_PIN_FLIPSENSE 13 /* Mechanical flip sensing */ +#define U300_GPIO_PIN_GPIO14 14 /* DSP JTAG Port RTCK */ +#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO16 16 /* Unrouted */ +#define U300_GPIO_PIN_GPIO17 17 /* Unrouted */ +#define U300_GPIO_PIN_GPIO18 18 /* Unrouted */ +#define U300_GPIO_PIN_GPIO19 19 /* Unrouted */ +#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */ +#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */ +#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */ +#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */ +#endif + +/* + * Individual pin assignments for the B330/S330 and B365/S365. + * Notice that the actual usage of these pins depends on the + * PAD MUX settings, that is why the same number can potentially + * appear several times. In the reference design each pin is only + * used for one purpose. These were determined by inspecting the + * S365 schematic. + */ +#if defined(CONFIG_MACH_U300_BS330) || defined(CONFIG_MACH_U300_BS365) || \ + defined(CONFIG_MACH_U300_BS335) +#define U300_GPIO_PIN_UART_RX 0 +#define U300_GPIO_PIN_UART_TX 1 +#define U300_GPIO_PIN_UART_CTS 2 +#define U300_GPIO_PIN_UART_RTS 3 +#define U300_GPIO_PIN_CAM_MAIN_STANDBY 4 /* Camera MAIN standby */ +#define U300_GPIO_PIN_GPIO05 5 /* Unrouted */ +#define U300_GPIO_PIN_MS_CD 6 /* Memory Stick Card insertion */ +#define U300_GPIO_PIN_GPIO07 7 /* Test point TP2430 */ + +#define U300_GPIO_PIN_GPIO08 8 /* Test point TP2437 */ +#define U300_GPIO_PIN_GPIO09 9 /* Test point TP2431 */ +#define U300_GPIO_PIN_GPIO10 10 /* Test point TP2432 */ +#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */ +#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */ +#define U300_GPIO_PIN_CAM_SUB_STANDBY 13 /* Camera SUB standby */ +#define U300_GPIO_PIN_GPIO14 14 /* Test point TP2436 */ +#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO16 16 /* Test point TP2438 */ +#define U300_GPIO_PIN_PHFSENSE 17 /* Headphone jack sensing */ +#define U300_GPIO_PIN_GPIO18 18 /* Test point TP2439 */ +#define U300_GPIO_PIN_GPIO19 19 /* Routed somewhere */ +#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */ +#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */ +#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */ +#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO24 24 /* Unrouted */ +#define U300_GPIO_PIN_GPIO25 25 /* Unrouted */ +#define U300_GPIO_PIN_GPIO26 26 /* Unrouted */ +#define U300_GPIO_PIN_GPIO27 27 /* Unrouted */ +#define U300_GPIO_PIN_GPIO28 28 /* Unrouted */ +#define U300_GPIO_PIN_GPIO29 29 /* Unrouted */ +#define U300_GPIO_PIN_GPIO30 30 /* Unrouted */ +#define U300_GPIO_PIN_GPIO31 31 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO32 32 /* Unrouted */ +#define U300_GPIO_PIN_GPIO33 33 /* Unrouted */ +#define U300_GPIO_PIN_GPIO34 34 /* Unrouted */ +#define U300_GPIO_PIN_GPIO35 35 /* Unrouted */ +#define U300_GPIO_PIN_GPIO36 36 /* Unrouted */ +#define U300_GPIO_PIN_GPIO37 37 /* Unrouted */ +#define U300_GPIO_PIN_GPIO38 38 /* Unrouted */ +#define U300_GPIO_PIN_GPIO39 39 /* Unrouted */ + +#ifdef CONFIG_MACH_U300_BS335 + +#define U300_GPIO_PIN_GPIO40 40 /* Unrouted */ +#define U300_GPIO_PIN_GPIO41 41 /* Unrouted */ +#define U300_GPIO_PIN_GPIO42 42 /* Unrouted */ +#define U300_GPIO_PIN_GPIO43 43 /* Unrouted */ +#define U300_GPIO_PIN_GPIO44 44 /* Unrouted */ +#define U300_GPIO_PIN_GPIO45 45 /* Unrouted */ +#define U300_GPIO_PIN_GPIO46 46 /* Unrouted */ +#define U300_GPIO_PIN_GPIO47 47 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO48 48 /* Unrouted */ +#define U300_GPIO_PIN_GPIO49 49 /* Unrouted */ +#define U300_GPIO_PIN_GPIO50 50 /* Unrouted */ +#define U300_GPIO_PIN_GPIO51 51 /* Unrouted */ +#define U300_GPIO_PIN_GPIO52 52 /* Unrouted */ +#define U300_GPIO_PIN_GPIO53 53 /* Unrouted */ +#define U300_GPIO_PIN_GPIO54 54 /* Unrouted */ +#define U300_GPIO_PIN_GPIO55 55 /* Unrouted */ +#endif + +#endif + +/* translates a pin number to a port number */ +#define PIN_TO_PORT(val) (val >> 3) + +/* These can be found in arch/arm/mach-u300/gpio.c */ +extern int gpio_request(unsigned gpio, const char *label); +extern void gpio_free(unsigned gpio); +extern int gpio_direction_input(unsigned gpio); +extern int gpio_direction_output(unsigned gpio, int value); +extern int gpio_register_callback(unsigned gpio, + int (*func)(void *arg), + void *); +extern int gpio_unregister_callback(unsigned gpio); +extern void enable_irq_on_gpio_pin(unsigned gpio, int edge); +extern void disable_irq_on_gpio_pin(unsigned gpio); +extern void gpio_pullup(unsigned gpio, int value); +extern int gpio_get_value(unsigned gpio); +extern void gpio_set_value(unsigned gpio, int value); + +/* wrappers to sleep-enable the previous two functions */ +static inline unsigned gpio_to_irq(unsigned gpio) +{ + return PIN_TO_PORT(gpio) + IRQ_U300_GPIO_PORT0; +} + +static inline unsigned irq_to_gpio(unsigned irq) +{ + /* + * FIXME: This is no 1-1 mapping at all, it points to the + * whole block of 8 pins. + */ + return (irq - IRQ_U300_GPIO_PORT0) << 3; +} + +#endif diff --git a/arch/arm/mach-u300/padmux.c b/arch/arm/mach-u300/padmux.c new file mode 100644 index 00000000000..f3664564f08 --- /dev/null +++ b/arch/arm/mach-u300/padmux.c @@ -0,0 +1,58 @@ +/* + * + * arch/arm/mach-u300/padmux.c + * + * + * Copyright (C) 2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * U300 PADMUX functions + * Author: Linus Walleij + * + */ +#include +#include +#include +#include + +#include "padmux.h" + +/* Set the PAD MUX to route the MMC reader correctly to GPIO0. */ +void pmx_set_mission_mode_mmc(void) +{ + u16 val; + + val = readw(U300_SYSCON_VBASE + U300_SYSCON_PMC1LR); + val &= ~U300_SYSCON_PMC1LR_MMCSD_MASK; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_PMC1LR); + val = readw(U300_SYSCON_VBASE + U300_SYSCON_PMC1HR); + val &= ~U300_SYSCON_PMC1HR_APP_GPIO_1_MASK; + val |= U300_SYSCON_PMC1HR_APP_GPIO_1_MMC; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_PMC1HR); +} + +void pmx_set_mission_mode_spi(void) +{ + u16 val; + + /* Set up padmuxing so the SPI port and its chipselects are active */ + val = readw(U300_SYSCON_VBASE + U300_SYSCON_PMC1HR); + /* + * Activate the SPI port (disable the use of these pins for generic + * GPIO, DSP, AAIF + */ + val &= ~U300_SYSCON_PMC1HR_APP_SPI_2_MASK; + val |= U300_SYSCON_PMC1HR_APP_SPI_2_SPI; + /* + * Use GPIO pin SPI CS1 for CS1 actually (it can be used for other + * things also) + */ + val &= ~U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK; + val |= U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI; + /* + * Use GPIO pin SPI CS2 for CS2 actually (it can be used for other + * things also) + */ + val &= ~U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK; + val |= U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_PMC1HR); +} diff --git a/arch/arm/mach-u300/padmux.h b/arch/arm/mach-u300/padmux.h new file mode 100644 index 00000000000..8c2099ac504 --- /dev/null +++ b/arch/arm/mach-u300/padmux.h @@ -0,0 +1,19 @@ +/* + * + * arch/arm/mach-u300/padmux.h + * + * + * Copyright (C) 2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * U300 PADMUX API + * Author: Linus Walleij + * + */ + +#ifndef __MACH_U300_PADMUX_H +#define __MACH_U300_PADMUX_H + +void pmx_set_mission_mode_mmc(void); +void pmx_set_mission_mode_spi(void); + +#endif -- cgit v1.2.3 From cd27e485410aa7e7464b0126d968fe8c2a5c045b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 23 Apr 2009 10:21:30 +0100 Subject: [ARM] 5474/1: U300 clocking framework This adds the clocking framework and hooks into the clkdevice for U300 series platforms. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-u300/clock.c | 1487 ++++++++++++++++++++++++++++++ arch/arm/mach-u300/clock.h | 53 ++ arch/arm/mach-u300/include/mach/clkdev.h | 7 + 3 files changed, 1547 insertions(+) create mode 100644 arch/arm/mach-u300/clock.c create mode 100644 arch/arm/mach-u300/clock.h create mode 100644 arch/arm/mach-u300/include/mach/clkdev.h (limited to 'arch/arm/mach-u300') diff --git a/arch/arm/mach-u300/clock.c b/arch/arm/mach-u300/clock.c new file mode 100644 index 00000000000..d6f8232757f --- /dev/null +++ b/arch/arm/mach-u300/clock.c @@ -0,0 +1,1487 @@ +/* + * + * arch/arm/mach-u300/clock.c + * + * + * Copyright (C) 2007-2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * Define clocks in the app platform. + * Author: Linus Walleij + * Author: Jonas Aaberg + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "clock.h" + +/* + * TODO: + * - move all handling of the CCR register into this file and create + * a spinlock for the CCR register + * - switch to the clkdevice lookup mechanism that maps clocks to + * device ID:s instead when it becomes available in kernel 2.6.29. + * - implement rate get/set for all clocks that need it. + */ + +/* + * Syscon clock I/O registers lock so clock requests don't collide + * NOTE: this is a local lock only used to lock access to clock and + * reset registers in syscon. + */ +static DEFINE_SPINLOCK(syscon_clkreg_lock); +static DEFINE_SPINLOCK(syscon_resetreg_lock); + +/* + * The clocking hierarchy currently looks like this. + * NOTE: the idea is NOT to show how the clocks are routed on the chip! + * The ideas is to show dependencies, so a clock higher up in the + * hierarchy has to be on in order for another clock to be on. Now, + * both CPU and DMA can actually be on top of the hierarchy, and that + * is not modeled currently. Instead we have the backbone AMBA bus on + * top. This bus cannot be programmed in any way but conceptually it + * needs to be active for the bridges and devices to transport data. + * + * Please be aware that a few clocks are hw controlled, which mean that + * the hw itself can turn on/off or change the rate of the clock when + * needed! + * + * AMBA bus + * | + * +- CPU + * +- NANDIF NAND Flash interface + * +- SEMI Shared Memory interface + * +- ISP Image Signal Processor (U335 only) + * +- CDS (U335 only) + * +- DMA Direct Memory Access Controller + * +- AAIF APP/ACC Inteface (Mobile Scalable Link, MSL) + * +- APEX + * +- VIDEO_ENC AVE2/3 Video Encoder + * +- XGAM Graphics Accelerator Controller + * +- AHB + * | + * +- ahb:0 AHB Bridge + * | | + * | +- ahb:1 INTCON Interrupt controller + * | +- ahb:3 MSPRO Memory Stick Pro controller + * | +- ahb:4 EMIF External Memory interface + * | + * +- fast:0 FAST bridge + * | | + * | +- fast:1 MMCSD MMC/SD card reader controller + * | +- fast:2 I2S0 PCM I2S channel 0 controller + * | +- fast:3 I2S1 PCM I2S channel 1 controller + * | +- fast:4 I2C0 I2C channel 0 controller + * | +- fast:5 I2C1 I2C channel 1 controller + * | +- fast:6 SPI SPI controller + * | +- fast:7 UART1 Secondary UART (U335 only) + * | + * +- slow:0 SLOW bridge + * | + * +- slow:1 SYSCON (not possible to control) + * +- slow:2 WDOG Watchdog + * +- slow:3 UART0 primary UART + * +- slow:4 TIMER_APP Application timer - used in Linux + * +- slow:5 KEYPAD controller + * +- slow:6 GPIO controller + * +- slow:7 RTC controller + * +- slow:8 BT Bus Tracer (not used currently) + * +- slow:9 EH Event Handler (not used currently) + * +- slow:a TIMER_ACC Access style timer (not used currently) + * +- slow:b PPM (U335 only, what is that?) + */ + +/* + * Reset control functions. We remember if a block has been + * taken out of reset and don't remove the reset assertion again + * and vice versa. Currently we only remove resets so the + * enablement function is defined out. + */ +static void syscon_block_reset_enable(struct clk *clk) +{ + u16 val; + unsigned long iflags; + + /* Not all blocks support resetting */ + if (!clk->res_reg || !clk->res_mask) + return; + spin_lock_irqsave(&syscon_resetreg_lock, iflags); + val = readw(clk->res_reg); + val |= clk->res_mask; + writew(val, clk->res_reg); + spin_unlock_irqrestore(&syscon_resetreg_lock, iflags); + clk->reset = true; +} + +static void syscon_block_reset_disable(struct clk *clk) +{ + u16 val; + unsigned long iflags; + + /* Not all blocks support resetting */ + if (!clk->res_reg || !clk->res_mask) + return; + spin_lock_irqsave(&syscon_resetreg_lock, iflags); + val = readw(clk->res_reg); + val &= ~clk->res_mask; + writew(val, clk->res_reg); + spin_unlock_irqrestore(&syscon_resetreg_lock, iflags); + clk->reset = false; +} + +int __clk_get(struct clk *clk) +{ + u16 val; + + /* The MMC and MSPRO clocks need some special set-up */ + if (!strcmp(clk->name, "MCLK")) { + /* Set default MMC clock divisor to 18.9 MHz */ + writew(0x0054U, U300_SYSCON_VBASE + U300_SYSCON_MMF0R); + val = readw(U300_SYSCON_VBASE + U300_SYSCON_MMCR); + /* Disable the MMC feedback clock */ + val &= ~U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE; + /* Disable MSPRO frequency */ + val &= ~U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_MMCR); + } + if (!strcmp(clk->name, "MSPRO")) { + val = readw(U300_SYSCON_VBASE + U300_SYSCON_MMCR); + /* Disable the MMC feedback clock */ + val &= ~U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE; + /* Enable MSPRO frequency */ + val |= U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_MMCR); + } + return 1; +} +EXPORT_SYMBOL(__clk_get); + +void __clk_put(struct clk *clk) +{ +} +EXPORT_SYMBOL(__clk_put); + +static void syscon_clk_disable(struct clk *clk) +{ + unsigned long iflags; + + /* Don't touch the hardware controlled clocks */ + if (clk->hw_ctrld) + return; + + spin_lock_irqsave(&syscon_clkreg_lock, iflags); + writew(clk->clk_val, U300_SYSCON_VBASE + U300_SYSCON_SBCDR); + spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); +} + +static void syscon_clk_enable(struct clk *clk) +{ + unsigned long iflags; + + /* Don't touch the hardware controlled clocks */ + if (clk->hw_ctrld) + return; + + spin_lock_irqsave(&syscon_clkreg_lock, iflags); + writew(clk->clk_val, U300_SYSCON_VBASE + U300_SYSCON_SBCER); + spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); +} + +static u16 syscon_clk_get_rate(void) +{ + u16 val; + unsigned long iflags; + + spin_lock_irqsave(&syscon_clkreg_lock, iflags); + val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); + val &= U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK; + spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); + return val; +} + +#ifdef CONFIG_MACH_U300_USE_I2S_AS_MASTER +static void enable_i2s0_vcxo(void) +{ + u16 val; + unsigned long iflags; + + spin_lock_irqsave(&syscon_clkreg_lock, iflags); + /* Set I2S0 to use the VCXO 26 MHz clock */ + val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); + val |= U300_SYSCON_CCR_TURN_VCXO_ON; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); + val |= U300_SYSCON_CCR_I2S0_USE_VCXO; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); + val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR); + val |= U300_SYSCON_CEFR_I2S0_CLK_EN; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR); + spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); +} + +static void enable_i2s1_vcxo(void) +{ + u16 val; + unsigned long iflags; + + spin_lock_irqsave(&syscon_clkreg_lock, iflags); + /* Set I2S1 to use the VCXO 26 MHz clock */ + val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); + val |= U300_SYSCON_CCR_TURN_VCXO_ON; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); + val |= U300_SYSCON_CCR_I2S1_USE_VCXO; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); + val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR); + val |= U300_SYSCON_CEFR_I2S1_CLK_EN; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR); + spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); +} + +static void disable_i2s0_vcxo(void) +{ + u16 val; + unsigned long iflags; + + spin_lock_irqsave(&syscon_clkreg_lock, iflags); + /* Disable I2S0 use of the VCXO 26 MHz clock */ + val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); + val &= ~U300_SYSCON_CCR_I2S0_USE_VCXO; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); + /* Deactivate VCXO if noone else is using VCXO */ + if (!(val & U300_SYSCON_CCR_I2S1_USE_VCXO)) + val &= ~U300_SYSCON_CCR_TURN_VCXO_ON; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); + val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR); + val &= ~U300_SYSCON_CEFR_I2S0_CLK_EN; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR); + spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); +} + +static void disable_i2s1_vcxo(void) +{ + u16 val; + unsigned long iflags; + + spin_lock_irqsave(&syscon_clkreg_lock, iflags); + /* Disable I2S1 use of the VCXO 26 MHz clock */ + val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); + val &= ~U300_SYSCON_CCR_I2S1_USE_VCXO; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); + /* Deactivate VCXO if noone else is using VCXO */ + if (!(val & U300_SYSCON_CCR_I2S0_USE_VCXO)) + val &= ~U300_SYSCON_CCR_TURN_VCXO_ON; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); + val = readw(U300_SYSCON_VBASE + U300_SYSCON_CEFR); + val &= ~U300_SYSCON_CEFR_I2S0_CLK_EN; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_CEFR); + spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); +} +#endif /* CONFIG_MACH_U300_USE_I2S_AS_MASTER */ + + +static void syscon_clk_rate_set_mclk(unsigned long rate) +{ + u16 val; + u32 reg; + unsigned long iflags; + + switch (rate) { + case 18900000: + val = 0x0054; + break; + case 20800000: + val = 0x0044; + break; + case 23100000: + val = 0x0043; + break; + case 26000000: + val = 0x0033; + break; + case 29700000: + val = 0x0032; + break; + case 34700000: + val = 0x0022; + break; + case 41600000: + val = 0x0021; + break; + case 52000000: + val = 0x0011; + break; + case 104000000: + val = 0x0000; + break; + default: + printk(KERN_ERR "Trying to set MCLK to unknown speed! %ld\n", + rate); + return; + } + + spin_lock_irqsave(&syscon_clkreg_lock, iflags); + reg = readw(U300_SYSCON_VBASE + U300_SYSCON_MMF0R) & + ~U300_SYSCON_MMF0R_MASK; + writew(reg | val, U300_SYSCON_VBASE + U300_SYSCON_MMF0R); + spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); +} + +void syscon_clk_rate_set_cpuclk(unsigned long rate) +{ + u16 val; + unsigned long iflags; + + switch (rate) { + case 13000000: + val = U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER; + break; + case 52000000: + val = U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE; + break; + case 104000000: + val = U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH; + break; + case 208000000: + val = U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST; + break; + default: + return; + } + spin_lock_irqsave(&syscon_clkreg_lock, iflags); + val |= readw(U300_SYSCON_VBASE + U300_SYSCON_CCR) & + ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK ; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); + spin_unlock_irqrestore(&syscon_clkreg_lock, iflags); +} +EXPORT_SYMBOL(syscon_clk_rate_set_cpuclk); + +void clk_disable(struct clk *clk) +{ + unsigned long iflags; + + spin_lock_irqsave(&clk->lock, iflags); + if (clk->usecount > 0 && !(--clk->usecount)) { + /* some blocks lack clocking registers and cannot be disabled */ + if (clk->disable) + clk->disable(clk); + if (likely((u32)clk->parent)) + clk_disable(clk->parent); + } +#ifdef CONFIG_MACH_U300_USE_I2S_AS_MASTER + if (unlikely(!strcmp(clk->name, "I2S0"))) + disable_i2s0_vcxo(); + if (unlikely(!strcmp(clk->name, "I2S1"))) + disable_i2s1_vcxo(); +#endif + spin_unlock_irqrestore(&clk->lock, iflags); +} +EXPORT_SYMBOL(clk_disable); + +int clk_enable(struct clk *clk) +{ + int ret = 0; + unsigned long iflags; + + spin_lock_irqsave(&clk->lock, iflags); + if (clk->usecount++ == 0) { + if (likely((u32)clk->parent)) + ret = clk_enable(clk->parent); + + if (unlikely(ret != 0)) + clk->usecount--; + else { + /* remove reset line (we never enable reset again) */ + syscon_block_reset_disable(clk); + /* clocks without enable function are always on */ + if (clk->enable) + clk->enable(clk); +#ifdef CONFIG_MACH_U300_USE_I2S_AS_MASTER + if (unlikely(!strcmp(clk->name, "I2S0"))) + enable_i2s0_vcxo(); + if (unlikely(!strcmp(clk->name, "I2S1"))) + enable_i2s1_vcxo(); +#endif + } + } + spin_unlock_irqrestore(&clk->lock, iflags); + return ret; + +} +EXPORT_SYMBOL(clk_enable); + +/* Returns the clock rate in Hz */ +static unsigned long clk_get_rate_cpuclk(struct clk *clk) +{ + u16 val; + + val = syscon_clk_get_rate(); + + switch (val) { + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: + return 13000000; + case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: + return 52000000; + case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: + return 104000000; + case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST: + return 208000000; + default: + break; + } + return clk->rate; +} + +static unsigned long clk_get_rate_ahb_clk(struct clk *clk) +{ + u16 val; + + val = syscon_clk_get_rate(); + + switch (val) { + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: + return 6500000; + case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: + return 26000000; + case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: + case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST: + return 52000000; + default: + break; + } + return clk->rate; + +} + +static unsigned long clk_get_rate_emif_clk(struct clk *clk) +{ + u16 val; + + val = syscon_clk_get_rate(); + + switch (val) { + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: + return 13000000; + case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: + return 52000000; + case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: + case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST: + return 104000000; + default: + break; + } + return clk->rate; + +} + +static unsigned long clk_get_rate_xgamclk(struct clk *clk) +{ + u16 val; + + val = syscon_clk_get_rate(); + + switch (val) { + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: + return 6500000; + case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: + return 26000000; + case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: + case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST: + return 52000000; + default: + break; + } + + return clk->rate; +} + +static unsigned long clk_get_rate_mclk(struct clk *clk) +{ + u16 val; + + val = syscon_clk_get_rate(); + + switch (val) { + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: + /* + * Here, the 208 MHz PLL gets shut down and the always + * on 13 MHz PLL used for RTC etc kicks into use + * instead. + */ + return 13000000; + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: + case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: + case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: + case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST: + { + /* + * This clock is under program control. The register is + * divided in two nybbles, bit 7-4 gives cycles-1 to count + * high, bit 3-0 gives cycles-1 to count low. Distribute + * these with no more than 1 cycle difference between + * low and high and add low and high to get the actual + * divisor. The base PLL is 208 MHz. Writing 0x00 will + * divide by 1 and 1 so the highest frequency possible + * is 104 MHz. + * + * e.g. 0x54 => + * f = 208 / ((5+1) + (4+1)) = 208 / 11 = 18.9 MHz + */ + u16 val = readw(U300_SYSCON_VBASE + U300_SYSCON_MMF0R) & + U300_SYSCON_MMF0R_MASK; + switch (val) { + case 0x0054: + return 18900000; + case 0x0044: + return 20800000; + case 0x0043: + return 23100000; + case 0x0033: + return 26000000; + case 0x0032: + return 29700000; + case 0x0022: + return 34700000; + case 0x0021: + return 41600000; + case 0x0011: + return 52000000; + case 0x0000: + return 104000000; + default: + break; + } + } + default: + break; + } + + return clk->rate; +} + +static unsigned long clk_get_rate_i2s_i2c_spi(struct clk *clk) +{ + u16 val; + + val = syscon_clk_get_rate(); + + switch (val) { + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: + case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: + return 13000000; + case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: + case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: + case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST: + return 26000000; + default: + break; + } + + return clk->rate; +} + +unsigned long clk_get_rate(struct clk *clk) +{ + if (clk->get_rate) + return clk->get_rate(clk); + else + return clk->rate; +} +EXPORT_SYMBOL(clk_get_rate); + +static unsigned long clk_round_rate_mclk(struct clk *clk, unsigned long rate) +{ + if (rate >= 18900000) + return 18900000; + if (rate >= 20800000) + return 20800000; + if (rate >= 23100000) + return 23100000; + if (rate >= 26000000) + return 26000000; + if (rate >= 29700000) + return 29700000; + if (rate >= 34700000) + return 34700000; + if (rate >= 41600000) + return 41600000; + if (rate >= 52000000) + return 52000000; + return -EINVAL; +} + +static unsigned long clk_round_rate_cpuclk(struct clk *clk, unsigned long rate) +{ + if (rate >= 13000000) + return 13000000; + if (rate >= 52000000) + return 52000000; + if (rate >= 104000000) + return 104000000; + if (rate >= 208000000) + return 208000000; + return -EINVAL; +} + +/* + * This adjusts a requested rate to the closest exact rate + * a certain clock can provide. For a fixed clock it's + * mostly clk->rate. + */ +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + /* TODO: get apropriate switches for EMIFCLK, AHBCLK and MCLK */ + /* Else default to fixed value */ + + if (clk->round_rate) { + return (long) clk->round_rate(clk, rate); + } else { + printk(KERN_ERR "clock: Failed to round rate of %s\n", + clk->name); + } + return (long) clk->rate; +} +EXPORT_SYMBOL(clk_round_rate); + +static int clk_set_rate_mclk(struct clk *clk, unsigned long rate) +{ + syscon_clk_rate_set_mclk(clk_round_rate(clk, rate)); + return 0; +} + +static int clk_set_rate_cpuclk(struct clk *clk, unsigned long rate) +{ + syscon_clk_rate_set_cpuclk(clk_round_rate(clk, rate)); + return 0; +} + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + /* TODO: set for EMIFCLK and AHBCLK */ + /* Else assume the clock is fixed and fail */ + if (clk->set_rate) { + return clk->set_rate(clk, rate); + } else { + printk(KERN_ERR "clock: Failed to set %s to %ld hz\n", + clk->name, rate); + return -1; + } +} +EXPORT_SYMBOL(clk_set_rate); + +/* + * Clock definitions. The clock parents are set to respective + * bridge and the clock framework makes sure that the clocks have + * parents activated and are brought out of reset when in use. + * + * Clocks that have hw_ctrld = true are hw controlled, and the hw + * can by itself turn these clocks on and off. + * So in other words, we don't really have to care about them. + */ + +static struct clk amba_clk = { + .name = "AMBA", + .rate = 52000000, /* this varies! */ + .hw_ctrld = true, + .reset = false, +}; + +/* + * These blocks are connected directly to the AMBA bus + * with no bridge. + */ + +static struct clk cpu_clk = { + .name = "CPU", + .parent = &amba_clk, + .rate = 208000000, /* this varies! */ + .hw_ctrld = true, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, + .res_mask = U300_SYSCON_RRR_CPU_RESET_EN, + .set_rate = clk_set_rate_cpuclk, + .get_rate = clk_get_rate_cpuclk, + .round_rate = clk_round_rate_cpuclk, +}; + +static struct clk nandif_clk = { + .name = "NANDIF", + .parent = &amba_clk, + .hw_ctrld = false, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, + .res_mask = U300_SYSCON_RRR_NANDIF_RESET_EN, + .clk_val = U300_SYSCON_SBCER_NANDIF_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, +}; + +static struct clk semi_clk = { + .name = "SEMI", + .parent = &amba_clk, + .rate = 0, /* FIXME */ + /* It is not possible to reset SEMI */ + .hw_ctrld = false, + .reset = false, + .clk_val = U300_SYSCON_SBCER_SEMI_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, +}; + +#ifdef CONFIG_MACH_U300_BS335 +static struct clk isp_clk = { + .name = "ISP", + .parent = &amba_clk, + .rate = 0, /* FIXME */ + .hw_ctrld = false, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, + .res_mask = U300_SYSCON_RRR_ISP_RESET_EN, + .clk_val = U300_SYSCON_SBCER_ISP_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, +}; + +static struct clk cds_clk = { + .name = "CDS", + .parent = &amba_clk, + .rate = 0, /* FIXME */ + .hw_ctrld = false, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, + .res_mask = U300_SYSCON_RRR_CDS_RESET_EN, + .clk_val = U300_SYSCON_SBCER_CDS_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, +}; +#endif + +static struct clk dma_clk = { + .name = "DMA", + .parent = &amba_clk, + .rate = 52000000, /* this varies! */ + .hw_ctrld = true, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, + .res_mask = U300_SYSCON_RRR_DMAC_RESET_EN, + .clk_val = U300_SYSCON_SBCER_DMAC_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, +}; + +static struct clk aaif_clk = { + .name = "AAIF", + .parent = &amba_clk, + .rate = 52000000, /* this varies! */ + .hw_ctrld = true, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, + .res_mask = U300_SYSCON_RRR_AAIF_RESET_EN, + .clk_val = U300_SYSCON_SBCER_AAIF_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, +}; + +static struct clk apex_clk = { + .name = "APEX", + .parent = &amba_clk, + .rate = 0, /* FIXME */ + .hw_ctrld = true, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, + .res_mask = U300_SYSCON_RRR_APEX_RESET_EN, + .clk_val = U300_SYSCON_SBCER_APEX_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, +}; + +static struct clk video_enc_clk = { + .name = "VIDEO_ENC", + .parent = &amba_clk, + .rate = 208000000, /* this varies! */ + .hw_ctrld = false, + .reset = false, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, + /* This has XGAM in the name but refers to the video encoder */ + .res_mask = U300_SYSCON_RRR_XGAM_VC_SYNC_RESET_EN, + .clk_val = U300_SYSCON_SBCER_VIDEO_ENC_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, +}; + +static struct clk xgam_clk = { + .name = "XGAMCLK", + .parent = &amba_clk, + .rate = 52000000, /* this varies! */ + .hw_ctrld = false, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, + .res_mask = U300_SYSCON_RRR_XGAM_RESET_EN, + .clk_val = U300_SYSCON_SBCER_XGAM_CLK_EN, + .get_rate = clk_get_rate_xgamclk, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, +}; + +/* This clock is used to activate the video encoder */ +static struct clk ahb_clk = { + .name = "AHB", + .parent = &amba_clk, + .rate = 52000000, /* this varies! */ + .hw_ctrld = false, /* This one is set to false due to HW bug */ + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, + .res_mask = U300_SYSCON_RRR_AHB_RESET_EN, + .clk_val = U300_SYSCON_SBCER_AHB_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, + .get_rate = clk_get_rate_ahb_clk, +}; + + +/* + * Clocks on the AHB bridge + */ + +static struct clk ahb_subsys_clk = { + .name = "AHB_SUBSYS", + .parent = &amba_clk, + .rate = 52000000, /* this varies! */ + .hw_ctrld = true, + .reset = false, + .clk_val = U300_SYSCON_SBCER_AHB_SUBSYS_BRIDGE_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, + .get_rate = clk_get_rate_ahb_clk, +}; + +static struct clk intcon_clk = { + .name = "INTCON", + .parent = &ahb_subsys_clk, + .rate = 52000000, /* this varies! */ + .hw_ctrld = false, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, + .res_mask = U300_SYSCON_RRR_INTCON_RESET_EN, + /* INTCON can be reset but not clock-gated */ +}; + +static struct clk mspro_clk = { + .name = "MSPRO", + .parent = &ahb_subsys_clk, + .rate = 0, /* FIXME */ + .hw_ctrld = false, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, + .res_mask = U300_SYSCON_RRR_MSPRO_RESET_EN, + .clk_val = U300_SYSCON_SBCER_MSPRO_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, +}; + +static struct clk emif_clk = { + .name = "EMIF", + .parent = &ahb_subsys_clk, + .rate = 104000000, /* this varies! */ + .hw_ctrld = false, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RRR, + .res_mask = U300_SYSCON_RRR_EMIF_RESET_EN, + .clk_val = U300_SYSCON_SBCER_EMIF_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, + .get_rate = clk_get_rate_emif_clk, +}; + + +/* + * Clocks on the FAST bridge + */ +static struct clk fast_clk = { + .name = "FAST_BRIDGE", + .parent = &amba_clk, + .rate = 13000000, /* this varies! */ + .hw_ctrld = true, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR, + .res_mask = U300_SYSCON_RFR_FAST_BRIDGE_RESET_ENABLE, + .clk_val = U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, +}; + +static struct clk mmcsd_clk = { + .name = "MCLK", + .parent = &fast_clk, + .rate = 18900000, /* this varies! */ + .hw_ctrld = false, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR, + .res_mask = U300_SYSCON_RFR_MMC_RESET_ENABLE, + .clk_val = U300_SYSCON_SBCER_MMC_CLK_EN, + .get_rate = clk_get_rate_mclk, + .set_rate = clk_set_rate_mclk, + .round_rate = clk_round_rate_mclk, + .disable = syscon_clk_disable, + .enable = syscon_clk_enable, +}; + +static struct clk i2s0_clk = { + .name = "i2s0", + .parent = &fast_clk, + .rate = 26000000, /* this varies! */ + .hw_ctrld = true, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR, + .res_mask = U300_SYSCON_RFR_PCM_I2S0_RESET_ENABLE, + .clk_val = U300_SYSCON_SBCER_I2S0_CORE_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, + .get_rate = clk_get_rate_i2s_i2c_spi, +}; + +static struct clk i2s1_clk = { + .name = "i2s1", + .parent = &fast_clk, + .rate = 26000000, /* this varies! */ + .hw_ctrld = true, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR, + .res_mask = U300_SYSCON_RFR_PCM_I2S1_RESET_ENABLE, + .clk_val = U300_SYSCON_SBCER_I2S1_CORE_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, + .get_rate = clk_get_rate_i2s_i2c_spi, +}; + +static struct clk i2c0_clk = { + .name = "I2C0", + .parent = &fast_clk, + .rate = 26000000, /* this varies! */ + .hw_ctrld = false, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR, + .res_mask = U300_SYSCON_RFR_I2C0_RESET_ENABLE, + .clk_val = U300_SYSCON_SBCER_I2C0_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, + .get_rate = clk_get_rate_i2s_i2c_spi, +}; + +static struct clk i2c1_clk = { + .name = "I2C1", + .parent = &fast_clk, + .rate = 26000000, /* this varies! */ + .hw_ctrld = false, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR, + .res_mask = U300_SYSCON_RFR_I2C1_RESET_ENABLE, + .clk_val = U300_SYSCON_SBCER_I2C1_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, + .get_rate = clk_get_rate_i2s_i2c_spi, +}; + +static struct clk spi_clk = { + .name = "SPI", + .parent = &fast_clk, + .rate = 26000000, /* this varies! */ + .hw_ctrld = false, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR, + .res_mask = U300_SYSCON_RFR_SPI_RESET_ENABLE, + .clk_val = U300_SYSCON_SBCER_SPI_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, + .get_rate = clk_get_rate_i2s_i2c_spi, +}; + +#ifdef CONFIG_MACH_U300_BS335 +static struct clk uart1_clk = { + .name = "UART1", + .parent = &fast_clk, + .rate = 13000000, + .hw_ctrld = false, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RFR, + .res_mask = U300_SYSCON_RFR_UART1_RESET_ENABLE, + .clk_val = U300_SYSCON_SBCER_UART1_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, +}; +#endif + + +/* + * Clocks on the SLOW bridge + */ +static struct clk slow_clk = { + .name = "SLOW_BRIDGE", + .parent = &amba_clk, + .rate = 13000000, + .hw_ctrld = true, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, + .res_mask = U300_SYSCON_RSR_SLOW_BRIDGE_RESET_EN, + .clk_val = U300_SYSCON_SBCER_SLOW_BRIDGE_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, +}; + +/* TODO: implement SYSCON clock? */ + +static struct clk wdog_clk = { + .name = "WDOG", + .parent = &slow_clk, + .hw_ctrld = false, + .rate = 32768, + .reset = false, + /* This is always on, cannot be enabled/disabled or reset */ +}; + +/* This one is hardwired to PLL13 */ +static struct clk uart_clk = { + .name = "UARTCLK", + .parent = &slow_clk, + .rate = 13000000, + .hw_ctrld = false, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, + .res_mask = U300_SYSCON_RSR_UART_RESET_EN, + .clk_val = U300_SYSCON_SBCER_UART_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, +}; + +static struct clk keypad_clk = { + .name = "KEYPAD", + .parent = &slow_clk, + .rate = 32768, + .hw_ctrld = false, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, + .res_mask = U300_SYSCON_RSR_KEYPAD_RESET_EN, + .clk_val = U300_SYSCON_SBCER_KEYPAD_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, +}; + +static struct clk gpio_clk = { + .name = "GPIO", + .parent = &slow_clk, + .rate = 13000000, + .hw_ctrld = true, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, + .res_mask = U300_SYSCON_RSR_GPIO_RESET_EN, + .clk_val = U300_SYSCON_SBCER_GPIO_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, +}; + +static struct clk rtc_clk = { + .name = "RTC", + .parent = &slow_clk, + .rate = 32768, + .hw_ctrld = true, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, + .res_mask = U300_SYSCON_RSR_RTC_RESET_EN, + /* This clock is always on, cannot be enabled/disabled */ +}; + +static struct clk bustr_clk = { + .name = "BUSTR", + .parent = &slow_clk, + .rate = 13000000, + .hw_ctrld = true, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, + .res_mask = U300_SYSCON_RSR_BTR_RESET_EN, + .clk_val = U300_SYSCON_SBCER_BTR_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, +}; + +static struct clk evhist_clk = { + .name = "EVHIST", + .parent = &slow_clk, + .rate = 13000000, + .hw_ctrld = true, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, + .res_mask = U300_SYSCON_RSR_EH_RESET_EN, + .clk_val = U300_SYSCON_SBCER_EH_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, +}; + +static struct clk timer_clk = { + .name = "TIMER", + .parent = &slow_clk, + .rate = 13000000, + .hw_ctrld = true, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, + .res_mask = U300_SYSCON_RSR_ACC_TMR_RESET_EN, + .clk_val = U300_SYSCON_SBCER_ACC_TMR_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, +}; + +static struct clk app_timer_clk = { + .name = "TIMER_APP", + .parent = &slow_clk, + .rate = 13000000, + .hw_ctrld = true, + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, + .res_mask = U300_SYSCON_RSR_APP_TMR_RESET_EN, + .clk_val = U300_SYSCON_SBCER_APP_TMR_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, +}; + +#ifdef CONFIG_MACH_U300_BS335 +static struct clk ppm_clk = { + .name = "PPM", + .parent = &slow_clk, + .rate = 0, /* FIXME */ + .hw_ctrld = true, /* TODO: Look up if it is hw ctrld or not */ + .reset = true, + .res_reg = U300_SYSCON_VBASE + U300_SYSCON_RSR, + .res_mask = U300_SYSCON_RSR_PPM_RESET_EN, + .clk_val = U300_SYSCON_SBCER_PPM_CLK_EN, + .enable = syscon_clk_enable, + .disable = syscon_clk_disable, +}; +#endif + +#define DEF_LOOKUP(devid, clkref) \ + { \ + .dev_id = devid, \ + .clk = clkref, \ + } + +/* + * Here we only define clocks that are meaningful to + * look up through clockdevice. + */ +static struct clk_lookup lookups[] = { + /* Connected directly to the AMBA bus */ + DEF_LOOKUP("amba", &amba_clk), + DEF_LOOKUP("cpu", &cpu_clk), + DEF_LOOKUP("nandif", &nandif_clk), + DEF_LOOKUP("semi", &semi_clk), +#ifdef CONFIG_MACH_U300_BS335 + DEF_LOOKUP("isp", &isp_clk), + DEF_LOOKUP("cds", &cds_clk), +#endif + DEF_LOOKUP("dma", &dma_clk), + DEF_LOOKUP("aaif", &aaif_clk), + DEF_LOOKUP("apex", &apex_clk), + DEF_LOOKUP("video_enc", &video_enc_clk), + DEF_LOOKUP("xgam", &xgam_clk), + DEF_LOOKUP("ahb", &ahb_clk), + /* AHB bridge clocks */ + DEF_LOOKUP("ahb", &ahb_subsys_clk), + DEF_LOOKUP("intcon", &intcon_clk), + DEF_LOOKUP("mspro", &mspro_clk), + DEF_LOOKUP("pl172", &emif_clk), + /* FAST bridge clocks */ + DEF_LOOKUP("fast", &fast_clk), + DEF_LOOKUP("mmci", &mmcsd_clk), + /* + * The .0 and .1 identifiers on these comes from the platform device + * .id field and are assigned when the platform devices are registered. + */ + DEF_LOOKUP("i2s.0", &i2s0_clk), + DEF_LOOKUP("i2s.1", &i2s1_clk), + DEF_LOOKUP("stddci2c.0", &i2c0_clk), + DEF_LOOKUP("stddci2c.1", &i2c1_clk), + DEF_LOOKUP("pl022", &spi_clk), +#ifdef CONFIG_MACH_U300_BS335 + DEF_LOOKUP("uart1", &uart1_clk), +#endif + /* SLOW bridge clocks */ + DEF_LOOKUP("slow", &slow_clk), + DEF_LOOKUP("wdog", &wdog_clk), + DEF_LOOKUP("uart0", &uart_clk), + DEF_LOOKUP("apptimer", &app_timer_clk), + DEF_LOOKUP("keypad", &keypad_clk), + DEF_LOOKUP("u300-gpio", &gpio_clk), + DEF_LOOKUP("rtc0", &rtc_clk), + DEF_LOOKUP("bustr", &bustr_clk), + DEF_LOOKUP("evhist", &evhist_clk), + DEF_LOOKUP("timer", &timer_clk), +#ifdef CONFIG_MACH_U300_BS335 + DEF_LOOKUP("ppm", &ppm_clk), +#endif +}; + +static void __init clk_register(void) +{ + int i; + + /* Register the lookups */ + for (i = 0; i < ARRAY_SIZE(lookups); i++) + clkdev_add(&lookups[i]); +} + +/* + * These are the clocks for cells registered as primecell drivers + * on the AMBA bus. These must be on during AMBA device registration + * since the bus probe will attempt to read magic configuration + * registers for these devices. If they are deactivated these probes + * will fail. + * + * + * Please note that on emif, both RAM and NAND is connected in dual + * RAM phones. On single RAM phones, ram is on semi and NAND on emif. + * + */ +void u300_clock_primecells(void) +{ + clk_enable(&intcon_clk); + clk_enable(&uart_clk); +#ifdef CONFIG_MACH_U300_BS335 + clk_enable(&uart1_clk); +#endif + clk_enable(&spi_clk); + + clk_enable(&mmcsd_clk); + +} +EXPORT_SYMBOL(u300_clock_primecells); + +void u300_unclock_primecells(void) +{ + + clk_disable(&intcon_clk); + clk_disable(&uart_clk); +#ifdef CONFIG_MACH_U300_BS335 + clk_disable(&uart1_clk); +#endif + clk_disable(&spi_clk); + clk_disable(&mmcsd_clk); + +} +EXPORT_SYMBOL(u300_unclock_primecells); + +/* + * The interrupt controller is enabled before the clock API is registered. + */ +void u300_enable_intcon_clock(void) +{ + clk_enable(&intcon_clk); +} +EXPORT_SYMBOL(u300_enable_intcon_clock); + +/* + * The timer is enabled before the clock API is registered. + */ +void u300_enable_timer_clock(void) +{ + clk_enable(&app_timer_clk); +} +EXPORT_SYMBOL(u300_enable_timer_clock); + +#if (defined(CONFIG_DEBUG_FS) && defined(CONFIG_U300_DEBUG)) +/* + * The following makes it possible to view the status (especially + * reference count and reset status) for the clocks in the platform + * by looking into the special file /u300_clocks + */ + +/* A list of all clocks in the platform */ +static struct clk *clks[] = { + /* Top node clock for the AMBA bus */ + &amba_clk, + /* Connected directly to the AMBA bus */ + &cpu_clk, + &nandif_clk, + &semi_clk, +#ifdef CONFIG_MACH_U300_BS335 + &isp_clk, + &cds_clk, +#endif + &dma_clk, + &aaif_clk, + &apex_clk, + &video_enc_clk, + &xgam_clk, + &ahb_clk, + + /* AHB bridge clocks */ + &ahb_subsys_clk, + &intcon_clk, + &mspro_clk, + &emif_clk, + /* FAST bridge clocks */ + &fast_clk, + &mmcsd_clk, + &i2s0_clk, + &i2s1_clk, + &i2c0_clk, + &i2c1_clk, + &spi_clk, +#ifdef CONFIG_MACH_U300_BS335 + &uart1_clk, +#endif + /* SLOW bridge clocks */ + &slow_clk, + &wdog_clk, + &uart_clk, + &app_timer_clk, + &keypad_clk, + &gpio_clk, + &rtc_clk, + &bustr_clk, + &evhist_clk, + &timer_clk, +#ifdef CONFIG_MACH_U300_BS335 + &ppm_clk, +#endif +}; + +static int u300_clocks_show(struct seq_file *s, void *data) +{ + struct clk *clk; + int i; + + seq_printf(s, "CLOCK DEVICE RESET STATE\t" \ + "ACTIVE\tUSERS\tHW CTRL FREQ\n"); + seq_printf(s, "---------------------------------------------" \ + "-----------------------------------------\n"); + for (i = 0; i < ARRAY_SIZE(clks); i++) { + clk = clks[i]; + if (clk != ERR_PTR(-ENOENT)) { + /* Format clock and device name nicely */ + char cdp[33]; + int chars; + + chars = snprintf(&cdp[0], 17, "%s", clk->name); + while (chars < 16) { + cdp[chars] = ' '; + chars++; + } + chars = snprintf(&cdp[16], 17, "%s", clk->dev ? + dev_name(clk->dev) : "N/A"); + while (chars < 16) { + cdp[chars+16] = ' '; + chars++; + } + cdp[32] = '\0'; + if (clk->get_rate) + seq_printf(s, + "%s%s\t%s\t%d\t%s\t%lu Hz\n", + &cdp[0], + clk->reset ? + "ASSERTED" : "RELEASED", + clk->usecount ? "ON" : "OFF", + clk->usecount, + clk->hw_ctrld ? "YES" : "NO ", + clk->get_rate(clk)); + else + seq_printf(s, + "%s%s\t%s\t%d\t%s\t" \ + "(unknown rate)\n", + &cdp[0], + clk->reset ? + "ASSERTED" : "RELEASED", + clk->usecount ? "ON" : "OFF", + clk->usecount, + clk->hw_ctrld ? "YES" : "NO "); + } + } + return 0; +} + +static int u300_clocks_open(struct inode *inode, struct file *file) +{ + return single_open(file, u300_clocks_show, NULL); +} + +static const struct file_operations u300_clocks_operations = { + .open = u300_clocks_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void init_clk_read_procfs(void) +{ + /* Expose a simple debugfs interface to view all clocks */ + (void) debugfs_create_file("u300_clocks", S_IFREG | S_IRUGO, + NULL, NULL, &u300_clocks_operations); +} +#else +static inline void init_clk_read_procfs(void) +{ +} +#endif + +static int __init u300_clock_init(void) +{ + u16 val; + + /* + * FIXME: shall all this powermanagement stuff really live here??? + */ + + /* Set system to run at PLL208, max performance, a known state. */ + val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); + val &= ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); + /* Wait for the PLL208 to lock if not locked in yet */ + while (!(readw(U300_SYSCON_VBASE + U300_SYSCON_CSR) & + U300_SYSCON_CSR_PLL208_LOCK_IND)); + + /* Power management enable */ + val = readw(U300_SYSCON_VBASE + U300_SYSCON_PMCR); + val |= U300_SYSCON_PMCR_PWR_MGNT_ENABLE; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_PMCR); + + clk_register(); + + init_clk_read_procfs(); + + /* + * Some of these may be on when we boot the system so make sure they + * are turned OFF. + */ + syscon_block_reset_enable(&timer_clk); + timer_clk.disable(&timer_clk); + + /* + * These shall be turned on by default when we boot the system + * so make sure they are ON. (Adding CPU here is a bit too much.) + * These clocks will be claimed by drivers later. + */ + syscon_block_reset_disable(&semi_clk); + syscon_block_reset_disable(&emif_clk); + semi_clk.enable(&semi_clk); + emif_clk.enable(&emif_clk); + + return 0; +} +/* initialize clocking early to be available later in the boot */ +core_initcall(u300_clock_init); diff --git a/arch/arm/mach-u300/clock.h b/arch/arm/mach-u300/clock.h new file mode 100644 index 00000000000..fc6d9ccfe7e --- /dev/null +++ b/arch/arm/mach-u300/clock.h @@ -0,0 +1,53 @@ +/* + * arch/arm/mach-u300/include/mach/clock.h + * + * Copyright (C) 2004 - 2005 Nokia corporation + * Written by Tuukka Tikkanen + * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc + * Copyright (C) 2007-2009 ST-Ericsson AB + * Adopted to ST-Ericsson U300 platforms by + * Jonas Aaberg + * + * 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. + * + */ + +#ifndef __MACH_CLOCK_H +#define __MACH_CLOCK_H + +#include + +struct clk { + struct list_head node; + struct module *owner; + struct device *dev; + const char *name; + struct clk *parent; + + spinlock_t lock; + unsigned long rate; + bool reset; + __u16 clk_val; + __s8 usecount; + __u32 res_reg; + __u16 res_mask; + + bool hw_ctrld; + + void (*recalc) (struct clk *); + int (*set_rate) (struct clk *, unsigned long); + unsigned long (*get_rate) (struct clk *); + unsigned long (*round_rate) (struct clk *, unsigned long); + void (*init) (struct clk *); + void (*enable) (struct clk *); + void (*disable) (struct clk *); +}; + +void u300_clock_primecells(void); +void u300_unclock_primecells(void); +void u300_enable_intcon_clock(void); +void u300_enable_timer_clock(void); + +#endif diff --git a/arch/arm/mach-u300/include/mach/clkdev.h b/arch/arm/mach-u300/include/mach/clkdev.h new file mode 100644 index 00000000000..92e3cc872c6 --- /dev/null +++ b/arch/arm/mach-u300/include/mach/clkdev.h @@ -0,0 +1,7 @@ +#ifndef __MACH_CLKDEV_H +#define __MACH_CLKDEV_H + +int __clk_get(struct clk *clk); +void __clk_put(struct clk *clk); + +#endif -- cgit v1.2.3 From bb3cee2b35d2b9edab71997bd06040ff37483e08 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 23 Apr 2009 10:22:13 +0100 Subject: [ARM] 5473/1: U300 core machine support This adds core support for the ST-Ericsson U300 series platforms: U300, U330, U335 and U365. Supports memory mappings, interrupt controller, system timer (clocksource and clockevents), and binds to the existing drivers for the PrimeCells used in this design: PL190 (VIC), PL180 (MMC/SD host) and PL011 (UART). This is intented to serve as starting point for our mainling work, more patches to follow. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-u300/Kconfig | 105 +++++ arch/arm/mach-u300/Makefile | 11 + arch/arm/mach-u300/core.c | 649 ++++++++++++++++++++++++++ arch/arm/mach-u300/include/mach/debug-macro.S | 22 + arch/arm/mach-u300/include/mach/entry-macro.S | 40 ++ arch/arm/mach-u300/include/mach/memory.h | 42 ++ arch/arm/mach-u300/include/mach/platform.h | 19 + arch/arm/mach-u300/include/mach/system.h | 42 ++ arch/arm/mach-u300/include/mach/timex.h | 17 + arch/arm/mach-u300/include/mach/uncompress.h | 46 ++ arch/arm/mach-u300/include/mach/vmalloc.h | 12 + arch/arm/mach-u300/mmc.c | 216 +++++++++ arch/arm/mach-u300/mmc.h | 18 + arch/arm/mach-u300/timer.c | 422 +++++++++++++++++ arch/arm/mach-u300/u300.c | 55 +++ 15 files changed, 1716 insertions(+) create mode 100644 arch/arm/mach-u300/Kconfig create mode 100644 arch/arm/mach-u300/Makefile create mode 100644 arch/arm/mach-u300/core.c create mode 100644 arch/arm/mach-u300/include/mach/debug-macro.S create mode 100644 arch/arm/mach-u300/include/mach/entry-macro.S create mode 100644 arch/arm/mach-u300/include/mach/memory.h create mode 100644 arch/arm/mach-u300/include/mach/platform.h create mode 100644 arch/arm/mach-u300/include/mach/system.h create mode 100644 arch/arm/mach-u300/include/mach/timex.h create mode 100644 arch/arm/mach-u300/include/mach/uncompress.h create mode 100644 arch/arm/mach-u300/include/mach/vmalloc.h create mode 100644 arch/arm/mach-u300/mmc.c create mode 100644 arch/arm/mach-u300/mmc.h create mode 100644 arch/arm/mach-u300/timer.c create mode 100644 arch/arm/mach-u300/u300.c (limited to 'arch/arm/mach-u300') diff --git a/arch/arm/mach-u300/Kconfig b/arch/arm/mach-u300/Kconfig new file mode 100644 index 00000000000..337b9aabce4 --- /dev/null +++ b/arch/arm/mach-u300/Kconfig @@ -0,0 +1,105 @@ +if ARCH_U300 + +menu "ST-Ericsson AB U300/U330/U335/U365 Platform" + +comment "ST-Ericsson Mobile Platform Products" + +config MACH_U300 + bool "U300" + +comment "ST-Ericsson U300/U330/U335/U365 Feature Selections" + +choice + prompt "U300/U330/U335/U365 system type" + default MACH_U300_BS2X + ---help--- + You need to select the target system, i.e. the + U300/U330/U335/U365 board that you want to compile your kernel + for. + +config MACH_U300_BS2X + bool "S26/S26/B25/B26 Test Products" + depends on MACH_U300 + help + Select this if you're developing on the + S26/S25 test products. (Also works on + B26/B25 big boards.) + +config MACH_U300_BS330 + bool "S330/B330 Test Products" + depends on MACH_U300 + help + Select this if you're developing on the + S330/B330 test products. + +config MACH_U300_BS335 + bool "S335/B335 Test Products" + depends on MACH_U300 + help + Select this if you're developing on the + S335/B335 test products. + +config MACH_U300_BS365 + bool "S365/B365 Test Products" + depends on MACH_U300 + help + Select this if you're developing on the + S365/B365 test products. + +endchoice + +choice + prompt "Memory configuration" + default MACH_U300_SINGLE_RAM + ---help--- + You have to config the kernel according to the physical memory + configuration. + +config MACH_U300_SINGLE_RAM + bool "Single RAM" + help + Select this if you want support for Single RAM phones. + +config MACH_U300_DUAL_RAM + bool "Dual RAM" + help + Select this if you want support for Dual RAM phones. + This is two RAM memorys on different EMIFs. +endchoice + +config U300_DEBUG + bool "Debug support for U300" + depends on PM + help + Debug support for U300 in sysfs, procfs etc. + +config MACH_U300_SEMI_IS_SHARED + bool "The SEMI is used by both the access and application side" + depends on MACH_U300 + help + This makes it possible to use the SEMI (Shared External + Memory Interface) from both from access and application + side. + +comment "All the settings below must match the bootloader's settings" + +config MACH_U300_ACCESS_MEM_SIZE + int "Access CPU memory allocation" + range 7 25 + depends on MACH_U300_SINGLE_RAM + default 13 + help + How much memory in MiB that the Access side CPU has allocated + +config MACH_U300_2MB_ALIGNMENT_FIX + bool "2MiB alignment fix" + depends on MACH_U300_SINGLE_RAM + default y + help + If yes and the Access side CPU has allocated an odd size in + MiB, this fix gives you one MiB extra that would otherwise be + lost due to Linux 2 MiB alignment policy. + +endmenu + +endif diff --git a/arch/arm/mach-u300/Makefile b/arch/arm/mach-u300/Makefile new file mode 100644 index 00000000000..24950e0df4b --- /dev/null +++ b/arch/arm/mach-u300/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for the linux kernel, U300 machine. +# + +obj-y := core.o clock.o timer.o gpio.o padmux.o +obj-m := +obj-n := +obj- := + +obj-$(CONFIG_ARCH_U300) += u300.o +obj-$(CONFIG_MMC) += mmc.o diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c new file mode 100644 index 00000000000..1f2ed21a0ab --- /dev/null +++ b/arch/arm/mach-u300/core.c @@ -0,0 +1,649 @@ +/* + * + * arch/arm/mach-u300/core.c + * + * + * Copyright (C) 2007-2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * Core platform support, IRQ handling and device definitions. + * Author: Linus Walleij + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "clock.h" +#include "mmc.h" + +/* + * Static I/O mappings that are needed for booting the U300 platforms. The + * only things we need are the areas where we find the timer, syscon and + * intcon, since the remaining device drivers will map their own memory + * physical to virtual as the need arise. + */ +static struct map_desc u300_io_desc[] __initdata = { + { + .virtual = U300_SLOW_PER_VIRT_BASE, + .pfn = __phys_to_pfn(U300_SLOW_PER_PHYS_BASE), + .length = SZ_64K, + .type = MT_DEVICE, + }, + { + .virtual = U300_AHB_PER_VIRT_BASE, + .pfn = __phys_to_pfn(U300_AHB_PER_PHYS_BASE), + .length = SZ_32K, + .type = MT_DEVICE, + }, + { + .virtual = U300_FAST_PER_VIRT_BASE, + .pfn = __phys_to_pfn(U300_FAST_PER_PHYS_BASE), + .length = SZ_32K, + .type = MT_DEVICE, + }, + { + .virtual = 0xffff2000, /* TCM memory */ + .pfn = __phys_to_pfn(0xffff2000), + .length = SZ_16K, + .type = MT_DEVICE, + }, + + /* + * This overlaps with the IRQ vectors etc at 0xffff0000, so these + * may have to be moved to 0x00000000 in order to use the ROM. + */ + /* + { + .virtual = U300_BOOTROM_VIRT_BASE, + .pfn = __phys_to_pfn(U300_BOOTROM_PHYS_BASE), + .length = SZ_64K, + .type = MT_ROM, + }, + */ +}; + +void __init u300_map_io(void) +{ + iotable_init(u300_io_desc, ARRAY_SIZE(u300_io_desc)); +} + +/* + * Declaration of devices found on the U300 board and + * their respective memory locations. + */ +static struct amba_device uart0_device = { + .dev = { + .init_name = "uart0", /* Slow device at 0x3000 offset */ + .platform_data = NULL, + }, + .res = { + .start = U300_UART0_BASE, + .end = U300_UART0_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + .irq = { IRQ_U300_UART0, NO_IRQ }, +}; + +/* The U335 have an additional UART1 on the APP CPU */ +#ifdef CONFIG_MACH_U300_BS335 +static struct amba_device uart1_device = { + .dev = { + .init_name = "uart1", /* Fast device at 0x7000 offset */ + .platform_data = NULL, + }, + .res = { + .start = U300_UART1_BASE, + .end = U300_UART1_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + .irq = { IRQ_U300_UART1, NO_IRQ }, +}; +#endif + +static struct amba_device pl172_device = { + .dev = { + .init_name = "pl172", /* AHB device at 0x4000 offset */ + .platform_data = NULL, + }, + .res = { + .start = U300_EMIF_CFG_BASE, + .end = U300_EMIF_CFG_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + + +/* + * Everything within this next ifdef deals with external devices connected to + * the APP SPI bus. + */ +static struct amba_device pl022_device = { + .dev = { + .coherent_dma_mask = ~0, + .init_name = "pl022", /* Fast device at 0x6000 offset */ + }, + .res = { + .start = U300_SPI_BASE, + .end = U300_SPI_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_U300_SPI, NO_IRQ }, + /* + * This device has a DMA channel but the Linux driver does not use + * it currently. + */ +}; + +static struct amba_device mmcsd_device = { + .dev = { + .init_name = "mmci", /* Fast device at 0x1000 offset */ + .platform_data = NULL, /* Added later */ + }, + .res = { + .start = U300_MMCSD_BASE, + .end = U300_MMCSD_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_U300_MMCSD_MCIINTR0, IRQ_U300_MMCSD_MCIINTR1 }, + /* + * This device has a DMA channel but the Linux driver does not use + * it currently. + */ +}; + +/* + * The order of device declaration may be important, since some devices + * have dependencies on other devices being initialized first. + */ +static struct amba_device *amba_devs[] __initdata = { + &uart0_device, +#ifdef CONFIG_MACH_U300_BS335 + &uart1_device, +#endif + &pl022_device, + &pl172_device, + &mmcsd_device, +}; + +/* Here follows a list of all hw resources that the platform devices + * allocate. Note, clock dependencies are not included + */ + +static struct resource gpio_resources[] = { + { + .start = U300_GPIO_BASE, + .end = (U300_GPIO_BASE + SZ_4K - 1), + .flags = IORESOURCE_MEM, + }, + { + .name = "gpio0", + .start = IRQ_U300_GPIO_PORT0, + .end = IRQ_U300_GPIO_PORT0, + .flags = IORESOURCE_IRQ, + }, + { + .name = "gpio1", + .start = IRQ_U300_GPIO_PORT1, + .end = IRQ_U300_GPIO_PORT1, + .flags = IORESOURCE_IRQ, + }, + { + .name = "gpio2", + .start = IRQ_U300_GPIO_PORT2, + .end = IRQ_U300_GPIO_PORT2, + .flags = IORESOURCE_IRQ, + }, +#ifdef U300_COH901571_3 + { + .name = "gpio3", + .start = IRQ_U300_GPIO_PORT3, + .end = IRQ_U300_GPIO_PORT3, + .flags = IORESOURCE_IRQ, + }, + { + .name = "gpio4", + .start = IRQ_U300_GPIO_PORT4, + .end = IRQ_U300_GPIO_PORT4, + .flags = IORESOURCE_IRQ, + }, +#ifdef CONFIG_MACH_U300_BS335 + { + .name = "gpio5", + .start = IRQ_U300_GPIO_PORT5, + .end = IRQ_U300_GPIO_PORT5, + .flags = IORESOURCE_IRQ, + }, + { + .name = "gpio6", + .start = IRQ_U300_GPIO_PORT6, + .end = IRQ_U300_GPIO_PORT6, + .flags = IORESOURCE_IRQ, + }, +#endif /* CONFIG_MACH_U300_BS335 */ +#endif /* U300_COH901571_3 */ +}; + +static struct resource keypad_resources[] = { + { + .start = U300_KEYPAD_BASE, + .end = U300_KEYPAD_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "coh901461-press", + .start = IRQ_U300_KEYPAD_KEYBF, + .end = IRQ_U300_KEYPAD_KEYBF, + .flags = IORESOURCE_IRQ, + }, + { + .name = "coh901461-release", + .start = IRQ_U300_KEYPAD_KEYBR, + .end = IRQ_U300_KEYPAD_KEYBR, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource rtc_resources[] = { + { + .start = U300_RTC_BASE, + .end = U300_RTC_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_U300_RTC, + .end = IRQ_U300_RTC, + .flags = IORESOURCE_IRQ, + }, +}; + +/* + * Fsmc does have IRQs: #43 and #44 (NFIF and NFIF2) + * but these are not yet used by the driver. + */ +static struct resource fsmc_resources[] = { + { + .start = U300_NAND_IF_PHYS_BASE, + .end = U300_NAND_IF_PHYS_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct resource i2c0_resources[] = { + { + .start = U300_I2C0_BASE, + .end = U300_I2C0_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_U300_I2C0, + .end = IRQ_U300_I2C0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource i2c1_resources[] = { + { + .start = U300_I2C1_BASE, + .end = U300_I2C1_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_U300_I2C1, + .end = IRQ_U300_I2C1, + .flags = IORESOURCE_IRQ, + }, + +}; + +static struct resource wdog_resources[] = { + { + .start = U300_WDOG_BASE, + .end = U300_WDOG_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_U300_WDOG, + .end = IRQ_U300_WDOG, + .flags = IORESOURCE_IRQ, + } +}; + +/* TODO: These should be protected by suitable #ifdef's */ +static struct resource ave_resources[] = { + { + .name = "AVE3e I/O Area", + .start = U300_VIDEOENC_BASE, + .end = U300_VIDEOENC_BASE + SZ_512K - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "AVE3e IRQ0", + .start = IRQ_U300_VIDEO_ENC_0, + .end = IRQ_U300_VIDEO_ENC_0, + .flags = IORESOURCE_IRQ, + }, + { + .name = "AVE3e IRQ1", + .start = IRQ_U300_VIDEO_ENC_1, + .end = IRQ_U300_VIDEO_ENC_1, + .flags = IORESOURCE_IRQ, + }, + { + .name = "AVE3e Physmem Area", + .start = 0, /* 0 will be remapped to reserved memory */ + .end = SZ_1M - 1, + .flags = IORESOURCE_MEM, + }, + /* + * The AVE3e requires two regions of 256MB that it considers + * "invisible". The hardware will not be able to access these + * adresses, so they should never point to system RAM. + */ + { + .name = "AVE3e Reserved 0", + .start = 0xd0000000, + .end = 0xd0000000 + SZ_256M - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "AVE3e Reserved 1", + .start = 0xe0000000, + .end = 0xe0000000 + SZ_256M - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device wdog_device = { + .name = "wdog", + .id = -1, + .num_resources = ARRAY_SIZE(wdog_resources), + .resource = wdog_resources, +}; + +static struct platform_device i2c0_device = { + .name = "stddci2c", + .id = 0, + .num_resources = ARRAY_SIZE(i2c0_resources), + .resource = i2c0_resources, +}; + +static struct platform_device i2c1_device = { + .name = "stddci2c", + .id = 1, + .num_resources = ARRAY_SIZE(i2c1_resources), + .resource = i2c1_resources, +}; + +static struct platform_device gpio_device = { + .name = "u300-gpio", + .id = -1, + .num_resources = ARRAY_SIZE(gpio_resources), + .resource = gpio_resources, +}; + +static struct platform_device keypad_device = { + .name = "keypad", + .id = -1, + .num_resources = ARRAY_SIZE(keypad_resources), + .resource = keypad_resources, +}; + +static struct platform_device rtc_device = { + .name = "rtc0", + .id = -1, + .num_resources = ARRAY_SIZE(rtc_resources), + .resource = rtc_resources, +}; + +static struct platform_device fsmc_device = { + .name = "nandif", + .id = -1, + .num_resources = ARRAY_SIZE(fsmc_resources), + .resource = fsmc_resources, +}; + +static struct platform_device ave_device = { + .name = "video_enc", + .id = -1, + .num_resources = ARRAY_SIZE(ave_resources), + .resource = ave_resources, +}; + +/* + * Notice that AMBA devices are initialized before platform devices. + * + */ +static struct platform_device *platform_devs[] __initdata = { + &i2c0_device, + &i2c1_device, + &keypad_device, + &rtc_device, + &gpio_device, + &fsmc_device, + &wdog_device, + &ave_device +}; + + +/* + * Interrupts: the U300 platforms have two pl190 ARM PrimeCells connected + * together so some interrupts are connected to the first one and some + * to the second one. + */ +void __init u300_init_irq(void) +{ + u32 mask[2] = {0, 0}; + int i; + + for (i = 0; i < NR_IRQS; i++) + set_bit(i, (unsigned long *) &mask[0]); + u300_enable_intcon_clock(); + vic_init((void __iomem *) U300_INTCON0_VBASE, 0, mask[0]); + vic_init((void __iomem *) U300_INTCON1_VBASE, 32, mask[1]); +} + + +/* + * U300 platforms peripheral handling + */ +struct db_chip { + u16 chipid; + const char *name; +}; + +/* + * This is a list of the Digital Baseband chips used in the U300 platform. + */ +static struct db_chip db_chips[] __initdata = { + { + .chipid = 0xb800, + .name = "DB3000", + }, + { + .chipid = 0xc000, + .name = "DB3100", + }, + { + .chipid = 0xc800, + .name = "DB3150", + }, + { + .chipid = 0xd800, + .name = "DB3200", + }, + { + .chipid = 0xe000, + .name = "DB3250", + }, + { + .chipid = 0xe800, + .name = "DB3210", + }, + { + .chipid = 0xf000, + .name = "DB3350 P1x", + }, + { + .chipid = 0xf100, + .name = "DB3350 P2x", + }, + { + .chipid = 0x0000, /* List terminator */ + .name = NULL, + } +}; + +static void u300_init_check_chip(void) +{ + + u16 val; + struct db_chip *chip; + const char *chipname; + const char unknown[] = "UNKNOWN"; + + /* Read out and print chip ID */ + val = readw(U300_SYSCON_VBASE + U300_SYSCON_CIDR); + /* This is in funky bigendian order... */ + val = (val & 0xFFU) << 8 | (val >> 8); + chip = db_chips; + chipname = unknown; + + for ( ; chip->chipid; chip++) { + if (chip->chipid == (val & 0xFF00U)) { + chipname = chip->name; + break; + } + } + printk(KERN_INFO "Initializing U300 system on %s baseband chip " \ + "(chip ID 0x%04x)\n", chipname, val); + +#ifdef CONFIG_MACH_U300_BS26 + if ((val & 0xFF00U) != 0xc800) { + printk(KERN_ERR "Platform configured for BS25/BS26 " \ + "with DB3150 but %s detected, expect problems!", + chipname); + } +#endif +#ifdef CONFIG_MACH_U300_BS330 + if ((val & 0xFF00U) != 0xd800) { + printk(KERN_ERR "Platform configured for BS330 " \ + "with DB3200 but %s detected, expect problems!", + chipname); + } +#endif +#ifdef CONFIG_MACH_U300_BS335 + if ((val & 0xFF00U) != 0xf000 && (val & 0xFF00U) != 0xf100) { + printk(KERN_ERR "Platform configured for BS365 " \ + " with DB3350 but %s detected, expect problems!", + chipname); + } +#endif +#ifdef CONFIG_MACH_U300_BS365 + if ((val & 0xFF00U) != 0xe800) { + printk(KERN_ERR "Platform configured for BS365 " \ + "with DB3210 but %s detected, expect problems!", + chipname); + } +#endif + + +} + +/* + * Some devices and their resources require reserved physical memory from + * the end of the available RAM. This function traverses the list of devices + * and assigns actual adresses to these. + */ +static void __init u300_assign_physmem(void) +{ + unsigned long curr_start = __pa(high_memory); + int i, j; + + for (i = 0; i < ARRAY_SIZE(platform_devs); i++) { + for (j = 0; j < platform_devs[i]->num_resources; j++) { + struct resource *const res = + &platform_devs[i]->resource[j]; + + if (IORESOURCE_MEM == res->flags && + 0 == res->start) { + res->start = curr_start; + res->end += curr_start; + curr_start += (res->end - res->start + 1); + + printk(KERN_INFO "core.c: Mapping RAM " \ + "%#x-%#x to device %s:%s\n", + res->start, res->end, + platform_devs[i]->name, res->name); + } + } + } +} + +void __init u300_init_devices(void) +{ + int i; + u16 val; + + /* Check what platform we run and print some status information */ + u300_init_check_chip(); + + /* Set system to run at PLL208, max performance, a known state. */ + val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR); + val &= ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR); + /* Wait for the PLL208 to lock if not locked in yet */ + while (!(readw(U300_SYSCON_VBASE + U300_SYSCON_CSR) & + U300_SYSCON_CSR_PLL208_LOCK_IND)); + + /* Register the AMBA devices in the AMBA bus abstraction layer */ + u300_clock_primecells(); + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; + amba_device_register(d, &iomem_resource); + } + u300_unclock_primecells(); + + u300_assign_physmem(); + + /* Register the platform devices */ + platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); + +#ifndef CONFIG_MACH_U300_SEMI_IS_SHARED + /* + * Enable SEMI self refresh. Self-refresh of the SDRAM is entered when + * both subsystems are requesting this mode. + * If we not share the Acc SDRAM, this is never the case. Therefore + * enable it here from the App side. + */ + val = readw(U300_SYSCON_VBASE + U300_SYSCON_SMCR) | + U300_SYSCON_SMCR_SEMI_SREFREQ_ENABLE; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_SMCR); +#endif /* CONFIG_MACH_U300_SEMI_IS_SHARED */ +} + +static int core_module_init(void) +{ + /* + * This needs to be initialized later: it needs the input framework + * to be initialized first. + */ + return mmc_init(&mmcsd_device); +} +module_init(core_module_init); diff --git a/arch/arm/mach-u300/include/mach/debug-macro.S b/arch/arm/mach-u300/include/mach/debug-macro.S new file mode 100644 index 00000000000..f3a1cbbeeab --- /dev/null +++ b/arch/arm/mach-u300/include/mach/debug-macro.S @@ -0,0 +1,22 @@ +/* + * + * arch-arm/mach-u300/include/mach/debug-macro.S + * + * + * Copyright (C) 2006-2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * Debugging macro include header. + * Author: Linus Walleij + */ +#include + + .macro addruart,rx + /* If we move the adress using MMU, use this. */ + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + ldreq \rx, = U300_SLOW_PER_PHYS_BASE @ MMU off, physical address + ldrne \rx, = U300_SLOW_PER_VIRT_BASE @ MMU on, virtual address + orr \rx, \rx, #0x00003000 + .endm + +#include diff --git a/arch/arm/mach-u300/include/mach/entry-macro.S b/arch/arm/mach-u300/include/mach/entry-macro.S new file mode 100644 index 00000000000..20731ae39d3 --- /dev/null +++ b/arch/arm/mach-u300/include/mach/entry-macro.S @@ -0,0 +1,40 @@ +/* + * + * arch-arm/mach-u300/include/mach/entry-macro.S + * + * + * Copyright (C) 2006-2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * Low-level IRQ helper macros for ST-Ericsson U300 + * Author: Linus Walleij + */ +#include +#include + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \base, = U300_AHB_PER_VIRT_BASE-U300_AHB_PER_PHYS_BASE+U300_INTCON0_BASE + ldr \irqstat, [\base, #VIC_IRQ_STATUS] @ get masked status + mov \irqnr, #0 + teq \irqstat, #0 + bne 1002f +1001: ldr \base, = U300_AHB_PER_VIRT_BASE-U300_AHB_PER_PHYS_BASE+U300_INTCON1_BASE + ldr \irqstat, [\base, #VIC_IRQ_STATUS] @ get masked status + mov \irqnr, #32 + teq \irqstat, #0 + beq 1003f +1002: tst \irqstat, #1 + bne 1003f + add \irqnr, \irqnr, #1 + movs \irqstat, \irqstat, lsr #1 + bne 1002b +1003: /* EQ will be set if no irqs pending */ + .endm diff --git a/arch/arm/mach-u300/include/mach/memory.h b/arch/arm/mach-u300/include/mach/memory.h new file mode 100644 index 00000000000..bf134bcc129 --- /dev/null +++ b/arch/arm/mach-u300/include/mach/memory.h @@ -0,0 +1,42 @@ +/* + * + * arch/arm/mach-u300/include/mach/memory.h + * + * + * Copyright (C) 2007-2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * Memory virtual/physical mapping constants. + * Author: Linus Walleij + * Author: Jonas Aaberg + */ + +#ifndef __MACH_MEMORY_H +#define __MACH_MEMORY_H + +#ifdef CONFIG_MACH_U300_DUAL_RAM + +#define PHYS_OFFSET UL(0x48000000) +#define BOOT_PARAMS_OFFSET (PHYS_OFFSET + 0x100) + +#else + +#ifdef CONFIG_MACH_U300_2MB_ALIGNMENT_FIX +#define PHYS_OFFSET (0x28000000 + \ + (CONFIG_MACH_U300_ACCESS_MEM_SIZE - \ + (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024) +#else +#define PHYS_OFFSET (0x28000000 + \ + (CONFIG_MACH_U300_ACCESS_MEM_SIZE + \ + (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024) +#endif +#define BOOT_PARAMS_OFFSET (0x28000000 + \ + (CONFIG_MACH_U300_ACCESS_MEM_SIZE + \ + (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024 + 0x100) +#endif + +/* + * We enable a real big DMA buffer if need be. + */ +#define CONSISTENT_DMA_SIZE SZ_4M + +#endif diff --git a/arch/arm/mach-u300/include/mach/platform.h b/arch/arm/mach-u300/include/mach/platform.h new file mode 100644 index 00000000000..77d9210a82e --- /dev/null +++ b/arch/arm/mach-u300/include/mach/platform.h @@ -0,0 +1,19 @@ +/* + * + * arch/arm/mach-u300/include/mach/platform.h + * + * + * Copyright (C) 2006-2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * Basic platform init and mapping functions. + * Author: Linus Walleij + */ + +#ifndef __ASSEMBLY__ + +void u300_map_io(void); +void u300_init_irq(void); +void u300_init_devices(void); +extern struct sys_timer u300_timer; + +#endif diff --git a/arch/arm/mach-u300/include/mach/system.h b/arch/arm/mach-u300/include/mach/system.h new file mode 100644 index 00000000000..8daf13634ce --- /dev/null +++ b/arch/arm/mach-u300/include/mach/system.h @@ -0,0 +1,42 @@ +/* + * + * arch/arm/mach-u300/include/mach/system.h + * + * + * Copyright (C) 2007-2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * System shutdown and reset functions. + * Author: Linus Walleij + */ +#include +#include +#include +#include + +/* Forward declare this function from the watchdog */ +void coh901327_watchdog_reset(void); + +static inline void arch_idle(void) +{ + cpu_do_idle(); +} + +static void arch_reset(char mode, const char *cmd) +{ + switch (mode) { + case 's': + case 'h': + printk(KERN_CRIT "RESET: shutting down/rebooting system\n"); + /* Disable interrupts */ + local_irq_disable(); +#ifdef CONFIG_COH901327_WATCHDOG + coh901327_watchdog_reset(); +#endif + break; + default: + /* Do nothing */ + break; + } + /* Wait for system do die/reset. */ + while (1); +} diff --git a/arch/arm/mach-u300/include/mach/timex.h b/arch/arm/mach-u300/include/mach/timex.h new file mode 100644 index 00000000000..f233b72633f --- /dev/null +++ b/arch/arm/mach-u300/include/mach/timex.h @@ -0,0 +1,17 @@ +/* + * + * arch/arm/mach-u300/include/mach/timex.h + * + * + * Copyright (C) 2006-2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * Platform tick rate definition. + * Author: Linus Walleij + */ +#ifndef __MACH_TIMEX_H +#define __MACH_TIMEX_H + +/* This is for the APP OS GP1 (General Purpose 1) timer */ +#define CLOCK_TICK_RATE 1000000 + +#endif diff --git a/arch/arm/mach-u300/include/mach/uncompress.h b/arch/arm/mach-u300/include/mach/uncompress.h new file mode 100644 index 00000000000..29acb718acf --- /dev/null +++ b/arch/arm/mach-u300/include/mach/uncompress.h @@ -0,0 +1,46 @@ +/* + * arch/arm/mach-u300/include/mach/uncompress.h + * + * Copyright (C) 2003 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#define AMBA_UART_DR (*(volatile unsigned char *)0xc0013000) +#define AMBA_UART_LCRH (*(volatile unsigned char *)0xc001302C) +#define AMBA_UART_CR (*(volatile unsigned char *)0xc0013030) +#define AMBA_UART_FR (*(volatile unsigned char *)0xc0013018) + +/* + * This does not append a newline + */ +static inline void putc(int c) +{ + while (AMBA_UART_FR & (1 << 5)) + barrier(); + + AMBA_UART_DR = c; +} + +static inline void flush(void) +{ + while (AMBA_UART_FR & (1 << 3)) + barrier(); +} + +/* + * nothing to do + */ +#define arch_decomp_setup() +#define arch_decomp_wdog() diff --git a/arch/arm/mach-u300/include/mach/vmalloc.h b/arch/arm/mach-u300/include/mach/vmalloc.h new file mode 100644 index 00000000000..b00c51a66fb --- /dev/null +++ b/arch/arm/mach-u300/include/mach/vmalloc.h @@ -0,0 +1,12 @@ +/* + * + * arch/arm/mach-u300/include/mach/vmalloc.h + * + * + * Copyright (C) 2006-2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * Virtual memory allocations + * End must be above the I/O registers and on an even 2MiB boundary. + * Author: Linus Walleij + */ +#define VMALLOC_END 0xfe800000 diff --git a/arch/arm/mach-u300/mmc.c b/arch/arm/mach-u300/mmc.c new file mode 100644 index 00000000000..3138d3955c9 --- /dev/null +++ b/arch/arm/mach-u300/mmc.c @@ -0,0 +1,216 @@ +/* + * + * arch/arm/mach-u300/mmc.c + * + * + * Copyright (C) 2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * + * Author: Linus Walleij + * Author: Johan Lundin + * Author: Jonas Aaberg + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "mmc.h" + +struct mmci_card_event { + struct input_dev *mmc_input; + int mmc_inserted; + struct work_struct workq; + struct mmc_platform_data mmc0_plat_data; +}; + +static unsigned int mmc_status(struct device *dev) +{ + struct mmci_card_event *mmci_card = container_of( + dev->platform_data, + struct mmci_card_event, mmc0_plat_data); + + return mmci_card->mmc_inserted; +} + +/* + * Here follows a large chunk of code which will only be enabled if you + * have both the AB3100 chip mounted and the MMC subsystem activated. + */ + +static u32 mmc_translate_vdd(struct device *dev, unsigned int voltage) +{ + int v; + + /* + * MMC Spec: + * bit 7: 1.70 - 1.95V + * bit 8 - 14: 2.0 - 2.6V + * bit 15 - 23: 2.7 - 3.6V + * + * ab3100 voltages: + * 000 - 2.85V + * 001 - 2.75V + * 010 - 1.8V + * 011 - 1.5V + */ + switch (voltage) { + case 8: + v = 3; + break; + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + v = 1; + break; + case 16: + v = 1; + break; + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + v = 0; + break; + default: + v = 0; + break; + } + + /* PL180 voltage register bits */ + return v << 2; +} + + + +static int mmci_callback(void *data) +{ + struct mmci_card_event *mmci_card = data; + + disable_irq_on_gpio_pin(U300_GPIO_PIN_MMC_CD); + schedule_work(&mmci_card->workq); + + return 0; +} + + +static ssize_t gpio_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct mmci_card_event *mmci_card = container_of( + dev->platform_data, + struct mmci_card_event, mmc0_plat_data); + + + return sprintf(buf, "%d\n", !mmci_card->mmc_inserted); +} + +static DEVICE_ATTR(mmc_inserted, S_IRUGO, gpio_show, NULL); + +static void _mmci_callback(struct work_struct *ws) +{ + + struct mmci_card_event *mmci_card = container_of( + ws, + struct mmci_card_event, workq); + + mdelay(20); + + mmci_card->mmc_inserted = !!gpio_get_value(U300_GPIO_PIN_MMC_CD); + + input_report_switch(mmci_card->mmc_input, KEY_INSERT, + !mmci_card->mmc_inserted); + input_sync(mmci_card->mmc_input); + + pr_debug("MMC/SD card was %s\n", + mmci_card->mmc_inserted ? "removed" : "inserted"); + + enable_irq_on_gpio_pin(U300_GPIO_PIN_MMC_CD, !mmci_card->mmc_inserted); +} + +int __devinit mmc_init(struct amba_device *adev) +{ + struct mmci_card_event *mmci_card; + struct device *mmcsd_device = &adev->dev; + int ret = 0; + + mmci_card = kzalloc(sizeof(struct mmci_card_event), GFP_KERNEL); + if (!mmci_card) + return -ENOMEM; + + /* Nominally 2.85V on our platform */ + mmci_card->mmc0_plat_data.ocr_mask = MMC_VDD_28_29; + mmci_card->mmc0_plat_data.translate_vdd = mmc_translate_vdd; + mmci_card->mmc0_plat_data.status = mmc_status; + + mmcsd_device->platform_data = (void *) &mmci_card->mmc0_plat_data; + + INIT_WORK(&mmci_card->workq, _mmci_callback); + + ret = gpio_request(U300_GPIO_PIN_MMC_CD, "MMC card detection"); + if (ret) { + printk(KERN_CRIT "Could not allocate MMC card detection " \ + "GPIO pin\n"); + goto out; + } + + ret = gpio_direction_input(U300_GPIO_PIN_MMC_CD); + if (ret) { + printk(KERN_CRIT "Invalid GPIO pin requested\n"); + goto out; + } + + ret = sysfs_create_file(&mmcsd_device->kobj, + &dev_attr_mmc_inserted.attr); + if (ret) + goto out; + + mmci_card->mmc_input = input_allocate_device(); + if (!mmci_card->mmc_input) { + printk(KERN_CRIT "Could not allocate MMC input device\n"); + return -ENOMEM; + } + + mmci_card->mmc_input->name = "MMC insert notification"; + mmci_card->mmc_input->id.bustype = BUS_HOST; + mmci_card->mmc_input->id.vendor = 0; + mmci_card->mmc_input->id.product = 0; + mmci_card->mmc_input->id.version = 0x0100; + mmci_card->mmc_input->dev.parent = mmcsd_device; + input_set_capability(mmci_card->mmc_input, EV_SW, KEY_INSERT); + + /* + * Since this must always be compiled into the kernel, this input + * is never unregistered or free:ed. + */ + ret = input_register_device(mmci_card->mmc_input); + if (ret) { + input_free_device(mmci_card->mmc_input); + goto out; + } + + input_set_drvdata(mmci_card->mmc_input, mmci_card); + + ret = gpio_register_callback(U300_GPIO_PIN_MMC_CD, mmci_callback, + mmci_card); + + schedule_work(&mmci_card->workq); + + printk(KERN_INFO "Registered MMC insert/remove notification\n"); +out: + return ret; +} diff --git a/arch/arm/mach-u300/mmc.h b/arch/arm/mach-u300/mmc.h new file mode 100644 index 00000000000..92b85125abb --- /dev/null +++ b/arch/arm/mach-u300/mmc.h @@ -0,0 +1,18 @@ +/* + * + * arch/arm/mach-u300/mmc.h + * + * + * Copyright (C) 2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * + * Author: Jonas Aaberg + */ +#ifndef MMC_H +#define MMC_H + +#include + +int __devinit mmc_init(struct amba_device *adev); + +#endif diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c new file mode 100644 index 00000000000..57b5351b181 --- /dev/null +++ b/arch/arm/mach-u300/timer.c @@ -0,0 +1,422 @@ +/* + * + * arch/arm/mach-u300/timer.c + * + * + * Copyright (C) 2007-2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * Timer COH 901 328, runs the OS timer interrupt. + * Author: Linus Walleij + */ +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Generic stuff */ +#include +#include +#include + +#include "clock.h" + +/* + * APP side special timer registers + * This timer contains four timers which can fire an interrupt each. + * OS (operating system) timer @ 32768 Hz + * DD (device driver) timer @ 1 kHz + * GP1 (general purpose 1) timer @ 1MHz + * GP2 (general purpose 2) timer @ 1MHz + */ + +/* Reset OS Timer 32bit (-/W) */ +#define U300_TIMER_APP_ROST (0x0000) +#define U300_TIMER_APP_ROST_TIMER_RESET (0x00000000) +/* Enable OS Timer 32bit (-/W) */ +#define U300_TIMER_APP_EOST (0x0004) +#define U300_TIMER_APP_EOST_TIMER_ENABLE (0x00000000) +/* Disable OS Timer 32bit (-/W) */ +#define U300_TIMER_APP_DOST (0x0008) +#define U300_TIMER_APP_DOST_TIMER_DISABLE (0x00000000) +/* OS Timer Mode Register 32bit (-/W) */ +#define U300_TIMER_APP_SOSTM (0x000c) +#define U300_TIMER_APP_SOSTM_MODE_CONTINUOUS (0x00000000) +#define U300_TIMER_APP_SOSTM_MODE_ONE_SHOT (0x00000001) +/* OS Timer Status Register 32bit (R/-) */ +#define U300_TIMER_APP_OSTS (0x0010) +#define U300_TIMER_APP_OSTS_TIMER_STATE_MASK (0x0000000F) +#define U300_TIMER_APP_OSTS_TIMER_STATE_IDLE (0x00000001) +#define U300_TIMER_APP_OSTS_TIMER_STATE_ACTIVE (0x00000002) +#define U300_TIMER_APP_OSTS_ENABLE_IND (0x00000010) +#define U300_TIMER_APP_OSTS_MODE_MASK (0x00000020) +#define U300_TIMER_APP_OSTS_MODE_CONTINUOUS (0x00000000) +#define U300_TIMER_APP_OSTS_MODE_ONE_SHOT (0x00000020) +#define U300_TIMER_APP_OSTS_IRQ_ENABLED_IND (0x00000040) +#define U300_TIMER_APP_OSTS_IRQ_PENDING_IND (0x00000080) +/* OS Timer Current Count Register 32bit (R/-) */ +#define U300_TIMER_APP_OSTCC (0x0014) +/* OS Timer Terminal Count Register 32bit (R/W) */ +#define U300_TIMER_APP_OSTTC (0x0018) +/* OS Timer Interrupt Enable Register 32bit (-/W) */ +#define U300_TIMER_APP_OSTIE (0x001c) +#define U300_TIMER_APP_OSTIE_IRQ_DISABLE (0x00000000) +#define U300_TIMER_APP_OSTIE_IRQ_ENABLE (0x00000001) +/* OS Timer Interrupt Acknowledge Register 32bit (-/W) */ +#define U300_TIMER_APP_OSTIA (0x0020) +#define U300_TIMER_APP_OSTIA_IRQ_ACK (0x00000080) + +/* Reset DD Timer 32bit (-/W) */ +#define U300_TIMER_APP_RDDT (0x0040) +#define U300_TIMER_APP_RDDT_TIMER_RESET (0x00000000) +/* Enable DD Timer 32bit (-/W) */ +#define U300_TIMER_APP_EDDT (0x0044) +#define U300_TIMER_APP_EDDT_TIMER_ENABLE (0x00000000) +/* Disable DD Timer 32bit (-/W) */ +#define U300_TIMER_APP_DDDT (0x0048) +#define U300_TIMER_APP_DDDT_TIMER_DISABLE (0x00000000) +/* DD Timer Mode Register 32bit (-/W) */ +#define U300_TIMER_APP_SDDTM (0x004c) +#define U300_TIMER_APP_SDDTM_MODE_CONTINUOUS (0x00000000) +#define U300_TIMER_APP_SDDTM_MODE_ONE_SHOT (0x00000001) +/* DD Timer Status Register 32bit (R/-) */ +#define U300_TIMER_APP_DDTS (0x0050) +#define U300_TIMER_APP_DDTS_TIMER_STATE_MASK (0x0000000F) +#define U300_TIMER_APP_DDTS_TIMER_STATE_IDLE (0x00000001) +#define U300_TIMER_APP_DDTS_TIMER_STATE_ACTIVE (0x00000002) +#define U300_TIMER_APP_DDTS_ENABLE_IND (0x00000010) +#define U300_TIMER_APP_DDTS_MODE_MASK (0x00000020) +#define U300_TIMER_APP_DDTS_MODE_CONTINUOUS (0x00000000) +#define U300_TIMER_APP_DDTS_MODE_ONE_SHOT (0x00000020) +#define U300_TIMER_APP_DDTS_IRQ_ENABLED_IND (0x00000040) +#define U300_TIMER_APP_DDTS_IRQ_PENDING_IND (0x00000080) +/* DD Timer Current Count Register 32bit (R/-) */ +#define U300_TIMER_APP_DDTCC (0x0054) +/* DD Timer Terminal Count Register 32bit (R/W) */ +#define U300_TIMER_APP_DDTTC (0x0058) +/* DD Timer Interrupt Enable Register 32bit (-/W) */ +#define U300_TIMER_APP_DDTIE (0x005c) +#define U300_TIMER_APP_DDTIE_IRQ_DISABLE (0x00000000) +#define U300_TIMER_APP_DDTIE_IRQ_ENABLE (0x00000001) +/* DD Timer Interrupt Acknowledge Register 32bit (-/W) */ +#define U300_TIMER_APP_DDTIA (0x0060) +#define U300_TIMER_APP_DDTIA_IRQ_ACK (0x00000080) + +/* Reset GP1 Timer 32bit (-/W) */ +#define U300_TIMER_APP_RGPT1 (0x0080) +#define U300_TIMER_APP_RGPT1_TIMER_RESET (0x00000000) +/* Enable GP1 Timer 32bit (-/W) */ +#define U300_TIMER_APP_EGPT1 (0x0084) +#define U300_TIMER_APP_EGPT1_TIMER_ENABLE (0x00000000) +/* Disable GP1 Timer 32bit (-/W) */ +#define U300_TIMER_APP_DGPT1 (0x0088) +#define U300_TIMER_APP_DGPT1_TIMER_DISABLE (0x00000000) +/* GP1 Timer Mode Register 32bit (-/W) */ +#define U300_TIMER_APP_SGPT1M (0x008c) +#define U300_TIMER_APP_SGPT1M_MODE_CONTINUOUS (0x00000000) +#define U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT (0x00000001) +/* GP1 Timer Status Register 32bit (R/-) */ +#define U300_TIMER_APP_GPT1S (0x0090) +#define U300_TIMER_APP_GPT1S_TIMER_STATE_MASK (0x0000000F) +#define U300_TIMER_APP_GPT1S_TIMER_STATE_IDLE (0x00000001) +#define U300_TIMER_APP_GPT1S_TIMER_STATE_ACTIVE (0x00000002) +#define U300_TIMER_APP_GPT1S_ENABLE_IND (0x00000010) +#define U300_TIMER_APP_GPT1S_MODE_MASK (0x00000020) +#define U300_TIMER_APP_GPT1S_MODE_CONTINUOUS (0x00000000) +#define U300_TIMER_APP_GPT1S_MODE_ONE_SHOT (0x00000020) +#define U300_TIMER_APP_GPT1S_IRQ_ENABLED_IND (0x00000040) +#define U300_TIMER_APP_GPT1S_IRQ_PENDING_IND (0x00000080) +/* GP1 Timer Current Count Register 32bit (R/-) */ +#define U300_TIMER_APP_GPT1CC (0x0094) +/* GP1 Timer Terminal Count Register 32bit (R/W) */ +#define U300_TIMER_APP_GPT1TC (0x0098) +/* GP1 Timer Interrupt Enable Register 32bit (-/W) */ +#define U300_TIMER_APP_GPT1IE (0x009c) +#define U300_TIMER_APP_GPT1IE_IRQ_DISABLE (0x00000000) +#define U300_TIMER_APP_GPT1IE_IRQ_ENABLE (0x00000001) +/* GP1 Timer Interrupt Acknowledge Register 32bit (-/W) */ +#define U300_TIMER_APP_GPT1IA (0x00a0) +#define U300_TIMER_APP_GPT1IA_IRQ_ACK (0x00000080) + +/* Reset GP2 Timer 32bit (-/W) */ +#define U300_TIMER_APP_RGPT2 (0x00c0) +#define U300_TIMER_APP_RGPT2_TIMER_RESET (0x00000000) +/* Enable GP2 Timer 32bit (-/W) */ +#define U300_TIMER_APP_EGPT2 (0x00c4) +#define U300_TIMER_APP_EGPT2_TIMER_ENABLE (0x00000000) +/* Disable GP2 Timer 32bit (-/W) */ +#define U300_TIMER_APP_DGPT2 (0x00c8) +#define U300_TIMER_APP_DGPT2_TIMER_DISABLE (0x00000000) +/* GP2 Timer Mode Register 32bit (-/W) */ +#define U300_TIMER_APP_SGPT2M (0x00cc) +#define U300_TIMER_APP_SGPT2M_MODE_CONTINUOUS (0x00000000) +#define U300_TIMER_APP_SGPT2M_MODE_ONE_SHOT (0x00000001) +/* GP2 Timer Status Register 32bit (R/-) */ +#define U300_TIMER_APP_GPT2S (0x00d0) +#define U300_TIMER_APP_GPT2S_TIMER_STATE_MASK (0x0000000F) +#define U300_TIMER_APP_GPT2S_TIMER_STATE_IDLE (0x00000001) +#define U300_TIMER_APP_GPT2S_TIMER_STATE_ACTIVE (0x00000002) +#define U300_TIMER_APP_GPT2S_ENABLE_IND (0x00000010) +#define U300_TIMER_APP_GPT2S_MODE_MASK (0x00000020) +#define U300_TIMER_APP_GPT2S_MODE_CONTINUOUS (0x00000000) +#define U300_TIMER_APP_GPT2S_MODE_ONE_SHOT (0x00000020) +#define U300_TIMER_APP_GPT2S_IRQ_ENABLED_IND (0x00000040) +#define U300_TIMER_APP_GPT2S_IRQ_PENDING_IND (0x00000080) +/* GP2 Timer Current Count Register 32bit (R/-) */ +#define U300_TIMER_APP_GPT2CC (0x00d4) +/* GP2 Timer Terminal Count Register 32bit (R/W) */ +#define U300_TIMER_APP_GPT2TC (0x00d8) +/* GP2 Timer Interrupt Enable Register 32bit (-/W) */ +#define U300_TIMER_APP_GPT2IE (0x00dc) +#define U300_TIMER_APP_GPT2IE_IRQ_DISABLE (0x00000000) +#define U300_TIMER_APP_GPT2IE_IRQ_ENABLE (0x00000001) +/* GP2 Timer Interrupt Acknowledge Register 32bit (-/W) */ +#define U300_TIMER_APP_GPT2IA (0x00e0) +#define U300_TIMER_APP_GPT2IA_IRQ_ACK (0x00000080) + +/* Clock request control register - all four timers */ +#define U300_TIMER_APP_CRC (0x100) +#define U300_TIMER_APP_CRC_CLOCK_REQUEST_ENABLE (0x00000001) + +#define TICKS_PER_JIFFY ((CLOCK_TICK_RATE + (HZ/2)) / HZ) +#define US_PER_TICK ((1000000 + (HZ/2)) / HZ) + +/* + * The u300_set_mode() function is always called first, if we + * have oneshot timer active, the oneshot scheduling function + * u300_set_next_event() is called immediately after. + */ +static void u300_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + /* Disable interrupts on GPT1 */ + writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, + U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE); + /* Disable GP1 while we're reprogramming it. */ + writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, + U300_TIMER_APP_VBASE + U300_TIMER_APP_DGPT1); + /* + * Set the periodic mode to a certain number of ticks per + * jiffy. + */ + writel(TICKS_PER_JIFFY, + U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1TC); + /* + * Set continuous mode, so the timer keeps triggering + * interrupts. + */ + writel(U300_TIMER_APP_SGPT1M_MODE_CONTINUOUS, + U300_TIMER_APP_VBASE + U300_TIMER_APP_SGPT1M); + /* Enable timer interrupts */ + writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE, + U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE); + /* Then enable the OS timer again */ + writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE, + U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT1); + break; + case CLOCK_EVT_MODE_ONESHOT: + /* Just break; here? */ + /* + * The actual event will be programmed by the next event hook, + * so we just set a dummy value somewhere at the end of the + * universe here. + */ + /* Disable interrupts on GPT1 */ + writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, + U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE); + /* Disable GP1 while we're reprogramming it. */ + writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, + U300_TIMER_APP_VBASE + U300_TIMER_APP_DGPT1); + /* + * Expire far in the future, u300_set_next_event() will be + * called soon... + */ + writel(0xFFFFFFFF, U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1TC); + /* We run one shot per tick here! */ + writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT, + U300_TIMER_APP_VBASE + U300_TIMER_APP_SGPT1M); + /* Enable interrupts for this timer */ + writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE, + U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE); + /* Enable timer */ + writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE, + U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT1); + break; + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + /* Disable interrupts on GP1 */ + writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, + U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE); + /* Disable GP1 */ + writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, + U300_TIMER_APP_VBASE + U300_TIMER_APP_DGPT1); + break; + case CLOCK_EVT_MODE_RESUME: + /* Ignore this call */ + break; + } +} + +/* + * The app timer in one shot mode obviously has to be reprogrammed + * in EXACTLY this sequence to work properly. Do NOT try to e.g. replace + * the interrupt disable + timer disable commands with a reset command, + * it will fail miserably. Apparently (and I found this the hard way) + * the timer is very sensitive to the instruction order, though you don't + * get that impression from the data sheet. + */ +static int u300_set_next_event(unsigned long cycles, + struct clock_event_device *evt) + +{ + /* Disable interrupts on GPT1 */ + writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE, + U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE); + /* Disable GP1 while we're reprogramming it. */ + writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE, + U300_TIMER_APP_VBASE + U300_TIMER_APP_DGPT1); + /* Reset the General Purpose timer 1. */ + writel(U300_TIMER_APP_RGPT1_TIMER_RESET, + U300_TIMER_APP_VBASE + U300_TIMER_APP_RGPT1); + /* IRQ in n * cycles */ + writel(cycles, U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1TC); + /* + * We run one shot per tick here! (This is necessary to reconfigure, + * the timer will tilt if you don't!) + */ + writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT, + U300_TIMER_APP_VBASE + U300_TIMER_APP_SGPT1M); + /* Enable timer interrupts */ + writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE, + U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IE); + /* Then enable the OS timer again */ + writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE, + U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT1); + return 0; +} + + +/* Use general purpose timer 1 as clock event */ +static struct clock_event_device clockevent_u300_1mhz = { + .name = "GPT1", + .rating = 300, /* Reasonably fast and accurate clock event */ + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + /* 22 calculated using the algorithm in arch/mips/kernel/time.c */ + .shift = 22, + .set_next_event = u300_set_next_event, + .set_mode = u300_set_mode, +}; + +/* Clock event timer interrupt handler */ +static irqreturn_t u300_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = &clockevent_u300_1mhz; + /* ACK/Clear timer IRQ for the APP GPT1 Timer */ + writel(U300_TIMER_APP_GPT1IA_IRQ_ACK, + U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT1IA); + evt->event_handler(evt); + return IRQ_HANDLED; +} + +static struct irqaction u300_timer_irq = { + .name = "U300 Timer Tick", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = u300_timer_interrupt, +}; + +/* Use general purpose timer 2 as clock source */ +static cycle_t u300_get_cycles(void) +{ + return (cycles_t) readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC); +} + +static struct clocksource clocksource_u300_1mhz = { + .name = "GPT2", + .rating = 300, /* Reasonably fast and accurate clock source */ + .read = u300_get_cycles, + .mask = CLOCKSOURCE_MASK(32), /* 32 bits */ + /* 22 calculated using the algorithm in arch/mips/kernel/time.c */ + .shift = 22, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + + +/* + * This sets up the system timers, clock source and clock event. + */ +static void __init u300_timer_init(void) +{ + u300_enable_timer_clock(); + /* + * Disable the "OS" and "DD" timers - these are designed for Symbian! + * Example usage in cnh1601578 cpu subsystem pd_timer_app.c + */ + writel(U300_TIMER_APP_CRC_CLOCK_REQUEST_ENABLE, + U300_TIMER_APP_VBASE + U300_TIMER_APP_CRC); + writel(U300_TIMER_APP_ROST_TIMER_RESET, + U300_TIMER_APP_VBASE + U300_TIMER_APP_ROST); + writel(U300_TIMER_APP_DOST_TIMER_DISABLE, + U300_TIMER_APP_VBASE + U300_TIMER_APP_DOST); + writel(U300_TIMER_APP_RDDT_TIMER_RESET, + U300_TIMER_APP_VBASE + U300_TIMER_APP_RDDT); + writel(U300_TIMER_APP_DDDT_TIMER_DISABLE, + U300_TIMER_APP_VBASE + U300_TIMER_APP_DDDT); + + /* Reset the General Purpose timer 1. */ + writel(U300_TIMER_APP_RGPT1_TIMER_RESET, + U300_TIMER_APP_VBASE + U300_TIMER_APP_RGPT1); + + /* Set up the IRQ handler */ + setup_irq(IRQ_U300_TIMER_APP_GP1, &u300_timer_irq); + + /* Reset the General Purpose timer 2 */ + writel(U300_TIMER_APP_RGPT2_TIMER_RESET, + U300_TIMER_APP_VBASE + U300_TIMER_APP_RGPT2); + /* Set this timer to run around forever */ + writel(0xFFFFFFFFU, U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2TC); + /* Set continuous mode so it wraps around */ + writel(U300_TIMER_APP_SGPT2M_MODE_CONTINUOUS, + U300_TIMER_APP_VBASE + U300_TIMER_APP_SGPT2M); + /* Disable timer interrupts */ + writel(U300_TIMER_APP_GPT2IE_IRQ_DISABLE, + U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2IE); + /* Then enable the GP2 timer to use as a free running us counter */ + writel(U300_TIMER_APP_EGPT2_TIMER_ENABLE, + U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT2); + + /* This is a pure microsecond clock source */ + clocksource_u300_1mhz.mult = + clocksource_khz2mult(1000, clocksource_u300_1mhz.shift); + if (clocksource_register(&clocksource_u300_1mhz)) + printk(KERN_ERR "timer: failed to initialize clock " + "source %s\n", clocksource_u300_1mhz.name); + + clockevent_u300_1mhz.mult = + div_sc(1000000, NSEC_PER_SEC, clockevent_u300_1mhz.shift); + /* 32bit counter, so 32bits delta is max */ + clockevent_u300_1mhz.max_delta_ns = + clockevent_delta2ns(0xffffffff, &clockevent_u300_1mhz); + /* This timer is slow enough to set for 1 cycle == 1 MHz */ + clockevent_u300_1mhz.min_delta_ns = + clockevent_delta2ns(1, &clockevent_u300_1mhz); + clockevent_u300_1mhz.cpumask = cpumask_of(0); + clockevents_register_device(&clockevent_u300_1mhz); + /* + * TODO: init and register the rest of the timers too, they can be + * used by hrtimers! + */ +} + +/* + * Very simple system timer that only register the clock event and + * clock source. + */ +struct sys_timer u300_timer = { + .init = u300_timer_init, +}; diff --git a/arch/arm/mach-u300/u300.c b/arch/arm/mach-u300/u300.c new file mode 100644 index 00000000000..d2a0b8847a1 --- /dev/null +++ b/arch/arm/mach-u300/u300.c @@ -0,0 +1,55 @@ +/* + * + * arch/arm/mach-u300/u300.c + * + * + * Copyright (C) 2006-2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * Platform machine definition. + * Author: Linus Walleij + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void __init u300_init_machine(void) +{ + u300_init_devices(); +} + +#ifdef CONFIG_MACH_U300_BS2X +#define MACH_U300_STRING "Ericsson AB U300 S25/S26/B25/B26 Prototype Board" +#endif + +#ifdef CONFIG_MACH_U300_BS330 +#define MACH_U300_STRING "Ericsson AB U330 S330/B330 Prototype Board" +#endif + +#ifdef CONFIG_MACH_U300_BS335 +#define MACH_U300_STRING "Ericsson AB U335 S335/B335 Prototype Board" +#endif + +#ifdef CONFIG_MACH_U300_BS365 +#define MACH_U300_STRING "Ericsson AB U365 S365/B365 Prototype Board" +#endif + +MACHINE_START(U300, MACH_U300_STRING) + /* Maintainer: Linus Walleij */ + .phys_io = U300_AHB_PER_PHYS_BASE, + .io_pg_offst = ((U300_AHB_PER_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = BOOT_PARAMS_OFFSET, + .map_io = u300_map_io, + .init_irq = u300_init_irq, + .timer = &u300_timer, + .init_machine = u300_init_machine, +MACHINE_END -- cgit v1.2.3 From f7a9a4d782628b4bd2392d931b95bd49732a2918 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 8 May 2009 08:59:51 +0100 Subject: [ARM] 5510/1: U300 GPIO debug and init fixes This moves the GPIO driver away from using __devinit and __devexit It also removes all printk() in favor of using dev_* print macros on pdev->dev struct instead. Surplus prints are removed, and the platform_device_probe() function is used instead of putting a .probe function in the platform driver struct. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-u300/gpio.c | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) (limited to 'arch/arm/mach-u300') diff --git a/arch/arm/mach-u300/gpio.c b/arch/arm/mach-u300/gpio.c index 2d5ae8ecb8c..308cdb197a9 100644 --- a/arch/arm/mach-u300/gpio.c +++ b/arch/arm/mach-u300/gpio.c @@ -36,6 +36,7 @@ static struct clk *clk; /* Memory resource */ static struct resource *memres; static void __iomem *virtbase; +static struct device *gpiodev; struct u300_gpio_port { const char *name; @@ -264,8 +265,8 @@ static struct gpio_struct gpio_pin[U300_GPIO_MAX]; int gpio_register_callback(unsigned gpio, int (*func)(void *arg), void *data) { if (gpio_pin[gpio].callback) - printk(KERN_WARNING "GPIO: %s: WARNING: callback already " \ - "registered for gpio pin#%d\n", __func__, gpio); + dev_warn(gpiodev, "%s: WARNING: callback already " + "registered for gpio pin#%d\n", __func__, gpio); gpio_pin[gpio].callback = func; gpio_pin[gpio].data = data; @@ -276,8 +277,8 @@ EXPORT_SYMBOL(gpio_register_callback); int gpio_unregister_callback(unsigned gpio) { if (!gpio_pin[gpio].callback) - printk(KERN_WARNING "GPIO: %s: WARNING: callback already " \ - "unregistered for gpio pin#%d\n", __func__, gpio); + dev_warn(gpiodev, "%s: WARNING: callback already " + "unregistered for gpio pin#%d\n", __func__, gpio); gpio_pin[gpio].callback = NULL; gpio_pin[gpio].data = NULL; @@ -303,8 +304,8 @@ void gpio_free(unsigned gpio) gpio_users--; gpio_pin[gpio].users--; if (unlikely(gpio_pin[gpio].users < 0)) { - printk(KERN_WARNING "GPIO: Warning: gpio#%d release mismatch\n", - gpio); + dev_warn(gpiodev, "warning: gpio#%d release mismatch\n", + gpio); gpio_pin[gpio].users = 0; } @@ -492,7 +493,7 @@ static irqreturn_t gpio_irq_handler(int irq, void *dev_id) if (gpio_pin[gpio].callback) (void)gpio_pin[gpio].callback(gpio_pin[gpio].data); else - printk(KERN_DEBUG "GPIO: Stray GPIO IRQ on line %d\n", + dev_dbg(gpiodev, "stray GPIO IRQ on line %d\n", gpio); } return IRQ_HANDLED; @@ -548,25 +549,26 @@ static void gpio_set_initial_values(void) #endif } -static int __devinit gpio_probe(struct platform_device *pdev) +static int __init gpio_probe(struct platform_device *pdev) { u32 val; int err = 0; int i; int num_irqs; + gpiodev = &pdev->dev; memset(gpio_pin, 0, sizeof(gpio_pin)); /* Get GPIO clock */ clk = clk_get(&pdev->dev, NULL); if (IS_ERR(clk)) { err = PTR_ERR(clk); - printk(KERN_ERR "GPIO: could not get GPIO clock\n"); + dev_err(gpiodev, "could not get GPIO clock\n"); goto err_no_clk; } err = clk_enable(clk); if (err) { - printk(KERN_ERR "GPIO: could not enable GPIO clock\n"); + dev_err(gpiodev, "could not enable GPIO clock\n"); goto err_no_clk_enable; } @@ -580,22 +582,24 @@ static int __devinit gpio_probe(struct platform_device *pdev) goto err_no_ioregion; } - virtbase = ioremap(memres->start, memres->end - memres->start + 1); + virtbase = ioremap(memres->start, resource_size(memres)); if (!virtbase) { err = -ENOMEM; goto err_no_ioremap; } + dev_info(gpiodev, "remapped 0x%08x to %p\n", + memres->start, virtbase); #ifdef U300_COH901335 - printk(KERN_INFO "GPIO: Initializing GPIO Controller COH 901 335\n"); + dev_info(gpiodev, "initializing GPIO Controller COH 901 335\n"); /* Turn on the GPIO block */ writel(U300_GPIO_CR_BLOCK_CLOCK_ENABLE, virtbase + U300_GPIO_CR); #endif #ifdef U300_COH901571_3 - printk(KERN_INFO "GPIO: Initializing GPIO Controller COH 901 571/3\n"); + dev_info(gpiodev, "initializing GPIO Controller COH 901 571/3\n"); val = readl(virtbase + U300_GPIO_CR); - printk(KERN_INFO "GPIO: COH901571/3 block version: %d, " \ + dev_info(gpiodev, "COH901571/3 block version: %d, " \ "number of cores: %d\n", ((val & 0x0000FE00) >> 9), ((val & 0x000001FC) >> 2)); @@ -623,15 +627,14 @@ static int __devinit gpio_probe(struct platform_device *pdev) gpio_ports[num_irqs].name, &gpio_ports[num_irqs]); if (err) { - printk(KERN_CRIT "GPIO: Cannot allocate IRQ for %s!\n", - gpio_ports[num_irqs].name); + dev_err(gpiodev, "cannot allocate IRQ for %s!\n", + gpio_ports[num_irqs].name); goto err_no_irq; } /* Turns off PortX_irq_force */ writel(0x0, virtbase + U300_GPIO_PXIFR + num_irqs * U300_GPIO_PORTX_SPACING); } - printk(KERN_INFO "GPIO: U300 gpio module loaded\n"); return 0; @@ -647,11 +650,11 @@ static int __devinit gpio_probe(struct platform_device *pdev) err_no_clk_enable: clk_put(clk); err_no_clk: - printk(KERN_INFO "GPIO: module ERROR:%d\n", err); + dev_info(gpiodev, "module ERROR:%d\n", err); return err; } -static int __devexit gpio_remove(struct platform_device *pdev) +static int __exit gpio_remove(struct platform_device *pdev) { int i; @@ -670,14 +673,13 @@ static struct platform_driver gpio_driver = { .driver = { .name = "u300-gpio", }, - .probe = gpio_probe, - .remove = __devexit_p(gpio_remove), + .remove = __exit_p(gpio_remove), }; static int __init u300_gpio_init(void) { - return platform_driver_register(&gpio_driver); + return platform_driver_probe(&gpio_driver, gpio_probe); } static void __exit u300_gpio_exit(void) -- cgit v1.2.3 From ed31b2dfad01d23446860c983ff94460d7971c48 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 31 May 2009 15:08:11 +0100 Subject: [ARM] make U300 clk_set_rate() return a _real_ errno Another stupid instance of "return -1"-ism. Signed-off-by: Russell King --- arch/arm/mach-u300/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/mach-u300') diff --git a/arch/arm/mach-u300/clock.c b/arch/arm/mach-u300/clock.c index d6f8232757f..5cd04d6751b 100644 --- a/arch/arm/mach-u300/clock.c +++ b/arch/arm/mach-u300/clock.c @@ -682,7 +682,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate) } else { printk(KERN_ERR "clock: Failed to set %s to %ld hz\n", clk->name, rate); - return -1; + return -EINVAL; } } EXPORT_SYMBOL(clk_set_rate); -- cgit v1.2.3 From 7666c17e2b0986a079da46122d8658544416c2cf Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 1 Jun 2009 14:27:26 +0100 Subject: [ARM] 5535/1: U300 Makefile.boot The Makefile.boot file for the U300 port. This will compile the kernel for different ZRELADDR depending on the location of physical RAM in the chosen configuration. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/mach-u300/Makefile.boot | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 arch/arm/mach-u300/Makefile.boot (limited to 'arch/arm/mach-u300') diff --git a/arch/arm/mach-u300/Makefile.boot b/arch/arm/mach-u300/Makefile.boot new file mode 100644 index 00000000000..6fbfc6ea2d3 --- /dev/null +++ b/arch/arm/mach-u300/Makefile.boot @@ -0,0 +1,15 @@ +# Note: the following conditions must always be true: +# ZRELADDR == virt_to_phys(TEXTADDR) +# PARAMS_PHYS must be within 4MB of ZRELADDR +# INITRD_PHYS must be in RAM + +ifdef CONFIG_MACH_U300_SINGLE_RAM + zreladdr-y := 0x28E08000 + params_phys-y := 0x28E00100 +else + zreladdr-y := 0x48008000 + params_phys-y := 0x48000100 +endif + +# This isn't used. +#initrd_phys-y := 0x29800000 -- cgit v1.2.3