* [PATCH 3/6] U6715 gpio platform driver This driver is U6 platform generic (V2)
2010-04-28 7:32 U6/U6715 ARM architecture files, 1rst try Philippe Langlais
@ 2010-04-28 7:32 ` Philippe Langlais
0 siblings, 0 replies; 17+ messages in thread
From: Philippe Langlais @ 2010-04-28 7:32 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Philippe Langlais <philippe.langlais@stericsson.com>
---
arch/arm/mach-u67xx/board_u67xx_wavex.c | 469 ++++++++++++++++++++
arch/arm/mach-u67xx/devices.c | 12 +-
arch/arm/plat-u6xxx/Makefile | 2 +-
arch/arm/plat-u6xxx/gpio.c | 716 +++++++++++++++++++++++++++++++
arch/arm/plat-u6xxx/include/mach/gpio.h | 396 +++++++++++++++++
5 files changed, 1588 insertions(+), 7 deletions(-)
create mode 100644 arch/arm/plat-u6xxx/gpio.c
create mode 100644 arch/arm/plat-u6xxx/include/mach/gpio.h
diff --git a/arch/arm/mach-u67xx/board_u67xx_wavex.c b/arch/arm/mach-u67xx/board_u67xx_wavex.c
index edfb983..d2f4db0 100644
--- a/arch/arm/mach-u67xx/board_u67xx_wavex.c
+++ b/arch/arm/mach-u67xx/board_u67xx_wavex.c
@@ -24,6 +24,474 @@
#include <asm/mach/arch.h>
#include <mach/irqs.h>
#include <mach/timer.h>
+#include <mach/gpio.h>
+
+#include <mach/scon.h>
+
+/**
+ * SCON initial settings
+ * Allows to define the PIN multiplexing for all the platform (Linux and Modem)
+ */
+struct u6_scon_config u6_scon_init_config[SCON_REGISTER_NB] = {
+ {
+ (void __iomem *) SCON_SYSMUX0_REG,
+ 0 |
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A0 & 0xF))) | /* FM IRQ */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_A1 & 0xF))) | /* UART 2 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_A2 & 0xF))) | /* UART 2 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A3 & 0xF))) |
+ (GPIO_MODE_MUX3 << (2 * (GPIO_A4 & 0xF))) | /* SIMOFF_copy for modem */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A5 & 0xF))) | /* for AGPS */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A6 & 0xF))) | /* LCD backlight
+ -> ressource backligth*/
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A7 & 0xF))) | /* Bluetooth */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A8 & 0xF))) | /* Reserved for mode DPWS*/
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A9 & 0xF))) | /* Reserved for mode DPWS*/
+ (GPIO_MODE_MUX1 << (2 * (GPIO_A10 & 0xF))) | /* UART2 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_A11 & 0xF))) | /* UART2 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_A12 & 0xF))) | /* UART 1, configured
+ by boot, don't touch */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A13 & 0xF))) | /* free */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A14 & 0xF))) | /* PMU irq */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A15 & 0xF)))
+ },
+ {
+ (void __iomem *) SCON_SYSMUX1_REG,
+ 0 |
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A16 & 0xF))) | /* FCI data 3 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A17 & 0xF))) | /* free */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A18 & 0xF))) | /* FCI data 2 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A19 & 0xF))) | /* FCI data 1 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A20 & 0xF))) | /* Cam Ligth copy */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A21 & 0xF))) | /* RF on -> GPIO */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_A22 & 0xF))) | /* RF RF_DPN */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A23 & 0xF))) | /* RF reset -> GPIO */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A24 & 0xF))) | /* AGPS reset */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A25 & 0xF))) | /* AGPS wake up */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A26 & 0xF))) | /* free */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A27 & 0xF))) | /* SPI1 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A28 & 0xF))) | /* SPI1 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_A29 & 0xF))) | /* Audio IIS */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A30 & 0xF))) | /* AGPS pwr on */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A31 & 0xF))) /* free */
+ },
+ {
+ (void __iomem *) SCON_SYSMUX2_REG,
+ 0 |
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B0 & 0xF))) | /* RF DD */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B1 & 0xF))) | /* RF DU */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B2 & 0xF))) | /* RF FSC */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B3 & 0xF))) | /* RF DCL */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B4 & 0xF))) | /* UART RTS1 -> console */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B5 & 0xF))) | /* UART TXD1 -> console */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B6 & 0xF))) | /* NFI ready -> for NFI */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B7 & 0xF))) | /* VDE_EOFI -> VDE already
+ configured by splashscreen */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B8 & 0xF))) | /* RFEN0 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_B9 & 0xF))) | /* FCICMD -> for FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_B10 & 0xF))) | /* FCICLK -> for FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_B11 & 0xF))) | /* FCIDATA0 -> for FCI */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B12 & 0xF))) | /* RFSIG6 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B13 & 0xF))) | /* RFSIG7 */
+ (GPIO_MODE_MUX3 << (2 * (GPIO_B14 & 0xF))) |
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B15 & 0xF))) /* RFDATA */
+ },
+ {
+ (void __iomem *) SCON_SYSMUX3_REG,
+ 0
+ },
+ {
+ (void __iomem *) SCON_SYSMUX4_REG,
+ 0 |
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C0 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C1 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C2 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C3 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C4 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C5 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C6 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C7 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C8 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C9 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C10 & 0xF))) | /* VDE */
+#ifdef CONFIG_EBI_BUS
+ (GPIO_MODE_MUX2 << (2 * (GPIO_C11 & 0xF))) | /* EBI_CS0 */
+#else
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C11 & 0xF))) | /* VDE */
+#endif
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C12 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C13 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C14 & 0xF))) | /* KCOL0 -> keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C15 & 0xF))) /* KCOL1 -> keypad */
+
+ },
+ {
+ (void __iomem *) SCON_SYSMUX5_REG,
+ 0 |
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C16 & 0xF))) | /* KCOL2 -> keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C17 & 0xF))) | /* KCOL3 -> keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C18 & 0xF))) | /* KCOL4 -> keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C19 & 0xF))) | /* KROW0 -> keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C20 & 0xF))) | /* KROW1 -> keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C21 & 0xF))) | /* KROW2 -> keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C22 & 0xF))) | /* KROW3 -> keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C23 & 0xF))) | /* KROW4 -> keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C24 & 0xF))) | /* RF3GSPIEN0 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C25 & 0xF))) | /* RF3GSPIDATA */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C26 & 0xF))) | /* RF3GSPICLK */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C27 & 0xF))) | /* RFSM_OUT0 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C28 & 0xF))) | /* RFSM_OUT1 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C29 & 0xF))) | /* RFSM_OUT2 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_C30 & 0xF))) | /* I2C -> ressource */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_C31 & 0xF))) /* I2C -> ressource */
+ },
+ {
+ (void __iomem *) SCON_SYSMUX6_REG,
+ 0 |
+ (GPIO_MODE_MUX1 << (2 * (GPIO_D0 & 0xF))) | /* CAM PWRDN1 -> CAM */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D1 & 0xF))) | /* CAM DATA 0 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D2 & 0xF))) | /* CAM DATA 1 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D3 & 0xF))) | /* CAM DATA 2 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D4 & 0xF))) | /* CAM DATA 3 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D5 & 0xF))) | /* CAM DATA 4 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D6 & 0xF))) | /* CAM DATA 5 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D7 & 0xF))) | /* CAM DATA 6 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D8 & 0xF))) | /* CAM DATA 7 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D9 & 0xF))) | /* CAM DATA 8 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D10 & 0xF))) | /* CAM DATA 9 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D11 & 0xF))) | /* CAMVS */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D12 & 0xF))) | /* CAMHS */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D13 & 0xF))) | /* CAMCLKI */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D14 & 0xF))) | /* CAMCLKO */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_D15 & 0xF))) /* VDDC2EN */
+ },
+ {
+ (void __iomem *) SCON_SYSMUX7_REG,
+ 0 |
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D16 & 0xF))) | /* RF3GGPO9 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D17 & 0xF))) | /* RF3GGPO8 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_D18 & 0xF))) | /* FCI card detect, FCI */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_D19 & 0xF))) | /* CAM_Prelight copy, CAM*/
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D20 & 0xF))) | /* UART1 RXD1 -> Console */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D21 & 0xF))) | /* DIISWS */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D22 & 0xF))) | /* DIISSDO */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D23 & 0xF))) | /* DIISCK */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_D24 & 0xF))) | /* GPIOD24 ->FM Reset */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_D25 & 0xF))) | /* RFSIG3 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D26 & 0xF))) | /* RF3GGPO6 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D27 & 0xF))) | /* RF3GGPO7 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D28 & 0xF))) | /* RF3GGPO5 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_D29 & 0xF))) | /* GPIOD29 USB suspend */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D30 & 0xF))) | /* RF3GGPO4 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D31 & 0xF))) /* RFCLK */
+ },
+#ifdef CONFIG_MACH_U67XX_V2_WAVEB_2GB
+{
+ (void __iomem *) SCON_SYSMUX8_REG,
+ 0 |
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E0 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E1 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E2 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E3 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E4 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E5 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E6 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E7 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E8 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E9 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E10 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E11 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E12 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E13 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E14 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E15 & 0xF))) /* DEBUG */
+ },
+ {
+ (void __iomem *) SCON_SYSMUX9_REG,
+ 0 |
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E16 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E17 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E18 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E19 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E20 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E21 & 0xF))) | /* SDATO2 -> SPI2 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E22 & 0xF))) | /* SDATIN2 -> SPI2 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E23 & 0xF))) | /* SCLK2 -> SPI2 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E24 & 0xF))) | /* FCI_copy -> FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E25 & 0xF))) | /* FCI_copy -> FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E26 & 0xF))) | /* FCI_copy -> FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E27 & 0xF))) | /* FCI_copy -> FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E28 & 0xF))) | /* FCI_copy -> FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E29 & 0xF))) | /* FCI_copy
+ -> FCI USB suspend */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E30 & 0xF))) | /* RFSM_OUT3 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E31 & 0xF))) /* GPIO CAM */
+ },
+#else
+{
+ (void __iomem *) SCON_SYSMUX8_REG,
+ 0 |
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E0 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E1 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E2 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E3 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E4 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E5 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E6 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E7 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E8 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E9 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E10 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E11 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E12 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E13 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E14 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E15 & 0xF))) /* DEBUG */
+ },
+ {
+ (void __iomem *) SCON_SYSMUX9_REG,
+ 0 |
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E16 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E17 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E18 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E19 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E20 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E21 & 0xF))) | /* SDATO2 -> SPI2 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E22 & 0xF))) | /* SDATIN2 -> SPI2 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E23 & 0xF))) | /* SCLK2 -> SPI2 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E24 & 0xF))) | /* FCI_copy -> FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E25 & 0xF))) | /* FCI_copy -> FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E26 & 0xF))) | /* FCI_copy -> FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E27 & 0xF))) | /* FCI_copy -> FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E28 & 0xF))) | /* FCI_copy -> FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E29 & 0xF))) | /* FCI_copy
+ -> FCI USB suspend */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E30 & 0xF))) | /* RFSM_OUT3 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E31 & 0xF))) /* GPIO CAM */
+ },
+
+#endif
+ {
+ (void __iomem *) SCON_SYSMUX10_REG,
+ 0 |
+#ifdef CONFIG_EBI_BUS
+ (GPIO_MODE_MUX3 << (2 * (GPIO_F0 & 0xF))) | /* EBI_IO0_copy */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F1 & 0xF))) | /* EBI_OE_RW_copy */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F2 & 0xF))) | /* EBI_WE_E_copy */
+#else
+ (GPIO_MODE_MUX1 << (2 * (GPIO_F0 & 0xF))) | /* CAM_PWR_REG -> CAM */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_F1 & 0xF))) | /* AGPS FRAME_SYNC, AGPS */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F2 & 0xF))) | /* free */
+#endif
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F3 & 0xF))) | /* KCOL5 -> Keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F4 & 0xF))) | /* KCOL6 -> Keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F5 & 0xF))) | /* KCOL7 -> Keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F6 & 0xF))) | /* KROW5 -> Keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F7 & 0xF))) | /* KROW6 -> Keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F8 & 0xF))) | /* KROW7 -> Keypad */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_F9 & 0xF))) | /* eMMC_PDn -> FCI */
+#ifdef CONFIG_EBI_BUS
+ (GPIO_MODE_MUX3 << (2 * (GPIO_F10 & 0xF))) | /* VDE_CS0_copy */
+ (GPIO_MODE_MUX3 << (2 * (GPIO_F11 & 0xF))) | /* EBI_IO1_copy */
+ (GPIO_MODE_MUX3 << (2 * (GPIO_F12 & 0xF))) | /* EBI_IO2_copy */
+ (GPIO_MODE_MUX3 << (2 * (GPIO_F13 & 0xF))) | /* EBI_IO3_copy */
+ (GPIO_MODE_MUX3 << (2 * (GPIO_F14 & 0xF))) | /* EBI_IO4_copy */
+ (GPIO_MODE_MUX3 << (2 * (GPIO_F15 & 0xF))) /* EBI_IO5_copy */
+#else
+ (GPIO_MODE_MUX3 << (2 * (GPIO_F10 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F11 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F12 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F13 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F14 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F15 & 0xF))) /* VDE */
+#endif
+ },
+ {
+ (void __iomem *) SCON_SYSMUX11_REG,
+ 0 |
+#ifdef CONFIG_EBI_BUS
+ (GPIO_MODE_MUX3 << (2 * (GPIO_F16 & 0xF))) | /* EBI_IO6_copy */
+ (GPIO_MODE_MUX3 << (2 * (GPIO_F17 & 0xF))) | /* EBI_IO7_copy */
+#else
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F16 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F17 & 0xF))) | /* VDE */
+#endif
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F18 & 0xF))) /* NFI_CE_n -> NFI */
+ },
+ /* Configure PAD Value */
+ {
+ (void __iomem *) SCON_SYSPAD0_REG,
+ 0 |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A0 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A1 & 0xF))) |
+ (SCON_PAD_PLAIN_INPUT << (2 * (GPIO_A2 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A3 & 0xF))) |
+ (SCON_PAD_PLAIN_INPUT << (2 * (GPIO_A4 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A5 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A6 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A7 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A8 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A9 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A10 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A11 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A12 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A13 & 0xF))) |
+ (SCON_PAD_PLAIN_INPUT << (2 * (GPIO_A14 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A15 & 0xF)))
+ },
+ {
+ (void __iomem *) SCON_SYSPAD1_REG,
+ 0 |
+ (SCON_PAD_PLAIN_INPUT << (2 * (GPIO_A16 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A17 & 0xF))) |
+ (SCON_PAD_PLAIN_INPUT << (2 * (GPIO_A18 & 0xF))) |
+ (SCON_PAD_PLAIN_INPUT << (2 * (GPIO_A19 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A20 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A21 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A22 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A23 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A24 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A25 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A26 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A27 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A28 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A29 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A30 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A31 & 0xF)))
+ },
+ {
+ (void __iomem *) SCON_SYSPAD2_REG,
+ 0 |
+ (SCON_PAD_PULL_DOWN << (2 * (GPIO_B0 & 0xF))) |
+ (SCON_PAD_PULL_DOWN << (2 * (GPIO_B1 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B2 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B3 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B4 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B5 & 0xF))) |
+ (SCON_PAD_PLAIN_INPUT << (2 * (GPIO_B6 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B7 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B8 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B9 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B10 & 0xF))) |
+ (SCON_PAD_PLAIN_INPUT << (2 * (GPIO_B11 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B12 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B13 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B14 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B15 & 0xF)))
+ },
+};
+
+/* GPIO def settings to avoid HW issue */
+struct u6_gpio_config u6_gpio_init_config[] = {
+ /* GPIO A bank */
+ {
+ .gpio = GPIO_A5,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 1,
+ },
+ {
+ .gpio = GPIO_A6,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 1,
+ },
+ {
+ .gpio = GPIO_A7,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_A8,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 1,
+ },
+ {
+ .gpio = GPIO_A9,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 1,
+ },
+ {
+ .gpio = GPIO_A13,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_A17,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_A21,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_A23,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_A24,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 1,
+ },
+ {
+ .gpio = GPIO_A25,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_A30,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ /* GPIO B bank */
+ /* GPIO C bank */
+ /* GPIO D bank */
+ {
+ .gpio = GPIO_D0,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_D24,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_D29,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ /* GPIO E bank */
+ {
+ .gpio = GPIO_E31,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ /* GPIO F bank */
+ {
+ .gpio = GPIO_F0,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_F1,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_F2,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_F9,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ }
+};
+
+u32 gpio_to_configure = ARRAY_SIZE(u6_gpio_init_config);
/* List of board specific devices */
static struct platform_device *devices[] __initdata = {
@@ -31,6 +499,7 @@ static struct platform_device *devices[] __initdata = {
void __init u67xx_init(void)
{
+ u6_gpio_init();
/* Add specific board devices */
platform_add_devices(devices, ARRAY_SIZE(devices));
}
diff --git a/arch/arm/mach-u67xx/devices.c b/arch/arm/mach-u67xx/devices.c
index 0ead380..8e812fb 100644
--- a/arch/arm/mach-u67xx/devices.c
+++ b/arch/arm/mach-u67xx/devices.c
@@ -48,12 +48,12 @@ unsigned char extint_to_gpio[NR_EXTINT] = {
EXPORT_SYMBOL(extint_to_gpio);
struct gpio_bank u6_gpio_bank[6] = {
- {(void __iomem *)GPIOA_PINS_REG, (void __iomem *)SCON_SYSMUX0_REG},
- {(void __iomem *)GPIOB_PINS_REG, (void __iomem *)SCON_SYSMUX2_REG},
- {(void __iomem *)GPIOC_PINS_REG, (void __iomem *)SCON_SYSMUX4_REG},
- {(void __iomem *)GPIOD_PINS_REG, (void __iomem *)SCON_SYSMUX6_REG},
- {(void __iomem *)GPIOE_PINS_REG, (void __iomem *)SCON_SYSMUX8_REG},
- {(void __iomem *)GPIOF_PINS_REG, (void __iomem *)SCON_SYSMUX10_REG},
+ {GPIOA_PINS_REG, SCON_SYSMUX0_REG},
+ {GPIOB_PINS_REG, SCON_SYSMUX2_REG},
+ {GPIOC_PINS_REG, SCON_SYSMUX4_REG},
+ {GPIOD_PINS_REG, SCON_SYSMUX6_REG},
+ {GPIOE_PINS_REG, SCON_SYSMUX8_REG},
+ {GPIOF_PINS_REG, SCON_SYSMUX10_REG},
};
static struct gpio_data u6_gpio_data = {
diff --git a/arch/arm/plat-u6xxx/Makefile b/arch/arm/plat-u6xxx/Makefile
index afdf82b..3d6898e 100644
--- a/arch/arm/plat-u6xxx/Makefile
+++ b/arch/arm/plat-u6xxx/Makefile
@@ -3,6 +3,6 @@
#
# Common support
-obj-y := io.o irq.o clock.o
+obj-y := io.o irq.o clock.o gpio.o
obj-$(CONFIG_U6_MTU_TIMER) += timer.o
diff --git a/arch/arm/plat-u6xxx/gpio.c b/arch/arm/plat-u6xxx/gpio.c
new file mode 100644
index 0000000..40e25fc
--- /dev/null
+++ b/arch/arm/plat-u6xxx/gpio.c
@@ -0,0 +1,716 @@
+/*
+ * linux/arch/arm/plat-u6xxx/gpio.c
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Loic Pallardy <loic.pallardy@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ * Support functions for GPIO
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/sysdev.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <mach/irqs.h>
+#include <mach/gpio.h>
+#include <asm/mach/irq.h>
+#include <mach/scon.h>
+
+/*
+ * PN5220 GPIO/MUX registers
+ * defined in asm/arch/registers.h
+ */
+
+#define U6_GPIO_PINS_OFFSET 0
+#define U6_GPIO_OUTPUT_OFFSET 4
+#define U6_GPIO_DIR_OFFSET 8
+
+#define U6_MUX2_OFFSET 4
+
+static struct gpio_bank *gpio_bank_desc;
+static int gpio_bank_count;
+
+static inline struct gpio_bank *get_gpio_bank(int gpio)
+{
+ /* 32 GPIOs per bank */
+ return &(gpio_bank_desc[gpio >> 5]);
+}
+
+static inline int get_gpio_index(int gpio)
+{
+ return gpio & 0x1f;
+}
+
+static int check_gpio(int gpio)
+{
+ int retval = ((unsigned int)gpio) < GPIO_COUNT;
+ if (unlikely(!retval)) {
+ printk(KERN_ERR "u6-gpio: invalid GPIO %d\n", gpio);
+ dump_stack();
+ }
+ return retval;
+}
+
+static inline int gpio_is_requested(struct gpio_bank *bank, unsigned long mask)
+{
+ return bank->reserved_map & mask;
+}
+
+static int check_gpio_requested(struct gpio_bank *bank, int index)
+{
+ int retval = gpio_is_requested(bank, 1 << index);
+ if (unlikely(!retval)) {
+ char c = 'A' + (bank - get_gpio_bank(0));
+ printk(KERN_ERR "u6-gpio: GPIO %c%d is not requested yet\n",
+ c, index);
+ dump_stack();
+ }
+ return retval;
+}
+
+static int check_gpio_unrequested(struct gpio_bank *bank, int index)
+{
+ int retval = !gpio_is_requested(bank, 1 << index);
+ if (unlikely(!retval)) {
+ char c = 'A' + (bank - get_gpio_bank(0));
+ printk(KERN_ERR "u6-gpio: GPIO %c%d is already requested\n",
+ c, index);
+ dump_stack();
+ }
+ return retval;
+}
+
+static int check_gpio_irq(int gpio_irq)
+{
+ int retval = ((unsigned int)gpio_irq) < NR_EXTINT;
+ if (unlikely(!retval)) {
+ printk(KERN_ERR "u6-gpio: invalid GPIO-IRQ %d\n", gpio_irq);
+ dump_stack();
+ }
+ return retval;
+}
+
+static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
+{
+ u32 reg = bank->gpio_base;
+ u32 l;
+
+ /* select direction register */
+ reg += U6_GPIO_DIR_OFFSET;
+
+ /* in register 0 = input, 1 = output */
+ l = inl(reg);
+ if (is_input)
+ l &= ~(1 << gpio);
+ else
+ l |= (1 << gpio);
+ outl(l, reg);
+}
+
+int u6_gpio_set_direction(int gpio, int is_input)
+{
+ unsigned long flags, index;
+ struct gpio_bank *bank;
+
+ if (!check_gpio(gpio))
+ return -EINVAL;
+
+ bank = get_gpio_bank(gpio);
+ index = get_gpio_index(gpio);
+ if (!check_gpio_requested(bank, index))
+ return -EINVAL;
+
+ spin_lock_irqsave(&bank->lock, flags);
+ _set_gpio_direction(bank, index, is_input);
+ spin_unlock_irqrestore(&bank->lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(u6_gpio_set_direction);
+
+static void _set_gpio_mode(struct gpio_bank *bank, int gpio, int mode)
+{
+ u32 reg = bank->mux_base;
+ unsigned long flags;
+ unsigned long l;
+
+ /* select direction register */
+ if (gpio >= 16) {
+ reg += U6_MUX2_OFFSET;
+ gpio -= 16;
+ }
+
+ hw_raw_local_irq_save(flags);
+ /* apply mux mode */
+ /* width 2 bit */
+ l = inl(reg);
+ l &= ~(3 << (gpio * 2));
+ l |= (mode << (gpio * 2));
+ outl(l, reg);
+ hw_raw_local_irq_restore(flags);
+}
+
+int u6_gpio_set_mode(int gpio, int mode)
+{
+ struct gpio_bank *bank;
+ int index;
+
+ if (!check_gpio(gpio))
+ return -EINVAL;
+
+ bank = get_gpio_bank(gpio);
+ index = get_gpio_index(gpio);
+ if (!check_gpio_requested(bank, index))
+ return -EINVAL;
+
+ spin_lock(&bank->lock);
+ _set_gpio_mode(bank, get_gpio_index(gpio), mode);
+ spin_unlock(&bank->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(u6_gpio_set_mode);
+
+int u6_gpio_set_mode_gpio(int gpio)
+{
+ int muxmode = gpio >= GPIO_B0 ? GPIO_MODE_MUX1 : GPIO_MODE_MUX0;
+ return u6_gpio_set_mode(gpio, muxmode);
+}
+EXPORT_SYMBOL(u6_gpio_set_mode_gpio);
+
+static void _write_gpio_pin(struct gpio_bank *bank, int gpio, int gpio_value)
+{
+ u32 reg = bank->gpio_base;
+ unsigned long flags;
+ unsigned long l = 0;
+
+ reg += U6_GPIO_OUTPUT_OFFSET;
+ hw_raw_local_irq_save(flags);
+ l = inl(reg);
+ if (gpio_value)
+ l |= 1 << gpio;
+ else
+ l &= ~(1 << gpio);
+ outl(l, reg);
+ hw_raw_local_irq_restore(flags);
+
+}
+
+static int u6_gpio_to_extint(int gpio)
+{
+ int extint_idx;
+
+ for (extint_idx = 0; extint_idx < NR_EXTINT; extint_idx++)
+ if (extint_to_gpio[extint_idx] == gpio)
+ return extint_idx;
+
+ return -1;
+}
+
+int u6_gpio_write_pin(int gpio, int gpio_value)
+{
+ struct gpio_bank *bank;
+ unsigned long index;
+
+ if (!check_gpio(gpio))
+ return -EINVAL;
+
+ bank = get_gpio_bank(gpio);
+ index = get_gpio_index(gpio);
+ if (!check_gpio_requested(bank, index))
+ return -EINVAL;
+
+ spin_lock(&bank->lock);
+ _write_gpio_pin(bank, index, gpio_value);
+ spin_unlock(&bank->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(u6_gpio_write_pin);
+
+int u6_gpio_read_pin(int gpio)
+{
+ struct gpio_bank *bank;
+ u32 reg;
+ u32 l = 0;
+ int irq, index;
+
+ if (!check_gpio(gpio))
+ return -EINVAL;
+
+ bank = get_gpio_bank(gpio);
+ index = get_gpio_index(gpio);
+ if (!check_gpio_requested(bank, index))
+ return -EINVAL;
+
+ /* check if the GPIO is used as extint */
+ irq = u6_gpio_to_extint(gpio);
+ if (irq >= 0) {
+ /* and if it's an alternate internal signal */
+ /* (cf U67xx datasheet table 444) */
+ reg = EXTINT_CFGx(irq);
+ l = inl(reg);
+ if (l & EXTINT_SEL_ALTERNATE) {
+ reg = EXTINT_SIGNAL_REG;
+ return (inl(reg) & (1 << irq)) != 0;
+ }
+ }
+
+ reg = bank->gpio_base;
+ reg += U6_GPIO_PINS_OFFSET;
+ return (inl(reg) & (1 << index)) != 0;
+}
+EXPORT_SYMBOL(u6_gpio_read_pin);
+
+static int _u6_gpio_request(struct gpio_bank *bank, int index)
+{
+ int retval = 0;
+ unsigned long mask = 1 << index;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bank->lock, flags);
+ if (unlikely(!check_gpio_unrequested(bank, index)))
+ retval = -EINVAL;
+ else
+ bank->reserved_map |= mask;
+ spin_unlock_irqrestore(&bank->lock, flags);
+
+ return retval;
+}
+
+static int u6_gpio_acquire(struct gpio_chip *chip, unsigned offset)
+{
+ struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
+
+ return _u6_gpio_request(bank, offset);
+}
+
+int u6_gpio_request(int gpio)
+{
+ int index;
+ struct gpio_bank *bank;
+
+ if (!check_gpio(gpio))
+ return -EINVAL;
+
+ index = get_gpio_index(gpio);
+ bank = get_gpio_bank(gpio);
+
+ return _u6_gpio_request(bank, index);
+}
+EXPORT_SYMBOL(u6_gpio_request);
+
+static void _u6_gpio_free(struct gpio_bank *bank, int index)
+{
+ unsigned long mask = 1 << index;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bank->lock, flags);
+ if (likely(check_gpio_requested(bank, index)))
+ bank->reserved_map &= ~mask;
+ spin_unlock_irqrestore(&bank->lock, flags);
+}
+
+static void u6_gpio_release(struct gpio_chip *chip, unsigned offset)
+{
+ struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
+
+ return _u6_gpio_free(bank, offset);
+}
+
+void u6_gpio_free(int gpio)
+{
+ int index;
+ struct gpio_bank *bank;
+
+ if (!check_gpio(gpio))
+ return;
+
+ index = get_gpio_index(gpio);
+ bank = get_gpio_bank(gpio);
+ _u6_gpio_free(bank, index);
+}
+EXPORT_SYMBOL(u6_gpio_free);
+
+/* New GPIO_GENERIC interface */
+
+static int gpio_input(struct gpio_chip *chip, unsigned offset)
+{
+ struct gpio_bank *bank;
+ unsigned long flags;
+
+ bank = container_of(chip, struct gpio_bank, chip);
+ spin_lock_irqsave(&bank->lock, flags);
+ _set_gpio_direction(bank, offset, 1);
+ spin_unlock_irqrestore(&bank->lock, flags);
+ return 0;
+}
+
+static int gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ return u6_gpio_read_pin(chip->base + offset);
+}
+
+static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct gpio_bank *bank;
+ unsigned long flags;
+
+ bank = container_of(chip, struct gpio_bank, chip);
+ spin_lock_irqsave(&bank->lock, flags);
+ _write_gpio_pin(bank, offset, value);
+ _set_gpio_direction(bank, offset, 0);
+ spin_unlock_irqrestore(&bank->lock, flags);
+ return 0;
+}
+
+static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct gpio_bank *bank;
+ unsigned long flags;
+
+ bank = container_of(chip, struct gpio_bank, chip);
+ spin_lock_irqsave(&bank->lock, flags);
+ _write_gpio_pin(bank, offset, value);
+ spin_unlock_irqrestore(&bank->lock, flags);
+}
+
+static int gpio_2irq(struct gpio_chip *chip, unsigned offset)
+{
+ return u6_gpio_to_extint(chip->base + offset);
+}
+
+/*
+ * U6 EXTINT : only EXTINT 3 is managed by Linux
+ * We need to unmask the GPIO bank interrupt as soon as possible to
+ * avoid missing GPIO interrupts for other lines in the bank.
+ * Then we need to mask-read-clear-unmask the triggered GPIO lines
+ * in the bank to avoid missing nested interrupts for a GPIO line.
+ * If we wait to unmask individual GPIO lines in the bank after the
+ * line's interrupt handler has been run, we may miss some nested
+ * interrupts.
+ */
+static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+ unsigned long isr;
+ unsigned long flags;
+ unsigned int gpio_irq;
+
+ /* LPA TBD */
+ desc->chip->ack(irq);
+
+ /* read status */
+ hw_raw_local_irq_save(flags);
+ isr = inl(EXTINT_STATUS_REG) & inl(EXTINT_ENABLE3_REG);
+ /* clear IRQ source(s) */
+ outl(~isr, EXTINT_STATUS_REG);
+ hw_raw_local_irq_restore(flags);
+
+ gpio_irq = IRQ_COUNT;
+ for (; isr != 0; isr >>= 1, gpio_irq++) {
+ struct irq_desc *d;
+ if (!(isr & 1))
+ continue;
+ d = irq_desc + gpio_irq;
+#ifdef CONFIG_DEBUG_EXTINT
+ printk(KERN_ERR "got something from EXTINT#%i line\n",
+ gpio_irq - IRQ_COUNT);
+#endif
+ desc_handle_irq(gpio_irq, d);
+ }
+
+}
+
+static void gpio_ack_irq(unsigned int irq)
+{
+ unsigned int gpio_irq = irq - IRQ_COUNT;
+ unsigned long flags;
+ hw_raw_local_irq_save(flags);
+ outl(~(1 << gpio_irq), EXTINT_STATUS_REG);
+ hw_raw_local_irq_restore(flags);
+}
+
+static void gpio_mask_irq(unsigned int irq)
+{
+ unsigned int gpio_irq = irq - IRQ_COUNT;
+ outl(inl(EXTINT_ENABLE3_REG) & ~(1 << gpio_irq),
+ EXTINT_ENABLE3_REG);
+}
+
+static void gpio_unmask_irq(unsigned int irq)
+{
+ unsigned int gpio_irq = irq - IRQ_COUNT;
+ outl(inl(EXTINT_ENABLE3_REG) | (1 << gpio_irq),
+ EXTINT_ENABLE3_REG);
+}
+
+int u6_gpio_clear_irq(unsigned int irq)
+{
+ unsigned int gpio_irq;
+ unsigned long flags;
+ gpio_irq = irq - IRQ_COUNT;
+ if (!check_gpio_irq(gpio_irq))
+ return -EINVAL;
+ hw_raw_local_irq_save(flags);
+ outl(~(1 << gpio_irq), EXTINT_STATUS_REG);
+ hw_raw_local_irq_restore(flags);
+ return 0;
+}
+EXPORT_SYMBOL(u6_gpio_clear_irq);
+
+int u6_gpio_set_irq_debounce(int irq, int cycles)
+{
+ int gpio;
+ struct gpio_bank *bank;
+ u32 reg;
+ int mode;
+ u32 l = 0;
+
+ gpio = EXTINT_TO_GPIO(irq);
+ irq -= IRQ_COUNT;
+ if (!check_gpio_irq(irq))
+ goto err;
+
+ bank = get_gpio_bank(gpio);
+ if (!check_gpio_requested(bank, get_gpio_index(gpio)))
+ return -EINVAL;
+
+ reg = EXTINT_CFGx(irq);
+ l = inl(reg);
+
+ mode = l & (3 << EXTINT_MODE_SHIFT);
+ if (mode == EXTINT_MODE_BYPASS)
+ goto err;
+
+ /* clear mode and set streching to debounce */
+ if (mode == EXTINT_MODE_STRETCHING) {
+ l &= ~(3 << EXTINT_MODE_SHIFT);
+ l |= EXTINT_MODE_DEBOUNCE;
+ }
+ /* clear and set the debounce field */
+ l &= ~(7 << EXTINT_DEBOUNCE_SHIFT);
+ l |= ((cycles & 0x7) << EXTINT_DEBOUNCE_SHIFT);
+ outl(l, reg);
+
+ return 0;
+err:
+ return -EINVAL;
+}
+EXPORT_SYMBOL(u6_gpio_set_irq_debounce);
+
+int u6_gpio_set_irq_selection(int irq, int selection)
+{
+ int gpio, index;
+ struct gpio_bank *bank;
+ u32 l = 0;
+ u32 reg;
+
+ gpio = EXTINT_TO_GPIO(irq);
+ irq -= IRQ_COUNT;
+ if (!check_gpio_irq(irq))
+ return -EINVAL;
+
+ bank = get_gpio_bank(gpio);
+ index = get_gpio_index(gpio);
+ if (!check_gpio_requested(bank, index))
+ return -EINVAL;
+
+ reg = EXTINT_CFGx(irq);
+ l = inl(reg);
+
+ if (selection == EXTINT_SEL_ALTERNATE)
+ l |= EXTINT_SEL_ALTERNATE;
+ else
+ l &= ~EXTINT_SEL_ALTERNATE;
+ outl(l, reg);
+
+ return 0;
+}
+EXPORT_SYMBOL(u6_gpio_set_irq_selection);
+
+/*
+ * -the level type set the bypass mode
+ * -and by default the edge type select the stretching mode.
+ * if you would a debounce you must defined your nb
+ * cycle with u6_set_gpio_debounce
+ */
+static int _set_gpio_triggering(int gpio_irq, int trigger)
+{
+ u32 reg = EXTINT_CFGx(gpio_irq);
+ u32 l = 0;
+
+ l = inl(reg);
+ l &= ~(3 << 6 | 1 << 2);
+
+ if (trigger == IRQ_TYPE_LEVEL_LOW)
+ l |= EXTINT_POL_NEGATIVE;
+ else if (trigger == IRQ_TYPE_LEVEL_HIGH)
+ l |= EXTINT_POL_POSITIVE;
+ else if (trigger == IRQ_TYPE_EDGE_RISING)
+ l |= (EXTINT_MODE_STRETCHING | EXTINT_POL_POSITIVE);
+ else if (trigger == IRQ_TYPE_EDGE_FALLING)
+ l |= (EXTINT_MODE_STRETCHING | EXTINT_POL_NEGATIVE);
+ else if (trigger == IRQ_TYPE_EDGE_BOTH)
+ l |= EXTINT_MODE_DUAL_EDGE;
+ else
+ goto err;
+
+ outl(l, reg);
+
+ return 0;
+err:
+ return -EINVAL;
+}
+
+static int gpio_irq_type(unsigned irq, unsigned type)
+{
+ unsigned gpio_irq;
+ int retval;
+
+ gpio_irq = irq - IRQ_COUNT;
+
+ if (!check_gpio_irq(gpio_irq))
+ return -EINVAL;
+
+ if (type & (IRQF_TRIGGER_PROBE))
+ return -EINVAL;
+
+ retval = _set_gpio_triggering(gpio_irq, type);
+ return retval;
+}
+
+static struct irq_chip gpio_irq_chip = {
+ .ack = gpio_ack_irq,
+ .disable = gpio_mask_irq,
+ .enable = gpio_unmask_irq,
+ .mask = gpio_mask_irq,
+ .unmask = gpio_unmask_irq,
+ .set_type = gpio_irq_type,
+ /*.set_wake = gpio_wake_enable, */
+};
+
+static int initialized;
+
+static int __init u6_gpio_probe(struct platform_device *pdev)
+{
+ int i, j;
+ int gpio = 0;
+ struct gpio_bank *bank;
+ struct gpio_data *data = pdev->dev.platform_data;
+ unsigned long flags;
+
+ initialized = 1;
+
+ printk(KERN_INFO "U6 GPIO\n");
+ gpio_bank_desc = data->gpio_bank_desc;
+ gpio_bank_count = data->nb_banks;
+
+ for (i = 0; i < gpio_bank_count; i++) {
+ int gpio_count = 32; /* 32 GPIO per bank */
+ bank = &gpio_bank_desc[i];
+ bank->reserved_map = 0;
+ spin_lock_init(&bank->lock);
+
+ bank->chip.request = u6_gpio_acquire;
+ bank->chip.free = u6_gpio_release;
+ bank->chip.direction_input = gpio_input;
+ bank->chip.get = gpio_get;
+ bank->chip.direction_output = gpio_output;
+ bank->chip.set = gpio_set;
+ bank->chip.to_irq = gpio_2irq;
+ bank->chip.label = "gpio";
+ bank->chip.base = gpio;
+ gpio += gpio_count;
+
+ bank->chip.ngpio = gpio_count;
+
+ gpiochip_add(&bank->chip);
+
+ }
+
+ /* for extint */
+ for (j = IRQ_COUNT; j < IRQ_COUNT + NR_EXTINT; j++) {
+ set_irq_chip(j, &gpio_irq_chip);
+ set_irq_handler(j, handle_simple_irq);
+ set_irq_flags(j, IRQF_VALID);
+ }
+
+ hw_raw_local_irq_save(flags);
+ /* mask all EXT IRQ sources before registring handler */
+ /* read status */
+ j = inl(EXTINT_STATUS_REG) & inl(EXTINT_ENABLE3_REG);
+ /* clear IRQ source(s) */
+ outl(j, EXTINT_STATUS_REG);
+
+ outl(0, EXTINT_ENABLE3_REG);
+
+ /* set irq in low level */
+ set_irq_type(IRQ_EXTINT3, IRQF_TRIGGER_LOW);
+
+ /* chained GPIO-IRQ on EXTINT3 */
+ set_irq_chained_handler(IRQ_EXTINT3, gpio_irq_handler);
+ hw_raw_local_irq_restore(flags);
+
+ return 0;
+}
+
+static struct platform_driver u6_gpio_driver = {
+ .probe = u6_gpio_probe,
+ .remove = NULL,
+ .suspend = NULL,
+ .resume = NULL,
+ .driver = {
+ .name = "u6-gpio",
+ },
+};
+
+static struct sysdev_class u6_gpio_sysclass = {
+ .name = "gpio",
+ .suspend = 0, /*u6_gpio_suspend, */
+ .resume = 0, /*u6_gpio_resume, */
+};
+
+static struct sys_device u6_gpio_device = {
+ .id = 0,
+ .cls = &u6_gpio_sysclass,
+};
+
+/*
+ * This may get called early from board specific init
+ * for boards that have interrupts routed via FPGA.
+ */
+int u6_gpio_init(void)
+{
+ if (!initialized)
+ return platform_driver_register(&u6_gpio_driver);
+ else
+ return 0;
+}
+
+static int __init u6_gpio_sysinit(void)
+{
+ int ret = 0;
+
+ if (!initialized)
+ ret = u6_gpio_init();
+
+ if (ret == 0) {
+ ret = sysdev_class_register(&u6_gpio_sysclass);
+ if (ret == 0)
+ ret = sysdev_register(&u6_gpio_device);
+ }
+
+ return ret;
+}
+
+arch_initcall(u6_gpio_sysinit);
diff --git a/arch/arm/plat-u6xxx/include/mach/gpio.h b/arch/arm/plat-u6xxx/include/mach/gpio.h
new file mode 100644
index 0000000..f69af5d
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/gpio.h
@@ -0,0 +1,396 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/gpio.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Loic Pallardy <loic.pallardy@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ * GPIO handling defines and functions
+ */
+
+#ifndef __ASM_PLAT_U6_GPIO_H
+#define __ASM_PLAT_U6_GPIO_H
+
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/gpio.h>
+
+#include <linux/errno.h>
+#include <asm-generic/gpio.h>
+
+/* GPIO bank description */
+struct gpio_bank {
+ u32 gpio_base;
+ u32 mux_base;
+ u16 irq;
+ u16 virtual_irq_start;
+ int method;
+ u32 reserved_map;
+ u32 suspend_wakeup;
+ u32 saved_wakeup;
+ spinlock_t lock;
+ struct gpio_chip chip;
+};
+
+
+struct gpio_data {
+ u32 nb_banks;
+ struct gpio_bank *gpio_bank_desc;
+};
+
+
+/* GPIO Init configuration */
+
+struct u6_gpio_config {
+ u32 gpio;
+ u32 dir;
+ u32 value;
+};
+
+
+/* list of GPIO */
+enum U6_GPIO_LIST {
+ GPIO_A0 = 0,
+ GPIO_A1,
+ GPIO_A2,
+ GPIO_A3,
+ GPIO_A4,
+ GPIO_A5,
+ GPIO_A6,
+ GPIO_A7,
+ GPIO_A8,
+ GPIO_A9,
+ GPIO_A10,
+ GPIO_A11,
+ GPIO_A12,
+ GPIO_A13,
+ GPIO_A14,
+ GPIO_A15,
+ GPIO_A16,
+ GPIO_A17,
+ GPIO_A18,
+ GPIO_A19,
+ GPIO_A20,
+ GPIO_A21,
+ GPIO_A22,
+ GPIO_A23,
+ GPIO_A24,
+ GPIO_A25,
+ GPIO_A26,
+ GPIO_A27,
+ GPIO_A28,
+ GPIO_A29,
+ GPIO_A30,
+ GPIO_A31,
+ GPIO_B0,
+ GPIO_B1,
+ GPIO_B2,
+ GPIO_B3,
+ GPIO_B4,
+ GPIO_B5,
+ GPIO_B6,
+ GPIO_B7,
+ GPIO_B8,
+ GPIO_B9,
+ GPIO_B10,
+ GPIO_B11,
+ GPIO_B12,
+ GPIO_B13,
+ GPIO_B14,
+ GPIO_B15,
+ GPIO_B16,
+ GPIO_B17,
+ GPIO_B18,
+ GPIO_B19,
+ GPIO_B20,
+ GPIO_B21,
+ GPIO_B22,
+ GPIO_B23,
+ GPIO_B24,
+ GPIO_B25,
+ GPIO_B26,
+ GPIO_B27,
+ GPIO_B28,
+ GPIO_B29,
+ GPIO_B30,
+ GPIO_B31,
+ GPIO_C0,
+ GPIO_C1,
+ GPIO_C2,
+ GPIO_C3,
+ GPIO_C4,
+ GPIO_C5,
+ GPIO_C6,
+ GPIO_C7,
+ GPIO_C8,
+ GPIO_C9,
+ GPIO_C10,
+ GPIO_C11,
+ GPIO_C12,
+ GPIO_C13,
+ GPIO_C14,
+ GPIO_C15,
+ GPIO_C16,
+ GPIO_C17,
+ GPIO_C18,
+ GPIO_C19,
+ GPIO_C20,
+ GPIO_C21,
+ GPIO_C22,
+ GPIO_C23,
+ GPIO_C24,
+ GPIO_C25,
+ GPIO_C26,
+ GPIO_C27,
+ GPIO_C28,
+ GPIO_C29,
+ GPIO_C30,
+ GPIO_C31,
+ GPIO_D0,
+ GPIO_D1,
+ GPIO_D2,
+ GPIO_D3,
+ GPIO_D4,
+ GPIO_D5,
+ GPIO_D6,
+ GPIO_D7,
+ GPIO_D8,
+ GPIO_D9,
+ GPIO_D10,
+ GPIO_D11,
+ GPIO_D12,
+ GPIO_D13,
+ GPIO_D14,
+ GPIO_D15,
+ GPIO_D16,
+ GPIO_D17,
+ GPIO_D18,
+ GPIO_D19,
+ GPIO_D20,
+ GPIO_D21,
+ GPIO_D22,
+ GPIO_D23,
+ GPIO_D24,
+ GPIO_D25,
+ GPIO_D26,
+ GPIO_D27,
+ GPIO_D28,
+ GPIO_D29,
+ GPIO_D30,
+ GPIO_D31,
+ GPIO_E0,
+ GPIO_E1,
+ GPIO_E2,
+ GPIO_E3,
+ GPIO_E4,
+ GPIO_E5,
+ GPIO_E6,
+ GPIO_E7,
+ GPIO_E8,
+ GPIO_E9,
+ GPIO_E10,
+ GPIO_E11,
+ GPIO_E12,
+ GPIO_E13,
+ GPIO_E14,
+ GPIO_E15,
+ GPIO_E16,
+ GPIO_E17,
+ GPIO_E18,
+ GPIO_E19,
+ GPIO_E20,
+ GPIO_E21,
+ GPIO_E22,
+ GPIO_E23,
+ GPIO_E24,
+ GPIO_E25,
+ GPIO_E26,
+ GPIO_E27,
+ GPIO_E28,
+ GPIO_E29,
+ GPIO_E30,
+ GPIO_E31,
+ GPIO_F0,
+ GPIO_F1,
+ GPIO_F2,
+ GPIO_F3,
+ GPIO_F4,
+ GPIO_F5,
+ GPIO_F6,
+ GPIO_F7,
+ GPIO_F8,
+ GPIO_F9,
+ GPIO_F10,
+ GPIO_F11,
+ GPIO_F12,
+ GPIO_F13,
+ GPIO_F14,
+ GPIO_F15,
+ GPIO_F16,
+ GPIO_F17,
+ GPIO_F18,
+ GPIO_F19,
+ GPIO_F20,
+ GPIO_F21,
+ GPIO_F22,
+ GPIO_F23,
+ GPIO_F24,
+ GPIO_F25,
+ GPIO_F26,
+ GPIO_F27,
+ GPIO_F28,
+ GPIO_F29,
+ GPIO_F30,
+ GPIO_F31,
+ GPIO_COUNT,
+};
+
+enum PMU_GPIO_LIST {
+ PMU_GPIO1 = GPIO_COUNT,
+ PMU_GPIO2,
+ PMU_GPIO3,
+ PMU_GPIO4,
+};
+
+enum U6_GPIO_MODE {
+ GPIO_MODE_MUX0 = 0,
+ GPIO_MODE_MUX1,
+ GPIO_MODE_MUX2,
+ GPIO_MODE_MUX3
+};
+
+
+#define GPIO_DIR_INPUT 1
+#define GPIO_DIR_OUTPUT 0
+
+
+extern int u6_gpio_init(void); /* Call from board init only */
+extern int u6_gpio_request(int gpio);
+extern void u6_gpio_free(int gpio);
+extern int u6_gpio_set_mode(int gpio, int mode);
+extern int u6_gpio_set_mode_gpio(int gpio);
+extern int u6_gpio_set_direction(int gpio, int is_input);
+extern int u6_gpio_write_pin(int gpio, int gpio_value);
+extern int u6_gpio_read_pin(int gpio);
+extern int u6_gpio_set_irq_debounce(int irq, int cycles);
+extern int u6_gpio_set_irq_selection(int irq, int selection);
+extern int u6_gpio_clear_irq(unsigned int irq);
+
+
+/*
+ * Wrappers for "new style" GPIO calls, using the new infrastructure
+ * which lets us plug in FPGA, I2C, and other implementations.
+ */
+
+static inline int gpio_get_value(unsigned gpio)
+{
+ return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+ __gpio_set_value(gpio, value);
+}
+
+static inline int gpio_cansleep(unsigned gpio)
+{
+ return __gpio_cansleep(gpio);
+}
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+ return __gpio_to_irq(gpio);
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+ return EXTINT_TO_GPIO(irq);
+}
+
+/*****************************************************************************
+* Hardware Register Definitions for EXTINT
+*****************************************************************************/
+
+/* EXTINT ENABLE1 Register (32 bits) */
+#define EXTINT_ENABLE1_OFFSET 0x60
+#define EXTINT_ENABLE1_REG IO_ADDRESS(EXTINT_BASE + EXTINT_ENABLE1_OFFSET)
+
+/* EXTINT ENABLE2 Register (32 bits) */
+#define EXTINT_ENABLE2_OFFSET 0x64
+#define EXTINT_ENABLE2_REG IO_ADDRESS(EXTINT_BASE + EXTINT_ENABLE2_OFFSET)
+
+/* EXTINT ENABLE3 Register (32 bits) */
+#define EXTINT_ENABLE3_OFFSET 0x68
+#define EXTINT_ENABLE3_REG IO_ADDRESS(EXTINT_BASE + EXTINT_ENABLE3_OFFSET)
+
+/* EXTINT STATUS Register (32 bits) */
+#define EXTINT_STATUS_OFFSET 0x6C
+#define EXTINT_STATUS_REG IO_ADDRESS(EXTINT_BASE + EXTINT_STATUS_OFFSET)
+
+/* EXTINT SIGNAL Register (32 bits) */
+#define EXTINT_SIGNAL_OFFSET 0x70
+#define EXTINT_SIGNAL_REG IO_ADDRESS(EXTINT_BASE + EXTINT_SIGNAL_OFFSET)
+
+/* Bits definition for register EXTINT_CFG[23:0] */
+#define EXTINT_MODE_SHIFT 6
+#define EXTINT_MODE_FIELD (0xFFFFFFFF - (0x3UL<<EXTINT_MODE_SHIFT))
+#define EXTINT_MODE_BYPASS (0x0UL<<EXTINT_MODE_SHIFT)
+#define EXTINT_MODE_STRETCHING (0x1UL<<EXTINT_MODE_SHIFT)
+#define EXTINT_MODE_DEBOUNCE (0x2UL<<EXTINT_MODE_SHIFT)
+#define EXTINT_MODE_DUAL_EDGE (0x3UL<<EXTINT_MODE_SHIFT)
+#define EXTINT_DEBOUNCE_SHIFT 3
+#define EXTINT_DEBOUNCE_FIELD (0xFFFFFFFF - (0x7UL<<EXTINT_DEBOUNCE_SHIFT))
+#define EXTINT_DEBOUNCE_0 (0x0UL<<EXTINT_DEBOUNCE_SHIFT)
+#define EXTINT_DEBOUNCE_1 (0x1UL<<EXTINT_DEBOUNCE_SHIFT)
+#define EXTINT_DEBOUNCE_2 (0x2UL<<EXTINT_DEBOUNCE_SHIFT)
+#define EXTINT_DEBOUNCE_3 (0x3UL<<EXTINT_DEBOUNCE_SHIFT)
+#define EXTINT_DEBOUNCE_7 (0x7UL<<EXTINT_DEBOUNCE_SHIFT)
+#define EXTINT_POL_SHIFT 2
+#define EXTINT_POL_FIELD (0xFFFFFFFF - (0x1UL<<EXTINT_POL_SHIFT))
+#define EXTINT_POL_NEGATIVE (0x0UL<<EXTINT_POL_SHIFT)
+#define EXTINT_POL_POSITIVE (0x1UL<<EXTINT_POL_SHIFT)
+#define EXTINT_POL (0x1UL<<EXTINT_POL_SHIFT)
+#define EXTINT_SEL_SHIFT 1
+#define EXTINT_SEL_FIELD (0xFFFFFFFF - (0x1UL<<EXTINT_SEL_SHIFT))
+#define EXTINT_SEL_EXTINT (0x0UL<<EXTINT_SEL_SHIFT)
+#define EXTINT_SEL_ALTERNATE (0x1UL<<EXTINT_SEL_SHIFT)
+#define EXTINT_SEL (0x1UL<<EXTINT_SEL_SHIFT)
+
+/*****************************************************************************/
+/* Register description for ENABLE[3:1] */
+
+/* Bits definition for register EXTINT_ENABLE[3:1] */
+#define EXTINT_ENABLE_SHIFT 0
+#define EXTINT_ENABLE_FIELD (0xFFFFFFFF - (0xFFFFFFUL<<EXTINT_ENABLE_SHIFT))
+#define EXTINT_ENABLE_0 (0x0UL<<EXTINT_ENABLE_SHIFT)
+#define EXTINT_ENABLE_1 (0x1UL<<EXTINT_ENABLE_SHIFT)
+
+/*****************************************************************************/
+/* Register description for STATUS */
+
+/* Bits definition for register EXTINT_STATUS */
+#define EXTINT_STATUS_SHIFT 0
+#define EXTINT_STATUS_FIELD (0xFFFFFFFF - (0xFFFFFFUL<<EXTINT_STATUS_SHIFT))
+#define EXTINT_STATUS_0 (0x0UL<<EXTINT_STATUS_SHIFT)
+#define EXTINT_STATUS_1 (0x1UL<<EXTINT_STATUS_SHIFT)
+
+/*****************************************************************************
+* Hardware Register Definitions for GPIOx
+*****************************************************************************/
+/* Offsets */
+#define GPIO_PINS_OFFSET 0x0
+#define GPIO_OR_OFFSET 0x4
+#define GPIO_DR_OFFSET 0x8
+
+/* GPIOx PINS Registers (32 bits) */
+#define GPIOA_PINS_REG IO_ADDRESS(GPIOA_BASE + GPIO_PINS_OFFSET)
+#define GPIOB_PINS_REG IO_ADDRESS(GPIOB_BASE + GPIO_PINS_OFFSET)
+#define GPIOC_PINS_REG IO_ADDRESS(GPIOC_BASE + GPIO_PINS_OFFSET)
+#define GPIOD_PINS_REG IO_ADDRESS(GPIOD_BASE + GPIO_PINS_OFFSET)
+#define GPIOE_PINS_REG IO_ADDRESS(GPIOE_BASE + GPIO_PINS_OFFSET)
+#define GPIOF_PINS_REG IO_ADDRESS(GPIOF_BASE + GPIO_PINS_OFFSET)
+
+/* GPIOx OR Registers (32 bits) */
+#define GPIOA_OR_REG IO_ADDRESS(GPIOC_BASE + GPIO_OR_OFFSET)
+
+#endif
--
1.7.0.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* U6/U6715 ARM architecture files, 2nd try
@ 2010-05-27 8:27 Philippe Langlais
2010-05-27 8:27 ` [PATCH 1/6] U6/U6715 ARM architecture files Philippe Langlais
` (5 more replies)
0 siblings, 6 replies; 17+ messages in thread
From: Philippe Langlais @ 2010-05-27 8:27 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
Here my second try for ST-Ericsson U6715 & U6 familly ARM926ejs SoC.
I take into account the too few remarks received from my first post.
This patch series apply on latest linux-next tree.
Information on U6715 is here: http://www.stericsson.com/platforms/U6715.jsp
Acked-by: Linus Walleij <linus.walleij@stericsson.com>
In hope to be merged in the next linux kernel.
Regards,
Philippe.
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 1/6] U6/U6715 ARM architecture files
2010-05-27 8:27 U6/U6715 ARM architecture files, 2nd try Philippe Langlais
@ 2010-05-27 8:27 ` Philippe Langlais
2010-06-24 14:08 ` Russell King - ARM Linux
2010-05-27 8:27 ` [PATCH 2/6] U6715 clocks gating management U6 clock generic driver & U6715 cgu clock specific (V2) Philippe Langlais
` (4 subsequent siblings)
5 siblings, 1 reply; 17+ messages in thread
From: Philippe Langlais @ 2010-05-27 8:27 UTC (permalink / raw)
To: linux-arm-kernel
V2 after first internal review
Signed-off-by: Philippe Langlais <philippe.langlais@stericsson.com>
---
arch/arm/Kconfig | 10 +
arch/arm/Makefile | 2 +
arch/arm/mach-u67xx/Kconfig | 11 +
arch/arm/mach-u67xx/Makefile | 11 +
arch/arm/mach-u67xx/Makefile.boot | 4 +
arch/arm/mach-u67xx/board_u67xx_wavex.c | 48 ++
arch/arm/mach-u67xx/devices.c | 95 ++++
arch/arm/plat-u6xxx/Kconfig | 20 +
arch/arm/plat-u6xxx/Makefile | 8 +
arch/arm/plat-u6xxx/include/mach/cpu.h | 36 ++
arch/arm/plat-u6xxx/include/mach/debug-macro.S | 38 ++
arch/arm/plat-u6xxx/include/mach/entry-macro.S | 32 ++
arch/arm/plat-u6xxx/include/mach/hardware.h | 41 ++
arch/arm/plat-u6xxx/include/mach/io.h | 20 +
arch/arm/plat-u6xxx/include/mach/irqs.h | 130 +++++
arch/arm/plat-u6xxx/include/mach/memory.h | 24 +
arch/arm/plat-u6xxx/include/mach/platform.h | 15 +
arch/arm/plat-u6xxx/include/mach/regs-u6.h | 121 +++++
arch/arm/plat-u6xxx/include/mach/scon.h | 121 +++++
arch/arm/plat-u6xxx/include/mach/system.h | 42 ++
arch/arm/plat-u6xxx/include/mach/timer.h | 24 +
arch/arm/plat-u6xxx/include/mach/timex.h | 23 +
arch/arm/plat-u6xxx/include/mach/uncompress.h | 50 ++
arch/arm/plat-u6xxx/include/mach/vmalloc.h | 10 +
arch/arm/plat-u6xxx/io.c | 34 ++
arch/arm/plat-u6xxx/irq.c | 231 ++++++++
arch/arm/plat-u6xxx/timer.c | 679 ++++++++++++++++++++++++
27 files changed, 1880 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-u67xx/Kconfig
create mode 100644 arch/arm/mach-u67xx/Makefile
create mode 100644 arch/arm/mach-u67xx/Makefile.boot
create mode 100644 arch/arm/mach-u67xx/board_u67xx_wavex.c
create mode 100644 arch/arm/mach-u67xx/devices.c
create mode 100644 arch/arm/plat-u6xxx/Kconfig
create mode 100644 arch/arm/plat-u6xxx/Makefile
create mode 100644 arch/arm/plat-u6xxx/include/mach/cpu.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/debug-macro.S
create mode 100644 arch/arm/plat-u6xxx/include/mach/entry-macro.S
create mode 100644 arch/arm/plat-u6xxx/include/mach/hardware.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/io.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/irqs.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/memory.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/platform.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/regs-u6.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/scon.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/system.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/timer.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/timex.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/uncompress.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/vmalloc.h
create mode 100644 arch/arm/plat-u6xxx/io.c
create mode 100644 arch/arm/plat-u6xxx/irq.c
create mode 100644 arch/arm/plat-u6xxx/timer.c
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 1f254bd..8248c0a 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -741,6 +741,13 @@ config ARCH_U300
help
Support for ST-Ericsson U300 series mobile platforms.
+config PLAT_U6XXX
+ bool "ST-Ericsson U6XXX Series"
+ select GENERIC_GPIO
+ select ARCH_REQUIRE_GPIOLIB
+ help
+ Support for ST-Ericsson's U6XXX architecture
+
config ARCH_U8500
bool "ST-Ericsson U8500 Series"
select CPU_V7
@@ -910,6 +917,9 @@ source "arch/arm/plat-stmp3xxx/Kconfig"
source "arch/arm/mach-u300/Kconfig"
+source "arch/arm/plat-u6xxx/Kconfig"
+source "arch/arm/mach-u67xx/Kconfig"
+
source "arch/arm/mach-ux500/Kconfig"
source "arch/arm/mach-versatile/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 64ba313..9a7cab3 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -176,6 +176,7 @@ machine-$(CONFIG_ARCH_SHMOBILE) := shmobile
machine-$(CONFIG_ARCH_STMP378X) := stmp378x
machine-$(CONFIG_ARCH_STMP37XX) := stmp37xx
machine-$(CONFIG_ARCH_U300) := u300
+machine-$(CONFIG_ARCH_U67XX) := u67xx
machine-$(CONFIG_ARCH_U8500) := ux500
machine-$(CONFIG_ARCH_VERSATILE) := versatile
machine-$(CONFIG_ARCH_VEXPRESS) := vexpress
@@ -201,6 +202,7 @@ plat-$(CONFIG_PLAT_S3C24XX) := s3c24xx samsung
plat-$(CONFIG_PLAT_S5P) := s5p samsung
plat-$(CONFIG_PLAT_SPEAR) := spear
plat-$(CONFIG_PLAT_VERSATILE) := versatile
+plat-$(CONFIG_PLAT_U6XXX) := u6xxx
ifeq ($(CONFIG_ARCH_EBSA110),y)
# This is what happens if you forget the IOCS16 line.
diff --git a/arch/arm/mach-u67xx/Kconfig b/arch/arm/mach-u67xx/Kconfig
new file mode 100644
index 0000000..48f53fb
--- /dev/null
+++ b/arch/arm/mach-u67xx/Kconfig
@@ -0,0 +1,11 @@
+comment "U67XX Board Type"
+ depends on ARCH_U67XX
+
+choice
+ prompt "Choose the U67XX Board type"
+ default MACH_U67XX_WAVEC_2GB
+ help
+ "Choose the ST-Ericsson Reference Design Board"
+ config MACH_U67XX_WAVEC_2GB
+ bool "U67XX WaveC Board with 2Gb Micron combo"
+endchoice
diff --git a/arch/arm/mach-u67xx/Makefile b/arch/arm/mach-u67xx/Makefile
new file mode 100644
index 0000000..38cf624
--- /dev/null
+++ b/arch/arm/mach-u67xx/Makefile
@@ -0,0 +1,11 @@
+#
+## Makefile for the linux kernel, hardware dependent part of ST-Ericsson U67xx
+#
+#
+## Object file lists.
+
+# Common support
+obj-y := devices.o
+
+# Specific board support
+obj-$(CONFIG_MACH_U67XX_WAVEC_2GB) += board_u67xx_wavex.o
diff --git a/arch/arm/mach-u67xx/Makefile.boot b/arch/arm/mach-u67xx/Makefile.boot
new file mode 100644
index 0000000..c4e8c02
--- /dev/null
+++ b/arch/arm/mach-u67xx/Makefile.boot
@@ -0,0 +1,4 @@
+ zreladdr-y := 0x20008000
+params_phys-y := 0x20000100
+initrd_phys-y := 0x26000000
+
diff --git a/arch/arm/mach-u67xx/board_u67xx_wavex.c b/arch/arm/mach-u67xx/board_u67xx_wavex.c
new file mode 100644
index 0000000..2a806e7
--- /dev/null
+++ b/arch/arm/mach-u67xx/board_u67xx_wavex.c
@@ -0,0 +1,48 @@
+/*
+ * linux/arch/arm/mach-u67xx/board_u67xx_wavex.c
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * Platform machine definition for U6XXX WAVEx Board.
+ */
+
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <mach/hardware.h>
+#include <asm/setup.h>
+
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <mach/irqs.h>
+#include <mach/timer.h>
+
+/* List of board specific devices */
+static struct platform_device *devices[] __initdata = {
+};
+
+void __init u67xx_init(void)
+{
+ /* Add specific board devices */
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+MACHINE_START(U6715, "STE_U67xx_refd")
+ /* Maintainer: Philippe Langlais <philippe.langlais@stericsson.com> */
+ .phys_io = UART1_BASE,
+ .io_pg_offst = (IO_ADDRESS(UART1_BASE) >> 18) & 0xfffc,
+ .boot_params = BOOT_PARAMS_OFFSET,
+ .map_io = u67xx_map_io,
+ .init_irq = u6_init_irq,
+ .init_machine = u67xx_init,
+ .timer = &u6_timer,
+MACHINE_END
+
diff --git a/arch/arm/mach-u67xx/devices.c b/arch/arm/mach-u67xx/devices.c
new file mode 100644
index 0000000..0ead380
--- /dev/null
+++ b/arch/arm/mach-u67xx/devices.c
@@ -0,0 +1,95 @@
+/*
+ * linux/arch/arm/mach-u67xx/devices.c
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * Device specification for the U67XX
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <mach/hardware.h>
+#include <mach/scon.h>
+#include <mach/gpio.h>
+
+/* EXTINT to GPIO mapping */
+unsigned char extint_to_gpio[NR_EXTINT] = {
+ GPIO_A0, /*extint 0 */
+ GPIO_A1, /*extint 1 */
+ GPIO_A2, /*extint 2 */
+ GPIO_A3, /*extint 3 */
+ GPIO_A4, /*extint 4 */
+ GPIO_A5, /*extint 5 */
+ GPIO_A12, /*extint 6 */
+ GPIO_A13, /*extint 7 */
+ GPIO_A14, /*extint 8 */
+ GPIO_A15, /*extint 9 */
+ GPIO_A16, /*extint 10 */
+ GPIO_A17, /*extint 11 */
+ GPIO_D19, /*extint 12 */
+ GPIO_A19, /*extint 13 */
+ GPIO_A20, /*extint 14 */
+ GPIO_B11, /*extint 15 */
+ GPIO_E30, /*extint 16 */
+ GPIO_D15, /*extint 17 */
+ GPIO_D20, /*extint 18 */
+ GPIO_B9, /*extint 19 */
+ GPIO_B7, /*extint 20 */
+ GPIO_A25, /*extint 21 */
+ GPIO_D18, /*extint 22 */
+ GPIO_A6 /*extint 23 */
+};
+EXPORT_SYMBOL(extint_to_gpio);
+
+struct gpio_bank u6_gpio_bank[6] = {
+ {(void __iomem *)GPIOA_PINS_REG, (void __iomem *)SCON_SYSMUX0_REG},
+ {(void __iomem *)GPIOB_PINS_REG, (void __iomem *)SCON_SYSMUX2_REG},
+ {(void __iomem *)GPIOC_PINS_REG, (void __iomem *)SCON_SYSMUX4_REG},
+ {(void __iomem *)GPIOD_PINS_REG, (void __iomem *)SCON_SYSMUX6_REG},
+ {(void __iomem *)GPIOE_PINS_REG, (void __iomem *)SCON_SYSMUX8_REG},
+ {(void __iomem *)GPIOF_PINS_REG, (void __iomem *)SCON_SYSMUX10_REG},
+};
+
+static struct gpio_data u6_gpio_data = {
+ ARRAY_SIZE(u6_gpio_bank), /* nb bank */
+ u6_gpio_bank
+};
+
+static struct resource u6_wavex_gpio_resources[] = {
+ [0] = {
+ .start = GPIOA_BASE, /* Physical address */
+ .end = GPIOA_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device u6_wavex_gpio_device = {
+ .name = "u6-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &u6_gpio_data,
+ },
+ .num_resources = ARRAY_SIZE(u6_wavex_gpio_resources),
+ .resource = u6_wavex_gpio_resources,
+};
+
+/* list of devices */
+static struct platform_device *platform_devs[] __initdata = {
+ &u6_wavex_gpio_device,
+};
+
+/* register generic devices */
+
+static int __init u67xx_devices_init(void)
+{
+ platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
+ return 0;
+}
+
+arch_initcall(u67xx_devices_init);
diff --git a/arch/arm/plat-u6xxx/Kconfig b/arch/arm/plat-u6xxx/Kconfig
new file mode 100644
index 0000000..b01f77c
--- /dev/null
+++ b/arch/arm/plat-u6xxx/Kconfig
@@ -0,0 +1,20 @@
+menu "STE U6XXX Implementations"
+
+choice
+ prompt "U67XX System Type"
+ default ARCH_U67XX
+
+config ARCH_U67XX
+ bool "U67XX"
+ select PLAT_U6XXX
+ select CPU_ARM926T
+ select GENERIC_TIME
+ select GENERIC_CLOCKEVENTS
+ select U6_MTU_TIMER
+endchoice
+
+endmenu
+
+config U6_MTU_TIMER
+ bool
+ default y
diff --git a/arch/arm/plat-u6xxx/Makefile b/arch/arm/plat-u6xxx/Makefile
new file mode 100644
index 0000000..12c832c
--- /dev/null
+++ b/arch/arm/plat-u6xxx/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the linux kernel hardware independant part of STE U6XXX.
+#
+
+# Common support
+obj-y := io.o irq.o
+
+obj-$(CONFIG_U6_MTU_TIMER) += timer.o
diff --git a/arch/arm/plat-u6xxx/include/mach/cpu.h b/arch/arm/plat-u6xxx/include/mach/cpu.h
new file mode 100644
index 0000000..7512ce6
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/cpu.h
@@ -0,0 +1,36 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/cpu.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ * U6 cpu type detection
+ */
+
+#ifndef __ASM_PLAT_CPU_H
+#define __ASM_PLAT_CPU_H
+
+/*
+ * Macros to group U6xxx into cpu classes.
+ * These can be used in most places.
+ * cpu_is_u67xx(): True for U67XX
+ */
+
+#define GET_U6XXX_CLASS ((inl(SCON_SYSVER_REG)&0x0F00)>>8)
+#define GET_U6XXX_SUBCLASS ((inl(SCON_SYSVER_REG)&0x0FF0)>>4)
+
+#define cpu_is_u67xx() 0
+#define cpu_is_u67xx_v2() 0
+#define cpu_is_u67xx_v3() 0
+
+#if defined(CONFIG_ARCH_U67XX)
+# undef cpu_is_u67xx
+# undef cpu_is_u67xx_v2
+# undef cpu_is_u67xx_v3
+# define cpu_is_u67xx() (GET_U6XXX_CLASS == 0x6)
+# define cpu_is_u67xx_v2() (GET_U6XXX_SUBCLASS == 0x62)
+# define cpu_is_u67xx_v3() (GET_U6XXX_SUBCLASS == 0x63)
+#endif
+
+#endif /* __ASM_PLAT_CPU_H */
+
diff --git a/arch/arm/plat-u6xxx/include/mach/debug-macro.S b/arch/arm/plat-u6xxx/include/mach/debug-macro.S
new file mode 100644
index 0000000..039c810
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/debug-macro.S
@@ -0,0 +1,38 @@
+/* linux/arch/arm/plat-u6xxx/include/mach/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ * Copyright (C) 2010 ST-Ericsson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#include <mach/hardware.h>
+
+ .macro addruart,rx
+ mrc p15, 0, \rx, c1, c0
+ tst \rx, #1 @ MMU enabled?
+ ldreq \rx, = UART1_BASE @ physical base address
+ ldrne \rx, = IO_ADDRESS(UART1_BASE) @ virtual base
+ .endm
+
+ .macro senduart,rd,rx
+ strb \rd, [\rx]
+ .endm
+
+ .macro waituart,rd,rx
+1001:
+ ldr \rd, [\rx, #20]
+ tst \rd, #1 << 5 @ LSR_THRE - 0 when full
+ beq 1001b
+ .endm
+
+ .macro busyuart,rd,rx
+1001:
+ ldr \rd, [\rx, #20]
+ tst \rd, #1 << 6 @ LSR_TEMT - 0 when busy
+ beq 1001b
+ .endm
diff --git a/arch/arm/plat-u6xxx/include/mach/entry-macro.S b/arch/arm/plat-u6xxx/include/mach/entry-macro.S
new file mode 100644
index 0000000..59bb2d2
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/entry-macro.S
@@ -0,0 +1,32 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/entry-macro.S
+ *
+ * Low-level IRQ helper macros for U6-based platforms
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_preamble, base, tmp
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ ldr \base, =IO_ADDRESS(INTC_BASE)
+ ldr \irqnr, [\base, #INTC_VECTOR_IRQ_OFFSET] @ load intc vector reg
+ mov \irqnr, \irqnr, lsr #3 @ Bits[0..2] are reserved
+ ands \irqnr, \irqnr, #0x00FF @ mask Bits[11..31]
+ .endm
+
+ .macro irq_prio_table
+ .endm
+
diff --git a/arch/arm/plat-u6xxx/include/mach/hardware.h b/arch/arm/plat-u6xxx/include/mach/hardware.h
new file mode 100644
index 0000000..79199ec
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/hardware.h
@@ -0,0 +1,41 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/hardware.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <asm/sizes.h>
+#ifndef __ASSEMBLER__
+#include <mach/cpu.h>
+#endif
+
+/*
+ * Processor specific registers defines
+ */
+#include "regs-u6.h"
+
+/*
+ * Where in virtual memory the IO devices (timers, system controllers
+ * and so on)
+ */
+
+#define IO_BASE_VIRT 0xE8000000 /* VA of IO */
+
+/* macro to get at IO space when running virtually */
+/* this version gives more IO address range to map*/
+#define IO_ADDRESS(x) ((x) - IO_BASE_PHYS + IO_BASE_VIRT)
+
+/* typesafe io address */
+#define __io_address(n) __io(IO_ADDRESS(n))
+
+/*
+ * Board specific defines
+ */
+
+#endif
+
diff --git a/arch/arm/plat-u6xxx/include/mach/io.h b/arch/arm/plat-u6xxx/include/mach/io.h
new file mode 100644
index 0000000..058b5e4
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/io.h
@@ -0,0 +1,20 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/io.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * Dummy IO map & IO definitions
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a) __typesafe_io(a)
+#define __mem_pci(a) (a)
+
+void u67xx_map_io(void);
+
+#endif /* __ASM_ARM_ARCH_IO_H */
diff --git a/arch/arm/plat-u6xxx/include/mach/irqs.h b/arch/arm/plat-u6xxx/include/mach/irqs.h
new file mode 100644
index 0000000..abd5ab7
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/irqs.h
@@ -0,0 +1,130 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/irqs.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef __ASM_PLAT_U6_IRQS_H
+#define __ASM_PLAT_U6_IRQS_H
+
+#define IRQ_COUNT 65
+
+/* external IRQ definition EXTINT */
+#define IRQ_EXTINT(num) (IRQ_COUNT+(num))
+#define EXTINT_NUM(irq) ((irq)-IRQ_COUNT)
+
+#define NR_EXTINT 24
+#define NR_IRQS (IRQ_COUNT+NR_EXTINT)
+
+#ifndef __ASSEMBLY__
+extern unsigned char extint_to_gpio[NR_EXTINT];
+
+#define EXTINT_TO_GPIO(gpio_irq) extint_to_gpio[gpio_irq-IRQ_COUNT]
+
+#define hw_raw_local_irq_save raw_local_irq_save
+#define hw_raw_local_irq_restore raw_local_irq_restore
+
+void /*__init */ u6_init_irq(void);
+void u6_monitor_irq_enter(unsigned int irq);
+void u6_monitor_irq_exit(unsigned int irq);
+#endif /* __ASSEMBLY__ */
+
+/*
+ * Interrupt numbers
+ */
+#define IRQ_GHOST 0
+#define IRQ_EXTINT1 1
+#define IRQ_EXTINT2 2
+#define IRQ_EXTINT3 3
+#define IRQ_RFRD 4
+#define IRQ_MMTU 5
+#define IRQ_IIS 6
+#define IRQ_USB 7
+#define IRQ_I2C2 8
+#define IRQ_TVO 9
+#define IRQ_3G_WUP 10
+#define IRQ_3G_CALINT 11
+#define IRQ_3G_FRAME_IT 12
+#define IRQ_GPADCINT 13
+#define IRQ_ARM9_COMMTX 14
+#define IRQ_ARM9_COMMRX 15
+#define IRQ_KBS 16
+#define IRQ_SCTU2 17
+#define IRQ_SCTU1 18
+#define IRQ_PIO1 19
+#define IRQ_PIO2 20
+#define IRQ_FINT0 21
+#define IRQ_FINT1 22
+#define IRQ_UART2 23
+#define IRQ_UART1 24
+#define IRQ_SPI2 25
+#define IRQ_SPI1 26
+#define IRQ_FCI 27
+#define IRQ_I2C1 28
+#define IRQ_DMAU 29
+#define IRQ_USIM 30
+#define IRQ_HSDPA 31 /* reserved */
+#define IRQ_MSI 32
+#define IRQ_JDI 33
+#define IRQ_JDU 34
+#define IRQ_NFI 35
+#define IRQ_IPP 36
+#define IRQ_VDC 37
+#define IRQ_VEC 38
+#define IRQ_VDE 39
+#define IRQ_CAM 40
+#define IRQ_ETB_ACQ 41
+#define IRQ_ETB_FULL 42
+#define IRQ_RESERVED43 43
+#define IRQ_RESERVED44 44
+#define IRQ_RESERVED45 45 /* reserved */
+#define IRQ_RESERVED46 46
+#define IRQ_RESERVED47 47
+#define IRQ_PDCU 48
+#define IRQ_MC2SC0 49
+#define IRQ_MC2SC1 50
+#define IRQ_MC2SC2 51
+#define IRQ_MC2SC3 52
+#define IRQ_MC2SC4 53
+#define IRQ_MC2SC5 54
+#define IRQ_MC2SC6 55
+#define IRQ_MC2SC7 56
+
+/* INTC PRIOMASK_IRQ Register (32 bits) */
+#define INTC_PRIOMASK_IRQ_OFFSET 0x0
+#define INTC_PRIOMASK_IRQ_REG IO_ADDRESS(INTC_BASE + INTC_PRIOMASK_IRQ_OFFSET)
+
+/* INTC PRIOMASK_FIQ Register (32 bits) */
+#define INTC_PRIOMASK_FIQ_OFFSET 0x4
+#define INTC_PRIOMASK_FIQ_REG IO_ADDRESS(INTC_BASE + INTC_PRIOMASK_FIQ_OFFSET)
+
+/* INTC VECTOR_IRQ Register (32 bits) */
+#define INTC_VECTOR_IRQ_OFFSET 0x100
+#define INTC_VECTOR_IRQ_REG IO_ADDRESS(INTC_BASE + INTC_VECTOR_IRQ_OFFSET)
+
+/* INTC VECTOR_FIQ Register (32 bits) */
+#define INTC_VECTOR_FIQ_OFFSET 0x104
+#define INTC_VECTOR_FIQ_REG IO_ADDRESS(INTC_BASE + INTC_VECTOR_FIQ_OFFSET)
+
+/* INTC PENDING_* Registers (32 bits) */
+#define INTC_PENDING_1_OFFSET 0x200
+#define INTC_PENDING_2_OFFSET 0x204
+#define INTC_PENDING_3_OFFSET 0x208
+#define INTC_FEATURES_OFFSET 0x300
+
+/* INTC REQUEST 64 Registers (32 bits) */
+#define INTC_REQUEST1_OFFSET 0x404
+#define INTC_REQUEST64_OFFSET 0x500
+
+/* INTC MOD_ID Register (32 bits) */
+#define INTC_MOD_ID_OFFSET 0xFFC
+
+/* interrupt x [1..64] request configuration */
+#define INTC_REQUESTx(x) IO_ADDRESS(INTC_BASE+INTC_REQUEST1_OFFSET+(x-1)*4)
+
+/* EXTINTx [0..23] configuration register */
+#define EXTINT_CFGx(x) IO_ADDRESS(EXTINT_BASE+(x)*4)
+
+#endif /* __ASM_PLAT_U6_IRQS_H */
diff --git a/arch/arm/plat-u6xxx/include/mach/memory.h b/arch/arm/plat-u6xxx/include/mach/memory.h
new file mode 100644
index 0000000..0fa6cea
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/memory.h
@@ -0,0 +1,24 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/memory.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET UL(0x20000000)
+#define BOOT_PARAMS_OFFSET (PHYS_OFFSET + 0x100)
+
+/**
+ * CONSISTENT_DMA_SIZE: Size of DMA-consistent memory region.
+ * Must be multiple of 2M,between 2MB and 14MB inclusive
+ */
+#define CONSISTENT_DMA_SIZE (SZ_2M)
+
+#endif
diff --git a/arch/arm/plat-u6xxx/include/mach/platform.h b/arch/arm/plat-u6xxx/include/mach/platform.h
new file mode 100644
index 0000000..5265ccd
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/platform.h
@@ -0,0 +1,15 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/platform.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef __ASM_ARCH_PLATFORM_H
+#define __ASM_ARCH_PLATFORM_H 1
+
+#include <linux/types.h>
+#include <mach/hardware.h>
+
+#endif /* __ASM_ARCH_PLATFORM_H */
diff --git a/arch/arm/plat-u6xxx/include/mach/regs-u6.h b/arch/arm/plat-u6xxx/include/mach/regs-u6.h
new file mode 100644
index 0000000..aa2fbb0
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/regs-u6.h
@@ -0,0 +1,121 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/regs-u6.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ * Basic register address definitions in physical memory
+ */
+
+#if !defined(__REGS_U6_H__)
+#define __REGS_U6_H__
+
+#define IO_BASE_PHYS 0xC1000000 /* phys base address of reg */
+#define IO_SIZE 0x03400000 /* How much */
+
+/*
+ * System Controller Core devices base address table
+ */
+
+/* DMA Controller */
+#define DMAU_BASE (IO_BASE_PHYS + 0x0000000)
+
+/* Interrupt Controller */
+#define INTC_BASE (IO_BASE_PHYS + 0x0100000)
+
+/* SDRam controller */
+#define SDI_BASE (IO_BASE_PHYS + 0x0200000)
+
+/* Nand Flash Inteface controller */
+#define NFI_BASE (IO_BASE_PHYS + 0x0300000)
+
+/* USB controller */
+#define USB_BASE (IO_BASE_PHYS + 0x0400000)
+
+/* Video Display Engine */
+#define VDE_BASE (IO_BASE_PHYS + 0x0500000)
+
+/* Video Decoder */
+#define VDC_BASE (IO_BASE_PHYS + 0x1000000)
+
+/* Viedo Encoder */
+#define VEC_BASE (IO_BASE_PHYS + 0x1100000)
+
+/* Texture Codec, MPEG4 encoder sub module */
+#define TC_BASE (IO_BASE_PHYS + 0x1102000)
+
+/* Image Post-Processor */
+#define IPP2_BASE (IO_BASE_PHYS + 0x1200000)
+
+/* JPEG Decoder Unit */
+#define JDU_BASE (IO_BASE_PHYS + 0x1300000)
+
+/* TV output controller */
+#define TVO_BASE (IO_BASE_PHYS + 0x1400000)
+
+/* Camera controller */
+#define CAM_BASE (IO_BASE_PHYS + 0x1800000)
+
+/* External Bus Interfaces */
+#define EBI_BASE (IO_BASE_PHYS + 0x2001000)
+
+/* SPI controllers */
+#define SPI1_BASE (IO_BASE_PHYS + 0x2002000)
+#define SPI2_BASE (IO_BASE_PHYS + 0x2003000)
+
+/* SD/MMC controller */
+#define FCI_BASE (IO_BASE_PHYS + 0x2008000)
+
+/* Crypto Acceleration Engine */
+#define CAE_BASE (IO_BASE_PHYS + 0x2009000)
+
+/* Multimedia Timer Unit, aka MTU in Datasheet */
+#define MMTU_BASE (IO_BASE_PHYS + 0x2101000)
+
+/* System controller timer units */
+#define SCTU1_BASE (IO_BASE_PHYS + 0x2102000)
+#define SCTU2_BASE (IO_BASE_PHYS + 0x2103000)
+
+/* General Purpose I/O units */
+#define GPIOA_BASE (IO_BASE_PHYS + 0x2104000)
+#define GPIOB_BASE (IO_BASE_PHYS + 0x2104200)
+#define GPIOC_BASE (IO_BASE_PHYS + 0x2104400)
+#define GPIOD_BASE (IO_BASE_PHYS + 0x2104600)
+#define GPIOE_BASE (IO_BASE_PHYS + 0x2104800)
+#define GPIOF_BASE (IO_BASE_PHYS + 0x2104A00)
+
+/* External Interrupt controller */
+#define EXTINT_BASE (IO_BASE_PHYS + 0x2105000)
+
+/* Keyboard Scanner */
+#define KBS_BASE (IO_BASE_PHYS + 0x2106000)
+
+/* Pulse Width Modulators */
+#define PWM1_BASE (IO_BASE_PHYS + 0x2108000)
+#define PWM2_BASE (IO_BASE_PHYS + 0x2109000)
+#define PWM3_BASE (IO_BASE_PHYS + 0x210A000)
+
+/* I2C controllers */
+#define I2C1_BASE (IO_BASE_PHYS + 0x210C000)
+#define I2C2_BASE (IO_BASE_PHYS + 0x210D000)
+
+/* UARTs */
+#define UART1_BASE (IO_BASE_PHYS + 0x210E000)
+#define UART2_BASE (IO_BASE_PHYS + 0x210F000)
+
+/* Clock Generation Unit */
+#define CGU_BASE (IO_BASE_PHYS + 0x2200000)
+
+/* Time base Unit */
+#define TBU_BASE (IO_BASE_PHYS + 0x2201000)
+
+/* Power Down Control Unit */
+#define PDCU_BASE (IO_BASE_PHYS + 0x2202000)
+
+/* Watchdog & Reset Unit */
+#define WDRU_BASE (IO_BASE_PHYS + 0x2203000)
+
+/* System Configuration */
+#define SCON_BASE (IO_BASE_PHYS + 0x2204000)
+
+#endif /* __REGS_U6_H__ */
diff --git a/arch/arm/plat-u6xxx/include/mach/scon.h b/arch/arm/plat-u6xxx/include/mach/scon.h
new file mode 100644
index 0000000..67b7c89
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/scon.h
@@ -0,0 +1,121 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/scon.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Loic Pallardy <loic.pallardy@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * System Configuration Block registers
+ */
+
+#ifndef __ARCH_SCON_H
+#define __ARCH_SCON_H
+
+/*
+ * this structure allows to store SCON register values to set
+ * during initialization step
+ */
+
+struct u6_scon_config {
+ void __iomem *scon_reg_addr;
+ u32 scon_reg_value;
+};
+
+#define SCON_REGISTER_NB 15
+
+/* SCON SYSVER Register (32 bits) */
+#define SCON_SYSVER_OFFSET 0x0
+#define SCON_SYSVER_REG IO_ADDRESS(SCON_BASE + SCON_SYSVER_OFFSET)
+
+/* SCON SYSCON0 Register (32 bits) */
+#define SCON_SYSCON0_OFFSET 0x4
+#define SCON_SYSCON0_REG IO_ADDRESS(SCON_BASE + SCON_SYSCON0_OFFSET)
+
+/* SCON SYSPROT Register (32 bits) */
+#define SCON_SYSPROT_OFFSET 0x8
+#define SCON_SYSPROT_REG IO_ADDRESS(SCON_BASE + SCON_SYSPROT_OFFSET)
+
+/* SCON SYSMUX0 Register (32 bits) */
+#define SCON_SYSMUX0_OFFSET 0xC
+#define SCON_SYSMUX0_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX0_OFFSET)
+
+/* SCON SYSMUX1 Register (32 bits) */
+#define SCON_SYSMUX1_OFFSET 0x10
+#define SCON_SYSMUX1_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX1_OFFSET)
+
+/* SCON SYSMUX2 Register (32 bits) */
+#define SCON_SYSMUX2_OFFSET 0x14
+#define SCON_SYSMUX2_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX2_OFFSET)
+
+/* SCON SYSMUX3 Register (32 bits) */
+#define SCON_SYSMUX3_OFFSET 0x18
+#define SCON_SYSMUX3_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX3_OFFSET)
+
+/* SCON SYSMUX4 Register (32 bits) */
+#define SCON_SYSMUX4_OFFSET 0x1C
+#define SCON_SYSMUX4_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX4_OFFSET)
+
+/* SCON SYSMUX5 Register (32 bits) */
+#define SCON_SYSMUX5_OFFSET 0x20
+#define SCON_SYSMUX5_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX5_OFFSET)
+
+/* SCON SYSMUX6 Register (32 bits) */
+#define SCON_SYSMUX6_OFFSET 0x24
+#define SCON_SYSMUX6_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX6_OFFSET)
+
+/* SCON SYSMUX7 Register (32 bits) */
+#define SCON_SYSMUX7_OFFSET 0x28
+#define SCON_SYSMUX7_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX7_OFFSET)
+
+/* SCON SYSMUX8 Register (32 bits) */
+#define SCON_SYSMUX8_OFFSET 0x2C
+#define SCON_SYSMUX8_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX8_OFFSET)
+
+/* SCON SYSMUX9 Register (32 bits) */
+#define SCON_SYSMUX9_OFFSET 0x30
+#define SCON_SYSMUX9_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX9_OFFSET)
+
+/* SCON SYSMUX10 Register (32 bits) */
+#define SCON_SYSMUX10_OFFSET 0x34
+#define SCON_SYSMUX10_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX10_OFFSET)
+
+/* SCON SYSMUX11 Register (32 bits) */
+#define SCON_SYSMUX11_OFFSET 0x38
+#define SCON_SYSMUX11_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX11_OFFSET)
+
+/* SCON SYSPAD0 Register (32 bits) */
+#define SCON_SYSPAD0_OFFSET 0x50
+#define SCON_SYSPAD0_REG IO_ADDRESS(SCON_BASE + SCON_SYSPAD0_OFFSET)
+
+/* SCON SYSPAD1 Register (32 bits) */
+#define SCON_SYSPAD1_OFFSET 0x54
+#define SCON_SYSPAD1_REG IO_ADDRESS(SCON_BASE + SCON_SYSPAD1_OFFSET)
+
+/* SCON SYSPAD2 Register (32 bits) */
+#define SCON_SYSPAD2_OFFSET 0x58
+#define SCON_SYSPAD2_REG IO_ADDRESS(SCON_BASE + SCON_SYSPAD2_OFFSET)
+
+/* SCON SYSCON1 Register (32 bits) */
+#define SCON_SYSCON1_OFFSET 0x70
+#define SCON_SYSCON1_REG IO_ADDRESS(SCON_BASE + SCON_SYSCON1_OFFSET)
+
+/* SCON SYSIISMUX Register (32 bits) */
+#define SCON_SYSIISMUX_OFFSET 0x74
+#define SCON_SYSIISMUX_REG IO_ADDRESS(SCON_BASE + SCON_SYSIISMUX_OFFSET)
+
+/* SCON SYSAHBPROT Register (32 bits) */
+#define SCON_SYSAHBPROT_OFFSET 0x78
+#define SCON_SYSAHBPROT_REG IO_ADDRESS(SCON_BASE + SCON_SYSAHBPROT_OFFSET)
+
+/* SCON SYSIVSBRIDGE Register (32 bits) */
+#define SCON_SYSIVSBRIDGE_OFFSET 0x7C
+#define SCON_SYSIVSBRIDGE_REG IO_ADDRESS(SCON_BASE + SCON_SYSIVSBRIDGE_OFFSET)
+
+/* Register description for SYSPADx */
+/* SYSPAD configuration defines */
+#define SCON_PAD_PULL_UP 0
+#define SCON_PAD_REPEATER 1
+#define SCON_PAD_PLAIN_INPUT 2
+#define SCON_PAD_PULL_DOWN 3
+
+#endif
diff --git a/arch/arm/plat-u6xxx/include/mach/system.h b/arch/arm/plat-u6xxx/include/mach/system.h
new file mode 100644
index 0000000..cbe3380
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/system.h
@@ -0,0 +1,42 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/system.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+#include <mach/hardware.h>
+
+/* Watchdog & Reset Unit TIMER Register (16 bits) */
+#define WDRU_TIM_OFFSET 0x4
+
+static inline void arch_idle(void)
+{
+ /*
+ * This should do all the clock switching
+ * and wait for interrupt tricks
+ */
+ cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+ unsigned long flags;
+ /*
+ * To reset, we hit the on-board reset register
+ * in the system FPGA
+ */
+ /* diasble HW interruption */
+ hw_raw_local_irq_save(flags);
+ /* load watchdog with reset value */
+ outl(0x5, IO_ADDRESS(WDRU_BASE + WDRU_TIM_OFFSET));
+ /* wait for wachdog expiration */
+ while (1)
+ ;
+}
+
+#endif
diff --git a/arch/arm/plat-u6xxx/include/mach/timer.h b/arch/arm/plat-u6xxx/include/mach/timer.h
new file mode 100644
index 0000000..049e72d
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/timer.h
@@ -0,0 +1,24 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/timer.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef __PLAT_TIMER_H
+#define __PLAT_TIMER_H
+#ifdef U6_TIMER_C
+#define PUBLIC
+#else
+#define PUBLIC extern
+#endif
+
+struct sys_timer;
+
+PUBLIC struct sys_timer u6_timer;
+
+PUBLIC void __init u6_timer_init(void);
+
+#undef PUBLIC
+#endif
diff --git a/arch/arm/plat-u6xxx/include/mach/timex.h b/arch/arm/plat-u6xxx/include/mach/timex.h
new file mode 100644
index 0000000..1e71241
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/timex.h
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/timex.h
+ *
+ * Integrator architecture timex specifications
+ *
+ * Copyright (C) 1999 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 CLOCK_TICK_RATE (50000000 / 16)
diff --git a/arch/arm/plat-u6xxx/include/mach/uncompress.h b/arch/arm/plat-u6xxx/include/mach/uncompress.h
new file mode 100644
index 0000000..7dae14d
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/uncompress.h
@@ -0,0 +1,50 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/uncompress.h
+ *
+ * Copyright (C) 2010 ST-Ericsson SA
+ * 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
+ */
+
+#include <linux/io.h>
+#include "mach/hardware.h"
+
+/* UART THR Register (8 bits) */
+#define UART1_THR_OFFSET 0x0
+#define UART1_THR_REG IO_ADDRESS(UART1_BASE + UART1_THR_OFFSET)
+
+/* UART LSR Register (8 bits) */
+#define UART1_LSR_OFFSET 0x14
+#define UART1_LSR_REG IO_ADDRESS(UART1_BASE + UART1_LSR_OFFSET)
+
+static void putc(int c)
+{
+ if (c == '\n')
+ putc('\r');
+
+ while (!(readb(UART1_LSR_REG) & (1<<5)))
+ barrier();
+ writeb(c, UART1_THR_REG);
+}
+
+static inline void flush(void)
+{
+}
+
+/* nothing to do */
+#define arch_decomp_setup()
+
+#define arch_decomp_wdog()
diff --git a/arch/arm/plat-u6xxx/include/mach/vmalloc.h b/arch/arm/plat-u6xxx/include/mach/vmalloc.h
new file mode 100644
index 0000000..583033f
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/vmalloc.h
@@ -0,0 +1,10 @@
+/*
+ * linux/arch/arm/plat-u6/include/mach/vmalloc.h
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais@stericsson.com> for ST-Ericsson.
+ * 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.
+ */
+#define VMALLOC_END (PAGE_OFFSET + 0x28000000)
diff --git a/arch/arm/plat-u6xxx/io.c b/arch/arm/plat-u6xxx/io.c
new file mode 100644
index 0000000..d4ae93b
--- /dev/null
+++ b/arch/arm/plat-u6xxx/io.c
@@ -0,0 +1,34 @@
+/*
+ * linux/arch/arm/plat-u6xxx/io.c
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+#include <asm/mach/map.h>
+
+
+static struct map_desc u67xx_io_desc[] __initdata = {
+ {
+ .virtual = IO_BASE_VIRT, /* only peripherals */
+ .pfn = __phys_to_pfn(IO_BASE_PHYS),
+ .length = IO_SIZE,
+ .type = MT_DEVICE,
+ }
+};
+
+void __init u67xx_map_io(void)
+{
+ iotable_init(u67xx_io_desc, ARRAY_SIZE(u67xx_io_desc));
+}
+
diff --git a/arch/arm/plat-u6xxx/irq.c b/arch/arm/plat-u6xxx/irq.c
new file mode 100644
index 0000000..1c11a2e
--- /dev/null
+++ b/arch/arm/plat-u6xxx/irq.c
@@ -0,0 +1,231 @@
+/*
+ * linux/arch/arm/plat-u6xxx/irq.c
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Loic Pallardy <loic.pallardy@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <asm/irq.h>
+#include <mach/hardware.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <mach/irqs.h> /* U6 specific constants, types */
+
+#define INTC_REQUESTx_PENDING_MASK (1 << 31)
+#define INTC_REQUESTx_SET_SWINT_MASK (1 << 30)
+#define INTC_REQUESTx_CLR_SWINT_MASK (1 << 29)
+#define INTC_REQUESTx_WE_PRIORITY_MASK (1 << 28)
+#define INTC_REQUESTx_WE_TARGET_MASK (1 << 27)
+#define INTC_REQUESTx_WE_ENABLE_MASK (1 << 26)
+#define INTC_REQUESTx_WE_ACTIVE_LOW_MASK (1 << 25)
+#define INTC_REQUESTx_ACTIVE_LOW_MASK (1 << 17)
+#define INTC_REQUESTx_ENABLE_MASK (1 << 16)
+#define INTC_REQUESTx_TARGET_MASK (1 << 8)
+
+#define INTC_IID_USB_LP_INT 13
+
+static void u6_irq_mask(uint32_t irqno)
+{
+ if (irqno > 0 || irqno < IRQ_COUNT) {
+ unsigned long flags;
+ uint32_t a, v;
+
+ hw_raw_local_irq_save(flags);
+
+ a = INTC_REQUESTx(irqno);
+ v = readl(a);
+ v &= ~INTC_REQUESTx_ENABLE_MASK;
+ v |= INTC_REQUESTx_WE_ENABLE_MASK;
+ v |= INTC_REQUESTx_CLR_SWINT_MASK;
+ writel(v, a);
+
+ hw_raw_local_irq_restore(flags);
+ }
+}
+
+static void u6_irq_unmask(uint32_t irqno)
+{
+ if (irqno > 0 || irqno < IRQ_COUNT) {
+ unsigned long flags;
+ uint32_t a, v;
+
+ hw_raw_local_irq_save(flags);
+
+ a = INTC_REQUESTx(irqno);
+ v = readl(a);
+ v |= INTC_REQUESTx_ENABLE_MASK;
+ v |= INTC_REQUESTx_WE_ENABLE_MASK;
+ v |= INTC_REQUESTx_CLR_SWINT_MASK;
+ writel(v, a);
+
+ hw_raw_local_irq_restore(flags);
+ }
+}
+
+static int u6_irq_type(unsigned irqno, unsigned type)
+{
+ int l;
+ uint32_t reg = INTC_REQUESTx(irqno);
+
+ if (irqno > 0 || irqno < IRQ_COUNT) {
+ if (type == IRQF_TRIGGER_LOW) {
+ l = (INTC_REQUESTx_ACTIVE_LOW_MASK
+ | INTC_REQUESTx_WE_ACTIVE_LOW_MASK);
+ } else if (type == IRQF_TRIGGER_HIGH) {
+ l = (INTC_REQUESTx_WE_ACTIVE_LOW_MASK);
+ } else {
+ goto bad;
+ }
+
+ writel(l, reg);
+ return 0;
+
+ }
+
+bad:
+ return -EINVAL;
+}
+
+int u6_irq_enabled(uint32_t irqno)
+{
+ if (irqno > 0 || irqno < IRQ_COUNT) {
+ uint32_t a = INTC_REQUESTx(irqno);
+ uint32_t v = readl(a);
+
+ return v & INTC_REQUESTx_ENABLE_MASK;
+ } else
+ return 0;
+}
+
+static struct irq_chip u6_irq_chip = {
+ .ack = u6_irq_mask,
+ .mask = u6_irq_mask, /* disable irqs */
+ .unmask = u6_irq_unmask, /* enable irqs */
+ .set_type = u6_irq_type,
+};
+
+
+#if defined(CONFIG_ARCH_U67XX)
+
+static const uint32_t u6_irq_config[] = {
+ 0, /* GHOST 0 */
+ INTC_REQUESTx_ACTIVE_LOW_MASK, /* EXTINT1 1 */
+ INTC_REQUESTx_ACTIVE_LOW_MASK, /* EXTINT2 2 */
+ INTC_REQUESTx_ACTIVE_LOW_MASK, /* EXTINT3 3 */
+ 0, /* RFRD 4 */
+ 0, /* MTU 5 */
+ 0, /* IIS 6 */
+ 0, /* USB 7 */
+ INTC_REQUESTx_ACTIVE_LOW_MASK, /* I2C2 8 */
+ 0, /* TVO 9 */
+ 0, /* 3G_WUP 10 */
+ 0, /* 3G_CALINT 11 */
+ 0, /* 3G_FRAME_IT 12 */
+ 0, /* GPADCINT 13 */
+ 0, /* ARM9_COMMTX 14 */
+ 0, /* ARM9_COMMRX 15 */
+ 0, /* KBS 16 */
+ 0, /* SCTU2 17 */
+ 0, /* SCTU1 18 */
+ 0, /* PIO1 19 */
+ 0, /* PIO2 20 */
+ 0, /* FINT0 21 */
+ 0, /* FINT1 22 */
+ 0, /* UART2 23 */
+ 0, /* UART1 24 */
+ 0, /* SPI2 25 */
+ 0, /* SPI1 26 */
+ 0, /* FCI 27 */
+ INTC_REQUESTx_ACTIVE_LOW_MASK, /* I2C1 28 */
+ 0, /* DMAU 29 */
+ 0, /* USIM 30 */
+ 0, /* RESERVED31 31 */
+ INTC_REQUESTx_ACTIVE_LOW_MASK, /* MSI 32 */
+ 0, /* JDI 33 */
+ 0, /* JDU 34 */
+ 0, /* NFI 35 */
+ 0, /* IPP 36 */
+ 0, /* VDC 37 */
+ 0, /* VEC 38 */
+ 0, /* VDE 39 */
+ INTC_REQUESTx_ACTIVE_LOW_MASK, /* CAM 40 */
+ 0, /* ETB_ACQ 41 */
+ 0, /* ETB_FULL 42 */
+ 0, /* DIGRF_TX 43 */
+ 0, /* DIGRF_RX 44 */
+ 0, /* RESERVED45 45 */
+ 0, /* FIR_FI 46 */
+ 0, /* FIR 47 */
+ 0, /* PDCU 48 */
+ 0, /* MC2SC0 49 */
+ 0, /* MC2SC1 50 */
+ 0, /* MC2SC2 51 */
+ 0, /* MC2SC3 52 */
+ 0, /* MC2SC4 53 */
+ 0, /* MC2SC5 54 */
+ 0, /* MC2SC6 55 */
+ 0, /* MC2SC7 56 */
+ 0, /* Reserved 57 */
+ 0, /* Reserved 58 */
+ 0, /* Reserved 59 */
+ 0, /* Reserved 60 */
+ 0, /* Reserved 61 */
+ 0, /* Reserved 62 */
+ 0, /* Reserved 63 */
+ 0, /* Reserved 64 */
+};
+
+#endif
+
+static const uint32_t u6_irq_irq_priority;
+static const uint32_t u6_irq_fiq_priority;
+
+void __init u6_init_irq(void)
+{
+ unsigned int irqno;
+
+ /* Clock interrupt controller.
+ */
+ struct clk *clk = clk_get(NULL, "INTC");
+ clk_enable(clk);
+ clk_put(clk);
+
+ /* The address of the vector table INTCdata.asm is assumed to be aligned
+ * to a 2KB boundary. Thus the register access value will be padded with
+ * zeroes, which is conforming to the 'READ_ONLY' attributes of the LS
+ * 11 bits. We are using the same table for both IRQ and FIQ.
+ */
+ writel(0, INTC_VECTOR_FIQ_REG); /* no vector IRQ */
+ writel(0, INTC_VECTOR_IRQ_REG); /* no vector FIQ */
+
+ writel(u6_irq_irq_priority, INTC_PRIOMASK_IRQ_REG);
+ writel(u6_irq_fiq_priority, INTC_PRIOMASK_FIQ_REG);
+
+ /* Initialize the individual interrupt sources.
+ */
+ for (irqno = 1; irqno < IRQ_COUNT; irqno += 1) {
+ uint32_t a = INTC_REQUESTx(irqno);
+ uint32_t v = u6_irq_config[irqno];
+
+ v |= 4;
+ v |= INTC_REQUESTx_WE_ACTIVE_LOW_MASK;
+ v |= INTC_REQUESTx_WE_TARGET_MASK;
+ v |= INTC_REQUESTx_WE_PRIORITY_MASK;
+ v |= INTC_REQUESTx_WE_ENABLE_MASK;
+ v |= INTC_REQUESTx_CLR_SWINT_MASK;
+
+ writel(v, a);
+
+ set_irq_chip(irqno, &u6_irq_chip);
+ set_irq_handler(irqno, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID | IRQF_PROBE);
+ }
+}
diff --git a/arch/arm/plat-u6xxx/timer.c b/arch/arm/plat-u6xxx/timer.c
new file mode 100644
index 0000000..62f13f5
--- /dev/null
+++ b/arch/arm/plat-u6xxx/timer.c
@@ -0,0 +1,679 @@
+/*
+ * linux/arch/arm/plat-u6xxx/timer.c
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Vincent Guittot <vincent.guittot@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/mach/time.h>
+
+#include <mach/hardware.h>
+
+#include <asm/mach/irq.h>
+#include <linux/interrupt.h>
+#include <mach/irqs.h>
+
+#include <linux/clk.h>
+
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+
+#ifdef CONFIG_U6_POWER_SYSFS
+#include "power_sysfs.h"
+#endif
+
+/*** System timer variable ***/
+struct sys_timer u6_timer;
+
+/*** Module definition ***/
+/*************************/
+
+#define MODULE_NAME "U6_TIMER"
+#define PKMOD MODULE_NAME ": "
+
+#undef U6_TIMER_DEBUG
+#if defined(U6_TIMER_DEBUG)
+#define debug(fmt, args...) \
+ printk(PKMOD fmt, ## args)
+#else
+#define debug(fmt, args...)
+#endif
+
+#define U6_MMTU_CLOCK_SOURCE
+
+/*** MMTU clock devices ***/
+/*************************/
+
+/*** MMTU HW ip register index definition ***/
+#define MMTU_CON_IDX 0
+#define MMTU_TCVAL_IDX 1
+#define MMTU_PRESCALER_IDX 2
+#define MMTU_MATCH_CON_IDX 3
+#define MMTU_MATCH0_IDX 5
+#define MMTU_MATCH1_IDX 6
+#define MMTU_INT_OFFSET 0x3F4
+#define MMTU_MOD_CONF_IDX 1
+#define MMTU_INT_CLR_ENA_IDX 2
+#define MMTU_INT_SET_ENA_IDX 3
+#define MMTU_INT_STATUS_IDX 4
+#define MMTU_INT_ENABLE_IDX 5
+#define MMTU_INT_CLR_STAT_IDX 6
+#define MMTU_INT_SET_STAT_IDX 7
+
+#define MMTU_IRQ_MASK 0x1
+#define MMTU_USED_MATCH_IDX MMTU_MATCH0_IDX
+
+/* MMTU sys clock definition */
+#define MMTU_SYS_FRQ 13000000
+
+/*** MMTU Clock event device ***/
+#define MMTU_ROOT_FRQ 8000
+static int u6_mmtu_set_next_event(unsigned long cycles,
+ struct clock_event_device *evt);
+static void u6_mmtu_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt);
+
+static struct clock_event_device clockevent_mmtu = {
+ .name = "mmtu_timer",
+ .rating = 360,
+ .shift = 30,
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .set_next_event = u6_mmtu_set_next_event,
+ .set_mode = u6_mmtu_set_mode,
+};
+
+/*** MMTU Clock source device ***/
+#ifdef U6_MMTU_CLOCK_SOURCE
+static cycle_t u6_mmtu_read(struct clocksource *);
+
+static struct clocksource clocksource_mmtu = {
+ .name = "mmtu_timer",
+ .rating = 360,
+ .read = u6_mmtu_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 8,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+#endif
+
+/*** MMTU driver ***/
+#define RELOAD_COUNTER_POWER_MMTU 32
+#define RELOAD_COUNTER_MMTU (1 << RELOAD_COUNTER_POWER_MMTU)
+
+struct mmtu_ctxt {
+ unsigned long *base;
+ int autoreload;
+ uint32_t compvalue;
+ uint32_t endvalue;
+ struct clk *clk;
+ int mode;
+};
+
+struct mmtu_ctxt mmtu_table[1] = {
+ {
+ .base = (unsigned long *)IO_ADDRESS(MMTU_BASE),
+ .autoreload = 0,
+ .compvalue = 0,
+ .endvalue = 0,
+ .clk = NULL,
+ .mode = 0,
+ },
+};
+
+static inline struct mmtu_ctxt *u6_mmtu_get_context(int id)
+{
+ return &(mmtu_table[id]);
+}
+
+static inline int u6_mmtu_timer_start(unsigned long cycles, int id);
+static inline void u6_mmtu_clk_enable(int id);
+static inline void u6_mmtu_clk_disable(int id);
+
+static irqreturn_t
+u6_mmtu_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ uint8_t status, enable;
+ struct mmtu_ctxt *mmtu;
+
+ mmtu = u6_mmtu_get_context(0);
+
+ status = readl((mmtu->base + MMTU_INT_OFFSET + MMTU_INT_STATUS_IDX));
+ enable = readl((mmtu->base + MMTU_INT_OFFSET + MMTU_INT_ENABLE_IDX));
+
+ debug("mmtu_timer_interrupt %d\n", status);
+
+ if (status & enable & MMTU_IRQ_MASK) {
+ struct clock_event_device *evt = &clockevent_mmtu;
+
+ writel(MMTU_IRQ_MASK, (mmtu->base + MMTU_INT_OFFSET
+ + MMTU_INT_CLR_STAT_IDX));
+
+ if (mmtu->autoreload)
+ u6_mmtu_timer_start(mmtu->compvalue, 0);
+ else
+ writel(MMTU_IRQ_MASK,
+ (mmtu->base + MMTU_INT_OFFSET +
+ MMTU_INT_CLR_ENA_IDX));
+
+ if (evt->event_handler)
+ evt->event_handler(evt);
+ }
+ return IRQ_HANDLED;
+}
+
+static struct irqaction u6_mmtu_timer_irq = {
+ .name = "U6 MMTU timer Tick",
+ .flags = IRQF_DISABLED,
+ .handler = (irq_handler_t) u6_mmtu_timer_interrupt,
+};
+
+static inline void u6_mmtu_clk_enable(int id)
+{
+ struct mmtu_ctxt *mmtu = u6_mmtu_get_context(id);
+
+ /* Clock Multimedia Timer Unit.
+ */
+ if ((mmtu->clk != NULL) && (mmtu->mode == 0)) {
+ debug("mmtu_clk_enable\n");
+ mmtu->mode = 1;
+ clk_enable(mmtu->clk);
+ }
+}
+
+static inline void u6_mmtu_clk_disable(int id)
+{
+ struct mmtu_ctxt *mmtu = u6_mmtu_get_context(id);
+
+ /* Clock Multimedia Timer Unit.
+ */
+ if ((mmtu->clk != NULL) && (mmtu->mode == 1)) {
+ debug("mmtu_clk_disable\n");
+ clk_disable(mmtu->clk);
+ mmtu->mode = 0;
+ }
+}
+
+static inline int u6_mmtu_timer_start(unsigned long cycles, int id)
+{
+ struct mmtu_ctxt *mmtu = u6_mmtu_get_context(id);
+
+ debug("mmtu_timer_start %d\n", cycles);
+ u6_mmtu_clk_enable(id);
+
+ /* MMTU limitation : can't set a value smaller or equal to tcval + 1 */
+ cycles = cycles < 2 ? 2 : cycles;
+
+ mmtu->compvalue = cycles;
+
+ mmtu->endvalue = mmtu->compvalue
+ + readl((mmtu->base + MMTU_TCVAL_IDX));
+
+ writel(MMTU_IRQ_MASK,
+ (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_STAT_IDX));
+
+ writel(mmtu->endvalue, (mmtu->base + MMTU_USED_MATCH_IDX));
+
+ writel(MMTU_IRQ_MASK,
+ (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_SET_ENA_IDX));
+
+ /* the value has already expired */
+ if ((mmtu->endvalue <= readl((mmtu->base + MMTU_TCVAL_IDX)))
+ && (mmtu->endvalue > mmtu->compvalue)
+ && !(readl((mmtu->base + MMTU_INT_OFFSET
+ + MMTU_INT_STATUS_IDX)) & MMTU_IRQ_MASK))
+ writel(MMTU_IRQ_MASK, (mmtu->base + MMTU_INT_OFFSET
+ + MMTU_INT_SET_STAT_IDX));
+
+ return 0;
+}
+
+static int u6_mmtu_timer_init(int id, unsigned long reload,
+ unsigned long prescale, int over_it)
+{
+
+ struct mmtu_ctxt *mmtu = u6_mmtu_get_context(id);
+
+ debug("mmtu_timer_init %d\n", id);
+
+ /* Enable clock */
+/*
+ u6_mmtu_clk_enable(id);
+ clk mngt not available yet
+ directly enable it
+*/
+ {
+ unsigned long flags;
+ unsigned long reg;
+ hw_raw_local_irq_save(flags);
+ reg = readl(CGU_GATESC2_REG);
+ reg |= 0x1 << 2;
+ writel(reg, CGU_GATESC2_REG);
+ hw_raw_local_irq_restore(flags);
+ }
+
+ /* Reset timer */
+ /* reset control register */
+ writel(0x0000, (mmtu->base + MMTU_CON_IDX));
+ writel(0x0002, (mmtu->base + MMTU_CON_IDX));
+ /* reset control register */
+ writel(0x0000, (mmtu->base + MMTU_CON_IDX));
+
+ /* clear whole enable irq register */
+ writel(0xFF, (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_ENA_IDX));
+ /* clear whole status register */
+ writel(0xFF, (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_STAT_IDX));
+
+ /* reset pre-scaler reload register */
+ writel(0x00000000, (mmtu->base + MMTU_PRESCALER_IDX));
+
+ /* reset match control register */
+ writel(0x0000, (mmtu->base + MMTU_MATCH_CON_IDX));
+ /* reset match 0 register */
+ writel(0x00000000, (mmtu->base + MMTU_MATCH0_IDX));
+ /* reset match 1 register */
+ writel(0x00000000, (mmtu->base + MMTU_MATCH1_IDX));
+
+ /* Initialize timer */
+ writel(prescale - 1, (mmtu->base + MMTU_PRESCALER_IDX));
+ /* power of 2 system clock */
+ writel(reload, (mmtu->base + MMTU_MATCH0_IDX));
+
+ /* enable counter register */
+ writel(0x0001, (mmtu->base + MMTU_CON_IDX));
+
+ /* clear whole status register */
+ writel(0xFF, (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_STAT_IDX));
+
+ if (id == 0)
+ setup_irq(IRQ_MMTU, &u6_mmtu_timer_irq);
+
+ /* Disable clock */
+#ifndef U6_MMTU_CLOCK_SOURCE
+ u6_mmtu_clk_disable(id);
+#endif
+ return 0;
+}
+
+/*** MMTU Clock event device ***/
+
+static int u6_mmtu_set_next_event(unsigned long cycles,
+ struct clock_event_device *evt)
+{
+ debug("mmtu_set_next_event %d\n", cycles);
+ u6_mmtu_timer_start(cycles, 0);
+
+ return 0;
+}
+
+static void u6_mmtu_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ struct mmtu_ctxt *mmtu = u6_mmtu_get_context(0);
+ unsigned long reg;
+
+ debug("mmtu_set_mode %d\n", mode);
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_UNUSED:
+ writel(MMTU_IRQ_MASK,
+ (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_ENA_IDX));
+ writel(MMTU_IRQ_MASK,
+ (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_STAT_IDX));
+
+ reg = readl((mmtu->base + MMTU_TCVAL_IDX));
+ writel(reg - 1, (mmtu->base + MMTU_USED_MATCH_IDX));
+
+#ifndef U6_MMTU_CLOCK_SOURCE
+ u6_mmtu_clk_disable(0);
+
+ if (mmtu->clk != NULL)
+ clk_put(mmtu->clk);
+#endif
+ mmtu->autoreload = 0;
+ break;
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ mmtu->autoreload = 0;
+
+ if (mmtu->clk == NULL) {
+ mmtu->clk = clk_get(0, "MMTU");
+ if (IS_ERR(mmtu->clk))
+ mmtu->clk = NULL;
+ }
+
+ writel(MMTU_IRQ_MASK,
+ (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_STAT_IDX));
+ writel(MMTU_IRQ_MASK,
+ (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_SET_ENA_IDX));
+ case CLOCK_EVT_MODE_ONESHOT:
+ case CLOCK_EVT_MODE_RESUME:
+ mmtu->autoreload = 0;
+ break;
+ case CLOCK_EVT_MODE_PERIODIC:
+ writel(MMTU_IRQ_MASK,
+ (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_SET_ENA_IDX));
+ mmtu->autoreload = 1;
+ break;
+ }
+}
+
+static void u6_clockevent_init_mmtu(void)
+{
+ printk(PKMOD "clockevent_init_mmtu\n");
+
+ /* prescale 13Mhz -> 1Mhz */
+#ifndef U6_MMTU_CLOCK_SOURCE
+ u6_mmtu_timer_init(0, 0, (MMTU_SYS_FRQ / MMTU_ROOT_FRQ), 0);
+#endif
+
+/* issue it is shorter than reality and generates spurious irq */
+/* clockevent_mmtu.mult = div_sc(MMTU_ROOT_FRQ, NSEC_PER_SEC,
+ * clockevent_mmtu.shift) + 1;*/
+ clockevent_mmtu.mult =
+ div_sc(MMTU_ROOT_FRQ, NSEC_PER_SEC, clockevent_mmtu.shift);
+
+/* clockevent_mmtu.max_delta_ns = div_sc(RELOAD_COUNTER_MMTU,
+ * clockevent_mmtu.mult, clockevent_mmtu.shift);*/
+/* In fact it is wider than the 32bits variable !!! */
+ clockevent_mmtu.max_delta_ns = 0xFFFFFFFF;
+
+/* MMTU HW limitation: match register can't be set w/ tcval+1 */
+/* clockevent_mmtu.min_delta_ns = div_sc(1, clockevent_mmtu.mult,
+ * clockevent_mmtu.shift)+1;*/
+ clockevent_mmtu.min_delta_ns =
+ div_sc(2, clockevent_mmtu.mult, clockevent_mmtu.shift) + 1;
+ /* avoid to much timer interrupt with 10us min between 2 irq */
+ if (clockevent_mmtu.min_delta_ns < 10000)
+ clockevent_mmtu.min_delta_ns = 10000;
+ else if (clockevent_mmtu.max_delta_ns < 10000)
+ clockevent_mmtu.min_delta_ns = clockevent_mmtu.max_delta_ns>>1;
+
+ clockevent_mmtu.cpumask = get_cpu_mask(0);
+ clockevents_register_device(&clockevent_mmtu);
+
+ u6_mmtu_set_next_event(MMTU_ROOT_FRQ / HZ, &clockevent_mmtu);
+}
+
+/*** MMTU Clock source device ***/
+#ifdef U6_MMTU_CLOCK_SOURCE
+
+static cycle_t u6_mmtu_read(struct clocksource *source)
+{
+ struct mmtu_ctxt *mmtu = u6_mmtu_get_context(0);
+
+ return readl((mmtu->base + MMTU_TCVAL_IDX)) & source->mask;
+}
+
+static void u6_clocksource_init_mmtu(void)
+{
+ printk(PKMOD "clocksource_init_mmtu\n");
+
+ if (MMTU_ROOT_FRQ >= 1000000)
+ clocksource_mmtu.mult =
+ clocksource_khz2mult((MMTU_ROOT_FRQ / 1000),
+ clocksource_mmtu.shift);
+ else
+ clocksource_mmtu.mult = clocksource_hz2mult((MMTU_ROOT_FRQ),
+ clocksource_mmtu.shift);
+
+ u6_mmtu_timer_init(0, 0, (MMTU_SYS_FRQ / MMTU_ROOT_FRQ), 0);
+
+ clocksource_register(&clocksource_mmtu);
+}
+
+unsigned long long u6_mmtu_time(void)
+{
+ unsigned long long ticks64 = u6_mmtu_read(&clocksource_mmtu);
+
+ return (ticks64 * clocksource_mmtu.mult) >> clocksource_mmtu.shift;
+}
+#endif
+
+/*** SysFs interface ***/
+/***********************/
+#ifdef CONFIG_U6_POWER_SYSFS
+
+/*** Clock event sysfs interface **/
+
+#define shows_one_evt(file_name, object) \
+static ssize_t show_##file_name##_evt \
+(struct kobject *kobj, char *buf) \
+{ \
+ return sprintf(buf, "%s\n", clockevent_mmtu.object); \
+}
+
+#define showu_one_evt(file_name, object) \
+static ssize_t show_##file_name##_evt \
+(struct kobject *kobj, char *buf) \
+{ \
+ return sprintf(buf, "%u\n", clockevent_mmtu.object); \
+}
+
+#define showlu_one_evt(file_name, object) \
+static ssize_t show_##file_name##_evt \
+(struct kobject *kobj, char *buf) \
+{ \
+ return sprintf(buf, "%lu\n", clockevent_mmtu.object); \
+}
+
+#define storelu_one_evt(file_name, object) \
+static ssize_t store_##file_name##_evt \
+(struct kobject *kobj, const char *buf, size_t size) \
+{ \
+ unsigned long object; \
+ strict_strtoul(buf, 10, &object); \
+ clockevent_mmtu.object = object; \
+ return size; \
+}
+
+#define showx_one_evt(file_name, object) \
+static ssize_t show_##file_name##_evt \
+(struct kobject *kobj, char *buf) \
+{ \
+ return sprintf(buf, "0x%x\n", clockevent_mmtu.object); \
+}
+
+shows_one_evt(name, name);
+showu_one_evt(rating, rating);
+showlu_one_evt(mult, mult);
+#ifdef CONFIG_U6_TIMER_TUNE
+storelu_one_evt(mult, mult);
+#endif
+showu_one_evt(shift, shift);
+showx_one_evt(features, features);
+showlu_one_evt(min_delta_ns, min_delta_ns);
+showlu_one_evt(max_delta_ns, max_delta_ns);
+
+static ssize_t show_clock_mode_evt(struct kobject *kobj, char *buf)
+{
+ struct mmtu_ctxt *mmtu = u6_mmtu_get_context(0);
+
+ return sprintf(buf, "%u\n", mmtu->mode);
+}
+
+static ssize_t show_periodic_evt(struct kobject *kobj, char *buf)
+{
+ struct mmtu_ctxt *mmtu = u6_mmtu_get_context(0);
+
+ return sprintf(buf, "%u\n", mmtu->autoreload);
+}
+
+static ssize_t show_next_event_evt(struct kobject *kobj, char *buf)
+{
+ struct mmtu_ctxt *mmtu = u6_mmtu_get_context(0);
+ uint8_t enable;
+
+ enable = readb((mmtu->base + MMTU_INT_OFFSET + MMTU_INT_ENABLE_IDX));
+
+ if (enable & 0x1)
+ return sprintf(buf, "%lu\n", (unsigned long)mmtu->endvalue);
+ else
+ return sprintf(buf, "No Event Set\n");
+}
+
+define_one_ro_ext(name, _evt);
+define_one_ro_ext(rating, _evt);
+#ifdef CONFIG_U6_TIMER_TUNE
+define_one_rw_ext(mult, _evt);
+#else
+define_one_ro_ext(mult, _evt);
+#endif
+define_one_ro_ext(shift, _evt);
+define_one_ro_ext(features, _evt);
+define_one_ro_ext(min_delta_ns, _evt);
+define_one_ro_ext(max_delta_ns, _evt);
+define_one_ro_ext(clock_mode, _evt);
+define_one_ro_ext(periodic, _evt);
+define_one_ro_ext(next_event, _evt);
+
+static struct attribute *dbs_attributes_event[] = {
+ &name_evt.attr,
+ &rating_evt.attr,
+ &mult_evt.attr,
+ &shift_evt.attr,
+ &features_evt.attr,
+ &min_delta_ns_evt.attr,
+ &max_delta_ns_evt.attr,
+ &clock_mode_evt.attr,
+ &periodic_evt.attr,
+ &next_event_evt.attr,
+ NULL
+};
+
+static struct attribute_group dbs_attr_event_group = {
+ .attrs = dbs_attributes_event,
+ .name = "mmtu_event",
+};
+
+/*** Clock source sysfs interface ***/
+#ifdef U6_MMTU_CLOCK_SOURCE
+
+#define shows_one_src(file_name, object) \
+static ssize_t show_##file_name##_src \
+(struct kobject *kobj, char *buf) \
+{ \
+ return sprintf(buf, "%s\n", clocksource_mmtu.object); \
+}
+
+#define showu_one_src(file_name, object) \
+static ssize_t show_##file_name##_src \
+(struct kobject *kobj, char *buf) \
+{ \
+ return sprintf(buf, "%u\n", clocksource_mmtu.object); \
+}
+
+#define showlu_one_src(file_name, object) \
+static ssize_t show_##file_name##_src \
+(struct kobject *kobj, char *buf) \
+{ \
+ return sprintf(buf, "%lu\n", clocksource_mmtu.object); \
+}
+
+#define showlx_one_src(file_name, object) \
+static ssize_t show_##file_name##_src \
+(struct kobject *kobj, char *buf) \
+{ \
+ return sprintf(buf, "0x%lx\n", clocksource_mmtu.object); \
+}
+
+#define showllx_one_src(file_name, object) \
+static ssize_t show_##file_name##_src \
+(struct kobject *kobj, char *buf) \
+{ \
+ return sprintf(buf, "0x%llx\n", clocksource_mmtu.object); \
+}
+
+shows_one_src(name, name);
+showu_one_src(rating, rating);
+showu_one_src(mult, mult);
+showu_one_src(shift, shift);
+showllx_one_src(mask, mask);
+showlx_one_src(flags, flags);
+
+static ssize_t show_stamp_src(struct kobject *kobj, char *buf)
+{
+ return sprintf(buf, "%lu\n",
+ (unsigned long)(u6_mmtu_read(&clocksource_mmtu)));
+}
+
+static ssize_t show_time_src(struct kobject *kobj, char *buf)
+{
+ return sprintf(buf, "%llu\n", u6_mmtu_time());
+}
+
+define_one_ro_ext(name, _src);
+define_one_ro_ext(rating, _src);
+define_one_ro_ext(mult, _src);
+define_one_ro_ext(shift, _src);
+define_one_ro_ext(mask, _src);
+define_one_ro_ext(flags, _src);
+define_one_ro_ext(stamp, _src);
+define_one_ro_ext(time, _src);
+
+static struct attribute *dbs_attributes_srce[] = {
+ &name_src.attr,
+ &rating_src.attr,
+ &mult_src.attr,
+ &shift_src.attr,
+ &mask_src.attr,
+ &flags_src.attr,
+ &stamp_src.attr,
+ &time_src.attr,
+ NULL
+};
+
+static struct attribute_group dbs_attr_srce_group = {
+ .attrs = dbs_attributes_srce,
+ .name = "mmtu_source",
+};
+#endif
+#endif
+
+/*** System timer init ***/
+/*************************/
+
+void __init u6_timer_init(void)
+{
+ printk(PKMOD "mmtu_timer_init\n");
+
+#ifdef U6_MMTU_CLOCK_SOURCE
+ u6_clocksource_init_mmtu();
+#endif
+
+ u6_clockevent_init_mmtu();
+
+}
+
+struct sys_timer u6_timer = {
+ .init = u6_timer_init,
+#ifndef CONFIG_GENERIC_TIME
+ .offset = NULL,
+#endif
+};
+
+#ifdef CONFIG_U6_POWER_SYSFS
+static int __init u6_mmtu_init_sysfs(void)
+{
+ printk(PKMOD "mmtu_init_sysfs\n");
+
+#ifdef U6_MMTU_CLOCK_SOURCE
+ if (sysfs_create_group(&u6_power_kobj, &dbs_attr_srce_group))
+ printk(PKMOD "Unable to register %s in sysfs\n",
+ dbs_attr_srce_group.name);
+#endif
+
+ if (sysfs_create_group(&u6_power_kobj, &dbs_attr_event_group))
+ printk(PKMOD "Unable to register %s in sysfs\n",
+ dbs_attr_event_group.name);
+
+ return 0;
+}
+
+module_init(u6_mmtu_init_sysfs);
+#endif
--
1.7.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 2/6] U6715 clocks gating management U6 clock generic driver & U6715 cgu clock specific (V2)
2010-05-27 8:27 U6/U6715 ARM architecture files, 2nd try Philippe Langlais
2010-05-27 8:27 ` [PATCH 1/6] U6/U6715 ARM architecture files Philippe Langlais
@ 2010-05-27 8:27 ` Philippe Langlais
2010-06-24 14:14 ` Russell King - ARM Linux
2010-05-27 8:27 ` [PATCH 3/6] U6715 gpio platform driver This driver is U6 platform generic (V2) Philippe Langlais
` (3 subsequent siblings)
5 siblings, 1 reply; 17+ messages in thread
From: Philippe Langlais @ 2010-05-27 8:27 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Philippe Langlais <philippe.langlais@stericsson.com>
---
arch/arm/mach-u67xx/Makefile | 2 +-
arch/arm/mach-u67xx/cgu.c | 760 ++++++++++++++++++++++++++
arch/arm/mach-u67xx/clock_u67xx.h | 876 ++++++++++++++++++++++++++++++
arch/arm/plat-u6xxx/Makefile | 2 +-
arch/arm/plat-u6xxx/clock.c | 650 ++++++++++++++++++++++
arch/arm/plat-u6xxx/include/mach/clock.h | 376 +++++++++++++
arch/arm/plat-u6xxx/timer.c | 1 +
7 files changed, 2665 insertions(+), 2 deletions(-)
create mode 100644 arch/arm/mach-u67xx/cgu.c
create mode 100644 arch/arm/mach-u67xx/clock_u67xx.h
create mode 100644 arch/arm/plat-u6xxx/clock.c
create mode 100644 arch/arm/plat-u6xxx/include/mach/clock.h
diff --git a/arch/arm/mach-u67xx/Makefile b/arch/arm/mach-u67xx/Makefile
index 38cf624..0572db8 100644
--- a/arch/arm/mach-u67xx/Makefile
+++ b/arch/arm/mach-u67xx/Makefile
@@ -5,7 +5,7 @@
## Object file lists.
# Common support
-obj-y := devices.o
+obj-y := devices.o cgu.o
# Specific board support
obj-$(CONFIG_MACH_U67XX_WAVEC_2GB) += board_u67xx_wavex.o
diff --git a/arch/arm/mach-u67xx/cgu.c b/arch/arm/mach-u67xx/cgu.c
new file mode 100644
index 0000000..58a6a7a
--- /dev/null
+++ b/arch/arm/mach-u67xx/cgu.c
@@ -0,0 +1,760 @@
+/*
+ * arch/arm/mach-u67xx/cgu.c
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Arnaud Troel <arnaud.troel@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * U67XX Clock Gating Unit basic driver/wrapper
+ * Based on the code from Michel Jaouen
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <mach/hardware.h>
+#include <mach/clock.h>
+
+#include "clock_u67xx.h"
+
+#define MODULE_NAME "U6_CGU"
+#define PKMOD MODULE_NAME ": "
+
+#if defined(DEBUG_CGU)
+#define debug(fmt, args...) \
+ printk(PKMOD fmt, ## args)
+#else
+#define debug(fmt, args...)
+#endif
+
+/**
+ * U6 hw low level access clock functions
+ **/
+static void u6_clk_disable(struct clk *clk);
+static int u6_clk_enable(struct clk *clk);
+
+/**
+ * HW enable clock function.
+ **/
+
+static int u67xx_cgu_enable_fake_clock(struct clk *clk)
+{
+ debug("u67xx_cgu_enable_fake_clock for %s\n", clk->name);
+ return 0;
+}
+
+static int u67xx_cgu_enable_hw_clock(struct clk *clk)
+{
+ unsigned long value;
+ debug("u67xx_cgu_enable_hw_clock for %s\n", clk->name);
+
+ if (unlikely(clk->enable_reg == 0)) {
+ printk(KERN_ERR "Enable for %s without enable register\n",
+ clk->name);
+ return 0;
+ }
+
+ value = readl(clk->enable_reg);
+ value |= 1 << clk->enable_bit;
+ writel(value, clk->enable_reg);
+
+ return 0;
+}
+
+static int u67xx_cgu_enable_tvo_pll_clock(struct clk *clk)
+{
+ unsigned long value;
+
+ debug("u67xx_cgu_enable_tvo_pll_clock for %s\n", clk->name);
+
+ if (unlikely(clk->enable_reg == 0)) {
+ printk(KERN_ERR "Enable for %s without enable register\n",
+ clk->name);
+ return 0;
+ }
+
+ value = readl(clk->enable_reg);
+ value |= 1 << clk->enable_bit;
+ writel(value, clk->enable_reg);
+
+ /* wait pll lock */
+ do {
+ value = readl(clk->enable_reg);
+ } while (!(value & (0x1 << 16)));
+
+ return 0;
+}
+
+static int u67xx_cgu_enable_shared_clock(struct clk *clk)
+{
+ unsigned long value;
+
+ debug("u67xx_cgu_enable_shared_clock for %s\n", clk->name);
+
+ if (unlikely(clk->enable_reg == 0)) {
+ printk(KERN_ERR "Enable for %s without enable register\n",
+ clk->name);
+ return 0;
+ }
+
+ value = readl(clk->enable_reg);
+ value |= 1 << clk->enable_bit;
+ writel(value, clk->enable_reg);
+
+ return 0;
+}
+
+static int u67xx_cgu_enable_clock(struct clk *clk)
+{
+ printk(PKMOD "No enable clock method for %s."
+ " You should use new one !!!\n", clk->name);
+ return 0;
+}
+
+static int u67xx_cgu_enable_camout(struct clk *clk)
+{
+ unsigned long value;
+ debug("u67xx_cgu_enable_hw_clock for %s\n", clk->name);
+
+ if (unlikely(clk->enable_reg == 0)) {
+ printk(KERN_ERR "Enable for %s without enable register\n",
+ clk->name);
+ return 0;
+ }
+
+ u6_clk_enable(&fix_ck);
+ u6_clk_enable(&plltv_ck);
+
+ value = readl(clk->enable_reg);
+ value |= 1 << clk->enable_bit;
+ writel(value, clk->enable_reg);
+
+ udelay(1);
+
+ u6_clk_disable(&fix_ck);
+ u6_clk_disable(&plltv_ck);
+
+ return 0;
+}
+
+/**
+ * HW disable clock function.
+ **/
+
+static void u67xx_cgu_disable_fake_clock(struct clk *clk)
+{
+ debug("u67xx_cgu_disable_fake_clock for %s\n", clk->name);
+}
+
+static void u67xx_cgu_disable_hw_clock(struct clk *clk)
+{
+ unsigned long value;
+
+ debug("u67xx_cgu_disable_hw_clock for %s\n", clk->name);
+
+ if (unlikely(clk->enable_reg == 0)) {
+ printk(KERN_ERR "Disable for %s without enable register\n",
+ clk->name);
+ return;
+ }
+
+ value = readl(clk->enable_reg);
+ value &= ~(1 << clk->enable_bit);
+ writel(value, clk->enable_reg);
+
+ return;
+}
+
+static void u67xx_cgu_disable_shared_clock(struct clk *clk)
+{
+ unsigned long value;
+
+ debug("u67xx_cgu_disable_shared_clock for %s\n", clk->name);
+
+ if (unlikely(clk->enable_reg == 0)) {
+ printk(KERN_ERR "Disable for %s without enable register\n",
+ clk->name);
+ return;
+ }
+
+ value = readl(clk->enable_reg);
+ value &= ~(1 << clk->enable_bit);
+ writel(value, clk->enable_reg);
+}
+
+static void u67xx_cgu_disable_clock(struct clk *clk)
+{
+ printk(PKMOD
+ " No disable clock method for %s. You should use one !!!\n",
+ clk->name);
+}
+
+/**
+ * set rate clock function.
+ **/
+
+static int u6_clk_set_rate_fci(struct clk *clk, unsigned long rate)
+{
+ int ret = 0;
+ unsigned long ratio = 0;
+ unsigned long reg;
+
+ if (!rate)
+ ratio = 31;
+ else {
+ if (rate > CLK_FC_CLK_MAX_FREQ)
+ rate = CLK_FC_CLK_MAX_FREQ;
+
+ /* compute diviser ratio */
+ ratio = (clk->parent->rate / rate) - 1;
+ if (ratio < 2)
+ ratio = 2;
+ if (ratio > 31)
+ ratio = 31;
+ }
+ clk->rate = clk->parent->rate / (ratio + 1);
+
+ /* for voltage working point only */
+ /* u67xx_set_freq(FC_CLK, clk->rate/1000 , clk->rate/1000); */
+
+ reg = readl(CGU_FIXCON_REG);
+ reg &= ~(0x1F << 22);
+ reg |= (ratio << 22);
+ writel(reg, CGU_FIXCON_REG);
+
+ reg = readl(CGU_SCCON_REG);
+ writel(reg, CGU_SCCON_REG);
+
+ return ret;
+}
+
+static int u6_clk_set_rate_camout(struct clk *clk, unsigned long rate)
+{
+ int ret = 0;
+ unsigned long ratio = 0;
+ unsigned long reg;
+
+ if (!rate)
+ return -EINVAL;
+
+ if (rate > CLK_CAM_CLK_MAX_FREQ)
+ rate = CLK_CAM_CLK_MAX_FREQ;
+
+ /* compute diviser ratio */
+ ratio = (clk->parent->rate / rate) - 1;
+ if (ratio < 1)
+ ratio = 1;
+ if (ratio > 63)
+ ratio = 63;
+
+ clk->rate = clk->parent->rate / (ratio + 1);
+
+ /* for voltage working point only */
+ /* u67xx_set_freq(CAM_CLK, clk->rate/1000 , clk->rate/1000); */
+
+ reg = readl(CGU_CAMCON_REG);
+
+ reg &= ~(0x3F << 0);
+ reg |= (ratio << 0);
+
+ writel(reg, CGU_CAMCON_REG);
+
+ return ret;
+}
+
+/**
+ * set parent clock function.
+ **/
+static int u6_clk_set_parent_camout(struct clk *clk, struct clk *parent)
+{
+ int ret = 0;
+ unsigned long srce = 0;
+ unsigned long reg;
+
+ if (!strcmp(parent->name, "TVOPLL"))
+ srce = 0;
+ else if (!strcmp(parent->name, "fix_ck"))
+ srce = 1;
+ else
+ return -EINVAL;
+
+ u6_clk_enable(&fix_ck);
+ u6_clk_enable(&plltv_ck);
+
+ reg = readl(CGU_CAMCON_REG);
+
+ reg &= ~(0x1 << 6);
+ reg |= (srce << 6);
+
+ writel(reg, CGU_CAMCON_REG);
+
+ udelay(1);
+
+ u6_clk_disable(&fix_ck);
+ u6_clk_disable(&plltv_ck);
+
+ clk->parent = parent;
+
+ return ret;
+}
+
+static int u6_clk_set_parent_uart(struct clk *clk, struct clk *parent)
+{
+
+ if (!strcmp(parent->name, "pclk2_ck")) {
+ clk->parent = parent;
+ return 0;
+ } else if (!strcmp(parent->name, "clk26m_ck")) {
+ clk->parent = parent;
+ return 0;
+ } else if (!strcmp(parent->name, "clk13m_ck")) {
+ clk->parent = parent;
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+/**
+ * HW init clock function.
+ **/
+
+static void u6_clk_dflt_init(struct clk *clk)
+{
+ if (clk->usecount == 0)
+ u67xx_cgu_disable_hw_clock(clk);
+ else
+ u67xx_cgu_enable_hw_clock(clk);
+ /* default rate to parent one */
+ clk->rate = clk->parent->rate;
+}
+
+static void u6_clk_init_hclk2(struct clk *clk)
+{
+ /* nothing to do */
+}
+
+static void u6_clk_init_fci(struct clk *clk)
+{
+ u6_clk_set_rate_fci(clk, clk->rate);
+}
+
+static void u6_clk_init_camout(struct clk *clk)
+{
+ u6_clk_set_parent_camout(clk, &fix_ck);
+ u6_clk_set_rate_camout(clk, clk->rate);
+}
+
+/*
+ * Update clock rate
+ */
+static void followparent_ivs_recalc(struct clk *clk)
+{
+ clk->rate = clk->parent->rate;
+ propagate_rate(clk);
+}
+
+/*
+ * U6 platform access clock functions
+ */
+
+/**
+ * @brief Disable a device clock.
+ * @param clk clock description structure
+ */
+static void u6_clk_disable(struct clk *clk)
+{
+ /* BUG_ON(!clk->ref_count); */
+ if ((clk->flags & ALWAYS_ENABLED) == ALWAYS_ENABLED)
+ return;
+
+ if (clk->usecount > 0 && !(--clk->usecount)) {
+ if (clk->disable)
+ clk->disable(clk);
+ else
+ u67xx_cgu_disable_clock(clk);
+
+ if (likely((u32) clk->parent))
+ u6_clk_disable(clk->parent);
+ }
+}
+
+/**
+ * @brief Enable a device clock.
+ * @param clk clock description structure
+ */
+static int u6_clk_enable(struct clk *clk)
+{
+ int ret = 0;
+
+ /* BUG_ON(!clk->ref_count); */
+ if ((clk->flags & ALWAYS_ENABLED) == ALWAYS_ENABLED)
+ return 0;
+
+ if (clk->usecount++ == 0) {
+ if (likely((u32) clk->parent))
+ ret = u6_clk_enable(clk->parent);
+
+ if (unlikely(ret != 0)) {
+ clk->usecount--;
+ return ret;
+ }
+
+ if (clk->enable)
+ ret = clk->enable(clk);
+ else
+ ret = u67xx_cgu_enable_clock(clk);
+
+ if (unlikely(ret != 0) && clk->parent) {
+ u6_clk_disable(clk->parent);
+ clk->usecount--;
+ }
+ }
+ return 0;
+}
+
+static long u6_clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ if (clk->round_rate)
+ return clk->round_rate(clk, rate);
+ else
+ return rate;
+}
+
+static int u6_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ int ret = 0;
+
+ /* BUG_ON(!clk->ref_count); */
+ if (clk->usecount > 0) {
+ if (clk->disable)
+ clk->disable(clk);
+ else
+ u67xx_cgu_disable_clock(clk);
+ }
+
+ if (clk->set_rate)
+ ret = clk->set_rate(clk, rate);
+ else
+ ret = -EINVAL;
+
+ if (clk->usecount > 0) {
+ if (clk->enable)
+ clk->enable(clk);
+ else
+ u67xx_cgu_enable_clock(clk);
+ }
+
+ /* propagate rate */
+ propagate_rate(clk);
+
+ return ret;
+}
+
+static int u6_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ int ret = 0;
+ int old_rate;
+
+ if (clk->usecount > 0) {
+ if (clk->disable)
+ clk->disable(clk);
+ else
+ u67xx_cgu_disable_clock(clk);
+
+ if (likely((u32) clk->parent))
+ u6_clk_disable(clk->parent);
+ }
+
+ old_rate = clk->rate;
+
+ if (clk->set_parent)
+ ret = clk->set_parent(clk, parent);
+ else
+ ret = -EINVAL;
+
+ if (clk->round_rate)
+ old_rate = clk->round_rate(clk, old_rate);
+
+ u6_clk_set_rate(clk, old_rate);
+
+ if (clk->usecount > 0) {
+ if (likely((u32) clk->parent))
+ u6_clk_enable(clk->parent);
+
+ if (clk->enable)
+ ret = clk->enable(clk);
+ else
+ ret = u67xx_cgu_enable_clock(clk);
+ }
+
+ /* propagate rate */
+ if (clk->flags & RATE_PROPAGATES)
+ propagate_rate(clk);
+
+ return ret;
+}
+
+static struct clk *u6_clk_get_parent(struct clk *clk)
+{
+ return clk->parent;
+}
+
+/*
+ * U6 platform clock constraint functions
+ */
+
+unsigned long clk_get_hw_constraint(unsigned long reg_addr)
+{
+ unsigned long reg;
+
+ reg = readl(reg_addr);
+
+ return reg;
+}
+
+ssize_t u6_clk_show_hw_rates(struct kobject *kobj, char *buf)
+{
+ int size = 0;
+ unsigned long reg, rate, msc, psc, mclk;
+
+ size += sprintf(&buf[size], "--HW-- : \n");
+
+ mclk = clk_get_hw_constraint(CGU_FIXCON_REG);
+ mclk = osc_ck.rate / 1000000 / (((mclk & (0x3 << 17)) >> 17) + 1);
+
+ reg = clk_get_hw_constraint(CGU_SCCON_REG);
+
+ msc = (((reg & (0xF << 25)) >> 25) + 1);
+ psc = (((reg & (0x3 << 15)) >> 15) + 1);
+ size += sprintf(&buf[size], "arm_ck is ");
+ if (reg & (1 << 17)) {
+ if (reg & (1 << 18))
+ rate = 312;
+ else
+ rate = 156;
+ rate = rate / msc / psc;
+ size += sprintf(&buf[size], "%lu", rate);
+ size += sprintf(&buf[size], "Mhz fix_ck pll\n");
+ } else {
+ rate = mclk * (((reg & (0xFF << 3)) >> 3) + 1)
+ / (((reg & (0xF << 11)) >> 11) + 1);
+ rate = rate / msc / psc;
+ size += sprintf(&buf[size], "%lu", rate);
+ size += sprintf(&buf[size], "Mhz sc_ck pll\n");
+ }
+
+ rate = rate / (((reg & (0xF << 21)) >> 21) + 1);
+
+ size += sprintf(&buf[size], "hclk_ck is %luMhz\n", rate);
+
+ reg = clk_get_hw_constraint(CGU_FIXCON_REG);
+
+ rate = 13 * (((reg & (0x3 << 20)) >> 20) + 1);
+
+ size += sprintf(&buf[size], "pclk2_ck is %luMhz\n", rate);
+
+ if (reg & (1 << 31)) {
+ if (reg & (1 << 29))
+ rate = 104;
+ else
+ rate = 78;
+ } else
+ rate = 13 + (13 * ((reg & (0x7 << 29)) >> 29));
+
+ size += sprintf(&buf[size], "hclk2_ck is %luMhz\n", rate);
+
+ reg = clk_get_hw_constraint(CGU_SDMCON_REG);
+
+ msc = (((reg & (0x7 << 0)) >> 0) + 1);
+
+ size += sprintf(&buf[size], "sdm_ck is ");
+ if (reg & (1 << 17)) {
+ if (reg & (1 << 18))
+ rate = 312;
+ else
+ rate = 156;
+ size += sprintf(&buf[size], "%lu", rate / msc);
+ size += sprintf(&buf[size], "Mhz fix_ck pll\n");
+ } else {
+ rate = mclk * 2 * (((reg & (0xFF << 3)) >> 3) + 1)
+ / (((reg & (0x3F << 11)) >> 11) + 1);
+ size += sprintf(&buf[size], "%lu", rate / msc);
+ size += sprintf(&buf[size], "Mhz sdm pll\n");
+ }
+
+ if (reg & (1 << 23))
+ size += sprintf(&buf[size], "ivs-sdm concentrator is enable\n");
+ else
+ size += sprintf(&buf[size],
+ "ivs-sdm concentrator is disable\n");
+
+ return size;
+}
+
+unsigned char *cgu_name_sc1[32] = {
+ "EBI", "01", "NFI", "SDI", "04", "MSI", "UCC", "JDI",
+ "08", "09", "10", "DMAU", "RFSM1", "IIS", "USBD", "FCI",
+ "USIM", "GEAC", "PWM3", "PWM2", "PWM1", "KBS", "GPIO", "UART2",
+ "UART1", "IIC2", "IIC1", "SPI2", "SPI1", "SCTU", "EXTINT", "INTC"
+};
+
+unsigned char *cgu_name_sc2[32] = {
+ "32", "33", "34", "35", "36", "37", "38", "39",
+ "40", "41", "42", "43", "44", "45", "46", "47",
+ "48", "49", "50", "51", "52", "53", "BBIP", "55",
+ "56", "57", "58", "ETB", "60", "MMTU", "62", "CAE"
+};
+
+ssize_t u6_clk_show_sc_constraints(struct kobject *kobj, char *buf)
+{
+ int i, size = 0;
+ unsigned long reg;
+
+ size += sprintf(&buf[size], "--SC-- : \n");
+
+ reg = clk_get_hw_constraint(CGU_GATESC1_REG);
+
+ for (i = 0; i < 32; i++) {
+ if ((reg >> i) & 0x1)
+ size +=
+ sprintf(&buf[size], "%s ,", cgu_name_sc1[31 - i]);
+ }
+
+ size += sprintf(&buf[size], "\n");
+
+ reg = clk_get_hw_constraint(CGU_GATESC2_REG);
+
+ for (i = 0; i < 32; i++) {
+ if ((reg >> i) & 0x1)
+ size +=
+ sprintf(&buf[size], "%s ,", cgu_name_sc2[31 - i]);
+ }
+
+ size += sprintf(&buf[size], "\n");
+
+ return size;
+}
+
+unsigned char *cgu_name_ivs[32] = {
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
+ "CAMJPE", "TVO", "JDU", "VDC", "VEC", "IPP", "VDE", "CAM"
+};
+
+ssize_t u6_clk_show_ivs_constraints(struct kobject *kobj, char *buf)
+{
+ int i, size = 0;
+ unsigned long reg;
+
+ size += sprintf(&buf[size], "--IVS-- : \n");
+
+ reg = clk_get_hw_constraint(CGU_GATEIVS_REG);
+
+ for (i = 0; i < 32; i++) {
+ if ((reg >> i) & 0x1)
+ size +=
+ sprintf(&buf[size], "%s ,", cgu_name_ivs[31 - i]);
+ }
+
+ size += sprintf(&buf[size], "\n");
+
+ return size;
+}
+
+ssize_t u6_clk_show_tvo_constraints(struct kobject *kobj, char *buf)
+{
+ int size = 0;
+ unsigned long reg;
+
+ size += sprintf(&buf[size], "--TVO-- : \n");
+
+ reg = clk_get_hw_constraint(CGU_TVCON_REG);
+
+ if ((reg >> 15) & 0x1)
+ size += sprintf(&buf[size], "tvclk_ck pll enable\n");
+ else
+ size += sprintf(&buf[size], "tvclk_ck pll disable\n");
+
+ if ((reg >> 12) & 0x1)
+ size += sprintf(&buf[size], "TVOPLL enable\n");
+ else
+ size += sprintf(&buf[size], "TVOPLL disable\n");
+
+ return size;
+}
+
+ssize_t u6_clk_show_cam_constraints(struct kobject *kobj, char *buf)
+{
+ int size = 0;
+ unsigned long reg, rate, div;
+
+ size += sprintf(&buf[size], "--CAM-- : \n");
+
+ reg = clk_get_hw_constraint(CGU_CAMCON_REG);
+
+ if ((reg >> 6) & 0x1) {
+ size += sprintf(&buf[size], "fix_clock is source\n");
+ rate = 312;
+ } else {
+ size += sprintf(&buf[size], "TVOPLL is source\n");
+ rate = 216;
+ }
+
+ div = ((reg & (0x3F << 0)) >> 0);
+
+ size += sprintf(&buf[size], "camo_ck is %luMhz\n", rate / (div + 1));
+
+ if ((reg >> 7) & 0x1)
+ size += sprintf(&buf[size], "camo_ck enable\n");
+ else
+ size += sprintf(&buf[size], "camo_ck disable\n");
+
+ return size;
+}
+
+/*
+ * U6 clock reset and init functions
+ */
+
+static struct clk_functions u6_clk_functions = {
+ .clk_enable = u6_clk_enable,
+ .clk_disable = u6_clk_disable,
+ .clk_round_rate = u6_clk_round_rate,
+ .clk_set_rate = u6_clk_set_rate,
+ .clk_set_parent = u6_clk_set_parent,
+ .clk_get_parent = u6_clk_get_parent,
+};
+
+/**
+ * @brief Attempts to connect the primary description structure for DMA case.
+ *
+ * We don't do any initialization since we expect the primary OS to have done
+ * it for us.
+ */
+static int __init u67xx_cgu_init(void)
+{
+ struct clk **clkp;
+ printk(PKMOD "clk management init\n");
+
+ if (mpurate)
+ sc_ck.rate = mpurate;
+
+ /* init clock function pointer table */
+ clk_init(&u6_clk_functions);
+
+ /* register and init clock elements */
+ for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
+ clkp++) {
+ clk_register(*clkp);
+ }
+
+ return 0;
+}
+
+arch_initcall(u67xx_cgu_init);
diff --git a/arch/arm/mach-u67xx/clock_u67xx.h b/arch/arm/mach-u67xx/clock_u67xx.h
new file mode 100644
index 0000000..d92e454
--- /dev/null
+++ b/arch/arm/mach-u67xx/clock_u67xx.h
@@ -0,0 +1,876 @@
+/*
+ * linux/arch/arm/mach-u67xx/clock_u67xx.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Loic Pallardy <loic.pallardy at stericsson.com for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc
+ */
+
+#ifndef __ARCH_ARM_MACH_U67XX_CLOCK_H
+#define __ARCH_ARM_MACH_U67XX_CLOCK_H
+
+static int u67xx_cgu_enable_fake_clock(struct clk *clk);
+static int u67xx_cgu_enable_hw_clock(struct clk *clk);
+static int u67xx_cgu_enable_shared_clock(struct clk *clk);
+static int u67xx_cgu_enable_tvo_pll_clock(struct clk *clk);
+static int u67xx_cgu_enable_camout(struct clk *clk);
+
+static void u67xx_cgu_disable_fake_clock(struct clk *clk);
+static void u67xx_cgu_disable_hw_clock(struct clk *clk);
+static void u67xx_cgu_disable_shared_clock(struct clk *clk);
+
+static void u6_clk_dflt_init(struct clk *clk);
+static void u6_clk_init_hclk2(struct clk *clk);
+static void u6_clk_init_fci(struct clk *clk);
+static void u6_clk_init_camout(struct clk *clk);
+
+static int u6_clk_set_rate_fci(struct clk *clk, unsigned long rate);
+static int u6_clk_set_rate_camout(struct clk *clk, unsigned long rate);
+
+static int u6_clk_set_parent_camout(struct clk *clk, struct clk *parent);
+static int u6_clk_set_parent_uart(struct clk *clk, struct clk *parent);
+
+static void followparent_ivs_recalc(struct clk *clk);
+
+/* used to remove useless clock cells */
+#undef U6_OPTIMIZED_TREE
+
+/*
+ * U6 clock tree.
+ *
+ * NOTE:In many cases here we are assigning a 'default' parent. In many
+ * cases the parent is selectable. The get/set parent calls will also
+ * switch sources.
+ *
+ * Many some clocks say always_enabled, but they can be auto idled for
+ * power savings. They will always be available upon clock request.
+ *
+ * Several sources are given initial rates which may be wrong, this will
+ * be fixed up in the init func.
+ *
+ * Things are broadly separated below by clock domains. It is
+ * noteworthy that most periferals have dependencies on multiple clock
+ * domains. Many get their interface clocks from the L4 domain, but get
+ * functional clocks from fixed sources or other core domain derived
+ * clock.
+ */
+
+/*** Basic clocks ***/
+
+/* Base external input clocks */
+static struct clk func_32k_ck = {
+ .name = "func_32k_ck",
+ .rate = 32000,
+ .flags = RATE_FIXED | ALWAYS_ENABLED,
+ .usecount = 1,
+};
+
+/* Typical 26MHz in standalone mode */
+static struct clk osc_ck = { /* (*12, *13, 19.2, *26, 38.4)MHz */
+ .name = "osc_ck",
+ .rate = 26000000, /* fixed up in clock init */
+ .flags = RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+ .usecount = 1,
+};
+
+/* System clock MCLK */
+/* With out modem likely 12MHz, with modem likely 13MHz */
+static struct clk sys_ck = { /* (*12, *13, 19.2, 26, 38.4)MHz */
+ .name = "sys_ck", /* ~ ref_clk also */
+ .parent = &osc_ck,
+ .rate = 13000000,
+ .flags = RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+ .usecount = 1,
+};
+
+/*** System PLLs ***/
+
+static struct clk sc_ck = { /* 275-550MHz */
+ .name = "sc_ck",
+ .parent = &sys_ck,
+ .rate = 416000000,
+ .flags = RATE_PROPAGATES,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+};
+
+static struct clk fix_ck = { /* 312MHz */
+ .name = "fix_ck",
+ .parent = &sys_ck,
+ .rate = 312000000,
+ .flags = RATE_FIXED,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+ .enable_bit = 0,
+};
+
+static struct clk tv_ck = { /* 216MHz */
+ .name = "tv_ck",
+ .parent = &fix_ck,
+ .rate = 216000000,
+ .flags = RATE_FIXED,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+};
+
+#ifndef U6_OPTIMIZED_TREE
+static struct clk dsp2_ck = { /* 156-320MHz */
+ .name = "dsp2_ck",
+ .parent = &sys_ck,
+ .rate = 208000000,
+ .flags = RATE_PROPAGATES,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+ .enable_bit = 8,
+};
+#endif
+
+static struct clk sdm_ck = { /* 275-550MHz */
+ .name = "sdm_ck",
+ .parent = &sys_ck,
+ .rate = 200000000,
+/* .flags = RATE_PROPAGATES,*/
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+ .enable_bit = 3,
+};
+
+/*** Master clock sources ***/
+
+static struct clk arm_ck = {
+ .name = "arm_ck",
+ .rate = 416000000,
+ .parent = &sc_ck,
+/* .flags = RATE_PROPAGATES,*/
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+};
+
+static struct clk hclk_ck = {
+ .name = "hclk_ck",
+ .rate = 208000000,
+ .parent = &arm_ck,
+ .flags = RATE_PROPAGATES,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+ .enable_bit = 1,
+};
+
+static struct clk hclk2_ck = {
+ .name = "hclk2_ck",
+/* .rate = 104000000,*/
+ .rate = 52000000,
+ .parent = &fix_ck,
+ .flags = RATE_PROPAGATES,
+ .init = u6_clk_init_hclk2,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+ .enable_bit = 2,
+};
+
+static struct clk sdm_ivs_ck = {
+ .name = "sdm_ivs_ck",
+ .parent = &hclk2_ck,
+ .rate = 104000000,
+ .flags = RATE_PROPAGATES,
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_ivs_recalc,
+ .enable_reg = CGU_SDMCON_REG,
+ .enable_bit = 23,
+};
+
+static struct clk pclk1_ck = {
+ .name = "pclk1_ck",
+ .rate = 104000000,
+ .parent = &hclk2_ck,
+ .flags = RATE_PROPAGATES,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+};
+
+static struct clk tvclk_ck = {
+ .name = "tvclk_ck",
+ .rate = 27000000,
+ .parent = &tv_ck,
+ .flags = RATE_FIXED,
+ .enable = u67xx_cgu_enable_tvo_pll_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .enable_reg = CGU_TVCON_REG,
+ .enable_bit = 15,
+};
+
+static struct clk pclk2_ck = {
+ .name = "pclk2_ck",
+ .rate = 52000000,
+ .parent = &fix_ck,
+ .flags = RATE_PROPAGATES,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+ .enable_bit = 4,
+};
+
+static struct clk clk24m_ck = {
+ .name = "clk24m_ck",
+ .rate = 24000000,
+ .parent = &fix_ck,
+ .flags = RATE_FIXED,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+ .enable_bit = 5,
+};
+
+static struct clk clk26m_ck = {
+ .name = "clk26m_ck",
+ .rate = 26000000,
+ .parent = &fix_ck,
+ .flags = RATE_FIXED,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+ .enable_bit = 6,
+};
+
+static struct clk clk13m_ck = {
+ .name = "clk13m_ck",
+ .rate = 13000000,
+ .parent = &fix_ck,
+ .flags = RATE_FIXED,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+ .enable_bit = 7,
+};
+
+static struct clk clk4m_ck = {
+ .name = "clk4m_ck",
+ .rate = 4000000,
+ .parent = &fix_ck,
+ .flags = RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+};
+
+#ifndef U6_OPTIMIZED_TREE
+static struct clk sioy1clk_ck = {
+ .name = "sioy1clk_ck",
+ .rate = 208000000,
+ .flags = RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+};
+
+static struct clk sioy2clk_ck = {
+ .name = "sioy2clk_ck",
+ .rate = 208000000,
+ .flags = RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+};
+
+static struct clk rfclk_ck = {
+ .name = "rfclk_ck",
+ .rate = 208000000,
+ .flags = RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+};
+#endif
+
+static struct clk fc_ck = {
+ .name = "fc_ck",
+/* .rate = 104000000,*/
+ .rate = 52000000,
+ .init = u6_clk_init_fci,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+ .set_rate = u6_clk_set_rate_fci,
+ .parent = &fix_ck,
+};
+
+static struct clk usb_d_ck = {
+ .name = "usb_d_ck",
+ .rate = 24000000,
+ .parent = &clk24m_ck,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+};
+
+static struct clk usb_h_ck = {
+ .name = "usb_h_ck",
+ .rate = 24000000,
+ .parent = &clk24m_ck,
+ .flags = RATE_FIXED,
+ .enable = u67xx_cgu_enable_fake_clock,
+ .disable = u67xx_cgu_disable_fake_clock,
+};
+
+#ifndef U6_OPTIMIZED_TREE
+static struct clk dcclk1_ck = {
+ .name = "dcclk1_ck",
+ .rate = 130000000,
+ .flags = RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+};
+
+static struct clk diclk1_ck = {
+ .name = "diclk1_ck",
+ .rate = 130000000,
+ .flags = RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+};
+
+static struct clk dcclk2_ck = {
+ .name = "dcclk2_ck",
+ .rate = 130000000,
+ .flags = RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+};
+
+static struct clk diclk2_ck = {
+ .name = "dicl2_ck",
+ .rate = 130000000,
+ .flags = RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES,
+};
+#endif
+
+static struct clk camo_ck = {
+ .name = "camo_ck",
+ .rate = 12000000,
+ .parent = &fix_ck,
+ .flags = RATE_PROPAGATES,
+ .init = u6_clk_init_camout,
+ .enable = u67xx_cgu_enable_camout,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .set_rate = u6_clk_set_rate_camout,
+ .set_parent = u6_clk_set_parent_camout,
+ .enable_reg = CGU_CAMCON_REG,
+ .enable_bit = 7,
+};
+
+/*** Peripheral clocks ***/
+
+/* CGUTVCON */
+static struct clk plltv_ck = {
+ .name = "TVOPLL",
+ .enable_reg = CGU_TVCON_REG,
+ .enable_bit = 12,
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .parent = &tvclk_ck,
+};
+
+/* CGUGATESC1 */
+#ifndef U6_OPTIMIZED_TREE
+static struct clk intc_ck = {
+ .name = "INTC",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 0,
+ .parent = &hclk2_ck,
+ .usecount = 1,
+};
+
+static struct clk extint_ck = {
+ .name = "EXTINT",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 1,
+ .parent = &pclk2_ck,
+ .usecount = 1,
+};
+
+static struct clk sctu_ck = {
+ .name = "SCTU",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 2,
+ .parent = &clk13m_ck,
+};
+#endif
+
+static struct clk spi1_ck = {
+ .name = "SPI1",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 3,
+ .parent = &pclk1_ck,
+};
+
+static struct clk spi2_ck = {
+ .name = "SPI2",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 4,
+ .parent = &pclk1_ck,
+};
+
+static struct clk iic1_ck = {
+ .name = "IIC1",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 5,
+ .parent = &pclk2_ck,
+};
+
+static struct clk iic2_ck = {
+ .name = "IIC2",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 6,
+ .parent = &pclk2_ck,
+};
+
+static struct clk uart1_ck = {
+ .name = "UART1",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .set_parent = u6_clk_set_parent_uart,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 7,
+ .parent = &clk13m_ck,
+ .usecount = 1,
+};
+
+static struct clk uart2_ck = {
+ .name = "UART2",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .set_parent = u6_clk_set_parent_uart,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 8,
+ .parent = &clk13m_ck,
+};
+
+#ifndef U6_OPTIMIZED_TREE
+static struct clk gpio_ck = {
+ .name = "GPIO",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 9,
+ .parent = &pclk2_ck,
+ .usecount = 1,
+};
+#endif
+
+static struct clk kbs_ck = {
+ .name = "KBS",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 10,
+ .parent = &func_32k_ck,
+};
+
+static struct clk pwm1_ck = {
+ .name = "PWM1",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 11,
+ .parent = &clk13m_ck,
+};
+
+static struct clk pwm2_ck = {
+ .name = "PWM2",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 12,
+ .parent = &clk13m_ck,
+};
+
+static struct clk pwm3_ck = {
+ .name = "PWM3",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 13,
+ .parent = &clk13m_ck,
+};
+
+static struct clk geac_ck = {
+ .name = "GEAC",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 14,
+ .parent = &pclk1_ck,
+};
+
+#ifndef U6_OPTIMIZED_TREE
+static struct clk usim_ck = {
+ .name = "USIM",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 15,
+ .parent = &pclk2_ck,
+};
+#endif
+
+static struct clk fci_ck = {
+ .name = "FCI",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 16,
+ .parent = &fc_ck,
+};
+
+static struct clk usbd_ck = {
+ .name = "USBD",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 17,
+ .parent = &hclk2_ck,
+};
+
+#ifndef U6_OPTIMIZED_TREE
+static struct clk iis_ck = {
+ .name = "IIS",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 18,
+ .parent = &clk24m_ck,
+};
+
+static struct clk rfsm1_ck = {
+ .name = "RFSM1",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 19,
+ .parent = &pclk1_ck,
+};
+#endif
+
+static struct clk dmau_ck = {
+ .name = "DMAU",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_shared_clock,
+ .disable = u67xx_cgu_disable_shared_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 20,
+ .parent = &hclk2_ck,
+};
+
+static struct clk jdi_ck = {
+ .name = "JDI",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 24,
+ .parent = &pclk2_ck,
+};
+
+#ifndef U6_OPTIMIZED_TREE
+static struct clk ucc_ck = {
+ .name = "UCC",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 25,
+ .parent = &pclk1_ck,
+};
+#endif
+
+static struct clk msi_ck = {
+ .name = "MSI",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 26,
+ .parent = &fc_ck,
+};
+
+static struct clk sdi_ck = {
+ .name = "SDI",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 28,
+ .parent = &hclk2_ck,
+};
+
+static struct clk nfi_ck = {
+ .name = "NFI",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 29,
+ .parent = &hclk2_ck,
+
+};
+
+static struct clk ebi_ck = {
+ .name = "EBI",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATESC1_REG,
+ .enable_bit = 31,
+ .parent = &hclk2_ck,
+
+};
+
+/* CGUGATESC2 */
+static struct clk cae_ck = {
+ .name = "CAE",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .enable_reg = CGU_GATESC2_REG,
+ .enable_bit = 0,
+ .parent = &pclk1_ck,
+};
+
+static struct clk mmtu_ck = {
+ .name = "MMTU",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_shared_clock,
+ .disable = u67xx_cgu_disable_shared_clock,
+ .enable_reg = CGU_GATESC2_REG,
+ .enable_bit = 2,
+ .parent = &clk13m_ck,
+ .usecount = 1,
+};
+
+/* OCL-2008-07-02: how to manage etbclk ? */
+/* static struct clk ETB_ck = */
+/* { */
+/* .name = "ETB", */
+/* .enable_reg = CGU_GATESC2_REG, */
+/* .enable_bit = 4, */
+/* .parent = &etbclk_ck, */
+/* }; */
+
+/* CGUGATEIVS */
+static struct clk cam_ck = {
+ .name = "CAM",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATEIVS_REG,
+ .enable_bit = 0,
+ .parent = &sdm_ivs_ck,
+};
+
+static struct clk vde_ck = {
+ .name = "VDE",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATEIVS_REG,
+ .enable_bit = 1,
+ .parent = &hclk2_ck,
+};
+
+static struct clk ipp_ck = {
+ .name = "IPP",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATEIVS_REG,
+ .enable_bit = 2,
+ .parent = &sdm_ivs_ck,
+};
+
+static struct clk vec_ck = {
+ .name = "VEC",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATEIVS_REG,
+ .enable_bit = 3,
+ .parent = &sdm_ivs_ck,
+};
+
+static struct clk vdc_ck = {
+ .name = "VDC",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATEIVS_REG,
+ .enable_bit = 4,
+ .parent = &sdm_ivs_ck,
+};
+
+static struct clk jdu_ck = {
+ .name = "JDU",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATEIVS_REG,
+ .enable_bit = 5,
+ .parent = &sdm_ivs_ck,
+};
+
+static struct clk tvoclk_ck = {
+ .name = "TVO",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATEIVS_REG,
+ .enable_bit = 6,
+ .parent = &sdm_ivs_ck,
+};
+
+static struct clk camjpe_ck = {
+ .name = "CAMJPE",
+ .init = u6_clk_dflt_init,
+ .enable = u67xx_cgu_enable_hw_clock,
+ .disable = u67xx_cgu_disable_hw_clock,
+ .recalc = followparent_recalc,
+ .enable_reg = CGU_GATEIVS_REG,
+ .enable_bit = 7,
+ .parent = &hclk_ck,
+};
+
+static struct clk *onchip_clks[] = {
+ /* external root sources */
+ &func_32k_ck,
+ &osc_ck,
+ &sys_ck,
+ &sc_ck,
+ &fix_ck,
+ &tv_ck,
+#ifndef U6_OPTIMIZED_TREE
+ &dsp2_ck,
+#endif
+ &sdm_ck,
+ &arm_ck,
+ &hclk_ck,
+ &hclk2_ck,
+ &pclk1_ck,
+ &pclk2_ck,
+ &tvclk_ck,
+ &clk24m_ck,
+ &clk26m_ck,
+ &clk13m_ck,
+ &clk4m_ck,
+ &fc_ck,
+#ifndef U6_OPTIMIZED_TREE
+ &sioy1clk_ck,
+ &sioy2clk_ck,
+ &rfclk_ck,
+#endif
+ &usb_h_ck,
+ &usb_d_ck,
+#ifndef U6_OPTIMIZED_TREE
+ &dcclk1_ck,
+ &diclk1_ck,
+ &dcclk2_ck,
+ &diclk2_ck,
+#endif
+ &camo_ck,
+ &tvoclk_ck,
+ &plltv_ck,
+#ifndef U6_OPTIMIZED_TREE
+ &intc_ck,
+ &extint_ck,
+ &sctu_ck,
+#endif
+ &spi1_ck,
+ &spi2_ck,
+ &iic1_ck,
+ &iic2_ck,
+ &uart1_ck,
+ &uart2_ck,
+#ifndef U6_OPTIMIZED_TREE
+ &gpio_ck,
+#endif
+ &kbs_ck,
+ &pwm1_ck,
+ &pwm2_ck,
+ &pwm3_ck,
+ &geac_ck,
+#ifndef U6_OPTIMIZED_TREE
+ &usim_ck,
+#endif
+ &fci_ck,
+ &usbd_ck,
+#ifndef U6_OPTIMIZED_TREE
+ &iis_ck,
+ &rfsm1_ck,
+#endif
+ &dmau_ck,
+ &jdi_ck,
+#ifndef U6_OPTIMIZED_TREE
+ &ucc_ck,
+#endif
+ &msi_ck,
+ &sdi_ck,
+ &nfi_ck,
+ &ebi_ck,
+ &cae_ck,
+ &mmtu_ck,
+ &sdm_ivs_ck,
+ &cam_ck,
+ &vde_ck,
+ &vdc_ck,
+ &vec_ck,
+ &ipp_ck,
+ &jdu_ck,
+ &camjpe_ck
+};
+
+#endif
diff --git a/arch/arm/plat-u6xxx/Makefile b/arch/arm/plat-u6xxx/Makefile
index 12c832c..afdf82b 100644
--- a/arch/arm/plat-u6xxx/Makefile
+++ b/arch/arm/plat-u6xxx/Makefile
@@ -3,6 +3,6 @@
#
# Common support
-obj-y := io.o irq.o
+obj-y := io.o irq.o clock.o
obj-$(CONFIG_U6_MTU_TIMER) += timer.o
diff --git a/arch/arm/plat-u6xxx/clock.c b/arch/arm/plat-u6xxx/clock.c
new file mode 100644
index 0000000..dd8fc02
--- /dev/null
+++ b/arch/arm/plat-u6xxx/clock.c
@@ -0,0 +1,650 @@
+/*
+ * linux/arch/arm/plat-u6xxx/clock.c
+ *
+ * Copyright (C) 2004 - 2005 Nokia corporation
+ * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ * Copyright (C) 2010 ST-Ericsson SA
+ *
+ * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
+ *
+ * Modified for u6 shared clock framework by Loic Pallardy @ ST-Ericsson.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/version.h>
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/notifier.h>
+
+#include <linux/io.h>
+
+#include <mach/clock.h>
+
+#ifdef CONFIG_U6_POWER_SYSFS
+#include "power_sysfs.h"
+#endif
+
+LIST_HEAD(clocks);
+
+static DEFINE_MUTEX(clocks_mutex);
+DEFINE_SPINLOCK(clockfw_lock);
+
+static struct clk_functions *arch_clock;
+
+/*
+ * Additionnal specific clock functions define in include/mach/clock.h
+ */
+
+/**
+ * clk_register_notifier - register a driver with clock mngt
+ * @nb: notifier function to register
+ * @clk: clock element rate change to be notified
+ *
+ * Add a driver to one of two lists: either a list of drivers that
+ * are notified about clock rate changes (once before and once after
+ * the transition),
+ * This function may sleep, and has the same return conditions as
+ * sru_blocking_notifier_chain_register.
+ */
+int clk_register_notifier(struct notifier_block *nb, struct clk *clk)
+{
+ int ret;
+
+ if (clk == ERR_PTR(-ENOENT))
+ return -EINVAL;
+
+ mutex_lock(&clocks_mutex);
+ if (clk->notifier)
+ ret = srcu_notifier_chain_register(clk->notifier, nb);
+ else
+ ret = -EINVAL;
+ mutex_unlock(&clocks_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_register_notifier);
+
+/**
+ * clk_unregister_notifier - unregister a driver with clock mngt
+ * @nb: notifier function to be unregistered
+ * @clk: clock element rate change to be notified
+ *
+ * Remove a driver from the clock mngt notifier list.
+ *
+ * This function may sleep, and has the same return conditions as
+ * sru_blocking_notifier_chain_unregister.
+ */
+int clk_unregister_notifier(struct notifier_block *nb, struct clk *clk)
+{
+ int ret;
+
+ if (clk == ERR_PTR(-ENOENT))
+ return -EINVAL;
+
+ mutex_lock(&clocks_mutex);
+ if (clk->notifier)
+ ret = srcu_notifier_chain_unregister(clk->notifier, nb);
+ else
+ ret = -EINVAL;
+ mutex_unlock(&clocks_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_unregister_notifier);
+
+/**
+ * clk_notify_transition - call notifier chain
+ *
+ * This function calls the transition notifiers and the and set rate
+ * It is called twice on all frequency changes that have
+ * external effects.
+ */
+int clk_notify_transition(struct clk *clk, unsigned int state, void *data)
+{
+ BUG_ON(irqs_disabled());
+
+ if (clk == ERR_PTR(-ENOENT))
+ return NOTIFY_BAD;
+
+ switch (state) {
+
+ case CLK_RATE_PRECHANGE:
+ case CLK_RATE_POSTCHANGE:
+/* printk("notif %u of frequency transition of %s to %lu Hz\n",
+ state, clk->name, (unsigned long)data);
+*/
+ break;
+
+ case CLK_SRCE_PRECHANGE:
+ case CLK_SRCE_POSTCHANGE:
+/* printk("notif %u of srce transition of %s to %s\n",
+ state, clk->name, ((struct clk *)data)->name);
+*/
+ break;
+ default:
+ printk(KERN_ERR "Unknown notification srce transition\n");
+ return NOTIFY_BAD;
+ break;
+ }
+
+ return srcu_notifier_call_chain(clk->notifier, state, data);
+}
+
+/*
+ * Standard clock functions defined in include/linux/clk.h
+ */
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+ struct clk *p, *clk = ERR_PTR(-ENOENT);
+
+ mutex_lock(&clocks_mutex);
+ list_for_each_entry(p, &clocks, node) {
+ if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+ clk = p;
+ break;
+ }
+ }
+ mutex_unlock(&clocks_mutex);
+
+ return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+int clk_enable(struct clk *clk)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ if (clk == ERR_PTR(-ENOENT))
+ return -EINVAL;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ if (arch_clock->clk_enable)
+ ret = arch_clock->clk_enable(clk);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+ unsigned long flags;
+
+ if (clk == ERR_PTR(-ENOENT))
+ return;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ if (arch_clock->clk_disable)
+ arch_clock->clk_disable(clk);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+int clk_get_usecount(struct clk *clk)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ if (clk == ERR_PTR(-ENOENT))
+ return -EINVAL;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ ret = clk->usecount;
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_get_usecount);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ unsigned long flags;
+ unsigned long ret = 0;
+
+ if (clk == ERR_PTR(-ENOENT))
+ return -EINVAL;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ ret = clk->rate;
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+void clk_put(struct clk *clk)
+{
+ if (clk && !IS_ERR(clk))
+ module_put(clk->owner);
+}
+EXPORT_SYMBOL(clk_put);
+
+/*
+ * Optional clock functions defined in include/linux/clk.h
+ */
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long flags;
+ long ret = rate;
+
+ if (clk == ERR_PTR(-ENOENT))
+ return -EINVAL;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ if (arch_clock->clk_round_rate)
+ ret = arch_clock->clk_round_rate(clk, rate);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ if (clk == ERR_PTR(-ENOENT))
+ return -EINVAL;
+
+ /* notification pre change */
+ if (clk->notifier)
+ ret = clk_notify_transition(clk,
+ CLK_RATE_PRECHANGE, (void *)rate);
+
+ if (!(ret & NOTIFY_STOP_MASK)) {
+ spin_lock_irqsave(&clockfw_lock, flags);
+ if (arch_clock->clk_set_rate)
+ ret = arch_clock->clk_set_rate(clk, rate);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+
+ /* notification post change */
+ if (clk->notifier)
+ clk_notify_transition(clk,
+ CLK_RATE_POSTCHANGE,
+ (void *)clk->rate);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ if (clk == ERR_PTR(-ENOENT))
+ return -EINVAL;
+
+ /* notification pre change */
+ if (clk->notifier)
+ ret = clk_notify_transition(clk,
+ CLK_SRCE_PRECHANGE, (void *)parent);
+
+ if (!(ret & NOTIFY_STOP_MASK)) {
+ spin_lock_irqsave(&clockfw_lock, flags);
+ if (arch_clock->clk_set_parent)
+ ret = arch_clock->clk_set_parent(clk, parent);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+
+ /* notification post change */
+ if (clk->notifier)
+ clk_notify_transition(clk,
+ CLK_SRCE_POSTCHANGE,
+ (void *)clk->parent);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+ unsigned long flags;
+ struct clk *ret = ERR_PTR(-ENOENT);
+
+ if (clk == ERR_PTR(-ENOENT))
+ return ret;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ if (arch_clock->clk_get_parent)
+ ret = arch_clock->clk_get_parent(clk);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
+/*
+ * Internal clock functions
+ */
+
+unsigned int __initdata mpurate;
+/*
+ * By default we use the rate set by the bootloader.
+ * You can override this with mpurate= cmdline option.
+ */
+static int __init u6_clk_setup(char *str)
+{
+ unsigned int tmp_rate;
+
+ get_option(&str, &tmp_rate);
+
+ if (!tmp_rate)
+ return 1;
+
+ mpurate = tmp_rate;
+
+ return 1;
+}
+
+__setup("mpurate=", u6_clk_setup);
+
+/* Used for clocks that always have same value as the parent clock */
+void followparent_recalc(struct clk *clk)
+{
+ clk->rate = clk->parent->rate;
+}
+
+/* Propagate rate to children */
+void propagate_rate(struct clk *tclk)
+{
+ struct clk *clkp;
+
+ list_for_each_entry(clkp, &clocks, node) {
+ if (likely(clkp->parent != tclk))
+ continue;
+ if (likely((u32) clkp->recalc))
+ clkp->recalc(clkp);
+ }
+}
+
+int clk_register(struct clk *clk)
+{
+ mutex_lock(&clocks_mutex);
+ list_add(&clk->node, &clocks);
+ if (clk->init)
+ clk->init(clk);
+ mutex_unlock(&clocks_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister(struct clk *clk)
+{
+ mutex_lock(&clocks_mutex);
+ list_del(&clk->node);
+ mutex_unlock(&clocks_mutex);
+}
+EXPORT_SYMBOL(clk_unregister);
+
+void clk_deny_idle(struct clk *clk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ if (arch_clock->clk_deny_idle)
+ arch_clock->clk_deny_idle(clk);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+}
+EXPORT_SYMBOL(clk_deny_idle);
+
+void clk_allow_idle(struct clk *clk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ if (arch_clock->clk_allow_idle)
+ arch_clock->clk_allow_idle(clk);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+}
+EXPORT_SYMBOL(clk_allow_idle);
+
+#ifdef CONFIG_U6_POWER_SYSFS
+/*
+ * SysFs interface
+ */
+
+/*** Clock mngt sysfs interface **/
+static char clk_name[64] = "MMTU";
+
+static ssize_t show_select(struct kobject *kobj, char *buf)
+{
+ return sprintf(buf, "%s \n", clk_name);
+}
+
+static ssize_t store_select(struct kobject *kobj, const char *buf, size_t size)
+{
+ strcpy(clk_name, buf);
+
+ clk_name[strlen(clk_name) - 1] = 0;
+
+ return size;
+}
+
+static ssize_t show_enable(struct kobject *kobj, char *buf)
+{
+ struct clk *clk;
+ clk = clk_get(NULL, clk_name);
+ if (clk == ERR_PTR(-ENOENT))
+ return sprintf(buf, "unable to get clk\n");
+ clk_put(clk);
+ return sprintf(buf, "%d \n", clk_get_usecount(clk));
+}
+
+static ssize_t store_enable(struct kobject *kobj, const char *buf, size_t size)
+{
+ struct clk *clk;
+ clk = clk_get(NULL, clk_name);
+ if (clk == ERR_PTR(-ENOENT))
+ return size;
+ clk_enable(clk);
+ clk_put(clk);
+ return size;
+}
+
+static ssize_t show_disable(struct kobject *kobj, char *buf)
+{
+ struct clk *clk;
+ clk = clk_get(NULL, clk_name);
+ if (clk == ERR_PTR(-ENOENT))
+ return sprintf(buf, "unable to get clk\n");
+ clk_put(clk);
+ return sprintf(buf, "%d \n", clk_get_usecount(clk));
+}
+
+static ssize_t store_disable(struct kobject *kobj, const char *buf, size_t size)
+{
+ struct clk *clk;
+ clk = clk_get(NULL, clk_name);
+ if (clk == ERR_PTR(-ENOENT))
+ return size;
+ clk_disable(clk);
+ clk_put(clk);
+ return size;
+}
+
+static ssize_t show_usecount(struct kobject *kobj, char *buf)
+{
+ struct clk *clk;
+ clk = clk_get(NULL, clk_name);
+ if (clk == ERR_PTR(-ENOENT))
+ return sprintf(buf, "unable to get clk\n");
+ clk_put(clk);
+ return sprintf(buf, "%d \n", clk_get_usecount(clk));
+}
+
+static ssize_t show_rate(struct kobject *kobj, char *buf)
+{
+ struct clk *clk;
+ clk = clk_get(NULL, clk_name);
+ if (clk == ERR_PTR(-ENOENT))
+ return sprintf(buf, "unable to get clk\n");
+ clk_put(clk);
+ return sprintf(buf, "%lu \n", clk_get_rate(clk));
+}
+
+static ssize_t store_rate(struct kobject *kobj, const char *buf, size_t size)
+{
+ struct clk *clk;
+ unsigned long rate;
+ if (strict_strtoul(buf, 10, &rate) == 0) {
+ clk = clk_get(NULL, clk_name);
+ if (clk == ERR_PTR(-ENOENT))
+ return size;
+ clk_set_rate(clk, rate);
+ clk_put(clk);
+ }
+ return size;
+}
+
+static ssize_t show_parent(struct kobject *kobj, char *buf)
+{
+ struct clk *clk, *pclk;
+ clk = clk_get(NULL, clk_name);
+ if (clk == ERR_PTR(-ENOENT))
+ return sprintf(buf, "unable to get clk\n");
+ pclk = clk_get_parent(clk);
+ clk_put(clk);
+ if ((pclk) && (pclk->name))
+ return sprintf(buf, "%s\n", pclk->name);
+ else
+ return sprintf(buf, "root\n");
+}
+
+static ssize_t store_parent(struct kobject *kobj, const char *buf, size_t size)
+{
+ struct clk *clk, *pclk;
+ char parent[32];
+ strcpy(parent, buf);
+ parent[strlen(parent) - 1] = 0;
+
+ clk = clk_get(NULL, clk_name);
+ if (clk == ERR_PTR(-ENOENT))
+ return size;
+
+ pclk = clk_get(NULL, parent);
+ if (pclk == ERR_PTR(-ENOENT)) {
+ clk_put(clk);
+ return size;
+ }
+ clk_put(pclk);
+ clk_set_parent(clk, pclk);
+ clk_put(clk);
+ return size;
+}
+
+static ssize_t show_list(struct kobject *kobj, char *buf)
+{
+ int size = 0;
+
+ struct clk *p;
+
+ list_for_each_entry(p, &clocks, node) {
+ size += sprintf(&buf[size], "%s\n", p->name);
+ }
+ return size;
+}
+
+/*** Clock mngt hw debug ***/
+static ssize_t show_hw_constraints(struct kobject *kobj, char *buf)
+{
+ int size = 0;
+
+ size += u6_clk_show_hw_rates(kobj, &buf[size]);
+
+ size += u6_clk_show_sc_constraints(kobj, &buf[size]);
+
+ size += u6_clk_show_ivs_constraints(kobj, &buf[size]);
+
+ size += u6_clk_show_tvo_constraints(kobj, &buf[size]);
+
+ size += u6_clk_show_cam_constraints(kobj, &buf[size]);
+
+ return size;
+}
+
+static ssize_t show_hw_rates(struct kobject *kobj, char *buf)
+{
+ int size = 0;
+
+ size += u6_clk_show_hw_rates(kobj, buf);
+
+ return size;
+}
+
+define_one_ro(hw_rates);
+define_one_ro(hw_constraints);
+define_one_rw(parent);
+define_one_rw(rate);
+define_one_ro(usecount);
+define_one_rw(disable);
+define_one_rw(enable);
+define_one_rw(select);
+define_one_ro(list);
+
+static struct attribute *dbs_attributes_clock[] = {
+
+ &hw_rates.attr,
+ &hw_constraints.attr,
+ &parent.attr,
+ &rate.attr,
+ &usecount.attr,
+ &disable.attr,
+ &enable.attr,
+ &select.attr,
+ &list.attr,
+ NULL
+};
+
+static struct attribute_group dbs_attr_clock_group = {
+ .attrs = dbs_attributes_clock,
+ .name = "clk_mngt",
+};
+
+#endif
+
+/*
+ * Init functions
+ */
+
+int __init clk_init(struct clk_functions *custom_clocks)
+{
+ if (!custom_clocks) {
+ printk(KERN_ERR "No custom clock functions registered\n");
+ BUG();
+ }
+
+ arch_clock = custom_clocks;
+
+ return 0;
+}
+
+#ifdef CONFIG_U6_POWER_SYSFS
+static int __init u6_clock_init_sysfs(void)
+{
+ if (sysfs_create_group(&u6_power_kobj, &dbs_attr_clock_group))
+ printk(KERN_ERR "Unable to register %s in sysfs\n",
+ dbs_attr_clock_group.name);
+
+ return 0;
+}
+
+module_init(u6_clock_init_sysfs);
+#endif
+
diff --git a/arch/arm/plat-u6xxx/include/mach/clock.h b/arch/arm/plat-u6xxx/include/mach/clock.h
new file mode 100644
index 0000000..bc83414
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/clock.h
@@ -0,0 +1,376 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/clock.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Loic Pallardy <loic.pallardy@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc
+ */
+
+#ifndef __PLAT_CLOCK_H
+#define __PLAT_CLOCK_H
+
+struct module;
+
+struct clk {
+ struct list_head node;
+ struct module *owner;
+ const char *name;
+ struct clk *parent;
+ unsigned long rate;
+ __u32 flags;
+ u32 enable_reg;
+ __u8 enable_bit;
+ __u8 rate_offset;
+ __u8 src_offset;
+ __s8 usecount;
+ void (*recalc)(struct clk *);
+ int (*set_rate)(struct clk *, unsigned long);
+ long (*round_rate)(struct clk *, unsigned long);
+ void (*init)(struct clk *);
+ int (*enable)(struct clk *);
+ void (*disable)(struct clk *);
+ int (*set_parent)(struct clk *, struct clk *);
+ struct srcu_notifier_head *notifier;
+};
+
+struct clk_functions {
+ int (*clk_enable)(struct clk *clk);
+ void (*clk_disable)(struct clk *clk);
+ long (*clk_round_rate)(struct clk *clk, unsigned long rate);
+ int (*clk_set_rate)(struct clk *clk, unsigned long rate);
+ int (*clk_set_parent)(struct clk *clk, struct clk *parent);
+ struct clk * (*clk_get_parent)(struct clk *clk);
+ void (*clk_allow_idle)(struct clk *clk);
+ void (*clk_deny_idle)(struct clk *clk);
+};
+
+extern unsigned int mpurate;
+extern struct list_head clocks;
+extern spinlock_t clockfw_lock;
+
+extern int clk_init(struct clk_functions *custom_clocks);
+extern int clk_register(struct clk *clk);
+extern void clk_unregister(struct clk *clk);
+
+extern void propagate_rate(struct clk *clk);
+extern void followparent_recalc(struct clk *clk);
+extern void clk_allow_idle(struct clk *clk);
+extern void clk_deny_idle(struct clk *clk);
+extern int clk_get_usecount(struct clk *clk);
+
+extern ssize_t u6_clk_show_hw_rates(struct kobject *kobj, char *buf);
+extern ssize_t u6_clk_show_sc_constraints(struct kobject *kobj, char *buf);
+extern ssize_t u6_clk_show_usb_constraints(struct kobject *kobj, char *buf);
+extern ssize_t u6_clk_show_ivs_constraints(struct kobject *kobj, char *buf);
+extern ssize_t u6_clk_show_tvo_constraints(struct kobject *kobj, char *buf);
+extern ssize_t u6_clk_show_cam_constraints(struct kobject *kobj, char *buf);
+
+extern unsigned long clk_get_hw_constraint(unsigned long reg_addr);
+
+
+/* Clock flags */
+#define RATE_CKCTL (1 << 0) /* Main fixed ratio clocks */
+#define RATE_FIXED (1 << 1) /* Fixed clock rate */
+#define RATE_PROPAGATES (1 << 2) /* Program children too */
+#define VIRTUAL_CLOCK (1 << 3) /* Composite clock from table */
+#define ALWAYS_ENABLED (1 << 4) /* Clock cannot be disabled */
+#define ENABLE_REG_32BIT (1 << 5) /* Use 32-bit access */
+#define VIRTUAL_IO_ADDRESS (1 << 6) /* Clock in virtual address */
+#define CLOCK_IDLE_CONTROL (1 << 7)
+#define CLOCK_NO_IDLE_PARENT (1 << 8)
+#define DELAYED_APP (1 << 9) /* Delay application of clock */
+#define CONFIG_PARTICIPANT (1 << 10) /* Fundamental clock */
+
+
+#define CLK_HCLK2_MAX_FREQ 104000000
+#define CLK_FC_CLK_MAX_FREQ 104000000
+#define CLK_CAM_CLK_MAX_FREQ 78000000
+
+/**
+ * clk_register_notifier - register a driver with clock mngt
+ * @nb: notifier function to register
+ * @clk: clock element rate change to be notified
+ */
+extern int clk_register_notifier(struct notifier_block *nb, struct clk *clk);
+
+/**
+ * clk_unregister_notifier - unregister a driver with clock mngt
+ * @nb: notifier function to register
+ * @clk: clock element rate change to be notified
+ */
+extern int clk_unregister_notifier(struct notifier_block *nb, struct clk *clk);
+
+/**
+ * clk_notify_transition - call notifier chain
+ *
+ * This function calls the transition notifiers and the and set rate
+ * It is called twice on all frequency changes that have
+ * external effects.
+ */
+extern int clk_notify_transition(struct clk *clk,
+ unsigned int state, void *data);
+
+#define CLK_RATE_PRECHANGE 0
+#define CLK_RATE_POSTCHANGE 1
+#define CLK_SRCE_PRECHANGE 2
+#define CLK_SRCE_POSTCHANGE 3
+
+/* Hardware Register Definitions CGU (Clock Gating Unit) */
+
+/* CGU DSP1CON Register (32 bits) */
+#define CGU_DSP1CON_OFFSET 0x0
+#define CGU_DSP1CON_REG IO_ADDRESS(CGU_BASE + CGU_DSP1CON_OFFSET)
+
+/* CGU SCCON Register (32 bits) */
+#define CGU_SCCON_OFFSET 0x4
+#define CGU_SCCON_REG IO_ADDRESS(CGU_BASE + CGU_SCCON_OFFSET)
+
+/* CGU GATESC1 Register (32 bits) */
+#define CGU_GATESC1_OFFSET 0x8
+#define CGU_GATESC1_REG IO_ADDRESS(CGU_BASE + CGU_GATESC1_OFFSET)
+
+/* CGU SLEEPSC Register (32 bits) */
+#define CGU_SLEEPSC_OFFSET 0xC
+#define CGU_SLEEPSC_REG IO_ADDRESS(CGU_BASE + CGU_SLEEPSC_OFFSET)
+
+/* CGU FDIV Register (32 bits) */
+#define CGU_FDIV_OFFSET 0x10
+#define CGU_FDIV_REG IO_ADDRESS(CGU_BASE + CGU_FDIV_OFFSET)
+
+/* CGU GATEIVS Register (32 bits) */
+#define CGU_GATEIVS_OFFSET 0x14
+#define CGU_GATEIVS_REG IO_ADDRESS(CGU_BASE + CGU_GATEIVS_OFFSET)
+
+/* CGU DSP2CON Register (32 bits) */
+#define CGU_DSP2CON_OFFSET 0x18
+#define CGU_DSP2CON_REG IO_ADDRESS(CGU_BASE + CGU_DSP2CON_OFFSET)
+
+/* CGU CAMCON Register (32 bits) */
+#define CGU_CAMCON_OFFSET 0x1C
+#define CGU_CAMCON_REG IO_ADDRESS(CGU_BASE + CGU_CAMCON_OFFSET)
+
+/* CGU GATESC2 Register (32 bits) */
+#define CGU_GATESC2_OFFSET 0x20
+#define CGU_GATESC2_REG IO_ADDRESS(CGU_BASE + CGU_GATESC2_OFFSET)
+
+/* CGU SDMCON Register (32 bits) */
+#define CGU_SDMCON_OFFSET 0x24
+#define CGU_SDMCON_REG IO_ADDRESS(CGU_BASE + CGU_SDMCON_OFFSET)
+
+/* CGU TVCON Register (32 bits) */
+#define CGU_TVCON_OFFSET 0x28
+#define CGU_TVCON_REG IO_ADDRESS(CGU_BASE + CGU_TVCON_OFFSET)
+
+/* CGU IDLESC Register (32 bits) */
+#define CGU_IDLESC_OFFSET 0x2C
+#define CGU_IDLESC_REG IO_ADDRESS(CGU_BASE + CGU_IDLESC_OFFSET)
+
+/* CGU FIXCON Register (32 bits) */
+#define CGU_FIXCON_OFFSET 0x30
+#define CGU_FIXCON_REG IO_ADDRESS(CGU_BASE + CGU_FIXCON_OFFSET)
+
+/* CGU CNTCON Register (32 bits) */
+#define CGU_CNTCON_OFFSET 0x38
+#define CGU_CNTCON_REG IO_ADDRESS(CGU_BASE + CGU_CNTCON_OFFSET)
+
+/* Register description for GATESC1 */
+
+/* Bits definition for register CGU_GATESC1 */
+#define CGU_EBIEN_SHIFT 31
+#define CGU_EBIEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_EBIEN_SHIFT))
+#define CGU_EBIEN_0 (0x0UL<<CGU_EBIEN_SHIFT)
+#define CGU_EBIEN_1 (0x1UL<<CGU_EBIEN_SHIFT)
+#define CGU_EBIEN (0x1UL<<CGU_EBIEN_SHIFT)
+#define CGU_NFIEN_SHIFT 29
+#define CGU_NFIEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_NFIEN_SHIFT))
+#define CGU_NFIEN_0 (0x0UL<<CGU_NFIEN_SHIFT)
+#define CGU_NFIEN_1 (0x1UL<<CGU_NFIEN_SHIFT)
+#define CGU_NFIEN (0x1UL<<CGU_NFIEN_SHIFT)
+#define CGU_SDIEN_SHIFT 28
+#define CGU_SDIEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_SDIEN_SHIFT))
+#define CGU_SDIEN_0 (0x0UL<<CGU_SDIEN_SHIFT)
+#define CGU_SDIEN_1 (0x1UL<<CGU_SDIEN_SHIFT)
+#define CGU_SDIEN (0x1UL<<CGU_SDIEN_SHIFT)
+#define CGU_MSIEN_SHIFT 26
+#define CGU_MSIEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_MSIEN_SHIFT))
+#define CGU_MSIEN_0 (0x0UL<<CGU_MSIEN_SHIFT)
+#define CGU_MSIEN_1 (0x1UL<<CGU_MSIEN_SHIFT)
+#define CGU_MSIEN (0x1UL<<CGU_MSIEN_SHIFT)
+#define CGU_UCCEN_SHIFT 25
+#define CGU_UCCEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_UCCEN_SHIFT))
+#define CGU_UCCEN_0 (0x0UL<<CGU_UCCEN_SHIFT)
+#define CGU_UCCEN_1 (0x1UL<<CGU_UCCEN_SHIFT)
+#define CGU_UCCEN (0x1UL<<CGU_UCCEN_SHIFT)
+#define CGU_JDIEN_SHIFT 24
+#define CGU_JDIEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_JDIEN_SHIFT))
+#define CGU_JDIEN_0 (0x0UL<<CGU_JDIEN_SHIFT)
+#define CGU_JDIEN_1 (0x1UL<<CGU_JDIEN_SHIFT)
+#define CGU_JDIEN (0x1UL<<CGU_JDIEN_SHIFT)
+#define CGU_DMAUEN_SHIFT 20
+#define CGU_DMAUEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_DMAUEN_SHIFT))
+#define CGU_DMAUEN_0 (0x0UL<<CGU_DMAUEN_SHIFT)
+#define CGU_DMAUEN_1 (0x1UL<<CGU_DMAUEN_SHIFT)
+#define CGU_DMAUEN (0x1UL<<CGU_DMAUEN_SHIFT)
+#define CGU_RFSM1EN_SHIFT 19
+#define CGU_RFSM1EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_RFSM1EN_SHIFT))
+#define CGU_RFSM1EN_0 (0x0UL<<CGU_RFSM1EN_SHIFT)
+#define CGU_RFSM1EN_1 (0x1UL<<CGU_RFSM1EN_SHIFT)
+#define CGU_RFSM1EN (0x1UL<<CGU_RFSM1EN_SHIFT)
+#define CGU_SIISEN_SHIFT 18
+#define CGU_SIISEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_SIISEN_SHIFT))
+#define CGU_SIISEN_0 (0x0UL<<CGU_SIISEN_SHIFT)
+#define CGU_SIISEN_1 (0x1UL<<CGU_SIISEN_SHIFT)
+#define CGU_SIISEN (0x1UL<<CGU_SIISEN_SHIFT)
+#define CGU_USBEN_SHIFT 17
+#define CGU_USBEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_USBEN_SHIFT))
+#define CGU_USBEN_0 (0x0UL<<CGU_USBEN_SHIFT)
+#define CGU_USBEN_1 (0x1UL<<CGU_USBEN_SHIFT)
+#define CGU_USBEN (0x1UL<<CGU_USBEN_SHIFT)
+#define CGU_FCIEN_SHIFT 16
+#define CGU_FCIEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_FCIEN_SHIFT))
+#define CGU_FCIEN_0 (0x0UL<<CGU_FCIEN_SHIFT)
+#define CGU_FCIEN_1 (0x1UL<<CGU_FCIEN_SHIFT)
+#define CGU_FCIEN (0x1UL<<CGU_FCIEN_SHIFT)
+#define CGU_USIMEN_SHIFT 15
+#define CGU_USIMEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_USIMEN_SHIFT))
+#define CGU_USIMEN_0 (0x0UL<<CGU_USIMEN_SHIFT)
+#define CGU_USIMEN_1 (0x1UL<<CGU_USIMEN_SHIFT)
+#define CGU_USIMEN (0x1UL<<CGU_USIMEN_SHIFT)
+#define CGU_GEACEN_SHIFT 14
+#define CGU_GEACEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_GEACEN_SHIFT))
+#define CGU_GEACEN_0 (0x0UL<<CGU_GEACEN_SHIFT)
+#define CGU_GEACEN_1 (0x1UL<<CGU_GEACEN_SHIFT)
+#define CGU_GEACEN (0x1UL<<CGU_GEACEN_SHIFT)
+#define CGU_PWM3EN_SHIFT 13
+#define CGU_PWM3EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_PWM3EN_SHIFT))
+#define CGU_PWM3EN_0 (0x0UL<<CGU_PWM3EN_SHIFT)
+#define CGU_PWM3EN_1 (0x1UL<<CGU_PWM3EN_SHIFT)
+#define CGU_PWM3EN (0x1UL<<CGU_PWM3EN_SHIFT)
+#define CGU_PWM2EN_SHIFT 12
+#define CGU_PWM2EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_PWM2EN_SHIFT))
+#define CGU_PWM2EN_0 (0x0UL<<CGU_PWM2EN_SHIFT)
+#define CGU_PWM2EN_1 (0x1UL<<CGU_PWM2EN_SHIFT)
+#define CGU_PWM2EN (0x1UL<<CGU_PWM2EN_SHIFT)
+#define CGU_PWM1EN_SHIFT 11
+#define CGU_PWM1EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_PWM1EN_SHIFT))
+#define CGU_PWM1EN_0 (0x0UL<<CGU_PWM1EN_SHIFT)
+#define CGU_PWM1EN_1 (0x1UL<<CGU_PWM1EN_SHIFT)
+#define CGU_PWM1EN (0x1UL<<CGU_PWM1EN_SHIFT)
+#define CGU_KBSEN_SHIFT 10
+#define CGU_KBSEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_KBSEN_SHIFT))
+#define CGU_KBSEN_0 (0x0UL<<CGU_KBSEN_SHIFT)
+#define CGU_KBSEN_1 (0x1UL<<CGU_KBSEN_SHIFT)
+#define CGU_KBSEN (0x1UL<<CGU_KBSEN_SHIFT)
+#define CGU_GPIOEN_SHIFT 9
+#define CGU_GPIOEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_GPIOEN_SHIFT))
+#define CGU_GPIOEN_0 (0x0UL<<CGU_GPIOEN_SHIFT)
+#define CGU_GPIOEN_1 (0x1UL<<CGU_GPIOEN_SHIFT)
+#define CGU_GPIOEN (0x1UL<<CGU_GPIOEN_SHIFT)
+#define CGU_UART2EN_SHIFT 8
+#define CGU_UART2EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_UART2EN_SHIFT))
+#define CGU_UART2EN_0 (0x0UL<<CGU_UART2EN_SHIFT)
+#define CGU_UART2EN_1 (0x1UL<<CGU_UART2EN_SHIFT)
+#define CGU_UART2EN (0x1UL<<CGU_UART2EN_SHIFT)
+#define CGU_UART1EN_SHIFT 7
+#define CGU_UART1EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_UART1EN_SHIFT))
+#define CGU_UART1EN_0 (0x0UL<<CGU_UART1EN_SHIFT)
+#define CGU_UART1EN_1 (0x1UL<<CGU_UART1EN_SHIFT)
+#define CGU_UART1EN (0x1UL<<CGU_UART1EN_SHIFT)
+#define CGU_IIC2EN_SHIFT 6
+#define CGU_IIC2EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_IIC2EN_SHIFT))
+#define CGU_IIC2EN_0 (0x0UL<<CGU_IIC2EN_SHIFT)
+#define CGU_IIC2EN_1 (0x1UL<<CGU_IIC2EN_SHIFT)
+#define CGU_IIC2EN (0x1UL<<CGU_IIC2EN_SHIFT)
+#define CGU_IIC1EN_SHIFT 5
+#define CGU_IIC1EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_IIC1EN_SHIFT))
+#define CGU_IIC1EN_0 (0x0UL<<CGU_IIC1EN_SHIFT)
+#define CGU_IIC1EN_1 (0x1UL<<CGU_IIC1EN_SHIFT)
+#define CGU_IIC1EN (0x1UL<<CGU_IIC1EN_SHIFT)
+#define CGU_SPI2EN_SHIFT 4
+#define CGU_SPI2EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_SPI2EN_SHIFT))
+#define CGU_SPI2EN_0 (0x0UL<<CGU_SPI2EN_SHIFT)
+#define CGU_SPI2EN_1 (0x1UL<<CGU_SPI2EN_SHIFT)
+#define CGU_SPI2EN (0x1UL<<CGU_SPI2EN_SHIFT)
+#define CGU_SPI1EN_SHIFT 3
+#define CGU_SPI1EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_SPI1EN_SHIFT))
+#define CGU_SPI1EN_0 (0x0UL<<CGU_SPI1EN_SHIFT)
+#define CGU_SPI1EN_1 (0x1UL<<CGU_SPI1EN_SHIFT)
+#define CGU_SPI1EN (0x1UL<<CGU_SPI1EN_SHIFT)
+#define CGU_SCTUEN_SHIFT 2
+#define CGU_SCTUEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_SCTUEN_SHIFT))
+#define CGU_SCTUEN_0 (0x0UL<<CGU_SCTUEN_SHIFT)
+#define CGU_SCTUEN_1 (0x1UL<<CGU_SCTUEN_SHIFT)
+#define CGU_SCTUEN (0x1UL<<CGU_SCTUEN_SHIFT)
+#define CGU_EXTINTEN_SHIFT 1
+#define CGU_EXTINTEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_EXTINTEN_SHIFT))
+#define CGU_EXTINTEN_0 (0x0UL<<CGU_EXTINTEN_SHIFT)
+#define CGU_EXTINTEN_1 (0x1UL<<CGU_EXTINTEN_SHIFT)
+#define CGU_EXTINTEN (0x1UL<<CGU_EXTINTEN_SHIFT)
+#define CGU_INTCEN_SHIFT 0
+#define CGU_INTCEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_INTCEN_SHIFT))
+#define CGU_INTCEN_0 (0x0UL<<CGU_INTCEN_SHIFT)
+#define CGU_INTCEN_1 (0x1UL<<CGU_INTCEN_SHIFT)
+#define CGU_INTCEN (0x1UL<<CGU_INTCEN_SHIFT)
+
+/* Register description for GATESC2 */
+
+/* Bits definition for register CGU_GATESC2 */
+#define CGU_TRAUPCLKEN_SHIFT 15
+#define CGU_TRAUPCLKEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_TRAUPCLKEN_SHIFT))
+#define CGU_TRAUPCLKEN_0 (0x0UL<<CGU_TRAUPCLKEN_SHIFT)
+#define CGU_TRAUPCLKEN_1 (0x1UL<<CGU_TRAUPCLKEN_SHIFT)
+#define CGU_TRAUPCLKEN (0x1UL<<CGU_TRAUPCLKEN_SHIFT)
+#define CGU_AUTRXPCLKEN_SHIFT 12
+#define CGU_AUTRXPCLKEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_AUTRXPCLKEN_SHIFT))
+#define CGU_AUTRXPCLKEN_0 (0x0UL<<CGU_AUTRXPCLKEN_SHIFT)
+#define CGU_AUTRXPCLKEN_1 (0x1UL<<CGU_AUTRXPCLKEN_SHIFT)
+#define CGU_AUTRXPCLKEN (0x1UL<<CGU_AUTRXPCLKEN_SHIFT)
+#define CGU_AUTRXMCLK2EN_SHIFT 11
+#define CGU_AUTRXMCLK2EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_AUTRXMCLK2EN_SHIFT))
+#define CGU_AUTRXMCLK2EN_0 (0x0UL<<CGU_AUTRXMCLK2EN_SHIFT)
+#define CGU_AUTRXMCLK2EN_1 (0x1UL<<CGU_AUTRXMCLK2EN_SHIFT)
+#define CGU_AUTRXMCLK2EN (0x1UL<<CGU_AUTRXMCLK2EN_SHIFT)
+#define CGU_AUTRXMCLK1EN_SHIFT 10
+#define CGU_AUTRXMCLK1EN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_AUTRXMCLK1EN_SHIFT))
+#define CGU_AUTRXMCLK1EN_0 (0x0UL<<CGU_AUTRXMCLK1EN_SHIFT)
+#define CGU_AUTRXMCLK1EN_1 (0x1UL<<CGU_AUTRXMCLK1EN_SHIFT)
+#define CGU_AUTRXMCLK1EN (0x1UL<<CGU_AUTRXMCLK1EN_SHIFT)
+#define CGU_BBIPCLKEN_SHIFT 9
+#define CGU_BBIPCLKEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_BBIPCLKEN_SHIFT))
+#define CGU_BBIPCLKEN_0 (0x0UL<<CGU_BBIPCLKEN_SHIFT)
+#define CGU_BBIPCLKEN_1 (0x1UL<<CGU_BBIPCLKEN_SHIFT)
+#define CGU_BBIPCLKEN (0x1UL<<CGU_BBIPCLKEN_SHIFT)
+#define CGU_HSDPAHCLKEN_SHIFT 8
+#define CGU_HSDPAHCLKEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_HSDPAHCLKEN_SHIFT))
+#define CGU_HSDPAHCLKEN_0 (0x0UL<<CGU_HSDPAHCLKEN_SHIFT)
+#define CGU_HSDPAHCLKEN_1 (0x1UL<<CGU_HSDPAHCLKEN_SHIFT)
+#define CGU_HSDPAHCLKEN (0x1UL<<CGU_HSDPAHCLKEN_SHIFT)
+#define CGU_3GMHCLKEN_SHIFT 7
+#define CGU_3GMHCLKEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_3GMHCLKEN_SHIFT))
+#define CGU_3GMHCLKEN_0 (0x0UL<<CGU_3GMHCLKEN_SHIFT)
+#define CGU_3GMHCLKEN_1 (0x1UL<<CGU_3GMHCLKEN_SHIFT)
+#define CGU_3GMHCLKEN (0x1UL<<CGU_3GMHCLKEN_SHIFT)
+#define CGU_3GMMCLKEN_SHIFT 6
+#define CGU_3GMMCLKEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_3GMMCLKEN_SHIFT))
+#define CGU_3GMMCLKEN_0 (0x0UL<<CGU_3GMMCLKEN_SHIFT)
+#define CGU_3GMMCLKEN_1 (0x1UL<<CGU_3GMMCLKEN_SHIFT)
+#define CGU_3GMMCLKEN (0x1UL<<CGU_3GMMCLKEN_SHIFT)
+#define CGU_ETBEN_SHIFT 4
+#define CGU_ETBEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_ETBEN_SHIFT))
+#define CGU_ETBEN_0 (0x0UL<<CGU_ETBEN_SHIFT)
+#define CGU_ETBEN_1 (0x1UL<<CGU_ETBEN_SHIFT)
+#define CGU_ETBEN (0x1UL<<CGU_ETBEN_SHIFT)
+#define CGU_MMTUEN_SHIFT 2
+#define CGU_MMTUEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_MMTUEN_SHIFT))
+#define CGU_MMTUEN_0 (0x0UL<<CGU_MMTUEN_SHIFT)
+#define CGU_MMTUEN_1 (0x1UL<<CGU_MMTUEN_SHIFT)
+#define CGU_MMTUEN (0x1UL<<CGU_MMTUEN_SHIFT)
+#define CGU_CAEEN_SHIFT 0
+#define CGU_CAEEN_FIELD (0xFFFFFFFF - (0x1UL<<CGU_CAEEN_SHIFT))
+#define CGU_CAEEN_0 (0x0UL<<CGU_CAEEN_SHIFT)
+#define CGU_CAEEN_1 (0x1UL<<CGU_CAEEN_SHIFT)
+#define CGU_CAEEN (0x1UL<<CGU_CAEEN_SHIFT)
+
+#endif
diff --git a/arch/arm/plat-u6xxx/timer.c b/arch/arm/plat-u6xxx/timer.c
index 62f13f5..357e87c 100644
--- a/arch/arm/plat-u6xxx/timer.c
+++ b/arch/arm/plat-u6xxx/timer.c
@@ -19,6 +19,7 @@
#include <asm/mach/irq.h>
#include <linux/interrupt.h>
#include <mach/irqs.h>
+#include <mach/clock.h>
#include <linux/clk.h>
--
1.7.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 3/6] U6715 gpio platform driver This driver is U6 platform generic (V2)
2010-05-27 8:27 U6/U6715 ARM architecture files, 2nd try Philippe Langlais
2010-05-27 8:27 ` [PATCH 1/6] U6/U6715 ARM architecture files Philippe Langlais
2010-05-27 8:27 ` [PATCH 2/6] U6715 clocks gating management U6 clock generic driver & U6715 cgu clock specific (V2) Philippe Langlais
@ 2010-05-27 8:27 ` Philippe Langlais
2010-06-24 14:26 ` Russell King - ARM Linux
2010-05-27 8:27 ` [PATCH 4/6] U6715 platform serial driver It's a generic driver for all U6 platform (V2) Philippe Langlais
` (2 subsequent siblings)
5 siblings, 1 reply; 17+ messages in thread
From: Philippe Langlais @ 2010-05-27 8:27 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Philippe Langlais <philippe.langlais@stericsson.com>
---
arch/arm/mach-u67xx/board_u67xx_wavex.c | 469 ++++++++++++++++++++
arch/arm/mach-u67xx/devices.c | 12 +-
arch/arm/plat-u6xxx/Makefile | 2 +-
arch/arm/plat-u6xxx/gpio.c | 716 +++++++++++++++++++++++++++++++
arch/arm/plat-u6xxx/include/mach/gpio.h | 396 +++++++++++++++++
5 files changed, 1588 insertions(+), 7 deletions(-)
create mode 100644 arch/arm/plat-u6xxx/gpio.c
create mode 100644 arch/arm/plat-u6xxx/include/mach/gpio.h
diff --git a/arch/arm/mach-u67xx/board_u67xx_wavex.c b/arch/arm/mach-u67xx/board_u67xx_wavex.c
index 2a806e7..a21e465 100644
--- a/arch/arm/mach-u67xx/board_u67xx_wavex.c
+++ b/arch/arm/mach-u67xx/board_u67xx_wavex.c
@@ -24,6 +24,474 @@
#include <asm/mach/arch.h>
#include <mach/irqs.h>
#include <mach/timer.h>
+#include <mach/gpio.h>
+
+#include <mach/scon.h>
+
+/**
+ * SCON initial settings
+ * Allows to define the PIN multiplexing for all the platform (Linux and Modem)
+ */
+struct u6_scon_config u6_scon_init_config[SCON_REGISTER_NB] = {
+ {
+ (void __iomem *) SCON_SYSMUX0_REG,
+ 0 |
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A0 & 0xF))) | /* FM IRQ */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_A1 & 0xF))) | /* UART 2 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_A2 & 0xF))) | /* UART 2 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A3 & 0xF))) |
+ (GPIO_MODE_MUX3 << (2 * (GPIO_A4 & 0xF))) | /* SIMOFF_copy for modem */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A5 & 0xF))) | /* for AGPS */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A6 & 0xF))) | /* LCD backlight
+ -> ressource backligth*/
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A7 & 0xF))) | /* Bluetooth */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A8 & 0xF))) | /* Reserved for mode DPWS*/
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A9 & 0xF))) | /* Reserved for mode DPWS*/
+ (GPIO_MODE_MUX1 << (2 * (GPIO_A10 & 0xF))) | /* UART2 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_A11 & 0xF))) | /* UART2 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_A12 & 0xF))) | /* UART 1, configured
+ by boot, don't touch */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A13 & 0xF))) | /* free */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A14 & 0xF))) | /* PMU irq */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A15 & 0xF)))
+ },
+ {
+ (void __iomem *) SCON_SYSMUX1_REG,
+ 0 |
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A16 & 0xF))) | /* FCI data 3 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A17 & 0xF))) | /* free */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A18 & 0xF))) | /* FCI data 2 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A19 & 0xF))) | /* FCI data 1 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A20 & 0xF))) | /* Cam Ligth copy */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A21 & 0xF))) | /* RF on -> GPIO */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_A22 & 0xF))) | /* RF RF_DPN */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A23 & 0xF))) | /* RF reset -> GPIO */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A24 & 0xF))) | /* AGPS reset */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A25 & 0xF))) | /* AGPS wake up */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A26 & 0xF))) | /* free */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A27 & 0xF))) | /* SPI1 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A28 & 0xF))) | /* SPI1 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_A29 & 0xF))) | /* Audio IIS */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A30 & 0xF))) | /* AGPS pwr on */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_A31 & 0xF))) /* free */
+ },
+ {
+ (void __iomem *) SCON_SYSMUX2_REG,
+ 0 |
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B0 & 0xF))) | /* RF DD */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B1 & 0xF))) | /* RF DU */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B2 & 0xF))) | /* RF FSC */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B3 & 0xF))) | /* RF DCL */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B4 & 0xF))) | /* UART RTS1 -> console */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B5 & 0xF))) | /* UART TXD1 -> console */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B6 & 0xF))) | /* NFI ready -> for NFI */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B7 & 0xF))) | /* VDE_EOFI -> VDE already
+ configured by splashscreen */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B8 & 0xF))) | /* RFEN0 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_B9 & 0xF))) | /* FCICMD -> for FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_B10 & 0xF))) | /* FCICLK -> for FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_B11 & 0xF))) | /* FCIDATA0 -> for FCI */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B12 & 0xF))) | /* RFSIG6 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B13 & 0xF))) | /* RFSIG7 */
+ (GPIO_MODE_MUX3 << (2 * (GPIO_B14 & 0xF))) |
+ (GPIO_MODE_MUX0 << (2 * (GPIO_B15 & 0xF))) /* RFDATA */
+ },
+ {
+ (void __iomem *) SCON_SYSMUX3_REG,
+ 0
+ },
+ {
+ (void __iomem *) SCON_SYSMUX4_REG,
+ 0 |
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C0 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C1 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C2 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C3 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C4 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C5 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C6 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C7 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C8 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C9 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C10 & 0xF))) | /* VDE */
+#ifdef CONFIG_EBI_BUS
+ (GPIO_MODE_MUX2 << (2 * (GPIO_C11 & 0xF))) | /* EBI_CS0 */
+#else
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C11 & 0xF))) | /* VDE */
+#endif
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C12 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C13 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C14 & 0xF))) | /* KCOL0 -> keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C15 & 0xF))) /* KCOL1 -> keypad */
+
+ },
+ {
+ (void __iomem *) SCON_SYSMUX5_REG,
+ 0 |
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C16 & 0xF))) | /* KCOL2 -> keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C17 & 0xF))) | /* KCOL3 -> keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C18 & 0xF))) | /* KCOL4 -> keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C19 & 0xF))) | /* KROW0 -> keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C20 & 0xF))) | /* KROW1 -> keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C21 & 0xF))) | /* KROW2 -> keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C22 & 0xF))) | /* KROW3 -> keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C23 & 0xF))) | /* KROW4 -> keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C24 & 0xF))) | /* RF3GSPIEN0 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C25 & 0xF))) | /* RF3GSPIDATA */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C26 & 0xF))) | /* RF3GSPICLK */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C27 & 0xF))) | /* RFSM_OUT0 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C28 & 0xF))) | /* RFSM_OUT1 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_C29 & 0xF))) | /* RFSM_OUT2 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_C30 & 0xF))) | /* I2C -> ressource */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_C31 & 0xF))) /* I2C -> ressource */
+ },
+ {
+ (void __iomem *) SCON_SYSMUX6_REG,
+ 0 |
+ (GPIO_MODE_MUX1 << (2 * (GPIO_D0 & 0xF))) | /* CAM PWRDN1 -> CAM */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D1 & 0xF))) | /* CAM DATA 0 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D2 & 0xF))) | /* CAM DATA 1 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D3 & 0xF))) | /* CAM DATA 2 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D4 & 0xF))) | /* CAM DATA 3 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D5 & 0xF))) | /* CAM DATA 4 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D6 & 0xF))) | /* CAM DATA 5 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D7 & 0xF))) | /* CAM DATA 6 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D8 & 0xF))) | /* CAM DATA 7 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D9 & 0xF))) | /* CAM DATA 8 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D10 & 0xF))) | /* CAM DATA 9 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D11 & 0xF))) | /* CAMVS */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D12 & 0xF))) | /* CAMHS */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D13 & 0xF))) | /* CAMCLKI */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D14 & 0xF))) | /* CAMCLKO */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_D15 & 0xF))) /* VDDC2EN */
+ },
+ {
+ (void __iomem *) SCON_SYSMUX7_REG,
+ 0 |
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D16 & 0xF))) | /* RF3GGPO9 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D17 & 0xF))) | /* RF3GGPO8 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_D18 & 0xF))) | /* FCI card detect, FCI */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_D19 & 0xF))) | /* CAM_Prelight copy, CAM*/
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D20 & 0xF))) | /* UART1 RXD1 -> Console */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D21 & 0xF))) | /* DIISWS */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D22 & 0xF))) | /* DIISSDO */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D23 & 0xF))) | /* DIISCK */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_D24 & 0xF))) | /* GPIOD24 ->FM Reset */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_D25 & 0xF))) | /* RFSIG3 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D26 & 0xF))) | /* RF3GGPO6 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D27 & 0xF))) | /* RF3GGPO7 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D28 & 0xF))) | /* RF3GGPO5 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_D29 & 0xF))) | /* GPIOD29 USB suspend */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D30 & 0xF))) | /* RF3GGPO4 */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_D31 & 0xF))) /* RFCLK */
+ },
+#ifdef CONFIG_MACH_U67XX_V2_WAVEB_2GB
+{
+ (void __iomem *) SCON_SYSMUX8_REG,
+ 0 |
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E0 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E1 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E2 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E3 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E4 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E5 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E6 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E7 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E8 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E9 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E10 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E11 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E12 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E13 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E14 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E15 & 0xF))) /* DEBUG */
+ },
+ {
+ (void __iomem *) SCON_SYSMUX9_REG,
+ 0 |
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E16 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E17 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E18 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E19 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E20 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E21 & 0xF))) | /* SDATO2 -> SPI2 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E22 & 0xF))) | /* SDATIN2 -> SPI2 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E23 & 0xF))) | /* SCLK2 -> SPI2 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E24 & 0xF))) | /* FCI_copy -> FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E25 & 0xF))) | /* FCI_copy -> FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E26 & 0xF))) | /* FCI_copy -> FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E27 & 0xF))) | /* FCI_copy -> FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E28 & 0xF))) | /* FCI_copy -> FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E29 & 0xF))) | /* FCI_copy
+ -> FCI USB suspend */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E30 & 0xF))) | /* RFSM_OUT3 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E31 & 0xF))) /* GPIO CAM */
+ },
+#else
+{
+ (void __iomem *) SCON_SYSMUX8_REG,
+ 0 |
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E0 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E1 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E2 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E3 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E4 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E5 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E6 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E7 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E8 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E9 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E10 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E11 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E12 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E13 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E14 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E15 & 0xF))) /* DEBUG */
+ },
+ {
+ (void __iomem *) SCON_SYSMUX9_REG,
+ 0 |
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E16 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E17 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E18 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E19 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX2 << (2 * (GPIO_E20 & 0xF))) | /* DEBUG */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E21 & 0xF))) | /* SDATO2 -> SPI2 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E22 & 0xF))) | /* SDATIN2 -> SPI2 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E23 & 0xF))) | /* SCLK2 -> SPI2 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E24 & 0xF))) | /* FCI_copy -> FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E25 & 0xF))) | /* FCI_copy -> FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E26 & 0xF))) | /* FCI_copy -> FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E27 & 0xF))) | /* FCI_copy -> FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E28 & 0xF))) | /* FCI_copy -> FCI */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E29 & 0xF))) | /* FCI_copy
+ -> FCI USB suspend */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_E30 & 0xF))) | /* RFSM_OUT3 */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_E31 & 0xF))) /* GPIO CAM */
+ },
+
+#endif
+ {
+ (void __iomem *) SCON_SYSMUX10_REG,
+ 0 |
+#ifdef CONFIG_EBI_BUS
+ (GPIO_MODE_MUX3 << (2 * (GPIO_F0 & 0xF))) | /* EBI_IO0_copy */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F1 & 0xF))) | /* EBI_OE_RW_copy */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F2 & 0xF))) | /* EBI_WE_E_copy */
+#else
+ (GPIO_MODE_MUX1 << (2 * (GPIO_F0 & 0xF))) | /* CAM_PWR_REG -> CAM */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_F1 & 0xF))) | /* AGPS FRAME_SYNC, AGPS */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F2 & 0xF))) | /* free */
+#endif
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F3 & 0xF))) | /* KCOL5 -> Keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F4 & 0xF))) | /* KCOL6 -> Keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F5 & 0xF))) | /* KCOL7 -> Keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F6 & 0xF))) | /* KROW5 -> Keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F7 & 0xF))) | /* KROW6 -> Keypad */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F8 & 0xF))) | /* KROW7 -> Keypad */
+ (GPIO_MODE_MUX1 << (2 * (GPIO_F9 & 0xF))) | /* eMMC_PDn -> FCI */
+#ifdef CONFIG_EBI_BUS
+ (GPIO_MODE_MUX3 << (2 * (GPIO_F10 & 0xF))) | /* VDE_CS0_copy */
+ (GPIO_MODE_MUX3 << (2 * (GPIO_F11 & 0xF))) | /* EBI_IO1_copy */
+ (GPIO_MODE_MUX3 << (2 * (GPIO_F12 & 0xF))) | /* EBI_IO2_copy */
+ (GPIO_MODE_MUX3 << (2 * (GPIO_F13 & 0xF))) | /* EBI_IO3_copy */
+ (GPIO_MODE_MUX3 << (2 * (GPIO_F14 & 0xF))) | /* EBI_IO4_copy */
+ (GPIO_MODE_MUX3 << (2 * (GPIO_F15 & 0xF))) /* EBI_IO5_copy */
+#else
+ (GPIO_MODE_MUX3 << (2 * (GPIO_F10 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F11 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F12 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F13 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F14 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F15 & 0xF))) /* VDE */
+#endif
+ },
+ {
+ (void __iomem *) SCON_SYSMUX11_REG,
+ 0 |
+#ifdef CONFIG_EBI_BUS
+ (GPIO_MODE_MUX3 << (2 * (GPIO_F16 & 0xF))) | /* EBI_IO6_copy */
+ (GPIO_MODE_MUX3 << (2 * (GPIO_F17 & 0xF))) | /* EBI_IO7_copy */
+#else
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F16 & 0xF))) | /* VDE */
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F17 & 0xF))) | /* VDE */
+#endif
+ (GPIO_MODE_MUX0 << (2 * (GPIO_F18 & 0xF))) /* NFI_CE_n -> NFI */
+ },
+ /* Configure PAD Value */
+ {
+ (void __iomem *) SCON_SYSPAD0_REG,
+ 0 |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A0 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A1 & 0xF))) |
+ (SCON_PAD_PLAIN_INPUT << (2 * (GPIO_A2 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A3 & 0xF))) |
+ (SCON_PAD_PLAIN_INPUT << (2 * (GPIO_A4 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A5 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A6 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A7 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A8 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A9 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A10 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A11 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A12 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A13 & 0xF))) |
+ (SCON_PAD_PLAIN_INPUT << (2 * (GPIO_A14 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A15 & 0xF)))
+ },
+ {
+ (void __iomem *) SCON_SYSPAD1_REG,
+ 0 |
+ (SCON_PAD_PLAIN_INPUT << (2 * (GPIO_A16 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A17 & 0xF))) |
+ (SCON_PAD_PLAIN_INPUT << (2 * (GPIO_A18 & 0xF))) |
+ (SCON_PAD_PLAIN_INPUT << (2 * (GPIO_A19 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A20 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A21 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A22 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A23 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A24 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A25 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A26 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A27 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A28 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A29 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A30 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_A31 & 0xF)))
+ },
+ {
+ (void __iomem *) SCON_SYSPAD2_REG,
+ 0 |
+ (SCON_PAD_PULL_DOWN << (2 * (GPIO_B0 & 0xF))) |
+ (SCON_PAD_PULL_DOWN << (2 * (GPIO_B1 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B2 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B3 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B4 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B5 & 0xF))) |
+ (SCON_PAD_PLAIN_INPUT << (2 * (GPIO_B6 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B7 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B8 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B9 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B10 & 0xF))) |
+ (SCON_PAD_PLAIN_INPUT << (2 * (GPIO_B11 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B12 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B13 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B14 & 0xF))) |
+ (SCON_PAD_REPEATER << (2 * (GPIO_B15 & 0xF)))
+ },
+};
+
+/* GPIO def settings to avoid HW issue */
+struct u6_gpio_config u6_gpio_init_config[] = {
+ /* GPIO A bank */
+ {
+ .gpio = GPIO_A5,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 1,
+ },
+ {
+ .gpio = GPIO_A6,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 1,
+ },
+ {
+ .gpio = GPIO_A7,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_A8,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 1,
+ },
+ {
+ .gpio = GPIO_A9,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 1,
+ },
+ {
+ .gpio = GPIO_A13,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_A17,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_A21,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_A23,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_A24,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 1,
+ },
+ {
+ .gpio = GPIO_A25,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_A30,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ /* GPIO B bank */
+ /* GPIO C bank */
+ /* GPIO D bank */
+ {
+ .gpio = GPIO_D0,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_D24,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_D29,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ /* GPIO E bank */
+ {
+ .gpio = GPIO_E31,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ /* GPIO F bank */
+ {
+ .gpio = GPIO_F0,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_F1,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_F2,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ },
+ {
+ .gpio = GPIO_F9,
+ .dir = GPIO_DIR_OUTPUT ,
+ .value = 0,
+ }
+};
+
+u32 gpio_to_configure = ARRAY_SIZE(u6_gpio_init_config);
/* List of board specific devices */
static struct platform_device *devices[] __initdata = {
@@ -31,6 +499,7 @@ static struct platform_device *devices[] __initdata = {
void __init u67xx_init(void)
{
+ u6_gpio_init();
/* Add specific board devices */
platform_add_devices(devices, ARRAY_SIZE(devices));
}
diff --git a/arch/arm/mach-u67xx/devices.c b/arch/arm/mach-u67xx/devices.c
index 0ead380..8e812fb 100644
--- a/arch/arm/mach-u67xx/devices.c
+++ b/arch/arm/mach-u67xx/devices.c
@@ -48,12 +48,12 @@ unsigned char extint_to_gpio[NR_EXTINT] = {
EXPORT_SYMBOL(extint_to_gpio);
struct gpio_bank u6_gpio_bank[6] = {
- {(void __iomem *)GPIOA_PINS_REG, (void __iomem *)SCON_SYSMUX0_REG},
- {(void __iomem *)GPIOB_PINS_REG, (void __iomem *)SCON_SYSMUX2_REG},
- {(void __iomem *)GPIOC_PINS_REG, (void __iomem *)SCON_SYSMUX4_REG},
- {(void __iomem *)GPIOD_PINS_REG, (void __iomem *)SCON_SYSMUX6_REG},
- {(void __iomem *)GPIOE_PINS_REG, (void __iomem *)SCON_SYSMUX8_REG},
- {(void __iomem *)GPIOF_PINS_REG, (void __iomem *)SCON_SYSMUX10_REG},
+ {GPIOA_PINS_REG, SCON_SYSMUX0_REG},
+ {GPIOB_PINS_REG, SCON_SYSMUX2_REG},
+ {GPIOC_PINS_REG, SCON_SYSMUX4_REG},
+ {GPIOD_PINS_REG, SCON_SYSMUX6_REG},
+ {GPIOE_PINS_REG, SCON_SYSMUX8_REG},
+ {GPIOF_PINS_REG, SCON_SYSMUX10_REG},
};
static struct gpio_data u6_gpio_data = {
diff --git a/arch/arm/plat-u6xxx/Makefile b/arch/arm/plat-u6xxx/Makefile
index afdf82b..3d6898e 100644
--- a/arch/arm/plat-u6xxx/Makefile
+++ b/arch/arm/plat-u6xxx/Makefile
@@ -3,6 +3,6 @@
#
# Common support
-obj-y := io.o irq.o clock.o
+obj-y := io.o irq.o clock.o gpio.o
obj-$(CONFIG_U6_MTU_TIMER) += timer.o
diff --git a/arch/arm/plat-u6xxx/gpio.c b/arch/arm/plat-u6xxx/gpio.c
new file mode 100644
index 0000000..40e25fc
--- /dev/null
+++ b/arch/arm/plat-u6xxx/gpio.c
@@ -0,0 +1,716 @@
+/*
+ * linux/arch/arm/plat-u6xxx/gpio.c
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Loic Pallardy <loic.pallardy@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ * Support functions for GPIO
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/sysdev.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <mach/irqs.h>
+#include <mach/gpio.h>
+#include <asm/mach/irq.h>
+#include <mach/scon.h>
+
+/*
+ * PN5220 GPIO/MUX registers
+ * defined in asm/arch/registers.h
+ */
+
+#define U6_GPIO_PINS_OFFSET 0
+#define U6_GPIO_OUTPUT_OFFSET 4
+#define U6_GPIO_DIR_OFFSET 8
+
+#define U6_MUX2_OFFSET 4
+
+static struct gpio_bank *gpio_bank_desc;
+static int gpio_bank_count;
+
+static inline struct gpio_bank *get_gpio_bank(int gpio)
+{
+ /* 32 GPIOs per bank */
+ return &(gpio_bank_desc[gpio >> 5]);
+}
+
+static inline int get_gpio_index(int gpio)
+{
+ return gpio & 0x1f;
+}
+
+static int check_gpio(int gpio)
+{
+ int retval = ((unsigned int)gpio) < GPIO_COUNT;
+ if (unlikely(!retval)) {
+ printk(KERN_ERR "u6-gpio: invalid GPIO %d\n", gpio);
+ dump_stack();
+ }
+ return retval;
+}
+
+static inline int gpio_is_requested(struct gpio_bank *bank, unsigned long mask)
+{
+ return bank->reserved_map & mask;
+}
+
+static int check_gpio_requested(struct gpio_bank *bank, int index)
+{
+ int retval = gpio_is_requested(bank, 1 << index);
+ if (unlikely(!retval)) {
+ char c = 'A' + (bank - get_gpio_bank(0));
+ printk(KERN_ERR "u6-gpio: GPIO %c%d is not requested yet\n",
+ c, index);
+ dump_stack();
+ }
+ return retval;
+}
+
+static int check_gpio_unrequested(struct gpio_bank *bank, int index)
+{
+ int retval = !gpio_is_requested(bank, 1 << index);
+ if (unlikely(!retval)) {
+ char c = 'A' + (bank - get_gpio_bank(0));
+ printk(KERN_ERR "u6-gpio: GPIO %c%d is already requested\n",
+ c, index);
+ dump_stack();
+ }
+ return retval;
+}
+
+static int check_gpio_irq(int gpio_irq)
+{
+ int retval = ((unsigned int)gpio_irq) < NR_EXTINT;
+ if (unlikely(!retval)) {
+ printk(KERN_ERR "u6-gpio: invalid GPIO-IRQ %d\n", gpio_irq);
+ dump_stack();
+ }
+ return retval;
+}
+
+static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
+{
+ u32 reg = bank->gpio_base;
+ u32 l;
+
+ /* select direction register */
+ reg += U6_GPIO_DIR_OFFSET;
+
+ /* in register 0 = input, 1 = output */
+ l = inl(reg);
+ if (is_input)
+ l &= ~(1 << gpio);
+ else
+ l |= (1 << gpio);
+ outl(l, reg);
+}
+
+int u6_gpio_set_direction(int gpio, int is_input)
+{
+ unsigned long flags, index;
+ struct gpio_bank *bank;
+
+ if (!check_gpio(gpio))
+ return -EINVAL;
+
+ bank = get_gpio_bank(gpio);
+ index = get_gpio_index(gpio);
+ if (!check_gpio_requested(bank, index))
+ return -EINVAL;
+
+ spin_lock_irqsave(&bank->lock, flags);
+ _set_gpio_direction(bank, index, is_input);
+ spin_unlock_irqrestore(&bank->lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(u6_gpio_set_direction);
+
+static void _set_gpio_mode(struct gpio_bank *bank, int gpio, int mode)
+{
+ u32 reg = bank->mux_base;
+ unsigned long flags;
+ unsigned long l;
+
+ /* select direction register */
+ if (gpio >= 16) {
+ reg += U6_MUX2_OFFSET;
+ gpio -= 16;
+ }
+
+ hw_raw_local_irq_save(flags);
+ /* apply mux mode */
+ /* width 2 bit */
+ l = inl(reg);
+ l &= ~(3 << (gpio * 2));
+ l |= (mode << (gpio * 2));
+ outl(l, reg);
+ hw_raw_local_irq_restore(flags);
+}
+
+int u6_gpio_set_mode(int gpio, int mode)
+{
+ struct gpio_bank *bank;
+ int index;
+
+ if (!check_gpio(gpio))
+ return -EINVAL;
+
+ bank = get_gpio_bank(gpio);
+ index = get_gpio_index(gpio);
+ if (!check_gpio_requested(bank, index))
+ return -EINVAL;
+
+ spin_lock(&bank->lock);
+ _set_gpio_mode(bank, get_gpio_index(gpio), mode);
+ spin_unlock(&bank->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(u6_gpio_set_mode);
+
+int u6_gpio_set_mode_gpio(int gpio)
+{
+ int muxmode = gpio >= GPIO_B0 ? GPIO_MODE_MUX1 : GPIO_MODE_MUX0;
+ return u6_gpio_set_mode(gpio, muxmode);
+}
+EXPORT_SYMBOL(u6_gpio_set_mode_gpio);
+
+static void _write_gpio_pin(struct gpio_bank *bank, int gpio, int gpio_value)
+{
+ u32 reg = bank->gpio_base;
+ unsigned long flags;
+ unsigned long l = 0;
+
+ reg += U6_GPIO_OUTPUT_OFFSET;
+ hw_raw_local_irq_save(flags);
+ l = inl(reg);
+ if (gpio_value)
+ l |= 1 << gpio;
+ else
+ l &= ~(1 << gpio);
+ outl(l, reg);
+ hw_raw_local_irq_restore(flags);
+
+}
+
+static int u6_gpio_to_extint(int gpio)
+{
+ int extint_idx;
+
+ for (extint_idx = 0; extint_idx < NR_EXTINT; extint_idx++)
+ if (extint_to_gpio[extint_idx] == gpio)
+ return extint_idx;
+
+ return -1;
+}
+
+int u6_gpio_write_pin(int gpio, int gpio_value)
+{
+ struct gpio_bank *bank;
+ unsigned long index;
+
+ if (!check_gpio(gpio))
+ return -EINVAL;
+
+ bank = get_gpio_bank(gpio);
+ index = get_gpio_index(gpio);
+ if (!check_gpio_requested(bank, index))
+ return -EINVAL;
+
+ spin_lock(&bank->lock);
+ _write_gpio_pin(bank, index, gpio_value);
+ spin_unlock(&bank->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(u6_gpio_write_pin);
+
+int u6_gpio_read_pin(int gpio)
+{
+ struct gpio_bank *bank;
+ u32 reg;
+ u32 l = 0;
+ int irq, index;
+
+ if (!check_gpio(gpio))
+ return -EINVAL;
+
+ bank = get_gpio_bank(gpio);
+ index = get_gpio_index(gpio);
+ if (!check_gpio_requested(bank, index))
+ return -EINVAL;
+
+ /* check if the GPIO is used as extint */
+ irq = u6_gpio_to_extint(gpio);
+ if (irq >= 0) {
+ /* and if it's an alternate internal signal */
+ /* (cf U67xx datasheet table 444) */
+ reg = EXTINT_CFGx(irq);
+ l = inl(reg);
+ if (l & EXTINT_SEL_ALTERNATE) {
+ reg = EXTINT_SIGNAL_REG;
+ return (inl(reg) & (1 << irq)) != 0;
+ }
+ }
+
+ reg = bank->gpio_base;
+ reg += U6_GPIO_PINS_OFFSET;
+ return (inl(reg) & (1 << index)) != 0;
+}
+EXPORT_SYMBOL(u6_gpio_read_pin);
+
+static int _u6_gpio_request(struct gpio_bank *bank, int index)
+{
+ int retval = 0;
+ unsigned long mask = 1 << index;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bank->lock, flags);
+ if (unlikely(!check_gpio_unrequested(bank, index)))
+ retval = -EINVAL;
+ else
+ bank->reserved_map |= mask;
+ spin_unlock_irqrestore(&bank->lock, flags);
+
+ return retval;
+}
+
+static int u6_gpio_acquire(struct gpio_chip *chip, unsigned offset)
+{
+ struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
+
+ return _u6_gpio_request(bank, offset);
+}
+
+int u6_gpio_request(int gpio)
+{
+ int index;
+ struct gpio_bank *bank;
+
+ if (!check_gpio(gpio))
+ return -EINVAL;
+
+ index = get_gpio_index(gpio);
+ bank = get_gpio_bank(gpio);
+
+ return _u6_gpio_request(bank, index);
+}
+EXPORT_SYMBOL(u6_gpio_request);
+
+static void _u6_gpio_free(struct gpio_bank *bank, int index)
+{
+ unsigned long mask = 1 << index;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bank->lock, flags);
+ if (likely(check_gpio_requested(bank, index)))
+ bank->reserved_map &= ~mask;
+ spin_unlock_irqrestore(&bank->lock, flags);
+}
+
+static void u6_gpio_release(struct gpio_chip *chip, unsigned offset)
+{
+ struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
+
+ return _u6_gpio_free(bank, offset);
+}
+
+void u6_gpio_free(int gpio)
+{
+ int index;
+ struct gpio_bank *bank;
+
+ if (!check_gpio(gpio))
+ return;
+
+ index = get_gpio_index(gpio);
+ bank = get_gpio_bank(gpio);
+ _u6_gpio_free(bank, index);
+}
+EXPORT_SYMBOL(u6_gpio_free);
+
+/* New GPIO_GENERIC interface */
+
+static int gpio_input(struct gpio_chip *chip, unsigned offset)
+{
+ struct gpio_bank *bank;
+ unsigned long flags;
+
+ bank = container_of(chip, struct gpio_bank, chip);
+ spin_lock_irqsave(&bank->lock, flags);
+ _set_gpio_direction(bank, offset, 1);
+ spin_unlock_irqrestore(&bank->lock, flags);
+ return 0;
+}
+
+static int gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ return u6_gpio_read_pin(chip->base + offset);
+}
+
+static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct gpio_bank *bank;
+ unsigned long flags;
+
+ bank = container_of(chip, struct gpio_bank, chip);
+ spin_lock_irqsave(&bank->lock, flags);
+ _write_gpio_pin(bank, offset, value);
+ _set_gpio_direction(bank, offset, 0);
+ spin_unlock_irqrestore(&bank->lock, flags);
+ return 0;
+}
+
+static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct gpio_bank *bank;
+ unsigned long flags;
+
+ bank = container_of(chip, struct gpio_bank, chip);
+ spin_lock_irqsave(&bank->lock, flags);
+ _write_gpio_pin(bank, offset, value);
+ spin_unlock_irqrestore(&bank->lock, flags);
+}
+
+static int gpio_2irq(struct gpio_chip *chip, unsigned offset)
+{
+ return u6_gpio_to_extint(chip->base + offset);
+}
+
+/*
+ * U6 EXTINT : only EXTINT 3 is managed by Linux
+ * We need to unmask the GPIO bank interrupt as soon as possible to
+ * avoid missing GPIO interrupts for other lines in the bank.
+ * Then we need to mask-read-clear-unmask the triggered GPIO lines
+ * in the bank to avoid missing nested interrupts for a GPIO line.
+ * If we wait to unmask individual GPIO lines in the bank after the
+ * line's interrupt handler has been run, we may miss some nested
+ * interrupts.
+ */
+static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+ unsigned long isr;
+ unsigned long flags;
+ unsigned int gpio_irq;
+
+ /* LPA TBD */
+ desc->chip->ack(irq);
+
+ /* read status */
+ hw_raw_local_irq_save(flags);
+ isr = inl(EXTINT_STATUS_REG) & inl(EXTINT_ENABLE3_REG);
+ /* clear IRQ source(s) */
+ outl(~isr, EXTINT_STATUS_REG);
+ hw_raw_local_irq_restore(flags);
+
+ gpio_irq = IRQ_COUNT;
+ for (; isr != 0; isr >>= 1, gpio_irq++) {
+ struct irq_desc *d;
+ if (!(isr & 1))
+ continue;
+ d = irq_desc + gpio_irq;
+#ifdef CONFIG_DEBUG_EXTINT
+ printk(KERN_ERR "got something from EXTINT#%i line\n",
+ gpio_irq - IRQ_COUNT);
+#endif
+ desc_handle_irq(gpio_irq, d);
+ }
+
+}
+
+static void gpio_ack_irq(unsigned int irq)
+{
+ unsigned int gpio_irq = irq - IRQ_COUNT;
+ unsigned long flags;
+ hw_raw_local_irq_save(flags);
+ outl(~(1 << gpio_irq), EXTINT_STATUS_REG);
+ hw_raw_local_irq_restore(flags);
+}
+
+static void gpio_mask_irq(unsigned int irq)
+{
+ unsigned int gpio_irq = irq - IRQ_COUNT;
+ outl(inl(EXTINT_ENABLE3_REG) & ~(1 << gpio_irq),
+ EXTINT_ENABLE3_REG);
+}
+
+static void gpio_unmask_irq(unsigned int irq)
+{
+ unsigned int gpio_irq = irq - IRQ_COUNT;
+ outl(inl(EXTINT_ENABLE3_REG) | (1 << gpio_irq),
+ EXTINT_ENABLE3_REG);
+}
+
+int u6_gpio_clear_irq(unsigned int irq)
+{
+ unsigned int gpio_irq;
+ unsigned long flags;
+ gpio_irq = irq - IRQ_COUNT;
+ if (!check_gpio_irq(gpio_irq))
+ return -EINVAL;
+ hw_raw_local_irq_save(flags);
+ outl(~(1 << gpio_irq), EXTINT_STATUS_REG);
+ hw_raw_local_irq_restore(flags);
+ return 0;
+}
+EXPORT_SYMBOL(u6_gpio_clear_irq);
+
+int u6_gpio_set_irq_debounce(int irq, int cycles)
+{
+ int gpio;
+ struct gpio_bank *bank;
+ u32 reg;
+ int mode;
+ u32 l = 0;
+
+ gpio = EXTINT_TO_GPIO(irq);
+ irq -= IRQ_COUNT;
+ if (!check_gpio_irq(irq))
+ goto err;
+
+ bank = get_gpio_bank(gpio);
+ if (!check_gpio_requested(bank, get_gpio_index(gpio)))
+ return -EINVAL;
+
+ reg = EXTINT_CFGx(irq);
+ l = inl(reg);
+
+ mode = l & (3 << EXTINT_MODE_SHIFT);
+ if (mode == EXTINT_MODE_BYPASS)
+ goto err;
+
+ /* clear mode and set streching to debounce */
+ if (mode == EXTINT_MODE_STRETCHING) {
+ l &= ~(3 << EXTINT_MODE_SHIFT);
+ l |= EXTINT_MODE_DEBOUNCE;
+ }
+ /* clear and set the debounce field */
+ l &= ~(7 << EXTINT_DEBOUNCE_SHIFT);
+ l |= ((cycles & 0x7) << EXTINT_DEBOUNCE_SHIFT);
+ outl(l, reg);
+
+ return 0;
+err:
+ return -EINVAL;
+}
+EXPORT_SYMBOL(u6_gpio_set_irq_debounce);
+
+int u6_gpio_set_irq_selection(int irq, int selection)
+{
+ int gpio, index;
+ struct gpio_bank *bank;
+ u32 l = 0;
+ u32 reg;
+
+ gpio = EXTINT_TO_GPIO(irq);
+ irq -= IRQ_COUNT;
+ if (!check_gpio_irq(irq))
+ return -EINVAL;
+
+ bank = get_gpio_bank(gpio);
+ index = get_gpio_index(gpio);
+ if (!check_gpio_requested(bank, index))
+ return -EINVAL;
+
+ reg = EXTINT_CFGx(irq);
+ l = inl(reg);
+
+ if (selection == EXTINT_SEL_ALTERNATE)
+ l |= EXTINT_SEL_ALTERNATE;
+ else
+ l &= ~EXTINT_SEL_ALTERNATE;
+ outl(l, reg);
+
+ return 0;
+}
+EXPORT_SYMBOL(u6_gpio_set_irq_selection);
+
+/*
+ * -the level type set the bypass mode
+ * -and by default the edge type select the stretching mode.
+ * if you would a debounce you must defined your nb
+ * cycle with u6_set_gpio_debounce
+ */
+static int _set_gpio_triggering(int gpio_irq, int trigger)
+{
+ u32 reg = EXTINT_CFGx(gpio_irq);
+ u32 l = 0;
+
+ l = inl(reg);
+ l &= ~(3 << 6 | 1 << 2);
+
+ if (trigger == IRQ_TYPE_LEVEL_LOW)
+ l |= EXTINT_POL_NEGATIVE;
+ else if (trigger == IRQ_TYPE_LEVEL_HIGH)
+ l |= EXTINT_POL_POSITIVE;
+ else if (trigger == IRQ_TYPE_EDGE_RISING)
+ l |= (EXTINT_MODE_STRETCHING | EXTINT_POL_POSITIVE);
+ else if (trigger == IRQ_TYPE_EDGE_FALLING)
+ l |= (EXTINT_MODE_STRETCHING | EXTINT_POL_NEGATIVE);
+ else if (trigger == IRQ_TYPE_EDGE_BOTH)
+ l |= EXTINT_MODE_DUAL_EDGE;
+ else
+ goto err;
+
+ outl(l, reg);
+
+ return 0;
+err:
+ return -EINVAL;
+}
+
+static int gpio_irq_type(unsigned irq, unsigned type)
+{
+ unsigned gpio_irq;
+ int retval;
+
+ gpio_irq = irq - IRQ_COUNT;
+
+ if (!check_gpio_irq(gpio_irq))
+ return -EINVAL;
+
+ if (type & (IRQF_TRIGGER_PROBE))
+ return -EINVAL;
+
+ retval = _set_gpio_triggering(gpio_irq, type);
+ return retval;
+}
+
+static struct irq_chip gpio_irq_chip = {
+ .ack = gpio_ack_irq,
+ .disable = gpio_mask_irq,
+ .enable = gpio_unmask_irq,
+ .mask = gpio_mask_irq,
+ .unmask = gpio_unmask_irq,
+ .set_type = gpio_irq_type,
+ /*.set_wake = gpio_wake_enable, */
+};
+
+static int initialized;
+
+static int __init u6_gpio_probe(struct platform_device *pdev)
+{
+ int i, j;
+ int gpio = 0;
+ struct gpio_bank *bank;
+ struct gpio_data *data = pdev->dev.platform_data;
+ unsigned long flags;
+
+ initialized = 1;
+
+ printk(KERN_INFO "U6 GPIO\n");
+ gpio_bank_desc = data->gpio_bank_desc;
+ gpio_bank_count = data->nb_banks;
+
+ for (i = 0; i < gpio_bank_count; i++) {
+ int gpio_count = 32; /* 32 GPIO per bank */
+ bank = &gpio_bank_desc[i];
+ bank->reserved_map = 0;
+ spin_lock_init(&bank->lock);
+
+ bank->chip.request = u6_gpio_acquire;
+ bank->chip.free = u6_gpio_release;
+ bank->chip.direction_input = gpio_input;
+ bank->chip.get = gpio_get;
+ bank->chip.direction_output = gpio_output;
+ bank->chip.set = gpio_set;
+ bank->chip.to_irq = gpio_2irq;
+ bank->chip.label = "gpio";
+ bank->chip.base = gpio;
+ gpio += gpio_count;
+
+ bank->chip.ngpio = gpio_count;
+
+ gpiochip_add(&bank->chip);
+
+ }
+
+ /* for extint */
+ for (j = IRQ_COUNT; j < IRQ_COUNT + NR_EXTINT; j++) {
+ set_irq_chip(j, &gpio_irq_chip);
+ set_irq_handler(j, handle_simple_irq);
+ set_irq_flags(j, IRQF_VALID);
+ }
+
+ hw_raw_local_irq_save(flags);
+ /* mask all EXT IRQ sources before registring handler */
+ /* read status */
+ j = inl(EXTINT_STATUS_REG) & inl(EXTINT_ENABLE3_REG);
+ /* clear IRQ source(s) */
+ outl(j, EXTINT_STATUS_REG);
+
+ outl(0, EXTINT_ENABLE3_REG);
+
+ /* set irq in low level */
+ set_irq_type(IRQ_EXTINT3, IRQF_TRIGGER_LOW);
+
+ /* chained GPIO-IRQ on EXTINT3 */
+ set_irq_chained_handler(IRQ_EXTINT3, gpio_irq_handler);
+ hw_raw_local_irq_restore(flags);
+
+ return 0;
+}
+
+static struct platform_driver u6_gpio_driver = {
+ .probe = u6_gpio_probe,
+ .remove = NULL,
+ .suspend = NULL,
+ .resume = NULL,
+ .driver = {
+ .name = "u6-gpio",
+ },
+};
+
+static struct sysdev_class u6_gpio_sysclass = {
+ .name = "gpio",
+ .suspend = 0, /*u6_gpio_suspend, */
+ .resume = 0, /*u6_gpio_resume, */
+};
+
+static struct sys_device u6_gpio_device = {
+ .id = 0,
+ .cls = &u6_gpio_sysclass,
+};
+
+/*
+ * This may get called early from board specific init
+ * for boards that have interrupts routed via FPGA.
+ */
+int u6_gpio_init(void)
+{
+ if (!initialized)
+ return platform_driver_register(&u6_gpio_driver);
+ else
+ return 0;
+}
+
+static int __init u6_gpio_sysinit(void)
+{
+ int ret = 0;
+
+ if (!initialized)
+ ret = u6_gpio_init();
+
+ if (ret == 0) {
+ ret = sysdev_class_register(&u6_gpio_sysclass);
+ if (ret == 0)
+ ret = sysdev_register(&u6_gpio_device);
+ }
+
+ return ret;
+}
+
+arch_initcall(u6_gpio_sysinit);
diff --git a/arch/arm/plat-u6xxx/include/mach/gpio.h b/arch/arm/plat-u6xxx/include/mach/gpio.h
new file mode 100644
index 0000000..a205f1c
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/gpio.h
@@ -0,0 +1,396 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/gpio.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Loic Pallardy <loic.pallardy@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ * GPIO handling defines and functions
+ */
+
+#ifndef __ASM_PLAT_U6_GPIO_H
+#define __ASM_PLAT_U6_GPIO_H
+
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/gpio.h>
+
+#include <linux/errno.h>
+#include <asm-generic/gpio.h>
+
+/* GPIO bank description */
+struct gpio_bank {
+ u32 gpio_base;
+ u32 mux_base;
+ u16 irq;
+ u16 virtual_irq_start;
+ int method;
+ u32 reserved_map;
+ u32 suspend_wakeup;
+ u32 saved_wakeup;
+ spinlock_t lock;
+ struct gpio_chip chip;
+};
+
+
+struct gpio_data {
+ u32 nb_banks;
+ struct gpio_bank *gpio_bank_desc;
+};
+
+
+/* GPIO Init configuration */
+
+struct u6_gpio_config {
+ u32 gpio;
+ u32 dir;
+ u32 value;
+};
+
+
+/* list of GPIO */
+enum U6_GPIO_LIST {
+ GPIO_A0 = 0,
+ GPIO_A1,
+ GPIO_A2,
+ GPIO_A3,
+ GPIO_A4,
+ GPIO_A5,
+ GPIO_A6,
+ GPIO_A7,
+ GPIO_A8,
+ GPIO_A9,
+ GPIO_A10,
+ GPIO_A11,
+ GPIO_A12,
+ GPIO_A13,
+ GPIO_A14,
+ GPIO_A15,
+ GPIO_A16,
+ GPIO_A17,
+ GPIO_A18,
+ GPIO_A19,
+ GPIO_A20,
+ GPIO_A21,
+ GPIO_A22,
+ GPIO_A23,
+ GPIO_A24,
+ GPIO_A25,
+ GPIO_A26,
+ GPIO_A27,
+ GPIO_A28,
+ GPIO_A29,
+ GPIO_A30,
+ GPIO_A31,
+ GPIO_B0,
+ GPIO_B1,
+ GPIO_B2,
+ GPIO_B3,
+ GPIO_B4,
+ GPIO_B5,
+ GPIO_B6,
+ GPIO_B7,
+ GPIO_B8,
+ GPIO_B9,
+ GPIO_B10,
+ GPIO_B11,
+ GPIO_B12,
+ GPIO_B13,
+ GPIO_B14,
+ GPIO_B15,
+ GPIO_B16,
+ GPIO_B17,
+ GPIO_B18,
+ GPIO_B19,
+ GPIO_B20,
+ GPIO_B21,
+ GPIO_B22,
+ GPIO_B23,
+ GPIO_B24,
+ GPIO_B25,
+ GPIO_B26,
+ GPIO_B27,
+ GPIO_B28,
+ GPIO_B29,
+ GPIO_B30,
+ GPIO_B31,
+ GPIO_C0,
+ GPIO_C1,
+ GPIO_C2,
+ GPIO_C3,
+ GPIO_C4,
+ GPIO_C5,
+ GPIO_C6,
+ GPIO_C7,
+ GPIO_C8,
+ GPIO_C9,
+ GPIO_C10,
+ GPIO_C11,
+ GPIO_C12,
+ GPIO_C13,
+ GPIO_C14,
+ GPIO_C15,
+ GPIO_C16,
+ GPIO_C17,
+ GPIO_C18,
+ GPIO_C19,
+ GPIO_C20,
+ GPIO_C21,
+ GPIO_C22,
+ GPIO_C23,
+ GPIO_C24,
+ GPIO_C25,
+ GPIO_C26,
+ GPIO_C27,
+ GPIO_C28,
+ GPIO_C29,
+ GPIO_C30,
+ GPIO_C31,
+ GPIO_D0,
+ GPIO_D1,
+ GPIO_D2,
+ GPIO_D3,
+ GPIO_D4,
+ GPIO_D5,
+ GPIO_D6,
+ GPIO_D7,
+ GPIO_D8,
+ GPIO_D9,
+ GPIO_D10,
+ GPIO_D11,
+ GPIO_D12,
+ GPIO_D13,
+ GPIO_D14,
+ GPIO_D15,
+ GPIO_D16,
+ GPIO_D17,
+ GPIO_D18,
+ GPIO_D19,
+ GPIO_D20,
+ GPIO_D21,
+ GPIO_D22,
+ GPIO_D23,
+ GPIO_D24,
+ GPIO_D25,
+ GPIO_D26,
+ GPIO_D27,
+ GPIO_D28,
+ GPIO_D29,
+ GPIO_D30,
+ GPIO_D31,
+ GPIO_E0,
+ GPIO_E1,
+ GPIO_E2,
+ GPIO_E3,
+ GPIO_E4,
+ GPIO_E5,
+ GPIO_E6,
+ GPIO_E7,
+ GPIO_E8,
+ GPIO_E9,
+ GPIO_E10,
+ GPIO_E11,
+ GPIO_E12,
+ GPIO_E13,
+ GPIO_E14,
+ GPIO_E15,
+ GPIO_E16,
+ GPIO_E17,
+ GPIO_E18,
+ GPIO_E19,
+ GPIO_E20,
+ GPIO_E21,
+ GPIO_E22,
+ GPIO_E23,
+ GPIO_E24,
+ GPIO_E25,
+ GPIO_E26,
+ GPIO_E27,
+ GPIO_E28,
+ GPIO_E29,
+ GPIO_E30,
+ GPIO_E31,
+ GPIO_F0,
+ GPIO_F1,
+ GPIO_F2,
+ GPIO_F3,
+ GPIO_F4,
+ GPIO_F5,
+ GPIO_F6,
+ GPIO_F7,
+ GPIO_F8,
+ GPIO_F9,
+ GPIO_F10,
+ GPIO_F11,
+ GPIO_F12,
+ GPIO_F13,
+ GPIO_F14,
+ GPIO_F15,
+ GPIO_F16,
+ GPIO_F17,
+ GPIO_F18,
+ GPIO_F19,
+ GPIO_F20,
+ GPIO_F21,
+ GPIO_F22,
+ GPIO_F23,
+ GPIO_F24,
+ GPIO_F25,
+ GPIO_F26,
+ GPIO_F27,
+ GPIO_F28,
+ GPIO_F29,
+ GPIO_F30,
+ GPIO_F31,
+ GPIO_COUNT,
+};
+
+enum PMU_GPIO_LIST {
+ PMU_GPIO1 = GPIO_COUNT,
+ PMU_GPIO2,
+ PMU_GPIO3,
+ PMU_GPIO4,
+};
+
+enum U6_GPIO_MODE {
+ GPIO_MODE_MUX0 = 0,
+ GPIO_MODE_MUX1,
+ GPIO_MODE_MUX2,
+ GPIO_MODE_MUX3
+};
+
+
+#define GPIO_DIR_INPUT 1
+#define GPIO_DIR_OUTPUT 0
+
+
+extern int u6_gpio_init(void); /* Call from board init only */
+extern int u6_gpio_request(int gpio);
+extern void u6_gpio_free(int gpio);
+extern int u6_gpio_set_mode(int gpio, int mode);
+extern int u6_gpio_set_mode_gpio(int gpio);
+extern int u6_gpio_set_direction(int gpio, int is_input);
+extern int u6_gpio_write_pin(int gpio, int gpio_value);
+extern int u6_gpio_read_pin(int gpio);
+extern int u6_gpio_set_irq_debounce(int irq, int cycles);
+extern int u6_gpio_set_irq_selection(int irq, int selection);
+extern int u6_gpio_clear_irq(unsigned int irq);
+
+
+/*
+ * Wrappers for "new style" GPIO calls, using the new infrastructure
+ * which lets us plug in FPGA, I2C, and other implementations.
+ */
+
+static inline int gpio_get_value(unsigned gpio)
+{
+ return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+ __gpio_set_value(gpio, value);
+}
+
+static inline int gpio_cansleep(unsigned gpio)
+{
+ return __gpio_cansleep(gpio);
+}
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+ return __gpio_to_irq(gpio);
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+ return EXTINT_TO_GPIO(irq);
+}
+
+/*
+* Hardware Register Definitions for EXTINT
+ */
+
+/* EXTINT ENABLE1 Register (32 bits) */
+#define EXTINT_ENABLE1_OFFSET 0x60
+#define EXTINT_ENABLE1_REG IO_ADDRESS(EXTINT_BASE + EXTINT_ENABLE1_OFFSET)
+
+/* EXTINT ENABLE2 Register (32 bits) */
+#define EXTINT_ENABLE2_OFFSET 0x64
+#define EXTINT_ENABLE2_REG IO_ADDRESS(EXTINT_BASE + EXTINT_ENABLE2_OFFSET)
+
+/* EXTINT ENABLE3 Register (32 bits) */
+#define EXTINT_ENABLE3_OFFSET 0x68
+#define EXTINT_ENABLE3_REG IO_ADDRESS(EXTINT_BASE + EXTINT_ENABLE3_OFFSET)
+
+/* EXTINT STATUS Register (32 bits) */
+#define EXTINT_STATUS_OFFSET 0x6C
+#define EXTINT_STATUS_REG IO_ADDRESS(EXTINT_BASE + EXTINT_STATUS_OFFSET)
+
+/* EXTINT SIGNAL Register (32 bits) */
+#define EXTINT_SIGNAL_OFFSET 0x70
+#define EXTINT_SIGNAL_REG IO_ADDRESS(EXTINT_BASE + EXTINT_SIGNAL_OFFSET)
+
+/* Bits definition for register EXTINT_CFG[23:0] */
+#define EXTINT_MODE_SHIFT 6
+#define EXTINT_MODE_FIELD (0xFFFFFFFF - (0x3UL<<EXTINT_MODE_SHIFT))
+#define EXTINT_MODE_BYPASS (0x0UL<<EXTINT_MODE_SHIFT)
+#define EXTINT_MODE_STRETCHING (0x1UL<<EXTINT_MODE_SHIFT)
+#define EXTINT_MODE_DEBOUNCE (0x2UL<<EXTINT_MODE_SHIFT)
+#define EXTINT_MODE_DUAL_EDGE (0x3UL<<EXTINT_MODE_SHIFT)
+#define EXTINT_DEBOUNCE_SHIFT 3
+#define EXTINT_DEBOUNCE_FIELD (0xFFFFFFFF - (0x7UL<<EXTINT_DEBOUNCE_SHIFT))
+#define EXTINT_DEBOUNCE_0 (0x0UL<<EXTINT_DEBOUNCE_SHIFT)
+#define EXTINT_DEBOUNCE_1 (0x1UL<<EXTINT_DEBOUNCE_SHIFT)
+#define EXTINT_DEBOUNCE_2 (0x2UL<<EXTINT_DEBOUNCE_SHIFT)
+#define EXTINT_DEBOUNCE_3 (0x3UL<<EXTINT_DEBOUNCE_SHIFT)
+#define EXTINT_DEBOUNCE_7 (0x7UL<<EXTINT_DEBOUNCE_SHIFT)
+#define EXTINT_POL_SHIFT 2
+#define EXTINT_POL_FIELD (0xFFFFFFFF - (0x1UL<<EXTINT_POL_SHIFT))
+#define EXTINT_POL_NEGATIVE (0x0UL<<EXTINT_POL_SHIFT)
+#define EXTINT_POL_POSITIVE (0x1UL<<EXTINT_POL_SHIFT)
+#define EXTINT_POL (0x1UL<<EXTINT_POL_SHIFT)
+#define EXTINT_SEL_SHIFT 1
+#define EXTINT_SEL_FIELD (0xFFFFFFFF - (0x1UL<<EXTINT_SEL_SHIFT))
+#define EXTINT_SEL_EXTINT (0x0UL<<EXTINT_SEL_SHIFT)
+#define EXTINT_SEL_ALTERNATE (0x1UL<<EXTINT_SEL_SHIFT)
+#define EXTINT_SEL (0x1UL<<EXTINT_SEL_SHIFT)
+
+/*****************************************************************************/
+/* Register description for ENABLE[3:1] */
+
+/* Bits definition for register EXTINT_ENABLE[3:1] */
+#define EXTINT_ENABLE_SHIFT 0
+#define EXTINT_ENABLE_FIELD (0xFFFFFFFF - (0xFFFFFFUL<<EXTINT_ENABLE_SHIFT))
+#define EXTINT_ENABLE_0 (0x0UL<<EXTINT_ENABLE_SHIFT)
+#define EXTINT_ENABLE_1 (0x1UL<<EXTINT_ENABLE_SHIFT)
+
+/*****************************************************************************/
+/* Register description for STATUS */
+
+/* Bits definition for register EXTINT_STATUS */
+#define EXTINT_STATUS_SHIFT 0
+#define EXTINT_STATUS_FIELD (0xFFFFFFFF - (0xFFFFFFUL<<EXTINT_STATUS_SHIFT))
+#define EXTINT_STATUS_0 (0x0UL<<EXTINT_STATUS_SHIFT)
+#define EXTINT_STATUS_1 (0x1UL<<EXTINT_STATUS_SHIFT)
+
+/*****************************************************************************
+* Hardware Register Definitions for GPIOx
+*****************************************************************************/
+/* Offsets */
+#define GPIO_PINS_OFFSET 0x0
+#define GPIO_OR_OFFSET 0x4
+#define GPIO_DR_OFFSET 0x8
+
+/* GPIOx PINS Registers (32 bits) */
+#define GPIOA_PINS_REG IO_ADDRESS(GPIOA_BASE + GPIO_PINS_OFFSET)
+#define GPIOB_PINS_REG IO_ADDRESS(GPIOB_BASE + GPIO_PINS_OFFSET)
+#define GPIOC_PINS_REG IO_ADDRESS(GPIOC_BASE + GPIO_PINS_OFFSET)
+#define GPIOD_PINS_REG IO_ADDRESS(GPIOD_BASE + GPIO_PINS_OFFSET)
+#define GPIOE_PINS_REG IO_ADDRESS(GPIOE_BASE + GPIO_PINS_OFFSET)
+#define GPIOF_PINS_REG IO_ADDRESS(GPIOF_BASE + GPIO_PINS_OFFSET)
+
+/* GPIOx OR Registers (32 bits) */
+#define GPIOA_OR_REG IO_ADDRESS(GPIOC_BASE + GPIO_OR_OFFSET)
+
+#endif
--
1.7.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 4/6] U6715 platform serial driver It's a generic driver for all U6 platform (V2)
2010-05-27 8:27 U6/U6715 ARM architecture files, 2nd try Philippe Langlais
` (2 preceding siblings ...)
2010-05-27 8:27 ` [PATCH 3/6] U6715 gpio platform driver This driver is U6 platform generic (V2) Philippe Langlais
@ 2010-05-27 8:27 ` Philippe Langlais
2010-06-24 14:17 ` Russell King - ARM Linux
2010-05-27 8:27 ` [PATCH 5/6] U6715 8250 serial like driver Philippe Langlais
2010-05-27 8:27 ` [PATCH 6/6] U6715 Default configuration for ST-Ericsson reference design boards Philippe Langlais
5 siblings, 1 reply; 17+ messages in thread
From: Philippe Langlais @ 2010-05-27 8:27 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Philippe Langlais <philippe.langlais@stericsson.com>
---
arch/arm/plat-u6xxx/Makefile | 2 +-
arch/arm/plat-u6xxx/include/mach/serial.h | 23 ++++++
arch/arm/plat-u6xxx/serial.c | 115 +++++++++++++++++++++++++++++
3 files changed, 139 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/plat-u6xxx/include/mach/serial.h
create mode 100644 arch/arm/plat-u6xxx/serial.c
diff --git a/arch/arm/plat-u6xxx/Makefile b/arch/arm/plat-u6xxx/Makefile
index 3d6898e..f12068c 100644
--- a/arch/arm/plat-u6xxx/Makefile
+++ b/arch/arm/plat-u6xxx/Makefile
@@ -3,6 +3,6 @@
#
# Common support
-obj-y := io.o irq.o clock.o gpio.o
+obj-y := io.o irq.o clock.o gpio.o serial.o
obj-$(CONFIG_U6_MTU_TIMER) += timer.o
diff --git a/arch/arm/plat-u6xxx/include/mach/serial.h b/arch/arm/plat-u6xxx/include/mach/serial.h
new file mode 100644
index 0000000..a136e7f
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/serial.h
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/serial.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Ludovic Barre <ludovic.barre@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+
+#ifndef __SERIAL_H
+#define __SERIAL_H
+
+#include <linux/clk.h>
+
+struct u6_uart {
+ struct clk *uartClk;
+ struct clk *pClk_13M;
+ struct clk *pClk_26M;
+ struct clk *pClk_pclk;
+ char uart_name[7];
+};
+
+#endif /* __SERIAL_H */
diff --git a/arch/arm/plat-u6xxx/serial.c b/arch/arm/plat-u6xxx/serial.c
new file mode 100644
index 0000000..a0e91dd
--- /dev/null
+++ b/arch/arm/plat-u6xxx/serial.c
@@ -0,0 +1,115 @@
+/*
+ * linux/arch/arm/plat-u6xxx/serial.c
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Ludovic Barre <ludovic.barre@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ * U6 cpu type detection
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+#include <mach/hardware.h>
+#include <mach/serial.h>
+
+#define BASE_BAUD (7372800)
+
+/*
+ * Internal UARTs need to be initialized for the 8250 autoconfig to work
+ * properly. Note that the TX watermark initialization may not be needed
+ * once the 8250.c watermark handling code is merged.
+ */
+static struct plat_serial8250_port serial_platform_data[] = {
+ {
+ .membase = (void __iomem *)IO_ADDRESS(UART1_BASE),
+ .mapbase = UART1_BASE,
+ .irq = IRQ_UART1,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = BASE_BAUD,
+ },
+ {
+ .membase = (void __iomem *)IO_ADDRESS(UART2_BASE),
+ .mapbase = UART2_BASE,
+ .irq = IRQ_UART2,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = BASE_BAUD,
+ },
+ /* void declaration needed by serial core */
+ {
+ .flags = 0
+ },
+};
+
+static struct platform_device serial_device = {
+ .name = "serial8250",
+ .id = 0,
+ .dev = {.platform_data = serial_platform_data,},
+};
+
+static int __init u6_serial_init(void)
+{
+ int i;
+ struct clk *pClk_13M;
+ struct clk *pClk_26M;
+ struct clk *pClk_pclk;
+ struct u6_uart *uart_u6;
+
+ pClk_13M = clk_get(NULL, "clk13m_ck");
+ pClk_26M = clk_get(NULL, "clk26m_ck");
+ pClk_pclk = clk_get(NULL, "pclk2_ck");
+
+ if (IS_ERR(pClk_13M) || IS_ERR(pClk_26M) || IS_ERR(pClk_pclk)) {
+ printk(KERN_WARNING "%s: parents clk failed\n", __func__);
+ goto out;
+ }
+
+ /* supress void element from loop */
+ for (i = 0; i < (ARRAY_SIZE(serial_platform_data) - 1); i++) {
+ struct clk *clk_tmp = NULL;
+
+ /* Allocation of u6 struct on uart X */
+ uart_u6 = kzalloc(sizeof(*uart_u6), GFP_KERNEL);
+ if (!uart_u6)
+ continue;
+
+ if (serial_platform_data[i].irq == IRQ_UART1) {
+ clk_tmp = clk_get(NULL, "UART1");
+ strcpy(uart_u6->uart_name, "UART1");
+ } else if (serial_platform_data[i].irq == IRQ_UART2) {
+ clk_tmp = clk_get(NULL, "UART2");
+ strcpy(uart_u6->uart_name, "UART2");
+ }
+
+ /* initialize pclk2 rate management withdrawn FIXME */
+
+ if (!IS_ERR(clk_tmp) && clk_tmp != NULL) {
+ uart_u6->uartClk = clk_tmp;
+ uart_u6->pClk_13M = pClk_13M;
+ uart_u6->pClk_26M = pClk_26M;
+ uart_u6->pClk_pclk = pClk_pclk;
+ serial_platform_data[i].private_data = uart_u6;
+ } else {
+ printk(KERN_WARNING
+ "%s - get uart clock failed error:%ld\n",
+ __func__, PTR_ERR(clk_tmp));
+ kfree(uart_u6);
+ continue;
+ }
+ }
+
+out:
+ /* free clks */
+ clk_put(pClk_13M);
+ clk_put(pClk_26M);
+ clk_put(pClk_pclk);
+
+ return platform_device_register(&serial_device);
+}
+arch_initcall(u6_serial_init);
--
1.7.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 5/6] U6715 8250 serial like driver
2010-05-27 8:27 U6/U6715 ARM architecture files, 2nd try Philippe Langlais
` (3 preceding siblings ...)
2010-05-27 8:27 ` [PATCH 4/6] U6715 platform serial driver It's a generic driver for all U6 platform (V2) Philippe Langlais
@ 2010-05-27 8:27 ` Philippe Langlais
2010-06-24 14:31 ` Russell King - ARM Linux
2010-05-27 8:27 ` [PATCH 6/6] U6715 Default configuration for ST-Ericsson reference design boards Philippe Langlais
5 siblings, 1 reply; 17+ messages in thread
From: Philippe Langlais @ 2010-05-27 8:27 UTC (permalink / raw)
To: linux-arm-kernel
Some modifications in 16550A/8250 serial driver
and clock management specificity
Signed-off-by: Philippe Langlais <philippe.langlais@stericsson.com>
---
drivers/serial/8250.c | 26 ++++++-
drivers/serial/8250_u6.c | 177 +++++++++++++++++++++++++++++++++++++++++++
drivers/serial/Kconfig | 19 +++++
drivers/serial/Makefile | 1 +
include/linux/serial_8250.h | 8 ++
5 files changed, 230 insertions(+), 1 deletions(-)
create mode 100644 drivers/serial/8250_u6.c
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 891e1dd..7be3aac 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -199,10 +199,16 @@ static const struct serial8250_config uart_config[] = {
},
[PORT_16550A] = {
.name = "16550A",
+#if defined(CONFIG_SERIAL_8250_U6)
+ .fifo_size = 64,
+ .tx_loadsz = 64,
+ .flags = UART_CAP_FIFO | UART_CAP_AFE,
+#else
.fifo_size = 16,
.tx_loadsz = 16,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO,
+#endif
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
},
[PORT_CIRRUS] = {
.name = "Cirrus",
@@ -2268,6 +2274,13 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
/*
* Ask the core to calculate the divisor for us.
*/
+#ifdef CONFIG_SERIAL_8250_CUSTOM_CLOCK
+ baud = uart_get_baud_rate(port, termios, old, 0,
+ CONFIG_SERIAL_8250_CUSTOM_MAX_BAUDRATE);
+ /* Calculate the new uart clock frequency if it is tunable */
+ port->uartclk = serial8250_get_custom_clock(port, baud);
+#endif
+
baud = uart_get_baud_rate(port, termios, old,
port->uartclk / 16 / 0xffff,
port->uartclk / 16);
@@ -2298,6 +2311,13 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
up->mcr &= ~UART_MCR_AFE;
if (termios->c_cflag & CRTSCTS)
up->mcr |= UART_MCR_AFE;
+#if defined(CONFIG_SERIAL_8250_U6)
+ /**
+ * When AFE is active, let the HW handle the stop/restart TX
+ * upon CTS change. It reacts much quicker than the SW driver.
+ */
+ port->flags &= ~ASYNC_CTS_FLOW;
+#endif
}
/*
@@ -2383,6 +2403,10 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
}
+#ifdef CONFIG_SERIAL_8250_CUSTOM_CLOCK
+ /* set the new uart clock frequency if it is tunable */
+ serial8250_set_custom_clock(port);
+#endif
serial_dl_write(up, quot);
/*
diff --git a/drivers/serial/8250_u6.c b/drivers/serial/8250_u6.c
new file mode 100644
index 0000000..e359ee6
--- /dev/null
+++ b/drivers/serial/8250_u6.c
@@ -0,0 +1,177 @@
+/*
+ * linux/drivers/serial/8250_pnx.c
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Ludovic Barre <ludovic.barre@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/serial_core.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <mach/serial.h>
+#include <mach/hardware.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <mach/clock.h>
+
+/* Register description for FDIV_CTRL */
+/* UART FDIV_CTRL Register (8 bits) */
+#define UARTX_FDIV_CTRL_OFFSET 0xC00
+/* UART FDIV_M Register (16 bits) */
+#define UARTX_FDIV_M_OFFSET 0xC04
+/* UART FDIV_N Register (16 bits) */
+#define UARTX_FDIV_N_OFFSET 0xC08
+
+/* Bits definition for register UARTX_FDIV_CTRL */
+#define UARTX_FDIV_ENABLE_SHIFT 7
+#define UARTX_FDIV_ENABLE_FIELD (0xFFFFFFFF - (0x1UL<<UARTX_FDIV_ENABLE_SHIFT))
+#define UARTX_FDIV_ENABLE_OFF (0x0UL<<UARTX_FDIV_ENABLE_SHIFT)
+#define UARTX_FDIV_ENABLE_ON (0x1UL<<UARTX_FDIV_ENABLE_SHIFT)
+#define UARTX_FDIV_ENABLE (0x1UL<<UARTX_FDIV_ENABLE_SHIFT)
+#define UARTX_CLKSEL_SHIFT 0
+#define UARTX_CLKSEL_FIELD (0xFFFFFFFF - (0x3UL<<UARTX_CLKSEL_SHIFT))
+#define UARTX_CLKSEL_PCLK (0x0UL<<UARTX_CLKSEL_SHIFT)
+#define UARTX_CLKSEL_13M (0x1UL<<UARTX_CLKSEL_SHIFT)
+#define UARTX_CLKSEL_26M (0x2UL<<UARTX_CLKSEL_SHIFT)
+#define UARTX_CLKSEL_3 (0x3UL<<UARTX_CLKSEL_SHIFT)
+
+/*
+ * console and pctools has needed to start before serial_init
+ * (with cgu interface)
+ */
+static int uart_enable_clock(struct uart_port *port)
+{
+ u32 v;
+ v = readl(CGU_GATESC1_REG);
+
+ if (port->irq == IRQ_UART1)
+ v |= CGU_UART1EN_1;
+ else if (port->irq == IRQ_UART2)
+ v |= CGU_UART2EN_1;
+
+ writel(v, CGU_GATESC1_REG);
+
+ return 0;
+}
+
+static int uart_disable_clock(struct uart_port *port)
+{
+ u32 v;
+ v = readl(CGU_GATESC1_REG);
+
+ if (port->irq == IRQ_UART1)
+ v &= ~CGU_UART1EN_0;
+ else if (port->irq == IRQ_UART2)
+ v &= ~CGU_UART2EN_0;
+
+ writel(v, CGU_GATESC1_REG);
+
+ return 0;
+}
+
+unsigned int serial8250_enable_clock(struct uart_port *port)
+{
+ struct u6_uart *uart_u6 = port->private_data;
+
+ if (!uart_u6)
+ return uart_enable_clock(port);
+
+ if (IS_ERR(uart_u6->uartClk)) {
+ printk(KERN_WARNING "%s - uart clock failed error:%ld\n",
+ __func__, PTR_ERR(uart_u6->uartClk));
+ return PTR_ERR(uart_u6->uartClk);
+ }
+
+ if (clk_get_usecount(uart_u6->uartClk) == 0)
+ clk_enable(uart_u6->uartClk);
+ return 0;
+}
+
+unsigned int serial8250_disable_clock(struct uart_port *port)
+{
+ struct u6_uart *uart_u6 = port->private_data;
+
+ if (!uart_u6)
+ return uart_disable_clock(port);
+
+ if (IS_ERR(uart_u6->uartClk)) {
+ printk(KERN_WARNING "%s - uart clk error :%ld\n", __func__,
+ PTR_ERR(uart_u6->uartClk));
+ return PTR_ERR(uart_u6->uartClk);
+ }
+ if (clk_get_usecount(uart_u6->uartClk) >= 1)
+ clk_disable(uart_u6->uartClk);
+
+ return 0;
+}
+
+unsigned int serial8250_get_custom_clock(struct uart_port *port,
+ unsigned int baud)
+{
+ switch (baud) {
+ case 3250000:
+ return 52000000;
+ case 2000000:
+ return 32000000;
+ case 1843200:
+ return 29491200;
+ case 921600:
+ return 14745600;
+ default:
+ return 7372800;
+ }
+}
+
+void serial8250_set_custom_clock(struct uart_port *port)
+{
+ u32 fdiv_m = 0x5F37;
+ u32 fdiv_n = 0x3600;
+ u32 fdiv_ctrl = UARTX_FDIV_ENABLE_ON;
+ struct clk *parentClk = NULL;
+ struct u6_uart *uart_u6 = port->private_data;
+
+ switch (port->uartclk) {
+ case 7372800: /* clk=13MHz */
+ fdiv_ctrl |= UARTX_CLKSEL_13M;
+ break;
+ case 14745600: /* clk=26MHz */
+ fdiv_ctrl |= UARTX_CLKSEL_26M;
+ break;
+ case 29491200: /* clk=pclk */
+ fdiv_ctrl |= UARTX_CLKSEL_PCLK;
+ break;
+ case 32000000: /* clk=pclk */
+ fdiv_n = 0x3A98;
+ fdiv_ctrl |= UARTX_CLKSEL_PCLK;
+ break;
+ case 52000000: /* clk=pclk */
+ fdiv_n = 0x5F37;
+ fdiv_ctrl |= UARTX_CLKSEL_PCLK;
+ break;
+ }
+
+ if (uart_u6 != NULL && !IS_ERR(uart_u6->uartClk)) {
+ /* if cgu interface is ready and u6_serial_init */
+ if (fdiv_ctrl & UARTX_CLKSEL_26M)
+ parentClk = uart_u6->pClk_26M;
+ else if (fdiv_ctrl & UARTX_CLKSEL_PCLK)
+ parentClk = uart_u6->pClk_pclk;
+ else
+ parentClk = uart_u6->pClk_13M;
+
+ if (!IS_ERR(parentClk)) {
+ serial8250_disable_clock(port);
+
+ if (clk_set_parent(uart_u6->uartClk, parentClk) != 0)
+ printk(KERN_WARNING "%s: set parent failed\n",
+ __func__);
+
+ serial8250_enable_clock(port);
+ }
+ }
+
+ writel(fdiv_m, port->membase + UARTX_FDIV_M_OFFSET);
+ writel(fdiv_n, port->membase + UARTX_FDIV_N_OFFSET);
+ writel(fdiv_ctrl, port->membase + UARTX_FDIV_CTRL_OFFSET);
+}
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 8b23165..665b76b 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -163,6 +163,25 @@ config SERIAL_8250_MANY_PORTS
say N here to save some memory. You can also say Y if you have an
"intelligent" multiport card such as Cyclades, Digiboards, etc.
+config SERIAL_8250_U6XXX
+ bool
+ depends on SERIAL_8250_EXTENDED && PLAT_U6XXX
+ default y
+
+config SERIAL_8250_CUSTOM_CLOCK
+ bool "Support serial ports with tunable input clock frequency"
+ depends on SERIAL_8250_EXTENDED && SERIAL_8250_U6XXX
+ default y
+ help
+ Say Y here if your platform has specific registers to change UART clock frequency.
+
+config SERIAL_8250_CUSTOM_MAX_BAUDRATE
+ int "Maximal reachable baudrate"
+ depends on SERIAL_8250_CUSTOM_CLOCK
+ default "3250000"
+ help
+ The value of the maximal reachable baudrate when tuning UART clock frequency (default value: 3.25MBds).
+
#
# Multi-port serial cards
#
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 208a855..4d9fd81 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o
obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o
obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o
+obj-$(CONFIG_SERIAL_8250_U6XXX) += 8250_u6.o
obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index fb46aba..3e86ceb 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -72,4 +72,12 @@ extern int serial8250_find_port(struct uart_port *p);
extern int serial8250_find_port_for_earlycon(void);
extern int setup_early_serial8250_console(char *cmdline);
+#ifdef CONFIG_SERIAL_8250_CUSTOM_CLOCK
+unsigned int serial8250_enable_clock(struct uart_port *port);
+unsigned int serial8250_disable_clock(struct uart_port *port);
+unsigned int serial8250_get_custom_clock(struct uart_port *port,
+ unsigned int baud);
+void serial8250_set_custom_clock(struct uart_port *port);
+#endif
+
#endif
--
1.7.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 6/6] U6715 Default configuration for ST-Ericsson reference design boards
2010-05-27 8:27 U6/U6715 ARM architecture files, 2nd try Philippe Langlais
` (4 preceding siblings ...)
2010-05-27 8:27 ` [PATCH 5/6] U6715 8250 serial like driver Philippe Langlais
@ 2010-05-27 8:27 ` Philippe Langlais
5 siblings, 0 replies; 17+ messages in thread
From: Philippe Langlais @ 2010-05-27 8:27 UTC (permalink / raw)
To: linux-arm-kernel
It's a minimal configuration
Signed-off-by: Philippe Langlais <philippe.langlais@stericsson.com>
---
arch/arm/configs/u67xx_wavex_defconfig | 1096 ++++++++++++++++++++++++++++++++
1 files changed, 1096 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/configs/u67xx_wavex_defconfig
diff --git a/arch/arm/configs/u67xx_wavex_defconfig b/arch/arm/configs/u67xx_wavex_defconfig
new file mode 100644
index 0000000..d9f7834
--- /dev/null
+++ b/arch/arm/configs/u67xx_wavex_defconfig
@@ -0,0 +1,1096 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.34
+# Thu May 27 09:37:28 2010
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_LZO is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+# CONFIG_PERF_COUNTERS is not set
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_VEXPRESS is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CNS3XXX is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_NUC93X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_SHMOBILE is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5P6440 is not set
+# CONFIG_ARCH_S5P6442 is not set
+# CONFIG_ARCH_S5PC100 is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+CONFIG_PLAT_U6XXX=y
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_PLAT_SPEAR is not set
+
+#
+# STE U6XXX Implementations
+#
+CONFIG_ARCH_U67XX=y
+CONFIG_U6_MTU_TIMER=y
+
+#
+# U67XX Board Type
+#
+CONFIG_MACH_U67XX_WAVEC_2GB=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_PABRT_LEGACY=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=999999
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_CMDLINE="console=ttyS0,115200n8 quiet initrd=0x26000000 rootfstype=ext2 root=/dev/ram0"
+# CONFIG_CMDLINE_FORCE is not set
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=2
+CONFIG_BLK_DEV_RAM_SIZE=32768
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=m
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_NETDEVICES is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_U6XXX=y
+CONFIG_SERIAL_8250_CUSTOM_CLOCK=y
+CONFIG_SERIAL_8250_CUSTOM_MAX_BAUDRATE=3250000
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_IT8761E is not set
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+
+#
+# AC97 GPIO expanders:
+#
+
+#
+# MODULbus GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_MFD_SUPPORT=y
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_FANOTIFY=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-15"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_XATTRS is not set
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-15"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+CONFIG_NLS_ISO8859_15=y
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_LOCKUP_DETECTOR=y
+# CONFIG_HARDLOCKUP_DETECTOR is not set
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+CONFIG_DEBUG_PREEMPT=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_PI_LIST=y
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_VM=y
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_LKDTM is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_RING_BUFFER_ALLOW_SWAP=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_BOOT_TRACER is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_RING_BUFFER_BENCHMARK is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_ARM_UNWIND is not set
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+# CONFIG_OC_ETM is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+# CONFIG_SHM_SIGNAL is not set
+# CONFIG_IOQ is not set
--
1.7.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 1/6] U6/U6715 ARM architecture files
2010-05-27 8:27 ` [PATCH 1/6] U6/U6715 ARM architecture files Philippe Langlais
@ 2010-06-24 14:08 ` Russell King - ARM Linux
2010-06-25 13:34 ` Philippe Langlais
0 siblings, 1 reply; 17+ messages in thread
From: Russell King - ARM Linux @ 2010-06-24 14:08 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, May 27, 2010 at 10:27:27AM +0200, Philippe Langlais wrote:
> diff --git a/arch/arm/mach-u67xx/devices.c b/arch/arm/mach-u67xx/devices.c
> new file mode 100644
> index 0000000..0ead380
> --- /dev/null
> +++ b/arch/arm/mach-u67xx/devices.c
> @@ -0,0 +1,95 @@
> +/*
> + * linux/arch/arm/mach-u67xx/devices.c
> + *
> + * Copyright (C) ST-Ericsson SA 2010
> + * Author: Philippe Langlais <philippe.langlais@stericsson.com> for ST-Ericsson.
> + * License terms: GNU General Public License (GPL), version 2
> + *
> + * Device specification for the U67XX
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/device.h>
> +#include <linux/ioport.h>
> +#include <linux/platform_device.h>
> +#include <linux/fs.h>
> +#include <mach/hardware.h>
> +#include <mach/scon.h>
> +#include <mach/gpio.h>
linux/gpio.h
> +struct gpio_bank u6_gpio_bank[6] = {
> + {(void __iomem *)GPIOA_PINS_REG, (void __iomem *)SCON_SYSMUX0_REG},
> + {(void __iomem *)GPIOB_PINS_REG, (void __iomem *)SCON_SYSMUX2_REG},
> + {(void __iomem *)GPIOC_PINS_REG, (void __iomem *)SCON_SYSMUX4_REG},
> + {(void __iomem *)GPIOD_PINS_REG, (void __iomem *)SCON_SYSMUX6_REG},
> + {(void __iomem *)GPIOE_PINS_REG, (void __iomem *)SCON_SYSMUX8_REG},
> + {(void __iomem *)GPIOF_PINS_REG, (void __iomem *)SCON_SYSMUX10_REG},
Would be nice to get rid of these casts - instead moving them to the
point of definition instead - or maybe doing as other platforms do and
defining an IOMEM() macro which does the cast and using that in the
definitions.
iow, something like:
#define IOMEM(x) ((void __iomem *)(x))
#define GPIOA_PINS_REG IOMEM(whatever)
and if you need GPIOA_PINS_REG to be usable in assembly, arrange for
the IOMEM() macro to handle that for you.
> diff --git a/arch/arm/plat-u6xxx/include/mach/entry-macro.S b/arch/arm/plat-u6xxx/include/mach/entry-macro.S
> new file mode 100644
> index 0000000..59bb2d2
> --- /dev/null
> +++ b/arch/arm/plat-u6xxx/include/mach/entry-macro.S
> @@ -0,0 +1,32 @@
> +/*
> + * linux/arch/arm/plat-u6xxx/include/mach/entry-macro.S
> + *
> + * Low-level IRQ helper macros for U6-based platforms
> + * Copyright (C) ST-Ericsson SA 2010
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +#include <mach/hardware.h>
> +#include <mach/irqs.h>
> +
> + .macro arch_ret_to_user, tmp1, tmp2
> + .endm
> +
> + .macro disable_fiq
> + .endm
> +
> + .macro get_irqnr_preamble, base, tmp
> + .endm
This macro is there to allow you to be a little more efficient - rather
than reloading the base address of the interrupt controller each time
around the interrupt handling loop, you can put it in the above macro
to take it outside the loop.
> +#define hw_raw_local_irq_save raw_local_irq_save
> +#define hw_raw_local_irq_restore raw_local_irq_restore
What's the purpose of these additional aliases?
> +/* INTC PRIOMASK_IRQ Register (32 bits) */
> +#define INTC_PRIOMASK_IRQ_OFFSET 0x0
> +#define INTC_PRIOMASK_IRQ_REG IO_ADDRESS(INTC_BASE + INTC_PRIOMASK_IRQ_OFFSET)
> +
> +/* INTC PRIOMASK_FIQ Register (32 bits) */
> +#define INTC_PRIOMASK_FIQ_OFFSET 0x4
> +#define INTC_PRIOMASK_FIQ_REG IO_ADDRESS(INTC_BASE + INTC_PRIOMASK_FIQ_OFFSET)
> +
> +/* INTC VECTOR_IRQ Register (32 bits) */
> +#define INTC_VECTOR_IRQ_OFFSET 0x100
> +#define INTC_VECTOR_IRQ_REG IO_ADDRESS(INTC_BASE + INTC_VECTOR_IRQ_OFFSET)
> +
> +/* INTC VECTOR_FIQ Register (32 bits) */
> +#define INTC_VECTOR_FIQ_OFFSET 0x104
> +#define INTC_VECTOR_FIQ_REG IO_ADDRESS(INTC_BASE + INTC_VECTOR_FIQ_OFFSET)
> +
> +/* INTC PENDING_* Registers (32 bits) */
> +#define INTC_PENDING_1_OFFSET 0x200
> +#define INTC_PENDING_2_OFFSET 0x204
> +#define INTC_PENDING_3_OFFSET 0x208
> +#define INTC_FEATURES_OFFSET 0x300
> +
> +/* INTC REQUEST 64 Registers (32 bits) */
> +#define INTC_REQUEST1_OFFSET 0x404
> +#define INTC_REQUEST64_OFFSET 0x500
> +
> +/* INTC MOD_ID Register (32 bits) */
> +#define INTC_MOD_ID_OFFSET 0xFFC
> +
> +/* interrupt x [1..64] request configuration */
> +#define INTC_REQUESTx(x) IO_ADDRESS(INTC_BASE+INTC_REQUEST1_OFFSET+(x-1)*4)
> +
> +/* EXTINTx [0..23] configuration register */
> +#define EXTINT_CFGx(x) IO_ADDRESS(EXTINT_BASE+(x)*4)
Does it really make sense to export all these definitions to the entire
kernel?
> diff --git a/arch/arm/plat-u6xxx/include/mach/memory.h b/arch/arm/plat-u6xxx/include/mach/memory.h
> new file mode 100644
> index 0000000..0fa6cea
> --- /dev/null
> +++ b/arch/arm/plat-u6xxx/include/mach/memory.h
> @@ -0,0 +1,24 @@
> +/*
> + * linux/arch/arm/plat-u6xxx/include/mach/memory.h
> + *
> + * Copyright (C) ST-Ericsson SA 2010
> + * Author: Philippe Langlais <philippe.langlais@stericsson.com> for ST-Ericsson.
> + * License terms: GNU General Public License (GPL), version 2
> + */
> +
> +#ifndef __ASM_ARCH_MEMORY_H
> +#define __ASM_ARCH_MEMORY_H
> +
> +/*
> + * Physical DRAM offset.
> + */
> +#define PHYS_OFFSET UL(0x20000000)
> +#define BOOT_PARAMS_OFFSET (PHYS_OFFSET + 0x100)
Does it make sense to export this to the world?
> +
> +/**
> + * CONSISTENT_DMA_SIZE: Size of DMA-consistent memory region.
> + * Must be multiple of 2M,between 2MB and 14MB inclusive
> + */
> +#define CONSISTENT_DMA_SIZE (SZ_2M)
It defaults to 2MB, so this definition is redundant.
> diff --git a/arch/arm/plat-u6xxx/include/mach/platform.h b/arch/arm/plat-u6xxx/include/mach/platform.h
> new file mode 100644
> index 0000000..5265ccd
> --- /dev/null
> +++ b/arch/arm/plat-u6xxx/include/mach/platform.h
> @@ -0,0 +1,15 @@
> +/*
> + * linux/arch/arm/plat-u6xxx/include/mach/platform.h
> + *
> + * Copyright (C) ST-Ericsson SA 2010
> + * Author: Philippe Langlais <philippe.langlais@stericsson.com> for ST-Ericsson.
> + * License terms: GNU General Public License (GPL), version 2
> + */
> +
> +#ifndef __ASM_ARCH_PLATFORM_H
> +#define __ASM_ARCH_PLATFORM_H 1
> +
> +#include <linux/types.h>
> +#include <mach/hardware.h>
> +
> +#endif /* __ASM_ARCH_PLATFORM_H */
If there's nothing required in this file, it doesn't need to exist.
> diff --git a/arch/arm/plat-u6xxx/include/mach/timer.h b/arch/arm/plat-u6xxx/include/mach/timer.h
> new file mode 100644
> index 0000000..049e72d
> --- /dev/null
> +++ b/arch/arm/plat-u6xxx/include/mach/timer.h
> @@ -0,0 +1,24 @@
> +/*
> + * linux/arch/arm/plat-u6xxx/include/mach/timer.h
> + *
> + * Copyright (C) ST-Ericsson SA 2010
> + * Author: Philippe Langlais <philippe.langlais@stericsson.com> for ST-Ericsson.
> + * License terms: GNU General Public License (GPL), version 2
> + */
> +
> +#ifndef __PLAT_TIMER_H
> +#define __PLAT_TIMER_H
> +#ifdef U6_TIMER_C
> +#define PUBLIC
> +#else
> +#define PUBLIC extern
> +#endif
Err, no - there's really no need for such hacks in C, and I can't find
anywhere which defines U6_TIMER_C.
> +
> +struct sys_timer;
> +
> +PUBLIC struct sys_timer u6_timer;
> +
> +PUBLIC void __init u6_timer_init(void);
> +
> +#undef PUBLIC
> +#endif
> diff --git a/arch/arm/plat-u6xxx/include/mach/vmalloc.h b/arch/arm/plat-u6xxx/include/mach/vmalloc.h
> new file mode 100644
> index 0000000..583033f
> --- /dev/null
> +++ b/arch/arm/plat-u6xxx/include/mach/vmalloc.h
> @@ -0,0 +1,10 @@
> +/*
> + * linux/arch/arm/plat-u6/include/mach/vmalloc.h
> + * Copyright (C) ST-Ericsson SA 2010
> + * Author: Philippe Langlais <philippe.langlais@stericsson.com> for ST-Ericsson.
> + * 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.
> + */
> +#define VMALLOC_END (PAGE_OFFSET + 0x28000000)
Is the upper limit of vmalloc space is dependent on PAGE_OFFSET? If
not, then it shouldn't be using a calculation based upon that value.
> diff --git a/arch/arm/plat-u6xxx/timer.c b/arch/arm/plat-u6xxx/timer.c
> new file mode 100644
> index 0000000..62f13f5
> --- /dev/null
> +++ b/arch/arm/plat-u6xxx/timer.c
> @@ -0,0 +1,679 @@
> +/*
> + * linux/arch/arm/plat-u6xxx/timer.c
> + *
> + * Copyright (C) ST-Ericsson SA 2010
> + * Author: Vincent Guittot <vincent.guittot@stericsson.com> for ST-Ericsson.
> + * License terms: GNU General Public License (GPL), version 2
> + */
> +
> +#include <linux/types.h>
> +#include <linux/kernel.h>
> +#include <linux/err.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +
> +#include <asm/mach/time.h>
> +
> +#include <mach/hardware.h>
> +
> +#include <asm/mach/irq.h>
> +#include <linux/interrupt.h>
> +#include <mach/irqs.h>
> +
> +#include <linux/clk.h>
> +
> +#include <linux/clocksource.h>
> +#include <linux/clockchips.h>
linux/ includes before asm/ includes. asm/ includes before mach/ includes
please.
> +#undef U6_TIMER_DEBUG
> +#if defined(U6_TIMER_DEBUG)
> +#define debug(fmt, args...) \
> + printk(PKMOD fmt, ## args)
> +#else
> +#define debug(fmt, args...)
> +#endif
You could use pr_debug() instead, and define 'DEBUG' at the top of the
file you want debug messages from.
> +static irqreturn_t
> +u6_mmtu_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
> +{
> + uint8_t status, enable;
> + struct mmtu_ctxt *mmtu;
> +
> + mmtu = u6_mmtu_get_context(0);
> +
> + status = readl((mmtu->base + MMTU_INT_OFFSET + MMTU_INT_STATUS_IDX));
> + enable = readl((mmtu->base + MMTU_INT_OFFSET + MMTU_INT_ENABLE_IDX));
> +
> + debug("mmtu_timer_interrupt %d\n", status);
> +
> + if (status & enable & MMTU_IRQ_MASK) {
> + struct clock_event_device *evt = &clockevent_mmtu;
> +
> + writel(MMTU_IRQ_MASK, (mmtu->base + MMTU_INT_OFFSET
> + + MMTU_INT_CLR_STAT_IDX));
> +
> + if (mmtu->autoreload)
> + u6_mmtu_timer_start(mmtu->compvalue, 0);
If your hardware doesn't do reloadable timers, you're not supposed to
emulate it. The generic time infrastructure contains all the code
that's required to handle periodic timer interrupts with timers only
capable of one-shot mode.
> + else
> + writel(MMTU_IRQ_MASK,
> + (mmtu->base + MMTU_INT_OFFSET +
> + MMTU_INT_CLR_ENA_IDX));
> +
> + if (evt->event_handler)
> + evt->event_handler(evt);
> + }
> + return IRQ_HANDLED;
> +}
> +
> +static struct irqaction u6_mmtu_timer_irq = {
> + .name = "U6 MMTU timer Tick",
> + .flags = IRQF_DISABLED,
> + .handler = (irq_handler_t) u6_mmtu_timer_interrupt,
> +};
> +
> +static inline void u6_mmtu_clk_enable(int id)
> +{
> + struct mmtu_ctxt *mmtu = u6_mmtu_get_context(id);
> +
> + /* Clock Multimedia Timer Unit.
> + */
> + if ((mmtu->clk != NULL) && (mmtu->mode == 0)) {
> + debug("mmtu_clk_enable\n");
> + mmtu->mode = 1;
> + clk_enable(mmtu->clk);
> + }
> +}
> +
> +static inline void u6_mmtu_clk_disable(int id)
> +{
> + struct mmtu_ctxt *mmtu = u6_mmtu_get_context(id);
> +
> + /* Clock Multimedia Timer Unit.
> + */
> + if ((mmtu->clk != NULL) && (mmtu->mode == 1)) {
> + debug("mmtu_clk_disable\n");
> + clk_disable(mmtu->clk);
> + mmtu->mode = 0;
> + }
> +}
> +
> +static inline int u6_mmtu_timer_start(unsigned long cycles, int id)
> +{
> + struct mmtu_ctxt *mmtu = u6_mmtu_get_context(id);
> +
> + debug("mmtu_timer_start %d\n", cycles);
> + u6_mmtu_clk_enable(id);
> +
> + /* MMTU limitation : can't set a value smaller or equal to tcval + 1 */
> + cycles = cycles < 2 ? 2 : cycles;
> +
> + mmtu->compvalue = cycles;
> +
> + mmtu->endvalue = mmtu->compvalue
> + + readl((mmtu->base + MMTU_TCVAL_IDX));
> +
> + writel(MMTU_IRQ_MASK,
> + (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_STAT_IDX));
> +
> + writel(mmtu->endvalue, (mmtu->base + MMTU_USED_MATCH_IDX));
> +
> + writel(MMTU_IRQ_MASK,
> + (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_SET_ENA_IDX));
> +
> + /* the value has already expired */
> + if ((mmtu->endvalue <= readl((mmtu->base + MMTU_TCVAL_IDX)))
> + && (mmtu->endvalue > mmtu->compvalue)
> + && !(readl((mmtu->base + MMTU_INT_OFFSET
> + + MMTU_INT_STATUS_IDX)) & MMTU_IRQ_MASK))
> + writel(MMTU_IRQ_MASK, (mmtu->base + MMTU_INT_OFFSET
> + + MMTU_INT_SET_STAT_IDX));
> +
> + return 0;
> +}
> +
> +static int u6_mmtu_timer_init(int id, unsigned long reload,
> + unsigned long prescale, int over_it)
> +{
> +
> + struct mmtu_ctxt *mmtu = u6_mmtu_get_context(id);
> +
> + debug("mmtu_timer_init %d\n", id);
> +
> + /* Enable clock */
> +/*
> + u6_mmtu_clk_enable(id);
> + clk mngt not available yet
> + directly enable it
> +*/
> + {
> + unsigned long flags;
> + unsigned long reg;
> + hw_raw_local_irq_save(flags);
> + reg = readl(CGU_GATESC2_REG);
> + reg |= 0x1 << 2;
> + writel(reg, CGU_GATESC2_REG);
> + hw_raw_local_irq_restore(flags);
> + }
> +
> + /* Reset timer */
> + /* reset control register */
> + writel(0x0000, (mmtu->base + MMTU_CON_IDX));
> + writel(0x0002, (mmtu->base + MMTU_CON_IDX));
> + /* reset control register */
> + writel(0x0000, (mmtu->base + MMTU_CON_IDX));
> +
> + /* clear whole enable irq register */
> + writel(0xFF, (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_ENA_IDX));
> + /* clear whole status register */
> + writel(0xFF, (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_STAT_IDX));
> +
> + /* reset pre-scaler reload register */
> + writel(0x00000000, (mmtu->base + MMTU_PRESCALER_IDX));
> +
> + /* reset match control register */
> + writel(0x0000, (mmtu->base + MMTU_MATCH_CON_IDX));
> + /* reset match 0 register */
> + writel(0x00000000, (mmtu->base + MMTU_MATCH0_IDX));
> + /* reset match 1 register */
> + writel(0x00000000, (mmtu->base + MMTU_MATCH1_IDX));
> +
> + /* Initialize timer */
> + writel(prescale - 1, (mmtu->base + MMTU_PRESCALER_IDX));
> + /* power of 2 system clock */
> + writel(reload, (mmtu->base + MMTU_MATCH0_IDX));
> +
> + /* enable counter register */
> + writel(0x0001, (mmtu->base + MMTU_CON_IDX));
> +
> + /* clear whole status register */
> + writel(0xFF, (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_STAT_IDX));
> +
> + if (id == 0)
> + setup_irq(IRQ_MMTU, &u6_mmtu_timer_irq);
> +
> + /* Disable clock */
> +#ifndef U6_MMTU_CLOCK_SOURCE
> + u6_mmtu_clk_disable(id);
> +#endif
> + return 0;
> +}
> +
> +/*** MMTU Clock event device ***/
> +
> +static int u6_mmtu_set_next_event(unsigned long cycles,
> + struct clock_event_device *evt)
> +{
> + debug("mmtu_set_next_event %d\n", cycles);
> + u6_mmtu_timer_start(cycles, 0);
> +
> + return 0;
> +}
> +
> +static void u6_mmtu_set_mode(enum clock_event_mode mode,
> + struct clock_event_device *evt)
> +{
> + struct mmtu_ctxt *mmtu = u6_mmtu_get_context(0);
> + unsigned long reg;
> +
> + debug("mmtu_set_mode %d\n", mode);
> +
> + switch (mode) {
> + case CLOCK_EVT_MODE_UNUSED:
> + writel(MMTU_IRQ_MASK,
> + (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_ENA_IDX));
> + writel(MMTU_IRQ_MASK,
> + (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_STAT_IDX));
> +
> + reg = readl((mmtu->base + MMTU_TCVAL_IDX));
> + writel(reg - 1, (mmtu->base + MMTU_USED_MATCH_IDX));
> +
> +#ifndef U6_MMTU_CLOCK_SOURCE
> + u6_mmtu_clk_disable(0);
> +
> + if (mmtu->clk != NULL)
> + clk_put(mmtu->clk);
> +#endif
> + mmtu->autoreload = 0;
> + break;
> + case CLOCK_EVT_MODE_SHUTDOWN:
> + mmtu->autoreload = 0;
> +
> + if (mmtu->clk == NULL) {
> + mmtu->clk = clk_get(0, "MMTU");
> + if (IS_ERR(mmtu->clk))
> + mmtu->clk = NULL;
> + }
> +
> + writel(MMTU_IRQ_MASK,
> + (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_STAT_IDX));
> + writel(MMTU_IRQ_MASK,
> + (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_SET_ENA_IDX));
> + case CLOCK_EVT_MODE_ONESHOT:
> + case CLOCK_EVT_MODE_RESUME:
> + mmtu->autoreload = 0;
> + break;
> + case CLOCK_EVT_MODE_PERIODIC:
> + writel(MMTU_IRQ_MASK,
> + (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_SET_ENA_IDX));
> + mmtu->autoreload = 1;
> + break;
> + }
> +}
> +
> +static void u6_clockevent_init_mmtu(void)
> +{
> + printk(PKMOD "clockevent_init_mmtu\n");
> +
> + /* prescale 13Mhz -> 1Mhz */
> +#ifndef U6_MMTU_CLOCK_SOURCE
> + u6_mmtu_timer_init(0, 0, (MMTU_SYS_FRQ / MMTU_ROOT_FRQ), 0);
> +#endif
> +
> +/* issue it is shorter than reality and generates spurious irq */
> +/* clockevent_mmtu.mult = div_sc(MMTU_ROOT_FRQ, NSEC_PER_SEC,
> + * clockevent_mmtu.shift) + 1;*/
> + clockevent_mmtu.mult =
> + div_sc(MMTU_ROOT_FRQ, NSEC_PER_SEC, clockevent_mmtu.shift);
> +
> +/* clockevent_mmtu.max_delta_ns = div_sc(RELOAD_COUNTER_MMTU,
> + * clockevent_mmtu.mult, clockevent_mmtu.shift);*/
> +/* In fact it is wider than the 32bits variable !!! */
> + clockevent_mmtu.max_delta_ns = 0xFFFFFFFF;
> +
> +/* MMTU HW limitation: match register can't be set w/ tcval+1 */
> +/* clockevent_mmtu.min_delta_ns = div_sc(1, clockevent_mmtu.mult,
> + * clockevent_mmtu.shift)+1;*/
> + clockevent_mmtu.min_delta_ns =
> + div_sc(2, clockevent_mmtu.mult, clockevent_mmtu.shift) + 1;
> + /* avoid to much timer interrupt with 10us min between 2 irq */
> + if (clockevent_mmtu.min_delta_ns < 10000)
> + clockevent_mmtu.min_delta_ns = 10000;
> + else if (clockevent_mmtu.max_delta_ns < 10000)
> + clockevent_mmtu.min_delta_ns = clockevent_mmtu.max_delta_ns>>1;
> +
> + clockevent_mmtu.cpumask = get_cpu_mask(0);
> + clockevents_register_device(&clockevent_mmtu);
> +
> + u6_mmtu_set_next_event(MMTU_ROOT_FRQ / HZ, &clockevent_mmtu);
> +}
> +
> +/*** MMTU Clock source device ***/
> +#ifdef U6_MMTU_CLOCK_SOURCE
> +
> +static cycle_t u6_mmtu_read(struct clocksource *source)
> +{
> + struct mmtu_ctxt *mmtu = u6_mmtu_get_context(0);
> +
> + return readl((mmtu->base + MMTU_TCVAL_IDX)) & source->mask;
> +}
Clocksource read functions don't require the value masking.
> +
> +static void u6_clocksource_init_mmtu(void)
> +{
> + printk(PKMOD "clocksource_init_mmtu\n");
> +
> + if (MMTU_ROOT_FRQ >= 1000000)
> + clocksource_mmtu.mult =
> + clocksource_khz2mult((MMTU_ROOT_FRQ / 1000),
> + clocksource_mmtu.shift);
> + else
> + clocksource_mmtu.mult = clocksource_hz2mult((MMTU_ROOT_FRQ),
> + clocksource_mmtu.shift);
> +
> + u6_mmtu_timer_init(0, 0, (MMTU_SYS_FRQ / MMTU_ROOT_FRQ), 0);
> +
> + clocksource_register(&clocksource_mmtu);
> +}
> +
> +unsigned long long u6_mmtu_time(void)
> +{
> + unsigned long long ticks64 = u6_mmtu_read(&clocksource_mmtu);
> +
> + return (ticks64 * clocksource_mmtu.mult) >> clocksource_mmtu.shift;
> +}
Can you explain the purpose of this function please, and why you export
the ticks and value from this function via sysfs?
> +#endif
> +
> +/*** SysFs interface ***/
> +/***********************/
> +#ifdef CONFIG_U6_POWER_SYSFS
> +
> +/*** Clock event sysfs interface **/
> +
> +#define shows_one_evt(file_name, object) \
> +static ssize_t show_##file_name##_evt \
> +(struct kobject *kobj, char *buf) \
> +{ \
> + return sprintf(buf, "%s\n", clockevent_mmtu.object); \
> +}
> +
> +#define showu_one_evt(file_name, object) \
> +static ssize_t show_##file_name##_evt \
> +(struct kobject *kobj, char *buf) \
> +{ \
> + return sprintf(buf, "%u\n", clockevent_mmtu.object); \
> +}
> +
> +#define showlu_one_evt(file_name, object) \
> +static ssize_t show_##file_name##_evt \
> +(struct kobject *kobj, char *buf) \
> +{ \
> + return sprintf(buf, "%lu\n", clockevent_mmtu.object); \
> +}
> +
> +#define storelu_one_evt(file_name, object) \
> +static ssize_t store_##file_name##_evt \
> +(struct kobject *kobj, const char *buf, size_t size) \
> +{ \
> + unsigned long object; \
> + strict_strtoul(buf, 10, &object); \
> + clockevent_mmtu.object = object; \
> + return size; \
> +}
> +
> +#define showx_one_evt(file_name, object) \
> +static ssize_t show_##file_name##_evt \
> +(struct kobject *kobj, char *buf) \
> +{ \
> + return sprintf(buf, "0x%x\n", clockevent_mmtu.object); \
> +}
> +
> +shows_one_evt(name, name);
> +showu_one_evt(rating, rating);
> +showlu_one_evt(mult, mult);
> +#ifdef CONFIG_U6_TIMER_TUNE
> +storelu_one_evt(mult, mult);
> +#endif
> +showu_one_evt(shift, shift);
> +showx_one_evt(features, features);
> +showlu_one_evt(min_delta_ns, min_delta_ns);
> +showlu_one_evt(max_delta_ns, max_delta_ns);
Why do you want all these parameters exported to userspace? Maybe you
should discuss your requirement here with the generic time people
before submitting it?
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 2/6] U6715 clocks gating management U6 clock generic driver & U6715 cgu clock specific (V2)
2010-05-27 8:27 ` [PATCH 2/6] U6715 clocks gating management U6 clock generic driver & U6715 cgu clock specific (V2) Philippe Langlais
@ 2010-06-24 14:14 ` Russell King - ARM Linux
2010-07-05 7:09 ` Philippe Langlais
0 siblings, 1 reply; 17+ messages in thread
From: Russell King - ARM Linux @ 2010-06-24 14:14 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, May 27, 2010 at 10:27:28AM +0200, Philippe Langlais wrote:
> +#if defined(DEBUG_CGU)
> +#define debug(fmt, args...) \
> + printk(PKMOD fmt, ## args)
> +#else
> +#define debug(fmt, args...)
> +#endif
pr_debug?
> +
> +/**
> + * U6 hw low level access clock functions
> + **/
> +static void u6_clk_disable(struct clk *clk);
> +static int u6_clk_enable(struct clk *clk);
> +
> +/**
> + * HW enable clock function.
> + **/
> +
> +static int u67xx_cgu_enable_fake_clock(struct clk *clk)
> +{
> + debug("u67xx_cgu_enable_fake_clock for %s\n", clk->name);
> + return 0;
> +}
> +
> +static int u67xx_cgu_enable_hw_clock(struct clk *clk)
> +{
> + unsigned long value;
> + debug("u67xx_cgu_enable_hw_clock for %s\n", clk->name);
> +
> + if (unlikely(clk->enable_reg == 0)) {
These are pointers. 0 is an integer. Use NULL. Check your code with
sparse and you'll get warnings for these things.
> +/*** Basic clocks ***/
> +
> +/* Base external input clocks */
> +static struct clk func_32k_ck = {
> + .name = "func_32k_ck",
> + .rate = 32000,
> + .flags = RATE_FIXED | ALWAYS_ENABLED,
> + .usecount = 1,
> +};
Don't put data definitions in header files.
> +static struct clk *onchip_clks[] = {
> + /* external root sources */
> + &func_32k_ck,
> + &osc_ck,
> + &sys_ck,
> + &sc_ck,
> + &fix_ck,
> + &tv_ck,
> +#ifndef U6_OPTIMIZED_TREE
> + &dsp2_ck,
> +#endif
> + &sdm_ck,
> + &arm_ck,
> + &hclk_ck,
> + &hclk2_ck,
> + &pclk1_ck,
> + &pclk2_ck,
> + &tvclk_ck,
This all looks very much like it was copied from the OMAP code as of about
a year ago. The OMAP code has moved forwards with lots of improvements,
including using clkdev to eliminate the disgusting SoC specific code from
drivers (which clkdev is there to prevent.)
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 4/6] U6715 platform serial driver It's a generic driver for all U6 platform (V2)
2010-05-27 8:27 ` [PATCH 4/6] U6715 platform serial driver It's a generic driver for all U6 platform (V2) Philippe Langlais
@ 2010-06-24 14:17 ` Russell King - ARM Linux
0 siblings, 0 replies; 17+ messages in thread
From: Russell King - ARM Linux @ 2010-06-24 14:17 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, May 27, 2010 at 10:27:30AM +0200, Philippe Langlais wrote:
> +struct u6_uart {
> + struct clk *uartClk;
> + struct clk *pClk_13M;
> + struct clk *pClk_26M;
> + struct clk *pClk_pclk;
> + char uart_name[7];
> +};
Passing struct clk's through platform data into drivers... what's the
point of the clk API again?
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 3/6] U6715 gpio platform driver This driver is U6 platform generic (V2)
2010-05-27 8:27 ` [PATCH 3/6] U6715 gpio platform driver This driver is U6 platform generic (V2) Philippe Langlais
@ 2010-06-24 14:26 ` Russell King - ARM Linux
2010-07-05 7:14 ` Philippe Langlais
0 siblings, 1 reply; 17+ messages in thread
From: Russell King - ARM Linux @ 2010-06-24 14:26 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, May 27, 2010 at 10:27:29AM +0200, Philippe Langlais wrote:
> Signed-off-by: Philippe Langlais <philippe.langlais@stericsson.com>
> ---
> arch/arm/mach-u67xx/board_u67xx_wavex.c | 469 ++++++++++++++++++++
> arch/arm/mach-u67xx/devices.c | 12 +-
> arch/arm/plat-u6xxx/Makefile | 2 +-
> arch/arm/plat-u6xxx/gpio.c | 716 +++++++++++++++++++++++++++++++
> arch/arm/plat-u6xxx/include/mach/gpio.h | 396 +++++++++++++++++
> 5 files changed, 1588 insertions(+), 7 deletions(-)
> create mode 100644 arch/arm/plat-u6xxx/gpio.c
> create mode 100644 arch/arm/plat-u6xxx/include/mach/gpio.h
>
> diff --git a/arch/arm/mach-u67xx/board_u67xx_wavex.c b/arch/arm/mach-u67xx/board_u67xx_wavex.c
> index 2a806e7..a21e465 100644
> --- a/arch/arm/mach-u67xx/board_u67xx_wavex.c
> +++ b/arch/arm/mach-u67xx/board_u67xx_wavex.c
> @@ -24,6 +24,474 @@
> #include <asm/mach/arch.h>
> #include <mach/irqs.h>
> #include <mach/timer.h>
> +#include <mach/gpio.h>
linux/gpio.h
> +
> +#include <mach/scon.h>
> +
> +/**
> + * SCON initial settings
> + * Allows to define the PIN multiplexing for all the platform (Linux and Modem)
> + */
> +struct u6_scon_config u6_scon_init_config[SCON_REGISTER_NB] = {
> + {
> + (void __iomem *) SCON_SYSMUX0_REG,
IOMEM() to eliminate the cast?
> +/* GPIO def settings to avoid HW issue */
> +struct u6_gpio_config u6_gpio_init_config[] = {
> + /* GPIO A bank */
> + {
> + .gpio = GPIO_A5,
> + .dir = GPIO_DIR_OUTPUT ,
Unnecessary spaces between 'OUTPUT' and ','
> + .value = 1,
> + },
> + {
> + .gpio = GPIO_A6,
> + .dir = GPIO_DIR_OUTPUT ,
> + .value = 1,
> + },
> + {
> + .gpio = GPIO_A7,
> + .dir = GPIO_DIR_OUTPUT ,
> + .value = 0,
> + },
> + {
> + .gpio = GPIO_A8,
> + .dir = GPIO_DIR_OUTPUT ,
> + .value = 1,
> + },
> + {
> + .gpio = GPIO_A9,
> + .dir = GPIO_DIR_OUTPUT ,
> + .value = 1,
> + },
> + {
> + .gpio = GPIO_A13,
> + .dir = GPIO_DIR_OUTPUT ,
> + .value = 0,
> + },
> + {
> + .gpio = GPIO_A17,
> + .dir = GPIO_DIR_OUTPUT ,
> + .value = 0,
> + },
> + {
> + .gpio = GPIO_A21,
> + .dir = GPIO_DIR_OUTPUT ,
> + .value = 0,
> + },
> + {
> + .gpio = GPIO_A23,
> + .dir = GPIO_DIR_OUTPUT ,
> + .value = 0,
> + },
> + {
> + .gpio = GPIO_A24,
> + .dir = GPIO_DIR_OUTPUT ,
> + .value = 1,
> + },
> + {
> + .gpio = GPIO_A25,
> + .dir = GPIO_DIR_OUTPUT ,
> + .value = 0,
> + },
> + {
> + .gpio = GPIO_A30,
> + .dir = GPIO_DIR_OUTPUT ,
> + .value = 0,
> + },
> + /* GPIO B bank */
> + /* GPIO C bank */
> + /* GPIO D bank */
> + {
> + .gpio = GPIO_D0,
> + .dir = GPIO_DIR_OUTPUT ,
> + .value = 0,
> + },
> + {
> + .gpio = GPIO_D24,
> + .dir = GPIO_DIR_OUTPUT ,
> + .value = 0,
> + },
> + {
> + .gpio = GPIO_D29,
> + .dir = GPIO_DIR_OUTPUT ,
> + .value = 0,
> + },
> + /* GPIO E bank */
> + {
> + .gpio = GPIO_E31,
> + .dir = GPIO_DIR_OUTPUT ,
> + .value = 0,
> + },
> + /* GPIO F bank */
> + {
> + .gpio = GPIO_F0,
> + .dir = GPIO_DIR_OUTPUT ,
> + .value = 0,
> + },
> + {
> + .gpio = GPIO_F1,
> + .dir = GPIO_DIR_OUTPUT ,
> + .value = 0,
> + },
> + {
> + .gpio = GPIO_F2,
> + .dir = GPIO_DIR_OUTPUT ,
> + .value = 0,
> + },
> + {
> + .gpio = GPIO_F9,
> + .dir = GPIO_DIR_OUTPUT ,
> + .value = 0,
> + }
> +};
> +
> +u32 gpio_to_configure = ARRAY_SIZE(u6_gpio_init_config);
>
> /* List of board specific devices */
> static struct platform_device *devices[] __initdata = {
> @@ -31,6 +499,7 @@ static struct platform_device *devices[] __initdata = {
>
> void __init u67xx_init(void)
> {
> + u6_gpio_init();
> /* Add specific board devices */
> platform_add_devices(devices, ARRAY_SIZE(devices));
> }
> diff --git a/arch/arm/mach-u67xx/devices.c b/arch/arm/mach-u67xx/devices.c
> index 0ead380..8e812fb 100644
> --- a/arch/arm/mach-u67xx/devices.c
> +++ b/arch/arm/mach-u67xx/devices.c
> @@ -48,12 +48,12 @@ unsigned char extint_to_gpio[NR_EXTINT] = {
> EXPORT_SYMBOL(extint_to_gpio);
>
> struct gpio_bank u6_gpio_bank[6] = {
> - {(void __iomem *)GPIOA_PINS_REG, (void __iomem *)SCON_SYSMUX0_REG},
> - {(void __iomem *)GPIOB_PINS_REG, (void __iomem *)SCON_SYSMUX2_REG},
> - {(void __iomem *)GPIOC_PINS_REG, (void __iomem *)SCON_SYSMUX4_REG},
> - {(void __iomem *)GPIOD_PINS_REG, (void __iomem *)SCON_SYSMUX6_REG},
> - {(void __iomem *)GPIOE_PINS_REG, (void __iomem *)SCON_SYSMUX8_REG},
> - {(void __iomem *)GPIOF_PINS_REG, (void __iomem *)SCON_SYSMUX10_REG},
> + {GPIOA_PINS_REG, SCON_SYSMUX0_REG},
> + {GPIOB_PINS_REG, SCON_SYSMUX2_REG},
> + {GPIOC_PINS_REG, SCON_SYSMUX4_REG},
> + {GPIOD_PINS_REG, SCON_SYSMUX6_REG},
> + {GPIOE_PINS_REG, SCON_SYSMUX8_REG},
> + {GPIOF_PINS_REG, SCON_SYSMUX10_REG},
> };
>
> static struct gpio_data u6_gpio_data = {
> diff --git a/arch/arm/plat-u6xxx/Makefile b/arch/arm/plat-u6xxx/Makefile
> index afdf82b..3d6898e 100644
> --- a/arch/arm/plat-u6xxx/Makefile
> +++ b/arch/arm/plat-u6xxx/Makefile
> @@ -3,6 +3,6 @@
> #
>
> # Common support
> -obj-y := io.o irq.o clock.o
> +obj-y := io.o irq.o clock.o gpio.o
>
> obj-$(CONFIG_U6_MTU_TIMER) += timer.o
> diff --git a/arch/arm/plat-u6xxx/gpio.c b/arch/arm/plat-u6xxx/gpio.c
> new file mode 100644
> index 0000000..40e25fc
> --- /dev/null
> +++ b/arch/arm/plat-u6xxx/gpio.c
> @@ -0,0 +1,716 @@
> +/*
> + * linux/arch/arm/plat-u6xxx/gpio.c
> + *
> + * Copyright (C) ST-Ericsson SA 2010
> + * Author: Loic Pallardy <loic.pallardy@stericsson.com> for ST-Ericsson.
> + * License terms: GNU General Public License (GPL), version 2
> + * Support functions for GPIO
> + */
> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/sched.h>
> +#include <linux/interrupt.h>
> +#include <linux/ptrace.h>
> +#include <linux/sysdev.h>
> +#include <linux/err.h>
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +
> +#include <mach/hardware.h>
> +#include <asm/irq.h>
> +#include <mach/irqs.h>
> +#include <mach/gpio.h>
> +#include <asm/mach/irq.h>
> +#include <mach/scon.h>
asm/ before mach/.
> +
> +/*
> + * PN5220 GPIO/MUX registers
> + * defined in asm/arch/registers.h
> + */
> +
> +#define U6_GPIO_PINS_OFFSET 0
> +#define U6_GPIO_OUTPUT_OFFSET 4
> +#define U6_GPIO_DIR_OFFSET 8
> +
> +#define U6_MUX2_OFFSET 4
> +
> +static struct gpio_bank *gpio_bank_desc;
> +static int gpio_bank_count;
> +
> +static inline struct gpio_bank *get_gpio_bank(int gpio)
> +{
> + /* 32 GPIOs per bank */
> + return &(gpio_bank_desc[gpio >> 5]);
> +}
> +
> +static inline int get_gpio_index(int gpio)
> +{
> + return gpio & 0x1f;
> +}
> +
> +static int check_gpio(int gpio)
> +{
> + int retval = ((unsigned int)gpio) < GPIO_COUNT;
> + if (unlikely(!retval)) {
> + printk(KERN_ERR "u6-gpio: invalid GPIO %d\n", gpio);
> + dump_stack();
> + }
return WARN_ON((unsigned int)gpio < GPIO_COUNT);
or use WARN(condition, format) if you want a custom message.
> +static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
> +{
> + u32 reg = bank->gpio_base;
> + u32 l;
> +
> + /* select direction register */
> + reg += U6_GPIO_DIR_OFFSET;
> +
> + /* in register 0 = input, 1 = output */
> + l = inl(reg);
inl/outl are for PCI/ISA based IO accesses/emulation. I don't think your
GPIO block is a PCI/ISA peripheral, so it should not be using these macros.
> +static int initialized;
> +
> +static int __init u6_gpio_probe(struct platform_device *pdev)
> +{
> + int i, j;
> + int gpio = 0;
> + struct gpio_bank *bank;
> + struct gpio_data *data = pdev->dev.platform_data;
> + unsigned long flags;
> +
> + initialized = 1;
Why is this here when you're really wanting to prevent the platform
driver structure being registered more than once?
> +
> + printk(KERN_INFO "U6 GPIO\n");
> + gpio_bank_desc = data->gpio_bank_desc;
> + gpio_bank_count = data->nb_banks;
> +
> + for (i = 0; i < gpio_bank_count; i++) {
> + int gpio_count = 32; /* 32 GPIO per bank */
> + bank = &gpio_bank_desc[i];
> + bank->reserved_map = 0;
> + spin_lock_init(&bank->lock);
> +
> + bank->chip.request = u6_gpio_acquire;
> + bank->chip.free = u6_gpio_release;
> + bank->chip.direction_input = gpio_input;
> + bank->chip.get = gpio_get;
> + bank->chip.direction_output = gpio_output;
> + bank->chip.set = gpio_set;
> + bank->chip.to_irq = gpio_2irq;
> + bank->chip.label = "gpio";
> + bank->chip.base = gpio;
> + gpio += gpio_count;
> +
> + bank->chip.ngpio = gpio_count;
> +
> + gpiochip_add(&bank->chip);
> +
> + }
> +
> + /* for extint */
> + for (j = IRQ_COUNT; j < IRQ_COUNT + NR_EXTINT; j++) {
> + set_irq_chip(j, &gpio_irq_chip);
> + set_irq_handler(j, handle_simple_irq);
> + set_irq_flags(j, IRQF_VALID);
> + }
> +
> + hw_raw_local_irq_save(flags);
> + /* mask all EXT IRQ sources before registring handler */
> + /* read status */
> + j = inl(EXTINT_STATUS_REG) & inl(EXTINT_ENABLE3_REG);
> + /* clear IRQ source(s) */
> + outl(j, EXTINT_STATUS_REG);
> +
> + outl(0, EXTINT_ENABLE3_REG);
> +
> + /* set irq in low level */
> + set_irq_type(IRQ_EXTINT3, IRQF_TRIGGER_LOW);
> +
> + /* chained GPIO-IRQ on EXTINT3 */
> + set_irq_chained_handler(IRQ_EXTINT3, gpio_irq_handler);
> + hw_raw_local_irq_restore(flags);
> +
> + return 0;
> +}
> +
> +static struct platform_driver u6_gpio_driver = {
> + .probe = u6_gpio_probe,
> + .remove = NULL,
> + .suspend = NULL,
> + .resume = NULL,
> + .driver = {
> + .name = "u6-gpio",
> + },
> +};
> +
> +static struct sysdev_class u6_gpio_sysclass = {
> + .name = "gpio",
> + .suspend = 0, /*u6_gpio_suspend, */
> + .resume = 0, /*u6_gpio_resume, */
> +};
> +
> +static struct sys_device u6_gpio_device = {
> + .id = 0,
> + .cls = &u6_gpio_sysclass,
> +};
> +
> +/*
> + * This may get called early from board specific init
> + * for boards that have interrupts routed via FPGA.
> + */
> +int u6_gpio_init(void)
> +{
> + if (!initialized)
> + return platform_driver_register(&u6_gpio_driver);
Shouldn't this set 'initialized' once the platform driver has been
registered to prevent the platform driver being registered again?
> + else
> + return 0;
> +}
> +
> +static int __init u6_gpio_sysinit(void)
> +{
> + int ret = 0;
> +
> + if (!initialized)
> + ret = u6_gpio_init();
Why not just call u6_gpio_init(), which handles the special case anyway?
> +
> + if (ret == 0) {
> + ret = sysdev_class_register(&u6_gpio_sysclass);
> + if (ret == 0)
> + ret = sysdev_register(&u6_gpio_device);
> + }
> +
> + return ret;
> +}
> +
> +arch_initcall(u6_gpio_sysinit);
> diff --git a/arch/arm/plat-u6xxx/include/mach/gpio.h b/arch/arm/plat-u6xxx/include/mach/gpio.h
> new file mode 100644
> index 0000000..a205f1c
> --- /dev/null
> +++ b/arch/arm/plat-u6xxx/include/mach/gpio.h
> @@ -0,0 +1,396 @@
> +/*
> + * linux/arch/arm/plat-u6xxx/include/mach/gpio.h
> + *
> + * Copyright (C) ST-Ericsson SA 2010
> + * Author: Loic Pallardy <loic.pallardy@stericsson.com> for ST-Ericsson.
> + * License terms: GNU General Public License (GPL), version 2
> + * GPIO handling defines and functions
> + */
> +
> +#ifndef __ASM_PLAT_U6_GPIO_H
> +#define __ASM_PLAT_U6_GPIO_H
> +
> +#include <linux/io.h>
> +#include <mach/hardware.h>
> +#include <mach/irqs.h>
> +#include <mach/gpio.h>
Recursive include of mach/gpio.h
> +
> +#include <linux/errno.h>
> +#include <asm-generic/gpio.h>
linux/ includes before asm and mach includes.
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 5/6] U6715 8250 serial like driver
2010-05-27 8:27 ` [PATCH 5/6] U6715 8250 serial like driver Philippe Langlais
@ 2010-06-24 14:31 ` Russell King - ARM Linux
2010-07-05 7:39 ` Philippe Langlais
0 siblings, 1 reply; 17+ messages in thread
From: Russell King - ARM Linux @ 2010-06-24 14:31 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, May 27, 2010 at 10:27:31AM +0200, Philippe Langlais wrote:
> Some modifications in 16550A/8250 serial driver
> and clock management specificity
Can't say much about this; you need to get people interested in serial to
review this. The comments about header file ordering apply.
> @@ -199,10 +199,16 @@ static const struct serial8250_config uart_config[] = {
> },
> [PORT_16550A] = {
> .name = "16550A",
> +#if defined(CONFIG_SERIAL_8250_U6)
> + .fifo_size = 64,
> + .tx_loadsz = 64,
> + .flags = UART_CAP_FIFO | UART_CAP_AFE,
If you have auto flow control, then you don't have a 16550A. You have
something that is compatible with a 16550A - maybe it's more closely
related to a 16750?
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 1/6] U6/U6715 ARM architecture files
2010-06-24 14:08 ` Russell King - ARM Linux
@ 2010-06-25 13:34 ` Philippe Langlais
0 siblings, 0 replies; 17+ messages in thread
From: Philippe Langlais @ 2010-06-25 13:34 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
Many thanks for your comments.
On 06/24/10 16:08, Russell King - ARM Linux wrote:
> On Thu, May 27, 2010 at 10:27:27AM +0200, Philippe Langlais wrote:
>
>> diff --git a/arch/arm/mach-u67xx/devices.c b/arch/arm/mach-u67xx/devices.c
>> new file mode 100644
>> index 0000000..0ead380
>> --- /dev/null
>> +++ b/arch/arm/mach-u67xx/devices.c
>> @@ -0,0 +1,95 @@
>> +/*
>> + * linux/arch/arm/mach-u67xx/devices.c
>> + *
>> + * Copyright (C) ST-Ericsson SA 2010
>> + * Author: Philippe Langlais<philippe.langlais@stericsson.com> for ST-Ericsson.
>> + * License terms: GNU General Public License (GPL), version 2
>> + *
>> + * Device specification for the U67XX
>> + */
>> +
>> +#include<linux/kernel.h>
>> +#include<linux/init.h>
>> +#include<linux/device.h>
>> +#include<linux/ioport.h>
>> +#include<linux/platform_device.h>
>> +#include<linux/fs.h>
>> +#include<mach/hardware.h>
>> +#include<mach/scon.h>
>> +#include<mach/gpio.h>
>>
> linux/gpio.h
>
>
>> +struct gpio_bank u6_gpio_bank[6] = {
>> + {(void __iomem *)GPIOA_PINS_REG, (void __iomem *)SCON_SYSMUX0_REG},
>> + {(void __iomem *)GPIOB_PINS_REG, (void __iomem *)SCON_SYSMUX2_REG},
>> + {(void __iomem *)GPIOC_PINS_REG, (void __iomem *)SCON_SYSMUX4_REG},
>> + {(void __iomem *)GPIOD_PINS_REG, (void __iomem *)SCON_SYSMUX6_REG},
>> + {(void __iomem *)GPIOE_PINS_REG, (void __iomem *)SCON_SYSMUX8_REG},
>> + {(void __iomem *)GPIOF_PINS_REG, (void __iomem *)SCON_SYSMUX10_REG},
>>
> Would be nice to get rid of these casts - instead moving them to the
> point of definition instead - or maybe doing as other platforms do and
> defining an IOMEM() macro which does the cast and using that in the
> definitions.
>
> iow, something like:
>
> #define IOMEM(x) ((void __iomem *)(x))
>
> #define GPIOA_PINS_REG IOMEM(whatever)
>
> and if you need GPIOA_PINS_REG to be usable in assembly, arrange for
> the IOMEM() macro to handle that for you.
>
>
OK, it's already done in PATCH 5/6, I made a mistake at patch build.
I'll delete GPIO stuff from this patch.
>> diff --git a/arch/arm/plat-u6xxx/include/mach/entry-macro.S b/arch/arm/plat-u6xxx/include/mach/entry-macro.S
>> new file mode 100644
>> index 0000000..59bb2d2
>> --- /dev/null
>> +++ b/arch/arm/plat-u6xxx/include/mach/entry-macro.S
>> @@ -0,0 +1,32 @@
>> +/*
>> + * linux/arch/arm/plat-u6xxx/include/mach/entry-macro.S
>> + *
>> + * Low-level IRQ helper macros for U6-based platforms
>> + * Copyright (C) ST-Ericsson SA 2010
>> + *
>> + * This file is licensed under the terms of the GNU General Public
>> + * License version 2. This program is licensed "as is" without any
>> + * warranty of any kind, whether express or implied.
>> + */
>> +#include<mach/hardware.h>
>> +#include<mach/irqs.h>
>> +
>> + .macro arch_ret_to_user, tmp1, tmp2
>> + .endm
>> +
>> + .macro disable_fiq
>> + .endm
>> +
>> + .macro get_irqnr_preamble, base, tmp
>> + .endm
>>
> This macro is there to allow you to be a little more efficient - rather
> than reloading the base address of the interrupt controller each time
> around the interrupt handling loop, you can put it in the above macro
> to take it outside the loop.
>
>
OK
>> +#define hw_raw_local_irq_save raw_local_irq_save
>> +#define hw_raw_local_irq_restore raw_local_irq_restore
>>
> What's the purpose of these additional aliases?
>
>
Necessary for our para-virtualized drivers, but not for normal kernel usage.
Will be removed.
>> +/* INTC PRIOMASK_IRQ Register (32 bits) */
>> +#define INTC_PRIOMASK_IRQ_OFFSET 0x0
>> +#define INTC_PRIOMASK_IRQ_REG IO_ADDRESS(INTC_BASE + INTC_PRIOMASK_IRQ_OFFSET)
>> +
>> +/* INTC PRIOMASK_FIQ Register (32 bits) */
>> +#define INTC_PRIOMASK_FIQ_OFFSET 0x4
>> +#define INTC_PRIOMASK_FIQ_REG IO_ADDRESS(INTC_BASE + INTC_PRIOMASK_FIQ_OFFSET)
>> +
>> +/* INTC VECTOR_IRQ Register (32 bits) */
>> +#define INTC_VECTOR_IRQ_OFFSET 0x100
>> +#define INTC_VECTOR_IRQ_REG IO_ADDRESS(INTC_BASE + INTC_VECTOR_IRQ_OFFSET)
>> +
>> +/* INTC VECTOR_FIQ Register (32 bits) */
>> +#define INTC_VECTOR_FIQ_OFFSET 0x104
>> +#define INTC_VECTOR_FIQ_REG IO_ADDRESS(INTC_BASE + INTC_VECTOR_FIQ_OFFSET)
>> +
>> +/* INTC PENDING_* Registers (32 bits) */
>> +#define INTC_PENDING_1_OFFSET 0x200
>> +#define INTC_PENDING_2_OFFSET 0x204
>> +#define INTC_PENDING_3_OFFSET 0x208
>> +#define INTC_FEATURES_OFFSET 0x300
>> +
>> +/* INTC REQUEST 64 Registers (32 bits) */
>> +#define INTC_REQUEST1_OFFSET 0x404
>> +#define INTC_REQUEST64_OFFSET 0x500
>> +
>> +/* INTC MOD_ID Register (32 bits) */
>> +#define INTC_MOD_ID_OFFSET 0xFFC
>> +
>> +/* interrupt x [1..64] request configuration */
>> +#define INTC_REQUESTx(x) IO_ADDRESS(INTC_BASE+INTC_REQUEST1_OFFSET+(x-1)*4)
>> +
>> +/* EXTINTx [0..23] configuration register */
>> +#define EXTINT_CFGx(x) IO_ADDRESS(EXTINT_BASE+(x)*4)
>>
> Does it really make sense to export all these definitions to the entire
> kernel?
>
>
I'll try to move it into plat-u6xxx/irq.c
>> diff --git a/arch/arm/plat-u6xxx/include/mach/memory.h b/arch/arm/plat-u6xxx/include/mach/memory.h
>> new file mode 100644
>> index 0000000..0fa6cea
>> --- /dev/null
>> +++ b/arch/arm/plat-u6xxx/include/mach/memory.h
>> @@ -0,0 +1,24 @@
>> +/*
>> + * linux/arch/arm/plat-u6xxx/include/mach/memory.h
>> + *
>> + * Copyright (C) ST-Ericsson SA 2010
>> + * Author: Philippe Langlais<philippe.langlais@stericsson.com> for ST-Ericsson.
>> + * License terms: GNU General Public License (GPL), version 2
>> + */
>> +
>> +#ifndef __ASM_ARCH_MEMORY_H
>> +#define __ASM_ARCH_MEMORY_H
>> +
>> +/*
>> + * Physical DRAM offset.
>> + */
>> +#define PHYS_OFFSET UL(0x20000000)
>> +#define BOOT_PARAMS_OFFSET (PHYS_OFFSET + 0x100)
>>
> Does it make sense to export this to the world?
>
I take our U300 as example, but I can change that.
>> +
>> +/**
>> + * CONSISTENT_DMA_SIZE: Size of DMA-consistent memory region.
>> + * Must be multiple of 2M,between 2MB and 14MB inclusive
>> + */
>> +#define CONSISTENT_DMA_SIZE (SZ_2M)
>>
> It defaults to 2MB, so this definition is redundant.
>
>
OK, no problem
>> diff --git a/arch/arm/plat-u6xxx/include/mach/platform.h b/arch/arm/plat-u6xxx/include/mach/platform.h
>> new file mode 100644
>> index 0000000..5265ccd
>> --- /dev/null
>> +++ b/arch/arm/plat-u6xxx/include/mach/platform.h
>> @@ -0,0 +1,15 @@
>> +/*
>> + * linux/arch/arm/plat-u6xxx/include/mach/platform.h
>> + *
>> + * Copyright (C) ST-Ericsson SA 2010
>> + * Author: Philippe Langlais<philippe.langlais@stericsson.com> for ST-Ericsson.
>> + * License terms: GNU General Public License (GPL), version 2
>> + */
>> +
>> +#ifndef __ASM_ARCH_PLATFORM_H
>> +#define __ASM_ARCH_PLATFORM_H 1
>> +
>> +#include<linux/types.h>
>> +#include<mach/hardware.h>
>> +
>> +#endif /* __ASM_ARCH_PLATFORM_H */
>>
> If there's nothing required in this file, it doesn't need to exist.
>
>
OK
>> diff --git a/arch/arm/plat-u6xxx/include/mach/timer.h b/arch/arm/plat-u6xxx/include/mach/timer.h
>> new file mode 100644
>> index 0000000..049e72d
>> --- /dev/null
>> +++ b/arch/arm/plat-u6xxx/include/mach/timer.h
>> @@ -0,0 +1,24 @@
>> +/*
>> + * linux/arch/arm/plat-u6xxx/include/mach/timer.h
>> + *
>> + * Copyright (C) ST-Ericsson SA 2010
>> + * Author: Philippe Langlais<philippe.langlais@stericsson.com> for ST-Ericsson.
>> + * License terms: GNU General Public License (GPL), version 2
>> + */
>> +
>> +#ifndef __PLAT_TIMER_H
>> +#define __PLAT_TIMER_H
>> +#ifdef U6_TIMER_C
>> +#define PUBLIC
>> +#else
>> +#define PUBLIC extern
>> +#endif
>>
> Err, no - there's really no need for such hacks in C, and I can't find
> anywhere which defines U6_TIMER_C.
>
>
OK
>> +
>> +struct sys_timer;
>> +
>> +PUBLIC struct sys_timer u6_timer;
>> +
>> +PUBLIC void __init u6_timer_init(void);
>> +
>> +#undef PUBLIC
>> +#endif
>>
>
>> diff --git a/arch/arm/plat-u6xxx/include/mach/vmalloc.h b/arch/arm/plat-u6xxx/include/mach/vmalloc.h
>> new file mode 100644
>> index 0000000..583033f
>> --- /dev/null
>> +++ b/arch/arm/plat-u6xxx/include/mach/vmalloc.h
>> @@ -0,0 +1,10 @@
>> +/*
>> + * linux/arch/arm/plat-u6/include/mach/vmalloc.h
>> + * Copyright (C) ST-Ericsson SA 2010
>> + * Author: Philippe Langlais<philippe.langlais@stericsson.com> for ST-Ericsson.
>> + * 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.
>> + */
>> +#define VMALLOC_END (PAGE_OFFSET + 0x28000000)
>>
> Is the upper limit of vmalloc space is dependent on PAGE_OFFSET? If
> not, then it shouldn't be using a calculation based upon that value.
>
>
OK
>> diff --git a/arch/arm/plat-u6xxx/timer.c b/arch/arm/plat-u6xxx/timer.c
>> new file mode 100644
>> index 0000000..62f13f5
>> --- /dev/null
>> +++ b/arch/arm/plat-u6xxx/timer.c
>> @@ -0,0 +1,679 @@
>> +/*
>> + * linux/arch/arm/plat-u6xxx/timer.c
>> + *
>> + * Copyright (C) ST-Ericsson SA 2010
>> + * Author: Vincent Guittot<vincent.guittot@stericsson.com> for ST-Ericsson.
>> + * License terms: GNU General Public License (GPL), version 2
>> + */
>> +
>> +#include<linux/types.h>
>> +#include<linux/kernel.h>
>> +#include<linux/err.h>
>> +#include<linux/init.h>
>> +#include<linux/io.h>
>> +
>> +#include<asm/mach/time.h>
>> +
>> +#include<mach/hardware.h>
>> +
>> +#include<asm/mach/irq.h>
>> +#include<linux/interrupt.h>
>> +#include<mach/irqs.h>
>> +
>> +#include<linux/clk.h>
>> +
>> +#include<linux/clocksource.h>
>> +#include<linux/clockchips.h>
>>
> linux/ includes before asm/ includes. asm/ includes before mach/ includes
> please.
>
>
OK
>> +#undef U6_TIMER_DEBUG
>> +#if defined(U6_TIMER_DEBUG)
>> +#define debug(fmt, args...) \
>> + printk(PKMOD fmt, ## args)
>> +#else
>> +#define debug(fmt, args...)
>> +#endif
>>
> You could use pr_debug() instead, and define 'DEBUG' at the top of the
> file you want debug messages from.
>
OK
>
>> +static irqreturn_t
>> +u6_mmtu_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
>> +{
>> + uint8_t status, enable;
>> + struct mmtu_ctxt *mmtu;
>> +
>> + mmtu = u6_mmtu_get_context(0);
>> +
>> + status = readl((mmtu->base + MMTU_INT_OFFSET + MMTU_INT_STATUS_IDX));
>> + enable = readl((mmtu->base + MMTU_INT_OFFSET + MMTU_INT_ENABLE_IDX));
>> +
>> + debug("mmtu_timer_interrupt %d\n", status);
>> +
>> + if (status& enable& MMTU_IRQ_MASK) {
>> + struct clock_event_device *evt =&clockevent_mmtu;
>> +
>> + writel(MMTU_IRQ_MASK, (mmtu->base + MMTU_INT_OFFSET
>> + + MMTU_INT_CLR_STAT_IDX));
>> +
>> + if (mmtu->autoreload)
>> + u6_mmtu_timer_start(mmtu->compvalue, 0);
>>
> If your hardware doesn't do reloadable timers, you're not supposed to
> emulate it. The generic time infrastructure contains all the code
> that's required to handle periodic timer interrupts with timers only
> capable of one-shot mode.
>
>
We removed this code and it's works => OK
>
>> + else
>> + writel(MMTU_IRQ_MASK,
>> + (mmtu->base + MMTU_INT_OFFSET +
>> + MMTU_INT_CLR_ENA_IDX));
>> +
>> + if (evt->event_handler)
>> + evt->event_handler(evt);
>> + }
>> + return IRQ_HANDLED;
>> +}
>> +
>> +static struct irqaction u6_mmtu_timer_irq = {
>> + .name = "U6 MMTU timer Tick",
>> + .flags = IRQF_DISABLED,
>> + .handler = (irq_handler_t) u6_mmtu_timer_interrupt,
>> +};
>> +
>> +static inline void u6_mmtu_clk_enable(int id)
>> +{
>> + struct mmtu_ctxt *mmtu = u6_mmtu_get_context(id);
>> +
>> + /* Clock Multimedia Timer Unit.
>> + */
>> + if ((mmtu->clk != NULL)&& (mmtu->mode == 0)) {
>> + debug("mmtu_clk_enable\n");
>> + mmtu->mode = 1;
>> + clk_enable(mmtu->clk);
>> + }
>> +}
>> +
>> +static inline void u6_mmtu_clk_disable(int id)
>> +{
>> + struct mmtu_ctxt *mmtu = u6_mmtu_get_context(id);
>> +
>> + /* Clock Multimedia Timer Unit.
>> + */
>> + if ((mmtu->clk != NULL)&& (mmtu->mode == 1)) {
>> + debug("mmtu_clk_disable\n");
>> + clk_disable(mmtu->clk);
>> + mmtu->mode = 0;
>> + }
>> +}
>> +
>> +static inline int u6_mmtu_timer_start(unsigned long cycles, int id)
>> +{
>> + struct mmtu_ctxt *mmtu = u6_mmtu_get_context(id);
>> +
>> + debug("mmtu_timer_start %d\n", cycles);
>> + u6_mmtu_clk_enable(id);
>> +
>> + /* MMTU limitation : can't set a value smaller or equal to tcval + 1 */
>> + cycles = cycles< 2 ? 2 : cycles;
>> +
>> + mmtu->compvalue = cycles;
>> +
>> + mmtu->endvalue = mmtu->compvalue
>> + + readl((mmtu->base + MMTU_TCVAL_IDX));
>> +
>> + writel(MMTU_IRQ_MASK,
>> + (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_STAT_IDX));
>> +
>> + writel(mmtu->endvalue, (mmtu->base + MMTU_USED_MATCH_IDX));
>> +
>> + writel(MMTU_IRQ_MASK,
>> + (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_SET_ENA_IDX));
>> +
>> + /* the value has already expired */
>> + if ((mmtu->endvalue<= readl((mmtu->base + MMTU_TCVAL_IDX)))
>> +&& (mmtu->endvalue> mmtu->compvalue)
>> +&& !(readl((mmtu->base + MMTU_INT_OFFSET
>> + + MMTU_INT_STATUS_IDX))& MMTU_IRQ_MASK))
>> + writel(MMTU_IRQ_MASK, (mmtu->base + MMTU_INT_OFFSET
>> + + MMTU_INT_SET_STAT_IDX));
>> +
>> + return 0;
>> +}
>> +
>> +static int u6_mmtu_timer_init(int id, unsigned long reload,
>> + unsigned long prescale, int over_it)
>> +{
>> +
>> + struct mmtu_ctxt *mmtu = u6_mmtu_get_context(id);
>> +
>> + debug("mmtu_timer_init %d\n", id);
>> +
>> + /* Enable clock */
>> +/*
>> + u6_mmtu_clk_enable(id);
>> + clk mngt not available yet
>> + directly enable it
>> +*/
>> + {
>> + unsigned long flags;
>> + unsigned long reg;
>> + hw_raw_local_irq_save(flags);
>> + reg = readl(CGU_GATESC2_REG);
>> + reg |= 0x1<< 2;
>> + writel(reg, CGU_GATESC2_REG);
>> + hw_raw_local_irq_restore(flags);
>> + }
>> +
>> + /* Reset timer */
>> + /* reset control register */
>> + writel(0x0000, (mmtu->base + MMTU_CON_IDX));
>> + writel(0x0002, (mmtu->base + MMTU_CON_IDX));
>> + /* reset control register */
>> + writel(0x0000, (mmtu->base + MMTU_CON_IDX));
>> +
>> + /* clear whole enable irq register */
>> + writel(0xFF, (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_ENA_IDX));
>> + /* clear whole status register */
>> + writel(0xFF, (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_STAT_IDX));
>> +
>> + /* reset pre-scaler reload register */
>> + writel(0x00000000, (mmtu->base + MMTU_PRESCALER_IDX));
>> +
>> + /* reset match control register */
>> + writel(0x0000, (mmtu->base + MMTU_MATCH_CON_IDX));
>> + /* reset match 0 register */
>> + writel(0x00000000, (mmtu->base + MMTU_MATCH0_IDX));
>> + /* reset match 1 register */
>> + writel(0x00000000, (mmtu->base + MMTU_MATCH1_IDX));
>> +
>> + /* Initialize timer */
>> + writel(prescale - 1, (mmtu->base + MMTU_PRESCALER_IDX));
>> + /* power of 2 system clock */
>> + writel(reload, (mmtu->base + MMTU_MATCH0_IDX));
>> +
>> + /* enable counter register */
>> + writel(0x0001, (mmtu->base + MMTU_CON_IDX));
>> +
>> + /* clear whole status register */
>> + writel(0xFF, (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_STAT_IDX));
>> +
>> + if (id == 0)
>> + setup_irq(IRQ_MMTU,&u6_mmtu_timer_irq);
>> +
>> + /* Disable clock */
>> +#ifndef U6_MMTU_CLOCK_SOURCE
>> + u6_mmtu_clk_disable(id);
>> +#endif
>> + return 0;
>> +}
>> +
>> +/*** MMTU Clock event device ***/
>> +
>> +static int u6_mmtu_set_next_event(unsigned long cycles,
>> + struct clock_event_device *evt)
>> +{
>> + debug("mmtu_set_next_event %d\n", cycles);
>> + u6_mmtu_timer_start(cycles, 0);
>> +
>> + return 0;
>> +}
>> +
>> +static void u6_mmtu_set_mode(enum clock_event_mode mode,
>> + struct clock_event_device *evt)
>> +{
>> + struct mmtu_ctxt *mmtu = u6_mmtu_get_context(0);
>> + unsigned long reg;
>> +
>> + debug("mmtu_set_mode %d\n", mode);
>> +
>> + switch (mode) {
>> + case CLOCK_EVT_MODE_UNUSED:
>> + writel(MMTU_IRQ_MASK,
>> + (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_ENA_IDX));
>> + writel(MMTU_IRQ_MASK,
>> + (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_STAT_IDX));
>> +
>> + reg = readl((mmtu->base + MMTU_TCVAL_IDX));
>> + writel(reg - 1, (mmtu->base + MMTU_USED_MATCH_IDX));
>> +
>> +#ifndef U6_MMTU_CLOCK_SOURCE
>> + u6_mmtu_clk_disable(0);
>> +
>> + if (mmtu->clk != NULL)
>> + clk_put(mmtu->clk);
>> +#endif
>> + mmtu->autoreload = 0;
>> + break;
>> + case CLOCK_EVT_MODE_SHUTDOWN:
>> + mmtu->autoreload = 0;
>> +
>> + if (mmtu->clk == NULL) {
>> + mmtu->clk = clk_get(0, "MMTU");
>> + if (IS_ERR(mmtu->clk))
>> + mmtu->clk = NULL;
>> + }
>> +
>> + writel(MMTU_IRQ_MASK,
>> + (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_STAT_IDX));
>> + writel(MMTU_IRQ_MASK,
>> + (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_SET_ENA_IDX));
>> + case CLOCK_EVT_MODE_ONESHOT:
>> + case CLOCK_EVT_MODE_RESUME:
>> + mmtu->autoreload = 0;
>> + break;
>> + case CLOCK_EVT_MODE_PERIODIC:
>> + writel(MMTU_IRQ_MASK,
>> + (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_SET_ENA_IDX));
>> + mmtu->autoreload = 1;
>> + break;
>> + }
>> +}
>> +
>> +static void u6_clockevent_init_mmtu(void)
>> +{
>> + printk(PKMOD "clockevent_init_mmtu\n");
>> +
>> + /* prescale 13Mhz -> 1Mhz */
>> +#ifndef U6_MMTU_CLOCK_SOURCE
>> + u6_mmtu_timer_init(0, 0, (MMTU_SYS_FRQ / MMTU_ROOT_FRQ), 0);
>> +#endif
>> +
>> +/* issue it is shorter than reality and generates spurious irq */
>> +/* clockevent_mmtu.mult = div_sc(MMTU_ROOT_FRQ, NSEC_PER_SEC,
>> + * clockevent_mmtu.shift) + 1;*/
>> + clockevent_mmtu.mult =
>> + div_sc(MMTU_ROOT_FRQ, NSEC_PER_SEC, clockevent_mmtu.shift);
>> +
>> +/* clockevent_mmtu.max_delta_ns = div_sc(RELOAD_COUNTER_MMTU,
>> + * clockevent_mmtu.mult, clockevent_mmtu.shift);*/
>> +/* In fact it is wider than the 32bits variable !!! */
>> + clockevent_mmtu.max_delta_ns = 0xFFFFFFFF;
>> +
>> +/* MMTU HW limitation: match register can't be set w/ tcval+1 */
>> +/* clockevent_mmtu.min_delta_ns = div_sc(1, clockevent_mmtu.mult,
>> + * clockevent_mmtu.shift)+1;*/
>> + clockevent_mmtu.min_delta_ns =
>> + div_sc(2, clockevent_mmtu.mult, clockevent_mmtu.shift) + 1;
>> + /* avoid to much timer interrupt with 10us min between 2 irq */
>> + if (clockevent_mmtu.min_delta_ns< 10000)
>> + clockevent_mmtu.min_delta_ns = 10000;
>> + else if (clockevent_mmtu.max_delta_ns< 10000)
>> + clockevent_mmtu.min_delta_ns = clockevent_mmtu.max_delta_ns>>1;
>> +
>> + clockevent_mmtu.cpumask = get_cpu_mask(0);
>> + clockevents_register_device(&clockevent_mmtu);
>> +
>> + u6_mmtu_set_next_event(MMTU_ROOT_FRQ / HZ,&clockevent_mmtu);
>> +}
>> +
>> +/*** MMTU Clock source device ***/
>> +#ifdef U6_MMTU_CLOCK_SOURCE
>> +
>> +static cycle_t u6_mmtu_read(struct clocksource *source)
>> +{
>> + struct mmtu_ctxt *mmtu = u6_mmtu_get_context(0);
>> +
>> + return readl((mmtu->base + MMTU_TCVAL_IDX))& source->mask;
>> +}
>>
> Clocksource read functions don't require the value masking.
>
OK
>
>> +
>> +static void u6_clocksource_init_mmtu(void)
>> +{
>> + printk(PKMOD "clocksource_init_mmtu\n");
>> +
>> + if (MMTU_ROOT_FRQ>= 1000000)
>> + clocksource_mmtu.mult =
>> + clocksource_khz2mult((MMTU_ROOT_FRQ / 1000),
>> + clocksource_mmtu.shift);
>> + else
>> + clocksource_mmtu.mult = clocksource_hz2mult((MMTU_ROOT_FRQ),
>> + clocksource_mmtu.shift);
>> +
>> + u6_mmtu_timer_init(0, 0, (MMTU_SYS_FRQ / MMTU_ROOT_FRQ), 0);
>> +
>> + clocksource_register(&clocksource_mmtu);
>> +}
>> +
>> +unsigned long long u6_mmtu_time(void)
>> +{
>> + unsigned long long ticks64 = u6_mmtu_read(&clocksource_mmtu);
>> +
>> + return (ticks64 * clocksource_mmtu.mult)>> clocksource_mmtu.shift;
>> +}
>>
> Can you explain the purpose of this function please, and why you export
> the ticks and value from this function via sysfs?
>
It's for debug purpose, can be removed for standard kernel.
>
>> +#endif
>> +
>> +/*** SysFs interface ***/
>> +/***********************/
>> +#ifdef CONFIG_U6_POWER_SYSFS
>> +
>> +/*** Clock event sysfs interface **/
>> +
>> +#define shows_one_evt(file_name, object) \
>> +static ssize_t show_##file_name##_evt \
>> +(struct kobject *kobj, char *buf) \
>> +{ \
>> + return sprintf(buf, "%s\n", clockevent_mmtu.object); \
>> +}
>> +
>> +#define showu_one_evt(file_name, object) \
>> +static ssize_t show_##file_name##_evt \
>> +(struct kobject *kobj, char *buf) \
>> +{ \
>> + return sprintf(buf, "%u\n", clockevent_mmtu.object); \
>> +}
>> +
>> +#define showlu_one_evt(file_name, object) \
>> +static ssize_t show_##file_name##_evt \
>> +(struct kobject *kobj, char *buf) \
>> +{ \
>> + return sprintf(buf, "%lu\n", clockevent_mmtu.object); \
>> +}
>> +
>> +#define storelu_one_evt(file_name, object) \
>> +static ssize_t store_##file_name##_evt \
>> +(struct kobject *kobj, const char *buf, size_t size) \
>> +{ \
>> + unsigned long object; \
>> + strict_strtoul(buf, 10,&object); \
>> + clockevent_mmtu.object = object; \
>> + return size; \
>> +}
>> +
>> +#define showx_one_evt(file_name, object) \
>> +static ssize_t show_##file_name##_evt \
>> +(struct kobject *kobj, char *buf) \
>> +{ \
>> + return sprintf(buf, "0x%x\n", clockevent_mmtu.object); \
>> +}
>> +
>> +shows_one_evt(name, name);
>> +showu_one_evt(rating, rating);
>> +showlu_one_evt(mult, mult);
>> +#ifdef CONFIG_U6_TIMER_TUNE
>> +storelu_one_evt(mult, mult);
>> +#endif
>> +showu_one_evt(shift, shift);
>> +showx_one_evt(features, features);
>> +showlu_one_evt(min_delta_ns, min_delta_ns);
>> +showlu_one_evt(max_delta_ns, max_delta_ns);
>>
> Why do you want all these parameters exported to userspace? Maybe you
> should discuss your requirement here with the generic time people
> before submitting it?
>
For debug only => removed all
I'll fix this patch next week and send it to the list.
Regards,
Philippe
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 2/6] U6715 clocks gating management U6 clock generic driver & U6715 cgu clock specific (V2)
2010-06-24 14:14 ` Russell King - ARM Linux
@ 2010-07-05 7:09 ` Philippe Langlais
0 siblings, 0 replies; 17+ messages in thread
From: Philippe Langlais @ 2010-07-05 7:09 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
OK for all your remarks, we have changed our implementation to follow
the new one using clkdev.
The new patch will be sent today.
Regards
Philippe
On 06/24/10 16:14, Russell King - ARM Linux wrote:
> On Thu, May 27, 2010 at 10:27:28AM +0200, Philippe Langlais wrote:
>
>> +#if defined(DEBUG_CGU)
>> +#define debug(fmt, args...) \
>> + printk(PKMOD fmt, ## args)
>> +#else
>> +#define debug(fmt, args...)
>> +#endif
>>
> pr_debug?
>
>> +
>> +/**
>> + * U6 hw low level access clock functions
>> + **/
>> +static void u6_clk_disable(struct clk *clk);
>> +static int u6_clk_enable(struct clk *clk);
>> +
>> +/**
>> + * HW enable clock function.
>> + **/
>> +
>> +static int u67xx_cgu_enable_fake_clock(struct clk *clk)
>> +{
>> + debug("u67xx_cgu_enable_fake_clock for %s\n", clk->name);
>> + return 0;
>> +}
>> +
>> +static int u67xx_cgu_enable_hw_clock(struct clk *clk)
>> +{
>> + unsigned long value;
>> + debug("u67xx_cgu_enable_hw_clock for %s\n", clk->name);
>> +
>> + if (unlikely(clk->enable_reg == 0)) {
>>
> These are pointers. 0 is an integer. Use NULL. Check your code with
> sparse and you'll get warnings for these things.
>
>
>> +/*** Basic clocks ***/
>> +
>> +/* Base external input clocks */
>> +static struct clk func_32k_ck = {
>> + .name = "func_32k_ck",
>> + .rate = 32000,
>> + .flags = RATE_FIXED | ALWAYS_ENABLED,
>> + .usecount = 1,
>> +};
>>
> Don't put data definitions in header files.
>
>
>> +static struct clk *onchip_clks[] = {
>> + /* external root sources */
>> + &func_32k_ck,
>> + &osc_ck,
>> + &sys_ck,
>> + &sc_ck,
>> + &fix_ck,
>> + &tv_ck,
>> +#ifndef U6_OPTIMIZED_TREE
>> + &dsp2_ck,
>> +#endif
>> + &sdm_ck,
>> + &arm_ck,
>> + &hclk_ck,
>> + &hclk2_ck,
>> + &pclk1_ck,
>> + &pclk2_ck,
>> + &tvclk_ck,
>>
> This all looks very much like it was copied from the OMAP code as of about
> a year ago. The OMAP code has moved forwards with lots of improvements,
> including using clkdev to eliminate the disgusting SoC specific code from
> drivers (which clkdev is there to prevent.)
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 3/6] U6715 gpio platform driver This driver is U6 platform generic (V2)
2010-06-24 14:26 ` Russell King - ARM Linux
@ 2010-07-05 7:14 ` Philippe Langlais
0 siblings, 0 replies; 17+ messages in thread
From: Philippe Langlais @ 2010-07-05 7:14 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
I' have fix in the following patch all your comments.
Regards,
Philippe
On 06/24/10 16:26, Russell King - ARM Linux wrote:
> On Thu, May 27, 2010 at 10:27:29AM +0200, Philippe Langlais wrote:
>
>> Signed-off-by: Philippe Langlais<philippe.langlais@stericsson.com>
>> ---
>> arch/arm/mach-u67xx/board_u67xx_wavex.c | 469 ++++++++++++++++++++
>> arch/arm/mach-u67xx/devices.c | 12 +-
>> arch/arm/plat-u6xxx/Makefile | 2 +-
>> arch/arm/plat-u6xxx/gpio.c | 716 +++++++++++++++++++++++++++++++
>> arch/arm/plat-u6xxx/include/mach/gpio.h | 396 +++++++++++++++++
>> 5 files changed, 1588 insertions(+), 7 deletions(-)
>> create mode 100644 arch/arm/plat-u6xxx/gpio.c
>> create mode 100644 arch/arm/plat-u6xxx/include/mach/gpio.h
>>
>> diff --git a/arch/arm/mach-u67xx/board_u67xx_wavex.c b/arch/arm/mach-u67xx/board_u67xx_wavex.c
>> index 2a806e7..a21e465 100644
>> --- a/arch/arm/mach-u67xx/board_u67xx_wavex.c
>> +++ b/arch/arm/mach-u67xx/board_u67xx_wavex.c
>> @@ -24,6 +24,474 @@
>> #include<asm/mach/arch.h>
>> #include<mach/irqs.h>
>> #include<mach/timer.h>
>> +#include<mach/gpio.h>
>>
> linux/gpio.h
>
>
>> +
>> +#include<mach/scon.h>
>> +
>> +/**
>> + * SCON initial settings
>> + * Allows to define the PIN multiplexing for all the platform (Linux and Modem)
>> + */
>> +struct u6_scon_config u6_scon_init_config[SCON_REGISTER_NB] = {
>> + {
>> + (void __iomem *) SCON_SYSMUX0_REG,
>>
> IOMEM() to eliminate the cast?
>
>
>> +/* GPIO def settings to avoid HW issue */
>> +struct u6_gpio_config u6_gpio_init_config[] = {
>> + /* GPIO A bank */
>> + {
>> + .gpio = GPIO_A5,
>> + .dir = GPIO_DIR_OUTPUT ,
>>
> Unnecessary spaces between 'OUTPUT' and ','
>
>
>> + .value = 1,
>> + },
>> + {
>> + .gpio = GPIO_A6,
>> + .dir = GPIO_DIR_OUTPUT ,
>> + .value = 1,
>> + },
>> + {
>> + .gpio = GPIO_A7,
>> + .dir = GPIO_DIR_OUTPUT ,
>> + .value = 0,
>> + },
>> + {
>> + .gpio = GPIO_A8,
>> + .dir = GPIO_DIR_OUTPUT ,
>> + .value = 1,
>> + },
>> + {
>> + .gpio = GPIO_A9,
>> + .dir = GPIO_DIR_OUTPUT ,
>> + .value = 1,
>> + },
>> + {
>> + .gpio = GPIO_A13,
>> + .dir = GPIO_DIR_OUTPUT ,
>> + .value = 0,
>> + },
>> + {
>> + .gpio = GPIO_A17,
>> + .dir = GPIO_DIR_OUTPUT ,
>> + .value = 0,
>> + },
>> + {
>> + .gpio = GPIO_A21,
>> + .dir = GPIO_DIR_OUTPUT ,
>> + .value = 0,
>> + },
>> + {
>> + .gpio = GPIO_A23,
>> + .dir = GPIO_DIR_OUTPUT ,
>> + .value = 0,
>> + },
>> + {
>> + .gpio = GPIO_A24,
>> + .dir = GPIO_DIR_OUTPUT ,
>> + .value = 1,
>> + },
>> + {
>> + .gpio = GPIO_A25,
>> + .dir = GPIO_DIR_OUTPUT ,
>> + .value = 0,
>> + },
>> + {
>> + .gpio = GPIO_A30,
>> + .dir = GPIO_DIR_OUTPUT ,
>> + .value = 0,
>> + },
>> + /* GPIO B bank */
>> + /* GPIO C bank */
>> + /* GPIO D bank */
>> + {
>> + .gpio = GPIO_D0,
>> + .dir = GPIO_DIR_OUTPUT ,
>> + .value = 0,
>> + },
>> + {
>> + .gpio = GPIO_D24,
>> + .dir = GPIO_DIR_OUTPUT ,
>> + .value = 0,
>> + },
>> + {
>> + .gpio = GPIO_D29,
>> + .dir = GPIO_DIR_OUTPUT ,
>> + .value = 0,
>> + },
>> + /* GPIO E bank */
>> + {
>> + .gpio = GPIO_E31,
>> + .dir = GPIO_DIR_OUTPUT ,
>> + .value = 0,
>> + },
>> + /* GPIO F bank */
>> + {
>> + .gpio = GPIO_F0,
>> + .dir = GPIO_DIR_OUTPUT ,
>> + .value = 0,
>> + },
>> + {
>> + .gpio = GPIO_F1,
>> + .dir = GPIO_DIR_OUTPUT ,
>> + .value = 0,
>> + },
>> + {
>> + .gpio = GPIO_F2,
>> + .dir = GPIO_DIR_OUTPUT ,
>> + .value = 0,
>> + },
>> + {
>> + .gpio = GPIO_F9,
>> + .dir = GPIO_DIR_OUTPUT ,
>> + .value = 0,
>> + }
>> +};
>> +
>> +u32 gpio_to_configure = ARRAY_SIZE(u6_gpio_init_config);
>>
>> /* List of board specific devices */
>> static struct platform_device *devices[] __initdata = {
>> @@ -31,6 +499,7 @@ static struct platform_device *devices[] __initdata = {
>>
>> void __init u67xx_init(void)
>> {
>> + u6_gpio_init();
>> /* Add specific board devices */
>> platform_add_devices(devices, ARRAY_SIZE(devices));
>> }
>> diff --git a/arch/arm/mach-u67xx/devices.c b/arch/arm/mach-u67xx/devices.c
>> index 0ead380..8e812fb 100644
>> --- a/arch/arm/mach-u67xx/devices.c
>> +++ b/arch/arm/mach-u67xx/devices.c
>> @@ -48,12 +48,12 @@ unsigned char extint_to_gpio[NR_EXTINT] = {
>> EXPORT_SYMBOL(extint_to_gpio);
>>
>> struct gpio_bank u6_gpio_bank[6] = {
>> - {(void __iomem *)GPIOA_PINS_REG, (void __iomem *)SCON_SYSMUX0_REG},
>> - {(void __iomem *)GPIOB_PINS_REG, (void __iomem *)SCON_SYSMUX2_REG},
>> - {(void __iomem *)GPIOC_PINS_REG, (void __iomem *)SCON_SYSMUX4_REG},
>> - {(void __iomem *)GPIOD_PINS_REG, (void __iomem *)SCON_SYSMUX6_REG},
>> - {(void __iomem *)GPIOE_PINS_REG, (void __iomem *)SCON_SYSMUX8_REG},
>> - {(void __iomem *)GPIOF_PINS_REG, (void __iomem *)SCON_SYSMUX10_REG},
>> + {GPIOA_PINS_REG, SCON_SYSMUX0_REG},
>> + {GPIOB_PINS_REG, SCON_SYSMUX2_REG},
>> + {GPIOC_PINS_REG, SCON_SYSMUX4_REG},
>> + {GPIOD_PINS_REG, SCON_SYSMUX6_REG},
>> + {GPIOE_PINS_REG, SCON_SYSMUX8_REG},
>> + {GPIOF_PINS_REG, SCON_SYSMUX10_REG},
>> };
>>
>> static struct gpio_data u6_gpio_data = {
>> diff --git a/arch/arm/plat-u6xxx/Makefile b/arch/arm/plat-u6xxx/Makefile
>> index afdf82b..3d6898e 100644
>> --- a/arch/arm/plat-u6xxx/Makefile
>> +++ b/arch/arm/plat-u6xxx/Makefile
>> @@ -3,6 +3,6 @@
>> #
>>
>> # Common support
>> -obj-y := io.o irq.o clock.o
>> +obj-y := io.o irq.o clock.o gpio.o
>>
>> obj-$(CONFIG_U6_MTU_TIMER) += timer.o
>> diff --git a/arch/arm/plat-u6xxx/gpio.c b/arch/arm/plat-u6xxx/gpio.c
>> new file mode 100644
>> index 0000000..40e25fc
>> --- /dev/null
>> +++ b/arch/arm/plat-u6xxx/gpio.c
>> @@ -0,0 +1,716 @@
>> +/*
>> + * linux/arch/arm/plat-u6xxx/gpio.c
>> + *
>> + * Copyright (C) ST-Ericsson SA 2010
>> + * Author: Loic Pallardy<loic.pallardy@stericsson.com> for ST-Ericsson.
>> + * License terms: GNU General Public License (GPL), version 2
>> + * Support functions for GPIO
>> + */
>> +
>> +#include<linux/init.h>
>> +#include<linux/kernel.h>
>> +#include<linux/module.h>
>> +#include<linux/platform_device.h>
>> +#include<linux/sched.h>
>> +#include<linux/interrupt.h>
>> +#include<linux/ptrace.h>
>> +#include<linux/sysdev.h>
>> +#include<linux/err.h>
>> +#include<linux/clk.h>
>> +#include<linux/io.h>
>> +
>> +#include<mach/hardware.h>
>> +#include<asm/irq.h>
>> +#include<mach/irqs.h>
>> +#include<mach/gpio.h>
>> +#include<asm/mach/irq.h>
>> +#include<mach/scon.h>
>>
> asm/ before mach/.
>
>
>> +
>> +/*
>> + * PN5220 GPIO/MUX registers
>> + * defined in asm/arch/registers.h
>> + */
>> +
>> +#define U6_GPIO_PINS_OFFSET 0
>> +#define U6_GPIO_OUTPUT_OFFSET 4
>> +#define U6_GPIO_DIR_OFFSET 8
>> +
>> +#define U6_MUX2_OFFSET 4
>> +
>> +static struct gpio_bank *gpio_bank_desc;
>> +static int gpio_bank_count;
>> +
>> +static inline struct gpio_bank *get_gpio_bank(int gpio)
>> +{
>> + /* 32 GPIOs per bank */
>> + return&(gpio_bank_desc[gpio>> 5]);
>> +}
>> +
>> +static inline int get_gpio_index(int gpio)
>> +{
>> + return gpio& 0x1f;
>> +}
>> +
>> +static int check_gpio(int gpio)
>> +{
>> + int retval = ((unsigned int)gpio)< GPIO_COUNT;
>> + if (unlikely(!retval)) {
>> + printk(KERN_ERR "u6-gpio: invalid GPIO %d\n", gpio);
>> + dump_stack();
>> + }
>>
> return WARN_ON((unsigned int)gpio< GPIO_COUNT);
>
> or use WARN(condition, format) if you want a custom message.
>
>
>> +static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
>> +{
>> + u32 reg = bank->gpio_base;
>> + u32 l;
>> +
>> + /* select direction register */
>> + reg += U6_GPIO_DIR_OFFSET;
>> +
>> + /* in register 0 = input, 1 = output */
>> + l = inl(reg);
>>
> inl/outl are for PCI/ISA based IO accesses/emulation. I don't think your
> GPIO block is a PCI/ISA peripheral, so it should not be using these macros.
>
>
>> +static int initialized;
>> +
>> +static int __init u6_gpio_probe(struct platform_device *pdev)
>> +{
>> + int i, j;
>> + int gpio = 0;
>> + struct gpio_bank *bank;
>> + struct gpio_data *data = pdev->dev.platform_data;
>> + unsigned long flags;
>> +
>> + initialized = 1;
>>
> Why is this here when you're really wanting to prevent the platform
> driver structure being registered more than once?
>
>
>> +
>> + printk(KERN_INFO "U6 GPIO\n");
>> + gpio_bank_desc = data->gpio_bank_desc;
>> + gpio_bank_count = data->nb_banks;
>> +
>> + for (i = 0; i< gpio_bank_count; i++) {
>> + int gpio_count = 32; /* 32 GPIO per bank */
>> + bank =&gpio_bank_desc[i];
>> + bank->reserved_map = 0;
>> + spin_lock_init(&bank->lock);
>> +
>> + bank->chip.request = u6_gpio_acquire;
>> + bank->chip.free = u6_gpio_release;
>> + bank->chip.direction_input = gpio_input;
>> + bank->chip.get = gpio_get;
>> + bank->chip.direction_output = gpio_output;
>> + bank->chip.set = gpio_set;
>> + bank->chip.to_irq = gpio_2irq;
>> + bank->chip.label = "gpio";
>> + bank->chip.base = gpio;
>> + gpio += gpio_count;
>> +
>> + bank->chip.ngpio = gpio_count;
>> +
>> + gpiochip_add(&bank->chip);
>> +
>> + }
>> +
>> + /* for extint */
>> + for (j = IRQ_COUNT; j< IRQ_COUNT + NR_EXTINT; j++) {
>> + set_irq_chip(j,&gpio_irq_chip);
>> + set_irq_handler(j, handle_simple_irq);
>> + set_irq_flags(j, IRQF_VALID);
>> + }
>> +
>> + hw_raw_local_irq_save(flags);
>> + /* mask all EXT IRQ sources before registring handler */
>> + /* read status */
>> + j = inl(EXTINT_STATUS_REG)& inl(EXTINT_ENABLE3_REG);
>> + /* clear IRQ source(s) */
>> + outl(j, EXTINT_STATUS_REG);
>> +
>> + outl(0, EXTINT_ENABLE3_REG);
>> +
>> + /* set irq in low level */
>> + set_irq_type(IRQ_EXTINT3, IRQF_TRIGGER_LOW);
>> +
>> + /* chained GPIO-IRQ on EXTINT3 */
>> + set_irq_chained_handler(IRQ_EXTINT3, gpio_irq_handler);
>> + hw_raw_local_irq_restore(flags);
>> +
>> + return 0;
>> +}
>> +
>> +static struct platform_driver u6_gpio_driver = {
>> + .probe = u6_gpio_probe,
>> + .remove = NULL,
>> + .suspend = NULL,
>> + .resume = NULL,
>> + .driver = {
>> + .name = "u6-gpio",
>> + },
>> +};
>> +
>> +static struct sysdev_class u6_gpio_sysclass = {
>> + .name = "gpio",
>> + .suspend = 0, /*u6_gpio_suspend, */
>> + .resume = 0, /*u6_gpio_resume, */
>> +};
>> +
>> +static struct sys_device u6_gpio_device = {
>> + .id = 0,
>> + .cls =&u6_gpio_sysclass,
>> +};
>> +
>> +/*
>> + * This may get called early from board specific init
>> + * for boards that have interrupts routed via FPGA.
>> + */
>> +int u6_gpio_init(void)
>> +{
>> + if (!initialized)
>> + return platform_driver_register(&u6_gpio_driver);
>>
> Shouldn't this set 'initialized' once the platform driver has been
> registered to prevent the platform driver being registered again?
>
>
>> + else
>> + return 0;
>> +}
>> +
>> +static int __init u6_gpio_sysinit(void)
>> +{
>> + int ret = 0;
>> +
>> + if (!initialized)
>> + ret = u6_gpio_init();
>>
> Why not just call u6_gpio_init(), which handles the special case anyway?
>
>
>> +
>> + if (ret == 0) {
>> + ret = sysdev_class_register(&u6_gpio_sysclass);
>> + if (ret == 0)
>> + ret = sysdev_register(&u6_gpio_device);
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +arch_initcall(u6_gpio_sysinit);
>> diff --git a/arch/arm/plat-u6xxx/include/mach/gpio.h b/arch/arm/plat-u6xxx/include/mach/gpio.h
>> new file mode 100644
>> index 0000000..a205f1c
>> --- /dev/null
>> +++ b/arch/arm/plat-u6xxx/include/mach/gpio.h
>> @@ -0,0 +1,396 @@
>> +/*
>> + * linux/arch/arm/plat-u6xxx/include/mach/gpio.h
>> + *
>> + * Copyright (C) ST-Ericsson SA 2010
>> + * Author: Loic Pallardy<loic.pallardy@stericsson.com> for ST-Ericsson.
>> + * License terms: GNU General Public License (GPL), version 2
>> + * GPIO handling defines and functions
>> + */
>> +
>> +#ifndef __ASM_PLAT_U6_GPIO_H
>> +#define __ASM_PLAT_U6_GPIO_H
>> +
>> +#include<linux/io.h>
>> +#include<mach/hardware.h>
>> +#include<mach/irqs.h>
>> +#include<mach/gpio.h>
>>
> Recursive include of mach/gpio.h
>
>
>> +
>> +#include<linux/errno.h>
>> +#include<asm-generic/gpio.h>
>>
> linux/ includes before asm and mach includes.
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 5/6] U6715 8250 serial like driver
2010-06-24 14:31 ` Russell King - ARM Linux
@ 2010-07-05 7:39 ` Philippe Langlais
0 siblings, 0 replies; 17+ messages in thread
From: Philippe Langlais @ 2010-07-05 7:39 UTC (permalink / raw)
To: linux-arm-kernel
Hi
On 06/24/10 16:31, Russell King - ARM Linux wrote:
> On Thu, May 27, 2010 at 10:27:31AM +0200, Philippe Langlais wrote:
>
>> Some modifications in 16550A/8250 serial driver
>> and clock management specificity
>>
> Can't say much about this; you need to get people interested in serial to
> review this. The comments about header file ordering apply.
>
>
>> @@ -199,10 +199,16 @@ static const struct serial8250_config uart_config[] = {
>> },
>> [PORT_16550A] = {
>> .name = "16550A",
>> +#if defined(CONFIG_SERIAL_8250_U6)
>> + .fifo_size = 64,
>> + .tx_loadsz = 64,
>> + .flags = UART_CAP_FIFO | UART_CAP_AFE,
>>
> If you have auto flow control, then you don't have a 16550A. You have
> something that is compatible with a 16550A - maybe it's more closely
> related to a 16750?
>
I'll send our serial driver to the LKML and discuss about that.
Regards
Philippe
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2010-07-05 7:39 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-27 8:27 U6/U6715 ARM architecture files, 2nd try Philippe Langlais
2010-05-27 8:27 ` [PATCH 1/6] U6/U6715 ARM architecture files Philippe Langlais
2010-06-24 14:08 ` Russell King - ARM Linux
2010-06-25 13:34 ` Philippe Langlais
2010-05-27 8:27 ` [PATCH 2/6] U6715 clocks gating management U6 clock generic driver & U6715 cgu clock specific (V2) Philippe Langlais
2010-06-24 14:14 ` Russell King - ARM Linux
2010-07-05 7:09 ` Philippe Langlais
2010-05-27 8:27 ` [PATCH 3/6] U6715 gpio platform driver This driver is U6 platform generic (V2) Philippe Langlais
2010-06-24 14:26 ` Russell King - ARM Linux
2010-07-05 7:14 ` Philippe Langlais
2010-05-27 8:27 ` [PATCH 4/6] U6715 platform serial driver It's a generic driver for all U6 platform (V2) Philippe Langlais
2010-06-24 14:17 ` Russell King - ARM Linux
2010-05-27 8:27 ` [PATCH 5/6] U6715 8250 serial like driver Philippe Langlais
2010-06-24 14:31 ` Russell King - ARM Linux
2010-07-05 7:39 ` Philippe Langlais
2010-05-27 8:27 ` [PATCH 6/6] U6715 Default configuration for ST-Ericsson reference design boards Philippe Langlais
-- strict thread matches above, loose matches on Subject: below --
2010-04-28 7:32 U6/U6715 ARM architecture files, 1rst try Philippe Langlais
2010-04-28 7:32 ` [PATCH 3/6] U6715 gpio platform driver This driver is U6 platform generic (V2) Philippe Langlais
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).