diff options
307 files changed, 12275 insertions, 3239 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index b527bf5701c9..a19a5266d5fc 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -720,9 +720,11 @@ config ARCH_S5PC100 | |||
720 | config ARCH_S5PV210 | 720 | config ARCH_S5PV210 |
721 | bool "Samsung S5PV210/S5PC110" | 721 | bool "Samsung S5PV210/S5PC110" |
722 | select CPU_V7 | 722 | select CPU_V7 |
723 | select ARCH_SPARSEMEM_ENABLE | ||
723 | select GENERIC_GPIO | 724 | select GENERIC_GPIO |
724 | select HAVE_CLK | 725 | select HAVE_CLK |
725 | select ARM_L1_CACHE_SHIFT_6 | 726 | select ARM_L1_CACHE_SHIFT_6 |
727 | select ARCH_HAS_CPUFREQ | ||
726 | select ARCH_USES_GETTIMEOFFSET | 728 | select ARCH_USES_GETTIMEOFFSET |
727 | select HAVE_S3C2410_I2C | 729 | select HAVE_S3C2410_I2C |
728 | select HAVE_S3C_RTC | 730 | select HAVE_S3C_RTC |
@@ -733,9 +735,13 @@ config ARCH_S5PV210 | |||
733 | config ARCH_S5PV310 | 735 | config ARCH_S5PV310 |
734 | bool "Samsung S5PV310/S5PC210" | 736 | bool "Samsung S5PV310/S5PC210" |
735 | select CPU_V7 | 737 | select CPU_V7 |
738 | select ARCH_SPARSEMEM_ENABLE | ||
736 | select GENERIC_GPIO | 739 | select GENERIC_GPIO |
737 | select HAVE_CLK | 740 | select HAVE_CLK |
738 | select GENERIC_CLOCKEVENTS | 741 | select GENERIC_CLOCKEVENTS |
742 | select HAVE_S3C_RTC | ||
743 | select HAVE_S3C2410_I2C | ||
744 | select HAVE_S3C2410_WATCHDOG | ||
739 | help | 745 | help |
740 | Samsung S5PV310 series based systems | 746 | Samsung S5PV310 series based systems |
741 | 747 | ||
@@ -1662,6 +1668,12 @@ if ARCH_HAS_CPUFREQ | |||
1662 | 1668 | ||
1663 | source "drivers/cpufreq/Kconfig" | 1669 | source "drivers/cpufreq/Kconfig" |
1664 | 1670 | ||
1671 | config CPU_FREQ_IMX | ||
1672 | tristate "CPUfreq driver for i.MX CPUs" | ||
1673 | depends on ARCH_MXC && CPU_FREQ | ||
1674 | help | ||
1675 | This enables the CPUfreq driver for i.MX CPUs. | ||
1676 | |||
1665 | config CPU_FREQ_SA1100 | 1677 | config CPU_FREQ_SA1100 |
1666 | bool | 1678 | bool |
1667 | 1679 | ||
diff --git a/arch/arm/configs/mx51_defconfig b/arch/arm/configs/mx51_defconfig index 163cfee7644c..5c7a87260fab 100644 --- a/arch/arm/configs/mx51_defconfig +++ b/arch/arm/configs/mx51_defconfig | |||
@@ -82,6 +82,7 @@ CONFIG_FEC=y | |||
82 | CONFIG_INPUT_FF_MEMLESS=m | 82 | CONFIG_INPUT_FF_MEMLESS=m |
83 | # CONFIG_INPUT_MOUSEDEV_PSAUX is not set | 83 | # CONFIG_INPUT_MOUSEDEV_PSAUX is not set |
84 | CONFIG_INPUT_EVDEV=y | 84 | CONFIG_INPUT_EVDEV=y |
85 | CONFIG_KEYBOARD_GPIO=y | ||
85 | CONFIG_INPUT_EVBUG=m | 86 | CONFIG_INPUT_EVBUG=m |
86 | CONFIG_MOUSE_PS2=m | 87 | CONFIG_MOUSE_PS2=m |
87 | CONFIG_MOUSE_PS2_ELANTECH=y | 88 | CONFIG_MOUSE_PS2_ELANTECH=y |
diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h index 6bcba48800fe..cc42d5fdee17 100644 --- a/arch/arm/include/asm/hardware/cache-l2x0.h +++ b/arch/arm/include/asm/hardware/cache-l2x0.h | |||
@@ -21,9 +21,6 @@ | |||
21 | #define __ASM_ARM_HARDWARE_L2X0_H | 21 | #define __ASM_ARM_HARDWARE_L2X0_H |
22 | 22 | ||
23 | #define L2X0_CACHE_ID 0x000 | 23 | #define L2X0_CACHE_ID 0x000 |
24 | #define L2X0_CACHE_ID_PART_MASK (0xf << 6) | ||
25 | #define L2X0_CACHE_ID_PART_L210 (1 << 6) | ||
26 | #define L2X0_CACHE_ID_PART_L310 (3 << 6) | ||
27 | #define L2X0_CACHE_TYPE 0x004 | 24 | #define L2X0_CACHE_TYPE 0x004 |
28 | #define L2X0_CTRL 0x100 | 25 | #define L2X0_CTRL 0x100 |
29 | #define L2X0_AUX_CTRL 0x104 | 26 | #define L2X0_AUX_CTRL 0x104 |
@@ -53,6 +50,16 @@ | |||
53 | #define L2X0_LINE_DATA 0xF10 | 50 | #define L2X0_LINE_DATA 0xF10 |
54 | #define L2X0_LINE_TAG 0xF30 | 51 | #define L2X0_LINE_TAG 0xF30 |
55 | #define L2X0_DEBUG_CTRL 0xF40 | 52 | #define L2X0_DEBUG_CTRL 0xF40 |
53 | #define L2X0_PREFETCH_CTRL 0xF60 | ||
54 | #define L2X0_POWER_CTRL 0xF80 | ||
55 | #define L2X0_DYNAMIC_CLK_GATING_EN (1 << 1) | ||
56 | #define L2X0_STNDBY_MODE_EN (1 << 0) | ||
57 | |||
58 | /* Registers shifts and masks */ | ||
59 | #define L2X0_CACHE_ID_PART_MASK (0xf << 6) | ||
60 | #define L2X0_CACHE_ID_PART_L210 (1 << 6) | ||
61 | #define L2X0_CACHE_ID_PART_L310 (3 << 6) | ||
62 | #define L2X0_AUX_CTRL_WAY_SIZE_MASK (0x3 << 17) | ||
56 | 63 | ||
57 | #ifndef __ASSEMBLY__ | 64 | #ifndef __ASSEMBLY__ |
58 | extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask); | 65 | extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask); |
diff --git a/arch/arm/include/asm/memblock.h b/arch/arm/include/asm/memblock.h index fdbc43b2e6c0..b8da2e415e4e 100644 --- a/arch/arm/include/asm/memblock.h +++ b/arch/arm/include/asm/memblock.h | |||
@@ -1,13 +1,6 @@ | |||
1 | #ifndef _ASM_ARM_MEMBLOCK_H | 1 | #ifndef _ASM_ARM_MEMBLOCK_H |
2 | #define _ASM_ARM_MEMBLOCK_H | 2 | #define _ASM_ARM_MEMBLOCK_H |
3 | 3 | ||
4 | #ifdef CONFIG_MMU | ||
5 | extern phys_addr_t lowmem_end_addr; | ||
6 | #define MEMBLOCK_REAL_LIMIT lowmem_end_addr | ||
7 | #else | ||
8 | #define MEMBLOCK_REAL_LIMIT 0 | ||
9 | #endif | ||
10 | |||
11 | struct meminfo; | 4 | struct meminfo; |
12 | struct machine_desc; | 5 | struct machine_desc; |
13 | 6 | ||
diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h index 25f76bae57ab..fc1900925275 100644 --- a/arch/arm/include/asm/outercache.h +++ b/arch/arm/include/asm/outercache.h | |||
@@ -25,6 +25,9 @@ struct outer_cache_fns { | |||
25 | void (*inv_range)(unsigned long, unsigned long); | 25 | void (*inv_range)(unsigned long, unsigned long); |
26 | void (*clean_range)(unsigned long, unsigned long); | 26 | void (*clean_range)(unsigned long, unsigned long); |
27 | void (*flush_range)(unsigned long, unsigned long); | 27 | void (*flush_range)(unsigned long, unsigned long); |
28 | void (*flush_all)(void); | ||
29 | void (*inv_all)(void); | ||
30 | void (*disable)(void); | ||
28 | #ifdef CONFIG_OUTER_CACHE_SYNC | 31 | #ifdef CONFIG_OUTER_CACHE_SYNC |
29 | void (*sync)(void); | 32 | void (*sync)(void); |
30 | #endif | 33 | #endif |
@@ -50,6 +53,24 @@ static inline void outer_flush_range(unsigned long start, unsigned long end) | |||
50 | outer_cache.flush_range(start, end); | 53 | outer_cache.flush_range(start, end); |
51 | } | 54 | } |
52 | 55 | ||
56 | static inline void outer_flush_all(void) | ||
57 | { | ||
58 | if (outer_cache.flush_all) | ||
59 | outer_cache.flush_all(); | ||
60 | } | ||
61 | |||
62 | static inline void outer_inv_all(void) | ||
63 | { | ||
64 | if (outer_cache.inv_all) | ||
65 | outer_cache.inv_all(); | ||
66 | } | ||
67 | |||
68 | static inline void outer_disable(void) | ||
69 | { | ||
70 | if (outer_cache.disable) | ||
71 | outer_cache.disable(); | ||
72 | } | ||
73 | |||
53 | #else | 74 | #else |
54 | 75 | ||
55 | static inline void outer_inv_range(unsigned long start, unsigned long end) | 76 | static inline void outer_inv_range(unsigned long start, unsigned long end) |
@@ -58,6 +79,9 @@ static inline void outer_clean_range(unsigned long start, unsigned long end) | |||
58 | { } | 79 | { } |
59 | static inline void outer_flush_range(unsigned long start, unsigned long end) | 80 | static inline void outer_flush_range(unsigned long start, unsigned long end) |
60 | { } | 81 | { } |
82 | static inline void outer_flush_all(void) { } | ||
83 | static inline void outer_inv_all(void) { } | ||
84 | static inline void outer_disable(void) { } | ||
61 | 85 | ||
62 | #endif | 86 | #endif |
63 | 87 | ||
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index 1fc74cbd1a19..3a8fd5140d7a 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c | |||
@@ -78,7 +78,10 @@ void machine_kexec(struct kimage *image) | |||
78 | local_fiq_disable(); | 78 | local_fiq_disable(); |
79 | setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/ | 79 | setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/ |
80 | flush_cache_all(); | 80 | flush_cache_all(); |
81 | outer_flush_all(); | ||
82 | outer_disable(); | ||
81 | cpu_proc_fin(); | 83 | cpu_proc_fin(); |
84 | outer_inv_all(); | ||
82 | flush_cache_all(); | 85 | flush_cache_all(); |
83 | cpu_reset(reboot_code_buffer_phys); | 86 | cpu_reset(reboot_code_buffer_phys); |
84 | } | 87 | } |
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 1953e3d21abf..cead8893b46b 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S | |||
@@ -113,6 +113,7 @@ SECTIONS | |||
113 | *(.rodata.*) | 113 | *(.rodata.*) |
114 | *(.glue_7) | 114 | *(.glue_7) |
115 | *(.glue_7t) | 115 | *(.glue_7t) |
116 | . = ALIGN(4); | ||
116 | *(.got) /* Global offset table */ | 117 | *(.got) /* Global offset table */ |
117 | ARM_CPU_KEEP(PROC_INFO) | 118 | ARM_CPU_KEEP(PROC_INFO) |
118 | } | 119 | } |
diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c index b8bbd31aa850..84a5ba03f1ba 100644 --- a/arch/arm/mach-imx/mach-mx27_3ds.c +++ b/arch/arm/mach-imx/mach-mx27_3ds.c | |||
@@ -23,16 +23,20 @@ | |||
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
25 | #include <linux/input/matrix_keypad.h> | 25 | #include <linux/input/matrix_keypad.h> |
26 | #include <linux/irq.h> | ||
26 | #include <asm/mach-types.h> | 27 | #include <asm/mach-types.h> |
27 | #include <asm/mach/arch.h> | 28 | #include <asm/mach/arch.h> |
28 | #include <asm/mach/time.h> | 29 | #include <asm/mach/time.h> |
29 | #include <mach/hardware.h> | 30 | #include <mach/hardware.h> |
30 | #include <mach/common.h> | 31 | #include <mach/common.h> |
31 | #include <mach/iomux-mx27.h> | 32 | #include <mach/iomux-mx27.h> |
33 | #include <mach/mmc.h> | ||
32 | 34 | ||
33 | #include "devices-imx27.h" | 35 | #include "devices-imx27.h" |
34 | #include "devices.h" | 36 | #include "devices.h" |
35 | 37 | ||
38 | #define SD1_EN_GPIO (GPIO_PORTB + 25) | ||
39 | |||
36 | static const int mx27pdk_pins[] __initconst = { | 40 | static const int mx27pdk_pins[] __initconst = { |
37 | /* UART1 */ | 41 | /* UART1 */ |
38 | PE12_PF_UART1_TXD, | 42 | PE12_PF_UART1_TXD, |
@@ -58,6 +62,14 @@ static const int mx27pdk_pins[] __initconst = { | |||
58 | PD15_AOUT_FEC_COL, | 62 | PD15_AOUT_FEC_COL, |
59 | PD16_AIN_FEC_TX_ER, | 63 | PD16_AIN_FEC_TX_ER, |
60 | PF23_AIN_FEC_TX_EN, | 64 | PF23_AIN_FEC_TX_EN, |
65 | /* SDHC1 */ | ||
66 | PE18_PF_SD1_D0, | ||
67 | PE19_PF_SD1_D1, | ||
68 | PE20_PF_SD1_D2, | ||
69 | PE21_PF_SD1_D3, | ||
70 | PE22_PF_SD1_CMD, | ||
71 | PE23_PF_SD1_CLK, | ||
72 | SD1_EN_GPIO | GPIO_GPIO | GPIO_OUT, | ||
61 | }; | 73 | }; |
62 | 74 | ||
63 | static const struct imxuart_platform_data uart_pdata __initconst = { | 75 | static const struct imxuart_platform_data uart_pdata __initconst = { |
@@ -85,13 +97,39 @@ static struct matrix_keymap_data mx27_3ds_keymap_data = { | |||
85 | .keymap_size = ARRAY_SIZE(mx27_3ds_keymap), | 97 | .keymap_size = ARRAY_SIZE(mx27_3ds_keymap), |
86 | }; | 98 | }; |
87 | 99 | ||
100 | static int mx27_3ds_sdhc1_init(struct device *dev, irq_handler_t detect_irq, | ||
101 | void *data) | ||
102 | { | ||
103 | return request_irq(IRQ_GPIOB(26), detect_irq, IRQF_TRIGGER_FALLING | | ||
104 | IRQF_TRIGGER_RISING, "sdhc1-card-detect", data); | ||
105 | } | ||
106 | |||
107 | static void mx27_3ds_sdhc1_exit(struct device *dev, void *data) | ||
108 | { | ||
109 | free_irq(IRQ_GPIOB(26), data); | ||
110 | } | ||
111 | |||
112 | static struct imxmmc_platform_data sdhc1_pdata = { | ||
113 | .init = mx27_3ds_sdhc1_init, | ||
114 | .exit = mx27_3ds_sdhc1_exit, | ||
115 | }; | ||
116 | |||
117 | static void mx27_3ds_sdhc1_enable_level_translator(void) | ||
118 | { | ||
119 | /* Turn on TXB0108 OE pin */ | ||
120 | gpio_request(SD1_EN_GPIO, "sd1_enable"); | ||
121 | gpio_direction_output(SD1_EN_GPIO, 1); | ||
122 | } | ||
123 | |||
88 | static void __init mx27pdk_init(void) | 124 | static void __init mx27pdk_init(void) |
89 | { | 125 | { |
90 | mxc_gpio_setup_multiple_pins(mx27pdk_pins, ARRAY_SIZE(mx27pdk_pins), | 126 | mxc_gpio_setup_multiple_pins(mx27pdk_pins, ARRAY_SIZE(mx27pdk_pins), |
91 | "mx27pdk"); | 127 | "mx27pdk"); |
128 | mx27_3ds_sdhc1_enable_level_translator(); | ||
92 | imx27_add_imx_uart0(&uart_pdata); | 129 | imx27_add_imx_uart0(&uart_pdata); |
93 | imx27_add_fec(NULL); | 130 | imx27_add_fec(NULL); |
94 | mxc_register_device(&imx_kpp_device, &mx27_3ds_keymap_data); | 131 | mxc_register_device(&imx_kpp_device, &mx27_3ds_keymap_data); |
132 | mxc_register_device(&mxc_sdhc_device0, &sdhc1_pdata); | ||
95 | } | 133 | } |
96 | 134 | ||
97 | static void __init mx27pdk_timer_init(void) | 135 | static void __init mx27pdk_timer_init(void) |
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c index babb22597163..e24e3d05397f 100644 --- a/arch/arm/mach-ixp2000/core.c +++ b/arch/arm/mach-ixp2000/core.c | |||
@@ -197,7 +197,7 @@ unsigned long ixp2000_gettimeoffset (void) | |||
197 | return offset / ticks_per_usec; | 197 | return offset / ticks_per_usec; |
198 | } | 198 | } |
199 | 199 | ||
200 | static int ixp2000_timer_interrupt(int irq, void *dev_id) | 200 | static irqreturn_t ixp2000_timer_interrupt(int irq, void *dev_id) |
201 | { | 201 | { |
202 | /* clear timer 1 */ | 202 | /* clear timer 1 */ |
203 | ixp2000_reg_wrb(IXP2000_T1_CLR, 1); | 203 | ixp2000_reg_wrb(IXP2000_T1_CLR, 1); |
diff --git a/arch/arm/mach-mx25/Kconfig b/arch/arm/mach-mx25/Kconfig index aa57e35ce3cd..38ca09a5df9d 100644 --- a/arch/arm/mach-mx25/Kconfig +++ b/arch/arm/mach-mx25/Kconfig | |||
@@ -6,6 +6,7 @@ config MACH_MX25_3DS | |||
6 | bool "Support MX25PDK (3DS) Platform" | 6 | bool "Support MX25PDK (3DS) Platform" |
7 | select IMX_HAVE_PLATFORM_IMX_UART | 7 | select IMX_HAVE_PLATFORM_IMX_UART |
8 | select IMX_HAVE_PLATFORM_MXC_NAND | 8 | select IMX_HAVE_PLATFORM_MXC_NAND |
9 | select IMX_HAVE_PLATFORM_ESDHC | ||
9 | 10 | ||
10 | config MACH_EUKREA_CPUIMX25 | 11 | config MACH_EUKREA_CPUIMX25 |
11 | bool "Support Eukrea CPUIMX25 Platform" | 12 | bool "Support Eukrea CPUIMX25 Platform" |
diff --git a/arch/arm/mach-mx25/mach-mx25_3ds.c b/arch/arm/mach-mx25/mach-mx25_3ds.c index 80805107a73e..f8be1eb0c062 100644 --- a/arch/arm/mach-mx25/mach-mx25_3ds.c +++ b/arch/arm/mach-mx25/mach-mx25_3ds.c | |||
@@ -96,6 +96,14 @@ static struct pad_desc mx25pdk_pads[] = { | |||
96 | MX25_PAD_KPP_COL1__KPP_COL1, | 96 | MX25_PAD_KPP_COL1__KPP_COL1, |
97 | MX25_PAD_KPP_COL2__KPP_COL2, | 97 | MX25_PAD_KPP_COL2__KPP_COL2, |
98 | MX25_PAD_KPP_COL3__KPP_COL3, | 98 | MX25_PAD_KPP_COL3__KPP_COL3, |
99 | |||
100 | /* SD1 */ | ||
101 | MX25_PAD_SD1_CMD__SD1_CMD, | ||
102 | MX25_PAD_SD1_CLK__SD1_CLK, | ||
103 | MX25_PAD_SD1_DATA0__SD1_DATA0, | ||
104 | MX25_PAD_SD1_DATA1__SD1_DATA1, | ||
105 | MX25_PAD_SD1_DATA2__SD1_DATA2, | ||
106 | MX25_PAD_SD1_DATA3__SD1_DATA3, | ||
99 | }; | 107 | }; |
100 | 108 | ||
101 | static const struct fec_platform_data mx25_fec_pdata __initconst = { | 109 | static const struct fec_platform_data mx25_fec_pdata __initconst = { |
@@ -193,6 +201,8 @@ static void __init mx25pdk_init(void) | |||
193 | mx25pdk_fec_reset(); | 201 | mx25pdk_fec_reset(); |
194 | imx25_add_fec(&mx25_fec_pdata); | 202 | imx25_add_fec(&mx25_fec_pdata); |
195 | mxc_register_device(&mx25_kpp_device, &mx25pdk_keymap_data); | 203 | mxc_register_device(&mx25_kpp_device, &mx25pdk_keymap_data); |
204 | |||
205 | imx25_add_esdhc(0, NULL); | ||
196 | } | 206 | } |
197 | 207 | ||
198 | static void __init mx25pdk_timer_init(void) | 208 | static void __init mx25pdk_timer_init(void) |
diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig index 096fd33f8ab9..5000ac1f93e3 100644 --- a/arch/arm/mach-mx3/Kconfig +++ b/arch/arm/mach-mx3/Kconfig | |||
@@ -143,8 +143,10 @@ config MACH_ARMADILLO5X0 | |||
143 | config MACH_MX35_3DS | 143 | config MACH_MX35_3DS |
144 | bool "Support MX35PDK platform" | 144 | bool "Support MX35PDK platform" |
145 | select ARCH_MX35 | 145 | select ARCH_MX35 |
146 | select MXC_DEBUG_BOARD | ||
146 | select IMX_HAVE_PLATFORM_IMX_UART | 147 | select IMX_HAVE_PLATFORM_IMX_UART |
147 | select IMX_HAVE_PLATFORM_MXC_NAND | 148 | select IMX_HAVE_PLATFORM_MXC_NAND |
149 | select IMX_HAVE_PLATFORM_ESDHC | ||
148 | default n | 150 | default n |
149 | help | 151 | help |
150 | Include support for MX35PDK platform. This includes specific | 152 | Include support for MX35PDK platform. This includes specific |
diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c index f4dff11aaee7..d4da9496089a 100644 --- a/arch/arm/mach-mx3/devices.c +++ b/arch/arm/mach-mx3/devices.c | |||
@@ -72,24 +72,24 @@ struct platform_device mxc_w1_master_device = { | |||
72 | #ifdef CONFIG_ARCH_MX31 | 72 | #ifdef CONFIG_ARCH_MX31 |
73 | static struct resource mxcsdhc0_resources[] = { | 73 | static struct resource mxcsdhc0_resources[] = { |
74 | { | 74 | { |
75 | .start = MMC_SDHC1_BASE_ADDR, | 75 | .start = MX31_MMC_SDHC1_BASE_ADDR, |
76 | .end = MMC_SDHC1_BASE_ADDR + SZ_16K - 1, | 76 | .end = MX31_MMC_SDHC1_BASE_ADDR + SZ_16K - 1, |
77 | .flags = IORESOURCE_MEM, | 77 | .flags = IORESOURCE_MEM, |
78 | }, { | 78 | }, { |
79 | .start = MXC_INT_MMC_SDHC1, | 79 | .start = MX31_INT_MMC_SDHC1, |
80 | .end = MXC_INT_MMC_SDHC1, | 80 | .end = MX31_INT_MMC_SDHC1, |
81 | .flags = IORESOURCE_IRQ, | 81 | .flags = IORESOURCE_IRQ, |
82 | }, | 82 | }, |
83 | }; | 83 | }; |
84 | 84 | ||
85 | static struct resource mxcsdhc1_resources[] = { | 85 | static struct resource mxcsdhc1_resources[] = { |
86 | { | 86 | { |
87 | .start = MMC_SDHC2_BASE_ADDR, | 87 | .start = MX31_MMC_SDHC2_BASE_ADDR, |
88 | .end = MMC_SDHC2_BASE_ADDR + SZ_16K - 1, | 88 | .end = MX31_MMC_SDHC2_BASE_ADDR + SZ_16K - 1, |
89 | .flags = IORESOURCE_MEM, | 89 | .flags = IORESOURCE_MEM, |
90 | }, { | 90 | }, { |
91 | .start = MXC_INT_MMC_SDHC2, | 91 | .start = MX31_INT_MMC_SDHC2, |
92 | .end = MXC_INT_MMC_SDHC2, | 92 | .end = MX31_INT_MMC_SDHC2, |
93 | .flags = IORESOURCE_IRQ, | 93 | .flags = IORESOURCE_IRQ, |
94 | }, | 94 | }, |
95 | }; | 95 | }; |
diff --git a/arch/arm/mach-mx3/mach-mx31_3ds.c b/arch/arm/mach-mx3/mach-mx31_3ds.c index 5c1d0e86c91e..0ad9e7821082 100644 --- a/arch/arm/mach-mx3/mach-mx31_3ds.c +++ b/arch/arm/mach-mx3/mach-mx31_3ds.c | |||
@@ -38,39 +38,9 @@ | |||
38 | #include "devices-imx31.h" | 38 | #include "devices-imx31.h" |
39 | #include "devices.h" | 39 | #include "devices.h" |
40 | 40 | ||
41 | /* Definitions for components on the Debug board */ | ||
42 | |||
43 | /* Base address of CPLD controller on the Debug board */ | ||
44 | #define DEBUG_BASE_ADDRESS CS5_IO_ADDRESS(MX3x_CS5_BASE_ADDR) | ||
45 | |||
46 | /* LAN9217 ethernet base address */ | ||
47 | #define LAN9217_BASE_ADDR MX3x_CS5_BASE_ADDR | ||
48 | |||
49 | /* CPLD config and interrupt base address */ | ||
50 | #define CPLD_ADDR (DEBUG_BASE_ADDRESS + 0x20000) | ||
51 | |||
52 | /* status, interrupt */ | ||
53 | #define CPLD_INT_STATUS_REG (CPLD_ADDR + 0x10) | ||
54 | #define CPLD_INT_MASK_REG (CPLD_ADDR + 0x38) | ||
55 | #define CPLD_INT_RESET_REG (CPLD_ADDR + 0x20) | ||
56 | /* magic word for debug CPLD */ | ||
57 | #define CPLD_MAGIC_NUMBER1_REG (CPLD_ADDR + 0x40) | ||
58 | #define CPLD_MAGIC_NUMBER2_REG (CPLD_ADDR + 0x48) | ||
59 | /* CPLD code version */ | ||
60 | #define CPLD_CODE_VER_REG (CPLD_ADDR + 0x50) | ||
61 | /* magic word for debug CPLD */ | ||
62 | #define CPLD_MAGIC_NUMBER3_REG (CPLD_ADDR + 0x58) | ||
63 | |||
64 | /* CPLD IRQ line for external uart, external ethernet etc */ | 41 | /* CPLD IRQ line for external uart, external ethernet etc */ |
65 | #define EXPIO_PARENT_INT IOMUX_TO_IRQ(MX31_PIN_GPIO1_1) | 42 | #define EXPIO_PARENT_INT IOMUX_TO_IRQ(MX31_PIN_GPIO1_1) |
66 | 43 | ||
67 | #define MXC_EXP_IO_BASE (MXC_BOARD_IRQ_START) | ||
68 | #define MXC_IRQ_TO_EXPIO(irq) ((irq) - MXC_EXP_IO_BASE) | ||
69 | |||
70 | #define EXPIO_INT_ENET (MXC_EXP_IO_BASE + 0) | ||
71 | |||
72 | #define MXC_MAX_EXP_IO_LINES 16 | ||
73 | |||
74 | /* | 44 | /* |
75 | * This file contains the board-specific initialization routines. | 45 | * This file contains the board-specific initialization routines. |
76 | */ | 46 | */ |
@@ -272,7 +242,7 @@ static void __init mxc_board_init(void) | |||
272 | imx31_add_imx_uart0(&uart_pdata); | 242 | imx31_add_imx_uart0(&uart_pdata); |
273 | imx31_add_mxc_nand(&mx31_3ds_nand_board_info); | 243 | imx31_add_mxc_nand(&mx31_3ds_nand_board_info); |
274 | 244 | ||
275 | imx31_add_spi_imx0(&spi1_pdata); | 245 | imx31_add_spi_imx1(&spi1_pdata); |
276 | spi_register_board_info(mx31_3ds_spi_devs, | 246 | spi_register_board_info(mx31_3ds_spi_devs, |
277 | ARRAY_SIZE(mx31_3ds_spi_devs)); | 247 | ARRAY_SIZE(mx31_3ds_spi_devs)); |
278 | 248 | ||
@@ -281,9 +251,9 @@ static void __init mxc_board_init(void) | |||
281 | mx31_3ds_usbotg_init(); | 251 | mx31_3ds_usbotg_init(); |
282 | mxc_register_device(&mxc_otg_udc_device, &usbotg_pdata); | 252 | mxc_register_device(&mxc_otg_udc_device, &usbotg_pdata); |
283 | 253 | ||
284 | if (!mxc_expio_init(CS5_BASE_ADDR, EXPIO_PARENT_INT)) | 254 | if (mxc_expio_init(MX31_CS5_BASE_ADDR, EXPIO_PARENT_INT)) |
285 | printk(KERN_WARNING "Init of the debugboard failed, all " | 255 | printk(KERN_WARNING "Init of the debug board failed, all " |
286 | "devices on the board are unusable.\n"); | 256 | "devices on the debug board are unusable.\n"); |
287 | } | 257 | } |
288 | 258 | ||
289 | static void __init mx31_3ds_timer_init(void) | 259 | static void __init mx31_3ds_timer_init(void) |
diff --git a/arch/arm/mach-mx3/mach-mx35_3ds.c b/arch/arm/mach-mx3/mach-mx35_3ds.c index 05f628d90725..b66a75aa2e88 100644 --- a/arch/arm/mach-mx3/mach-mx35_3ds.c +++ b/arch/arm/mach-mx3/mach-mx35_3ds.c | |||
@@ -38,11 +38,15 @@ | |||
38 | #include <mach/hardware.h> | 38 | #include <mach/hardware.h> |
39 | #include <mach/common.h> | 39 | #include <mach/common.h> |
40 | #include <mach/iomux-mx35.h> | 40 | #include <mach/iomux-mx35.h> |
41 | #include <mach/irqs.h> | ||
42 | #include <mach/3ds_debugboard.h> | ||
41 | #include <mach/mxc_ehci.h> | 43 | #include <mach/mxc_ehci.h> |
42 | 44 | ||
43 | #include "devices-imx35.h" | 45 | #include "devices-imx35.h" |
44 | #include "devices.h" | 46 | #include "devices.h" |
45 | 47 | ||
48 | #define EXPIO_PARENT_INT (MXC_INTERNAL_IRQS + GPIO_PORTA + 1) | ||
49 | |||
46 | static const struct imxuart_platform_data uart_pdata __initconst = { | 50 | static const struct imxuart_platform_data uart_pdata __initconst = { |
47 | .flags = IMXUART_HAVE_RTSCTS, | 51 | .flags = IMXUART_HAVE_RTSCTS, |
48 | }; | 52 | }; |
@@ -108,6 +112,13 @@ static struct pad_desc mx35pdk_pads[] = { | |||
108 | /* USBH1 */ | 112 | /* USBH1 */ |
109 | MX35_PAD_I2C2_CLK__USB_TOP_USBH2_PWR, | 113 | MX35_PAD_I2C2_CLK__USB_TOP_USBH2_PWR, |
110 | MX35_PAD_I2C2_DAT__USB_TOP_USBH2_OC, | 114 | MX35_PAD_I2C2_DAT__USB_TOP_USBH2_OC, |
115 | /* SDCARD */ | ||
116 | MX35_PAD_SD1_CMD__ESDHC1_CMD, | ||
117 | MX35_PAD_SD1_CLK__ESDHC1_CLK, | ||
118 | MX35_PAD_SD1_DATA0__ESDHC1_DAT0, | ||
119 | MX35_PAD_SD1_DATA1__ESDHC1_DAT1, | ||
120 | MX35_PAD_SD1_DATA2__ESDHC1_DAT2, | ||
121 | MX35_PAD_SD1_DATA3__ESDHC1_DAT3, | ||
111 | }; | 122 | }; |
112 | 123 | ||
113 | /* OTG config */ | 124 | /* OTG config */ |
@@ -140,6 +151,11 @@ static void __init mxc_board_init(void) | |||
140 | mxc_register_device(&mxc_usbh1, &usb_host_pdata); | 151 | mxc_register_device(&mxc_usbh1, &usb_host_pdata); |
141 | 152 | ||
142 | imx35_add_mxc_nand(&mx35pdk_nand_board_info); | 153 | imx35_add_mxc_nand(&mx35pdk_nand_board_info); |
154 | imx35_add_esdhc(0, NULL); | ||
155 | |||
156 | if (mxc_expio_init(MX35_CS5_BASE_ADDR, EXPIO_PARENT_INT)) | ||
157 | pr_warn("Init of the debugboard failed, all " | ||
158 | "devices on the debugboard are unusable.\n"); | ||
143 | } | 159 | } |
144 | 160 | ||
145 | static void __init mx35pdk_timer_init(void) | 161 | static void __init mx35pdk_timer_init(void) |
diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig index a2df9ac37996..3ec910a7a182 100644 --- a/arch/arm/mach-mx5/Kconfig +++ b/arch/arm/mach-mx5/Kconfig | |||
@@ -6,6 +6,7 @@ config ARCH_MX51 | |||
6 | select MXC_TZIC | 6 | select MXC_TZIC |
7 | select ARCH_MXC_IOMUX_V3 | 7 | select ARCH_MXC_IOMUX_V3 |
8 | select ARCH_MXC_AUDMUX_V2 | 8 | select ARCH_MXC_AUDMUX_V2 |
9 | select ARCH_HAS_CPUFREQ | ||
9 | 10 | ||
10 | comment "MX5 platforms:" | 11 | comment "MX5 platforms:" |
11 | 12 | ||
@@ -13,6 +14,7 @@ config MACH_MX51_BABBAGE | |||
13 | bool "Support MX51 BABBAGE platforms" | 14 | bool "Support MX51 BABBAGE platforms" |
14 | select IMX_HAVE_PLATFORM_IMX_I2C | 15 | select IMX_HAVE_PLATFORM_IMX_I2C |
15 | select IMX_HAVE_PLATFORM_IMX_UART | 16 | select IMX_HAVE_PLATFORM_IMX_UART |
17 | select IMX_HAVE_PLATFORM_ESDHC | ||
16 | help | 18 | help |
17 | Include support for MX51 Babbage platform, also known as MX51EVK in | 19 | Include support for MX51 Babbage platform, also known as MX51EVK in |
18 | u-boot. This includes specific configurations for the board and its | 20 | u-boot. This includes specific configurations for the board and its |
diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile index 1769c161a60d..462f177eddfe 100644 --- a/arch/arm/mach-mx5/Makefile +++ b/arch/arm/mach-mx5/Makefile | |||
@@ -5,6 +5,7 @@ | |||
5 | # Object file lists. | 5 | # Object file lists. |
6 | obj-y := cpu.o mm.o clock-mx51.o devices.o | 6 | obj-y := cpu.o mm.o clock-mx51.o devices.o |
7 | 7 | ||
8 | obj-$(CONFIG_CPU_FREQ_IMX) += cpu_op-mx51.o | ||
8 | obj-$(CONFIG_MACH_MX51_BABBAGE) += board-mx51_babbage.o | 9 | obj-$(CONFIG_MACH_MX51_BABBAGE) += board-mx51_babbage.o |
9 | obj-$(CONFIG_MACH_MX51_3DS) += board-mx51_3ds.o | 10 | obj-$(CONFIG_MACH_MX51_3DS) += board-mx51_3ds.o |
10 | obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += board-cpuimx51.o | 11 | obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += board-cpuimx51.o |
diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c index 0821fe9b3b27..acbe30df2e69 100644 --- a/arch/arm/mach-mx5/board-mx51_babbage.c +++ b/arch/arm/mach-mx5/board-mx51_babbage.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. | 2 | * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved. |
3 | * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com> | 3 | * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com> |
4 | * | 4 | * |
5 | * The code contained herein is licensed under the GNU General Public | 5 | * The code contained herein is licensed under the GNU General Public |
@@ -18,6 +18,8 @@ | |||
18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
19 | #include <linux/fsl_devices.h> | 19 | #include <linux/fsl_devices.h> |
20 | #include <linux/fec.h> | 20 | #include <linux/fec.h> |
21 | #include <linux/gpio_keys.h> | ||
22 | #include <linux/input.h> | ||
21 | 23 | ||
22 | #include <mach/common.h> | 24 | #include <mach/common.h> |
23 | #include <mach/hardware.h> | 25 | #include <mach/hardware.h> |
@@ -32,11 +34,13 @@ | |||
32 | 34 | ||
33 | #include "devices-imx51.h" | 35 | #include "devices-imx51.h" |
34 | #include "devices.h" | 36 | #include "devices.h" |
37 | #include "cpu_op-mx51.h" | ||
35 | 38 | ||
36 | #define BABBAGE_USB_HUB_RESET (0*32 + 7) /* GPIO_1_7 */ | 39 | #define BABBAGE_USB_HUB_RESET (0*32 + 7) /* GPIO_1_7 */ |
37 | #define BABBAGE_USBH1_STP (0*32 + 27) /* GPIO_1_27 */ | 40 | #define BABBAGE_USBH1_STP (0*32 + 27) /* GPIO_1_27 */ |
38 | #define BABBAGE_PHY_RESET (1*32 + 5) /* GPIO_2_5 */ | 41 | #define BABBAGE_PHY_RESET (1*32 + 5) /* GPIO_2_5 */ |
39 | #define BABBAGE_FEC_PHY_RESET (1*32 + 14) /* GPIO_2_14 */ | 42 | #define BABBAGE_FEC_PHY_RESET (1*32 + 14) /* GPIO_2_14 */ |
43 | #define BABBAGE_POWER_KEY (1*32 + 21) /* GPIO_2_21 */ | ||
40 | 44 | ||
41 | /* USB_CTRL_1 */ | 45 | /* USB_CTRL_1 */ |
42 | #define MX51_USB_CTRL_1_OFFSET 0x10 | 46 | #define MX51_USB_CTRL_1_OFFSET 0x10 |
@@ -46,6 +50,21 @@ | |||
46 | #define MX51_USB_PLL_DIV_19_2_MHZ 0x01 | 50 | #define MX51_USB_PLL_DIV_19_2_MHZ 0x01 |
47 | #define MX51_USB_PLL_DIV_24_MHZ 0x02 | 51 | #define MX51_USB_PLL_DIV_24_MHZ 0x02 |
48 | 52 | ||
53 | static struct gpio_keys_button babbage_buttons[] = { | ||
54 | { | ||
55 | .gpio = BABBAGE_POWER_KEY, | ||
56 | .code = BTN_0, | ||
57 | .desc = "PWR", | ||
58 | .active_low = 1, | ||
59 | .wakeup = 1, | ||
60 | }, | ||
61 | }; | ||
62 | |||
63 | static const struct gpio_keys_platform_data imx_button_data __initconst = { | ||
64 | .buttons = babbage_buttons, | ||
65 | .nbuttons = ARRAY_SIZE(babbage_buttons), | ||
66 | }; | ||
67 | |||
49 | static struct pad_desc mx51babbage_pads[] = { | 68 | static struct pad_desc mx51babbage_pads[] = { |
50 | /* UART1 */ | 69 | /* UART1 */ |
51 | MX51_PAD_UART1_RXD__UART1_RXD, | 70 | MX51_PAD_UART1_RXD__UART1_RXD, |
@@ -112,6 +131,22 @@ static struct pad_desc mx51babbage_pads[] = { | |||
112 | 131 | ||
113 | /* FEC PHY reset line */ | 132 | /* FEC PHY reset line */ |
114 | MX51_PAD_EIM_A20__GPIO_2_14, | 133 | MX51_PAD_EIM_A20__GPIO_2_14, |
134 | |||
135 | /* SD 1 */ | ||
136 | MX51_PAD_SD1_CMD__SD1_CMD, | ||
137 | MX51_PAD_SD1_CLK__SD1_CLK, | ||
138 | MX51_PAD_SD1_DATA0__SD1_DATA0, | ||
139 | MX51_PAD_SD1_DATA1__SD1_DATA1, | ||
140 | MX51_PAD_SD1_DATA2__SD1_DATA2, | ||
141 | MX51_PAD_SD1_DATA3__SD1_DATA3, | ||
142 | |||
143 | /* SD 2 */ | ||
144 | MX51_PAD_SD2_CMD__SD2_CMD, | ||
145 | MX51_PAD_SD2_CLK__SD2_CLK, | ||
146 | MX51_PAD_SD2_DATA0__SD2_DATA0, | ||
147 | MX51_PAD_SD2_DATA1__SD2_DATA1, | ||
148 | MX51_PAD_SD2_DATA2__SD2_DATA2, | ||
149 | MX51_PAD_SD2_DATA3__SD2_DATA3, | ||
115 | }; | 150 | }; |
116 | 151 | ||
117 | /* Serial ports */ | 152 | /* Serial ports */ |
@@ -281,13 +316,22 @@ __setup("otg_mode=", babbage_otg_mode); | |||
281 | static void __init mxc_board_init(void) | 316 | static void __init mxc_board_init(void) |
282 | { | 317 | { |
283 | struct pad_desc usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP; | 318 | struct pad_desc usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP; |
319 | struct pad_desc power_key = MX51_PAD_EIM_A27__GPIO_2_21; | ||
284 | 320 | ||
321 | #if defined(CONFIG_CPU_FREQ_IMX) | ||
322 | get_cpu_op = mx51_get_cpu_op; | ||
323 | #endif | ||
285 | mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads, | 324 | mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads, |
286 | ARRAY_SIZE(mx51babbage_pads)); | 325 | ARRAY_SIZE(mx51babbage_pads)); |
287 | mxc_init_imx_uart(); | 326 | mxc_init_imx_uart(); |
288 | babbage_fec_reset(); | 327 | babbage_fec_reset(); |
289 | imx51_add_fec(NULL); | 328 | imx51_add_fec(NULL); |
290 | 329 | ||
330 | /* Set the PAD settings for the pwr key. */ | ||
331 | power_key.pad_ctrl = MX51_GPIO_PAD_CTRL_2; | ||
332 | mxc_iomux_v3_setup_pad(&power_key); | ||
333 | imx51_add_gpio_keys(&imx_button_data); | ||
334 | |||
291 | imx51_add_imx_i2c(0, &babbage_i2c_data); | 335 | imx51_add_imx_i2c(0, &babbage_i2c_data); |
292 | imx51_add_imx_i2c(1, &babbage_i2c_data); | 336 | imx51_add_imx_i2c(1, &babbage_i2c_data); |
293 | mxc_register_device(&mxc_hsi2c_device, &babbage_hsi2c_data); | 337 | mxc_register_device(&mxc_hsi2c_device, &babbage_hsi2c_data); |
@@ -304,6 +348,9 @@ static void __init mxc_board_init(void) | |||
304 | /* setback USBH1_STP to be function */ | 348 | /* setback USBH1_STP to be function */ |
305 | mxc_iomux_v3_setup_pad(&usbh1stp); | 349 | mxc_iomux_v3_setup_pad(&usbh1stp); |
306 | babbage_usbhub_reset(); | 350 | babbage_usbhub_reset(); |
351 | |||
352 | imx51_add_esdhc(0, NULL); | ||
353 | imx51_add_esdhc(1, NULL); | ||
307 | } | 354 | } |
308 | 355 | ||
309 | static void __init mx51_babbage_timer_init(void) | 356 | static void __init mx51_babbage_timer_init(void) |
diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c index f2aae92cf0e2..8ac36d882927 100644 --- a/arch/arm/mach-mx5/clock-mx51.c +++ b/arch/arm/mach-mx5/clock-mx51.c | |||
@@ -362,7 +362,7 @@ static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent) | |||
362 | return 0; | 362 | return 0; |
363 | } | 363 | } |
364 | 364 | ||
365 | static unsigned long clk_arm_get_rate(struct clk *clk) | 365 | static unsigned long clk_cpu_get_rate(struct clk *clk) |
366 | { | 366 | { |
367 | u32 cacrr, div; | 367 | u32 cacrr, div; |
368 | unsigned long parent_rate; | 368 | unsigned long parent_rate; |
@@ -374,6 +374,22 @@ static unsigned long clk_arm_get_rate(struct clk *clk) | |||
374 | return parent_rate / div; | 374 | return parent_rate / div; |
375 | } | 375 | } |
376 | 376 | ||
377 | static int clk_cpu_set_rate(struct clk *clk, unsigned long rate) | ||
378 | { | ||
379 | u32 reg, cpu_podf; | ||
380 | unsigned long parent_rate; | ||
381 | |||
382 | parent_rate = clk_get_rate(clk->parent); | ||
383 | cpu_podf = parent_rate / rate - 1; | ||
384 | /* use post divider to change freq */ | ||
385 | reg = __raw_readl(MXC_CCM_CACRR); | ||
386 | reg &= ~MXC_CCM_CACRR_ARM_PODF_MASK; | ||
387 | reg |= cpu_podf << MXC_CCM_CACRR_ARM_PODF_OFFSET; | ||
388 | __raw_writel(reg, MXC_CCM_CACRR); | ||
389 | |||
390 | return 0; | ||
391 | } | ||
392 | |||
377 | static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent) | 393 | static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent) |
378 | { | 394 | { |
379 | u32 reg, mux; | 395 | u32 reg, mux; |
@@ -736,7 +752,8 @@ static struct clk periph_apm_clk = { | |||
736 | 752 | ||
737 | static struct clk cpu_clk = { | 753 | static struct clk cpu_clk = { |
738 | .parent = &pll1_sw_clk, | 754 | .parent = &pll1_sw_clk, |
739 | .get_rate = clk_arm_get_rate, | 755 | .get_rate = clk_cpu_get_rate, |
756 | .set_rate = clk_cpu_set_rate, | ||
740 | }; | 757 | }; |
741 | 758 | ||
742 | static struct clk ahb_clk = { | 759 | static struct clk ahb_clk = { |
@@ -1064,6 +1081,7 @@ static struct clk_lookup lookups[] = { | |||
1064 | _REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk) | 1081 | _REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk) |
1065 | _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk) | 1082 | _REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk) |
1066 | _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk) | 1083 | _REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk) |
1084 | _REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk) | ||
1067 | }; | 1085 | }; |
1068 | 1086 | ||
1069 | static void clk_tree_init(void) | 1087 | static void clk_tree_init(void) |
diff --git a/arch/arm/mach-mx5/cpu_op-mx51.c b/arch/arm/mach-mx5/cpu_op-mx51.c new file mode 100644 index 000000000000..9d34c3d4c024 --- /dev/null +++ b/arch/arm/mach-mx5/cpu_op-mx51.c | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. | ||
3 | */ | ||
4 | |||
5 | /* | ||
6 | * The code contained herein is licensed under the GNU General Public | ||
7 | * License. You may obtain a copy of the GNU General Public License | ||
8 | * Version 2 or later at the following locations: | ||
9 | * | ||
10 | * http://www.opensource.org/licenses/gpl-license.html | ||
11 | * http://www.gnu.org/copyleft/gpl.html | ||
12 | */ | ||
13 | |||
14 | #include <linux/types.h> | ||
15 | #include <mach/hardware.h> | ||
16 | #include <linux/kernel.h> | ||
17 | |||
18 | static struct cpu_op mx51_cpu_op[] = { | ||
19 | { | ||
20 | .cpu_rate = 160000000,}, | ||
21 | { | ||
22 | .cpu_rate = 800000000,}, | ||
23 | }; | ||
24 | |||
25 | struct cpu_op *mx51_get_cpu_op(int *op) | ||
26 | { | ||
27 | *op = ARRAY_SIZE(mx51_cpu_op); | ||
28 | return mx51_cpu_op; | ||
29 | } | ||
diff --git a/arch/arm/mach-mx5/cpu_op-mx51.h b/arch/arm/mach-mx5/cpu_op-mx51.h new file mode 100644 index 000000000000..97477fecb469 --- /dev/null +++ b/arch/arm/mach-mx5/cpu_op-mx51.h | |||
@@ -0,0 +1,14 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. | ||
3 | */ | ||
4 | |||
5 | /* | ||
6 | * The code contained herein is licensed under the GNU General Public | ||
7 | * License. You may obtain a copy of the GNU General Public License | ||
8 | * Version 2 or later at the following locations: | ||
9 | * | ||
10 | * http://www.opensource.org/licenses/gpl-license.html | ||
11 | * http://www.gnu.org/copyleft/gpl.html | ||
12 | */ | ||
13 | |||
14 | extern struct cpu_op *mx51_get_cpu_op(int *op); | ||
diff --git a/arch/arm/mach-mx5/devices-imx51.h b/arch/arm/mach-mx5/devices-imx51.h index 5cc910e60538..8c50cb5d05f5 100644 --- a/arch/arm/mach-mx5/devices-imx51.h +++ b/arch/arm/mach-mx5/devices-imx51.h | |||
@@ -13,6 +13,8 @@ extern const struct imx_fec_data imx51_fec_data __initconst; | |||
13 | #define imx51_add_fec(pdata) \ | 13 | #define imx51_add_fec(pdata) \ |
14 | imx_add_fec(&imx51_fec_data, pdata) | 14 | imx_add_fec(&imx51_fec_data, pdata) |
15 | 15 | ||
16 | #define imx51_add_gpio_keys(pdata) imx_add_gpio_keys(pdata) | ||
17 | |||
16 | extern const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst; | 18 | extern const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst; |
17 | #define imx51_add_imx_i2c(id, pdata) \ | 19 | #define imx51_add_imx_i2c(id, pdata) \ |
18 | imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata) | 20 | imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata) |
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index 923f9f5f91ce..2f895553e6a8 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c | |||
@@ -44,6 +44,13 @@ void __init gic_init_irq(void) | |||
44 | } | 44 | } |
45 | 45 | ||
46 | #ifdef CONFIG_CACHE_L2X0 | 46 | #ifdef CONFIG_CACHE_L2X0 |
47 | |||
48 | static void omap4_l2x0_disable(void) | ||
49 | { | ||
50 | /* Disable PL310 L2 Cache controller */ | ||
51 | omap_smc1(0x102, 0x0); | ||
52 | } | ||
53 | |||
47 | static int __init omap_l2_cache_init(void) | 54 | static int __init omap_l2_cache_init(void) |
48 | { | 55 | { |
49 | /* | 56 | /* |
@@ -70,6 +77,12 @@ static int __init omap_l2_cache_init(void) | |||
70 | else | 77 | else |
71 | l2x0_init(l2cache_base, 0x0e070000, 0xc0000fff); | 78 | l2x0_init(l2cache_base, 0x0e070000, 0xc0000fff); |
72 | 79 | ||
80 | /* | ||
81 | * Override default outer_cache.disable with a OMAP4 | ||
82 | * specific one | ||
83 | */ | ||
84 | outer_cache.disable = omap4_l2x0_disable; | ||
85 | |||
73 | return 0; | 86 | return 0; |
74 | } | 87 | } |
75 | early_initcall(omap_l2_cache_init); | 88 | early_initcall(omap_l2_cache_init); |
diff --git a/arch/arm/mach-s3c2410/include/mach/gpio.h b/arch/arm/mach-s3c2410/include/mach/gpio.h index b649bf2ccd5c..f7f6b07df30e 100644 --- a/arch/arm/mach-s3c2410/include/mach/gpio.h +++ b/arch/arm/mach-s3c2410/include/mach/gpio.h | |||
@@ -22,6 +22,8 @@ | |||
22 | 22 | ||
23 | #ifdef CONFIG_CPU_S3C244X | 23 | #ifdef CONFIG_CPU_S3C244X |
24 | #define ARCH_NR_GPIOS (32 * 9 + CONFIG_S3C24XX_GPIO_EXTRA) | 24 | #define ARCH_NR_GPIOS (32 * 9 + CONFIG_S3C24XX_GPIO_EXTRA) |
25 | #elif defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2416) | ||
26 | #define ARCH_NR_GPIOS (32 * 12 + CONFIG_S3C24XX_GPIO_EXTRA) | ||
25 | #else | 27 | #else |
26 | #define ARCH_NR_GPIOS (256 + CONFIG_S3C24XX_GPIO_EXTRA) | 28 | #define ARCH_NR_GPIOS (256 + CONFIG_S3C24XX_GPIO_EXTRA) |
27 | #endif | 29 | #endif |
@@ -30,8 +32,10 @@ | |||
30 | #include <mach/gpio-nrs.h> | 32 | #include <mach/gpio-nrs.h> |
31 | #include <mach/gpio-fns.h> | 33 | #include <mach/gpio-fns.h> |
32 | 34 | ||
33 | #ifdef CONFIG_CPU_S3C24XX | 35 | #ifdef CONFIG_CPU_S3C244X |
34 | #define S3C_GPIO_END (S3C2410_GPIO_BANKJ + 32) | 36 | #define S3C_GPIO_END (S3C2410_GPJ(0) + 32) |
37 | #elif defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2416) | ||
38 | #define S3C_GPIO_END (S3C2410_GPM(0) + 32) | ||
35 | #else | 39 | #else |
36 | #define S3C_GPIO_END (S3C2410_GPIO_BANKH + 32) | 40 | #define S3C_GPIO_END (S3C2410_GPH(0) + 32) |
37 | #endif | 41 | #endif |
diff --git a/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h b/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h index 08ab9dfb6ae6..101aeea22310 100644 --- a/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h +++ b/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h | |||
@@ -118,6 +118,8 @@ | |||
118 | #define S3C2443_SCLKCON_UARTCLK (1<<8) | 118 | #define S3C2443_SCLKCON_UARTCLK (1<<8) |
119 | #define S3C2443_SCLKCON_USBHOST (1<<1) | 119 | #define S3C2443_SCLKCON_USBHOST (1<<1) |
120 | 120 | ||
121 | #define S3C2443_PWRCFG_SLEEP (1<<15) | ||
122 | |||
121 | #include <asm/div64.h> | 123 | #include <asm/div64.h> |
122 | 124 | ||
123 | static inline unsigned int | 125 | static inline unsigned int |
diff --git a/arch/arm/mach-s3c2410/include/mach/vmalloc.h b/arch/arm/mach-s3c2410/include/mach/vmalloc.h index 54297eb0bf5e..7a311e8dddba 100644 --- a/arch/arm/mach-s3c2410/include/mach/vmalloc.h +++ b/arch/arm/mach-s3c2410/include/mach/vmalloc.h | |||
@@ -15,6 +15,6 @@ | |||
15 | #ifndef __ASM_ARCH_VMALLOC_H | 15 | #ifndef __ASM_ARCH_VMALLOC_H |
16 | #define __ASM_ARCH_VMALLOC_H | 16 | #define __ASM_ARCH_VMALLOC_H |
17 | 17 | ||
18 | #define VMALLOC_END 0xE0000000UL | 18 | #define VMALLOC_END 0xF6000000UL |
19 | 19 | ||
20 | #endif /* __ASM_ARCH_VMALLOC_H */ | 20 | #endif /* __ASM_ARCH_VMALLOC_H */ |
diff --git a/arch/arm/mach-s3c2412/s3c2412.c b/arch/arm/mach-s3c2412/s3c2412.c index bef39f77729d..4c6df51ddf33 100644 --- a/arch/arm/mach-s3c2412/s3c2412.c +++ b/arch/arm/mach-s3c2412/s3c2412.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <plat/clock.h> | 51 | #include <plat/clock.h> |
52 | #include <plat/pm.h> | 52 | #include <plat/pm.h> |
53 | #include <plat/pll.h> | 53 | #include <plat/pll.h> |
54 | #include <plat/nand-core.h> | ||
54 | 55 | ||
55 | #ifndef CONFIG_CPU_S3C2412_ONLY | 56 | #ifndef CONFIG_CPU_S3C2412_ONLY |
56 | void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO; | 57 | void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO; |
@@ -92,7 +93,7 @@ void __init s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no) | |||
92 | /* rename devices that are s3c2412/s3c2413 specific */ | 93 | /* rename devices that are s3c2412/s3c2413 specific */ |
93 | s3c_device_sdi.name = "s3c2412-sdi"; | 94 | s3c_device_sdi.name = "s3c2412-sdi"; |
94 | s3c_device_lcd.name = "s3c2412-lcd"; | 95 | s3c_device_lcd.name = "s3c2412-lcd"; |
95 | s3c_device_nand.name = "s3c2412-nand"; | 96 | s3c_nand_setname("s3c2412-nand"); |
96 | 97 | ||
97 | /* alter IRQ of SDI controller */ | 98 | /* alter IRQ of SDI controller */ |
98 | 99 | ||
diff --git a/arch/arm/mach-s3c2416/Kconfig b/arch/arm/mach-s3c2416/Kconfig index 657e4fe17f39..87b9c9f003bd 100644 --- a/arch/arm/mach-s3c2416/Kconfig +++ b/arch/arm/mach-s3c2416/Kconfig | |||
@@ -25,6 +25,11 @@ config S3C2416_DMA | |||
25 | help | 25 | help |
26 | Internal config node for S3C2416 DMA support | 26 | Internal config node for S3C2416 DMA support |
27 | 27 | ||
28 | config S3C2416_PM | ||
29 | bool | ||
30 | help | ||
31 | Internal config node to apply S3C2416 power management | ||
32 | |||
28 | menu "S3C2416 Machines" | 33 | menu "S3C2416 Machines" |
29 | 34 | ||
30 | config MACH_SMDK2416 | 35 | config MACH_SMDK2416 |
@@ -33,6 +38,7 @@ config MACH_SMDK2416 | |||
33 | select S3C_DEV_FB | 38 | select S3C_DEV_FB |
34 | select S3C_DEV_HSMMC | 39 | select S3C_DEV_HSMMC |
35 | select S3C_DEV_HSMMC1 | 40 | select S3C_DEV_HSMMC1 |
41 | select S3C2416_PM if PM | ||
36 | help | 42 | help |
37 | Say Y here if you are using an SMDK2416 | 43 | Say Y here if you are using an SMDK2416 |
38 | 44 | ||
diff --git a/arch/arm/mach-s3c2416/Makefile b/arch/arm/mach-s3c2416/Makefile index 6c12c7bf40ad..ef038d62ffdb 100644 --- a/arch/arm/mach-s3c2416/Makefile +++ b/arch/arm/mach-s3c2416/Makefile | |||
@@ -11,7 +11,7 @@ obj- := | |||
11 | 11 | ||
12 | obj-$(CONFIG_CPU_S3C2416) += s3c2416.o clock.o | 12 | obj-$(CONFIG_CPU_S3C2416) += s3c2416.o clock.o |
13 | obj-$(CONFIG_CPU_S3C2416) += irq.o | 13 | obj-$(CONFIG_CPU_S3C2416) += irq.o |
14 | 14 | obj-$(CONFIG_S3C2416_PM) += pm.o | |
15 | #obj-$(CONFIG_S3C2416_DMA) += dma.o | 15 | #obj-$(CONFIG_S3C2416_DMA) += dma.o |
16 | 16 | ||
17 | # Machine support | 17 | # Machine support |
diff --git a/arch/arm/mach-s3c2416/irq.c b/arch/arm/mach-s3c2416/irq.c index 89f521d59d06..084d121f368c 100644 --- a/arch/arm/mach-s3c2416/irq.c +++ b/arch/arm/mach-s3c2416/irq.c | |||
@@ -243,6 +243,8 @@ static int __init s3c2416_irq_add(struct sys_device *sysdev) | |||
243 | 243 | ||
244 | static struct sysdev_driver s3c2416_irq_driver = { | 244 | static struct sysdev_driver s3c2416_irq_driver = { |
245 | .add = s3c2416_irq_add, | 245 | .add = s3c2416_irq_add, |
246 | .suspend = s3c24xx_irq_suspend, | ||
247 | .resume = s3c24xx_irq_resume, | ||
246 | }; | 248 | }; |
247 | 249 | ||
248 | static int __init s3c2416_irq_init(void) | 250 | static int __init s3c2416_irq_init(void) |
diff --git a/arch/arm/mach-s3c2416/pm.c b/arch/arm/mach-s3c2416/pm.c new file mode 100644 index 000000000000..4a04205b04d5 --- /dev/null +++ b/arch/arm/mach-s3c2416/pm.c | |||
@@ -0,0 +1,84 @@ | |||
1 | /* linux/arch/arm/mach-s3c2416/pm.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * S3C2416 - PM support (Based on Ben Dooks' S3C2412 PM support) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/sysdev.h> | ||
14 | #include <linux/io.h> | ||
15 | |||
16 | #include <asm/cacheflush.h> | ||
17 | |||
18 | #include <mach/regs-power.h> | ||
19 | #include <mach/regs-s3c2443-clock.h> | ||
20 | |||
21 | #include <plat/cpu.h> | ||
22 | #include <plat/pm.h> | ||
23 | |||
24 | extern void s3c2412_sleep_enter(void); | ||
25 | |||
26 | static void s3c2416_cpu_suspend(void) | ||
27 | { | ||
28 | flush_cache_all(); | ||
29 | |||
30 | /* enable wakeup sources regardless of battery state */ | ||
31 | __raw_writel(S3C2443_PWRCFG_SLEEP, S3C2443_PWRCFG); | ||
32 | |||
33 | /* set the mode as sleep, 2BED represents "Go to BED" */ | ||
34 | __raw_writel(0x2BED, S3C2443_PWRMODE); | ||
35 | |||
36 | s3c2412_sleep_enter(); | ||
37 | } | ||
38 | |||
39 | static void s3c2416_pm_prepare(void) | ||
40 | { | ||
41 | /* | ||
42 | * write the magic value u-boot uses to check for resume into | ||
43 | * the INFORM0 register, and ensure INFORM1 is set to the | ||
44 | * correct address to resume from. | ||
45 | */ | ||
46 | __raw_writel(0x2BED, S3C2412_INFORM0); | ||
47 | __raw_writel(virt_to_phys(s3c_cpu_resume), S3C2412_INFORM1); | ||
48 | } | ||
49 | |||
50 | static int s3c2416_pm_add(struct sys_device *sysdev) | ||
51 | { | ||
52 | pm_cpu_prep = s3c2416_pm_prepare; | ||
53 | pm_cpu_sleep = s3c2416_cpu_suspend; | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static int s3c2416_pm_suspend(struct sys_device *dev, pm_message_t state) | ||
59 | { | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | static int s3c2416_pm_resume(struct sys_device *dev) | ||
64 | { | ||
65 | /* unset the return-from-sleep amd inform flags */ | ||
66 | __raw_writel(0x0, S3C2443_PWRMODE); | ||
67 | __raw_writel(0x0, S3C2412_INFORM0); | ||
68 | __raw_writel(0x0, S3C2412_INFORM1); | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static struct sysdev_driver s3c2416_pm_driver = { | ||
74 | .add = s3c2416_pm_add, | ||
75 | .suspend = s3c2416_pm_suspend, | ||
76 | .resume = s3c2416_pm_resume, | ||
77 | }; | ||
78 | |||
79 | static __init int s3c2416_pm_init(void) | ||
80 | { | ||
81 | return sysdev_driver_register(&s3c2416_sysclass, &s3c2416_pm_driver); | ||
82 | } | ||
83 | |||
84 | arch_initcall(s3c2416_pm_init); | ||
diff --git a/arch/arm/mach-s3c2416/s3c2416.c b/arch/arm/mach-s3c2416/s3c2416.c index bc30245e133b..63f39cdc0972 100644 --- a/arch/arm/mach-s3c2416/s3c2416.c +++ b/arch/arm/mach-s3c2416/s3c2416.c | |||
@@ -56,6 +56,7 @@ | |||
56 | 56 | ||
57 | #include <plat/iic-core.h> | 57 | #include <plat/iic-core.h> |
58 | #include <plat/fb-core.h> | 58 | #include <plat/fb-core.h> |
59 | #include <plat/nand-core.h> | ||
59 | 60 | ||
60 | static struct map_desc s3c2416_iodesc[] __initdata = { | 61 | static struct map_desc s3c2416_iodesc[] __initdata = { |
61 | IODESC_ENT(WATCHDOG), | 62 | IODESC_ENT(WATCHDOG), |
@@ -100,7 +101,7 @@ void __init s3c2416_init_uarts(struct s3c2410_uartcfg *cfg, int no) | |||
100 | { | 101 | { |
101 | s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no); | 102 | s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no); |
102 | 103 | ||
103 | s3c_device_nand.name = "s3c2416-nand"; | 104 | s3c_nand_setname("s3c2412-nand"); |
104 | } | 105 | } |
105 | 106 | ||
106 | /* s3c2416_map_io | 107 | /* s3c2416_map_io |
diff --git a/arch/arm/mach-s3c2440/s3c244x.c b/arch/arm/mach-s3c2440/s3c244x.c index 5e4a97e76533..90c1707b9c95 100644 --- a/arch/arm/mach-s3c2440/s3c244x.c +++ b/arch/arm/mach-s3c2440/s3c244x.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <plat/cpu.h> | 44 | #include <plat/cpu.h> |
45 | #include <plat/pm.h> | 45 | #include <plat/pm.h> |
46 | #include <plat/pll.h> | 46 | #include <plat/pll.h> |
47 | #include <plat/nand-core.h> | ||
47 | 48 | ||
48 | static struct map_desc s3c244x_iodesc[] __initdata = { | 49 | static struct map_desc s3c244x_iodesc[] __initdata = { |
49 | IODESC_ENT(CLKPWR), | 50 | IODESC_ENT(CLKPWR), |
@@ -68,7 +69,7 @@ void __init s3c244x_map_io(void) | |||
68 | 69 | ||
69 | s3c_device_sdi.name = "s3c2440-sdi"; | 70 | s3c_device_sdi.name = "s3c2440-sdi"; |
70 | s3c_device_i2c0.name = "s3c2440-i2c"; | 71 | s3c_device_i2c0.name = "s3c2440-i2c"; |
71 | s3c_device_nand.name = "s3c2440-nand"; | 72 | s3c_nand_setname("s3c2440-nand"); |
72 | s3c_device_ts.name = "s3c2440-ts"; | 73 | s3c_device_ts.name = "s3c2440-ts"; |
73 | s3c_device_usbgadget.name = "s3c2440-usbgadget"; | 74 | s3c_device_usbgadget.name = "s3c2440-usbgadget"; |
74 | } | 75 | } |
diff --git a/arch/arm/mach-s3c2443/s3c2443.c b/arch/arm/mach-s3c2443/s3c2443.c index 839b6b2ced74..33d18dd1ebd5 100644 --- a/arch/arm/mach-s3c2443/s3c2443.c +++ b/arch/arm/mach-s3c2443/s3c2443.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <plat/devs.h> | 36 | #include <plat/devs.h> |
37 | #include <plat/cpu.h> | 37 | #include <plat/cpu.h> |
38 | #include <plat/fb-core.h> | 38 | #include <plat/fb-core.h> |
39 | #include <plat/nand-core.h> | ||
39 | 40 | ||
40 | static struct map_desc s3c2443_iodesc[] __initdata = { | 41 | static struct map_desc s3c2443_iodesc[] __initdata = { |
41 | IODESC_ENT(WATCHDOG), | 42 | IODESC_ENT(WATCHDOG), |
@@ -62,7 +63,7 @@ int __init s3c2443_init(void) | |||
62 | 63 | ||
63 | s3c24xx_reset_hook = s3c2443_hard_reset; | 64 | s3c24xx_reset_hook = s3c2443_hard_reset; |
64 | 65 | ||
65 | s3c_device_nand.name = "s3c2412-nand"; | 66 | s3c_nand_setname("s3c2412-nand"); |
66 | s3c_fb_setname("s3c2443-fb"); | 67 | s3c_fb_setname("s3c2443-fb"); |
67 | 68 | ||
68 | /* change WDT IRQ number */ | 69 | /* change WDT IRQ number */ |
diff --git a/arch/arm/mach-s3c24a0/include/mach/vmalloc.h b/arch/arm/mach-s3c24a0/include/mach/vmalloc.h index 914656820794..6480b15277f3 100644 --- a/arch/arm/mach-s3c24a0/include/mach/vmalloc.h +++ b/arch/arm/mach-s3c24a0/include/mach/vmalloc.h | |||
@@ -12,6 +12,6 @@ | |||
12 | #ifndef __ASM_ARCH_VMALLOC_H | 12 | #ifndef __ASM_ARCH_VMALLOC_H |
13 | #define __ASM_ARCH_VMALLOC_H | 13 | #define __ASM_ARCH_VMALLOC_H |
14 | 14 | ||
15 | #define VMALLOC_END (0xe0000000UL) | 15 | #define VMALLOC_END 0xF6000000UL |
16 | 16 | ||
17 | #endif /* __ASM_ARCH_VMALLOC_H */ | 17 | #endif /* __ASM_ARCH_VMALLOC_H */ |
diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig index 546db5cb8929..1ca7bdc6485c 100644 --- a/arch/arm/mach-s3c64xx/Kconfig +++ b/arch/arm/mach-s3c64xx/Kconfig | |||
@@ -98,12 +98,33 @@ config MACH_ANW6410 | |||
98 | help | 98 | help |
99 | Machine support for the A&W6410 | 99 | Machine support for the A&W6410 |
100 | 100 | ||
101 | config MACH_MINI6410 | ||
102 | bool "MINI6410" | ||
103 | select CPU_S3C6410 | ||
104 | select S3C_DEV_HSMMC | ||
105 | select S3C_DEV_HSMMC1 | ||
106 | select S3C64XX_SETUP_SDHCI | ||
107 | select S3C_DEV_USB_HOST | ||
108 | select S3C_DEV_NAND | ||
109 | select S3C_DEV_FB | ||
110 | select S3C64XX_SETUP_FB_24BPP | ||
111 | select SAMSUNG_DEV_ADC | ||
112 | select SAMSUNG_DEV_TS | ||
113 | help | ||
114 | Machine support for the FriendlyARM MINI6410 | ||
115 | |||
101 | config MACH_REAL6410 | 116 | config MACH_REAL6410 |
102 | bool "REAL6410" | 117 | bool "REAL6410" |
103 | select CPU_S3C6410 | 118 | select CPU_S3C6410 |
104 | select S3C_DEV_HSMMC | 119 | select S3C_DEV_HSMMC |
105 | select S3C_DEV_HSMMC1 | 120 | select S3C_DEV_HSMMC1 |
106 | select S3C64XX_SETUP_SDHCI | 121 | select S3C64XX_SETUP_SDHCI |
122 | select S3C_DEV_FB | ||
123 | select S3C64XX_SETUP_FB_24BPP | ||
124 | select S3C_DEV_NAND | ||
125 | select SAMSUNG_DEV_ADC | ||
126 | select SAMSUNG_DEV_TS | ||
127 | select S3C_DEV_USB_HOST | ||
107 | help | 128 | help |
108 | Machine support for the CoreWind REAL6410 | 129 | Machine support for the CoreWind REAL6410 |
109 | 130 | ||
diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile index 90221a2e0c55..4657363f0674 100644 --- a/arch/arm/mach-s3c64xx/Makefile +++ b/arch/arm/mach-s3c64xx/Makefile | |||
@@ -53,6 +53,7 @@ obj-$(CONFIG_MACH_ANW6410) += mach-anw6410.o | |||
53 | obj-$(CONFIG_MACH_SMDK6400) += mach-smdk6400.o | 53 | obj-$(CONFIG_MACH_SMDK6400) += mach-smdk6400.o |
54 | obj-$(CONFIG_MACH_SMDK6410) += mach-smdk6410.o | 54 | obj-$(CONFIG_MACH_SMDK6410) += mach-smdk6410.o |
55 | obj-$(CONFIG_MACH_REAL6410) += mach-real6410.o | 55 | obj-$(CONFIG_MACH_REAL6410) += mach-real6410.o |
56 | obj-$(CONFIG_MACH_MINI6410) += mach-mini6410.o | ||
56 | obj-$(CONFIG_MACH_NCP) += mach-ncp.o | 57 | obj-$(CONFIG_MACH_NCP) += mach-ncp.o |
57 | obj-$(CONFIG_MACH_HMT) += mach-hmt.o | 58 | obj-$(CONFIG_MACH_HMT) += mach-hmt.o |
58 | obj-$(CONFIG_MACH_SMARTQ) += mach-smartq.o | 59 | obj-$(CONFIG_MACH_SMARTQ) += mach-smartq.o |
diff --git a/arch/arm/mach-s3c64xx/dev-audio.c b/arch/arm/mach-s3c64xx/dev-audio.c index 3838335f125b..76426a32c013 100644 --- a/arch/arm/mach-s3c64xx/dev-audio.c +++ b/arch/arm/mach-s3c64xx/dev-audio.c | |||
@@ -22,27 +22,16 @@ | |||
22 | #include <plat/audio.h> | 22 | #include <plat/audio.h> |
23 | #include <plat/gpio-cfg.h> | 23 | #include <plat/gpio-cfg.h> |
24 | 24 | ||
25 | #include <mach/gpio-bank-c.h> | ||
26 | #include <mach/gpio-bank-d.h> | ||
27 | #include <mach/gpio-bank-e.h> | ||
28 | #include <mach/gpio-bank-h.h> | ||
29 | |||
30 | static int s3c64xx_i2sv3_cfg_gpio(struct platform_device *pdev) | 25 | static int s3c64xx_i2sv3_cfg_gpio(struct platform_device *pdev) |
31 | { | 26 | { |
27 | unsigned int base; | ||
28 | |||
32 | switch (pdev->id) { | 29 | switch (pdev->id) { |
33 | case 0: | 30 | case 0: |
34 | s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_I2S0_CLK); | 31 | base = S3C64XX_GPD(0); |
35 | s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_I2S0_CDCLK); | ||
36 | s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_I2S0_LRCLK); | ||
37 | s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_I2S0_DI); | ||
38 | s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_I2S0_D0); | ||
39 | break; | 32 | break; |
40 | case 1: | 33 | case 1: |
41 | s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_I2S1_CLK); | 34 | base = S3C64XX_GPE(0); |
42 | s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_I2S1_CDCLK); | ||
43 | s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_I2S1_LRCLK); | ||
44 | s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_I2S1_DI); | ||
45 | s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_I2S1_D0); | ||
46 | break; | 35 | break; |
47 | default: | 36 | default: |
48 | printk(KERN_DEBUG "Invalid I2S Controller number: %d\n", | 37 | printk(KERN_DEBUG "Invalid I2S Controller number: %d\n", |
@@ -50,18 +39,17 @@ static int s3c64xx_i2sv3_cfg_gpio(struct platform_device *pdev) | |||
50 | return -EINVAL; | 39 | return -EINVAL; |
51 | } | 40 | } |
52 | 41 | ||
42 | s3c_gpio_cfgpin_range(base, 5, S3C_GPIO_SFN(3)); | ||
43 | |||
53 | return 0; | 44 | return 0; |
54 | } | 45 | } |
55 | 46 | ||
56 | static int s3c64xx_i2sv4_cfg_gpio(struct platform_device *pdev) | 47 | static int s3c64xx_i2sv4_cfg_gpio(struct platform_device *pdev) |
57 | { | 48 | { |
58 | s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C64XX_GPC4_I2S_V40_DO0); | 49 | s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C_GPIO_SFN(5)); |
59 | s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C64XX_GPC5_I2S_V40_DO1); | 50 | s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C_GPIO_SFN(5)); |
60 | s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C64XX_GPC7_I2S_V40_DO2); | 51 | s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C_GPIO_SFN(5)); |
61 | s3c_gpio_cfgpin(S3C64XX_GPH(6), S3C64XX_GPH6_I2S_V40_BCLK); | 52 | s3c_gpio_cfgpin_range(S3C64XX_GPH(6), 4, S3C_GPIO_SFN(5)); |
62 | s3c_gpio_cfgpin(S3C64XX_GPH(7), S3C64XX_GPH7_I2S_V40_CDCLK); | ||
63 | s3c_gpio_cfgpin(S3C64XX_GPH(8), S3C64XX_GPH8_I2S_V40_LRCLK); | ||
64 | s3c_gpio_cfgpin(S3C64XX_GPH(9), S3C64XX_GPH9_I2S_V40_DI); | ||
65 | 53 | ||
66 | return 0; | 54 | return 0; |
67 | } | 55 | } |
@@ -170,20 +158,14 @@ EXPORT_SYMBOL(s3c64xx_device_iisv4); | |||
170 | 158 | ||
171 | static int s3c64xx_pcm_cfg_gpio(struct platform_device *pdev) | 159 | static int s3c64xx_pcm_cfg_gpio(struct platform_device *pdev) |
172 | { | 160 | { |
161 | unsigned int base; | ||
162 | |||
173 | switch (pdev->id) { | 163 | switch (pdev->id) { |
174 | case 0: | 164 | case 0: |
175 | s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_PCM0_SCLK); | 165 | base = S3C64XX_GPD(0); |
176 | s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_PCM0_EXTCLK); | ||
177 | s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_PCM0_FSYNC); | ||
178 | s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_PCM0_SIN); | ||
179 | s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_PCM0_SOUT); | ||
180 | break; | 166 | break; |
181 | case 1: | 167 | case 1: |
182 | s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_PCM1_SCLK); | 168 | base = S3C64XX_GPE(0); |
183 | s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_PCM1_EXTCLK); | ||
184 | s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_PCM1_FSYNC); | ||
185 | s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_PCM1_SIN); | ||
186 | s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_PCM1_SOUT); | ||
187 | break; | 169 | break; |
188 | default: | 170 | default: |
189 | printk(KERN_DEBUG "Invalid PCM Controller number: %d\n", | 171 | printk(KERN_DEBUG "Invalid PCM Controller number: %d\n", |
@@ -191,6 +173,7 @@ static int s3c64xx_pcm_cfg_gpio(struct platform_device *pdev) | |||
191 | return -EINVAL; | 173 | return -EINVAL; |
192 | } | 174 | } |
193 | 175 | ||
176 | s3c_gpio_cfgpin_range(base, 5, S3C_GPIO_SFN(2)); | ||
194 | return 0; | 177 | return 0; |
195 | } | 178 | } |
196 | 179 | ||
@@ -264,24 +247,12 @@ EXPORT_SYMBOL(s3c64xx_device_pcm1); | |||
264 | 247 | ||
265 | static int s3c64xx_ac97_cfg_gpd(struct platform_device *pdev) | 248 | static int s3c64xx_ac97_cfg_gpd(struct platform_device *pdev) |
266 | { | 249 | { |
267 | s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_AC97_BITCLK); | 250 | return s3c_gpio_cfgpin_range(S3C64XX_GPD(0), 5, S3C_GPIO_SFN(4)); |
268 | s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_AC97_nRESET); | ||
269 | s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_AC97_SYNC); | ||
270 | s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_AC97_SDI); | ||
271 | s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_AC97_SDO); | ||
272 | |||
273 | return 0; | ||
274 | } | 251 | } |
275 | 252 | ||
276 | static int s3c64xx_ac97_cfg_gpe(struct platform_device *pdev) | 253 | static int s3c64xx_ac97_cfg_gpe(struct platform_device *pdev) |
277 | { | 254 | { |
278 | s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_AC97_BITCLK); | 255 | return s3c_gpio_cfgpin_range(S3C64XX_GPE(0), 5, S3C_GPIO_SFN(4)); |
279 | s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_AC97_nRESET); | ||
280 | s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_AC97_SYNC); | ||
281 | s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_AC97_SDI); | ||
282 | s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_AC97_SDO); | ||
283 | |||
284 | return 0; | ||
285 | } | 256 | } |
286 | 257 | ||
287 | static struct resource s3c64xx_ac97_resource[] = { | 258 | static struct resource s3c64xx_ac97_resource[] = { |
diff --git a/arch/arm/mach-s3c64xx/gpiolib.c b/arch/arm/mach-s3c64xx/gpiolib.c index 300dee4a667b..fd99a82e82c4 100644 --- a/arch/arm/mach-s3c64xx/gpiolib.c +++ b/arch/arm/mach-s3c64xx/gpiolib.c | |||
@@ -195,11 +195,6 @@ static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = { | |||
195 | .get_pull = s3c_gpio_getpull_updown, | 195 | .get_pull = s3c_gpio_getpull_updown, |
196 | }; | 196 | }; |
197 | 197 | ||
198 | int s3c64xx_gpio2int_gpn(struct gpio_chip *chip, unsigned pin) | ||
199 | { | ||
200 | return IRQ_EINT(0) + pin; | ||
201 | } | ||
202 | |||
203 | static struct s3c_gpio_chip gpio_2bit[] = { | 198 | static struct s3c_gpio_chip gpio_2bit[] = { |
204 | { | 199 | { |
205 | .base = S3C64XX_GPF_BASE, | 200 | .base = S3C64XX_GPF_BASE, |
@@ -227,12 +222,13 @@ static struct s3c_gpio_chip gpio_2bit[] = { | |||
227 | }, | 222 | }, |
228 | }, { | 223 | }, { |
229 | .base = S3C64XX_GPN_BASE, | 224 | .base = S3C64XX_GPN_BASE, |
225 | .irq_base = IRQ_EINT(0), | ||
230 | .config = &gpio_2bit_cfg_eint10, | 226 | .config = &gpio_2bit_cfg_eint10, |
231 | .chip = { | 227 | .chip = { |
232 | .base = S3C64XX_GPN(0), | 228 | .base = S3C64XX_GPN(0), |
233 | .ngpio = S3C64XX_GPIO_N_NR, | 229 | .ngpio = S3C64XX_GPIO_N_NR, |
234 | .label = "GPN", | 230 | .label = "GPN", |
235 | .to_irq = s3c64xx_gpio2int_gpn, | 231 | .to_irq = samsung_gpiolib_to_irq, |
236 | }, | 232 | }, |
237 | }, { | 233 | }, { |
238 | .base = S3C64XX_GPO_BASE, | 234 | .base = S3C64XX_GPO_BASE, |
diff --git a/arch/arm/mach-s3c64xx/include/mach/vmalloc.h b/arch/arm/mach-s3c64xx/include/mach/vmalloc.h index bc0e91389864..23f75e556a30 100644 --- a/arch/arm/mach-s3c64xx/include/mach/vmalloc.h +++ b/arch/arm/mach-s3c64xx/include/mach/vmalloc.h | |||
@@ -15,6 +15,6 @@ | |||
15 | #ifndef __ASM_ARCH_VMALLOC_H | 15 | #ifndef __ASM_ARCH_VMALLOC_H |
16 | #define __ASM_ARCH_VMALLOC_H | 16 | #define __ASM_ARCH_VMALLOC_H |
17 | 17 | ||
18 | #define VMALLOC_END 0xE0000000UL | 18 | #define VMALLOC_END 0xF6000000UL |
19 | 19 | ||
20 | #endif /* __ASM_ARCH_VMALLOC_H */ | 20 | #endif /* __ASM_ARCH_VMALLOC_H */ |
diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c new file mode 100644 index 000000000000..249c62956471 --- /dev/null +++ b/arch/arm/mach-s3c64xx/mach-mini6410.c | |||
@@ -0,0 +1,357 @@ | |||
1 | /* linux/arch/arm/mach-s3c64xx/mach-mini6410.c | ||
2 | * | ||
3 | * Copyright 2010 Darius Augulis <augulis.darius@gmail.com> | ||
4 | * Copyright 2008 Openmoko, Inc. | ||
5 | * Copyright 2008 Simtec Electronics | ||
6 | * Ben Dooks <ben@simtec.co.uk> | ||
7 | * http://armlinux.simtec.co.uk/ | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/init.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/fb.h> | ||
18 | #include <linux/gpio.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/list.h> | ||
21 | #include <linux/dm9000.h> | ||
22 | #include <linux/mtd/mtd.h> | ||
23 | #include <linux/mtd/partitions.h> | ||
24 | #include <linux/serial_core.h> | ||
25 | #include <linux/types.h> | ||
26 | |||
27 | #include <asm/mach-types.h> | ||
28 | #include <asm/mach/arch.h> | ||
29 | #include <asm/mach/map.h> | ||
30 | |||
31 | #include <mach/map.h> | ||
32 | #include <mach/regs-fb.h> | ||
33 | #include <mach/regs-gpio.h> | ||
34 | #include <mach/regs-modem.h> | ||
35 | #include <mach/regs-srom.h> | ||
36 | #include <mach/s3c6410.h> | ||
37 | |||
38 | #include <plat/adc.h> | ||
39 | #include <plat/cpu.h> | ||
40 | #include <plat/devs.h> | ||
41 | #include <plat/fb.h> | ||
42 | #include <plat/nand.h> | ||
43 | #include <plat/regs-serial.h> | ||
44 | #include <plat/ts.h> | ||
45 | |||
46 | #include <video/platform_lcd.h> | ||
47 | |||
48 | #define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK) | ||
49 | #define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB) | ||
50 | #define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE) | ||
51 | |||
52 | static struct s3c2410_uartcfg mini6410_uartcfgs[] __initdata = { | ||
53 | [0] = { | ||
54 | .hwport = 0, | ||
55 | .flags = 0, | ||
56 | .ucon = UCON, | ||
57 | .ulcon = ULCON, | ||
58 | .ufcon = UFCON, | ||
59 | }, | ||
60 | [1] = { | ||
61 | .hwport = 1, | ||
62 | .flags = 0, | ||
63 | .ucon = UCON, | ||
64 | .ulcon = ULCON, | ||
65 | .ufcon = UFCON, | ||
66 | }, | ||
67 | [2] = { | ||
68 | .hwport = 2, | ||
69 | .flags = 0, | ||
70 | .ucon = UCON, | ||
71 | .ulcon = ULCON, | ||
72 | .ufcon = UFCON, | ||
73 | }, | ||
74 | [3] = { | ||
75 | .hwport = 3, | ||
76 | .flags = 0, | ||
77 | .ucon = UCON, | ||
78 | .ulcon = ULCON, | ||
79 | .ufcon = UFCON, | ||
80 | }, | ||
81 | }; | ||
82 | |||
83 | /* DM9000AEP 10/100 ethernet controller */ | ||
84 | |||
85 | static struct resource mini6410_dm9k_resource[] = { | ||
86 | [0] = { | ||
87 | .start = S3C64XX_PA_XM0CSN1, | ||
88 | .end = S3C64XX_PA_XM0CSN1 + 1, | ||
89 | .flags = IORESOURCE_MEM | ||
90 | }, | ||
91 | [1] = { | ||
92 | .start = S3C64XX_PA_XM0CSN1 + 4, | ||
93 | .end = S3C64XX_PA_XM0CSN1 + 5, | ||
94 | .flags = IORESOURCE_MEM | ||
95 | }, | ||
96 | [2] = { | ||
97 | .start = S3C_EINT(7), | ||
98 | .end = S3C_EINT(7), | ||
99 | .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | ||
100 | } | ||
101 | }; | ||
102 | |||
103 | static struct dm9000_plat_data mini6410_dm9k_pdata = { | ||
104 | .flags = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM), | ||
105 | }; | ||
106 | |||
107 | static struct platform_device mini6410_device_eth = { | ||
108 | .name = "dm9000", | ||
109 | .id = -1, | ||
110 | .num_resources = ARRAY_SIZE(mini6410_dm9k_resource), | ||
111 | .resource = mini6410_dm9k_resource, | ||
112 | .dev = { | ||
113 | .platform_data = &mini6410_dm9k_pdata, | ||
114 | }, | ||
115 | }; | ||
116 | |||
117 | static struct mtd_partition mini6410_nand_part[] = { | ||
118 | [0] = { | ||
119 | .name = "uboot", | ||
120 | .size = SZ_1M, | ||
121 | .offset = 0, | ||
122 | }, | ||
123 | [1] = { | ||
124 | .name = "kernel", | ||
125 | .size = SZ_2M, | ||
126 | .offset = SZ_1M, | ||
127 | }, | ||
128 | [2] = { | ||
129 | .name = "rootfs", | ||
130 | .size = MTDPART_SIZ_FULL, | ||
131 | .offset = SZ_1M + SZ_2M, | ||
132 | }, | ||
133 | }; | ||
134 | |||
135 | static struct s3c2410_nand_set mini6410_nand_sets[] = { | ||
136 | [0] = { | ||
137 | .name = "nand", | ||
138 | .nr_chips = 1, | ||
139 | .nr_partitions = ARRAY_SIZE(mini6410_nand_part), | ||
140 | .partitions = mini6410_nand_part, | ||
141 | }, | ||
142 | }; | ||
143 | |||
144 | static struct s3c2410_platform_nand mini6410_nand_info = { | ||
145 | .tacls = 25, | ||
146 | .twrph0 = 55, | ||
147 | .twrph1 = 40, | ||
148 | .nr_sets = ARRAY_SIZE(mini6410_nand_sets), | ||
149 | .sets = mini6410_nand_sets, | ||
150 | }; | ||
151 | |||
152 | static struct s3c_fb_pd_win mini6410_fb_win[] = { | ||
153 | { | ||
154 | .win_mode = { /* 4.3" 480x272 */ | ||
155 | .left_margin = 3, | ||
156 | .right_margin = 2, | ||
157 | .upper_margin = 1, | ||
158 | .lower_margin = 1, | ||
159 | .hsync_len = 40, | ||
160 | .vsync_len = 1, | ||
161 | .xres = 480, | ||
162 | .yres = 272, | ||
163 | }, | ||
164 | .max_bpp = 32, | ||
165 | .default_bpp = 16, | ||
166 | }, { | ||
167 | .win_mode = { /* 7.0" 800x480 */ | ||
168 | .left_margin = 8, | ||
169 | .right_margin = 13, | ||
170 | .upper_margin = 7, | ||
171 | .lower_margin = 5, | ||
172 | .hsync_len = 3, | ||
173 | .vsync_len = 1, | ||
174 | .xres = 800, | ||
175 | .yres = 480, | ||
176 | }, | ||
177 | .max_bpp = 32, | ||
178 | .default_bpp = 16, | ||
179 | }, | ||
180 | }; | ||
181 | |||
182 | static struct s3c_fb_platdata mini6410_lcd_pdata __initdata = { | ||
183 | .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, | ||
184 | .win[0] = &mini6410_fb_win[0], | ||
185 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, | ||
186 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, | ||
187 | }; | ||
188 | |||
189 | static void mini6410_lcd_power_set(struct plat_lcd_data *pd, | ||
190 | unsigned int power) | ||
191 | { | ||
192 | if (power) | ||
193 | gpio_direction_output(S3C64XX_GPE(0), 1); | ||
194 | else | ||
195 | gpio_direction_output(S3C64XX_GPE(0), 0); | ||
196 | } | ||
197 | |||
198 | static struct plat_lcd_data mini6410_lcd_power_data = { | ||
199 | .set_power = mini6410_lcd_power_set, | ||
200 | }; | ||
201 | |||
202 | static struct platform_device mini6410_lcd_powerdev = { | ||
203 | .name = "platform-lcd", | ||
204 | .dev.parent = &s3c_device_fb.dev, | ||
205 | .dev.platform_data = &mini6410_lcd_power_data, | ||
206 | }; | ||
207 | |||
208 | static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = { | ||
209 | .delay = 10000, | ||
210 | .presc = 49, | ||
211 | .oversampling_shift = 2, | ||
212 | }; | ||
213 | |||
214 | static struct platform_device *mini6410_devices[] __initdata = { | ||
215 | &mini6410_device_eth, | ||
216 | &s3c_device_hsmmc0, | ||
217 | &s3c_device_hsmmc1, | ||
218 | &s3c_device_ohci, | ||
219 | &s3c_device_nand, | ||
220 | &s3c_device_fb, | ||
221 | &mini6410_lcd_powerdev, | ||
222 | &s3c_device_adc, | ||
223 | &s3c_device_ts, | ||
224 | }; | ||
225 | |||
226 | static void __init mini6410_map_io(void) | ||
227 | { | ||
228 | u32 tmp; | ||
229 | |||
230 | s3c64xx_init_io(NULL, 0); | ||
231 | s3c24xx_init_clocks(12000000); | ||
232 | s3c24xx_init_uarts(mini6410_uartcfgs, ARRAY_SIZE(mini6410_uartcfgs)); | ||
233 | |||
234 | /* set the LCD type */ | ||
235 | tmp = __raw_readl(S3C64XX_SPCON); | ||
236 | tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK; | ||
237 | tmp |= S3C64XX_SPCON_LCD_SEL_RGB; | ||
238 | __raw_writel(tmp, S3C64XX_SPCON); | ||
239 | |||
240 | /* remove the LCD bypass */ | ||
241 | tmp = __raw_readl(S3C64XX_MODEM_MIFPCON); | ||
242 | tmp &= ~MIFPCON_LCD_BYPASS; | ||
243 | __raw_writel(tmp, S3C64XX_MODEM_MIFPCON); | ||
244 | } | ||
245 | |||
246 | /* | ||
247 | * mini6410_features string | ||
248 | * | ||
249 | * 0-9 LCD configuration | ||
250 | * | ||
251 | */ | ||
252 | static char mini6410_features_str[12] __initdata = "0"; | ||
253 | |||
254 | static int __init mini6410_features_setup(char *str) | ||
255 | { | ||
256 | if (str) | ||
257 | strlcpy(mini6410_features_str, str, | ||
258 | sizeof(mini6410_features_str)); | ||
259 | return 1; | ||
260 | } | ||
261 | |||
262 | __setup("mini6410=", mini6410_features_setup); | ||
263 | |||
264 | #define FEATURE_SCREEN (1 << 0) | ||
265 | |||
266 | struct mini6410_features_t { | ||
267 | int done; | ||
268 | int lcd_index; | ||
269 | }; | ||
270 | |||
271 | static void mini6410_parse_features( | ||
272 | struct mini6410_features_t *features, | ||
273 | const char *features_str) | ||
274 | { | ||
275 | const char *fp = features_str; | ||
276 | |||
277 | features->done = 0; | ||
278 | features->lcd_index = 0; | ||
279 | |||
280 | while (*fp) { | ||
281 | char f = *fp++; | ||
282 | |||
283 | switch (f) { | ||
284 | case '0'...'9': /* tft screen */ | ||
285 | if (features->done & FEATURE_SCREEN) { | ||
286 | printk(KERN_INFO "MINI6410: '%c' ignored, " | ||
287 | "screen type already set\n", f); | ||
288 | } else { | ||
289 | int li = f - '0'; | ||
290 | if (li >= ARRAY_SIZE(mini6410_fb_win)) | ||
291 | printk(KERN_INFO "MINI6410: '%c' out " | ||
292 | "of range LCD mode\n", f); | ||
293 | else { | ||
294 | features->lcd_index = li; | ||
295 | } | ||
296 | } | ||
297 | features->done |= FEATURE_SCREEN; | ||
298 | break; | ||
299 | } | ||
300 | } | ||
301 | } | ||
302 | |||
303 | static void __init mini6410_machine_init(void) | ||
304 | { | ||
305 | u32 cs1; | ||
306 | struct mini6410_features_t features = { 0 }; | ||
307 | |||
308 | printk(KERN_INFO "MINI6410: Option string mini6410=%s\n", | ||
309 | mini6410_features_str); | ||
310 | |||
311 | /* Parse the feature string */ | ||
312 | mini6410_parse_features(&features, mini6410_features_str); | ||
313 | |||
314 | mini6410_lcd_pdata.win[0] = &mini6410_fb_win[features.lcd_index]; | ||
315 | |||
316 | printk(KERN_INFO "MINI6410: selected LCD display is %dx%d\n", | ||
317 | mini6410_lcd_pdata.win[0]->win_mode.xres, | ||
318 | mini6410_lcd_pdata.win[0]->win_mode.yres); | ||
319 | |||
320 | s3c_nand_set_platdata(&mini6410_nand_info); | ||
321 | s3c_fb_set_platdata(&mini6410_lcd_pdata); | ||
322 | s3c24xx_ts_set_platdata(&s3c_ts_platform); | ||
323 | |||
324 | /* configure nCS1 width to 16 bits */ | ||
325 | |||
326 | cs1 = __raw_readl(S3C64XX_SROM_BW) & | ||
327 | ~(S3C64XX_SROM_BW__CS_MASK << S3C64XX_SROM_BW__NCS1__SHIFT); | ||
328 | cs1 |= ((1 << S3C64XX_SROM_BW__DATAWIDTH__SHIFT) | | ||
329 | (1 << S3C64XX_SROM_BW__WAITENABLE__SHIFT) | | ||
330 | (1 << S3C64XX_SROM_BW__BYTEENABLE__SHIFT)) << | ||
331 | S3C64XX_SROM_BW__NCS1__SHIFT; | ||
332 | __raw_writel(cs1, S3C64XX_SROM_BW); | ||
333 | |||
334 | /* set timing for nCS1 suitable for ethernet chip */ | ||
335 | |||
336 | __raw_writel((0 << S3C64XX_SROM_BCX__PMC__SHIFT) | | ||
337 | (6 << S3C64XX_SROM_BCX__TACP__SHIFT) | | ||
338 | (4 << S3C64XX_SROM_BCX__TCAH__SHIFT) | | ||
339 | (1 << S3C64XX_SROM_BCX__TCOH__SHIFT) | | ||
340 | (13 << S3C64XX_SROM_BCX__TACC__SHIFT) | | ||
341 | (4 << S3C64XX_SROM_BCX__TCOS__SHIFT) | | ||
342 | (0 << S3C64XX_SROM_BCX__TACS__SHIFT), S3C64XX_SROM_BC1); | ||
343 | |||
344 | gpio_request(S3C64XX_GPF(15), "LCD power"); | ||
345 | gpio_request(S3C64XX_GPE(0), "LCD power"); | ||
346 | |||
347 | platform_add_devices(mini6410_devices, ARRAY_SIZE(mini6410_devices)); | ||
348 | } | ||
349 | |||
350 | MACHINE_START(MINI6410, "MINI6410") | ||
351 | /* Maintainer: Darius Augulis <augulis.darius@gmail.com> */ | ||
352 | .boot_params = S3C64XX_PA_SDRAM + 0x100, | ||
353 | .init_irq = s3c6410_init_irq, | ||
354 | .map_io = mini6410_map_io, | ||
355 | .init_machine = mini6410_machine_init, | ||
356 | .timer = &s3c24xx_timer, | ||
357 | MACHINE_END | ||
diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c index 4b4475da8ec6..f9ef9b5c5f5a 100644 --- a/arch/arm/mach-s3c64xx/mach-real6410.c +++ b/arch/arm/mach-s3c64xx/mach-real6410.c | |||
@@ -12,23 +12,39 @@ | |||
12 | * | 12 | * |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/kernel.h> | 15 | #include <linux/init.h> |
16 | #include <linux/types.h> | ||
17 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/fb.h> | ||
18 | #include <linux/gpio.h> | ||
19 | #include <linux/kernel.h> | ||
18 | #include <linux/list.h> | 20 | #include <linux/list.h> |
19 | #include <linux/init.h> | ||
20 | #include <linux/dm9000.h> | 21 | #include <linux/dm9000.h> |
21 | #include <linux/serial_core.h> | 22 | #include <linux/mtd/mtd.h> |
23 | #include <linux/mtd/partitions.h> | ||
22 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/serial_core.h> | ||
26 | #include <linux/types.h> | ||
27 | |||
23 | #include <asm/mach-types.h> | 28 | #include <asm/mach-types.h> |
24 | #include <asm/mach/arch.h> | 29 | #include <asm/mach/arch.h> |
25 | #include <asm/mach/map.h> | 30 | #include <asm/mach/map.h> |
31 | |||
26 | #include <mach/map.h> | 32 | #include <mach/map.h> |
27 | #include <mach/s3c6410.h> | 33 | #include <mach/regs-fb.h> |
34 | #include <mach/regs-gpio.h> | ||
35 | #include <mach/regs-modem.h> | ||
28 | #include <mach/regs-srom.h> | 36 | #include <mach/regs-srom.h> |
37 | #include <mach/s3c6410.h> | ||
38 | |||
39 | #include <plat/adc.h> | ||
29 | #include <plat/cpu.h> | 40 | #include <plat/cpu.h> |
30 | #include <plat/devs.h> | 41 | #include <plat/devs.h> |
42 | #include <plat/fb.h> | ||
43 | #include <plat/nand.h> | ||
31 | #include <plat/regs-serial.h> | 44 | #include <plat/regs-serial.h> |
45 | #include <plat/ts.h> | ||
46 | |||
47 | #include <video/platform_lcd.h> | ||
32 | 48 | ||
33 | #define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK) | 49 | #define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK) |
34 | #define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB) | 50 | #define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB) |
@@ -99,22 +115,192 @@ static struct platform_device real6410_device_eth = { | |||
99 | }, | 115 | }, |
100 | }; | 116 | }; |
101 | 117 | ||
118 | static struct s3c_fb_pd_win real6410_fb_win[] = { | ||
119 | { | ||
120 | .win_mode = { /* 4.3" 480x272 */ | ||
121 | .left_margin = 3, | ||
122 | .right_margin = 2, | ||
123 | .upper_margin = 1, | ||
124 | .lower_margin = 1, | ||
125 | .hsync_len = 40, | ||
126 | .vsync_len = 1, | ||
127 | .xres = 480, | ||
128 | .yres = 272, | ||
129 | }, | ||
130 | .max_bpp = 32, | ||
131 | .default_bpp = 16, | ||
132 | }, { | ||
133 | .win_mode = { /* 7.0" 800x480 */ | ||
134 | .left_margin = 8, | ||
135 | .right_margin = 13, | ||
136 | .upper_margin = 7, | ||
137 | .lower_margin = 5, | ||
138 | .hsync_len = 3, | ||
139 | .vsync_len = 1, | ||
140 | .xres = 800, | ||
141 | .yres = 480, | ||
142 | }, | ||
143 | .max_bpp = 32, | ||
144 | .default_bpp = 16, | ||
145 | }, | ||
146 | }; | ||
147 | |||
148 | static struct s3c_fb_platdata real6410_lcd_pdata __initdata = { | ||
149 | .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, | ||
150 | .win[0] = &real6410_fb_win[0], | ||
151 | .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, | ||
152 | .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, | ||
153 | }; | ||
154 | |||
155 | static struct mtd_partition real6410_nand_part[] = { | ||
156 | [0] = { | ||
157 | .name = "uboot", | ||
158 | .size = SZ_1M, | ||
159 | .offset = 0, | ||
160 | }, | ||
161 | [1] = { | ||
162 | .name = "kernel", | ||
163 | .size = SZ_2M, | ||
164 | .offset = SZ_1M, | ||
165 | }, | ||
166 | [2] = { | ||
167 | .name = "rootfs", | ||
168 | .size = MTDPART_SIZ_FULL, | ||
169 | .offset = SZ_1M + SZ_2M, | ||
170 | }, | ||
171 | }; | ||
172 | |||
173 | static struct s3c2410_nand_set real6410_nand_sets[] = { | ||
174 | [0] = { | ||
175 | .name = "nand", | ||
176 | .nr_chips = 1, | ||
177 | .nr_partitions = ARRAY_SIZE(real6410_nand_part), | ||
178 | .partitions = real6410_nand_part, | ||
179 | }, | ||
180 | }; | ||
181 | |||
182 | static struct s3c2410_platform_nand real6410_nand_info = { | ||
183 | .tacls = 25, | ||
184 | .twrph0 = 55, | ||
185 | .twrph1 = 40, | ||
186 | .nr_sets = ARRAY_SIZE(real6410_nand_sets), | ||
187 | .sets = real6410_nand_sets, | ||
188 | }; | ||
189 | |||
102 | static struct platform_device *real6410_devices[] __initdata = { | 190 | static struct platform_device *real6410_devices[] __initdata = { |
103 | &real6410_device_eth, | 191 | &real6410_device_eth, |
104 | &s3c_device_hsmmc0, | 192 | &s3c_device_hsmmc0, |
105 | &s3c_device_hsmmc1, | 193 | &s3c_device_hsmmc1, |
194 | &s3c_device_fb, | ||
195 | &s3c_device_nand, | ||
196 | &s3c_device_adc, | ||
197 | &s3c_device_ts, | ||
198 | &s3c_device_ohci, | ||
199 | }; | ||
200 | |||
201 | static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = { | ||
202 | .delay = 10000, | ||
203 | .presc = 49, | ||
204 | .oversampling_shift = 2, | ||
106 | }; | 205 | }; |
107 | 206 | ||
108 | static void __init real6410_map_io(void) | 207 | static void __init real6410_map_io(void) |
109 | { | 208 | { |
209 | u32 tmp; | ||
210 | |||
110 | s3c64xx_init_io(NULL, 0); | 211 | s3c64xx_init_io(NULL, 0); |
111 | s3c24xx_init_clocks(12000000); | 212 | s3c24xx_init_clocks(12000000); |
112 | s3c24xx_init_uarts(real6410_uartcfgs, ARRAY_SIZE(real6410_uartcfgs)); | 213 | s3c24xx_init_uarts(real6410_uartcfgs, ARRAY_SIZE(real6410_uartcfgs)); |
214 | |||
215 | /* set the LCD type */ | ||
216 | tmp = __raw_readl(S3C64XX_SPCON); | ||
217 | tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK; | ||
218 | tmp |= S3C64XX_SPCON_LCD_SEL_RGB; | ||
219 | __raw_writel(tmp, S3C64XX_SPCON); | ||
220 | |||
221 | /* remove the LCD bypass */ | ||
222 | tmp = __raw_readl(S3C64XX_MODEM_MIFPCON); | ||
223 | tmp &= ~MIFPCON_LCD_BYPASS; | ||
224 | __raw_writel(tmp, S3C64XX_MODEM_MIFPCON); | ||
225 | } | ||
226 | |||
227 | /* | ||
228 | * real6410_features string | ||
229 | * | ||
230 | * 0-9 LCD configuration | ||
231 | * | ||
232 | */ | ||
233 | static char real6410_features_str[12] __initdata = "0"; | ||
234 | |||
235 | static int __init real6410_features_setup(char *str) | ||
236 | { | ||
237 | if (str) | ||
238 | strlcpy(real6410_features_str, str, | ||
239 | sizeof(real6410_features_str)); | ||
240 | return 1; | ||
241 | } | ||
242 | |||
243 | __setup("real6410=", real6410_features_setup); | ||
244 | |||
245 | #define FEATURE_SCREEN (1 << 0) | ||
246 | |||
247 | struct real6410_features_t { | ||
248 | int done; | ||
249 | int lcd_index; | ||
250 | }; | ||
251 | |||
252 | static void real6410_parse_features( | ||
253 | struct real6410_features_t *features, | ||
254 | const char *features_str) | ||
255 | { | ||
256 | const char *fp = features_str; | ||
257 | |||
258 | features->done = 0; | ||
259 | features->lcd_index = 0; | ||
260 | |||
261 | while (*fp) { | ||
262 | char f = *fp++; | ||
263 | |||
264 | switch (f) { | ||
265 | case '0'...'9': /* tft screen */ | ||
266 | if (features->done & FEATURE_SCREEN) { | ||
267 | printk(KERN_INFO "REAL6410: '%c' ignored, " | ||
268 | "screen type already set\n", f); | ||
269 | } else { | ||
270 | int li = f - '0'; | ||
271 | if (li >= ARRAY_SIZE(real6410_fb_win)) | ||
272 | printk(KERN_INFO "REAL6410: '%c' out " | ||
273 | "of range LCD mode\n", f); | ||
274 | else { | ||
275 | features->lcd_index = li; | ||
276 | } | ||
277 | } | ||
278 | features->done |= FEATURE_SCREEN; | ||
279 | break; | ||
280 | } | ||
281 | } | ||
113 | } | 282 | } |
114 | 283 | ||
115 | static void __init real6410_machine_init(void) | 284 | static void __init real6410_machine_init(void) |
116 | { | 285 | { |
117 | u32 cs1; | 286 | u32 cs1; |
287 | struct real6410_features_t features = { 0 }; | ||
288 | |||
289 | printk(KERN_INFO "REAL6410: Option string real6410=%s\n", | ||
290 | real6410_features_str); | ||
291 | |||
292 | /* Parse the feature string */ | ||
293 | real6410_parse_features(&features, real6410_features_str); | ||
294 | |||
295 | real6410_lcd_pdata.win[0] = &real6410_fb_win[features.lcd_index]; | ||
296 | |||
297 | printk(KERN_INFO "REAL6410: selected LCD display is %dx%d\n", | ||
298 | real6410_lcd_pdata.win[0]->win_mode.xres, | ||
299 | real6410_lcd_pdata.win[0]->win_mode.yres); | ||
300 | |||
301 | s3c_fb_set_platdata(&real6410_lcd_pdata); | ||
302 | s3c_nand_set_platdata(&real6410_nand_info); | ||
303 | s3c24xx_ts_set_platdata(&s3c_ts_platform); | ||
118 | 304 | ||
119 | /* configure nCS1 width to 16 bits */ | 305 | /* configure nCS1 width to 16 bits */ |
120 | 306 | ||
@@ -136,6 +322,8 @@ static void __init real6410_machine_init(void) | |||
136 | (4 << S3C64XX_SROM_BCX__TCOS__SHIFT) | | 322 | (4 << S3C64XX_SROM_BCX__TCOS__SHIFT) | |
137 | (0 << S3C64XX_SROM_BCX__TACS__SHIFT), S3C64XX_SROM_BC1); | 323 | (0 << S3C64XX_SROM_BCX__TACS__SHIFT), S3C64XX_SROM_BC1); |
138 | 324 | ||
325 | gpio_request(S3C64XX_GPF(15), "LCD power"); | ||
326 | |||
139 | platform_add_devices(real6410_devices, ARRAY_SIZE(real6410_devices)); | 327 | platform_add_devices(real6410_devices, ARRAY_SIZE(real6410_devices)); |
140 | } | 328 | } |
141 | 329 | ||
diff --git a/arch/arm/mach-s3c64xx/setup-fb-24bpp.c b/arch/arm/mach-s3c64xx/setup-fb-24bpp.c index 000736877df2..8f3091182f9c 100644 --- a/arch/arm/mach-s3c64xx/setup-fb-24bpp.c +++ b/arch/arm/mach-s3c64xx/setup-fb-24bpp.c | |||
@@ -23,15 +23,6 @@ | |||
23 | 23 | ||
24 | extern void s3c64xx_fb_gpio_setup_24bpp(void) | 24 | extern void s3c64xx_fb_gpio_setup_24bpp(void) |
25 | { | 25 | { |
26 | unsigned int gpio; | 26 | s3c_gpio_cfgrange_nopull(S3C64XX_GPI(0), 16, S3C_GPIO_SFN(2)); |
27 | 27 | s3c_gpio_cfgrange_nopull(S3C64XX_GPJ(0), 12, S3C_GPIO_SFN(2)); | |
28 | for (gpio = S3C64XX_GPI(0); gpio <= S3C64XX_GPI(15); gpio++) { | ||
29 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
30 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
31 | } | ||
32 | |||
33 | for (gpio = S3C64XX_GPJ(0); gpio <= S3C64XX_GPJ(11); gpio++) { | ||
34 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
35 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
36 | } | ||
37 | } | 28 | } |
diff --git a/arch/arm/mach-s3c64xx/setup-ide.c b/arch/arm/mach-s3c64xx/setup-ide.c index c12c315f33bc..41b425602d88 100644 --- a/arch/arm/mach-s3c64xx/setup-ide.c +++ b/arch/arm/mach-s3c64xx/setup-ide.c | |||
@@ -17,11 +17,11 @@ | |||
17 | #include <mach/map.h> | 17 | #include <mach/map.h> |
18 | #include <mach/regs-clock.h> | 18 | #include <mach/regs-clock.h> |
19 | #include <plat/gpio-cfg.h> | 19 | #include <plat/gpio-cfg.h> |
20 | #include <plat/ata.h> | ||
20 | 21 | ||
21 | void s3c64xx_ide_setup_gpio(void) | 22 | void s3c64xx_ide_setup_gpio(void) |
22 | { | 23 | { |
23 | u32 reg; | 24 | u32 reg; |
24 | u32 gpio = 0; | ||
25 | 25 | ||
26 | reg = readl(S3C_MEM_SYS_CFG) & (~0x3f); | 26 | reg = readl(S3C_MEM_SYS_CFG) & (~0x3f); |
27 | 27 | ||
@@ -32,15 +32,12 @@ void s3c64xx_ide_setup_gpio(void) | |||
32 | s3c_gpio_cfgpin(S3C64XX_GPB(4), S3C_GPIO_SFN(4)); | 32 | s3c_gpio_cfgpin(S3C64XX_GPB(4), S3C_GPIO_SFN(4)); |
33 | 33 | ||
34 | /* Set XhiDATA[15:0] pins as CF Data[15:0] */ | 34 | /* Set XhiDATA[15:0] pins as CF Data[15:0] */ |
35 | for (gpio = S3C64XX_GPK(0); gpio <= S3C64XX_GPK(15); gpio++) | 35 | s3c_gpio_cfgpin_range(S3C64XX_GPK(0), 16, S3C_GPIO_SFN(5)); |
36 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(5)); | ||
37 | 36 | ||
38 | /* Set XhiADDR[2:0] pins as CF ADDR[2:0] */ | 37 | /* Set XhiADDR[2:0] pins as CF ADDR[2:0] */ |
39 | for (gpio = S3C64XX_GPL(0); gpio <= S3C64XX_GPL(2); gpio++) | 38 | s3c_gpio_cfgpin_range(S3C64XX_GPL(0), 3, S3C_GPIO_SFN(6)); |
40 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(6)); | ||
41 | 39 | ||
42 | /* Set Xhi ctrl pins as CF ctrl pins(IORDY, IOWR, IORD, CE[0:1]) */ | 40 | /* Set Xhi ctrl pins as CF ctrl pins(IORDY, IOWR, IORD, CE[0:1]) */ |
43 | s3c_gpio_cfgpin(S3C64XX_GPM(5), S3C_GPIO_SFN(1)); | 41 | s3c_gpio_cfgpin(S3C64XX_GPM(5), S3C_GPIO_SFN(1)); |
44 | for (gpio = S3C64XX_GPM(0); gpio <= S3C64XX_GPM(4); gpio++) | 42 | s3c_gpio_cfgpin_range(S3C64XX_GPM(0), 5, S3C_GPIO_SFN(6)); |
45 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(6)); | ||
46 | } | 43 | } |
diff --git a/arch/arm/mach-s3c64xx/setup-keypad.c b/arch/arm/mach-s3c64xx/setup-keypad.c index abc34e4e1a93..f8ed0d22db70 100644 --- a/arch/arm/mach-s3c64xx/setup-keypad.c +++ b/arch/arm/mach-s3c64xx/setup-keypad.c | |||
@@ -12,23 +12,13 @@ | |||
12 | 12 | ||
13 | #include <linux/gpio.h> | 13 | #include <linux/gpio.h> |
14 | #include <plat/gpio-cfg.h> | 14 | #include <plat/gpio-cfg.h> |
15 | #include <plat/keypad.h> | ||
15 | 16 | ||
16 | void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols) | 17 | void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols) |
17 | { | 18 | { |
18 | unsigned int gpio; | ||
19 | unsigned int end; | ||
20 | |||
21 | /* Set all the necessary GPK pins to special-function 3: KP_ROW[x] */ | 19 | /* Set all the necessary GPK pins to special-function 3: KP_ROW[x] */ |
22 | end = S3C64XX_GPK(8 + rows); | 20 | s3c_gpio_cfgrange_nopull(S3C64XX_GPK(8), 8 + rows, S3C_GPIO_SFN(3)); |
23 | for (gpio = S3C64XX_GPK(8); gpio < end; gpio++) { | ||
24 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); | ||
25 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
26 | } | ||
27 | 21 | ||
28 | /* Set all the necessary GPL pins to special-function 3: KP_COL[x] */ | 22 | /* Set all the necessary GPL pins to special-function 3: KP_COL[x] */ |
29 | end = S3C64XX_GPL(0 + cols); | 23 | s3c_gpio_cfgrange_nopull(S3C64XX_GPL(0), cols, S3C_GPIO_SFN(3)); |
30 | for (gpio = S3C64XX_GPL(0); gpio < end; gpio++) { | ||
31 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); | ||
32 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
33 | } | ||
34 | } | 24 | } |
diff --git a/arch/arm/mach-s3c64xx/setup-sdhci-gpio.c b/arch/arm/mach-s3c64xx/setup-sdhci-gpio.c index 322359591374..6eac071afae2 100644 --- a/arch/arm/mach-s3c64xx/setup-sdhci-gpio.c +++ b/arch/arm/mach-s3c64xx/setup-sdhci-gpio.c | |||
@@ -24,16 +24,9 @@ | |||
24 | void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) | 24 | void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) |
25 | { | 25 | { |
26 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; | 26 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; |
27 | unsigned int gpio; | ||
28 | unsigned int end; | ||
29 | 27 | ||
30 | end = S3C64XX_GPG(2 + width); | 28 | /* Set all the necessary GPG pins to special-function 2 */ |
31 | 29 | s3c_gpio_cfgrange_nopull(S3C64XX_GPG(0), 2 + width, S3C_GPIO_SFN(2)); | |
32 | /* Set all the necessary GPG pins to special-function 0 */ | ||
33 | for (gpio = S3C64XX_GPG(0); gpio < end; gpio++) { | ||
34 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
35 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
36 | } | ||
37 | 30 | ||
38 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { | 31 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { |
39 | s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP); | 32 | s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP); |
@@ -44,16 +37,9 @@ void s3c64xx_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) | |||
44 | void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) | 37 | void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) |
45 | { | 38 | { |
46 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; | 39 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; |
47 | unsigned int gpio; | ||
48 | unsigned int end; | ||
49 | 40 | ||
50 | end = S3C64XX_GPH(2 + width); | 41 | /* Set all the necessary GPH pins to special-function 2 */ |
51 | 42 | s3c_gpio_cfgrange_nopull(S3C64XX_GPH(0), 2 + width, S3C_GPIO_SFN(2)); | |
52 | /* Set all the necessary GPG pins to special-function 0 */ | ||
53 | for (gpio = S3C64XX_GPH(0); gpio < end; gpio++) { | ||
54 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
55 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
56 | } | ||
57 | 43 | ||
58 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { | 44 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { |
59 | s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP); | 45 | s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP); |
@@ -63,20 +49,9 @@ void s3c64xx_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) | |||
63 | 49 | ||
64 | void s3c64xx_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) | 50 | void s3c64xx_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) |
65 | { | 51 | { |
66 | unsigned int gpio; | 52 | /* Set all the necessary GPH pins to special-function 3 */ |
67 | unsigned int end; | 53 | s3c_gpio_cfgrange_nopull(S3C64XX_GPH(6), width, S3C_GPIO_SFN(3)); |
68 | 54 | ||
69 | end = S3C64XX_GPH(6 + width); | 55 | /* Set all the necessary GPC pins to special-function 3 */ |
70 | 56 | s3c_gpio_cfgrange_nopull(S3C64XX_GPC(4), 2, S3C_GPIO_SFN(3)); | |
71 | /* Set all the necessary GPH pins to special-function 1 */ | ||
72 | for (gpio = S3C64XX_GPH(6); gpio < end; gpio++) { | ||
73 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); | ||
74 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
75 | } | ||
76 | |||
77 | /* Set all the necessary GPC pins to special-function 1 */ | ||
78 | for (gpio = S3C64XX_GPC(4); gpio < S3C64XX_GPC(6); gpio++) { | ||
79 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); | ||
80 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
81 | } | ||
82 | } | 57 | } |
diff --git a/arch/arm/mach-s5p6442/Kconfig b/arch/arm/mach-s5p6442/Kconfig index 0fda0a5df968..33569e4007c4 100644 --- a/arch/arm/mach-s5p6442/Kconfig +++ b/arch/arm/mach-s5p6442/Kconfig | |||
@@ -11,7 +11,6 @@ if ARCH_S5P6442 | |||
11 | 11 | ||
12 | config CPU_S5P6442 | 12 | config CPU_S5P6442 |
13 | bool | 13 | bool |
14 | select PLAT_S5P | ||
15 | select S3C_PL330_DMA | 14 | select S3C_PL330_DMA |
16 | help | 15 | help |
17 | Enable S5P6442 CPU support | 16 | Enable S5P6442 CPU support |
diff --git a/arch/arm/mach-s5p6442/clock.c b/arch/arm/mach-s5p6442/clock.c index dcd20f17212a..16d6e7e61b50 100644 --- a/arch/arm/mach-s5p6442/clock.c +++ b/arch/arm/mach-s5p6442/clock.c | |||
@@ -192,6 +192,11 @@ static struct clk clk_pclkd1 = { | |||
192 | .parent = &clk_hclkd1, | 192 | .parent = &clk_hclkd1, |
193 | }; | 193 | }; |
194 | 194 | ||
195 | int s5p6442_clk_ip0_ctrl(struct clk *clk, int enable) | ||
196 | { | ||
197 | return s5p_gatectrl(S5P_CLKGATE_IP0, clk, enable); | ||
198 | } | ||
199 | |||
195 | int s5p6442_clk_ip3_ctrl(struct clk *clk, int enable) | 200 | int s5p6442_clk_ip3_ctrl(struct clk *clk, int enable) |
196 | { | 201 | { |
197 | return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable); | 202 | return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable); |
@@ -335,6 +340,16 @@ void __init_or_cpufreq s5p6442_setup_clocks(void) | |||
335 | clk_pclkd1.rate = pclkd1; | 340 | clk_pclkd1.rate = pclkd1; |
336 | } | 341 | } |
337 | 342 | ||
343 | static struct clk init_clocks_disable[] = { | ||
344 | { | ||
345 | .name = "pdma", | ||
346 | .id = -1, | ||
347 | .parent = &clk_pclkd1, | ||
348 | .enable = s5p6442_clk_ip0_ctrl, | ||
349 | .ctrlbit = (1 << 3), | ||
350 | }, | ||
351 | }; | ||
352 | |||
338 | static struct clk init_clocks[] = { | 353 | static struct clk init_clocks[] = { |
339 | { | 354 | { |
340 | .name = "systimer", | 355 | .name = "systimer", |
@@ -393,10 +408,23 @@ static struct clk *clks[] __initdata = { | |||
393 | 408 | ||
394 | void __init s5p6442_register_clocks(void) | 409 | void __init s5p6442_register_clocks(void) |
395 | { | 410 | { |
411 | struct clk *clkptr; | ||
412 | int i, ret; | ||
413 | |||
396 | s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); | 414 | s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); |
397 | 415 | ||
398 | s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); | 416 | s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); |
399 | s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); | 417 | s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); |
400 | 418 | ||
419 | clkptr = init_clocks_disable; | ||
420 | for (i = 0; i < ARRAY_SIZE(init_clocks_disable); i++, clkptr++) { | ||
421 | ret = s3c24xx_register_clock(clkptr); | ||
422 | if (ret < 0) { | ||
423 | printk(KERN_ERR "Fail to register clock %s (%d)\n", | ||
424 | clkptr->name, ret); | ||
425 | } else | ||
426 | (clkptr->enable)(clkptr, 0); | ||
427 | } | ||
428 | |||
401 | s3c_pwmclk_init(); | 429 | s3c_pwmclk_init(); |
402 | } | 430 | } |
diff --git a/arch/arm/mach-s5p6442/dev-audio.c b/arch/arm/mach-s5p6442/dev-audio.c index 7a4e34720b7b..3462197ff352 100644 --- a/arch/arm/mach-s5p6442/dev-audio.c +++ b/arch/arm/mach-s5p6442/dev-audio.c | |||
@@ -21,22 +21,16 @@ | |||
21 | 21 | ||
22 | static int s5p6442_cfg_i2s(struct platform_device *pdev) | 22 | static int s5p6442_cfg_i2s(struct platform_device *pdev) |
23 | { | 23 | { |
24 | unsigned int base; | ||
25 | |||
24 | /* configure GPIO for i2s port */ | 26 | /* configure GPIO for i2s port */ |
25 | switch (pdev->id) { | 27 | switch (pdev->id) { |
26 | case 1: | 28 | case 1: |
27 | s3c_gpio_cfgpin(S5P6442_GPC1(0), S3C_GPIO_SFN(2)); | 29 | base = S5P6442_GPC1(0); |
28 | s3c_gpio_cfgpin(S5P6442_GPC1(1), S3C_GPIO_SFN(2)); | ||
29 | s3c_gpio_cfgpin(S5P6442_GPC1(2), S3C_GPIO_SFN(2)); | ||
30 | s3c_gpio_cfgpin(S5P6442_GPC1(3), S3C_GPIO_SFN(2)); | ||
31 | s3c_gpio_cfgpin(S5P6442_GPC1(4), S3C_GPIO_SFN(2)); | ||
32 | break; | 30 | break; |
33 | 31 | ||
34 | case -1: | 32 | case -1: |
35 | s3c_gpio_cfgpin(S5P6442_GPC0(0), S3C_GPIO_SFN(2)); | 33 | base = S5P6442_GPC0(0); |
36 | s3c_gpio_cfgpin(S5P6442_GPC0(1), S3C_GPIO_SFN(2)); | ||
37 | s3c_gpio_cfgpin(S5P6442_GPC0(2), S3C_GPIO_SFN(2)); | ||
38 | s3c_gpio_cfgpin(S5P6442_GPC0(3), S3C_GPIO_SFN(2)); | ||
39 | s3c_gpio_cfgpin(S5P6442_GPC0(4), S3C_GPIO_SFN(2)); | ||
40 | break; | 34 | break; |
41 | 35 | ||
42 | default: | 36 | default: |
@@ -44,6 +38,7 @@ static int s5p6442_cfg_i2s(struct platform_device *pdev) | |||
44 | return -EINVAL; | 38 | return -EINVAL; |
45 | } | 39 | } |
46 | 40 | ||
41 | s3c_gpio_cfgpin_range(base, 5, S3C_GPIO_SFN(2)); | ||
47 | return 0; | 42 | return 0; |
48 | } | 43 | } |
49 | 44 | ||
@@ -111,21 +106,15 @@ struct platform_device s5p6442_device_iis1 = { | |||
111 | 106 | ||
112 | static int s5p6442_pcm_cfg_gpio(struct platform_device *pdev) | 107 | static int s5p6442_pcm_cfg_gpio(struct platform_device *pdev) |
113 | { | 108 | { |
109 | unsigned int base; | ||
110 | |||
114 | switch (pdev->id) { | 111 | switch (pdev->id) { |
115 | case 0: | 112 | case 0: |
116 | s3c_gpio_cfgpin(S5P6442_GPC0(0), S3C_GPIO_SFN(3)); | 113 | base = S5P6442_GPC0(0); |
117 | s3c_gpio_cfgpin(S5P6442_GPC0(1), S3C_GPIO_SFN(3)); | ||
118 | s3c_gpio_cfgpin(S5P6442_GPC0(2), S3C_GPIO_SFN(3)); | ||
119 | s3c_gpio_cfgpin(S5P6442_GPC0(3), S3C_GPIO_SFN(3)); | ||
120 | s3c_gpio_cfgpin(S5P6442_GPC0(4), S3C_GPIO_SFN(3)); | ||
121 | break; | 114 | break; |
122 | 115 | ||
123 | case 1: | 116 | case 1: |
124 | s3c_gpio_cfgpin(S5P6442_GPC1(0), S3C_GPIO_SFN(3)); | 117 | base = S5P6442_GPC1(0); |
125 | s3c_gpio_cfgpin(S5P6442_GPC1(1), S3C_GPIO_SFN(3)); | ||
126 | s3c_gpio_cfgpin(S5P6442_GPC1(2), S3C_GPIO_SFN(3)); | ||
127 | s3c_gpio_cfgpin(S5P6442_GPC1(3), S3C_GPIO_SFN(3)); | ||
128 | s3c_gpio_cfgpin(S5P6442_GPC1(4), S3C_GPIO_SFN(3)); | ||
129 | break; | 118 | break; |
130 | 119 | ||
131 | default: | 120 | default: |
@@ -133,6 +122,7 @@ static int s5p6442_pcm_cfg_gpio(struct platform_device *pdev) | |||
133 | return -EINVAL; | 122 | return -EINVAL; |
134 | } | 123 | } |
135 | 124 | ||
125 | s3c_gpio_cfgpin_range(base, 5, S3C_GPIO_SFN(3)); | ||
136 | return 0; | 126 | return 0; |
137 | } | 127 | } |
138 | 128 | ||
diff --git a/arch/arm/mach-s5p6442/dev-spi.c b/arch/arm/mach-s5p6442/dev-spi.c index e894651a88bd..cce8c2470709 100644 --- a/arch/arm/mach-s5p6442/dev-spi.c +++ b/arch/arm/mach-s5p6442/dev-spi.c | |||
@@ -38,11 +38,9 @@ static int s5p6442_spi_cfg_gpio(struct platform_device *pdev) | |||
38 | switch (pdev->id) { | 38 | switch (pdev->id) { |
39 | case 0: | 39 | case 0: |
40 | s3c_gpio_cfgpin(S5P6442_GPB(0), S3C_GPIO_SFN(2)); | 40 | s3c_gpio_cfgpin(S5P6442_GPB(0), S3C_GPIO_SFN(2)); |
41 | s3c_gpio_cfgpin(S5P6442_GPB(2), S3C_GPIO_SFN(2)); | ||
42 | s3c_gpio_cfgpin(S5P6442_GPB(3), S3C_GPIO_SFN(2)); | ||
43 | s3c_gpio_setpull(S5P6442_GPB(0), S3C_GPIO_PULL_UP); | 41 | s3c_gpio_setpull(S5P6442_GPB(0), S3C_GPIO_PULL_UP); |
44 | s3c_gpio_setpull(S5P6442_GPB(2), S3C_GPIO_PULL_UP); | 42 | s3c_gpio_cfgall_range(S5P6442_GPB(2), 2, |
45 | s3c_gpio_setpull(S5P6442_GPB(3), S3C_GPIO_PULL_UP); | 43 | S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); |
46 | break; | 44 | break; |
47 | 45 | ||
48 | default: | 46 | default: |
diff --git a/arch/arm/mach-s5p6442/dma.c b/arch/arm/mach-s5p6442/dma.c index ad4f8704b93d..7dfb13654f8a 100644 --- a/arch/arm/mach-s5p6442/dma.c +++ b/arch/arm/mach-s5p6442/dma.c | |||
@@ -82,7 +82,7 @@ static struct s3c_pl330_platdata s5p6442_pdma_pdata = { | |||
82 | 82 | ||
83 | static struct platform_device s5p6442_device_pdma = { | 83 | static struct platform_device s5p6442_device_pdma = { |
84 | .name = "s3c-pl330", | 84 | .name = "s3c-pl330", |
85 | .id = 1, | 85 | .id = -1, |
86 | .num_resources = ARRAY_SIZE(s5p6442_pdma_resource), | 86 | .num_resources = ARRAY_SIZE(s5p6442_pdma_resource), |
87 | .resource = s5p6442_pdma_resource, | 87 | .resource = s5p6442_pdma_resource, |
88 | .dev = { | 88 | .dev = { |
diff --git a/arch/arm/mach-s5p6442/include/mach/regs-clock.h b/arch/arm/mach-s5p6442/include/mach/regs-clock.h index d8360b5d4ece..00828a336991 100644 --- a/arch/arm/mach-s5p6442/include/mach/regs-clock.h +++ b/arch/arm/mach-s5p6442/include/mach/regs-clock.h | |||
@@ -46,6 +46,7 @@ | |||
46 | #define S5P_CLK_DIV5 S5P_CLKREG(0x314) | 46 | #define S5P_CLK_DIV5 S5P_CLKREG(0x314) |
47 | #define S5P_CLK_DIV6 S5P_CLKREG(0x318) | 47 | #define S5P_CLK_DIV6 S5P_CLKREG(0x318) |
48 | 48 | ||
49 | #define S5P_CLKGATE_IP0 S5P_CLKREG(0x460) | ||
49 | #define S5P_CLKGATE_IP3 S5P_CLKREG(0x46C) | 50 | #define S5P_CLKGATE_IP3 S5P_CLKREG(0x46C) |
50 | 51 | ||
51 | /* CLK_OUT */ | 52 | /* CLK_OUT */ |
diff --git a/arch/arm/mach-s5p6442/include/mach/vmalloc.h b/arch/arm/mach-s5p6442/include/mach/vmalloc.h index f5c83f02c18e..4aa55e55ac47 100644 --- a/arch/arm/mach-s5p6442/include/mach/vmalloc.h +++ b/arch/arm/mach-s5p6442/include/mach/vmalloc.h | |||
@@ -12,6 +12,6 @@ | |||
12 | #ifndef __ASM_ARCH_VMALLOC_H | 12 | #ifndef __ASM_ARCH_VMALLOC_H |
13 | #define __ASM_ARCH_VMALLOC_H | 13 | #define __ASM_ARCH_VMALLOC_H |
14 | 14 | ||
15 | #define VMALLOC_END 0xE0000000UL | 15 | #define VMALLOC_END 0xF6000000UL |
16 | 16 | ||
17 | #endif /* __ASM_ARCH_VMALLOC_H */ | 17 | #endif /* __ASM_ARCH_VMALLOC_H */ |
diff --git a/arch/arm/mach-s5p64x0/Kconfig b/arch/arm/mach-s5p64x0/Kconfig index fbcae9352022..164d2783d381 100644 --- a/arch/arm/mach-s5p64x0/Kconfig +++ b/arch/arm/mach-s5p64x0/Kconfig | |||
@@ -9,14 +9,12 @@ if ARCH_S5P64X0 | |||
9 | 9 | ||
10 | config CPU_S5P6440 | 10 | config CPU_S5P6440 |
11 | bool | 11 | bool |
12 | select PLAT_S5P | ||
13 | select S3C_PL330_DMA | 12 | select S3C_PL330_DMA |
14 | help | 13 | help |
15 | Enable S5P6440 CPU support | 14 | Enable S5P6440 CPU support |
16 | 15 | ||
17 | config CPU_S5P6450 | 16 | config CPU_S5P6450 |
18 | bool | 17 | bool |
19 | select PLAT_S5P | ||
20 | select S3C_PL330_DMA | 18 | select S3C_PL330_DMA |
21 | help | 19 | help |
22 | Enable S5P6450 CPU support | 20 | Enable S5P6450 CPU support |
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6440.c b/arch/arm/mach-s5p64x0/clock-s5p6440.c index f93dcd8b4d6a..e4883dc1c8d7 100644 --- a/arch/arm/mach-s5p64x0/clock-s5p6440.c +++ b/arch/arm/mach-s5p64x0/clock-s5p6440.c | |||
@@ -79,13 +79,16 @@ static int s5p6440_epll_set_rate(struct clk *clk, unsigned long rate) | |||
79 | __raw_writel(epll_con, S5P64X0_EPLL_CON); | 79 | __raw_writel(epll_con, S5P64X0_EPLL_CON); |
80 | __raw_writel(epll_con_k, S5P64X0_EPLL_CON_K); | 80 | __raw_writel(epll_con_k, S5P64X0_EPLL_CON_K); |
81 | 81 | ||
82 | printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n", | ||
83 | clk->rate, rate); | ||
84 | |||
82 | clk->rate = rate; | 85 | clk->rate = rate; |
83 | 86 | ||
84 | return 0; | 87 | return 0; |
85 | } | 88 | } |
86 | 89 | ||
87 | static struct clk_ops s5p6440_epll_ops = { | 90 | static struct clk_ops s5p6440_epll_ops = { |
88 | .get_rate = s5p64x0_epll_get_rate, | 91 | .get_rate = s5p_epll_get_rate, |
89 | .set_rate = s5p6440_epll_set_rate, | 92 | .set_rate = s5p6440_epll_set_rate, |
90 | }; | 93 | }; |
91 | 94 | ||
@@ -150,6 +153,12 @@ static struct clk init_clocks_disable[] = { | |||
150 | .enable = s5p64x0_hclk0_ctrl, | 153 | .enable = s5p64x0_hclk0_ctrl, |
151 | .ctrlbit = (1 << 8), | 154 | .ctrlbit = (1 << 8), |
152 | }, { | 155 | }, { |
156 | .name = "pdma", | ||
157 | .id = -1, | ||
158 | .parent = &clk_hclk_low.clk, | ||
159 | .enable = s5p64x0_hclk0_ctrl, | ||
160 | .ctrlbit = (1 << 12), | ||
161 | }, { | ||
153 | .name = "hsmmc", | 162 | .name = "hsmmc", |
154 | .id = 0, | 163 | .id = 0, |
155 | .parent = &clk_hclk_low.clk, | 164 | .parent = &clk_hclk_low.clk, |
@@ -331,12 +340,6 @@ static struct clk init_clocks[] = { | |||
331 | .enable = s5p64x0_hclk0_ctrl, | 340 | .enable = s5p64x0_hclk0_ctrl, |
332 | .ctrlbit = (1 << 21), | 341 | .ctrlbit = (1 << 21), |
333 | }, { | 342 | }, { |
334 | .name = "dma", | ||
335 | .id = -1, | ||
336 | .parent = &clk_hclk_low.clk, | ||
337 | .enable = s5p64x0_hclk0_ctrl, | ||
338 | .ctrlbit = (1 << 12), | ||
339 | }, { | ||
340 | .name = "uart", | 343 | .name = "uart", |
341 | .id = 0, | 344 | .id = 0, |
342 | .parent = &clk_pclk_low.clk, | 345 | .parent = &clk_pclk_low.clk, |
@@ -548,7 +551,7 @@ void __init_or_cpufreq s5p6440_setup_clocks(void) | |||
548 | 551 | ||
549 | /* Set S5P6440 functions for clk_fout_epll */ | 552 | /* Set S5P6440 functions for clk_fout_epll */ |
550 | 553 | ||
551 | clk_fout_epll.enable = s5p64x0_epll_enable; | 554 | clk_fout_epll.enable = s5p_epll_enable; |
552 | clk_fout_epll.ops = &s5p6440_epll_ops; | 555 | clk_fout_epll.ops = &s5p6440_epll_ops; |
553 | 556 | ||
554 | clk_48m.enable = s5p64x0_clk48m_ctrl; | 557 | clk_48m.enable = s5p64x0_clk48m_ctrl; |
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6450.c b/arch/arm/mach-s5p64x0/clock-s5p6450.c index f9afb05b217c..7dbf3c968f53 100644 --- a/arch/arm/mach-s5p64x0/clock-s5p6450.c +++ b/arch/arm/mach-s5p64x0/clock-s5p6450.c | |||
@@ -80,13 +80,16 @@ static int s5p6450_epll_set_rate(struct clk *clk, unsigned long rate) | |||
80 | __raw_writel(epll_con, S5P64X0_EPLL_CON); | 80 | __raw_writel(epll_con, S5P64X0_EPLL_CON); |
81 | __raw_writel(epll_con_k, S5P64X0_EPLL_CON_K); | 81 | __raw_writel(epll_con_k, S5P64X0_EPLL_CON_K); |
82 | 82 | ||
83 | printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n", | ||
84 | clk->rate, rate); | ||
85 | |||
83 | clk->rate = rate; | 86 | clk->rate = rate; |
84 | 87 | ||
85 | return 0; | 88 | return 0; |
86 | } | 89 | } |
87 | 90 | ||
88 | static struct clk_ops s5p6450_epll_ops = { | 91 | static struct clk_ops s5p6450_epll_ops = { |
89 | .get_rate = s5p64x0_epll_get_rate, | 92 | .get_rate = s5p_epll_get_rate, |
90 | .set_rate = s5p6450_epll_set_rate, | 93 | .set_rate = s5p6450_epll_set_rate, |
91 | }; | 94 | }; |
92 | 95 | ||
@@ -186,6 +189,12 @@ static struct clk init_clocks_disable[] = { | |||
186 | .enable = s5p64x0_hclk0_ctrl, | 189 | .enable = s5p64x0_hclk0_ctrl, |
187 | .ctrlbit = (1 << 3), | 190 | .ctrlbit = (1 << 3), |
188 | }, { | 191 | }, { |
192 | .name = "pdma", | ||
193 | .id = -1, | ||
194 | .parent = &clk_hclk_low.clk, | ||
195 | .enable = s5p64x0_hclk0_ctrl, | ||
196 | .ctrlbit = (1 << 12), | ||
197 | }, { | ||
189 | .name = "hsmmc", | 198 | .name = "hsmmc", |
190 | .id = 0, | 199 | .id = 0, |
191 | .parent = &clk_hclk_low.clk, | 200 | .parent = &clk_hclk_low.clk, |
@@ -283,12 +292,6 @@ static struct clk init_clocks[] = { | |||
283 | .enable = s5p64x0_hclk0_ctrl, | 292 | .enable = s5p64x0_hclk0_ctrl, |
284 | .ctrlbit = (1 << 21), | 293 | .ctrlbit = (1 << 21), |
285 | }, { | 294 | }, { |
286 | .name = "dma", | ||
287 | .id = -1, | ||
288 | .parent = &clk_hclk_low.clk, | ||
289 | .enable = s5p64x0_hclk0_ctrl, | ||
290 | .ctrlbit = (1 << 12), | ||
291 | }, { | ||
292 | .name = "uart", | 295 | .name = "uart", |
293 | .id = 0, | 296 | .id = 0, |
294 | .parent = &clk_pclk_low.clk, | 297 | .parent = &clk_pclk_low.clk, |
@@ -581,7 +584,7 @@ void __init_or_cpufreq s5p6450_setup_clocks(void) | |||
581 | 584 | ||
582 | /* Set S5P6450 functions for clk_fout_epll */ | 585 | /* Set S5P6450 functions for clk_fout_epll */ |
583 | 586 | ||
584 | clk_fout_epll.enable = s5p64x0_epll_enable; | 587 | clk_fout_epll.enable = s5p_epll_enable; |
585 | clk_fout_epll.ops = &s5p6450_epll_ops; | 588 | clk_fout_epll.ops = &s5p6450_epll_ops; |
586 | 589 | ||
587 | clk_48m.enable = s5p64x0_clk48m_ctrl; | 590 | clk_48m.enable = s5p64x0_clk48m_ctrl; |
diff --git a/arch/arm/mach-s5p64x0/clock.c b/arch/arm/mach-s5p64x0/clock.c index 523ba8039ac2..b52c6e2f37a6 100644 --- a/arch/arm/mach-s5p64x0/clock.c +++ b/arch/arm/mach-s5p64x0/clock.c | |||
@@ -73,24 +73,6 @@ static const u32 clock_table[][3] = { | |||
73 | {L2 * 1000, (3 << ARM_DIV_RATIO_SHIFT), (0 << S5P64X0_CLKDIV0_HCLK_SHIFT)}, | 73 | {L2 * 1000, (3 << ARM_DIV_RATIO_SHIFT), (0 << S5P64X0_CLKDIV0_HCLK_SHIFT)}, |
74 | }; | 74 | }; |
75 | 75 | ||
76 | int s5p64x0_epll_enable(struct clk *clk, int enable) | ||
77 | { | ||
78 | unsigned int ctrlbit = clk->ctrlbit; | ||
79 | unsigned int epll_con = __raw_readl(S5P64X0_EPLL_CON) & ~ctrlbit; | ||
80 | |||
81 | if (enable) | ||
82 | __raw_writel(epll_con | ctrlbit, S5P64X0_EPLL_CON); | ||
83 | else | ||
84 | __raw_writel(epll_con, S5P64X0_EPLL_CON); | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | unsigned long s5p64x0_epll_get_rate(struct clk *clk) | ||
90 | { | ||
91 | return clk->rate; | ||
92 | } | ||
93 | |||
94 | unsigned long s5p64x0_armclk_get_rate(struct clk *clk) | 76 | unsigned long s5p64x0_armclk_get_rate(struct clk *clk) |
95 | { | 77 | { |
96 | unsigned long rate = clk_get_rate(clk->parent); | 78 | unsigned long rate = clk_get_rate(clk->parent); |
diff --git a/arch/arm/mach-s5p64x0/dev-audio.c b/arch/arm/mach-s5p64x0/dev-audio.c index fa097bd68ca4..396bacc0a39a 100644 --- a/arch/arm/mach-s5p64x0/dev-audio.c +++ b/arch/arm/mach-s5p64x0/dev-audio.c | |||
@@ -24,13 +24,8 @@ static int s5p6440_cfg_i2s(struct platform_device *pdev) | |||
24 | /* configure GPIO for i2s port */ | 24 | /* configure GPIO for i2s port */ |
25 | switch (pdev->id) { | 25 | switch (pdev->id) { |
26 | case -1: | 26 | case -1: |
27 | s3c_gpio_cfgpin(S5P6440_GPR(4), S3C_GPIO_SFN(5)); | 27 | s3c_gpio_cfgpin_range(S5P6440_GPR(4), 5, S3C_GPIO_SFN(5)); |
28 | s3c_gpio_cfgpin(S5P6440_GPR(5), S3C_GPIO_SFN(5)); | 28 | s3c_gpio_cfgpin_range(S5P6440_GPR(13), 2, S3C_GPIO_SFN(5)); |
29 | s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(5)); | ||
30 | s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(5)); | ||
31 | s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(5)); | ||
32 | s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(5)); | ||
33 | s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(5)); | ||
34 | break; | 29 | break; |
35 | 30 | ||
36 | default: | 31 | default: |
@@ -47,13 +42,9 @@ static int s5p6450_cfg_i2s(struct platform_device *pdev) | |||
47 | switch (pdev->id) { | 42 | switch (pdev->id) { |
48 | case -1: | 43 | case -1: |
49 | s3c_gpio_cfgpin(S5P6450_GPB(4), S3C_GPIO_SFN(5)); | 44 | s3c_gpio_cfgpin(S5P6450_GPB(4), S3C_GPIO_SFN(5)); |
50 | s3c_gpio_cfgpin(S5P6450_GPR(4), S3C_GPIO_SFN(5)); | 45 | s3c_gpio_cfgpin_range(S5P6450_GPR(4), 5, S3C_GPIO_SFN(5)); |
51 | s3c_gpio_cfgpin(S5P6450_GPR(5), S3C_GPIO_SFN(5)); | 46 | s3c_gpio_cfgpin_range(S5P6450_GPR(13), 2, S3C_GPIO_SFN(5)); |
52 | s3c_gpio_cfgpin(S5P6450_GPR(6), S3C_GPIO_SFN(5)); | 47 | |
53 | s3c_gpio_cfgpin(S5P6450_GPR(7), S3C_GPIO_SFN(5)); | ||
54 | s3c_gpio_cfgpin(S5P6450_GPR(8), S3C_GPIO_SFN(5)); | ||
55 | s3c_gpio_cfgpin(S5P6450_GPR(13), S3C_GPIO_SFN(5)); | ||
56 | s3c_gpio_cfgpin(S5P6450_GPR(14), S3C_GPIO_SFN(5)); | ||
57 | break; | 48 | break; |
58 | 49 | ||
59 | default: | 50 | default: |
@@ -116,11 +107,8 @@ static int s5p6440_pcm_cfg_gpio(struct platform_device *pdev) | |||
116 | { | 107 | { |
117 | switch (pdev->id) { | 108 | switch (pdev->id) { |
118 | case 0: | 109 | case 0: |
119 | s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(2)); | 110 | s3c_gpio_cfgpin_range(S5P6440_GPR(6), 3, S3C_GPIO_SFN(2)); |
120 | s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(2)); | 111 | s3c_gpio_cfgpin_range(S5P6440_GPR(13), 2, S3C_GPIO_SFN(2)); |
121 | s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(2)); | ||
122 | s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(2)); | ||
123 | s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(2)); | ||
124 | break; | 112 | break; |
125 | 113 | ||
126 | default: | 114 | default: |
diff --git a/arch/arm/mach-s5p64x0/dev-spi.c b/arch/arm/mach-s5p64x0/dev-spi.c index 5b69ec4c8af3..e78ee18c76e3 100644 --- a/arch/arm/mach-s5p64x0/dev-spi.c +++ b/arch/arm/mach-s5p64x0/dev-spi.c | |||
@@ -39,23 +39,15 @@ static char *s5p64x0_spi_src_clks[] = { | |||
39 | */ | 39 | */ |
40 | static int s5p6440_spi_cfg_gpio(struct platform_device *pdev) | 40 | static int s5p6440_spi_cfg_gpio(struct platform_device *pdev) |
41 | { | 41 | { |
42 | unsigned int base; | ||
43 | |||
42 | switch (pdev->id) { | 44 | switch (pdev->id) { |
43 | case 0: | 45 | case 0: |
44 | s3c_gpio_cfgpin(S5P6440_GPC(0), S3C_GPIO_SFN(2)); | 46 | base = S5P6440_GPC(0); |
45 | s3c_gpio_cfgpin(S5P6440_GPC(1), S3C_GPIO_SFN(2)); | ||
46 | s3c_gpio_cfgpin(S5P6440_GPC(2), S3C_GPIO_SFN(2)); | ||
47 | s3c_gpio_setpull(S5P6440_GPC(0), S3C_GPIO_PULL_UP); | ||
48 | s3c_gpio_setpull(S5P6440_GPC(1), S3C_GPIO_PULL_UP); | ||
49 | s3c_gpio_setpull(S5P6440_GPC(2), S3C_GPIO_PULL_UP); | ||
50 | break; | 47 | break; |
51 | 48 | ||
52 | case 1: | 49 | case 1: |
53 | s3c_gpio_cfgpin(S5P6440_GPC(4), S3C_GPIO_SFN(2)); | 50 | base = S5P6440_GPC(4); |
54 | s3c_gpio_cfgpin(S5P6440_GPC(5), S3C_GPIO_SFN(2)); | ||
55 | s3c_gpio_cfgpin(S5P6440_GPC(6), S3C_GPIO_SFN(2)); | ||
56 | s3c_gpio_setpull(S5P6440_GPC(4), S3C_GPIO_PULL_UP); | ||
57 | s3c_gpio_setpull(S5P6440_GPC(5), S3C_GPIO_PULL_UP); | ||
58 | s3c_gpio_setpull(S5P6440_GPC(6), S3C_GPIO_PULL_UP); | ||
59 | break; | 51 | break; |
60 | 52 | ||
61 | default: | 53 | default: |
@@ -63,28 +55,23 @@ static int s5p6440_spi_cfg_gpio(struct platform_device *pdev) | |||
63 | return -EINVAL; | 55 | return -EINVAL; |
64 | } | 56 | } |
65 | 57 | ||
58 | s3c_gpio_cfgall_range(base, 3, | ||
59 | S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); | ||
60 | |||
66 | return 0; | 61 | return 0; |
67 | } | 62 | } |
68 | 63 | ||
69 | static int s5p6450_spi_cfg_gpio(struct platform_device *pdev) | 64 | static int s5p6450_spi_cfg_gpio(struct platform_device *pdev) |
70 | { | 65 | { |
66 | unsigned int base; | ||
67 | |||
71 | switch (pdev->id) { | 68 | switch (pdev->id) { |
72 | case 0: | 69 | case 0: |
73 | s3c_gpio_cfgpin(S5P6450_GPC(0), S3C_GPIO_SFN(2)); | 70 | base = S5P6450_GPC(0); |
74 | s3c_gpio_cfgpin(S5P6450_GPC(1), S3C_GPIO_SFN(2)); | ||
75 | s3c_gpio_cfgpin(S5P6450_GPC(2), S3C_GPIO_SFN(2)); | ||
76 | s3c_gpio_setpull(S5P6450_GPC(0), S3C_GPIO_PULL_UP); | ||
77 | s3c_gpio_setpull(S5P6450_GPC(1), S3C_GPIO_PULL_UP); | ||
78 | s3c_gpio_setpull(S5P6450_GPC(2), S3C_GPIO_PULL_UP); | ||
79 | break; | 71 | break; |
80 | 72 | ||
81 | case 1: | 73 | case 1: |
82 | s3c_gpio_cfgpin(S5P6450_GPC(4), S3C_GPIO_SFN(2)); | 74 | base = S5P6450_GPC(4); |
83 | s3c_gpio_cfgpin(S5P6450_GPC(5), S3C_GPIO_SFN(2)); | ||
84 | s3c_gpio_cfgpin(S5P6450_GPC(6), S3C_GPIO_SFN(2)); | ||
85 | s3c_gpio_setpull(S5P6450_GPC(4), S3C_GPIO_PULL_UP); | ||
86 | s3c_gpio_setpull(S5P6450_GPC(5), S3C_GPIO_PULL_UP); | ||
87 | s3c_gpio_setpull(S5P6450_GPC(6), S3C_GPIO_PULL_UP); | ||
88 | break; | 75 | break; |
89 | 76 | ||
90 | default: | 77 | default: |
@@ -92,6 +79,9 @@ static int s5p6450_spi_cfg_gpio(struct platform_device *pdev) | |||
92 | return -EINVAL; | 79 | return -EINVAL; |
93 | } | 80 | } |
94 | 81 | ||
82 | s3c_gpio_cfgall_range(base, 3, | ||
83 | S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); | ||
84 | |||
95 | return 0; | 85 | return 0; |
96 | } | 86 | } |
97 | 87 | ||
diff --git a/arch/arm/mach-s5p64x0/dma.c b/arch/arm/mach-s5p64x0/dma.c index 29a8c2410049..d7ad944b3475 100644 --- a/arch/arm/mach-s5p64x0/dma.c +++ b/arch/arm/mach-s5p64x0/dma.c | |||
@@ -122,7 +122,7 @@ static struct s3c_pl330_platdata s5p6450_pdma_pdata = { | |||
122 | 122 | ||
123 | static struct platform_device s5p64x0_device_pdma = { | 123 | static struct platform_device s5p64x0_device_pdma = { |
124 | .name = "s3c-pl330", | 124 | .name = "s3c-pl330", |
125 | .id = 0, | 125 | .id = -1, |
126 | .num_resources = ARRAY_SIZE(s5p64x0_pdma_resource), | 126 | .num_resources = ARRAY_SIZE(s5p64x0_pdma_resource), |
127 | .resource = s5p64x0_pdma_resource, | 127 | .resource = s5p64x0_pdma_resource, |
128 | .dev = { | 128 | .dev = { |
diff --git a/arch/arm/mach-s5p64x0/include/mach/regs-clock.h b/arch/arm/mach-s5p64x0/include/mach/regs-clock.h index 58e1bc813804..a133f22fa155 100644 --- a/arch/arm/mach-s5p64x0/include/mach/regs-clock.h +++ b/arch/arm/mach-s5p64x0/include/mach/regs-clock.h | |||
@@ -60,4 +60,6 @@ | |||
60 | #define ARM_DIV_RATIO_SHIFT 0 | 60 | #define ARM_DIV_RATIO_SHIFT 0 |
61 | #define ARM_DIV_MASK (0xF << ARM_DIV_RATIO_SHIFT) | 61 | #define ARM_DIV_MASK (0xF << ARM_DIV_RATIO_SHIFT) |
62 | 62 | ||
63 | #define S5P_EPLL_CON S5P64X0_EPLL_CON | ||
64 | |||
63 | #endif /* __ASM_ARCH_REGS_CLOCK_H */ | 65 | #endif /* __ASM_ARCH_REGS_CLOCK_H */ |
diff --git a/arch/arm/mach-s5p64x0/include/mach/vmalloc.h b/arch/arm/mach-s5p64x0/include/mach/vmalloc.h index 97a9df38f1cf..38dcc71a03cc 100644 --- a/arch/arm/mach-s5p64x0/include/mach/vmalloc.h +++ b/arch/arm/mach-s5p64x0/include/mach/vmalloc.h | |||
@@ -15,6 +15,6 @@ | |||
15 | #ifndef __ASM_ARCH_VMALLOC_H | 15 | #ifndef __ASM_ARCH_VMALLOC_H |
16 | #define __ASM_ARCH_VMALLOC_H | 16 | #define __ASM_ARCH_VMALLOC_H |
17 | 17 | ||
18 | #define VMALLOC_END 0xE0000000UL | 18 | #define VMALLOC_END 0xF6000000UL |
19 | 19 | ||
20 | #endif /* __ASM_ARCH_VMALLOC_H */ | 20 | #endif /* __ASM_ARCH_VMALLOC_H */ |
diff --git a/arch/arm/mach-s5p64x0/setup-i2c0.c b/arch/arm/mach-s5p64x0/setup-i2c0.c index dc4cc65a5019..46b463917c54 100644 --- a/arch/arm/mach-s5p64x0/setup-i2c0.c +++ b/arch/arm/mach-s5p64x0/setup-i2c0.c | |||
@@ -25,18 +25,14 @@ struct platform_device; /* don't need the contents */ | |||
25 | 25 | ||
26 | void s5p6440_i2c0_cfg_gpio(struct platform_device *dev) | 26 | void s5p6440_i2c0_cfg_gpio(struct platform_device *dev) |
27 | { | 27 | { |
28 | s3c_gpio_cfgpin(S5P6440_GPB(5), S3C_GPIO_SFN(2)); | 28 | s3c_gpio_cfgall_range(S5P6440_GPB(5), 2, |
29 | s3c_gpio_setpull(S5P6440_GPB(5), S3C_GPIO_PULL_UP); | 29 | S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); |
30 | s3c_gpio_cfgpin(S5P6440_GPB(6), S3C_GPIO_SFN(2)); | ||
31 | s3c_gpio_setpull(S5P6440_GPB(6), S3C_GPIO_PULL_UP); | ||
32 | } | 30 | } |
33 | 31 | ||
34 | void s5p6450_i2c0_cfg_gpio(struct platform_device *dev) | 32 | void s5p6450_i2c0_cfg_gpio(struct platform_device *dev) |
35 | { | 33 | { |
36 | s3c_gpio_cfgpin(S5P6450_GPB(5), S3C_GPIO_SFN(2)); | 34 | s3c_gpio_cfgall_range(S5P6450_GPB(5), 2, |
37 | s3c_gpio_setpull(S5P6450_GPB(5), S3C_GPIO_PULL_UP); | 35 | S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); |
38 | s3c_gpio_cfgpin(S5P6450_GPB(6), S3C_GPIO_SFN(2)); | ||
39 | s3c_gpio_setpull(S5P6450_GPB(6), S3C_GPIO_PULL_UP); | ||
40 | } | 36 | } |
41 | 37 | ||
42 | void s3c_i2c0_cfg_gpio(struct platform_device *dev) { } | 38 | void s3c_i2c0_cfg_gpio(struct platform_device *dev) { } |
diff --git a/arch/arm/mach-s5p64x0/setup-i2c1.c b/arch/arm/mach-s5p64x0/setup-i2c1.c index 2edd7912f8e4..6ad3b986021c 100644 --- a/arch/arm/mach-s5p64x0/setup-i2c1.c +++ b/arch/arm/mach-s5p64x0/setup-i2c1.c | |||
@@ -25,18 +25,14 @@ struct platform_device; /* don't need the contents */ | |||
25 | 25 | ||
26 | void s5p6440_i2c1_cfg_gpio(struct platform_device *dev) | 26 | void s5p6440_i2c1_cfg_gpio(struct platform_device *dev) |
27 | { | 27 | { |
28 | s3c_gpio_cfgpin(S5P6440_GPR(9), S3C_GPIO_SFN(6)); | 28 | s3c_gpio_cfgall_range(S5P6440_GPR(9), 2, |
29 | s3c_gpio_setpull(S5P6440_GPR(9), S3C_GPIO_PULL_UP); | 29 | S3C_GPIO_SFN(6), S3C_GPIO_PULL_UP); |
30 | s3c_gpio_cfgpin(S5P6440_GPR(10), S3C_GPIO_SFN(6)); | ||
31 | s3c_gpio_setpull(S5P6440_GPR(10), S3C_GPIO_PULL_UP); | ||
32 | } | 30 | } |
33 | 31 | ||
34 | void s5p6450_i2c1_cfg_gpio(struct platform_device *dev) | 32 | void s5p6450_i2c1_cfg_gpio(struct platform_device *dev) |
35 | { | 33 | { |
36 | s3c_gpio_cfgpin(S5P6450_GPR(9), S3C_GPIO_SFN(6)); | 34 | s3c_gpio_cfgall_range(S5P6450_GPR(9), 2, |
37 | s3c_gpio_setpull(S5P6450_GPR(9), S3C_GPIO_PULL_UP); | 35 | S3C_GPIO_SFN(6), S3C_GPIO_PULL_UP); |
38 | s3c_gpio_cfgpin(S5P6450_GPR(10), S3C_GPIO_SFN(6)); | ||
39 | s3c_gpio_setpull(S5P6450_GPR(10), S3C_GPIO_PULL_UP); | ||
40 | } | 36 | } |
41 | 37 | ||
42 | void s3c_i2c1_cfg_gpio(struct platform_device *dev) { } | 38 | void s3c_i2c1_cfg_gpio(struct platform_device *dev) { } |
diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig index 77ae4bfb74ba..b8fbf2fcba6f 100644 --- a/arch/arm/mach-s5pc100/Kconfig +++ b/arch/arm/mach-s5pc100/Kconfig | |||
@@ -9,7 +9,6 @@ if ARCH_S5PC100 | |||
9 | 9 | ||
10 | config CPU_S5PC100 | 10 | config CPU_S5PC100 |
11 | bool | 11 | bool |
12 | select PLAT_S5P | ||
13 | select S5P_EXT_INT | 12 | select S5P_EXT_INT |
14 | select S3C_PL330_DMA | 13 | select S3C_PL330_DMA |
15 | help | 14 | help |
diff --git a/arch/arm/mach-s5pc100/Makefile b/arch/arm/mach-s5pc100/Makefile index a021ed1fb4b6..eecab57d2e5d 100644 --- a/arch/arm/mach-s5pc100/Makefile +++ b/arch/arm/mach-s5pc100/Makefile | |||
@@ -11,7 +11,7 @@ obj- := | |||
11 | 11 | ||
12 | # Core support for S5PC100 system | 12 | # Core support for S5PC100 system |
13 | 13 | ||
14 | obj-$(CONFIG_CPU_S5PC100) += cpu.o init.o clock.o gpiolib.o irq-gpio.o | 14 | obj-$(CONFIG_CPU_S5PC100) += cpu.o init.o clock.o gpiolib.o |
15 | obj-$(CONFIG_CPU_S5PC100) += setup-i2c0.o | 15 | obj-$(CONFIG_CPU_S5PC100) += setup-i2c0.o |
16 | obj-$(CONFIG_CPU_S5PC100) += dma.o | 16 | obj-$(CONFIG_CPU_S5PC100) += dma.o |
17 | 17 | ||
diff --git a/arch/arm/mach-s5pc100/clock.c b/arch/arm/mach-s5pc100/clock.c index 084abd13b0a5..2d4a761a5163 100644 --- a/arch/arm/mach-s5pc100/clock.c +++ b/arch/arm/mach-s5pc100/clock.c | |||
@@ -273,24 +273,6 @@ static struct clksrc_clk clk_div_hdmi = { | |||
273 | .reg_div = { .reg = S5P_CLK_DIV3, .shift = 28, .size = 4 }, | 273 | .reg_div = { .reg = S5P_CLK_DIV3, .shift = 28, .size = 4 }, |
274 | }; | 274 | }; |
275 | 275 | ||
276 | static int s5pc100_epll_enable(struct clk *clk, int enable) | ||
277 | { | ||
278 | unsigned int ctrlbit = clk->ctrlbit; | ||
279 | unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit; | ||
280 | |||
281 | if (enable) | ||
282 | __raw_writel(epll_con | ctrlbit, S5P_EPLL_CON); | ||
283 | else | ||
284 | __raw_writel(epll_con, S5P_EPLL_CON); | ||
285 | |||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static unsigned long s5pc100_epll_get_rate(struct clk *clk) | ||
290 | { | ||
291 | return clk->rate; | ||
292 | } | ||
293 | |||
294 | static u32 epll_div[][4] = { | 276 | static u32 epll_div[][4] = { |
295 | { 32750000, 131, 3, 4 }, | 277 | { 32750000, 131, 3, 4 }, |
296 | { 32768000, 131, 3, 4 }, | 278 | { 32768000, 131, 3, 4 }, |
@@ -341,13 +323,16 @@ static int s5pc100_epll_set_rate(struct clk *clk, unsigned long rate) | |||
341 | 323 | ||
342 | __raw_writel(epll_con, S5P_EPLL_CON); | 324 | __raw_writel(epll_con, S5P_EPLL_CON); |
343 | 325 | ||
326 | printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n", | ||
327 | clk->rate, rate); | ||
328 | |||
344 | clk->rate = rate; | 329 | clk->rate = rate; |
345 | 330 | ||
346 | return 0; | 331 | return 0; |
347 | } | 332 | } |
348 | 333 | ||
349 | static struct clk_ops s5pc100_epll_ops = { | 334 | static struct clk_ops s5pc100_epll_ops = { |
350 | .get_rate = s5pc100_epll_get_rate, | 335 | .get_rate = s5p_epll_get_rate, |
351 | .set_rate = s5pc100_epll_set_rate, | 336 | .set_rate = s5pc100_epll_set_rate, |
352 | }; | 337 | }; |
353 | 338 | ||
@@ -691,55 +676,55 @@ static struct clk init_clocks_disable[] = { | |||
691 | }, { | 676 | }, { |
692 | .name = "iis", | 677 | .name = "iis", |
693 | .id = 0, | 678 | .id = 0, |
694 | .parent = &clk_div_d1_bus.clk, | 679 | .parent = &clk_div_pclkd1.clk, |
695 | .enable = s5pc100_d1_5_ctrl, | 680 | .enable = s5pc100_d1_5_ctrl, |
696 | .ctrlbit = (1 << 0), | 681 | .ctrlbit = (1 << 0), |
697 | }, { | 682 | }, { |
698 | .name = "iis", | 683 | .name = "iis", |
699 | .id = 1, | 684 | .id = 1, |
700 | .parent = &clk_div_d1_bus.clk, | 685 | .parent = &clk_div_pclkd1.clk, |
701 | .enable = s5pc100_d1_5_ctrl, | 686 | .enable = s5pc100_d1_5_ctrl, |
702 | .ctrlbit = (1 << 1), | 687 | .ctrlbit = (1 << 1), |
703 | }, { | 688 | }, { |
704 | .name = "iis", | 689 | .name = "iis", |
705 | .id = 2, | 690 | .id = 2, |
706 | .parent = &clk_div_d1_bus.clk, | 691 | .parent = &clk_div_pclkd1.clk, |
707 | .enable = s5pc100_d1_5_ctrl, | 692 | .enable = s5pc100_d1_5_ctrl, |
708 | .ctrlbit = (1 << 2), | 693 | .ctrlbit = (1 << 2), |
709 | }, { | 694 | }, { |
710 | .name = "ac97", | 695 | .name = "ac97", |
711 | .id = -1, | 696 | .id = -1, |
712 | .parent = &clk_div_d1_bus.clk, | 697 | .parent = &clk_div_pclkd1.clk, |
713 | .enable = s5pc100_d1_5_ctrl, | 698 | .enable = s5pc100_d1_5_ctrl, |
714 | .ctrlbit = (1 << 3), | 699 | .ctrlbit = (1 << 3), |
715 | }, { | 700 | }, { |
716 | .name = "pcm", | 701 | .name = "pcm", |
717 | .id = 0, | 702 | .id = 0, |
718 | .parent = &clk_div_d1_bus.clk, | 703 | .parent = &clk_div_pclkd1.clk, |
719 | .enable = s5pc100_d1_5_ctrl, | 704 | .enable = s5pc100_d1_5_ctrl, |
720 | .ctrlbit = (1 << 4), | 705 | .ctrlbit = (1 << 4), |
721 | }, { | 706 | }, { |
722 | .name = "pcm", | 707 | .name = "pcm", |
723 | .id = 1, | 708 | .id = 1, |
724 | .parent = &clk_div_d1_bus.clk, | 709 | .parent = &clk_div_pclkd1.clk, |
725 | .enable = s5pc100_d1_5_ctrl, | 710 | .enable = s5pc100_d1_5_ctrl, |
726 | .ctrlbit = (1 << 5), | 711 | .ctrlbit = (1 << 5), |
727 | }, { | 712 | }, { |
728 | .name = "spdif", | 713 | .name = "spdif", |
729 | .id = -1, | 714 | .id = -1, |
730 | .parent = &clk_div_d1_bus.clk, | 715 | .parent = &clk_div_pclkd1.clk, |
731 | .enable = s5pc100_d1_5_ctrl, | 716 | .enable = s5pc100_d1_5_ctrl, |
732 | .ctrlbit = (1 << 6), | 717 | .ctrlbit = (1 << 6), |
733 | }, { | 718 | }, { |
734 | .name = "adc", | 719 | .name = "adc", |
735 | .id = -1, | 720 | .id = -1, |
736 | .parent = &clk_div_d1_bus.clk, | 721 | .parent = &clk_div_pclkd1.clk, |
737 | .enable = s5pc100_d1_5_ctrl, | 722 | .enable = s5pc100_d1_5_ctrl, |
738 | .ctrlbit = (1 << 7), | 723 | .ctrlbit = (1 << 7), |
739 | }, { | 724 | }, { |
740 | .name = "keypad", | 725 | .name = "keypad", |
741 | .id = -1, | 726 | .id = -1, |
742 | .parent = &clk_div_d1_bus.clk, | 727 | .parent = &clk_div_pclkd1.clk, |
743 | .enable = s5pc100_d1_5_ctrl, | 728 | .enable = s5pc100_d1_5_ctrl, |
744 | .ctrlbit = (1 << 8), | 729 | .ctrlbit = (1 << 8), |
745 | }, { | 730 | }, { |
@@ -848,6 +833,18 @@ struct clksrc_sources clk_src_group3 = { | |||
848 | .nr_sources = ARRAY_SIZE(clk_src_group3_list), | 833 | .nr_sources = ARRAY_SIZE(clk_src_group3_list), |
849 | }; | 834 | }; |
850 | 835 | ||
836 | static struct clksrc_clk clk_sclk_audio0 = { | ||
837 | .clk = { | ||
838 | .name = "sclk_audio", | ||
839 | .id = 0, | ||
840 | .ctrlbit = (1 << 8), | ||
841 | .enable = s5pc100_sclk1_ctrl, | ||
842 | }, | ||
843 | .sources = &clk_src_group3, | ||
844 | .reg_src = { .reg = S5P_CLK_SRC3, .shift = 12, .size = 3 }, | ||
845 | .reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 }, | ||
846 | }; | ||
847 | |||
851 | static struct clk *clk_src_group4_list[] = { | 848 | static struct clk *clk_src_group4_list[] = { |
852 | [0] = &clk_mout_epll.clk, | 849 | [0] = &clk_mout_epll.clk, |
853 | [1] = &clk_div_mpll.clk, | 850 | [1] = &clk_div_mpll.clk, |
@@ -862,6 +859,18 @@ struct clksrc_sources clk_src_group4 = { | |||
862 | .nr_sources = ARRAY_SIZE(clk_src_group4_list), | 859 | .nr_sources = ARRAY_SIZE(clk_src_group4_list), |
863 | }; | 860 | }; |
864 | 861 | ||
862 | static struct clksrc_clk clk_sclk_audio1 = { | ||
863 | .clk = { | ||
864 | .name = "sclk_audio", | ||
865 | .id = 1, | ||
866 | .ctrlbit = (1 << 9), | ||
867 | .enable = s5pc100_sclk1_ctrl, | ||
868 | }, | ||
869 | .sources = &clk_src_group4, | ||
870 | .reg_src = { .reg = S5P_CLK_SRC3, .shift = 16, .size = 3 }, | ||
871 | .reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 }, | ||
872 | }; | ||
873 | |||
865 | static struct clk *clk_src_group5_list[] = { | 874 | static struct clk *clk_src_group5_list[] = { |
866 | [0] = &clk_mout_epll.clk, | 875 | [0] = &clk_mout_epll.clk, |
867 | [1] = &clk_div_mpll.clk, | 876 | [1] = &clk_div_mpll.clk, |
@@ -875,6 +884,18 @@ struct clksrc_sources clk_src_group5 = { | |||
875 | .nr_sources = ARRAY_SIZE(clk_src_group5_list), | 884 | .nr_sources = ARRAY_SIZE(clk_src_group5_list), |
876 | }; | 885 | }; |
877 | 886 | ||
887 | static struct clksrc_clk clk_sclk_audio2 = { | ||
888 | .clk = { | ||
889 | .name = "sclk_audio", | ||
890 | .id = 2, | ||
891 | .ctrlbit = (1 << 10), | ||
892 | .enable = s5pc100_sclk1_ctrl, | ||
893 | }, | ||
894 | .sources = &clk_src_group5, | ||
895 | .reg_src = { .reg = S5P_CLK_SRC3, .shift = 20, .size = 3 }, | ||
896 | .reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 }, | ||
897 | }; | ||
898 | |||
878 | static struct clk *clk_src_group6_list[] = { | 899 | static struct clk *clk_src_group6_list[] = { |
879 | [0] = &s5p_clk_27m, | 900 | [0] = &s5p_clk_27m, |
880 | [1] = &clk_vclk54m, | 901 | [1] = &clk_vclk54m, |
@@ -944,6 +965,64 @@ struct clksrc_sources clk_src_pwi = { | |||
944 | .nr_sources = ARRAY_SIZE(clk_src_pwi_list), | 965 | .nr_sources = ARRAY_SIZE(clk_src_pwi_list), |
945 | }; | 966 | }; |
946 | 967 | ||
968 | static struct clk *clk_sclk_spdif_list[] = { | ||
969 | [0] = &clk_sclk_audio0.clk, | ||
970 | [1] = &clk_sclk_audio1.clk, | ||
971 | [2] = &clk_sclk_audio2.clk, | ||
972 | }; | ||
973 | |||
974 | struct clksrc_sources clk_src_sclk_spdif = { | ||
975 | .sources = clk_sclk_spdif_list, | ||
976 | .nr_sources = ARRAY_SIZE(clk_sclk_spdif_list), | ||
977 | }; | ||
978 | |||
979 | static int s5pc100_spdif_set_rate(struct clk *clk, unsigned long rate) | ||
980 | { | ||
981 | struct clk *pclk; | ||
982 | int ret; | ||
983 | |||
984 | pclk = clk_get_parent(clk); | ||
985 | if (IS_ERR(pclk)) | ||
986 | return -EINVAL; | ||
987 | |||
988 | ret = pclk->ops->set_rate(pclk, rate); | ||
989 | clk_put(pclk); | ||
990 | |||
991 | return ret; | ||
992 | } | ||
993 | |||
994 | static unsigned long s5pc100_spdif_get_rate(struct clk *clk) | ||
995 | { | ||
996 | struct clk *pclk; | ||
997 | int rate; | ||
998 | |||
999 | pclk = clk_get_parent(clk); | ||
1000 | if (IS_ERR(pclk)) | ||
1001 | return -EINVAL; | ||
1002 | |||
1003 | rate = pclk->ops->get_rate(clk); | ||
1004 | clk_put(pclk); | ||
1005 | |||
1006 | return rate; | ||
1007 | } | ||
1008 | |||
1009 | static struct clk_ops s5pc100_sclk_spdif_ops = { | ||
1010 | .set_rate = s5pc100_spdif_set_rate, | ||
1011 | .get_rate = s5pc100_spdif_get_rate, | ||
1012 | }; | ||
1013 | |||
1014 | static struct clksrc_clk clk_sclk_spdif = { | ||
1015 | .clk = { | ||
1016 | .name = "sclk_spdif", | ||
1017 | .id = -1, | ||
1018 | .ctrlbit = (1 << 11), | ||
1019 | .enable = s5pc100_sclk1_ctrl, | ||
1020 | .ops = &s5pc100_sclk_spdif_ops, | ||
1021 | }, | ||
1022 | .sources = &clk_src_sclk_spdif, | ||
1023 | .reg_src = { .reg = S5P_CLK_SRC3, .shift = 24, .size = 2 }, | ||
1024 | }; | ||
1025 | |||
947 | static struct clksrc_clk clksrcs[] = { | 1026 | static struct clksrc_clk clksrcs[] = { |
948 | { | 1027 | { |
949 | .clk = { | 1028 | .clk = { |
@@ -1001,39 +1080,6 @@ static struct clksrc_clk clksrcs[] = { | |||
1001 | .reg_src = { .reg = S5P_CLK_SRC2, .shift = 28, .size = 2 }, | 1080 | .reg_src = { .reg = S5P_CLK_SRC2, .shift = 28, .size = 2 }, |
1002 | }, { | 1081 | }, { |
1003 | .clk = { | 1082 | .clk = { |
1004 | .name = "sclk_audio", | ||
1005 | .id = 0, | ||
1006 | .ctrlbit = (1 << 8), | ||
1007 | .enable = s5pc100_sclk1_ctrl, | ||
1008 | |||
1009 | }, | ||
1010 | .sources = &clk_src_group3, | ||
1011 | .reg_src = { .reg = S5P_CLK_SRC3, .shift = 12, .size = 3 }, | ||
1012 | .reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 }, | ||
1013 | }, { | ||
1014 | .clk = { | ||
1015 | .name = "sclk_audio", | ||
1016 | .id = 1, | ||
1017 | .ctrlbit = (1 << 9), | ||
1018 | .enable = s5pc100_sclk1_ctrl, | ||
1019 | |||
1020 | }, | ||
1021 | .sources = &clk_src_group4, | ||
1022 | .reg_src = { .reg = S5P_CLK_SRC3, .shift = 16, .size = 3 }, | ||
1023 | .reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 }, | ||
1024 | }, { | ||
1025 | .clk = { | ||
1026 | .name = "sclk_audio", | ||
1027 | .id = 2, | ||
1028 | .ctrlbit = (1 << 10), | ||
1029 | .enable = s5pc100_sclk1_ctrl, | ||
1030 | |||
1031 | }, | ||
1032 | .sources = &clk_src_group5, | ||
1033 | .reg_src = { .reg = S5P_CLK_SRC3, .shift = 20, .size = 3 }, | ||
1034 | .reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 }, | ||
1035 | }, { | ||
1036 | .clk = { | ||
1037 | .name = "sclk_lcd", | 1083 | .name = "sclk_lcd", |
1038 | .id = -1, | 1084 | .id = -1, |
1039 | .ctrlbit = (1 << 0), | 1085 | .ctrlbit = (1 << 0), |
@@ -1179,6 +1225,10 @@ static struct clksrc_clk *sysclks[] = { | |||
1179 | &clk_div_pclkd1, | 1225 | &clk_div_pclkd1, |
1180 | &clk_div_cam, | 1226 | &clk_div_cam, |
1181 | &clk_div_hdmi, | 1227 | &clk_div_hdmi, |
1228 | &clk_sclk_audio0, | ||
1229 | &clk_sclk_audio1, | ||
1230 | &clk_sclk_audio2, | ||
1231 | &clk_sclk_spdif, | ||
1182 | }; | 1232 | }; |
1183 | 1233 | ||
1184 | void __init_or_cpufreq s5pc100_setup_clocks(void) | 1234 | void __init_or_cpufreq s5pc100_setup_clocks(void) |
@@ -1196,7 +1246,7 @@ void __init_or_cpufreq s5pc100_setup_clocks(void) | |||
1196 | unsigned int ptr; | 1246 | unsigned int ptr; |
1197 | 1247 | ||
1198 | /* Set S5PC100 functions for clk_fout_epll */ | 1248 | /* Set S5PC100 functions for clk_fout_epll */ |
1199 | clk_fout_epll.enable = s5pc100_epll_enable; | 1249 | clk_fout_epll.enable = s5p_epll_enable; |
1200 | clk_fout_epll.ops = &s5pc100_epll_ops; | 1250 | clk_fout_epll.ops = &s5pc100_epll_ops; |
1201 | 1251 | ||
1202 | printk(KERN_DEBUG "%s: registering clocks\n", __func__); | 1252 | printk(KERN_DEBUG "%s: registering clocks\n", __func__); |
diff --git a/arch/arm/mach-s5pc100/dev-audio.c b/arch/arm/mach-s5pc100/dev-audio.c index a699ed6acc23..564e195ec493 100644 --- a/arch/arm/mach-s5pc100/dev-audio.c +++ b/arch/arm/mach-s5pc100/dev-audio.c | |||
@@ -24,19 +24,11 @@ static int s5pc100_cfg_i2s(struct platform_device *pdev) | |||
24 | /* configure GPIO for i2s port */ | 24 | /* configure GPIO for i2s port */ |
25 | switch (pdev->id) { | 25 | switch (pdev->id) { |
26 | case 1: | 26 | case 1: |
27 | s3c_gpio_cfgpin(S5PC100_GPC(0), S3C_GPIO_SFN(2)); | 27 | s3c_gpio_cfgpin_range(S5PC100_GPC(0), 5, S3C_GPIO_SFN(2)); |
28 | s3c_gpio_cfgpin(S5PC100_GPC(1), S3C_GPIO_SFN(2)); | ||
29 | s3c_gpio_cfgpin(S5PC100_GPC(2), S3C_GPIO_SFN(2)); | ||
30 | s3c_gpio_cfgpin(S5PC100_GPC(3), S3C_GPIO_SFN(2)); | ||
31 | s3c_gpio_cfgpin(S5PC100_GPC(4), S3C_GPIO_SFN(2)); | ||
32 | break; | 28 | break; |
33 | 29 | ||
34 | case 2: | 30 | case 2: |
35 | s3c_gpio_cfgpin(S5PC100_GPG3(0), S3C_GPIO_SFN(4)); | 31 | s3c_gpio_cfgpin_range(S5PC100_GPG3(0), 5, S3C_GPIO_SFN(4)); |
36 | s3c_gpio_cfgpin(S5PC100_GPG3(1), S3C_GPIO_SFN(4)); | ||
37 | s3c_gpio_cfgpin(S5PC100_GPG3(2), S3C_GPIO_SFN(4)); | ||
38 | s3c_gpio_cfgpin(S5PC100_GPG3(3), S3C_GPIO_SFN(4)); | ||
39 | s3c_gpio_cfgpin(S5PC100_GPG3(4), S3C_GPIO_SFN(4)); | ||
40 | break; | 32 | break; |
41 | 33 | ||
42 | case -1: /* Dedicated pins */ | 34 | case -1: /* Dedicated pins */ |
@@ -144,19 +136,11 @@ static int s5pc100_pcm_cfg_gpio(struct platform_device *pdev) | |||
144 | { | 136 | { |
145 | switch (pdev->id) { | 137 | switch (pdev->id) { |
146 | case 0: | 138 | case 0: |
147 | s3c_gpio_cfgpin(S5PC100_GPG3(0), S3C_GPIO_SFN(5)); | 139 | s3c_gpio_cfgpin_range(S5PC100_GPG3(0), 5, S3C_GPIO_SFN(5)); |
148 | s3c_gpio_cfgpin(S5PC100_GPG3(1), S3C_GPIO_SFN(5)); | ||
149 | s3c_gpio_cfgpin(S5PC100_GPG3(2), S3C_GPIO_SFN(5)); | ||
150 | s3c_gpio_cfgpin(S5PC100_GPG3(3), S3C_GPIO_SFN(5)); | ||
151 | s3c_gpio_cfgpin(S5PC100_GPG3(4), S3C_GPIO_SFN(5)); | ||
152 | break; | 140 | break; |
153 | 141 | ||
154 | case 1: | 142 | case 1: |
155 | s3c_gpio_cfgpin(S5PC100_GPC(0), S3C_GPIO_SFN(3)); | 143 | s3c_gpio_cfgpin_range(S5PC100_GPC(0), 5, S3C_GPIO_SFN(3)); |
156 | s3c_gpio_cfgpin(S5PC100_GPC(1), S3C_GPIO_SFN(3)); | ||
157 | s3c_gpio_cfgpin(S5PC100_GPC(2), S3C_GPIO_SFN(3)); | ||
158 | s3c_gpio_cfgpin(S5PC100_GPC(3), S3C_GPIO_SFN(3)); | ||
159 | s3c_gpio_cfgpin(S5PC100_GPC(4), S3C_GPIO_SFN(3)); | ||
160 | break; | 144 | break; |
161 | 145 | ||
162 | default: | 146 | default: |
@@ -231,13 +215,7 @@ struct platform_device s5pc100_device_pcm1 = { | |||
231 | 215 | ||
232 | static int s5pc100_ac97_cfg_gpio(struct platform_device *pdev) | 216 | static int s5pc100_ac97_cfg_gpio(struct platform_device *pdev) |
233 | { | 217 | { |
234 | s3c_gpio_cfgpin(S5PC100_GPC(0), S3C_GPIO_SFN(4)); | 218 | return s3c_gpio_cfgpin_range(S5PC100_GPC(0), 5, S3C_GPIO_SFN(4)); |
235 | s3c_gpio_cfgpin(S5PC100_GPC(1), S3C_GPIO_SFN(4)); | ||
236 | s3c_gpio_cfgpin(S5PC100_GPC(2), S3C_GPIO_SFN(4)); | ||
237 | s3c_gpio_cfgpin(S5PC100_GPC(3), S3C_GPIO_SFN(4)); | ||
238 | s3c_gpio_cfgpin(S5PC100_GPC(4), S3C_GPIO_SFN(4)); | ||
239 | |||
240 | return 0; | ||
241 | } | 219 | } |
242 | 220 | ||
243 | static struct resource s5pc100_ac97_resource[] = { | 221 | static struct resource s5pc100_ac97_resource[] = { |
@@ -285,3 +263,57 @@ struct platform_device s5pc100_device_ac97 = { | |||
285 | .coherent_dma_mask = DMA_BIT_MASK(32), | 263 | .coherent_dma_mask = DMA_BIT_MASK(32), |
286 | }, | 264 | }, |
287 | }; | 265 | }; |
266 | |||
267 | /* S/PDIF Controller platform_device */ | ||
268 | static int s5pc100_spdif_cfg_gpd(struct platform_device *pdev) | ||
269 | { | ||
270 | s3c_gpio_cfgpin_range(S5PC100_GPD(5), 2, S3C_GPIO_SFN(3)); | ||
271 | |||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | static int s5pc100_spdif_cfg_gpg3(struct platform_device *pdev) | ||
276 | { | ||
277 | s3c_gpio_cfgpin_range(S5PC100_GPG3(5), 2, S3C_GPIO_SFN(3)); | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | static struct resource s5pc100_spdif_resource[] = { | ||
283 | [0] = { | ||
284 | .start = S5PC100_PA_SPDIF, | ||
285 | .end = S5PC100_PA_SPDIF + 0x100 - 1, | ||
286 | .flags = IORESOURCE_MEM, | ||
287 | }, | ||
288 | [1] = { | ||
289 | .start = DMACH_SPDIF, | ||
290 | .end = DMACH_SPDIF, | ||
291 | .flags = IORESOURCE_DMA, | ||
292 | }, | ||
293 | }; | ||
294 | |||
295 | static struct s3c_audio_pdata s5p_spdif_pdata = { | ||
296 | .cfg_gpio = s5pc100_spdif_cfg_gpd, | ||
297 | }; | ||
298 | |||
299 | static u64 s5pc100_spdif_dmamask = DMA_BIT_MASK(32); | ||
300 | |||
301 | struct platform_device s5pc100_device_spdif = { | ||
302 | .name = "samsung-spdif", | ||
303 | .id = -1, | ||
304 | .num_resources = ARRAY_SIZE(s5pc100_spdif_resource), | ||
305 | .resource = s5pc100_spdif_resource, | ||
306 | .dev = { | ||
307 | .platform_data = &s5p_spdif_pdata, | ||
308 | .dma_mask = &s5pc100_spdif_dmamask, | ||
309 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
310 | }, | ||
311 | }; | ||
312 | |||
313 | void __init s5pc100_spdif_setup_gpio(int gpio) | ||
314 | { | ||
315 | if (gpio == S5PC100_SPDIF_GPD) | ||
316 | s5p_spdif_pdata.cfg_gpio = s5pc100_spdif_cfg_gpd; | ||
317 | else | ||
318 | s5p_spdif_pdata.cfg_gpio = s5pc100_spdif_cfg_gpg3; | ||
319 | } | ||
diff --git a/arch/arm/mach-s5pc100/dev-spi.c b/arch/arm/mach-s5pc100/dev-spi.c index a0ef7c302c16..57b19794d9bb 100644 --- a/arch/arm/mach-s5pc100/dev-spi.c +++ b/arch/arm/mach-s5pc100/dev-spi.c | |||
@@ -38,30 +38,20 @@ static int s5pc100_spi_cfg_gpio(struct platform_device *pdev) | |||
38 | { | 38 | { |
39 | switch (pdev->id) { | 39 | switch (pdev->id) { |
40 | case 0: | 40 | case 0: |
41 | s3c_gpio_cfgpin(S5PC100_GPB(0), S3C_GPIO_SFN(2)); | 41 | s3c_gpio_cfgall_range(S5PC100_GPB(0), 3, |
42 | s3c_gpio_cfgpin(S5PC100_GPB(1), S3C_GPIO_SFN(2)); | 42 | S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); |
43 | s3c_gpio_cfgpin(S5PC100_GPB(2), S3C_GPIO_SFN(2)); | ||
44 | s3c_gpio_setpull(S5PC100_GPB(0), S3C_GPIO_PULL_UP); | ||
45 | s3c_gpio_setpull(S5PC100_GPB(1), S3C_GPIO_PULL_UP); | ||
46 | s3c_gpio_setpull(S5PC100_GPB(2), S3C_GPIO_PULL_UP); | ||
47 | break; | 43 | break; |
48 | 44 | ||
49 | case 1: | 45 | case 1: |
50 | s3c_gpio_cfgpin(S5PC100_GPB(4), S3C_GPIO_SFN(2)); | 46 | s3c_gpio_cfgall_range(S5PC100_GPB(4), 3, |
51 | s3c_gpio_cfgpin(S5PC100_GPB(5), S3C_GPIO_SFN(2)); | 47 | S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); |
52 | s3c_gpio_cfgpin(S5PC100_GPB(6), S3C_GPIO_SFN(2)); | ||
53 | s3c_gpio_setpull(S5PC100_GPB(4), S3C_GPIO_PULL_UP); | ||
54 | s3c_gpio_setpull(S5PC100_GPB(5), S3C_GPIO_PULL_UP); | ||
55 | s3c_gpio_setpull(S5PC100_GPB(6), S3C_GPIO_PULL_UP); | ||
56 | break; | 48 | break; |
57 | 49 | ||
58 | case 2: | 50 | case 2: |
59 | s3c_gpio_cfgpin(S5PC100_GPG3(0), S3C_GPIO_SFN(3)); | 51 | s3c_gpio_cfgpin(S5PC100_GPG3(0), S3C_GPIO_SFN(3)); |
60 | s3c_gpio_cfgpin(S5PC100_GPG3(2), S3C_GPIO_SFN(3)); | ||
61 | s3c_gpio_cfgpin(S5PC100_GPG3(3), S3C_GPIO_SFN(3)); | ||
62 | s3c_gpio_setpull(S5PC100_GPG3(0), S3C_GPIO_PULL_UP); | 52 | s3c_gpio_setpull(S5PC100_GPG3(0), S3C_GPIO_PULL_UP); |
63 | s3c_gpio_setpull(S5PC100_GPG3(2), S3C_GPIO_PULL_UP); | 53 | s3c_gpio_cfgall_range(S5PC100_GPB(2), 2, |
64 | s3c_gpio_setpull(S5PC100_GPG3(3), S3C_GPIO_PULL_UP); | 54 | S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP); |
65 | break; | 55 | break; |
66 | 56 | ||
67 | default: | 57 | default: |
diff --git a/arch/arm/mach-s5pc100/dma.c b/arch/arm/mach-s5pc100/dma.c index 0f5517571e2c..bf4cd0fb97c6 100644 --- a/arch/arm/mach-s5pc100/dma.c +++ b/arch/arm/mach-s5pc100/dma.c | |||
@@ -81,7 +81,7 @@ static struct s3c_pl330_platdata s5pc100_pdma0_pdata = { | |||
81 | 81 | ||
82 | static struct platform_device s5pc100_device_pdma0 = { | 82 | static struct platform_device s5pc100_device_pdma0 = { |
83 | .name = "s3c-pl330", | 83 | .name = "s3c-pl330", |
84 | .id = 1, | 84 | .id = 0, |
85 | .num_resources = ARRAY_SIZE(s5pc100_pdma0_resource), | 85 | .num_resources = ARRAY_SIZE(s5pc100_pdma0_resource), |
86 | .resource = s5pc100_pdma0_resource, | 86 | .resource = s5pc100_pdma0_resource, |
87 | .dev = { | 87 | .dev = { |
@@ -143,7 +143,7 @@ static struct s3c_pl330_platdata s5pc100_pdma1_pdata = { | |||
143 | 143 | ||
144 | static struct platform_device s5pc100_device_pdma1 = { | 144 | static struct platform_device s5pc100_device_pdma1 = { |
145 | .name = "s3c-pl330", | 145 | .name = "s3c-pl330", |
146 | .id = 2, | 146 | .id = 1, |
147 | .num_resources = ARRAY_SIZE(s5pc100_pdma1_resource), | 147 | .num_resources = ARRAY_SIZE(s5pc100_pdma1_resource), |
148 | .resource = s5pc100_pdma1_resource, | 148 | .resource = s5pc100_pdma1_resource, |
149 | .dev = { | 149 | .dev = { |
diff --git a/arch/arm/mach-s5pc100/gpiolib.c b/arch/arm/mach-s5pc100/gpiolib.c index 0fab7f2cd8bf..20856eb7dd51 100644 --- a/arch/arm/mach-s5pc100/gpiolib.c +++ b/arch/arm/mach-s5pc100/gpiolib.c | |||
@@ -1,5 +1,7 @@ | |||
1 | /* | 1 | /* linux/arch/arm/mach-s5pc100/gpiolib.c |
2 | * arch/arm/plat-s5pc100/gpiolib.c | 2 | * |
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
3 | * | 5 | * |
4 | * Copyright 2009 Samsung Electronics Co | 6 | * Copyright 2009 Samsung Electronics Co |
5 | * Kyungmin Park <kyungmin.park@samsung.com> | 7 | * Kyungmin Park <kyungmin.park@samsung.com> |
@@ -61,30 +63,6 @@ | |||
61 | * L3 8 4Bit None | 63 | * L3 8 4Bit None |
62 | */ | 64 | */ |
63 | 65 | ||
64 | static int s5pc100_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset) | ||
65 | { | ||
66 | return S3C_IRQ_GPIO(chip->base + offset); | ||
67 | } | ||
68 | |||
69 | static int s5pc100_gpiolib_to_eint(struct gpio_chip *chip, unsigned int offset) | ||
70 | { | ||
71 | int base; | ||
72 | |||
73 | base = chip->base - S5PC100_GPH0(0); | ||
74 | if (base == 0) | ||
75 | return IRQ_EINT(offset); | ||
76 | base = chip->base - S5PC100_GPH1(0); | ||
77 | if (base == 0) | ||
78 | return IRQ_EINT(8 + offset); | ||
79 | base = chip->base - S5PC100_GPH2(0); | ||
80 | if (base == 0) | ||
81 | return IRQ_EINT(16 + offset); | ||
82 | base = chip->base - S5PC100_GPH3(0); | ||
83 | if (base == 0) | ||
84 | return IRQ_EINT(24 + offset); | ||
85 | return -EINVAL; | ||
86 | } | ||
87 | |||
88 | static struct s3c_gpio_cfg gpio_cfg = { | 66 | static struct s3c_gpio_cfg gpio_cfg = { |
89 | .set_config = s3c_gpio_setcfg_s3c64xx_4bit, | 67 | .set_config = s3c_gpio_setcfg_s3c64xx_4bit, |
90 | .set_pull = s3c_gpio_setpull_updown, | 68 | .set_pull = s3c_gpio_setpull_updown, |
@@ -104,209 +82,150 @@ static struct s3c_gpio_cfg gpio_cfg_noint = { | |||
104 | .get_pull = s3c_gpio_getpull_updown, | 82 | .get_pull = s3c_gpio_getpull_updown, |
105 | }; | 83 | }; |
106 | 84 | ||
85 | /* | ||
86 | * GPIO bank's base address given the index of the bank in the | ||
87 | * list of all gpio banks. | ||
88 | */ | ||
89 | #define S5PC100_BANK_BASE(bank_nr) (S5P_VA_GPIO + ((bank_nr) * 0x20)) | ||
90 | |||
91 | /* | ||
92 | * Following are the gpio banks in S5PC100. | ||
93 | * | ||
94 | * The 'config' member when left to NULL, is initialized to the default | ||
95 | * structure gpio_cfg in the init function below. | ||
96 | * | ||
97 | * The 'base' member is also initialized in the init function below. | ||
98 | * Note: The initialization of 'base' member of s3c_gpio_chip structure | ||
99 | * uses the above macro and depends on the banks being listed in order here. | ||
100 | */ | ||
107 | static struct s3c_gpio_chip s5pc100_gpio_chips[] = { | 101 | static struct s3c_gpio_chip s5pc100_gpio_chips[] = { |
108 | { | 102 | { |
109 | .base = S5PC100_GPA0_BASE, | ||
110 | .config = &gpio_cfg, | ||
111 | .chip = { | 103 | .chip = { |
112 | .base = S5PC100_GPA0(0), | 104 | .base = S5PC100_GPA0(0), |
113 | .ngpio = S5PC100_GPIO_A0_NR, | 105 | .ngpio = S5PC100_GPIO_A0_NR, |
114 | .label = "GPA0", | 106 | .label = "GPA0", |
115 | }, | 107 | }, |
116 | }, { | 108 | }, { |
117 | .base = S5PC100_GPA1_BASE, | ||
118 | .config = &gpio_cfg, | ||
119 | .chip = { | 109 | .chip = { |
120 | .base = S5PC100_GPA1(0), | 110 | .base = S5PC100_GPA1(0), |
121 | .ngpio = S5PC100_GPIO_A1_NR, | 111 | .ngpio = S5PC100_GPIO_A1_NR, |
122 | .label = "GPA1", | 112 | .label = "GPA1", |
123 | }, | 113 | }, |
124 | }, { | 114 | }, { |
125 | .base = S5PC100_GPB_BASE, | ||
126 | .config = &gpio_cfg, | ||
127 | .chip = { | 115 | .chip = { |
128 | .base = S5PC100_GPB(0), | 116 | .base = S5PC100_GPB(0), |
129 | .ngpio = S5PC100_GPIO_B_NR, | 117 | .ngpio = S5PC100_GPIO_B_NR, |
130 | .label = "GPB", | 118 | .label = "GPB", |
131 | }, | 119 | }, |
132 | }, { | 120 | }, { |
133 | .base = S5PC100_GPC_BASE, | ||
134 | .config = &gpio_cfg, | ||
135 | .chip = { | 121 | .chip = { |
136 | .base = S5PC100_GPC(0), | 122 | .base = S5PC100_GPC(0), |
137 | .ngpio = S5PC100_GPIO_C_NR, | 123 | .ngpio = S5PC100_GPIO_C_NR, |
138 | .label = "GPC", | 124 | .label = "GPC", |
139 | }, | 125 | }, |
140 | }, { | 126 | }, { |
141 | .base = S5PC100_GPD_BASE, | ||
142 | .config = &gpio_cfg, | ||
143 | .chip = { | 127 | .chip = { |
144 | .base = S5PC100_GPD(0), | 128 | .base = S5PC100_GPD(0), |
145 | .ngpio = S5PC100_GPIO_D_NR, | 129 | .ngpio = S5PC100_GPIO_D_NR, |
146 | .label = "GPD", | 130 | .label = "GPD", |
147 | }, | 131 | }, |
148 | }, { | 132 | }, { |
149 | .base = S5PC100_GPE0_BASE, | ||
150 | .config = &gpio_cfg, | ||
151 | .chip = { | 133 | .chip = { |
152 | .base = S5PC100_GPE0(0), | 134 | .base = S5PC100_GPE0(0), |
153 | .ngpio = S5PC100_GPIO_E0_NR, | 135 | .ngpio = S5PC100_GPIO_E0_NR, |
154 | .label = "GPE0", | 136 | .label = "GPE0", |
155 | }, | 137 | }, |
156 | }, { | 138 | }, { |
157 | .base = S5PC100_GPE1_BASE, | ||
158 | .config = &gpio_cfg, | ||
159 | .chip = { | 139 | .chip = { |
160 | .base = S5PC100_GPE1(0), | 140 | .base = S5PC100_GPE1(0), |
161 | .ngpio = S5PC100_GPIO_E1_NR, | 141 | .ngpio = S5PC100_GPIO_E1_NR, |
162 | .label = "GPE1", | 142 | .label = "GPE1", |
163 | }, | 143 | }, |
164 | }, { | 144 | }, { |
165 | .base = S5PC100_GPF0_BASE, | ||
166 | .config = &gpio_cfg, | ||
167 | .chip = { | 145 | .chip = { |
168 | .base = S5PC100_GPF0(0), | 146 | .base = S5PC100_GPF0(0), |
169 | .ngpio = S5PC100_GPIO_F0_NR, | 147 | .ngpio = S5PC100_GPIO_F0_NR, |
170 | .label = "GPF0", | 148 | .label = "GPF0", |
171 | }, | 149 | }, |
172 | }, { | 150 | }, { |
173 | .base = S5PC100_GPF1_BASE, | ||
174 | .config = &gpio_cfg, | ||
175 | .chip = { | 151 | .chip = { |
176 | .base = S5PC100_GPF1(0), | 152 | .base = S5PC100_GPF1(0), |
177 | .ngpio = S5PC100_GPIO_F1_NR, | 153 | .ngpio = S5PC100_GPIO_F1_NR, |
178 | .label = "GPF1", | 154 | .label = "GPF1", |
179 | }, | 155 | }, |
180 | }, { | 156 | }, { |
181 | .base = S5PC100_GPF2_BASE, | ||
182 | .config = &gpio_cfg, | ||
183 | .chip = { | 157 | .chip = { |
184 | .base = S5PC100_GPF2(0), | 158 | .base = S5PC100_GPF2(0), |
185 | .ngpio = S5PC100_GPIO_F2_NR, | 159 | .ngpio = S5PC100_GPIO_F2_NR, |
186 | .label = "GPF2", | 160 | .label = "GPF2", |
187 | }, | 161 | }, |
188 | }, { | 162 | }, { |
189 | .base = S5PC100_GPF3_BASE, | ||
190 | .config = &gpio_cfg, | ||
191 | .chip = { | 163 | .chip = { |
192 | .base = S5PC100_GPF3(0), | 164 | .base = S5PC100_GPF3(0), |
193 | .ngpio = S5PC100_GPIO_F3_NR, | 165 | .ngpio = S5PC100_GPIO_F3_NR, |
194 | .label = "GPF3", | 166 | .label = "GPF3", |
195 | }, | 167 | }, |
196 | }, { | 168 | }, { |
197 | .base = S5PC100_GPG0_BASE, | ||
198 | .config = &gpio_cfg, | ||
199 | .chip = { | 169 | .chip = { |
200 | .base = S5PC100_GPG0(0), | 170 | .base = S5PC100_GPG0(0), |
201 | .ngpio = S5PC100_GPIO_G0_NR, | 171 | .ngpio = S5PC100_GPIO_G0_NR, |
202 | .label = "GPG0", | 172 | .label = "GPG0", |
203 | }, | 173 | }, |
204 | }, { | 174 | }, { |
205 | .base = S5PC100_GPG1_BASE, | ||
206 | .config = &gpio_cfg, | ||
207 | .chip = { | 175 | .chip = { |
208 | .base = S5PC100_GPG1(0), | 176 | .base = S5PC100_GPG1(0), |
209 | .ngpio = S5PC100_GPIO_G1_NR, | 177 | .ngpio = S5PC100_GPIO_G1_NR, |
210 | .label = "GPG1", | 178 | .label = "GPG1", |
211 | }, | 179 | }, |
212 | }, { | 180 | }, { |
213 | .base = S5PC100_GPG2_BASE, | ||
214 | .config = &gpio_cfg, | ||
215 | .chip = { | 181 | .chip = { |
216 | .base = S5PC100_GPG2(0), | 182 | .base = S5PC100_GPG2(0), |
217 | .ngpio = S5PC100_GPIO_G2_NR, | 183 | .ngpio = S5PC100_GPIO_G2_NR, |
218 | .label = "GPG2", | 184 | .label = "GPG2", |
219 | }, | 185 | }, |
220 | }, { | 186 | }, { |
221 | .base = S5PC100_GPG3_BASE, | ||
222 | .config = &gpio_cfg, | ||
223 | .chip = { | 187 | .chip = { |
224 | .base = S5PC100_GPG3(0), | 188 | .base = S5PC100_GPG3(0), |
225 | .ngpio = S5PC100_GPIO_G3_NR, | 189 | .ngpio = S5PC100_GPIO_G3_NR, |
226 | .label = "GPG3", | 190 | .label = "GPG3", |
227 | }, | 191 | }, |
228 | }, { | 192 | }, { |
229 | .base = S5PC100_GPH0_BASE, | ||
230 | .config = &gpio_cfg_eint, | ||
231 | .chip = { | ||
232 | .base = S5PC100_GPH0(0), | ||
233 | .ngpio = S5PC100_GPIO_H0_NR, | ||
234 | .label = "GPH0", | ||
235 | }, | ||
236 | }, { | ||
237 | .base = S5PC100_GPH1_BASE, | ||
238 | .config = &gpio_cfg_eint, | ||
239 | .chip = { | ||
240 | .base = S5PC100_GPH1(0), | ||
241 | .ngpio = S5PC100_GPIO_H1_NR, | ||
242 | .label = "GPH1", | ||
243 | }, | ||
244 | }, { | ||
245 | .base = S5PC100_GPH2_BASE, | ||
246 | .config = &gpio_cfg_eint, | ||
247 | .chip = { | ||
248 | .base = S5PC100_GPH2(0), | ||
249 | .ngpio = S5PC100_GPIO_H2_NR, | ||
250 | .label = "GPH2", | ||
251 | }, | ||
252 | }, { | ||
253 | .base = S5PC100_GPH3_BASE, | ||
254 | .config = &gpio_cfg_eint, | ||
255 | .chip = { | ||
256 | .base = S5PC100_GPH3(0), | ||
257 | .ngpio = S5PC100_GPIO_H3_NR, | ||
258 | .label = "GPH3", | ||
259 | }, | ||
260 | }, { | ||
261 | .base = S5PC100_GPI_BASE, | ||
262 | .config = &gpio_cfg, | ||
263 | .chip = { | 193 | .chip = { |
264 | .base = S5PC100_GPI(0), | 194 | .base = S5PC100_GPI(0), |
265 | .ngpio = S5PC100_GPIO_I_NR, | 195 | .ngpio = S5PC100_GPIO_I_NR, |
266 | .label = "GPI", | 196 | .label = "GPI", |
267 | }, | 197 | }, |
268 | }, { | 198 | }, { |
269 | .base = S5PC100_GPJ0_BASE, | ||
270 | .config = &gpio_cfg, | ||
271 | .chip = { | 199 | .chip = { |
272 | .base = S5PC100_GPJ0(0), | 200 | .base = S5PC100_GPJ0(0), |
273 | .ngpio = S5PC100_GPIO_J0_NR, | 201 | .ngpio = S5PC100_GPIO_J0_NR, |
274 | .label = "GPJ0", | 202 | .label = "GPJ0", |
275 | }, | 203 | }, |
276 | }, { | 204 | }, { |
277 | .base = S5PC100_GPJ1_BASE, | ||
278 | .config = &gpio_cfg, | ||
279 | .chip = { | 205 | .chip = { |
280 | .base = S5PC100_GPJ1(0), | 206 | .base = S5PC100_GPJ1(0), |
281 | .ngpio = S5PC100_GPIO_J1_NR, | 207 | .ngpio = S5PC100_GPIO_J1_NR, |
282 | .label = "GPJ1", | 208 | .label = "GPJ1", |
283 | }, | 209 | }, |
284 | }, { | 210 | }, { |
285 | .base = S5PC100_GPJ2_BASE, | ||
286 | .config = &gpio_cfg, | ||
287 | .chip = { | 211 | .chip = { |
288 | .base = S5PC100_GPJ2(0), | 212 | .base = S5PC100_GPJ2(0), |
289 | .ngpio = S5PC100_GPIO_J2_NR, | 213 | .ngpio = S5PC100_GPIO_J2_NR, |
290 | .label = "GPJ2", | 214 | .label = "GPJ2", |
291 | }, | 215 | }, |
292 | }, { | 216 | }, { |
293 | .base = S5PC100_GPJ3_BASE, | ||
294 | .config = &gpio_cfg, | ||
295 | .chip = { | 217 | .chip = { |
296 | .base = S5PC100_GPJ3(0), | 218 | .base = S5PC100_GPJ3(0), |
297 | .ngpio = S5PC100_GPIO_J3_NR, | 219 | .ngpio = S5PC100_GPIO_J3_NR, |
298 | .label = "GPJ3", | 220 | .label = "GPJ3", |
299 | }, | 221 | }, |
300 | }, { | 222 | }, { |
301 | .base = S5PC100_GPJ4_BASE, | ||
302 | .config = &gpio_cfg, | ||
303 | .chip = { | 223 | .chip = { |
304 | .base = S5PC100_GPJ4(0), | 224 | .base = S5PC100_GPJ4(0), |
305 | .ngpio = S5PC100_GPIO_J4_NR, | 225 | .ngpio = S5PC100_GPIO_J4_NR, |
306 | .label = "GPJ4", | 226 | .label = "GPJ4", |
307 | }, | 227 | }, |
308 | }, { | 228 | }, { |
309 | .base = S5PC100_GPK0_BASE, | ||
310 | .config = &gpio_cfg_noint, | 229 | .config = &gpio_cfg_noint, |
311 | .chip = { | 230 | .chip = { |
312 | .base = S5PC100_GPK0(0), | 231 | .base = S5PC100_GPK0(0), |
@@ -314,7 +233,6 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = { | |||
314 | .label = "GPK0", | 233 | .label = "GPK0", |
315 | }, | 234 | }, |
316 | }, { | 235 | }, { |
317 | .base = S5PC100_GPK1_BASE, | ||
318 | .config = &gpio_cfg_noint, | 236 | .config = &gpio_cfg_noint, |
319 | .chip = { | 237 | .chip = { |
320 | .base = S5PC100_GPK1(0), | 238 | .base = S5PC100_GPK1(0), |
@@ -322,7 +240,6 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = { | |||
322 | .label = "GPK1", | 240 | .label = "GPK1", |
323 | }, | 241 | }, |
324 | }, { | 242 | }, { |
325 | .base = S5PC100_GPK2_BASE, | ||
326 | .config = &gpio_cfg_noint, | 243 | .config = &gpio_cfg_noint, |
327 | .chip = { | 244 | .chip = { |
328 | .base = S5PC100_GPK2(0), | 245 | .base = S5PC100_GPK2(0), |
@@ -330,7 +247,6 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = { | |||
330 | .label = "GPK2", | 247 | .label = "GPK2", |
331 | }, | 248 | }, |
332 | }, { | 249 | }, { |
333 | .base = S5PC100_GPK3_BASE, | ||
334 | .config = &gpio_cfg_noint, | 250 | .config = &gpio_cfg_noint, |
335 | .chip = { | 251 | .chip = { |
336 | .base = S5PC100_GPK3(0), | 252 | .base = S5PC100_GPK3(0), |
@@ -338,7 +254,6 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = { | |||
338 | .label = "GPK3", | 254 | .label = "GPK3", |
339 | }, | 255 | }, |
340 | }, { | 256 | }, { |
341 | .base = S5PC100_GPL0_BASE, | ||
342 | .config = &gpio_cfg_noint, | 257 | .config = &gpio_cfg_noint, |
343 | .chip = { | 258 | .chip = { |
344 | .base = S5PC100_GPL0(0), | 259 | .base = S5PC100_GPL0(0), |
@@ -346,7 +261,6 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = { | |||
346 | .label = "GPL0", | 261 | .label = "GPL0", |
347 | }, | 262 | }, |
348 | }, { | 263 | }, { |
349 | .base = S5PC100_GPL1_BASE, | ||
350 | .config = &gpio_cfg_noint, | 264 | .config = &gpio_cfg_noint, |
351 | .chip = { | 265 | .chip = { |
352 | .base = S5PC100_GPL1(0), | 266 | .base = S5PC100_GPL1(0), |
@@ -354,7 +268,6 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = { | |||
354 | .label = "GPL1", | 268 | .label = "GPL1", |
355 | }, | 269 | }, |
356 | }, { | 270 | }, { |
357 | .base = S5PC100_GPL2_BASE, | ||
358 | .config = &gpio_cfg_noint, | 271 | .config = &gpio_cfg_noint, |
359 | .chip = { | 272 | .chip = { |
360 | .base = S5PC100_GPL2(0), | 273 | .base = S5PC100_GPL2(0), |
@@ -362,7 +275,6 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = { | |||
362 | .label = "GPL2", | 275 | .label = "GPL2", |
363 | }, | 276 | }, |
364 | }, { | 277 | }, { |
365 | .base = S5PC100_GPL3_BASE, | ||
366 | .config = &gpio_cfg_noint, | 278 | .config = &gpio_cfg_noint, |
367 | .chip = { | 279 | .chip = { |
368 | .base = S5PC100_GPL3(0), | 280 | .base = S5PC100_GPL3(0), |
@@ -370,56 +282,72 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = { | |||
370 | .label = "GPL3", | 282 | .label = "GPL3", |
371 | }, | 283 | }, |
372 | }, { | 284 | }, { |
373 | .base = S5PC100_GPL4_BASE, | ||
374 | .config = &gpio_cfg_noint, | 285 | .config = &gpio_cfg_noint, |
375 | .chip = { | 286 | .chip = { |
376 | .base = S5PC100_GPL4(0), | 287 | .base = S5PC100_GPL4(0), |
377 | .ngpio = S5PC100_GPIO_L4_NR, | 288 | .ngpio = S5PC100_GPIO_L4_NR, |
378 | .label = "GPL4", | 289 | .label = "GPL4", |
379 | }, | 290 | }, |
291 | }, { | ||
292 | .base = (S5P_VA_GPIO + 0xC00), | ||
293 | .config = &gpio_cfg_eint, | ||
294 | .irq_base = IRQ_EINT(0), | ||
295 | .chip = { | ||
296 | .base = S5PC100_GPH0(0), | ||
297 | .ngpio = S5PC100_GPIO_H0_NR, | ||
298 | .label = "GPH0", | ||
299 | .to_irq = samsung_gpiolib_to_irq, | ||
300 | }, | ||
301 | }, { | ||
302 | .base = (S5P_VA_GPIO + 0xC20), | ||
303 | .config = &gpio_cfg_eint, | ||
304 | .irq_base = IRQ_EINT(8), | ||
305 | .chip = { | ||
306 | .base = S5PC100_GPH1(0), | ||
307 | .ngpio = S5PC100_GPIO_H1_NR, | ||
308 | .label = "GPH1", | ||
309 | .to_irq = samsung_gpiolib_to_irq, | ||
310 | }, | ||
311 | }, { | ||
312 | .base = (S5P_VA_GPIO + 0xC40), | ||
313 | .config = &gpio_cfg_eint, | ||
314 | .irq_base = IRQ_EINT(16), | ||
315 | .chip = { | ||
316 | .base = S5PC100_GPH2(0), | ||
317 | .ngpio = S5PC100_GPIO_H2_NR, | ||
318 | .label = "GPH2", | ||
319 | .to_irq = samsung_gpiolib_to_irq, | ||
320 | }, | ||
321 | }, { | ||
322 | .base = (S5P_VA_GPIO + 0xC60), | ||
323 | .config = &gpio_cfg_eint, | ||
324 | .irq_base = IRQ_EINT(24), | ||
325 | .chip = { | ||
326 | .base = S5PC100_GPH3(0), | ||
327 | .ngpio = S5PC100_GPIO_H3_NR, | ||
328 | .label = "GPH3", | ||
329 | .to_irq = samsung_gpiolib_to_irq, | ||
330 | }, | ||
380 | }, | 331 | }, |
381 | }; | 332 | }; |
382 | 333 | ||
383 | /* FIXME move from irq-gpio.c */ | 334 | static __init int s5pc100_gpiolib_init(void) |
384 | extern struct irq_chip s5pc100_gpioint; | ||
385 | extern void s5pc100_irq_gpioint_handler(unsigned int irq, struct irq_desc *desc); | ||
386 | |||
387 | static __init void s5pc100_gpiolib_link(struct s3c_gpio_chip *chip) | ||
388 | { | 335 | { |
389 | /* Interrupt */ | 336 | struct s3c_gpio_chip *chip = s5pc100_gpio_chips; |
390 | if (chip->config == &gpio_cfg) { | 337 | int nr_chips = ARRAY_SIZE(s5pc100_gpio_chips); |
391 | int i, irq; | 338 | int gpioint_group = 0; |
392 | 339 | int i; | |
393 | chip->chip.to_irq = s5pc100_gpiolib_to_irq; | ||
394 | 340 | ||
395 | for (i = 0; i < chip->chip.ngpio; i++) { | 341 | for (i = 0; i < nr_chips; i++, chip++) { |
396 | irq = S3C_IRQ_GPIO_BASE + chip->chip.base + i; | 342 | if (chip->config == NULL) { |
397 | set_irq_chip(irq, &s5pc100_gpioint); | 343 | chip->config = &gpio_cfg; |
398 | set_irq_data(irq, &chip->chip); | 344 | chip->group = gpioint_group++; |
399 | set_irq_handler(irq, handle_level_irq); | ||
400 | set_irq_flags(irq, IRQF_VALID); | ||
401 | } | 345 | } |
402 | } else if (chip->config == &gpio_cfg_eint) { | 346 | if (chip->base == NULL) |
403 | chip->chip.to_irq = s5pc100_gpiolib_to_eint; | 347 | chip->base = S5PC100_BANK_BASE(i); |
404 | } | 348 | } |
405 | } | ||
406 | |||
407 | static __init int s5pc100_gpiolib_init(void) | ||
408 | { | ||
409 | struct s3c_gpio_chip *chip; | ||
410 | int nr_chips; | ||
411 | |||
412 | chip = s5pc100_gpio_chips; | ||
413 | nr_chips = ARRAY_SIZE(s5pc100_gpio_chips); | ||
414 | |||
415 | for (; nr_chips > 0; nr_chips--, chip++) | ||
416 | s5pc100_gpiolib_link(chip); | ||
417 | |||
418 | samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips, | ||
419 | ARRAY_SIZE(s5pc100_gpio_chips)); | ||
420 | 349 | ||
421 | /* Interrupt */ | 350 | samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips, nr_chips); |
422 | set_irq_chained_handler(IRQ_GPIOINT, s5pc100_irq_gpioint_handler); | ||
423 | 351 | ||
424 | return 0; | 352 | return 0; |
425 | } | 353 | } |
diff --git a/arch/arm/mach-s5pc100/include/mach/gpio.h b/arch/arm/mach-s5pc100/include/mach/gpio.h index 71ae1f52df1d..29a8a12d9b4f 100644 --- a/arch/arm/mach-s5pc100/include/mach/gpio.h +++ b/arch/arm/mach-s5pc100/include/mach/gpio.h | |||
@@ -146,13 +146,6 @@ enum s5p_gpio_number { | |||
146 | /* define the number of gpios we need to the one after the MP04() range */ | 146 | /* define the number of gpios we need to the one after the MP04() range */ |
147 | #define ARCH_NR_GPIOS (S5PC100_GPIO_END + 1) | 147 | #define ARCH_NR_GPIOS (S5PC100_GPIO_END + 1) |
148 | 148 | ||
149 | #define EINT_MODE S3C_GPIO_SFN(0x2) | ||
150 | |||
151 | #define EINT_GPIO_0(x) S5PC100_GPH0(x) | ||
152 | #define EINT_GPIO_1(x) S5PC100_GPH1(x) | ||
153 | #define EINT_GPIO_2(x) S5PC100_GPH2(x) | ||
154 | #define EINT_GPIO_3(x) S5PC100_GPH3(x) | ||
155 | |||
156 | #include <asm-generic/gpio.h> | 149 | #include <asm-generic/gpio.h> |
157 | 150 | ||
158 | #endif /* __ASM_ARCH_GPIO_H */ | 151 | #endif /* __ASM_ARCH_GPIO_H */ |
diff --git a/arch/arm/mach-s5pc100/include/mach/irqs.h b/arch/arm/mach-s5pc100/include/mach/irqs.h index 06513e647242..d2eb4757381f 100644 --- a/arch/arm/mach-s5pc100/include/mach/irqs.h +++ b/arch/arm/mach-s5pc100/include/mach/irqs.h | |||
@@ -48,8 +48,8 @@ | |||
48 | #define IRQ_SPI1 S5P_IRQ_VIC1(16) | 48 | #define IRQ_SPI1 S5P_IRQ_VIC1(16) |
49 | #define IRQ_SPI2 S5P_IRQ_VIC1(17) | 49 | #define IRQ_SPI2 S5P_IRQ_VIC1(17) |
50 | #define IRQ_IRDA S5P_IRQ_VIC1(18) | 50 | #define IRQ_IRDA S5P_IRQ_VIC1(18) |
51 | #define IRQ_CAN0 S5P_IRQ_VIC1(19) | 51 | #define IRQ_IIC2 S5P_IRQ_VIC1(19) |
52 | #define IRQ_CAN1 S5P_IRQ_VIC1(20) | 52 | #define IRQ_IIC3 S5P_IRQ_VIC1(20) |
53 | #define IRQ_HSIRX S5P_IRQ_VIC1(21) | 53 | #define IRQ_HSIRX S5P_IRQ_VIC1(21) |
54 | #define IRQ_HSITX S5P_IRQ_VIC1(22) | 54 | #define IRQ_HSITX S5P_IRQ_VIC1(22) |
55 | #define IRQ_UHOST S5P_IRQ_VIC1(23) | 55 | #define IRQ_UHOST S5P_IRQ_VIC1(23) |
@@ -100,11 +100,12 @@ | |||
100 | #define S5P_EINT_BASE1 (S5P_IRQ_VIC0(0)) | 100 | #define S5P_EINT_BASE1 (S5P_IRQ_VIC0(0)) |
101 | #define S5P_EINT_BASE2 (IRQ_VIC_END + 1) | 101 | #define S5P_EINT_BASE2 (IRQ_VIC_END + 1) |
102 | 102 | ||
103 | #define S3C_IRQ_GPIO_BASE (IRQ_EINT(31) + 1) | 103 | /* GPIO interrupt */ |
104 | #define S3C_IRQ_GPIO(x) (S3C_IRQ_GPIO_BASE + (x)) | 104 | #define S5P_GPIOINT_BASE (IRQ_EINT(31) + 1) |
105 | #define S5P_GPIOINT_GROUP_MAXNR 21 | ||
105 | 106 | ||
106 | /* Until MP04 Groups -> 40 (exactly 39) Groups * 8 ~= 320 GPIOs */ | 107 | /* Set the default NR_IRQS */ |
107 | #define NR_IRQS (S3C_IRQ_GPIO(320) + 1) | 108 | #define NR_IRQS (IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1) |
108 | 109 | ||
109 | /* Compatibility */ | 110 | /* Compatibility */ |
110 | #define IRQ_LCD_FIFO IRQ_LCD0 | 111 | #define IRQ_LCD_FIFO IRQ_LCD0 |
diff --git a/arch/arm/mach-s5pc100/include/mach/map.h b/arch/arm/mach-s5pc100/include/mach/map.h index 8751ef4a6804..32e9cab5c864 100644 --- a/arch/arm/mach-s5pc100/include/mach/map.h +++ b/arch/arm/mach-s5pc100/include/mach/map.h | |||
@@ -110,6 +110,8 @@ | |||
110 | #define S5PC100_PA_PCM0 0xF2400000 | 110 | #define S5PC100_PA_PCM0 0xF2400000 |
111 | #define S5PC100_PA_PCM1 0xF2500000 | 111 | #define S5PC100_PA_PCM1 0xF2500000 |
112 | 112 | ||
113 | #define S5PC100_PA_SPDIF 0xF2600000 | ||
114 | |||
113 | #define S5PC100_PA_TSADC (0xF3000000) | 115 | #define S5PC100_PA_TSADC (0xF3000000) |
114 | 116 | ||
115 | /* KEYPAD */ | 117 | /* KEYPAD */ |
diff --git a/arch/arm/mach-s5pc100/include/mach/regs-gpio.h b/arch/arm/mach-s5pc100/include/mach/regs-gpio.h index dd6295e1251d..0bf73209ec7b 100644 --- a/arch/arm/mach-s5pc100/include/mach/regs-gpio.h +++ b/arch/arm/mach-s5pc100/include/mach/regs-gpio.h | |||
@@ -11,43 +11,6 @@ | |||
11 | 11 | ||
12 | #include <mach/map.h> | 12 | #include <mach/map.h> |
13 | 13 | ||
14 | /* S5PC100 */ | ||
15 | #define S5PC100_GPIO_BASE S5P_VA_GPIO | ||
16 | #define S5PC100_GPA0_BASE (S5PC100_GPIO_BASE + 0x0000) | ||
17 | #define S5PC100_GPA1_BASE (S5PC100_GPIO_BASE + 0x0020) | ||
18 | #define S5PC100_GPB_BASE (S5PC100_GPIO_BASE + 0x0040) | ||
19 | #define S5PC100_GPC_BASE (S5PC100_GPIO_BASE + 0x0060) | ||
20 | #define S5PC100_GPD_BASE (S5PC100_GPIO_BASE + 0x0080) | ||
21 | #define S5PC100_GPE0_BASE (S5PC100_GPIO_BASE + 0x00A0) | ||
22 | #define S5PC100_GPE1_BASE (S5PC100_GPIO_BASE + 0x00C0) | ||
23 | #define S5PC100_GPF0_BASE (S5PC100_GPIO_BASE + 0x00E0) | ||
24 | #define S5PC100_GPF1_BASE (S5PC100_GPIO_BASE + 0x0100) | ||
25 | #define S5PC100_GPF2_BASE (S5PC100_GPIO_BASE + 0x0120) | ||
26 | #define S5PC100_GPF3_BASE (S5PC100_GPIO_BASE + 0x0140) | ||
27 | #define S5PC100_GPG0_BASE (S5PC100_GPIO_BASE + 0x0160) | ||
28 | #define S5PC100_GPG1_BASE (S5PC100_GPIO_BASE + 0x0180) | ||
29 | #define S5PC100_GPG2_BASE (S5PC100_GPIO_BASE + 0x01A0) | ||
30 | #define S5PC100_GPG3_BASE (S5PC100_GPIO_BASE + 0x01C0) | ||
31 | #define S5PC100_GPH0_BASE (S5PC100_GPIO_BASE + 0x0C00) | ||
32 | #define S5PC100_GPH1_BASE (S5PC100_GPIO_BASE + 0x0C20) | ||
33 | #define S5PC100_GPH2_BASE (S5PC100_GPIO_BASE + 0x0C40) | ||
34 | #define S5PC100_GPH3_BASE (S5PC100_GPIO_BASE + 0x0C60) | ||
35 | #define S5PC100_GPI_BASE (S5PC100_GPIO_BASE + 0x01E0) | ||
36 | #define S5PC100_GPJ0_BASE (S5PC100_GPIO_BASE + 0x0200) | ||
37 | #define S5PC100_GPJ1_BASE (S5PC100_GPIO_BASE + 0x0220) | ||
38 | #define S5PC100_GPJ2_BASE (S5PC100_GPIO_BASE + 0x0240) | ||
39 | #define S5PC100_GPJ3_BASE (S5PC100_GPIO_BASE + 0x0260) | ||
40 | #define S5PC100_GPJ4_BASE (S5PC100_GPIO_BASE + 0x0280) | ||
41 | #define S5PC100_GPK0_BASE (S5PC100_GPIO_BASE + 0x02A0) | ||
42 | #define S5PC100_GPK1_BASE (S5PC100_GPIO_BASE + 0x02C0) | ||
43 | #define S5PC100_GPK2_BASE (S5PC100_GPIO_BASE + 0x02E0) | ||
44 | #define S5PC100_GPK3_BASE (S5PC100_GPIO_BASE + 0x0300) | ||
45 | #define S5PC100_GPL0_BASE (S5PC100_GPIO_BASE + 0x0320) | ||
46 | #define S5PC100_GPL1_BASE (S5PC100_GPIO_BASE + 0x0340) | ||
47 | #define S5PC100_GPL2_BASE (S5PC100_GPIO_BASE + 0x0360) | ||
48 | #define S5PC100_GPL3_BASE (S5PC100_GPIO_BASE + 0x0380) | ||
49 | #define S5PC100_GPL4_BASE (S5PC100_GPIO_BASE + 0x03A0) | ||
50 | |||
51 | #define S5PC100EINT30CON (S5P_VA_GPIO + 0xE00) | 14 | #define S5PC100EINT30CON (S5P_VA_GPIO + 0xE00) |
52 | #define S5P_EINT_CON(x) (S5PC100EINT30CON + ((x) * 0x4)) | 15 | #define S5P_EINT_CON(x) (S5PC100EINT30CON + ((x) * 0x4)) |
53 | 16 | ||
@@ -64,12 +27,12 @@ | |||
64 | 27 | ||
65 | #define eint_irq_to_bit(irq) (1 << (EINT_OFFSET(irq) & 0x7)) | 28 | #define eint_irq_to_bit(irq) (1 << (EINT_OFFSET(irq) & 0x7)) |
66 | 29 | ||
67 | /* values for S5P_EXTINT0 */ | 30 | #define EINT_MODE S3C_GPIO_SFN(0x2) |
68 | #define S5P_EXTINT_LOWLEV (0x00) | 31 | |
69 | #define S5P_EXTINT_HILEV (0x01) | 32 | #define EINT_GPIO_0(x) S5PC100_GPH0(x) |
70 | #define S5P_EXTINT_FALLEDGE (0x02) | 33 | #define EINT_GPIO_1(x) S5PC100_GPH1(x) |
71 | #define S5P_EXTINT_RISEEDGE (0x03) | 34 | #define EINT_GPIO_2(x) S5PC100_GPH2(x) |
72 | #define S5P_EXTINT_BOTHEDGE (0x04) | 35 | #define EINT_GPIO_3(x) S5PC100_GPH3(x) |
73 | 36 | ||
74 | #endif /* __ASM_MACH_S5PC100_REGS_GPIO_H */ | 37 | #endif /* __ASM_MACH_S5PC100_REGS_GPIO_H */ |
75 | 38 | ||
diff --git a/arch/arm/mach-s5pc100/include/mach/vmalloc.h b/arch/arm/mach-s5pc100/include/mach/vmalloc.h index be9df79903ed..44c8e5726d9d 100644 --- a/arch/arm/mach-s5pc100/include/mach/vmalloc.h +++ b/arch/arm/mach-s5pc100/include/mach/vmalloc.h | |||
@@ -12,6 +12,6 @@ | |||
12 | #ifndef __ASM_ARCH_VMALLOC_H | 12 | #ifndef __ASM_ARCH_VMALLOC_H |
13 | #define __ASM_ARCH_VMALLOC_H | 13 | #define __ASM_ARCH_VMALLOC_H |
14 | 14 | ||
15 | #define VMALLOC_END (0xe0000000UL) | 15 | #define VMALLOC_END 0xF6000000UL |
16 | 16 | ||
17 | #endif /* __ASM_ARCH_VMALLOC_H */ | 17 | #endif /* __ASM_ARCH_VMALLOC_H */ |
diff --git a/arch/arm/mach-s5pc100/irq-gpio.c b/arch/arm/mach-s5pc100/irq-gpio.c deleted file mode 100644 index 2bf86c18bc73..000000000000 --- a/arch/arm/mach-s5pc100/irq-gpio.c +++ /dev/null | |||
@@ -1,266 +0,0 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-s5pc100/irq-gpio.c | ||
3 | * | ||
4 | * Copyright (C) 2009 Samsung Electronics | ||
5 | * | ||
6 | * S5PC100 - Interrupt handling for IRQ_GPIO${group}(x) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/irq.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/gpio.h> | ||
18 | |||
19 | #include <mach/map.h> | ||
20 | #include <plat/gpio-cfg.h> | ||
21 | |||
22 | #define S5P_GPIOREG(x) (S5P_VA_GPIO + (x)) | ||
23 | |||
24 | #define CON_OFFSET 0x700 | ||
25 | #define MASK_OFFSET 0x900 | ||
26 | #define PEND_OFFSET 0xA00 | ||
27 | #define CON_OFFSET_2 0xE00 | ||
28 | #define MASK_OFFSET_2 0xF00 | ||
29 | #define PEND_OFFSET_2 0xF40 | ||
30 | |||
31 | #define GPIOINT_LEVEL_LOW 0x0 | ||
32 | #define GPIOINT_LEVEL_HIGH 0x1 | ||
33 | #define GPIOINT_EDGE_FALLING 0x2 | ||
34 | #define GPIOINT_EDGE_RISING 0x3 | ||
35 | #define GPIOINT_EDGE_BOTH 0x4 | ||
36 | |||
37 | static int group_to_con_offset(int group) | ||
38 | { | ||
39 | return group << 2; | ||
40 | } | ||
41 | |||
42 | static int group_to_mask_offset(int group) | ||
43 | { | ||
44 | return group << 2; | ||
45 | } | ||
46 | |||
47 | static int group_to_pend_offset(int group) | ||
48 | { | ||
49 | return group << 2; | ||
50 | } | ||
51 | |||
52 | static int s5pc100_get_start(unsigned int group) | ||
53 | { | ||
54 | switch (group) { | ||
55 | case 0: return S5PC100_GPIO_A0_START; | ||
56 | case 1: return S5PC100_GPIO_A1_START; | ||
57 | case 2: return S5PC100_GPIO_B_START; | ||
58 | case 3: return S5PC100_GPIO_C_START; | ||
59 | case 4: return S5PC100_GPIO_D_START; | ||
60 | case 5: return S5PC100_GPIO_E0_START; | ||
61 | case 6: return S5PC100_GPIO_E1_START; | ||
62 | case 7: return S5PC100_GPIO_F0_START; | ||
63 | case 8: return S5PC100_GPIO_F1_START; | ||
64 | case 9: return S5PC100_GPIO_F2_START; | ||
65 | case 10: return S5PC100_GPIO_F3_START; | ||
66 | case 11: return S5PC100_GPIO_G0_START; | ||
67 | case 12: return S5PC100_GPIO_G1_START; | ||
68 | case 13: return S5PC100_GPIO_G2_START; | ||
69 | case 14: return S5PC100_GPIO_G3_START; | ||
70 | case 15: return S5PC100_GPIO_I_START; | ||
71 | case 16: return S5PC100_GPIO_J0_START; | ||
72 | case 17: return S5PC100_GPIO_J1_START; | ||
73 | case 18: return S5PC100_GPIO_J2_START; | ||
74 | case 19: return S5PC100_GPIO_J3_START; | ||
75 | case 20: return S5PC100_GPIO_J4_START; | ||
76 | default: | ||
77 | BUG(); | ||
78 | } | ||
79 | |||
80 | return -EINVAL; | ||
81 | } | ||
82 | |||
83 | static int s5pc100_get_group(unsigned int irq) | ||
84 | { | ||
85 | irq -= S3C_IRQ_GPIO(0); | ||
86 | |||
87 | switch (irq) { | ||
88 | case S5PC100_GPIO_A0_START ... S5PC100_GPIO_A1_START - 1: | ||
89 | return 0; | ||
90 | case S5PC100_GPIO_A1_START ... S5PC100_GPIO_B_START - 1: | ||
91 | return 1; | ||
92 | case S5PC100_GPIO_B_START ... S5PC100_GPIO_C_START - 1: | ||
93 | return 2; | ||
94 | case S5PC100_GPIO_C_START ... S5PC100_GPIO_D_START - 1: | ||
95 | return 3; | ||
96 | case S5PC100_GPIO_D_START ... S5PC100_GPIO_E0_START - 1: | ||
97 | return 4; | ||
98 | case S5PC100_GPIO_E0_START ... S5PC100_GPIO_E1_START - 1: | ||
99 | return 5; | ||
100 | case S5PC100_GPIO_E1_START ... S5PC100_GPIO_F0_START - 1: | ||
101 | return 6; | ||
102 | case S5PC100_GPIO_F0_START ... S5PC100_GPIO_F1_START - 1: | ||
103 | return 7; | ||
104 | case S5PC100_GPIO_F1_START ... S5PC100_GPIO_F2_START - 1: | ||
105 | return 8; | ||
106 | case S5PC100_GPIO_F2_START ... S5PC100_GPIO_F3_START - 1: | ||
107 | return 9; | ||
108 | case S5PC100_GPIO_F3_START ... S5PC100_GPIO_G0_START - 1: | ||
109 | return 10; | ||
110 | case S5PC100_GPIO_G0_START ... S5PC100_GPIO_G1_START - 1: | ||
111 | return 11; | ||
112 | case S5PC100_GPIO_G1_START ... S5PC100_GPIO_G2_START - 1: | ||
113 | return 12; | ||
114 | case S5PC100_GPIO_G2_START ... S5PC100_GPIO_G3_START - 1: | ||
115 | return 13; | ||
116 | case S5PC100_GPIO_G3_START ... S5PC100_GPIO_H0_START - 1: | ||
117 | return 14; | ||
118 | case S5PC100_GPIO_I_START ... S5PC100_GPIO_J0_START - 1: | ||
119 | return 15; | ||
120 | case S5PC100_GPIO_J0_START ... S5PC100_GPIO_J1_START - 1: | ||
121 | return 16; | ||
122 | case S5PC100_GPIO_J1_START ... S5PC100_GPIO_J2_START - 1: | ||
123 | return 17; | ||
124 | case S5PC100_GPIO_J2_START ... S5PC100_GPIO_J3_START - 1: | ||
125 | return 18; | ||
126 | case S5PC100_GPIO_J3_START ... S5PC100_GPIO_J4_START - 1: | ||
127 | return 19; | ||
128 | case S5PC100_GPIO_J4_START ... S5PC100_GPIO_K0_START - 1: | ||
129 | return 20; | ||
130 | default: | ||
131 | BUG(); | ||
132 | } | ||
133 | |||
134 | return -EINVAL; | ||
135 | } | ||
136 | |||
137 | static int s5pc100_get_offset(unsigned int irq) | ||
138 | { | ||
139 | struct gpio_chip *chip = get_irq_data(irq); | ||
140 | return irq - S3C_IRQ_GPIO(chip->base); | ||
141 | } | ||
142 | |||
143 | static void s5pc100_gpioint_ack(unsigned int irq) | ||
144 | { | ||
145 | int group, offset, pend_offset; | ||
146 | unsigned int value; | ||
147 | |||
148 | group = s5pc100_get_group(irq); | ||
149 | offset = s5pc100_get_offset(irq); | ||
150 | pend_offset = group_to_pend_offset(group); | ||
151 | |||
152 | value = __raw_readl(S5P_GPIOREG(PEND_OFFSET) + pend_offset); | ||
153 | value |= 1 << offset; | ||
154 | __raw_writel(value, S5P_GPIOREG(PEND_OFFSET) + pend_offset); | ||
155 | } | ||
156 | |||
157 | static void s5pc100_gpioint_mask(unsigned int irq) | ||
158 | { | ||
159 | int group, offset, mask_offset; | ||
160 | unsigned int value; | ||
161 | |||
162 | group = s5pc100_get_group(irq); | ||
163 | offset = s5pc100_get_offset(irq); | ||
164 | mask_offset = group_to_mask_offset(group); | ||
165 | |||
166 | value = __raw_readl(S5P_GPIOREG(MASK_OFFSET) + mask_offset); | ||
167 | value |= 1 << offset; | ||
168 | __raw_writel(value, S5P_GPIOREG(MASK_OFFSET) + mask_offset); | ||
169 | } | ||
170 | |||
171 | static void s5pc100_gpioint_unmask(unsigned int irq) | ||
172 | { | ||
173 | int group, offset, mask_offset; | ||
174 | unsigned int value; | ||
175 | |||
176 | group = s5pc100_get_group(irq); | ||
177 | offset = s5pc100_get_offset(irq); | ||
178 | mask_offset = group_to_mask_offset(group); | ||
179 | |||
180 | value = __raw_readl(S5P_GPIOREG(MASK_OFFSET) + mask_offset); | ||
181 | value &= ~(1 << offset); | ||
182 | __raw_writel(value, S5P_GPIOREG(MASK_OFFSET) + mask_offset); | ||
183 | } | ||
184 | |||
185 | static void s5pc100_gpioint_mask_ack(unsigned int irq) | ||
186 | { | ||
187 | s5pc100_gpioint_mask(irq); | ||
188 | s5pc100_gpioint_ack(irq); | ||
189 | } | ||
190 | |||
191 | static int s5pc100_gpioint_set_type(unsigned int irq, unsigned int type) | ||
192 | { | ||
193 | int group, offset, con_offset; | ||
194 | unsigned int value; | ||
195 | |||
196 | group = s5pc100_get_group(irq); | ||
197 | offset = s5pc100_get_offset(irq); | ||
198 | con_offset = group_to_con_offset(group); | ||
199 | |||
200 | switch (type) { | ||
201 | case IRQ_TYPE_NONE: | ||
202 | printk(KERN_WARNING "No irq type\n"); | ||
203 | return -EINVAL; | ||
204 | case IRQ_TYPE_EDGE_RISING: | ||
205 | type = GPIOINT_EDGE_RISING; | ||
206 | break; | ||
207 | case IRQ_TYPE_EDGE_FALLING: | ||
208 | type = GPIOINT_EDGE_FALLING; | ||
209 | break; | ||
210 | case IRQ_TYPE_EDGE_BOTH: | ||
211 | type = GPIOINT_EDGE_BOTH; | ||
212 | break; | ||
213 | case IRQ_TYPE_LEVEL_HIGH: | ||
214 | type = GPIOINT_LEVEL_HIGH; | ||
215 | break; | ||
216 | case IRQ_TYPE_LEVEL_LOW: | ||
217 | type = GPIOINT_LEVEL_LOW; | ||
218 | break; | ||
219 | default: | ||
220 | BUG(); | ||
221 | } | ||
222 | |||
223 | |||
224 | value = __raw_readl(S5P_GPIOREG(CON_OFFSET) + con_offset); | ||
225 | value &= ~(0xf << (offset * 0x4)); | ||
226 | value |= (type << (offset * 0x4)); | ||
227 | __raw_writel(value, S5P_GPIOREG(CON_OFFSET) + con_offset); | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | struct irq_chip s5pc100_gpioint = { | ||
233 | .name = "GPIO", | ||
234 | .ack = s5pc100_gpioint_ack, | ||
235 | .mask = s5pc100_gpioint_mask, | ||
236 | .mask_ack = s5pc100_gpioint_mask_ack, | ||
237 | .unmask = s5pc100_gpioint_unmask, | ||
238 | .set_type = s5pc100_gpioint_set_type, | ||
239 | }; | ||
240 | |||
241 | void s5pc100_irq_gpioint_handler(unsigned int irq, struct irq_desc *desc) | ||
242 | { | ||
243 | int group, offset, pend_offset, mask_offset; | ||
244 | int real_irq, group_end; | ||
245 | unsigned int pend, mask; | ||
246 | |||
247 | group_end = 21; | ||
248 | |||
249 | for (group = 0; group < group_end; group++) { | ||
250 | pend_offset = group_to_pend_offset(group); | ||
251 | pend = __raw_readl(S5P_GPIOREG(PEND_OFFSET) + pend_offset); | ||
252 | if (!pend) | ||
253 | continue; | ||
254 | |||
255 | mask_offset = group_to_mask_offset(group); | ||
256 | mask = __raw_readl(S5P_GPIOREG(MASK_OFFSET) + mask_offset); | ||
257 | pend &= ~mask; | ||
258 | |||
259 | for (offset = 0; offset < 8; offset++) { | ||
260 | if (pend & (1 << offset)) { | ||
261 | real_irq = s5pc100_get_start(group) + offset; | ||
262 | generic_handle_irq(S3C_IRQ_GPIO(real_irq)); | ||
263 | } | ||
264 | } | ||
265 | } | ||
266 | } | ||
diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c index 880fb075092c..18b405d514d6 100644 --- a/arch/arm/mach-s5pc100/mach-smdkc100.c +++ b/arch/arm/mach-s5pc100/mach-smdkc100.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <plat/adc.h> | 47 | #include <plat/adc.h> |
48 | #include <plat/keypad.h> | 48 | #include <plat/keypad.h> |
49 | #include <plat/ts.h> | 49 | #include <plat/ts.h> |
50 | #include <plat/audio.h> | ||
50 | 51 | ||
51 | /* Following are default values for UCON, ULCON and UFCON UART registers */ | 52 | /* Following are default values for UCON, ULCON and UFCON UART registers */ |
52 | #define SMDKC100_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ | 53 | #define SMDKC100_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ |
@@ -196,6 +197,7 @@ static struct platform_device *smdkc100_devices[] __initdata = { | |||
196 | &s5p_device_fimc0, | 197 | &s5p_device_fimc0, |
197 | &s5p_device_fimc1, | 198 | &s5p_device_fimc1, |
198 | &s5p_device_fimc2, | 199 | &s5p_device_fimc2, |
200 | &s5pc100_device_spdif, | ||
199 | }; | 201 | }; |
200 | 202 | ||
201 | static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = { | 203 | static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = { |
@@ -226,6 +228,8 @@ static void __init smdkc100_machine_init(void) | |||
226 | 228 | ||
227 | samsung_keypad_set_platdata(&smdkc100_keypad_data); | 229 | samsung_keypad_set_platdata(&smdkc100_keypad_data); |
228 | 230 | ||
231 | s5pc100_spdif_setup_gpio(S5PC100_SPDIF_GPD); | ||
232 | |||
229 | /* LCD init */ | 233 | /* LCD init */ |
230 | gpio_request(S5PC100_GPD(0), "GPD"); | 234 | gpio_request(S5PC100_GPD(0), "GPD"); |
231 | gpio_request(S5PC100_GPH0(6), "GPH0"); | 235 | gpio_request(S5PC100_GPH0(6), "GPH0"); |
diff --git a/arch/arm/mach-s5pc100/setup-fb-24bpp.c b/arch/arm/mach-s5pc100/setup-fb-24bpp.c index 6eba6cb8e2f4..d31c0f3fe222 100644 --- a/arch/arm/mach-s5pc100/setup-fb-24bpp.c +++ b/arch/arm/mach-s5pc100/setup-fb-24bpp.c | |||
@@ -22,27 +22,15 @@ | |||
22 | 22 | ||
23 | #define DISR_OFFSET 0x7008 | 23 | #define DISR_OFFSET 0x7008 |
24 | 24 | ||
25 | void s5pc100_fb_gpio_setup_24bpp(void) | 25 | static void s5pc100_fb_setgpios(unsigned int base, unsigned int nr) |
26 | { | 26 | { |
27 | unsigned int gpio = 0; | 27 | s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(2)); |
28 | 28 | } | |
29 | for (gpio = S5PC100_GPF0(0); gpio <= S5PC100_GPF0(7); gpio++) { | ||
30 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
31 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
32 | } | ||
33 | |||
34 | for (gpio = S5PC100_GPF1(0); gpio <= S5PC100_GPF1(7); gpio++) { | ||
35 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
36 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
37 | } | ||
38 | |||
39 | for (gpio = S5PC100_GPF2(0); gpio <= S5PC100_GPF2(7); gpio++) { | ||
40 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
41 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
42 | } | ||
43 | 29 | ||
44 | for (gpio = S5PC100_GPF3(0); gpio <= S5PC100_GPF3(3); gpio++) { | 30 | void s5pc100_fb_gpio_setup_24bpp(void) |
45 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | 31 | { |
46 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | 32 | s5pc100_fb_setgpios(S5PC100_GPF0(0), 8); |
47 | } | 33 | s5pc100_fb_setgpios(S5PC100_GPF1(0), 8); |
34 | s5pc100_fb_setgpios(S5PC100_GPF2(0), 8); | ||
35 | s5pc100_fb_setgpios(S5PC100_GPF3(0), 4); | ||
48 | } | 36 | } |
diff --git a/arch/arm/mach-s5pc100/setup-i2c0.c b/arch/arm/mach-s5pc100/setup-i2c0.c index dd3174e6ecc5..eaef7a3bda49 100644 --- a/arch/arm/mach-s5pc100/setup-i2c0.c +++ b/arch/arm/mach-s5pc100/setup-i2c0.c | |||
@@ -23,8 +23,6 @@ struct platform_device; /* don't need the contents */ | |||
23 | 23 | ||
24 | void s3c_i2c0_cfg_gpio(struct platform_device *dev) | 24 | void s3c_i2c0_cfg_gpio(struct platform_device *dev) |
25 | { | 25 | { |
26 | s3c_gpio_cfgpin(S5PC100_GPD(3), S3C_GPIO_SFN(2)); | 26 | s3c_gpio_cfgall_range(S5PC100_GPD(3), 2, |
27 | s3c_gpio_setpull(S5PC100_GPD(3), S3C_GPIO_PULL_UP); | 27 | S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); |
28 | s3c_gpio_cfgpin(S5PC100_GPD(4), S3C_GPIO_SFN(2)); | ||
29 | s3c_gpio_setpull(S5PC100_GPD(4), S3C_GPIO_PULL_UP); | ||
30 | } | 28 | } |
diff --git a/arch/arm/mach-s5pc100/setup-i2c1.c b/arch/arm/mach-s5pc100/setup-i2c1.c index d1fec26b69ee..aaff74a90dee 100644 --- a/arch/arm/mach-s5pc100/setup-i2c1.c +++ b/arch/arm/mach-s5pc100/setup-i2c1.c | |||
@@ -23,8 +23,6 @@ struct platform_device; /* don't need the contents */ | |||
23 | 23 | ||
24 | void s3c_i2c1_cfg_gpio(struct platform_device *dev) | 24 | void s3c_i2c1_cfg_gpio(struct platform_device *dev) |
25 | { | 25 | { |
26 | s3c_gpio_cfgpin(S5PC100_GPD(5), S3C_GPIO_SFN(2)); | 26 | s3c_gpio_cfgall_range(S5PC100_GPD(5), 2, |
27 | s3c_gpio_setpull(S5PC100_GPD(5), S3C_GPIO_PULL_UP); | 27 | S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); |
28 | s3c_gpio_cfgpin(S5PC100_GPD(6), S3C_GPIO_SFN(2)); | ||
29 | s3c_gpio_setpull(S5PC100_GPD(6), S3C_GPIO_PULL_UP); | ||
30 | } | 28 | } |
diff --git a/arch/arm/mach-s5pc100/setup-ide.c b/arch/arm/mach-s5pc100/setup-ide.c index 83575671fb59..223aae044466 100644 --- a/arch/arm/mach-s5pc100/setup-ide.c +++ b/arch/arm/mach-s5pc100/setup-ide.c | |||
@@ -17,52 +17,39 @@ | |||
17 | #include <mach/regs-clock.h> | 17 | #include <mach/regs-clock.h> |
18 | #include <plat/gpio-cfg.h> | 18 | #include <plat/gpio-cfg.h> |
19 | 19 | ||
20 | static void s5pc100_ide_cfg_gpios(unsigned int base, unsigned int nr) | ||
21 | { | ||
22 | s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(4)); | ||
23 | |||
24 | for (; nr > 0; nr--, base++) | ||
25 | s5p_gpio_set_drvstr(base, S5P_GPIO_DRVSTR_LV4); | ||
26 | } | ||
27 | |||
20 | void s5pc100_ide_setup_gpio(void) | 28 | void s5pc100_ide_setup_gpio(void) |
21 | { | 29 | { |
22 | u32 reg; | 30 | u32 reg; |
23 | u32 gpio = 0; | ||
24 | 31 | ||
25 | /* Independent CF interface, CF chip select configuration */ | 32 | /* Independent CF interface, CF chip select configuration */ |
26 | reg = readl(S5PC100_MEM_SYS_CFG) & (~0x3f); | 33 | reg = readl(S5PC100_MEM_SYS_CFG) & (~0x3f); |
27 | writel(reg | MEM_SYS_CFG_EBI_FIX_PRI_CFCON, S5PC100_MEM_SYS_CFG); | 34 | writel(reg | MEM_SYS_CFG_EBI_FIX_PRI_CFCON, S5PC100_MEM_SYS_CFG); |
28 | 35 | ||
29 | /* CF_Add[0 - 2], CF_IORDY, CF_INTRQ, CF_DMARQ, CF_DMARST, CF_DMACK */ | 36 | /* CF_Add[0 - 2], CF_IORDY, CF_INTRQ, CF_DMARQ, CF_DMARST, CF_DMACK */ |
30 | for (gpio = S5PC100_GPJ0(0); gpio <= S5PC100_GPJ0(7); gpio++) { | 37 | s5pc100_ide_cfg_gpios(S5PC100_GPJ0(0), 8); |
31 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4)); | ||
32 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
33 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
34 | } | ||
35 | 38 | ||
36 | /*CF_Data[0 - 7] */ | 39 | /*CF_Data[0 - 7] */ |
37 | for (gpio = S5PC100_GPJ2(0); gpio <= S5PC100_GPJ2(7); gpio++) { | 40 | s5pc100_ide_cfg_gpios(S5PC100_GPJ2(0), 8); |
38 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4)); | ||
39 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
40 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
41 | } | ||
42 | 41 | ||
43 | /* CF_Data[8 - 15] */ | 42 | /* CF_Data[8 - 15] */ |
44 | for (gpio = S5PC100_GPJ3(0); gpio <= S5PC100_GPJ3(7); gpio++) { | 43 | s5pc100_ide_cfg_gpios(S5PC100_GPJ3(0), 8); |
45 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4)); | ||
46 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
47 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
48 | } | ||
49 | 44 | ||
50 | /* CF_CS0, CF_CS1, CF_IORD, CF_IOWR */ | 45 | /* CF_CS0, CF_CS1, CF_IORD, CF_IOWR */ |
51 | for (gpio = S5PC100_GPJ4(0); gpio <= S5PC100_GPJ4(3); gpio++) { | 46 | s5pc100_ide_cfg_gpios(S5PC100_GPJ4(0), 4); |
52 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4)); | ||
53 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
54 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
55 | } | ||
56 | 47 | ||
57 | /* EBI_OE, EBI_WE */ | 48 | /* EBI_OE, EBI_WE */ |
58 | for (gpio = S5PC100_GPK0(6); gpio <= S5PC100_GPK0(7); gpio++) | 49 | s3c_gpio_cfgpin_range(S5PC100_GPK0(6), 2, S3C_GPIO_SFN(0)); |
59 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0)); | ||
60 | 50 | ||
61 | /* CF_OE, CF_WE */ | 51 | /* CF_OE, CF_WE */ |
62 | for (gpio = S5PC100_GPK1(6); gpio <= S5PC100_GPK1(7); gpio++) { | 52 | s3c_gpio_cfgrange_nopull(S5PC100_GPK1(6), 8, S3C_GPIO_SFN(2)); |
63 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
64 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
65 | } | ||
66 | 53 | ||
67 | /* CF_CD */ | 54 | /* CF_CD */ |
68 | s3c_gpio_cfgpin(S5PC100_GPK3(5), S3C_GPIO_SFN(2)); | 55 | s3c_gpio_cfgpin(S5PC100_GPK3(5), S3C_GPIO_SFN(2)); |
diff --git a/arch/arm/mach-s5pc100/setup-keypad.c b/arch/arm/mach-s5pc100/setup-keypad.c index d0837a72a58e..ada377f0c206 100644 --- a/arch/arm/mach-s5pc100/setup-keypad.c +++ b/arch/arm/mach-s5pc100/setup-keypad.c | |||
@@ -15,20 +15,9 @@ | |||
15 | 15 | ||
16 | void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols) | 16 | void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols) |
17 | { | 17 | { |
18 | unsigned int gpio; | ||
19 | unsigned int end; | ||
20 | |||
21 | /* Set all the necessary GPH3 pins to special-function 3: KP_ROW[x] */ | 18 | /* Set all the necessary GPH3 pins to special-function 3: KP_ROW[x] */ |
22 | end = S5PC100_GPH3(rows); | 19 | s3c_gpio_cfgrange_nopull(S5PC100_GPH3(0), rows, S3C_GPIO_SFN(3)); |
23 | for (gpio = S5PC100_GPH3(0); gpio < end; gpio++) { | ||
24 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); | ||
25 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
26 | } | ||
27 | 20 | ||
28 | /* Set all the necessary GPH2 pins to special-function 3: KP_COL[x] */ | 21 | /* Set all the necessary GPH2 pins to special-function 3: KP_COL[x] */ |
29 | end = S5PC100_GPH2(cols); | 22 | s3c_gpio_cfgrange_nopull(S5PC100_GPH2(0), cols, S3C_GPIO_SFN(3)); |
30 | for (gpio = S5PC100_GPH2(0); gpio < end; gpio++) { | ||
31 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); | ||
32 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
33 | } | ||
34 | } | 23 | } |
diff --git a/arch/arm/mach-s5pc100/setup-sdhci-gpio.c b/arch/arm/mach-s5pc100/setup-sdhci-gpio.c index dc7208c639ea..03c02d04c68c 100644 --- a/arch/arm/mach-s5pc100/setup-sdhci-gpio.c +++ b/arch/arm/mach-s5pc100/setup-sdhci-gpio.c | |||
@@ -25,8 +25,6 @@ | |||
25 | void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) | 25 | void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) |
26 | { | 26 | { |
27 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; | 27 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; |
28 | unsigned int gpio; | ||
29 | unsigned int end; | ||
30 | unsigned int num; | 28 | unsigned int num; |
31 | 29 | ||
32 | num = width; | 30 | num = width; |
@@ -34,20 +32,11 @@ void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) | |||
34 | if (width == 8) | 32 | if (width == 8) |
35 | num = width - 2; | 33 | num = width - 2; |
36 | 34 | ||
37 | end = S5PC100_GPG0(2 + num); | ||
38 | |||
39 | /* Set all the necessary GPG0/GPG1 pins to special-function 0 */ | 35 | /* Set all the necessary GPG0/GPG1 pins to special-function 0 */ |
40 | for (gpio = S5PC100_GPG0(0); gpio < end; gpio++) { | 36 | s3c_gpio_cfgrange_nopull(S5PC100_GPG0(0), 2 + num, S3C_GPIO_SFN(2)); |
41 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
42 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
43 | } | ||
44 | 37 | ||
45 | if (width == 8) { | 38 | if (width == 8) |
46 | for (gpio = S5PC100_GPG1(0); gpio <= S5PC100_GPG1(1); gpio++) { | 39 | s3c_gpio_cfgrange_nopull(S5PC100_GPG1(0), 2, S3C_GPIO_SFN(2)); |
47 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
48 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
49 | } | ||
50 | } | ||
51 | 40 | ||
52 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { | 41 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { |
53 | s3c_gpio_setpull(S5PC100_GPG1(2), S3C_GPIO_PULL_UP); | 42 | s3c_gpio_setpull(S5PC100_GPG1(2), S3C_GPIO_PULL_UP); |
@@ -58,16 +47,9 @@ void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) | |||
58 | void s5pc100_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) | 47 | void s5pc100_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) |
59 | { | 48 | { |
60 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; | 49 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; |
61 | unsigned int gpio; | ||
62 | unsigned int end; | ||
63 | |||
64 | end = S5PC100_GPG2(2 + width); | ||
65 | 50 | ||
66 | /* Set all the necessary GPG2 pins to special-function 2 */ | 51 | /* Set all the necessary GPG2 pins to special-function 2 */ |
67 | for (gpio = S5PC100_GPG2(0); gpio < end; gpio++) { | 52 | s3c_gpio_cfgrange_nopull(S5PC100_GPG2(0), 2 + width, S3C_GPIO_SFN(2)); |
68 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
69 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
70 | } | ||
71 | 53 | ||
72 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { | 54 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { |
73 | s3c_gpio_setpull(S5PC100_GPG2(6), S3C_GPIO_PULL_UP); | 55 | s3c_gpio_setpull(S5PC100_GPG2(6), S3C_GPIO_PULL_UP); |
@@ -78,16 +60,9 @@ void s5pc100_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) | |||
78 | void s5pc100_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) | 60 | void s5pc100_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) |
79 | { | 61 | { |
80 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; | 62 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; |
81 | unsigned int gpio; | ||
82 | unsigned int end; | ||
83 | |||
84 | end = S5PC100_GPG3(2 + width); | ||
85 | 63 | ||
86 | /* Set all the necessary GPG3 pins to special-function 2 */ | 64 | /* Set all the necessary GPG3 pins to special-function 2 */ |
87 | for (gpio = S5PC100_GPG3(0); gpio < end; gpio++) { | 65 | s3c_gpio_cfgrange_nopull(S5PC100_GPG3(0), 2 + width, S3C_GPIO_SFN(2)); |
88 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
89 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
90 | } | ||
91 | 66 | ||
92 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { | 67 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { |
93 | s3c_gpio_setpull(S5PC100_GPG3(6), S3C_GPIO_PULL_UP); | 68 | s3c_gpio_setpull(S5PC100_GPG3(6), S3C_GPIO_PULL_UP); |
diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig index 5315fec3db86..862f239a0fdb 100644 --- a/arch/arm/mach-s5pv210/Kconfig +++ b/arch/arm/mach-s5pv210/Kconfig | |||
@@ -11,9 +11,9 @@ if ARCH_S5PV210 | |||
11 | 11 | ||
12 | config CPU_S5PV210 | 12 | config CPU_S5PV210 |
13 | bool | 13 | bool |
14 | select PLAT_S5P | ||
15 | select S3C_PL330_DMA | 14 | select S3C_PL330_DMA |
16 | select S5P_EXT_INT | 15 | select S5P_EXT_INT |
16 | select S5PV210_PM if PM | ||
17 | help | 17 | help |
18 | Enable S5PV210 CPU support | 18 | Enable S5PV210 CPU support |
19 | 19 | ||
@@ -58,7 +58,6 @@ menu "S5PC110 Machines" | |||
58 | config MACH_AQUILA | 58 | config MACH_AQUILA |
59 | bool "Aquila" | 59 | bool "Aquila" |
60 | select CPU_S5PV210 | 60 | select CPU_S5PV210 |
61 | select ARCH_SPARSEMEM_ENABLE | ||
62 | select S3C_DEV_FB | 61 | select S3C_DEV_FB |
63 | select S5P_DEV_FIMC0 | 62 | select S5P_DEV_FIMC0 |
64 | select S5P_DEV_FIMC1 | 63 | select S5P_DEV_FIMC1 |
@@ -75,7 +74,7 @@ config MACH_AQUILA | |||
75 | config MACH_GONI | 74 | config MACH_GONI |
76 | bool "GONI" | 75 | bool "GONI" |
77 | select CPU_S5PV210 | 76 | select CPU_S5PV210 |
78 | select ARCH_SPARSEMEM_ENABLE | 77 | select S5P_GPIO_INT |
79 | select S3C_DEV_FB | 78 | select S3C_DEV_FB |
80 | select S5P_DEV_FIMC0 | 79 | select S5P_DEV_FIMC0 |
81 | select S5P_DEV_FIMC1 | 80 | select S5P_DEV_FIMC1 |
@@ -83,8 +82,15 @@ config MACH_GONI | |||
83 | select S3C_DEV_HSMMC | 82 | select S3C_DEV_HSMMC |
84 | select S3C_DEV_HSMMC1 | 83 | select S3C_DEV_HSMMC1 |
85 | select S3C_DEV_HSMMC2 | 84 | select S3C_DEV_HSMMC2 |
85 | select S3C_DEV_I2C1 | ||
86 | select S3C_DEV_I2C2 | ||
87 | select S3C_DEV_USB_HSOTG | ||
86 | select S5P_DEV_ONENAND | 88 | select S5P_DEV_ONENAND |
89 | select SAMSUNG_DEV_KEYPAD | ||
87 | select S5PV210_SETUP_FB_24BPP | 90 | select S5PV210_SETUP_FB_24BPP |
91 | select S5PV210_SETUP_I2C1 | ||
92 | select S5PV210_SETUP_I2C2 | ||
93 | select S5PV210_SETUP_KEYPAD | ||
88 | select S5PV210_SETUP_SDHCI | 94 | select S5PV210_SETUP_SDHCI |
89 | help | 95 | help |
90 | Machine support for Samsung GONI board | 96 | Machine support for Samsung GONI board |
@@ -93,7 +99,6 @@ config MACH_GONI | |||
93 | config MACH_SMDKC110 | 99 | config MACH_SMDKC110 |
94 | bool "SMDKC110" | 100 | bool "SMDKC110" |
95 | select CPU_S5PV210 | 101 | select CPU_S5PV210 |
96 | select ARCH_SPARSEMEM_ENABLE | ||
97 | select S3C_DEV_I2C1 | 102 | select S3C_DEV_I2C1 |
98 | select S3C_DEV_I2C2 | 103 | select S3C_DEV_I2C2 |
99 | select S3C_DEV_RTC | 104 | select S3C_DEV_RTC |
@@ -113,7 +118,6 @@ menu "S5PV210 Machines" | |||
113 | config MACH_SMDKV210 | 118 | config MACH_SMDKV210 |
114 | bool "SMDKV210" | 119 | bool "SMDKV210" |
115 | select CPU_S5PV210 | 120 | select CPU_S5PV210 |
116 | select ARCH_SPARSEMEM_ENABLE | ||
117 | select S3C_DEV_HSMMC | 121 | select S3C_DEV_HSMMC |
118 | select S3C_DEV_HSMMC1 | 122 | select S3C_DEV_HSMMC1 |
119 | select S3C_DEV_HSMMC2 | 123 | select S3C_DEV_HSMMC2 |
@@ -134,6 +138,29 @@ config MACH_SMDKV210 | |||
134 | help | 138 | help |
135 | Machine support for Samsung SMDKV210 | 139 | Machine support for Samsung SMDKV210 |
136 | 140 | ||
141 | config MACH_TORBRECK | ||
142 | bool "Torbreck" | ||
143 | select CPU_S5PV210 | ||
144 | select ARCH_SPARSEMEM_ENABLE | ||
145 | select S3C_DEV_HSMMC | ||
146 | select S3C_DEV_HSMMC1 | ||
147 | select S3C_DEV_HSMMC2 | ||
148 | select S3C_DEV_HSMMC3 | ||
149 | select S3C_DEV_I2C1 | ||
150 | select S3C_DEV_I2C2 | ||
151 | select S3C_DEV_RTC | ||
152 | select S3C_DEV_WDT | ||
153 | select S5PV210_SETUP_I2C1 | ||
154 | select S5PV210_SETUP_I2C2 | ||
155 | select S5PV210_SETUP_SDHCI | ||
156 | help | ||
157 | Machine support for aESOP Torbreck | ||
158 | |||
137 | endmenu | 159 | endmenu |
138 | 160 | ||
161 | config S5PV210_PM | ||
162 | bool | ||
163 | help | ||
164 | Power Management code common to S5PV210 | ||
165 | |||
139 | endif | 166 | endif |
diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile index 704548912408..ff1a0db57a2f 100644 --- a/arch/arm/mach-s5pv210/Makefile +++ b/arch/arm/mach-s5pv210/Makefile | |||
@@ -14,6 +14,8 @@ obj- := | |||
14 | 14 | ||
15 | obj-$(CONFIG_CPU_S5PV210) += cpu.o init.o clock.o dma.o gpiolib.o | 15 | obj-$(CONFIG_CPU_S5PV210) += cpu.o init.o clock.o dma.o gpiolib.o |
16 | obj-$(CONFIG_CPU_S5PV210) += setup-i2c0.o | 16 | obj-$(CONFIG_CPU_S5PV210) += setup-i2c0.o |
17 | obj-$(CONFIG_S5PV210_PM) += pm.o sleep.o | ||
18 | obj-$(CONFIG_CPU_FREQ) += cpufreq.o | ||
17 | 19 | ||
18 | # machine support | 20 | # machine support |
19 | 21 | ||
@@ -21,6 +23,7 @@ obj-$(CONFIG_MACH_AQUILA) += mach-aquila.o | |||
21 | obj-$(CONFIG_MACH_SMDKV210) += mach-smdkv210.o | 23 | obj-$(CONFIG_MACH_SMDKV210) += mach-smdkv210.o |
22 | obj-$(CONFIG_MACH_SMDKC110) += mach-smdkc110.o | 24 | obj-$(CONFIG_MACH_SMDKC110) += mach-smdkc110.o |
23 | obj-$(CONFIG_MACH_GONI) += mach-goni.o | 25 | obj-$(CONFIG_MACH_GONI) += mach-goni.o |
26 | obj-$(CONFIG_MACH_TORBRECK) += mach-torbreck.o | ||
24 | 27 | ||
25 | # device support | 28 | # device support |
26 | 29 | ||
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index d562670e1b0b..019c3a69b0e4 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <plat/clock-clksrc.h> | 31 | #include <plat/clock-clksrc.h> |
32 | #include <plat/s5pv210.h> | 32 | #include <plat/s5pv210.h> |
33 | 33 | ||
34 | static unsigned long xtal; | ||
35 | |||
34 | static struct clksrc_clk clk_mout_apll = { | 36 | static struct clksrc_clk clk_mout_apll = { |
35 | .clk = { | 37 | .clk = { |
36 | .name = "mout_apll", | 38 | .name = "mout_apll", |
@@ -259,6 +261,36 @@ static struct clksrc_clk clk_sclk_vpll = { | |||
259 | .reg_src = { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 }, | 261 | .reg_src = { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 }, |
260 | }; | 262 | }; |
261 | 263 | ||
264 | static struct clk *clkset_moutdmc0src_list[] = { | ||
265 | [0] = &clk_sclk_a2m.clk, | ||
266 | [1] = &clk_mout_mpll.clk, | ||
267 | [2] = NULL, | ||
268 | [3] = NULL, | ||
269 | }; | ||
270 | |||
271 | static struct clksrc_sources clkset_moutdmc0src = { | ||
272 | .sources = clkset_moutdmc0src_list, | ||
273 | .nr_sources = ARRAY_SIZE(clkset_moutdmc0src_list), | ||
274 | }; | ||
275 | |||
276 | static struct clksrc_clk clk_mout_dmc0 = { | ||
277 | .clk = { | ||
278 | .name = "mout_dmc0", | ||
279 | .id = -1, | ||
280 | }, | ||
281 | .sources = &clkset_moutdmc0src, | ||
282 | .reg_src = { .reg = S5P_CLK_SRC6, .shift = 24, .size = 2 }, | ||
283 | }; | ||
284 | |||
285 | static struct clksrc_clk clk_sclk_dmc0 = { | ||
286 | .clk = { | ||
287 | .name = "sclk_dmc0", | ||
288 | .id = -1, | ||
289 | .parent = &clk_mout_dmc0.clk, | ||
290 | }, | ||
291 | .reg_div = { .reg = S5P_CLK_DIV6, .shift = 28, .size = 4 }, | ||
292 | }; | ||
293 | |||
262 | static unsigned long s5pv210_clk_imem_get_rate(struct clk *clk) | 294 | static unsigned long s5pv210_clk_imem_get_rate(struct clk *clk) |
263 | { | 295 | { |
264 | return clk_get_rate(clk->parent) / 2; | 296 | return clk_get_rate(clk->parent) / 2; |
@@ -268,8 +300,29 @@ static struct clk_ops clk_hclk_imem_ops = { | |||
268 | .get_rate = s5pv210_clk_imem_get_rate, | 300 | .get_rate = s5pv210_clk_imem_get_rate, |
269 | }; | 301 | }; |
270 | 302 | ||
303 | static unsigned long s5pv210_clk_fout_apll_get_rate(struct clk *clk) | ||
304 | { | ||
305 | return s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508); | ||
306 | } | ||
307 | |||
308 | static struct clk_ops clk_fout_apll_ops = { | ||
309 | .get_rate = s5pv210_clk_fout_apll_get_rate, | ||
310 | }; | ||
311 | |||
271 | static struct clk init_clocks_disable[] = { | 312 | static struct clk init_clocks_disable[] = { |
272 | { | 313 | { |
314 | .name = "pdma", | ||
315 | .id = 0, | ||
316 | .parent = &clk_hclk_psys.clk, | ||
317 | .enable = s5pv210_clk_ip0_ctrl, | ||
318 | .ctrlbit = (1 << 3), | ||
319 | }, { | ||
320 | .name = "pdma", | ||
321 | .id = 1, | ||
322 | .parent = &clk_hclk_psys.clk, | ||
323 | .enable = s5pv210_clk_ip0_ctrl, | ||
324 | .ctrlbit = (1 << 4), | ||
325 | }, { | ||
273 | .name = "rot", | 326 | .name = "rot", |
274 | .id = -1, | 327 | .id = -1, |
275 | .parent = &clk_hclk_dsys.clk, | 328 | .parent = &clk_hclk_dsys.clk, |
@@ -431,6 +484,12 @@ static struct clk init_clocks_disable[] = { | |||
431 | .parent = &clk_p, | 484 | .parent = &clk_p, |
432 | .enable = s5pv210_clk_ip3_ctrl, | 485 | .enable = s5pv210_clk_ip3_ctrl, |
433 | .ctrlbit = (1 << 6), | 486 | .ctrlbit = (1 << 6), |
487 | }, { | ||
488 | .name = "spdif", | ||
489 | .id = -1, | ||
490 | .parent = &clk_p, | ||
491 | .enable = s5pv210_clk_ip3_ctrl, | ||
492 | .ctrlbit = (1 << 0), | ||
434 | }, | 493 | }, |
435 | }; | 494 | }; |
436 | 495 | ||
@@ -660,6 +719,53 @@ static struct clksrc_sources clkset_sclk_spdif = { | |||
660 | .nr_sources = ARRAY_SIZE(clkset_sclk_spdif_list), | 719 | .nr_sources = ARRAY_SIZE(clkset_sclk_spdif_list), |
661 | }; | 720 | }; |
662 | 721 | ||
722 | static int s5pv210_spdif_set_rate(struct clk *clk, unsigned long rate) | ||
723 | { | ||
724 | struct clk *pclk; | ||
725 | int ret; | ||
726 | |||
727 | pclk = clk_get_parent(clk); | ||
728 | if (IS_ERR(pclk)) | ||
729 | return -EINVAL; | ||
730 | |||
731 | ret = pclk->ops->set_rate(pclk, rate); | ||
732 | clk_put(pclk); | ||
733 | |||
734 | return ret; | ||
735 | } | ||
736 | |||
737 | static unsigned long s5pv210_spdif_get_rate(struct clk *clk) | ||
738 | { | ||
739 | struct clk *pclk; | ||
740 | int rate; | ||
741 | |||
742 | pclk = clk_get_parent(clk); | ||
743 | if (IS_ERR(pclk)) | ||
744 | return -EINVAL; | ||
745 | |||
746 | rate = pclk->ops->get_rate(clk); | ||
747 | clk_put(pclk); | ||
748 | |||
749 | return rate; | ||
750 | } | ||
751 | |||
752 | static struct clk_ops s5pv210_sclk_spdif_ops = { | ||
753 | .set_rate = s5pv210_spdif_set_rate, | ||
754 | .get_rate = s5pv210_spdif_get_rate, | ||
755 | }; | ||
756 | |||
757 | static struct clksrc_clk clk_sclk_spdif = { | ||
758 | .clk = { | ||
759 | .name = "sclk_spdif", | ||
760 | .id = -1, | ||
761 | .enable = s5pv210_clk_mask0_ctrl, | ||
762 | .ctrlbit = (1 << 27), | ||
763 | .ops = &s5pv210_sclk_spdif_ops, | ||
764 | }, | ||
765 | .sources = &clkset_sclk_spdif, | ||
766 | .reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 }, | ||
767 | }; | ||
768 | |||
663 | static struct clk *clkset_group2_list[] = { | 769 | static struct clk *clkset_group2_list[] = { |
664 | [0] = &clk_ext_xtal_mux, | 770 | [0] = &clk_ext_xtal_mux, |
665 | [1] = &clk_xusbxti, | 771 | [1] = &clk_xusbxti, |
@@ -744,15 +850,6 @@ static struct clksrc_clk clksrcs[] = { | |||
744 | .sources = &clkset_sclk_mixer, | 850 | .sources = &clkset_sclk_mixer, |
745 | .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 }, | 851 | .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 }, |
746 | }, { | 852 | }, { |
747 | .clk = { | ||
748 | .name = "sclk_spdif", | ||
749 | .id = -1, | ||
750 | .enable = s5pv210_clk_mask0_ctrl, | ||
751 | .ctrlbit = (1 << 27), | ||
752 | }, | ||
753 | .sources = &clkset_sclk_spdif, | ||
754 | .reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 }, | ||
755 | }, { | ||
756 | .clk = { | 853 | .clk = { |
757 | .name = "sclk_fimc", | 854 | .name = "sclk_fimc", |
758 | .id = 0, | 855 | .id = 0, |
@@ -953,12 +1050,93 @@ static struct clksrc_clk *sysclks[] = { | |||
953 | &clk_sclk_dac, | 1050 | &clk_sclk_dac, |
954 | &clk_sclk_pixel, | 1051 | &clk_sclk_pixel, |
955 | &clk_sclk_hdmi, | 1052 | &clk_sclk_hdmi, |
1053 | &clk_mout_dmc0, | ||
1054 | &clk_sclk_dmc0, | ||
1055 | &clk_sclk_audio0, | ||
1056 | &clk_sclk_audio1, | ||
1057 | &clk_sclk_audio2, | ||
1058 | &clk_sclk_spdif, | ||
1059 | }; | ||
1060 | |||
1061 | static u32 epll_div[][6] = { | ||
1062 | { 48000000, 0, 48, 3, 3, 0 }, | ||
1063 | { 96000000, 0, 48, 3, 2, 0 }, | ||
1064 | { 144000000, 1, 72, 3, 2, 0 }, | ||
1065 | { 192000000, 0, 48, 3, 1, 0 }, | ||
1066 | { 288000000, 1, 72, 3, 1, 0 }, | ||
1067 | { 32750000, 1, 65, 3, 4, 35127 }, | ||
1068 | { 32768000, 1, 65, 3, 4, 35127 }, | ||
1069 | { 45158400, 0, 45, 3, 3, 10355 }, | ||
1070 | { 45000000, 0, 45, 3, 3, 10355 }, | ||
1071 | { 45158000, 0, 45, 3, 3, 10355 }, | ||
1072 | { 49125000, 0, 49, 3, 3, 9961 }, | ||
1073 | { 49152000, 0, 49, 3, 3, 9961 }, | ||
1074 | { 67737600, 1, 67, 3, 3, 48366 }, | ||
1075 | { 67738000, 1, 67, 3, 3, 48366 }, | ||
1076 | { 73800000, 1, 73, 3, 3, 47710 }, | ||
1077 | { 73728000, 1, 73, 3, 3, 47710 }, | ||
1078 | { 36000000, 1, 32, 3, 4, 0 }, | ||
1079 | { 60000000, 1, 60, 3, 3, 0 }, | ||
1080 | { 72000000, 1, 72, 3, 3, 0 }, | ||
1081 | { 80000000, 1, 80, 3, 3, 0 }, | ||
1082 | { 84000000, 0, 42, 3, 2, 0 }, | ||
1083 | { 50000000, 0, 50, 3, 3, 0 }, | ||
1084 | }; | ||
1085 | |||
1086 | static int s5pv210_epll_set_rate(struct clk *clk, unsigned long rate) | ||
1087 | { | ||
1088 | unsigned int epll_con, epll_con_k; | ||
1089 | unsigned int i; | ||
1090 | |||
1091 | /* Return if nothing changed */ | ||
1092 | if (clk->rate == rate) | ||
1093 | return 0; | ||
1094 | |||
1095 | epll_con = __raw_readl(S5P_EPLL_CON); | ||
1096 | epll_con_k = __raw_readl(S5P_EPLL_CON1); | ||
1097 | |||
1098 | epll_con_k &= ~PLL46XX_KDIV_MASK; | ||
1099 | epll_con &= ~(1 << 27 | | ||
1100 | PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT | | ||
1101 | PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT | | ||
1102 | PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT); | ||
1103 | |||
1104 | for (i = 0; i < ARRAY_SIZE(epll_div); i++) { | ||
1105 | if (epll_div[i][0] == rate) { | ||
1106 | epll_con_k |= epll_div[i][5] << 0; | ||
1107 | epll_con |= (epll_div[i][1] << 27 | | ||
1108 | epll_div[i][2] << PLL46XX_MDIV_SHIFT | | ||
1109 | epll_div[i][3] << PLL46XX_PDIV_SHIFT | | ||
1110 | epll_div[i][4] << PLL46XX_SDIV_SHIFT); | ||
1111 | break; | ||
1112 | } | ||
1113 | } | ||
1114 | |||
1115 | if (i == ARRAY_SIZE(epll_div)) { | ||
1116 | printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", | ||
1117 | __func__); | ||
1118 | return -EINVAL; | ||
1119 | } | ||
1120 | |||
1121 | __raw_writel(epll_con, S5P_EPLL_CON); | ||
1122 | __raw_writel(epll_con_k, S5P_EPLL_CON1); | ||
1123 | |||
1124 | printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n", | ||
1125 | clk->rate, rate); | ||
1126 | |||
1127 | clk->rate = rate; | ||
1128 | |||
1129 | return 0; | ||
1130 | } | ||
1131 | |||
1132 | static struct clk_ops s5pv210_epll_ops = { | ||
1133 | .set_rate = s5pv210_epll_set_rate, | ||
1134 | .get_rate = s5p_epll_get_rate, | ||
956 | }; | 1135 | }; |
957 | 1136 | ||
958 | void __init_or_cpufreq s5pv210_setup_clocks(void) | 1137 | void __init_or_cpufreq s5pv210_setup_clocks(void) |
959 | { | 1138 | { |
960 | struct clk *xtal_clk; | 1139 | struct clk *xtal_clk; |
961 | unsigned long xtal; | ||
962 | unsigned long vpllsrc; | 1140 | unsigned long vpllsrc; |
963 | unsigned long armclk; | 1141 | unsigned long armclk; |
964 | unsigned long hclk_msys; | 1142 | unsigned long hclk_msys; |
@@ -974,6 +1152,10 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) | |||
974 | unsigned int ptr; | 1152 | unsigned int ptr; |
975 | u32 clkdiv0, clkdiv1; | 1153 | u32 clkdiv0, clkdiv1; |
976 | 1154 | ||
1155 | /* Set functions for clk_fout_epll */ | ||
1156 | clk_fout_epll.enable = s5p_epll_enable; | ||
1157 | clk_fout_epll.ops = &s5pv210_epll_ops; | ||
1158 | |||
977 | printk(KERN_DEBUG "%s: registering clocks\n", __func__); | 1159 | printk(KERN_DEBUG "%s: registering clocks\n", __func__); |
978 | 1160 | ||
979 | clkdiv0 = __raw_readl(S5P_CLK_DIV0); | 1161 | clkdiv0 = __raw_readl(S5P_CLK_DIV0); |
@@ -992,11 +1174,12 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) | |||
992 | 1174 | ||
993 | apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508); | 1175 | apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508); |
994 | mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502); | 1176 | mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502); |
995 | epll = s5p_get_pll45xx(xtal, __raw_readl(S5P_EPLL_CON), pll_4500); | 1177 | epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON), |
1178 | __raw_readl(S5P_EPLL_CON1), pll_4600); | ||
996 | vpllsrc = clk_get_rate(&clk_vpllsrc.clk); | 1179 | vpllsrc = clk_get_rate(&clk_vpllsrc.clk); |
997 | vpll = s5p_get_pll45xx(vpllsrc, __raw_readl(S5P_VPLL_CON), pll_4502); | 1180 | vpll = s5p_get_pll45xx(vpllsrc, __raw_readl(S5P_VPLL_CON), pll_4502); |
998 | 1181 | ||
999 | clk_fout_apll.rate = apll; | 1182 | clk_fout_apll.ops = &clk_fout_apll_ops; |
1000 | clk_fout_mpll.rate = mpll; | 1183 | clk_fout_mpll.rate = mpll; |
1001 | clk_fout_epll.rate = epll; | 1184 | clk_fout_epll.rate = epll; |
1002 | clk_fout_vpll.rate = vpll; | 1185 | clk_fout_vpll.rate = vpll; |
diff --git a/arch/arm/mach-s5pv210/cpu.c b/arch/arm/mach-s5pv210/cpu.c index 2f16bfc0a116..8eb480e201b0 100644 --- a/arch/arm/mach-s5pv210/cpu.c +++ b/arch/arm/mach-s5pv210/cpu.c | |||
@@ -85,6 +85,21 @@ static struct map_desc s5pv210_iodesc[] __initdata = { | |||
85 | .pfn = __phys_to_pfn(S5PV210_PA_SROMC), | 85 | .pfn = __phys_to_pfn(S5PV210_PA_SROMC), |
86 | .length = SZ_4K, | 86 | .length = SZ_4K, |
87 | .type = MT_DEVICE, | 87 | .type = MT_DEVICE, |
88 | }, { | ||
89 | .virtual = (unsigned long)S5P_VA_DMC0, | ||
90 | .pfn = __phys_to_pfn(S5PV210_PA_DMC0), | ||
91 | .length = SZ_4K, | ||
92 | .type = MT_DEVICE, | ||
93 | }, { | ||
94 | .virtual = (unsigned long)S5P_VA_DMC1, | ||
95 | .pfn = __phys_to_pfn(S5PV210_PA_DMC1), | ||
96 | .length = SZ_4K, | ||
97 | .type = MT_DEVICE, | ||
98 | }, { | ||
99 | .virtual = (unsigned long)S3C_VA_USB_HSPHY, | ||
100 | .pfn =__phys_to_pfn(S5PV210_PA_HSPHY), | ||
101 | .length = SZ_4K, | ||
102 | .type = MT_DEVICE, | ||
88 | } | 103 | } |
89 | }; | 104 | }; |
90 | 105 | ||
diff --git a/arch/arm/mach-s5pv210/cpufreq.c b/arch/arm/mach-s5pv210/cpufreq.c new file mode 100644 index 000000000000..a6f22920a2c2 --- /dev/null +++ b/arch/arm/mach-s5pv210/cpufreq.c | |||
@@ -0,0 +1,484 @@ | |||
1 | /* linux/arch/arm/mach-s5pv210/cpufreq.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * CPU frequency scaling for S5PC110/S5PV210 | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/types.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/clk.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/cpufreq.h> | ||
20 | |||
21 | #include <mach/map.h> | ||
22 | #include <mach/regs-clock.h> | ||
23 | |||
24 | static struct clk *cpu_clk; | ||
25 | static struct clk *dmc0_clk; | ||
26 | static struct clk *dmc1_clk; | ||
27 | static struct cpufreq_freqs freqs; | ||
28 | |||
29 | /* APLL M,P,S values for 1G/800Mhz */ | ||
30 | #define APLL_VAL_1000 ((1 << 31) | (125 << 16) | (3 << 8) | 1) | ||
31 | #define APLL_VAL_800 ((1 << 31) | (100 << 16) | (3 << 8) | 1) | ||
32 | |||
33 | /* | ||
34 | * DRAM configurations to calculate refresh counter for changing | ||
35 | * frequency of memory. | ||
36 | */ | ||
37 | struct dram_conf { | ||
38 | unsigned long freq; /* HZ */ | ||
39 | unsigned long refresh; /* DRAM refresh counter * 1000 */ | ||
40 | }; | ||
41 | |||
42 | /* DRAM configuration (DMC0 and DMC1) */ | ||
43 | static struct dram_conf s5pv210_dram_conf[2]; | ||
44 | |||
45 | enum perf_level { | ||
46 | L0, L1, L2, L3, L4, | ||
47 | }; | ||
48 | |||
49 | enum s5pv210_mem_type { | ||
50 | LPDDR = 0x1, | ||
51 | LPDDR2 = 0x2, | ||
52 | DDR2 = 0x4, | ||
53 | }; | ||
54 | |||
55 | enum s5pv210_dmc_port { | ||
56 | DMC0 = 0, | ||
57 | DMC1, | ||
58 | }; | ||
59 | |||
60 | static struct cpufreq_frequency_table s5pv210_freq_table[] = { | ||
61 | {L0, 1000*1000}, | ||
62 | {L1, 800*1000}, | ||
63 | {L2, 400*1000}, | ||
64 | {L3, 200*1000}, | ||
65 | {L4, 100*1000}, | ||
66 | {0, CPUFREQ_TABLE_END}, | ||
67 | }; | ||
68 | |||
69 | static u32 clkdiv_val[5][11] = { | ||
70 | /* | ||
71 | * Clock divider value for following | ||
72 | * { APLL, A2M, HCLK_MSYS, PCLK_MSYS, | ||
73 | * HCLK_DSYS, PCLK_DSYS, HCLK_PSYS, PCLK_PSYS, | ||
74 | * ONEDRAM, MFC, G3D } | ||
75 | */ | ||
76 | |||
77 | /* L0 : [1000/200/100][166/83][133/66][200/200] */ | ||
78 | {0, 4, 4, 1, 3, 1, 4, 1, 3, 0, 0}, | ||
79 | |||
80 | /* L1 : [800/200/100][166/83][133/66][200/200] */ | ||
81 | {0, 3, 3, 1, 3, 1, 4, 1, 3, 0, 0}, | ||
82 | |||
83 | /* L2 : [400/200/100][166/83][133/66][200/200] */ | ||
84 | {1, 3, 1, 1, 3, 1, 4, 1, 3, 0, 0}, | ||
85 | |||
86 | /* L3 : [200/200/100][166/83][133/66][200/200] */ | ||
87 | {3, 3, 1, 1, 3, 1, 4, 1, 3, 0, 0}, | ||
88 | |||
89 | /* L4 : [100/100/100][83/83][66/66][100/100] */ | ||
90 | {7, 7, 0, 0, 7, 0, 9, 0, 7, 0, 0}, | ||
91 | }; | ||
92 | |||
93 | /* | ||
94 | * This function set DRAM refresh counter | ||
95 | * accoriding to operating frequency of DRAM | ||
96 | * ch: DMC port number 0 or 1 | ||
97 | * freq: Operating frequency of DRAM(KHz) | ||
98 | */ | ||
99 | static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq) | ||
100 | { | ||
101 | unsigned long tmp, tmp1; | ||
102 | void __iomem *reg = NULL; | ||
103 | |||
104 | if (ch == DMC0) | ||
105 | reg = (S5P_VA_DMC0 + 0x30); | ||
106 | else if (ch == DMC1) | ||
107 | reg = (S5P_VA_DMC1 + 0x30); | ||
108 | else | ||
109 | printk(KERN_ERR "Cannot find DMC port\n"); | ||
110 | |||
111 | /* Find current DRAM frequency */ | ||
112 | tmp = s5pv210_dram_conf[ch].freq; | ||
113 | |||
114 | do_div(tmp, freq); | ||
115 | |||
116 | tmp1 = s5pv210_dram_conf[ch].refresh; | ||
117 | |||
118 | do_div(tmp1, tmp); | ||
119 | |||
120 | __raw_writel(tmp1, reg); | ||
121 | } | ||
122 | |||
123 | int s5pv210_verify_speed(struct cpufreq_policy *policy) | ||
124 | { | ||
125 | if (policy->cpu) | ||
126 | return -EINVAL; | ||
127 | |||
128 | return cpufreq_frequency_table_verify(policy, s5pv210_freq_table); | ||
129 | } | ||
130 | |||
131 | unsigned int s5pv210_getspeed(unsigned int cpu) | ||
132 | { | ||
133 | if (cpu) | ||
134 | return 0; | ||
135 | |||
136 | return clk_get_rate(cpu_clk) / 1000; | ||
137 | } | ||
138 | |||
139 | static int s5pv210_target(struct cpufreq_policy *policy, | ||
140 | unsigned int target_freq, | ||
141 | unsigned int relation) | ||
142 | { | ||
143 | unsigned long reg; | ||
144 | unsigned int index, priv_index; | ||
145 | unsigned int pll_changing = 0; | ||
146 | unsigned int bus_speed_changing = 0; | ||
147 | |||
148 | freqs.old = s5pv210_getspeed(0); | ||
149 | |||
150 | if (cpufreq_frequency_table_target(policy, s5pv210_freq_table, | ||
151 | target_freq, relation, &index)) | ||
152 | return -EINVAL; | ||
153 | |||
154 | freqs.new = s5pv210_freq_table[index].frequency; | ||
155 | freqs.cpu = 0; | ||
156 | |||
157 | if (freqs.new == freqs.old) | ||
158 | return 0; | ||
159 | |||
160 | /* Finding current running level index */ | ||
161 | if (cpufreq_frequency_table_target(policy, s5pv210_freq_table, | ||
162 | freqs.old, relation, &priv_index)) | ||
163 | return -EINVAL; | ||
164 | |||
165 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
166 | |||
167 | if (freqs.new > freqs.old) { | ||
168 | /* Voltage up: will be implemented */ | ||
169 | } | ||
170 | |||
171 | /* Check if there need to change PLL */ | ||
172 | if ((index == L0) || (priv_index == L0)) | ||
173 | pll_changing = 1; | ||
174 | |||
175 | /* Check if there need to change System bus clock */ | ||
176 | if ((index == L4) || (priv_index == L4)) | ||
177 | bus_speed_changing = 1; | ||
178 | |||
179 | if (bus_speed_changing) { | ||
180 | /* | ||
181 | * Reconfigure DRAM refresh counter value for minimum | ||
182 | * temporary clock while changing divider. | ||
183 | * expected clock is 83Mhz : 7.8usec/(1/83Mhz) = 0x287 | ||
184 | */ | ||
185 | if (pll_changing) | ||
186 | s5pv210_set_refresh(DMC1, 83000); | ||
187 | else | ||
188 | s5pv210_set_refresh(DMC1, 100000); | ||
189 | |||
190 | s5pv210_set_refresh(DMC0, 83000); | ||
191 | } | ||
192 | |||
193 | /* | ||
194 | * APLL should be changed in this level | ||
195 | * APLL -> MPLL(for stable transition) -> APLL | ||
196 | * Some clock source's clock API are not prepared. | ||
197 | * Do not use clock API in below code. | ||
198 | */ | ||
199 | if (pll_changing) { | ||
200 | /* | ||
201 | * 1. Temporary Change divider for MFC and G3D | ||
202 | * SCLKA2M(200/1=200)->(200/4=50)Mhz | ||
203 | */ | ||
204 | reg = __raw_readl(S5P_CLK_DIV2); | ||
205 | reg &= ~(S5P_CLKDIV2_G3D_MASK | S5P_CLKDIV2_MFC_MASK); | ||
206 | reg |= (3 << S5P_CLKDIV2_G3D_SHIFT) | | ||
207 | (3 << S5P_CLKDIV2_MFC_SHIFT); | ||
208 | __raw_writel(reg, S5P_CLK_DIV2); | ||
209 | |||
210 | /* For MFC, G3D dividing */ | ||
211 | do { | ||
212 | reg = __raw_readl(S5P_CLKDIV_STAT0); | ||
213 | } while (reg & ((1 << 16) | (1 << 17))); | ||
214 | |||
215 | /* | ||
216 | * 2. Change SCLKA2M(200Mhz)to SCLKMPLL in MFC_MUX, G3D MUX | ||
217 | * (200/4=50)->(667/4=166)Mhz | ||
218 | */ | ||
219 | reg = __raw_readl(S5P_CLK_SRC2); | ||
220 | reg &= ~(S5P_CLKSRC2_G3D_MASK | S5P_CLKSRC2_MFC_MASK); | ||
221 | reg |= (1 << S5P_CLKSRC2_G3D_SHIFT) | | ||
222 | (1 << S5P_CLKSRC2_MFC_SHIFT); | ||
223 | __raw_writel(reg, S5P_CLK_SRC2); | ||
224 | |||
225 | do { | ||
226 | reg = __raw_readl(S5P_CLKMUX_STAT1); | ||
227 | } while (reg & ((1 << 7) | (1 << 3))); | ||
228 | |||
229 | /* | ||
230 | * 3. DMC1 refresh count for 133Mhz if (index == L4) is | ||
231 | * true refresh counter is already programed in upper | ||
232 | * code. 0x287@83Mhz | ||
233 | */ | ||
234 | if (!bus_speed_changing) | ||
235 | s5pv210_set_refresh(DMC1, 133000); | ||
236 | |||
237 | /* 4. SCLKAPLL -> SCLKMPLL */ | ||
238 | reg = __raw_readl(S5P_CLK_SRC0); | ||
239 | reg &= ~(S5P_CLKSRC0_MUX200_MASK); | ||
240 | reg |= (0x1 << S5P_CLKSRC0_MUX200_SHIFT); | ||
241 | __raw_writel(reg, S5P_CLK_SRC0); | ||
242 | |||
243 | do { | ||
244 | reg = __raw_readl(S5P_CLKMUX_STAT0); | ||
245 | } while (reg & (0x1 << 18)); | ||
246 | |||
247 | } | ||
248 | |||
249 | /* Change divider */ | ||
250 | reg = __raw_readl(S5P_CLK_DIV0); | ||
251 | |||
252 | reg &= ~(S5P_CLKDIV0_APLL_MASK | S5P_CLKDIV0_A2M_MASK | | ||
253 | S5P_CLKDIV0_HCLK200_MASK | S5P_CLKDIV0_PCLK100_MASK | | ||
254 | S5P_CLKDIV0_HCLK166_MASK | S5P_CLKDIV0_PCLK83_MASK | | ||
255 | S5P_CLKDIV0_HCLK133_MASK | S5P_CLKDIV0_PCLK66_MASK); | ||
256 | |||
257 | reg |= ((clkdiv_val[index][0] << S5P_CLKDIV0_APLL_SHIFT) | | ||
258 | (clkdiv_val[index][1] << S5P_CLKDIV0_A2M_SHIFT) | | ||
259 | (clkdiv_val[index][2] << S5P_CLKDIV0_HCLK200_SHIFT) | | ||
260 | (clkdiv_val[index][3] << S5P_CLKDIV0_PCLK100_SHIFT) | | ||
261 | (clkdiv_val[index][4] << S5P_CLKDIV0_HCLK166_SHIFT) | | ||
262 | (clkdiv_val[index][5] << S5P_CLKDIV0_PCLK83_SHIFT) | | ||
263 | (clkdiv_val[index][6] << S5P_CLKDIV0_HCLK133_SHIFT) | | ||
264 | (clkdiv_val[index][7] << S5P_CLKDIV0_PCLK66_SHIFT)); | ||
265 | |||
266 | __raw_writel(reg, S5P_CLK_DIV0); | ||
267 | |||
268 | do { | ||
269 | reg = __raw_readl(S5P_CLKDIV_STAT0); | ||
270 | } while (reg & 0xff); | ||
271 | |||
272 | /* ARM MCS value changed */ | ||
273 | reg = __raw_readl(S5P_ARM_MCS_CON); | ||
274 | reg &= ~0x3; | ||
275 | if (index >= L3) | ||
276 | reg |= 0x3; | ||
277 | else | ||
278 | reg |= 0x1; | ||
279 | |||
280 | __raw_writel(reg, S5P_ARM_MCS_CON); | ||
281 | |||
282 | if (pll_changing) { | ||
283 | /* 5. Set Lock time = 30us*24Mhz = 0x2cf */ | ||
284 | __raw_writel(0x2cf, S5P_APLL_LOCK); | ||
285 | |||
286 | /* | ||
287 | * 6. Turn on APLL | ||
288 | * 6-1. Set PMS values | ||
289 | * 6-2. Wait untile the PLL is locked | ||
290 | */ | ||
291 | if (index == L0) | ||
292 | __raw_writel(APLL_VAL_1000, S5P_APLL_CON); | ||
293 | else | ||
294 | __raw_writel(APLL_VAL_800, S5P_APLL_CON); | ||
295 | |||
296 | do { | ||
297 | reg = __raw_readl(S5P_APLL_CON); | ||
298 | } while (!(reg & (0x1 << 29))); | ||
299 | |||
300 | /* | ||
301 | * 7. Change souce clock from SCLKMPLL(667Mhz) | ||
302 | * to SCLKA2M(200Mhz) in MFC_MUX and G3D MUX | ||
303 | * (667/4=166)->(200/4=50)Mhz | ||
304 | */ | ||
305 | reg = __raw_readl(S5P_CLK_SRC2); | ||
306 | reg &= ~(S5P_CLKSRC2_G3D_MASK | S5P_CLKSRC2_MFC_MASK); | ||
307 | reg |= (0 << S5P_CLKSRC2_G3D_SHIFT) | | ||
308 | (0 << S5P_CLKSRC2_MFC_SHIFT); | ||
309 | __raw_writel(reg, S5P_CLK_SRC2); | ||
310 | |||
311 | do { | ||
312 | reg = __raw_readl(S5P_CLKMUX_STAT1); | ||
313 | } while (reg & ((1 << 7) | (1 << 3))); | ||
314 | |||
315 | /* | ||
316 | * 8. Change divider for MFC and G3D | ||
317 | * (200/4=50)->(200/1=200)Mhz | ||
318 | */ | ||
319 | reg = __raw_readl(S5P_CLK_DIV2); | ||
320 | reg &= ~(S5P_CLKDIV2_G3D_MASK | S5P_CLKDIV2_MFC_MASK); | ||
321 | reg |= (clkdiv_val[index][10] << S5P_CLKDIV2_G3D_SHIFT) | | ||
322 | (clkdiv_val[index][9] << S5P_CLKDIV2_MFC_SHIFT); | ||
323 | __raw_writel(reg, S5P_CLK_DIV2); | ||
324 | |||
325 | /* For MFC, G3D dividing */ | ||
326 | do { | ||
327 | reg = __raw_readl(S5P_CLKDIV_STAT0); | ||
328 | } while (reg & ((1 << 16) | (1 << 17))); | ||
329 | |||
330 | /* 9. Change MPLL to APLL in MSYS_MUX */ | ||
331 | reg = __raw_readl(S5P_CLK_SRC0); | ||
332 | reg &= ~(S5P_CLKSRC0_MUX200_MASK); | ||
333 | reg |= (0x0 << S5P_CLKSRC0_MUX200_SHIFT); | ||
334 | __raw_writel(reg, S5P_CLK_SRC0); | ||
335 | |||
336 | do { | ||
337 | reg = __raw_readl(S5P_CLKMUX_STAT0); | ||
338 | } while (reg & (0x1 << 18)); | ||
339 | |||
340 | /* | ||
341 | * 10. DMC1 refresh counter | ||
342 | * L4 : DMC1 = 100Mhz 7.8us/(1/100) = 0x30c | ||
343 | * Others : DMC1 = 200Mhz 7.8us/(1/200) = 0x618 | ||
344 | */ | ||
345 | if (!bus_speed_changing) | ||
346 | s5pv210_set_refresh(DMC1, 200000); | ||
347 | } | ||
348 | |||
349 | /* | ||
350 | * L4 level need to change memory bus speed, hence onedram clock divier | ||
351 | * and memory refresh parameter should be changed | ||
352 | */ | ||
353 | if (bus_speed_changing) { | ||
354 | reg = __raw_readl(S5P_CLK_DIV6); | ||
355 | reg &= ~S5P_CLKDIV6_ONEDRAM_MASK; | ||
356 | reg |= (clkdiv_val[index][8] << S5P_CLKDIV6_ONEDRAM_SHIFT); | ||
357 | __raw_writel(reg, S5P_CLK_DIV6); | ||
358 | |||
359 | do { | ||
360 | reg = __raw_readl(S5P_CLKDIV_STAT1); | ||
361 | } while (reg & (1 << 15)); | ||
362 | |||
363 | /* Reconfigure DRAM refresh counter value */ | ||
364 | if (index != L4) { | ||
365 | /* | ||
366 | * DMC0 : 166Mhz | ||
367 | * DMC1 : 200Mhz | ||
368 | */ | ||
369 | s5pv210_set_refresh(DMC0, 166000); | ||
370 | s5pv210_set_refresh(DMC1, 200000); | ||
371 | } else { | ||
372 | /* | ||
373 | * DMC0 : 83Mhz | ||
374 | * DMC1 : 100Mhz | ||
375 | */ | ||
376 | s5pv210_set_refresh(DMC0, 83000); | ||
377 | s5pv210_set_refresh(DMC1, 100000); | ||
378 | } | ||
379 | } | ||
380 | |||
381 | if (freqs.new < freqs.old) { | ||
382 | /* Voltage down: will be implemented */ | ||
383 | } | ||
384 | |||
385 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
386 | |||
387 | printk(KERN_DEBUG "Perf changed[L%d]\n", index); | ||
388 | |||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | #ifdef CONFIG_PM | ||
393 | static int s5pv210_cpufreq_suspend(struct cpufreq_policy *policy, | ||
394 | pm_message_t pmsg) | ||
395 | { | ||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | static int s5pv210_cpufreq_resume(struct cpufreq_policy *policy) | ||
400 | { | ||
401 | return 0; | ||
402 | } | ||
403 | #endif | ||
404 | |||
405 | static int check_mem_type(void __iomem *dmc_reg) | ||
406 | { | ||
407 | unsigned long val; | ||
408 | |||
409 | val = __raw_readl(dmc_reg + 0x4); | ||
410 | val = (val & (0xf << 8)); | ||
411 | |||
412 | return val >> 8; | ||
413 | } | ||
414 | |||
415 | static int __init s5pv210_cpu_init(struct cpufreq_policy *policy) | ||
416 | { | ||
417 | unsigned long mem_type; | ||
418 | |||
419 | cpu_clk = clk_get(NULL, "armclk"); | ||
420 | if (IS_ERR(cpu_clk)) | ||
421 | return PTR_ERR(cpu_clk); | ||
422 | |||
423 | dmc0_clk = clk_get(NULL, "sclk_dmc0"); | ||
424 | if (IS_ERR(dmc0_clk)) { | ||
425 | clk_put(cpu_clk); | ||
426 | return PTR_ERR(dmc0_clk); | ||
427 | } | ||
428 | |||
429 | dmc1_clk = clk_get(NULL, "hclk_msys"); | ||
430 | if (IS_ERR(dmc1_clk)) { | ||
431 | clk_put(dmc0_clk); | ||
432 | clk_put(cpu_clk); | ||
433 | return PTR_ERR(dmc1_clk); | ||
434 | } | ||
435 | |||
436 | if (policy->cpu != 0) | ||
437 | return -EINVAL; | ||
438 | |||
439 | /* | ||
440 | * check_mem_type : This driver only support LPDDR & LPDDR2. | ||
441 | * other memory type is not supported. | ||
442 | */ | ||
443 | mem_type = check_mem_type(S5P_VA_DMC0); | ||
444 | |||
445 | if ((mem_type != LPDDR) && (mem_type != LPDDR2)) { | ||
446 | printk(KERN_ERR "CPUFreq doesn't support this memory type\n"); | ||
447 | return -EINVAL; | ||
448 | } | ||
449 | |||
450 | /* Find current refresh counter and frequency each DMC */ | ||
451 | s5pv210_dram_conf[0].refresh = (__raw_readl(S5P_VA_DMC0 + 0x30) * 1000); | ||
452 | s5pv210_dram_conf[0].freq = clk_get_rate(dmc0_clk); | ||
453 | |||
454 | s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000); | ||
455 | s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk); | ||
456 | |||
457 | policy->cur = policy->min = policy->max = s5pv210_getspeed(0); | ||
458 | |||
459 | cpufreq_frequency_table_get_attr(s5pv210_freq_table, policy->cpu); | ||
460 | |||
461 | policy->cpuinfo.transition_latency = 40000; | ||
462 | |||
463 | return cpufreq_frequency_table_cpuinfo(policy, s5pv210_freq_table); | ||
464 | } | ||
465 | |||
466 | static struct cpufreq_driver s5pv210_driver = { | ||
467 | .flags = CPUFREQ_STICKY, | ||
468 | .verify = s5pv210_verify_speed, | ||
469 | .target = s5pv210_target, | ||
470 | .get = s5pv210_getspeed, | ||
471 | .init = s5pv210_cpu_init, | ||
472 | .name = "s5pv210", | ||
473 | #ifdef CONFIG_PM | ||
474 | .suspend = s5pv210_cpufreq_suspend, | ||
475 | .resume = s5pv210_cpufreq_resume, | ||
476 | #endif | ||
477 | }; | ||
478 | |||
479 | static int __init s5pv210_cpufreq_init(void) | ||
480 | { | ||
481 | return cpufreq_register_driver(&s5pv210_driver); | ||
482 | } | ||
483 | |||
484 | late_initcall(s5pv210_cpufreq_init); | ||
diff --git a/arch/arm/mach-s5pv210/dev-audio.c b/arch/arm/mach-s5pv210/dev-audio.c index 21dc6cf955c3..1303fcb12b51 100644 --- a/arch/arm/mach-s5pv210/dev-audio.c +++ b/arch/arm/mach-s5pv210/dev-audio.c | |||
@@ -24,29 +24,15 @@ static int s5pv210_cfg_i2s(struct platform_device *pdev) | |||
24 | /* configure GPIO for i2s port */ | 24 | /* configure GPIO for i2s port */ |
25 | switch (pdev->id) { | 25 | switch (pdev->id) { |
26 | case 1: | 26 | case 1: |
27 | s3c_gpio_cfgpin(S5PV210_GPC0(0), S3C_GPIO_SFN(2)); | 27 | s3c_gpio_cfgpin_range(S5PV210_GPC0(0), 5, S3C_GPIO_SFN(2)); |
28 | s3c_gpio_cfgpin(S5PV210_GPC0(1), S3C_GPIO_SFN(2)); | ||
29 | s3c_gpio_cfgpin(S5PV210_GPC0(2), S3C_GPIO_SFN(2)); | ||
30 | s3c_gpio_cfgpin(S5PV210_GPC0(3), S3C_GPIO_SFN(2)); | ||
31 | s3c_gpio_cfgpin(S5PV210_GPC0(4), S3C_GPIO_SFN(2)); | ||
32 | break; | 28 | break; |
33 | 29 | ||
34 | case 2: | 30 | case 2: |
35 | s3c_gpio_cfgpin(S5PV210_GPC1(0), S3C_GPIO_SFN(4)); | 31 | s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 5, S3C_GPIO_SFN(4)); |
36 | s3c_gpio_cfgpin(S5PV210_GPC1(1), S3C_GPIO_SFN(4)); | ||
37 | s3c_gpio_cfgpin(S5PV210_GPC1(2), S3C_GPIO_SFN(4)); | ||
38 | s3c_gpio_cfgpin(S5PV210_GPC1(3), S3C_GPIO_SFN(4)); | ||
39 | s3c_gpio_cfgpin(S5PV210_GPC1(4), S3C_GPIO_SFN(4)); | ||
40 | break; | 32 | break; |
41 | 33 | ||
42 | case -1: | 34 | case -1: |
43 | s3c_gpio_cfgpin(S5PV210_GPI(0), S3C_GPIO_SFN(2)); | 35 | s3c_gpio_cfgpin_range(S5PV210_GPI(0), 7, S3C_GPIO_SFN(2)); |
44 | s3c_gpio_cfgpin(S5PV210_GPI(1), S3C_GPIO_SFN(2)); | ||
45 | s3c_gpio_cfgpin(S5PV210_GPI(2), S3C_GPIO_SFN(2)); | ||
46 | s3c_gpio_cfgpin(S5PV210_GPI(3), S3C_GPIO_SFN(2)); | ||
47 | s3c_gpio_cfgpin(S5PV210_GPI(4), S3C_GPIO_SFN(2)); | ||
48 | s3c_gpio_cfgpin(S5PV210_GPI(5), S3C_GPIO_SFN(2)); | ||
49 | s3c_gpio_cfgpin(S5PV210_GPI(6), S3C_GPIO_SFN(2)); | ||
50 | break; | 36 | break; |
51 | 37 | ||
52 | default: | 38 | default: |
@@ -151,25 +137,13 @@ static int s5pv210_pcm_cfg_gpio(struct platform_device *pdev) | |||
151 | { | 137 | { |
152 | switch (pdev->id) { | 138 | switch (pdev->id) { |
153 | case 0: | 139 | case 0: |
154 | s3c_gpio_cfgpin(S5PV210_GPI(0), S3C_GPIO_SFN(3)); | 140 | s3c_gpio_cfgpin_range(S5PV210_GPI(0), 5, S3C_GPIO_SFN(3)); |
155 | s3c_gpio_cfgpin(S5PV210_GPI(1), S3C_GPIO_SFN(3)); | ||
156 | s3c_gpio_cfgpin(S5PV210_GPI(2), S3C_GPIO_SFN(3)); | ||
157 | s3c_gpio_cfgpin(S5PV210_GPI(3), S3C_GPIO_SFN(3)); | ||
158 | s3c_gpio_cfgpin(S5PV210_GPI(4), S3C_GPIO_SFN(3)); | ||
159 | break; | 141 | break; |
160 | case 1: | 142 | case 1: |
161 | s3c_gpio_cfgpin(S5PV210_GPC0(0), S3C_GPIO_SFN(3)); | 143 | s3c_gpio_cfgpin_range(S5PV210_GPC0(0), 5, S3C_GPIO_SFN(3)); |
162 | s3c_gpio_cfgpin(S5PV210_GPC0(1), S3C_GPIO_SFN(3)); | ||
163 | s3c_gpio_cfgpin(S5PV210_GPC0(2), S3C_GPIO_SFN(3)); | ||
164 | s3c_gpio_cfgpin(S5PV210_GPC0(3), S3C_GPIO_SFN(3)); | ||
165 | s3c_gpio_cfgpin(S5PV210_GPC0(4), S3C_GPIO_SFN(3)); | ||
166 | break; | 144 | break; |
167 | case 2: | 145 | case 2: |
168 | s3c_gpio_cfgpin(S5PV210_GPC1(0), S3C_GPIO_SFN(2)); | 146 | s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 5, S3C_GPIO_SFN(2)); |
169 | s3c_gpio_cfgpin(S5PV210_GPC1(1), S3C_GPIO_SFN(2)); | ||
170 | s3c_gpio_cfgpin(S5PV210_GPC1(2), S3C_GPIO_SFN(2)); | ||
171 | s3c_gpio_cfgpin(S5PV210_GPC1(3), S3C_GPIO_SFN(2)); | ||
172 | s3c_gpio_cfgpin(S5PV210_GPC1(4), S3C_GPIO_SFN(2)); | ||
173 | break; | 147 | break; |
174 | default: | 148 | default: |
175 | printk(KERN_DEBUG "Invalid PCM Controller number!"); | 149 | printk(KERN_DEBUG "Invalid PCM Controller number!"); |
@@ -271,13 +245,7 @@ struct platform_device s5pv210_device_pcm2 = { | |||
271 | 245 | ||
272 | static int s5pv210_ac97_cfg_gpio(struct platform_device *pdev) | 246 | static int s5pv210_ac97_cfg_gpio(struct platform_device *pdev) |
273 | { | 247 | { |
274 | s3c_gpio_cfgpin(S5PV210_GPC0(0), S3C_GPIO_SFN(4)); | 248 | return s3c_gpio_cfgpin_range(S5PV210_GPC0(0), 5, S3C_GPIO_SFN(4)); |
275 | s3c_gpio_cfgpin(S5PV210_GPC0(1), S3C_GPIO_SFN(4)); | ||
276 | s3c_gpio_cfgpin(S5PV210_GPC0(2), S3C_GPIO_SFN(4)); | ||
277 | s3c_gpio_cfgpin(S5PV210_GPC0(3), S3C_GPIO_SFN(4)); | ||
278 | s3c_gpio_cfgpin(S5PV210_GPC0(4), S3C_GPIO_SFN(4)); | ||
279 | |||
280 | return 0; | ||
281 | } | 249 | } |
282 | 250 | ||
283 | static struct resource s5pv210_ac97_resource[] = { | 251 | static struct resource s5pv210_ac97_resource[] = { |
@@ -325,3 +293,43 @@ struct platform_device s5pv210_device_ac97 = { | |||
325 | .coherent_dma_mask = DMA_BIT_MASK(32), | 293 | .coherent_dma_mask = DMA_BIT_MASK(32), |
326 | }, | 294 | }, |
327 | }; | 295 | }; |
296 | |||
297 | /* S/PDIF Controller platform_device */ | ||
298 | |||
299 | static int s5pv210_spdif_cfg_gpio(struct platform_device *pdev) | ||
300 | { | ||
301 | s3c_gpio_cfgpin_range(S5PV210_GPC1(0), 2, S3C_GPIO_SFN(3)); | ||
302 | |||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | static struct resource s5pv210_spdif_resource[] = { | ||
307 | [0] = { | ||
308 | .start = S5PV210_PA_SPDIF, | ||
309 | .end = S5PV210_PA_SPDIF + 0x100 - 1, | ||
310 | .flags = IORESOURCE_MEM, | ||
311 | }, | ||
312 | [1] = { | ||
313 | .start = DMACH_SPDIF, | ||
314 | .end = DMACH_SPDIF, | ||
315 | .flags = IORESOURCE_DMA, | ||
316 | }, | ||
317 | }; | ||
318 | |||
319 | static struct s3c_audio_pdata samsung_spdif_pdata = { | ||
320 | .cfg_gpio = s5pv210_spdif_cfg_gpio, | ||
321 | }; | ||
322 | |||
323 | static u64 s5pv210_spdif_dmamask = DMA_BIT_MASK(32); | ||
324 | |||
325 | struct platform_device s5pv210_device_spdif = { | ||
326 | .name = "samsung-spdif", | ||
327 | .id = -1, | ||
328 | .num_resources = ARRAY_SIZE(s5pv210_spdif_resource), | ||
329 | .resource = s5pv210_spdif_resource, | ||
330 | .dev = { | ||
331 | .platform_data = &samsung_spdif_pdata, | ||
332 | .dma_mask = &s5pv210_spdif_dmamask, | ||
333 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
334 | }, | ||
335 | }; | ||
diff --git a/arch/arm/mach-s5pv210/dev-spi.c b/arch/arm/mach-s5pv210/dev-spi.c index 826cdbc43e20..e3249a47e3b1 100644 --- a/arch/arm/mach-s5pv210/dev-spi.c +++ b/arch/arm/mach-s5pv210/dev-spi.c | |||
@@ -35,23 +35,15 @@ static char *spi_src_clks[] = { | |||
35 | */ | 35 | */ |
36 | static int s5pv210_spi_cfg_gpio(struct platform_device *pdev) | 36 | static int s5pv210_spi_cfg_gpio(struct platform_device *pdev) |
37 | { | 37 | { |
38 | unsigned int base; | ||
39 | |||
38 | switch (pdev->id) { | 40 | switch (pdev->id) { |
39 | case 0: | 41 | case 0: |
40 | s3c_gpio_cfgpin(S5PV210_GPB(0), S3C_GPIO_SFN(2)); | 42 | base = S5PV210_GPB(0); |
41 | s3c_gpio_cfgpin(S5PV210_GPB(1), S3C_GPIO_SFN(2)); | ||
42 | s3c_gpio_cfgpin(S5PV210_GPB(2), S3C_GPIO_SFN(2)); | ||
43 | s3c_gpio_setpull(S5PV210_GPB(0), S3C_GPIO_PULL_UP); | ||
44 | s3c_gpio_setpull(S5PV210_GPB(1), S3C_GPIO_PULL_UP); | ||
45 | s3c_gpio_setpull(S5PV210_GPB(2), S3C_GPIO_PULL_UP); | ||
46 | break; | 43 | break; |
47 | 44 | ||
48 | case 1: | 45 | case 1: |
49 | s3c_gpio_cfgpin(S5PV210_GPB(4), S3C_GPIO_SFN(2)); | 46 | base = S5PV210_GPB(4); |
50 | s3c_gpio_cfgpin(S5PV210_GPB(5), S3C_GPIO_SFN(2)); | ||
51 | s3c_gpio_cfgpin(S5PV210_GPB(6), S3C_GPIO_SFN(2)); | ||
52 | s3c_gpio_setpull(S5PV210_GPB(4), S3C_GPIO_PULL_UP); | ||
53 | s3c_gpio_setpull(S5PV210_GPB(5), S3C_GPIO_PULL_UP); | ||
54 | s3c_gpio_setpull(S5PV210_GPB(6), S3C_GPIO_PULL_UP); | ||
55 | break; | 47 | break; |
56 | 48 | ||
57 | default: | 49 | default: |
@@ -59,6 +51,9 @@ static int s5pv210_spi_cfg_gpio(struct platform_device *pdev) | |||
59 | return -EINVAL; | 51 | return -EINVAL; |
60 | } | 52 | } |
61 | 53 | ||
54 | s3c_gpio_cfgall_range(base, 3, | ||
55 | S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); | ||
56 | |||
62 | return 0; | 57 | return 0; |
63 | } | 58 | } |
64 | 59 | ||
diff --git a/arch/arm/mach-s5pv210/dma.c b/arch/arm/mach-s5pv210/dma.c index 778ad5fe231a..497d3439a142 100644 --- a/arch/arm/mach-s5pv210/dma.c +++ b/arch/arm/mach-s5pv210/dma.c | |||
@@ -82,7 +82,7 @@ static struct s3c_pl330_platdata s5pv210_pdma0_pdata = { | |||
82 | 82 | ||
83 | static struct platform_device s5pv210_device_pdma0 = { | 83 | static struct platform_device s5pv210_device_pdma0 = { |
84 | .name = "s3c-pl330", | 84 | .name = "s3c-pl330", |
85 | .id = 1, | 85 | .id = 0, |
86 | .num_resources = ARRAY_SIZE(s5pv210_pdma0_resource), | 86 | .num_resources = ARRAY_SIZE(s5pv210_pdma0_resource), |
87 | .resource = s5pv210_pdma0_resource, | 87 | .resource = s5pv210_pdma0_resource, |
88 | .dev = { | 88 | .dev = { |
@@ -144,7 +144,7 @@ static struct s3c_pl330_platdata s5pv210_pdma1_pdata = { | |||
144 | 144 | ||
145 | static struct platform_device s5pv210_device_pdma1 = { | 145 | static struct platform_device s5pv210_device_pdma1 = { |
146 | .name = "s3c-pl330", | 146 | .name = "s3c-pl330", |
147 | .id = 2, | 147 | .id = 1, |
148 | .num_resources = ARRAY_SIZE(s5pv210_pdma1_resource), | 148 | .num_resources = ARRAY_SIZE(s5pv210_pdma1_resource), |
149 | .resource = s5pv210_pdma1_resource, | 149 | .resource = s5pv210_pdma1_resource, |
150 | .dev = { | 150 | .dev = { |
diff --git a/arch/arm/mach-s5pv210/gpiolib.c b/arch/arm/mach-s5pv210/gpiolib.c index 0d459112d039..ab673effd767 100644 --- a/arch/arm/mach-s5pv210/gpiolib.c +++ b/arch/arm/mach-s5pv210/gpiolib.c | |||
@@ -150,6 +150,7 @@ static struct s3c_gpio_chip s5pv210_gpio_4bit[] = { | |||
150 | .label = "GPG3", | 150 | .label = "GPG3", |
151 | }, | 151 | }, |
152 | }, { | 152 | }, { |
153 | .config = &gpio_cfg_noint, | ||
153 | .chip = { | 154 | .chip = { |
154 | .base = S5PV210_GPI(0), | 155 | .base = S5PV210_GPI(0), |
155 | .ngpio = S5PV210_GPIO_I_NR, | 156 | .ngpio = S5PV210_GPIO_I_NR, |
@@ -223,34 +224,42 @@ static struct s3c_gpio_chip s5pv210_gpio_4bit[] = { | |||
223 | }, { | 224 | }, { |
224 | .base = (S5P_VA_GPIO + 0xC00), | 225 | .base = (S5P_VA_GPIO + 0xC00), |
225 | .config = &gpio_cfg_noint, | 226 | .config = &gpio_cfg_noint, |
227 | .irq_base = IRQ_EINT(0), | ||
226 | .chip = { | 228 | .chip = { |
227 | .base = S5PV210_GPH0(0), | 229 | .base = S5PV210_GPH0(0), |
228 | .ngpio = S5PV210_GPIO_H0_NR, | 230 | .ngpio = S5PV210_GPIO_H0_NR, |
229 | .label = "GPH0", | 231 | .label = "GPH0", |
232 | .to_irq = samsung_gpiolib_to_irq, | ||
230 | }, | 233 | }, |
231 | }, { | 234 | }, { |
232 | .base = (S5P_VA_GPIO + 0xC20), | 235 | .base = (S5P_VA_GPIO + 0xC20), |
233 | .config = &gpio_cfg_noint, | 236 | .config = &gpio_cfg_noint, |
237 | .irq_base = IRQ_EINT(8), | ||
234 | .chip = { | 238 | .chip = { |
235 | .base = S5PV210_GPH1(0), | 239 | .base = S5PV210_GPH1(0), |
236 | .ngpio = S5PV210_GPIO_H1_NR, | 240 | .ngpio = S5PV210_GPIO_H1_NR, |
237 | .label = "GPH1", | 241 | .label = "GPH1", |
242 | .to_irq = samsung_gpiolib_to_irq, | ||
238 | }, | 243 | }, |
239 | }, { | 244 | }, { |
240 | .base = (S5P_VA_GPIO + 0xC40), | 245 | .base = (S5P_VA_GPIO + 0xC40), |
241 | .config = &gpio_cfg_noint, | 246 | .config = &gpio_cfg_noint, |
247 | .irq_base = IRQ_EINT(16), | ||
242 | .chip = { | 248 | .chip = { |
243 | .base = S5PV210_GPH2(0), | 249 | .base = S5PV210_GPH2(0), |
244 | .ngpio = S5PV210_GPIO_H2_NR, | 250 | .ngpio = S5PV210_GPIO_H2_NR, |
245 | .label = "GPH2", | 251 | .label = "GPH2", |
252 | .to_irq = samsung_gpiolib_to_irq, | ||
246 | }, | 253 | }, |
247 | }, { | 254 | }, { |
248 | .base = (S5P_VA_GPIO + 0xC60), | 255 | .base = (S5P_VA_GPIO + 0xC60), |
249 | .config = &gpio_cfg_noint, | 256 | .config = &gpio_cfg_noint, |
257 | .irq_base = IRQ_EINT(24), | ||
250 | .chip = { | 258 | .chip = { |
251 | .base = S5PV210_GPH3(0), | 259 | .base = S5PV210_GPH3(0), |
252 | .ngpio = S5PV210_GPIO_H3_NR, | 260 | .ngpio = S5PV210_GPIO_H3_NR, |
253 | .label = "GPH3", | 261 | .label = "GPH3", |
262 | .to_irq = samsung_gpiolib_to_irq, | ||
254 | }, | 263 | }, |
255 | }, | 264 | }, |
256 | }; | 265 | }; |
@@ -259,11 +268,14 @@ static __init int s5pv210_gpiolib_init(void) | |||
259 | { | 268 | { |
260 | struct s3c_gpio_chip *chip = s5pv210_gpio_4bit; | 269 | struct s3c_gpio_chip *chip = s5pv210_gpio_4bit; |
261 | int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit); | 270 | int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit); |
271 | int gpioint_group = 0; | ||
262 | int i = 0; | 272 | int i = 0; |
263 | 273 | ||
264 | for (i = 0; i < nr_chips; i++, chip++) { | 274 | for (i = 0; i < nr_chips; i++, chip++) { |
265 | if (chip->config == NULL) | 275 | if (chip->config == NULL) { |
266 | chip->config = &gpio_cfg; | 276 | chip->config = &gpio_cfg; |
277 | chip->group = gpioint_group++; | ||
278 | } | ||
267 | if (chip->base == NULL) | 279 | if (chip->base == NULL) |
268 | chip->base = S5PV210_BANK_BASE(i); | 280 | chip->base = S5PV210_BANK_BASE(i); |
269 | } | 281 | } |
diff --git a/arch/arm/mach-s5pv210/include/mach/irqs.h b/arch/arm/mach-s5pv210/include/mach/irqs.h index e1c020e5a49b..119b95fdc3ce 100644 --- a/arch/arm/mach-s5pv210/include/mach/irqs.h +++ b/arch/arm/mach-s5pv210/include/mach/irqs.h | |||
@@ -55,8 +55,8 @@ | |||
55 | #define IRQ_SPI1 S5P_IRQ_VIC1(16) | 55 | #define IRQ_SPI1 S5P_IRQ_VIC1(16) |
56 | #define IRQ_SPI2 S5P_IRQ_VIC1(17) | 56 | #define IRQ_SPI2 S5P_IRQ_VIC1(17) |
57 | #define IRQ_IRDA S5P_IRQ_VIC1(18) | 57 | #define IRQ_IRDA S5P_IRQ_VIC1(18) |
58 | #define IRQ_CAN0 S5P_IRQ_VIC1(19) | 58 | #define IRQ_IIC2 S5P_IRQ_VIC1(19) |
59 | #define IRQ_CAN1 S5P_IRQ_VIC1(20) | 59 | #define IRQ_IIC3 S5P_IRQ_VIC1(20) |
60 | #define IRQ_HSIRX S5P_IRQ_VIC1(21) | 60 | #define IRQ_HSIRX S5P_IRQ_VIC1(21) |
61 | #define IRQ_HSITX S5P_IRQ_VIC1(22) | 61 | #define IRQ_HSITX S5P_IRQ_VIC1(22) |
62 | #define IRQ_UHOST S5P_IRQ_VIC1(23) | 62 | #define IRQ_UHOST S5P_IRQ_VIC1(23) |
@@ -109,7 +109,7 @@ | |||
109 | 109 | ||
110 | #define IRQ_IPC S5P_IRQ_VIC3(0) | 110 | #define IRQ_IPC S5P_IRQ_VIC3(0) |
111 | #define IRQ_HOSTIF S5P_IRQ_VIC3(1) | 111 | #define IRQ_HOSTIF S5P_IRQ_VIC3(1) |
112 | #define IRQ_MMC3 S5P_IRQ_VIC3(2) | 112 | #define IRQ_HSMMC3 S5P_IRQ_VIC3(2) |
113 | #define IRQ_CEC S5P_IRQ_VIC3(3) | 113 | #define IRQ_CEC S5P_IRQ_VIC3(3) |
114 | #define IRQ_TSI S5P_IRQ_VIC3(4) | 114 | #define IRQ_TSI S5P_IRQ_VIC3(4) |
115 | #define IRQ_MDNIE0 S5P_IRQ_VIC3(5) | 115 | #define IRQ_MDNIE0 S5P_IRQ_VIC3(5) |
@@ -121,8 +121,12 @@ | |||
121 | #define S5P_EINT_BASE1 (S5P_IRQ_VIC0(0)) | 121 | #define S5P_EINT_BASE1 (S5P_IRQ_VIC0(0)) |
122 | #define S5P_EINT_BASE2 (IRQ_VIC_END + 1) | 122 | #define S5P_EINT_BASE2 (IRQ_VIC_END + 1) |
123 | 123 | ||
124 | /* GPIO interrupt */ | ||
125 | #define S5P_GPIOINT_BASE (IRQ_EINT(31) + 1) | ||
126 | #define S5P_GPIOINT_GROUP_MAXNR 22 | ||
127 | |||
124 | /* Set the default NR_IRQS */ | 128 | /* Set the default NR_IRQS */ |
125 | #define NR_IRQS (IRQ_EINT(31) + 1) | 129 | #define NR_IRQS (IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1) |
126 | 130 | ||
127 | /* Compatibility */ | 131 | /* Compatibility */ |
128 | #define IRQ_LCD_FIFO IRQ_LCD0 | 132 | #define IRQ_LCD_FIFO IRQ_LCD0 |
diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h index bd9afd52466a..861d7fe11fc9 100644 --- a/arch/arm/mach-s5pv210/include/mach/map.h +++ b/arch/arm/mach-s5pv210/include/mach/map.h | |||
@@ -57,6 +57,8 @@ | |||
57 | 57 | ||
58 | #define S5P_SZ_UART SZ_256 | 58 | #define S5P_SZ_UART SZ_256 |
59 | 59 | ||
60 | #define S3C_VA_UARTx(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET)) | ||
61 | |||
60 | #define S5PV210_PA_SROMC (0xE8000000) | 62 | #define S5PV210_PA_SROMC (0xE8000000) |
61 | 63 | ||
62 | #define S5PV210_PA_CFCON (0xE8200000) | 64 | #define S5PV210_PA_CFCON (0xE8200000) |
@@ -73,6 +75,9 @@ | |||
73 | 75 | ||
74 | #define S5PV210_PA_HSMMC(x) (0xEB000000 + ((x) * 0x100000)) | 76 | #define S5PV210_PA_HSMMC(x) (0xEB000000 + ((x) * 0x100000)) |
75 | 77 | ||
78 | #define S5PV210_PA_HSOTG (0xEC000000) | ||
79 | #define S5PV210_PA_HSPHY (0xEC100000) | ||
80 | |||
76 | #define S5PV210_PA_VIC0 (0xF2000000) | 81 | #define S5PV210_PA_VIC0 (0xF2000000) |
77 | #define S5PV210_PA_VIC1 (0xF2100000) | 82 | #define S5PV210_PA_VIC1 (0xF2100000) |
78 | #define S5PV210_PA_VIC2 (0xF2200000) | 83 | #define S5PV210_PA_VIC2 (0xF2200000) |
@@ -81,6 +86,9 @@ | |||
81 | #define S5PV210_PA_SDRAM (0x20000000) | 86 | #define S5PV210_PA_SDRAM (0x20000000) |
82 | #define S5P_PA_SDRAM S5PV210_PA_SDRAM | 87 | #define S5P_PA_SDRAM S5PV210_PA_SDRAM |
83 | 88 | ||
89 | /* S/PDIF */ | ||
90 | #define S5PV210_PA_SPDIF 0xE1100000 | ||
91 | |||
84 | /* I2S */ | 92 | /* I2S */ |
85 | #define S5PV210_PA_IIS0 0xEEE30000 | 93 | #define S5PV210_PA_IIS0 0xEEE30000 |
86 | #define S5PV210_PA_IIS1 0xE2100000 | 94 | #define S5PV210_PA_IIS1 0xE2100000 |
@@ -96,6 +104,9 @@ | |||
96 | 104 | ||
97 | #define S5PV210_PA_ADC (0xE1700000) | 105 | #define S5PV210_PA_ADC (0xE1700000) |
98 | 106 | ||
107 | #define S5PV210_PA_DMC0 (0xF0000000) | ||
108 | #define S5PV210_PA_DMC1 (0xF1400000) | ||
109 | |||
99 | /* compatibiltiy defines. */ | 110 | /* compatibiltiy defines. */ |
100 | #define S3C_PA_UART S5PV210_PA_UART | 111 | #define S3C_PA_UART S5PV210_PA_UART |
101 | #define S3C_PA_HSMMC0 S5PV210_PA_HSMMC(0) | 112 | #define S3C_PA_HSMMC0 S5PV210_PA_HSMMC(0) |
@@ -108,6 +119,7 @@ | |||
108 | #define S3C_PA_FB S5PV210_PA_FB | 119 | #define S3C_PA_FB S5PV210_PA_FB |
109 | #define S3C_PA_RTC S5PV210_PA_RTC | 120 | #define S3C_PA_RTC S5PV210_PA_RTC |
110 | #define S3C_PA_WDT S5PV210_PA_WATCHDOG | 121 | #define S3C_PA_WDT S5PV210_PA_WATCHDOG |
122 | #define S3C_PA_USB_HSOTG S5PV210_PA_HSOTG | ||
111 | #define S5P_PA_FIMC0 S5PV210_PA_FIMC0 | 123 | #define S5P_PA_FIMC0 S5PV210_PA_FIMC0 |
112 | #define S5P_PA_FIMC1 S5PV210_PA_FIMC1 | 124 | #define S5P_PA_FIMC1 S5PV210_PA_FIMC1 |
113 | #define S5P_PA_FIMC2 S5PV210_PA_FIMC2 | 125 | #define S5P_PA_FIMC2 S5PV210_PA_FIMC2 |
diff --git a/arch/arm/mach-s5pv210/include/mach/pm-core.h b/arch/arm/mach-s5pv210/include/mach/pm-core.h new file mode 100644 index 000000000000..e8d394f8b057 --- /dev/null +++ b/arch/arm/mach-s5pv210/include/mach/pm-core.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* linux/arch/arm/mach-s5pv210/include/mach/pm-core.h | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * Based on arch/arm/mach-s3c2410/include/mach/pm-core.h, | ||
7 | * Copyright 2008 Simtec Electronics | ||
8 | * Ben Dooks <ben@simtec.co.uk> | ||
9 | * http://armlinux.simtec.co.uk/ | ||
10 | * | ||
11 | * S5PV210 - PM core support for arch/arm/plat-s5p/pm.c | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | */ | ||
17 | |||
18 | static inline void s3c_pm_debug_init_uart(void) | ||
19 | { | ||
20 | /* nothing here yet */ | ||
21 | } | ||
22 | |||
23 | static inline void s3c_pm_arch_prepare_irqs(void) | ||
24 | { | ||
25 | __raw_writel(s3c_irqwake_intmask, S5P_WAKEUP_MASK); | ||
26 | __raw_writel(s3c_irqwake_eintmask, S5P_EINT_WAKEUP_MASK); | ||
27 | } | ||
28 | |||
29 | static inline void s3c_pm_arch_stop_clocks(void) | ||
30 | { | ||
31 | /* nothing here yet */ | ||
32 | } | ||
33 | |||
34 | static inline void s3c_pm_arch_show_resume_irqs(void) | ||
35 | { | ||
36 | /* nothing here yet */ | ||
37 | } | ||
38 | |||
39 | static inline void s3c_pm_arch_update_uart(void __iomem *regs, | ||
40 | struct pm_uart_save *save) | ||
41 | { | ||
42 | /* nothing here yet */ | ||
43 | } | ||
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-clock.h b/arch/arm/mach-s5pv210/include/mach/regs-clock.h index 499aef737476..ebaabe021af9 100644 --- a/arch/arm/mach-s5pv210/include/mach/regs-clock.h +++ b/arch/arm/mach-s5pv210/include/mach/regs-clock.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #define S5P_APLL_CON S5P_CLKREG(0x100) | 25 | #define S5P_APLL_CON S5P_CLKREG(0x100) |
26 | #define S5P_MPLL_CON S5P_CLKREG(0x108) | 26 | #define S5P_MPLL_CON S5P_CLKREG(0x108) |
27 | #define S5P_EPLL_CON S5P_CLKREG(0x110) | 27 | #define S5P_EPLL_CON S5P_CLKREG(0x110) |
28 | #define S5P_EPLL_CON1 S5P_CLKREG(0x114) | ||
28 | #define S5P_VPLL_CON S5P_CLKREG(0x120) | 29 | #define S5P_VPLL_CON S5P_CLKREG(0x120) |
29 | 30 | ||
30 | #define S5P_CLK_SRC0 S5P_CLKREG(0x200) | 31 | #define S5P_CLK_SRC0 S5P_CLKREG(0x200) |
@@ -67,11 +68,28 @@ | |||
67 | #define S5P_CLKGATE_BUS1 S5P_CLKREG(0x488) | 68 | #define S5P_CLKGATE_BUS1 S5P_CLKREG(0x488) |
68 | #define S5P_CLK_OUT S5P_CLKREG(0x500) | 69 | #define S5P_CLK_OUT S5P_CLKREG(0x500) |
69 | 70 | ||
71 | /* DIV/MUX STATUS */ | ||
72 | #define S5P_CLKDIV_STAT0 S5P_CLKREG(0x1000) | ||
73 | #define S5P_CLKDIV_STAT1 S5P_CLKREG(0x1004) | ||
74 | #define S5P_CLKMUX_STAT0 S5P_CLKREG(0x1100) | ||
75 | #define S5P_CLKMUX_STAT1 S5P_CLKREG(0x1104) | ||
76 | |||
70 | /* CLKSRC0 */ | 77 | /* CLKSRC0 */ |
71 | #define S5P_CLKSRC0_MUX200_MASK (0x1<<16) | 78 | #define S5P_CLKSRC0_MUX200_SHIFT (16) |
79 | #define S5P_CLKSRC0_MUX200_MASK (0x1 << S5P_CLKSRC0_MUX200_SHIFT) | ||
72 | #define S5P_CLKSRC0_MUX166_MASK (0x1<<20) | 80 | #define S5P_CLKSRC0_MUX166_MASK (0x1<<20) |
73 | #define S5P_CLKSRC0_MUX133_MASK (0x1<<24) | 81 | #define S5P_CLKSRC0_MUX133_MASK (0x1<<24) |
74 | 82 | ||
83 | /* CLKSRC2 */ | ||
84 | #define S5P_CLKSRC2_G3D_SHIFT (0) | ||
85 | #define S5P_CLKSRC2_G3D_MASK (0x3 << S5P_CLKSRC2_G3D_SHIFT) | ||
86 | #define S5P_CLKSRC2_MFC_SHIFT (4) | ||
87 | #define S5P_CLKSRC2_MFC_MASK (0x3 << S5P_CLKSRC2_MFC_SHIFT) | ||
88 | |||
89 | /* CLKSRC6*/ | ||
90 | #define S5P_CLKSRC6_ONEDRAM_SHIFT (24) | ||
91 | #define S5P_CLKSRC6_ONEDRAM_MASK (0x3 << S5P_CLKSRC6_ONEDRAM_SHIFT) | ||
92 | |||
75 | /* CLKDIV0 */ | 93 | /* CLKDIV0 */ |
76 | #define S5P_CLKDIV0_APLL_SHIFT (0) | 94 | #define S5P_CLKDIV0_APLL_SHIFT (0) |
77 | #define S5P_CLKDIV0_APLL_MASK (0x7 << S5P_CLKDIV0_APLL_SHIFT) | 95 | #define S5P_CLKDIV0_APLL_MASK (0x7 << S5P_CLKDIV0_APLL_SHIFT) |
@@ -90,12 +108,24 @@ | |||
90 | #define S5P_CLKDIV0_PCLK66_SHIFT (28) | 108 | #define S5P_CLKDIV0_PCLK66_SHIFT (28) |
91 | #define S5P_CLKDIV0_PCLK66_MASK (0x7 << S5P_CLKDIV0_PCLK66_SHIFT) | 109 | #define S5P_CLKDIV0_PCLK66_MASK (0x7 << S5P_CLKDIV0_PCLK66_SHIFT) |
92 | 110 | ||
111 | /* CLKDIV2 */ | ||
112 | #define S5P_CLKDIV2_G3D_SHIFT (0) | ||
113 | #define S5P_CLKDIV2_G3D_MASK (0xF << S5P_CLKDIV2_G3D_SHIFT) | ||
114 | #define S5P_CLKDIV2_MFC_SHIFT (4) | ||
115 | #define S5P_CLKDIV2_MFC_MASK (0xF << S5P_CLKDIV2_MFC_SHIFT) | ||
116 | |||
117 | /* CLKDIV6 */ | ||
118 | #define S5P_CLKDIV6_ONEDRAM_SHIFT (28) | ||
119 | #define S5P_CLKDIV6_ONEDRAM_MASK (0xF << S5P_CLKDIV6_ONEDRAM_SHIFT) | ||
120 | |||
93 | #define S5P_SWRESET S5P_CLKREG(0x2000) | 121 | #define S5P_SWRESET S5P_CLKREG(0x2000) |
94 | 122 | ||
123 | #define S5P_ARM_MCS_CON S5P_CLKREG(0x6100) | ||
124 | |||
95 | /* Registers related to power management */ | 125 | /* Registers related to power management */ |
96 | #define S5P_PWR_CFG S5P_CLKREG(0xC000) | 126 | #define S5P_PWR_CFG S5P_CLKREG(0xC000) |
97 | #define S5P_EINT_WAKEUP_MASK S5P_CLKREG(0xC004) | 127 | #define S5P_EINT_WAKEUP_MASK S5P_CLKREG(0xC004) |
98 | #define S5P_WAKEUP_MASK S5P_CLKREG(0xC008) | 128 | #define S5P_WAKEUP_MASK S5P_CLKREG(0xC008) |
99 | #define S5P_PWR_MODE S5P_CLKREG(0xC00C) | 129 | #define S5P_PWR_MODE S5P_CLKREG(0xC00C) |
100 | #define S5P_NORMAL_CFG S5P_CLKREG(0xC010) | 130 | #define S5P_NORMAL_CFG S5P_CLKREG(0xC010) |
101 | #define S5P_IDLE_CFG S5P_CLKREG(0xC020) | 131 | #define S5P_IDLE_CFG S5P_CLKREG(0xC020) |
@@ -159,8 +189,11 @@ | |||
159 | #define S5P_SLEEP_CFG_USBOSC_EN (1 << 1) | 189 | #define S5P_SLEEP_CFG_USBOSC_EN (1 << 1) |
160 | 190 | ||
161 | /* OTHERS Resgister */ | 191 | /* OTHERS Resgister */ |
192 | #define S5P_OTHERS_RET_IO (1 << 31) | ||
193 | #define S5P_OTHERS_RET_CF (1 << 30) | ||
194 | #define S5P_OTHERS_RET_MMC (1 << 29) | ||
195 | #define S5P_OTHERS_RET_UART (1 << 28) | ||
162 | #define S5P_OTHERS_USB_SIG_MASK (1 << 16) | 196 | #define S5P_OTHERS_USB_SIG_MASK (1 << 16) |
163 | #define S5P_OTHERS_MIPI_DPHY_EN (1 << 28) | ||
164 | 197 | ||
165 | /* MIPI */ | 198 | /* MIPI */ |
166 | #define S5P_MIPI_DPHY_EN (3) | 199 | #define S5P_MIPI_DPHY_EN (3) |
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-gpio.h b/arch/arm/mach-s5pv210/include/mach/regs-gpio.h index 49e029b4978a..de0c89976078 100644 --- a/arch/arm/mach-s5pv210/include/mach/regs-gpio.h +++ b/arch/arm/mach-s5pv210/include/mach/regs-gpio.h | |||
@@ -31,13 +31,6 @@ | |||
31 | 31 | ||
32 | #define eint_irq_to_bit(irq) (1 << (EINT_OFFSET(irq) & 0x7)) | 32 | #define eint_irq_to_bit(irq) (1 << (EINT_OFFSET(irq) & 0x7)) |
33 | 33 | ||
34 | /* values for S5P_EXTINT0 */ | ||
35 | #define S5P_EXTINT_LOWLEV (0x00) | ||
36 | #define S5P_EXTINT_HILEV (0x01) | ||
37 | #define S5P_EXTINT_FALLEDGE (0x02) | ||
38 | #define S5P_EXTINT_RISEEDGE (0x03) | ||
39 | #define S5P_EXTINT_BOTHEDGE (0x04) | ||
40 | |||
41 | #define EINT_MODE S3C_GPIO_SFN(0xf) | 34 | #define EINT_MODE S3C_GPIO_SFN(0xf) |
42 | 35 | ||
43 | #define EINT_GPIO_0(x) S5PV210_GPH0(x) | 36 | #define EINT_GPIO_0(x) S5PV210_GPH0(x) |
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-sys.h b/arch/arm/mach-s5pv210/include/mach/regs-sys.h new file mode 100644 index 000000000000..26691d39d0f4 --- /dev/null +++ b/arch/arm/mach-s5pv210/include/mach/regs-sys.h | |||
@@ -0,0 +1,19 @@ | |||
1 | /* arch/arm/mach-s5pv210/include/mach/regs-sys.h | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
6 | * S5PV210 - System registers definitions | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #define S5PV210_USB_PHY_CON (S3C_VA_SYS + 0xE80C) | ||
14 | #define S5PV210_USB_PHY0_EN (1 << 0) | ||
15 | #define S5PV210_USB_PHY1_EN (1 << 1) | ||
16 | |||
17 | /* compatibility defines for s3c-hsotg driver */ | ||
18 | #define S3C64XX_OTHERS S5PV210_USB_PHY_CON | ||
19 | #define S3C64XX_OTHERS_USBMASK S5PV210_USB_PHY0_EN | ||
diff --git a/arch/arm/mach-s5pv210/include/mach/vmalloc.h b/arch/arm/mach-s5pv210/include/mach/vmalloc.h index df9a28808323..a6c659d68a5d 100644 --- a/arch/arm/mach-s5pv210/include/mach/vmalloc.h +++ b/arch/arm/mach-s5pv210/include/mach/vmalloc.h | |||
@@ -17,6 +17,6 @@ | |||
17 | #ifndef __ASM_ARCH_VMALLOC_H | 17 | #ifndef __ASM_ARCH_VMALLOC_H |
18 | #define __ASM_ARCH_VMALLOC_H __FILE__ | 18 | #define __ASM_ARCH_VMALLOC_H __FILE__ |
19 | 19 | ||
20 | #define VMALLOC_END (0xE0000000UL) | 20 | #define VMALLOC_END 0xF6000000UL |
21 | 21 | ||
22 | #endif /* __ASM_ARCH_VMALLOC_H */ | 22 | #endif /* __ASM_ARCH_VMALLOC_H */ |
diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c index 00883087363c..28677caf3613 100644 --- a/arch/arm/mach-s5pv210/mach-aquila.c +++ b/arch/arm/mach-s5pv210/mach-aquila.c | |||
@@ -16,6 +16,8 @@ | |||
16 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
17 | #include <linux/i2c-gpio.h> | 17 | #include <linux/i2c-gpio.h> |
18 | #include <linux/mfd/max8998.h> | 18 | #include <linux/mfd/max8998.h> |
19 | #include <linux/mfd/wm8994/pdata.h> | ||
20 | #include <linux/regulator/fixed.h> | ||
19 | #include <linux/gpio_keys.h> | 21 | #include <linux/gpio_keys.h> |
20 | #include <linux/input.h> | 22 | #include <linux/input.h> |
21 | #include <linux/gpio.h> | 23 | #include <linux/gpio.h> |
@@ -379,6 +381,119 @@ static struct max8998_platform_data aquila_max8998_pdata = { | |||
379 | }; | 381 | }; |
380 | #endif | 382 | #endif |
381 | 383 | ||
384 | static struct regulator_consumer_supply wm8994_fixed_voltage0_supplies[] = { | ||
385 | { | ||
386 | .dev_name = "5-001a", | ||
387 | .supply = "DBVDD", | ||
388 | }, { | ||
389 | .dev_name = "5-001a", | ||
390 | .supply = "AVDD2", | ||
391 | }, { | ||
392 | .dev_name = "5-001a", | ||
393 | .supply = "CPVDD", | ||
394 | }, | ||
395 | }; | ||
396 | |||
397 | static struct regulator_consumer_supply wm8994_fixed_voltage1_supplies[] = { | ||
398 | { | ||
399 | .dev_name = "5-001a", | ||
400 | .supply = "SPKVDD1", | ||
401 | }, { | ||
402 | .dev_name = "5-001a", | ||
403 | .supply = "SPKVDD2", | ||
404 | }, | ||
405 | }; | ||
406 | |||
407 | static struct regulator_init_data wm8994_fixed_voltage0_init_data = { | ||
408 | .constraints = { | ||
409 | .always_on = 1, | ||
410 | }, | ||
411 | .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage0_supplies), | ||
412 | .consumer_supplies = wm8994_fixed_voltage0_supplies, | ||
413 | }; | ||
414 | |||
415 | static struct regulator_init_data wm8994_fixed_voltage1_init_data = { | ||
416 | .constraints = { | ||
417 | .always_on = 1, | ||
418 | }, | ||
419 | .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage1_supplies), | ||
420 | .consumer_supplies = wm8994_fixed_voltage1_supplies, | ||
421 | }; | ||
422 | |||
423 | static struct fixed_voltage_config wm8994_fixed_voltage0_config = { | ||
424 | .supply_name = "VCC_1.8V_PDA", | ||
425 | .microvolts = 1800000, | ||
426 | .gpio = -EINVAL, | ||
427 | .init_data = &wm8994_fixed_voltage0_init_data, | ||
428 | }; | ||
429 | |||
430 | static struct fixed_voltage_config wm8994_fixed_voltage1_config = { | ||
431 | .supply_name = "V_BAT", | ||
432 | .microvolts = 3700000, | ||
433 | .gpio = -EINVAL, | ||
434 | .init_data = &wm8994_fixed_voltage1_init_data, | ||
435 | }; | ||
436 | |||
437 | static struct platform_device wm8994_fixed_voltage0 = { | ||
438 | .name = "reg-fixed-voltage", | ||
439 | .id = 0, | ||
440 | .dev = { | ||
441 | .platform_data = &wm8994_fixed_voltage0_config, | ||
442 | }, | ||
443 | }; | ||
444 | |||
445 | static struct platform_device wm8994_fixed_voltage1 = { | ||
446 | .name = "reg-fixed-voltage", | ||
447 | .id = 1, | ||
448 | .dev = { | ||
449 | .platform_data = &wm8994_fixed_voltage1_config, | ||
450 | }, | ||
451 | }; | ||
452 | |||
453 | static struct regulator_consumer_supply wm8994_avdd1_supply = { | ||
454 | .dev_name = "5-001a", | ||
455 | .supply = "AVDD1", | ||
456 | }; | ||
457 | |||
458 | static struct regulator_consumer_supply wm8994_dcvdd_supply = { | ||
459 | .dev_name = "5-001a", | ||
460 | .supply = "DCVDD", | ||
461 | }; | ||
462 | |||
463 | static struct regulator_init_data wm8994_ldo1_data = { | ||
464 | .constraints = { | ||
465 | .name = "AVDD1_3.0V", | ||
466 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | ||
467 | }, | ||
468 | .num_consumer_supplies = 1, | ||
469 | .consumer_supplies = &wm8994_avdd1_supply, | ||
470 | }; | ||
471 | |||
472 | static struct regulator_init_data wm8994_ldo2_data = { | ||
473 | .constraints = { | ||
474 | .name = "DCVDD_1.0V", | ||
475 | }, | ||
476 | .num_consumer_supplies = 1, | ||
477 | .consumer_supplies = &wm8994_dcvdd_supply, | ||
478 | }; | ||
479 | |||
480 | static struct wm8994_pdata wm8994_platform_data = { | ||
481 | /* configure gpio1 function: 0x0001(Logic level input/output) */ | ||
482 | .gpio_defaults[0] = 0x0001, | ||
483 | /* configure gpio3/4/5/7 function for AIF2 voice */ | ||
484 | .gpio_defaults[2] = 0x8100, | ||
485 | .gpio_defaults[3] = 0x8100, | ||
486 | .gpio_defaults[4] = 0x8100, | ||
487 | .gpio_defaults[6] = 0x0100, | ||
488 | /* configure gpio8/9/10/11 function for AIF3 BT */ | ||
489 | .gpio_defaults[7] = 0x8100, | ||
490 | .gpio_defaults[8] = 0x0100, | ||
491 | .gpio_defaults[9] = 0x0100, | ||
492 | .gpio_defaults[10] = 0x0100, | ||
493 | .ldo[0] = { S5PV210_MP03(6), NULL, &wm8994_ldo1_data }, /* XM0FRNB_2 */ | ||
494 | .ldo[1] = { 0, NULL, &wm8994_ldo2_data }, | ||
495 | }; | ||
496 | |||
382 | /* GPIO I2C PMIC */ | 497 | /* GPIO I2C PMIC */ |
383 | #define AP_I2C_GPIO_PMIC_BUS_4 4 | 498 | #define AP_I2C_GPIO_PMIC_BUS_4 4 |
384 | static struct i2c_gpio_platform_data aquila_i2c_gpio_pmic_data = { | 499 | static struct i2c_gpio_platform_data aquila_i2c_gpio_pmic_data = { |
@@ -404,6 +519,29 @@ static struct i2c_board_info i2c_gpio_pmic_devs[] __initdata = { | |||
404 | #endif | 519 | #endif |
405 | }; | 520 | }; |
406 | 521 | ||
522 | /* GPIO I2C AP 1.8V */ | ||
523 | #define AP_I2C_GPIO_BUS_5 5 | ||
524 | static struct i2c_gpio_platform_data aquila_i2c_gpio5_data = { | ||
525 | .sda_pin = S5PV210_MP05(3), /* XM0ADDR_11 */ | ||
526 | .scl_pin = S5PV210_MP05(2), /* XM0ADDR_10 */ | ||
527 | }; | ||
528 | |||
529 | static struct platform_device aquila_i2c_gpio5 = { | ||
530 | .name = "i2c-gpio", | ||
531 | .id = AP_I2C_GPIO_BUS_5, | ||
532 | .dev = { | ||
533 | .platform_data = &aquila_i2c_gpio5_data, | ||
534 | }, | ||
535 | }; | ||
536 | |||
537 | static struct i2c_board_info i2c_gpio5_devs[] __initdata = { | ||
538 | { | ||
539 | /* CS/ADDR = low 0x34 (FYI: high = 0x36) */ | ||
540 | I2C_BOARD_INFO("wm8994", 0x1a), | ||
541 | .platform_data = &wm8994_platform_data, | ||
542 | }, | ||
543 | }; | ||
544 | |||
407 | /* PMIC Power button */ | 545 | /* PMIC Power button */ |
408 | static struct gpio_keys_button aquila_gpio_keys_table[] = { | 546 | static struct gpio_keys_button aquila_gpio_keys_table[] = { |
409 | { | 547 | { |
@@ -475,6 +613,7 @@ static void aquila_setup_sdhci(void) | |||
475 | 613 | ||
476 | static struct platform_device *aquila_devices[] __initdata = { | 614 | static struct platform_device *aquila_devices[] __initdata = { |
477 | &aquila_i2c_gpio_pmic, | 615 | &aquila_i2c_gpio_pmic, |
616 | &aquila_i2c_gpio5, | ||
478 | &aquila_device_gpiokeys, | 617 | &aquila_device_gpiokeys, |
479 | &s3c_device_fb, | 618 | &s3c_device_fb, |
480 | &s5p_device_onenand, | 619 | &s5p_device_onenand, |
@@ -484,8 +623,33 @@ static struct platform_device *aquila_devices[] __initdata = { | |||
484 | &s5p_device_fimc0, | 623 | &s5p_device_fimc0, |
485 | &s5p_device_fimc1, | 624 | &s5p_device_fimc1, |
486 | &s5p_device_fimc2, | 625 | &s5p_device_fimc2, |
626 | &s5pv210_device_iis0, | ||
627 | &wm8994_fixed_voltage0, | ||
628 | &wm8994_fixed_voltage1, | ||
487 | }; | 629 | }; |
488 | 630 | ||
631 | static void __init aquila_sound_init(void) | ||
632 | { | ||
633 | unsigned int gpio; | ||
634 | |||
635 | /* CODEC_XTAL_EN | ||
636 | * | ||
637 | * The Aquila board have a oscillator which provide main clock | ||
638 | * to WM8994 codec. The oscillator provide 24MHz clock to WM8994 | ||
639 | * clock. Set gpio setting of "CODEC_XTAL_EN" to enable a oscillator. | ||
640 | * */ | ||
641 | gpio = S5PV210_GPH3(2); /* XEINT_26 */ | ||
642 | gpio_request(gpio, "CODEC_XTAL_EN"); | ||
643 | s3c_gpio_cfgpin(gpio, S3C_GPIO_OUTPUT); | ||
644 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
645 | |||
646 | /* Ths main clock of WM8994 codec uses the output of CLKOUT pin. | ||
647 | * The CLKOUT[9:8] set to 0x3(XUSBXTI) of 0xE010E000(OTHERS) | ||
648 | * because it needs 24MHz clock to operate WM8994 codec. | ||
649 | */ | ||
650 | __raw_writel(__raw_readl(S5P_OTHERS) | (0x3 << 8), S5P_OTHERS); | ||
651 | } | ||
652 | |||
489 | static void __init aquila_map_io(void) | 653 | static void __init aquila_map_io(void) |
490 | { | 654 | { |
491 | s5p_init_io(NULL, 0, S5P_VA_CHIPID); | 655 | s5p_init_io(NULL, 0, S5P_VA_CHIPID); |
@@ -506,6 +670,11 @@ static void __init aquila_machine_init(void) | |||
506 | s3c_fimc_setname(1, "s5p-fimc"); | 670 | s3c_fimc_setname(1, "s5p-fimc"); |
507 | s3c_fimc_setname(2, "s5p-fimc"); | 671 | s3c_fimc_setname(2, "s5p-fimc"); |
508 | 672 | ||
673 | /* SOUND */ | ||
674 | aquila_sound_init(); | ||
675 | i2c_register_board_info(AP_I2C_GPIO_BUS_5, i2c_gpio5_devs, | ||
676 | ARRAY_SIZE(i2c_gpio5_devs)); | ||
677 | |||
509 | /* FB */ | 678 | /* FB */ |
510 | s3c_fb_set_platdata(&aquila_lcd_pdata); | 679 | s3c_fb_set_platdata(&aquila_lcd_pdata); |
511 | 680 | ||
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index d9ecf57fc2a5..b1dcf964a768 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c | |||
@@ -15,7 +15,13 @@ | |||
15 | #include <linux/fb.h> | 15 | #include <linux/fb.h> |
16 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
17 | #include <linux/i2c-gpio.h> | 17 | #include <linux/i2c-gpio.h> |
18 | #include <linux/i2c/qt602240_ts.h> | ||
18 | #include <linux/mfd/max8998.h> | 19 | #include <linux/mfd/max8998.h> |
20 | #include <linux/mfd/wm8994/pdata.h> | ||
21 | #include <linux/regulator/fixed.h> | ||
22 | #include <linux/spi/spi.h> | ||
23 | #include <linux/spi/spi_gpio.h> | ||
24 | #include <linux/lcd.h> | ||
19 | #include <linux/gpio_keys.h> | 25 | #include <linux/gpio_keys.h> |
20 | #include <linux/input.h> | 26 | #include <linux/input.h> |
21 | #include <linux/gpio.h> | 27 | #include <linux/gpio.h> |
@@ -35,7 +41,10 @@ | |||
35 | #include <plat/devs.h> | 41 | #include <plat/devs.h> |
36 | #include <plat/cpu.h> | 42 | #include <plat/cpu.h> |
37 | #include <plat/fb.h> | 43 | #include <plat/fb.h> |
44 | #include <plat/iic.h> | ||
45 | #include <plat/keypad.h> | ||
38 | #include <plat/sdhci.h> | 46 | #include <plat/sdhci.h> |
47 | #include <plat/clock.h> | ||
39 | 48 | ||
40 | /* Following are default values for UCON, ULCON and UFCON UART registers */ | 49 | /* Following are default values for UCON, ULCON and UFCON UART registers */ |
41 | #define GONI_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ | 50 | #define GONI_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ |
@@ -87,13 +96,12 @@ static struct s3c2410_uartcfg goni_uartcfgs[] __initdata = { | |||
87 | /* Frame Buffer */ | 96 | /* Frame Buffer */ |
88 | static struct s3c_fb_pd_win goni_fb_win0 = { | 97 | static struct s3c_fb_pd_win goni_fb_win0 = { |
89 | .win_mode = { | 98 | .win_mode = { |
90 | .pixclock = 1000000000000ULL / ((16+16+2+480)*(28+3+2+800)*55), | ||
91 | .left_margin = 16, | 99 | .left_margin = 16, |
92 | .right_margin = 16, | 100 | .right_margin = 16, |
93 | .upper_margin = 3, | 101 | .upper_margin = 2, |
94 | .lower_margin = 28, | 102 | .lower_margin = 28, |
95 | .hsync_len = 2, | 103 | .hsync_len = 2, |
96 | .vsync_len = 2, | 104 | .vsync_len = 1, |
97 | .xres = 480, | 105 | .xres = 480, |
98 | .yres = 800, | 106 | .yres = 800, |
99 | .refresh = 55, | 107 | .refresh = 55, |
@@ -111,9 +119,160 @@ static struct s3c_fb_platdata goni_lcd_pdata __initdata = { | |||
111 | .setup_gpio = s5pv210_fb_gpio_setup_24bpp, | 119 | .setup_gpio = s5pv210_fb_gpio_setup_24bpp, |
112 | }; | 120 | }; |
113 | 121 | ||
122 | static int lcd_power_on(struct lcd_device *ld, int enable) | ||
123 | { | ||
124 | return 1; | ||
125 | } | ||
126 | |||
127 | static int reset_lcd(struct lcd_device *ld) | ||
128 | { | ||
129 | static unsigned int first = 1; | ||
130 | int reset_gpio = -1; | ||
131 | |||
132 | reset_gpio = S5PV210_MP05(5); | ||
133 | |||
134 | if (first) { | ||
135 | gpio_request(reset_gpio, "MLCD_RST"); | ||
136 | first = 0; | ||
137 | } | ||
138 | |||
139 | gpio_direction_output(reset_gpio, 1); | ||
140 | return 1; | ||
141 | } | ||
142 | |||
143 | static struct lcd_platform_data goni_lcd_platform_data = { | ||
144 | .reset = reset_lcd, | ||
145 | .power_on = lcd_power_on, | ||
146 | .lcd_enabled = 0, | ||
147 | .reset_delay = 120, /* 120ms */ | ||
148 | .power_on_delay = 25, /* 25ms */ | ||
149 | .power_off_delay = 200, /* 200ms */ | ||
150 | }; | ||
151 | |||
152 | #define LCD_BUS_NUM 3 | ||
153 | static struct spi_board_info spi_board_info[] __initdata = { | ||
154 | { | ||
155 | .modalias = "s6e63m0", | ||
156 | .platform_data = &goni_lcd_platform_data, | ||
157 | .max_speed_hz = 1200000, | ||
158 | .bus_num = LCD_BUS_NUM, | ||
159 | .chip_select = 0, | ||
160 | .mode = SPI_MODE_3, | ||
161 | .controller_data = (void *)S5PV210_MP01(1), /* DISPLAY_CS */ | ||
162 | }, | ||
163 | }; | ||
164 | |||
165 | static struct spi_gpio_platform_data lcd_spi_gpio_data = { | ||
166 | .sck = S5PV210_MP04(1), /* DISPLAY_CLK */ | ||
167 | .mosi = S5PV210_MP04(3), /* DISPLAY_SI */ | ||
168 | .miso = SPI_GPIO_NO_MISO, | ||
169 | .num_chipselect = 1, | ||
170 | }; | ||
171 | |||
172 | static struct platform_device goni_spi_gpio = { | ||
173 | .name = "spi_gpio", | ||
174 | .id = LCD_BUS_NUM, | ||
175 | .dev = { | ||
176 | .parent = &s3c_device_fb.dev, | ||
177 | .platform_data = &lcd_spi_gpio_data, | ||
178 | }, | ||
179 | }; | ||
180 | |||
181 | /* KEYPAD */ | ||
182 | static uint32_t keymap[] __initdata = { | ||
183 | /* KEY(row, col, keycode) */ | ||
184 | KEY(0, 1, KEY_MENU), /* Send */ | ||
185 | KEY(0, 2, KEY_BACK), /* End */ | ||
186 | KEY(1, 1, KEY_CONFIG), /* Half shot */ | ||
187 | KEY(1, 2, KEY_VOLUMEUP), | ||
188 | KEY(2, 1, KEY_CAMERA), /* Full shot */ | ||
189 | KEY(2, 2, KEY_VOLUMEDOWN), | ||
190 | }; | ||
191 | |||
192 | static struct matrix_keymap_data keymap_data __initdata = { | ||
193 | .keymap = keymap, | ||
194 | .keymap_size = ARRAY_SIZE(keymap), | ||
195 | }; | ||
196 | |||
197 | static struct samsung_keypad_platdata keypad_data __initdata = { | ||
198 | .keymap_data = &keymap_data, | ||
199 | .rows = 3, | ||
200 | .cols = 3, | ||
201 | }; | ||
202 | |||
203 | /* Radio */ | ||
204 | static struct i2c_board_info i2c1_devs[] __initdata = { | ||
205 | { | ||
206 | I2C_BOARD_INFO("si470x", 0x10), | ||
207 | }, | ||
208 | }; | ||
209 | |||
210 | static void __init goni_radio_init(void) | ||
211 | { | ||
212 | int gpio; | ||
213 | |||
214 | gpio = S5PV210_GPJ2(4); /* XMSMDATA_4 */ | ||
215 | gpio_request(gpio, "FM_INT"); | ||
216 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf)); | ||
217 | i2c1_devs[0].irq = gpio_to_irq(gpio); | ||
218 | |||
219 | gpio = S5PV210_GPJ2(5); /* XMSMDATA_5 */ | ||
220 | gpio_request(gpio, "FM_RST"); | ||
221 | gpio_direction_output(gpio, 1); | ||
222 | } | ||
223 | |||
224 | /* TSP */ | ||
225 | static struct qt602240_platform_data qt602240_platform_data = { | ||
226 | .x_line = 17, | ||
227 | .y_line = 11, | ||
228 | .x_size = 800, | ||
229 | .y_size = 480, | ||
230 | .blen = 0x21, | ||
231 | .threshold = 0x28, | ||
232 | .voltage = 2800000, /* 2.8V */ | ||
233 | .orient = QT602240_DIAGONAL, | ||
234 | }; | ||
235 | |||
236 | static struct s3c2410_platform_i2c i2c2_data __initdata = { | ||
237 | .flags = 0, | ||
238 | .bus_num = 2, | ||
239 | .slave_addr = 0x10, | ||
240 | .frequency = 400 * 1000, | ||
241 | .sda_delay = 100, | ||
242 | }; | ||
243 | |||
244 | static struct i2c_board_info i2c2_devs[] __initdata = { | ||
245 | { | ||
246 | I2C_BOARD_INFO("qt602240_ts", 0x4a), | ||
247 | .platform_data = &qt602240_platform_data, | ||
248 | }, | ||
249 | }; | ||
250 | |||
251 | static void __init goni_tsp_init(void) | ||
252 | { | ||
253 | int gpio; | ||
254 | |||
255 | gpio = S5PV210_GPJ1(3); /* XMSMADDR_11 */ | ||
256 | gpio_request(gpio, "TSP_LDO_ON"); | ||
257 | gpio_direction_output(gpio, 1); | ||
258 | gpio_export(gpio, 0); | ||
259 | |||
260 | gpio = S5PV210_GPJ0(5); /* XMSMADDR_5 */ | ||
261 | gpio_request(gpio, "TSP_INT"); | ||
262 | |||
263 | s5p_register_gpio_interrupt(gpio); | ||
264 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf)); | ||
265 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); | ||
266 | i2c2_devs[0].irq = gpio_to_irq(gpio); | ||
267 | } | ||
268 | |||
114 | /* MAX8998 regulators */ | 269 | /* MAX8998 regulators */ |
115 | #if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE) | 270 | #if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE) |
116 | 271 | ||
272 | static struct regulator_consumer_supply goni_ldo5_consumers[] = { | ||
273 | REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"), | ||
274 | }; | ||
275 | |||
117 | static struct regulator_init_data goni_ldo2_data = { | 276 | static struct regulator_init_data goni_ldo2_data = { |
118 | .constraints = { | 277 | .constraints = { |
119 | .name = "VALIVE_1.1V", | 278 | .name = "VALIVE_1.1V", |
@@ -153,6 +312,8 @@ static struct regulator_init_data goni_ldo5_data = { | |||
153 | .max_uV = 2800000, | 312 | .max_uV = 2800000, |
154 | .apply_uV = 1, | 313 | .apply_uV = 1, |
155 | }, | 314 | }, |
315 | .num_consumer_supplies = ARRAY_SIZE(goni_ldo5_consumers), | ||
316 | .consumer_supplies = goni_ldo5_consumers, | ||
156 | }; | 317 | }; |
157 | 318 | ||
158 | static struct regulator_init_data goni_ldo6_data = { | 319 | static struct regulator_init_data goni_ldo6_data = { |
@@ -360,6 +521,119 @@ static struct max8998_platform_data goni_max8998_pdata = { | |||
360 | }; | 521 | }; |
361 | #endif | 522 | #endif |
362 | 523 | ||
524 | static struct regulator_consumer_supply wm8994_fixed_voltage0_supplies[] = { | ||
525 | { | ||
526 | .dev_name = "5-001a", | ||
527 | .supply = "DBVDD", | ||
528 | }, { | ||
529 | .dev_name = "5-001a", | ||
530 | .supply = "AVDD2", | ||
531 | }, { | ||
532 | .dev_name = "5-001a", | ||
533 | .supply = "CPVDD", | ||
534 | }, | ||
535 | }; | ||
536 | |||
537 | static struct regulator_consumer_supply wm8994_fixed_voltage1_supplies[] = { | ||
538 | { | ||
539 | .dev_name = "5-001a", | ||
540 | .supply = "SPKVDD1", | ||
541 | }, { | ||
542 | .dev_name = "5-001a", | ||
543 | .supply = "SPKVDD2", | ||
544 | }, | ||
545 | }; | ||
546 | |||
547 | static struct regulator_init_data wm8994_fixed_voltage0_init_data = { | ||
548 | .constraints = { | ||
549 | .always_on = 1, | ||
550 | }, | ||
551 | .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage0_supplies), | ||
552 | .consumer_supplies = wm8994_fixed_voltage0_supplies, | ||
553 | }; | ||
554 | |||
555 | static struct regulator_init_data wm8994_fixed_voltage1_init_data = { | ||
556 | .constraints = { | ||
557 | .always_on = 1, | ||
558 | }, | ||
559 | .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage1_supplies), | ||
560 | .consumer_supplies = wm8994_fixed_voltage1_supplies, | ||
561 | }; | ||
562 | |||
563 | static struct fixed_voltage_config wm8994_fixed_voltage0_config = { | ||
564 | .supply_name = "VCC_1.8V_PDA", | ||
565 | .microvolts = 1800000, | ||
566 | .gpio = -EINVAL, | ||
567 | .init_data = &wm8994_fixed_voltage0_init_data, | ||
568 | }; | ||
569 | |||
570 | static struct fixed_voltage_config wm8994_fixed_voltage1_config = { | ||
571 | .supply_name = "V_BAT", | ||
572 | .microvolts = 3700000, | ||
573 | .gpio = -EINVAL, | ||
574 | .init_data = &wm8994_fixed_voltage1_init_data, | ||
575 | }; | ||
576 | |||
577 | static struct platform_device wm8994_fixed_voltage0 = { | ||
578 | .name = "reg-fixed-voltage", | ||
579 | .id = 0, | ||
580 | .dev = { | ||
581 | .platform_data = &wm8994_fixed_voltage0_config, | ||
582 | }, | ||
583 | }; | ||
584 | |||
585 | static struct platform_device wm8994_fixed_voltage1 = { | ||
586 | .name = "reg-fixed-voltage", | ||
587 | .id = 1, | ||
588 | .dev = { | ||
589 | .platform_data = &wm8994_fixed_voltage1_config, | ||
590 | }, | ||
591 | }; | ||
592 | |||
593 | static struct regulator_consumer_supply wm8994_avdd1_supply = { | ||
594 | .dev_name = "5-001a", | ||
595 | .supply = "AVDD1", | ||
596 | }; | ||
597 | |||
598 | static struct regulator_consumer_supply wm8994_dcvdd_supply = { | ||
599 | .dev_name = "5-001a", | ||
600 | .supply = "DCVDD", | ||
601 | }; | ||
602 | |||
603 | static struct regulator_init_data wm8994_ldo1_data = { | ||
604 | .constraints = { | ||
605 | .name = "AVDD1_3.0V", | ||
606 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | ||
607 | }, | ||
608 | .num_consumer_supplies = 1, | ||
609 | .consumer_supplies = &wm8994_avdd1_supply, | ||
610 | }; | ||
611 | |||
612 | static struct regulator_init_data wm8994_ldo2_data = { | ||
613 | .constraints = { | ||
614 | .name = "DCVDD_1.0V", | ||
615 | }, | ||
616 | .num_consumer_supplies = 1, | ||
617 | .consumer_supplies = &wm8994_dcvdd_supply, | ||
618 | }; | ||
619 | |||
620 | static struct wm8994_pdata wm8994_platform_data = { | ||
621 | /* configure gpio1 function: 0x0001(Logic level input/output) */ | ||
622 | .gpio_defaults[0] = 0x0001, | ||
623 | /* configure gpio3/4/5/7 function for AIF2 voice */ | ||
624 | .gpio_defaults[2] = 0x8100, | ||
625 | .gpio_defaults[3] = 0x8100, | ||
626 | .gpio_defaults[4] = 0x8100, | ||
627 | .gpio_defaults[6] = 0x0100, | ||
628 | /* configure gpio8/9/10/11 function for AIF3 BT */ | ||
629 | .gpio_defaults[7] = 0x8100, | ||
630 | .gpio_defaults[8] = 0x0100, | ||
631 | .gpio_defaults[9] = 0x0100, | ||
632 | .gpio_defaults[10] = 0x0100, | ||
633 | .ldo[0] = { S5PV210_MP03(6), NULL, &wm8994_ldo1_data }, /* XM0FRNB_2 */ | ||
634 | .ldo[1] = { 0, NULL, &wm8994_ldo2_data }, | ||
635 | }; | ||
636 | |||
363 | /* GPIO I2C PMIC */ | 637 | /* GPIO I2C PMIC */ |
364 | #define AP_I2C_GPIO_PMIC_BUS_4 4 | 638 | #define AP_I2C_GPIO_PMIC_BUS_4 4 |
365 | static struct i2c_gpio_platform_data goni_i2c_gpio_pmic_data = { | 639 | static struct i2c_gpio_platform_data goni_i2c_gpio_pmic_data = { |
@@ -385,6 +659,29 @@ static struct i2c_board_info i2c_gpio_pmic_devs[] __initdata = { | |||
385 | #endif | 659 | #endif |
386 | }; | 660 | }; |
387 | 661 | ||
662 | /* GPIO I2C AP 1.8V */ | ||
663 | #define AP_I2C_GPIO_BUS_5 5 | ||
664 | static struct i2c_gpio_platform_data goni_i2c_gpio5_data = { | ||
665 | .sda_pin = S5PV210_MP05(3), /* XM0ADDR_11 */ | ||
666 | .scl_pin = S5PV210_MP05(2), /* XM0ADDR_10 */ | ||
667 | }; | ||
668 | |||
669 | static struct platform_device goni_i2c_gpio5 = { | ||
670 | .name = "i2c-gpio", | ||
671 | .id = AP_I2C_GPIO_BUS_5, | ||
672 | .dev = { | ||
673 | .platform_data = &goni_i2c_gpio5_data, | ||
674 | }, | ||
675 | }; | ||
676 | |||
677 | static struct i2c_board_info i2c_gpio5_devs[] __initdata = { | ||
678 | { | ||
679 | /* CS/ADDR = low 0x34 (FYI: high = 0x36) */ | ||
680 | I2C_BOARD_INFO("wm8994", 0x1a), | ||
681 | .platform_data = &wm8994_platform_data, | ||
682 | }, | ||
683 | }; | ||
684 | |||
388 | /* PMIC Power button */ | 685 | /* PMIC Power button */ |
389 | static struct gpio_keys_button goni_gpio_keys_table[] = { | 686 | static struct gpio_keys_button goni_gpio_keys_table[] = { |
390 | { | 687 | { |
@@ -444,11 +741,37 @@ static struct s3c_sdhci_platdata goni_hsmmc2_data __initdata = { | |||
444 | .ext_cd_gpio_invert = 1, | 741 | .ext_cd_gpio_invert = 1, |
445 | }; | 742 | }; |
446 | 743 | ||
744 | static struct regulator_consumer_supply mmc2_supplies[] = { | ||
745 | REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"), | ||
746 | }; | ||
747 | |||
748 | static struct regulator_init_data mmc2_fixed_voltage_init_data = { | ||
749 | .constraints = { | ||
750 | .name = "V_TF_2.8V", | ||
751 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | ||
752 | }, | ||
753 | .num_consumer_supplies = ARRAY_SIZE(mmc2_supplies), | ||
754 | .consumer_supplies = mmc2_supplies, | ||
755 | }; | ||
756 | |||
757 | static struct fixed_voltage_config mmc2_fixed_voltage_config = { | ||
758 | .supply_name = "EXT_FLASH_EN", | ||
759 | .microvolts = 2800000, | ||
760 | .gpio = GONI_EXT_FLASH_EN, | ||
761 | .enable_high = true, | ||
762 | .init_data = &mmc2_fixed_voltage_init_data, | ||
763 | }; | ||
764 | |||
765 | static struct platform_device mmc2_fixed_voltage = { | ||
766 | .name = "reg-fixed-voltage", | ||
767 | .id = 2, | ||
768 | .dev = { | ||
769 | .platform_data = &mmc2_fixed_voltage_config, | ||
770 | }, | ||
771 | }; | ||
772 | |||
447 | static void goni_setup_sdhci(void) | 773 | static void goni_setup_sdhci(void) |
448 | { | 774 | { |
449 | gpio_request(GONI_EXT_FLASH_EN, "FLASH_EN"); | ||
450 | gpio_direction_output(GONI_EXT_FLASH_EN, 1); | ||
451 | |||
452 | s3c_sdhci0_set_platdata(&goni_hsmmc0_data); | 775 | s3c_sdhci0_set_platdata(&goni_hsmmc0_data); |
453 | s3c_sdhci1_set_platdata(&goni_hsmmc1_data); | 776 | s3c_sdhci1_set_platdata(&goni_hsmmc1_data); |
454 | s3c_sdhci2_set_platdata(&goni_hsmmc2_data); | 777 | s3c_sdhci2_set_platdata(&goni_hsmmc2_data); |
@@ -457,7 +780,10 @@ static void goni_setup_sdhci(void) | |||
457 | static struct platform_device *goni_devices[] __initdata = { | 780 | static struct platform_device *goni_devices[] __initdata = { |
458 | &s3c_device_fb, | 781 | &s3c_device_fb, |
459 | &s5p_device_onenand, | 782 | &s5p_device_onenand, |
783 | &goni_spi_gpio, | ||
460 | &goni_i2c_gpio_pmic, | 784 | &goni_i2c_gpio_pmic, |
785 | &goni_i2c_gpio5, | ||
786 | &mmc2_fixed_voltage, | ||
461 | &goni_device_gpiokeys, | 787 | &goni_device_gpiokeys, |
462 | &s5p_device_fimc0, | 788 | &s5p_device_fimc0, |
463 | &s5p_device_fimc1, | 789 | &s5p_device_fimc1, |
@@ -465,8 +791,24 @@ static struct platform_device *goni_devices[] __initdata = { | |||
465 | &s3c_device_hsmmc0, | 791 | &s3c_device_hsmmc0, |
466 | &s3c_device_hsmmc1, | 792 | &s3c_device_hsmmc1, |
467 | &s3c_device_hsmmc2, | 793 | &s3c_device_hsmmc2, |
794 | &s5pv210_device_iis0, | ||
795 | &s3c_device_usb_hsotg, | ||
796 | &samsung_device_keypad, | ||
797 | &s3c_device_i2c1, | ||
798 | &s3c_device_i2c2, | ||
799 | &wm8994_fixed_voltage0, | ||
800 | &wm8994_fixed_voltage1, | ||
468 | }; | 801 | }; |
469 | 802 | ||
803 | static void __init goni_sound_init(void) | ||
804 | { | ||
805 | /* Ths main clock of WM8994 codec uses the output of CLKOUT pin. | ||
806 | * The CLKOUT[9:8] set to 0x3(XUSBXTI) of 0xE010E000(OTHERS) | ||
807 | * because it needs 24MHz clock to operate WM8994 codec. | ||
808 | */ | ||
809 | __raw_writel(__raw_readl(S5P_OTHERS) | (0x3 << 8), S5P_OTHERS); | ||
810 | } | ||
811 | |||
470 | static void __init goni_map_io(void) | 812 | static void __init goni_map_io(void) |
471 | { | 813 | { |
472 | s5p_init_io(NULL, 0, S5P_VA_CHIPID); | 814 | s5p_init_io(NULL, 0, S5P_VA_CHIPID); |
@@ -476,6 +818,20 @@ static void __init goni_map_io(void) | |||
476 | 818 | ||
477 | static void __init goni_machine_init(void) | 819 | static void __init goni_machine_init(void) |
478 | { | 820 | { |
821 | /* Radio: call before I2C 1 registeration */ | ||
822 | goni_radio_init(); | ||
823 | |||
824 | /* I2C1 */ | ||
825 | s3c_i2c1_set_platdata(NULL); | ||
826 | i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs)); | ||
827 | |||
828 | /* TSP: call before I2C 2 registeration */ | ||
829 | goni_tsp_init(); | ||
830 | |||
831 | /* I2C2 */ | ||
832 | s3c_i2c2_set_platdata(&i2c2_data); | ||
833 | i2c_register_board_info(2, i2c2_devs, ARRAY_SIZE(i2c2_devs)); | ||
834 | |||
479 | /* PMIC */ | 835 | /* PMIC */ |
480 | goni_pmic_init(); | 836 | goni_pmic_init(); |
481 | i2c_register_board_info(AP_I2C_GPIO_PMIC_BUS_4, i2c_gpio_pmic_devs, | 837 | i2c_register_board_info(AP_I2C_GPIO_PMIC_BUS_4, i2c_gpio_pmic_devs, |
@@ -483,9 +839,22 @@ static void __init goni_machine_init(void) | |||
483 | /* SDHCI */ | 839 | /* SDHCI */ |
484 | goni_setup_sdhci(); | 840 | goni_setup_sdhci(); |
485 | 841 | ||
842 | /* SOUND */ | ||
843 | goni_sound_init(); | ||
844 | i2c_register_board_info(AP_I2C_GPIO_BUS_5, i2c_gpio5_devs, | ||
845 | ARRAY_SIZE(i2c_gpio5_devs)); | ||
846 | |||
486 | /* FB */ | 847 | /* FB */ |
487 | s3c_fb_set_platdata(&goni_lcd_pdata); | 848 | s3c_fb_set_platdata(&goni_lcd_pdata); |
488 | 849 | ||
850 | /* SPI */ | ||
851 | spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); | ||
852 | |||
853 | /* KEYPAD */ | ||
854 | samsung_keypad_set_platdata(&keypad_data); | ||
855 | |||
856 | clk_xusbxti.rate = 24000000; | ||
857 | |||
489 | platform_add_devices(goni_devices, ARRAY_SIZE(goni_devices)); | 858 | platform_add_devices(goni_devices, ARRAY_SIZE(goni_devices)); |
490 | } | 859 | } |
491 | 860 | ||
diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach-s5pv210/mach-smdkc110.c index cea9bca79d88..0ad7924fe62e 100644 --- a/arch/arm/mach-s5pv210/mach-smdkc110.c +++ b/arch/arm/mach-s5pv210/mach-smdkc110.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <plat/cpu.h> | 28 | #include <plat/cpu.h> |
29 | #include <plat/ata.h> | 29 | #include <plat/ata.h> |
30 | #include <plat/iic.h> | 30 | #include <plat/iic.h> |
31 | #include <plat/pm.h> | ||
31 | 32 | ||
32 | /* Following are default values for UCON, ULCON and UFCON UART registers */ | 33 | /* Following are default values for UCON, ULCON and UFCON UART registers */ |
33 | #define SMDKC110_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ | 34 | #define SMDKC110_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ |
@@ -81,6 +82,7 @@ static struct s3c_ide_platdata smdkc110_ide_pdata __initdata = { | |||
81 | static struct platform_device *smdkc110_devices[] __initdata = { | 82 | static struct platform_device *smdkc110_devices[] __initdata = { |
82 | &s5pv210_device_iis0, | 83 | &s5pv210_device_iis0, |
83 | &s5pv210_device_ac97, | 84 | &s5pv210_device_ac97, |
85 | &s5pv210_device_spdif, | ||
84 | &s3c_device_cfcon, | 86 | &s3c_device_cfcon, |
85 | &s3c_device_i2c0, | 87 | &s3c_device_i2c0, |
86 | &s3c_device_i2c1, | 88 | &s3c_device_i2c1, |
@@ -110,6 +112,8 @@ static void __init smdkc110_map_io(void) | |||
110 | 112 | ||
111 | static void __init smdkc110_machine_init(void) | 113 | static void __init smdkc110_machine_init(void) |
112 | { | 114 | { |
115 | s3c_pm_init(); | ||
116 | |||
113 | s3c_i2c0_set_platdata(NULL); | 117 | s3c_i2c0_set_platdata(NULL); |
114 | s3c_i2c1_set_platdata(NULL); | 118 | s3c_i2c1_set_platdata(NULL); |
115 | s3c_i2c2_set_platdata(NULL); | 119 | s3c_i2c2_set_platdata(NULL); |
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c index 83189ae9da9a..bcd7a5d53401 100644 --- a/arch/arm/mach-s5pv210/mach-smdkv210.c +++ b/arch/arm/mach-s5pv210/mach-smdkv210.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <plat/ata.h> | 31 | #include <plat/ata.h> |
32 | #include <plat/iic.h> | 32 | #include <plat/iic.h> |
33 | #include <plat/keypad.h> | 33 | #include <plat/keypad.h> |
34 | #include <plat/pm.h> | ||
34 | 35 | ||
35 | /* Following are default values for UCON, ULCON and UFCON UART registers */ | 36 | /* Following are default values for UCON, ULCON and UFCON UART registers */ |
36 | #define SMDKV210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ | 37 | #define SMDKV210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ |
@@ -103,6 +104,7 @@ static struct samsung_keypad_platdata smdkv210_keypad_data __initdata = { | |||
103 | static struct platform_device *smdkv210_devices[] __initdata = { | 104 | static struct platform_device *smdkv210_devices[] __initdata = { |
104 | &s5pv210_device_iis0, | 105 | &s5pv210_device_iis0, |
105 | &s5pv210_device_ac97, | 106 | &s5pv210_device_ac97, |
107 | &s5pv210_device_spdif, | ||
106 | &s3c_device_adc, | 108 | &s3c_device_adc, |
107 | &s3c_device_cfcon, | 109 | &s3c_device_cfcon, |
108 | &s3c_device_hsmmc0, | 110 | &s3c_device_hsmmc0, |
@@ -145,6 +147,8 @@ static void __init smdkv210_map_io(void) | |||
145 | 147 | ||
146 | static void __init smdkv210_machine_init(void) | 148 | static void __init smdkv210_machine_init(void) |
147 | { | 149 | { |
150 | s3c_pm_init(); | ||
151 | |||
148 | samsung_keypad_set_platdata(&smdkv210_keypad_data); | 152 | samsung_keypad_set_platdata(&smdkv210_keypad_data); |
149 | s3c24xx_ts_set_platdata(&s3c_ts_platform); | 153 | s3c24xx_ts_set_platdata(&s3c_ts_platform); |
150 | 154 | ||
diff --git a/arch/arm/mach-s5pv210/mach-torbreck.c b/arch/arm/mach-s5pv210/mach-torbreck.c new file mode 100644 index 000000000000..043c938806b0 --- /dev/null +++ b/arch/arm/mach-s5pv210/mach-torbreck.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* linux/arch/arm/mach-s5pv210/mach-torbreck.c | ||
2 | * | ||
3 | * Copyright (c) 2010 aESOP Community | ||
4 | * http://www.aesop.or.kr/ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/types.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/serial_core.h> | ||
16 | |||
17 | #include <asm/mach/arch.h> | ||
18 | #include <asm/mach/map.h> | ||
19 | #include <asm/setup.h> | ||
20 | #include <asm/mach-types.h> | ||
21 | |||
22 | #include <mach/map.h> | ||
23 | #include <mach/regs-clock.h> | ||
24 | |||
25 | #include <plat/regs-serial.h> | ||
26 | #include <plat/s5pv210.h> | ||
27 | #include <plat/devs.h> | ||
28 | #include <plat/cpu.h> | ||
29 | #include <plat/iic.h> | ||
30 | |||
31 | /* Following are default values for UCON, ULCON and UFCON UART registers */ | ||
32 | #define TORBRECK_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ | ||
33 | S3C2410_UCON_RXILEVEL | \ | ||
34 | S3C2410_UCON_TXIRQMODE | \ | ||
35 | S3C2410_UCON_RXIRQMODE | \ | ||
36 | S3C2410_UCON_RXFIFO_TOI | \ | ||
37 | S3C2443_UCON_RXERR_IRQEN) | ||
38 | |||
39 | #define TORBRECK_ULCON_DEFAULT S3C2410_LCON_CS8 | ||
40 | |||
41 | #define TORBRECK_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ | ||
42 | S5PV210_UFCON_TXTRIG4 | \ | ||
43 | S5PV210_UFCON_RXTRIG4) | ||
44 | |||
45 | static struct s3c2410_uartcfg torbreck_uartcfgs[] __initdata = { | ||
46 | [0] = { | ||
47 | .hwport = 0, | ||
48 | .flags = 0, | ||
49 | .ucon = TORBRECK_UCON_DEFAULT, | ||
50 | .ulcon = TORBRECK_ULCON_DEFAULT, | ||
51 | .ufcon = TORBRECK_UFCON_DEFAULT, | ||
52 | }, | ||
53 | [1] = { | ||
54 | .hwport = 1, | ||
55 | .flags = 0, | ||
56 | .ucon = TORBRECK_UCON_DEFAULT, | ||
57 | .ulcon = TORBRECK_ULCON_DEFAULT, | ||
58 | .ufcon = TORBRECK_UFCON_DEFAULT, | ||
59 | }, | ||
60 | [2] = { | ||
61 | .hwport = 2, | ||
62 | .flags = 0, | ||
63 | .ucon = TORBRECK_UCON_DEFAULT, | ||
64 | .ulcon = TORBRECK_ULCON_DEFAULT, | ||
65 | .ufcon = TORBRECK_UFCON_DEFAULT, | ||
66 | }, | ||
67 | [3] = { | ||
68 | .hwport = 3, | ||
69 | .flags = 0, | ||
70 | .ucon = TORBRECK_UCON_DEFAULT, | ||
71 | .ulcon = TORBRECK_ULCON_DEFAULT, | ||
72 | .ufcon = TORBRECK_UFCON_DEFAULT, | ||
73 | }, | ||
74 | }; | ||
75 | |||
76 | static struct platform_device *torbreck_devices[] __initdata = { | ||
77 | &s5pv210_device_iis0, | ||
78 | &s3c_device_cfcon, | ||
79 | &s3c_device_hsmmc0, | ||
80 | &s3c_device_hsmmc1, | ||
81 | &s3c_device_hsmmc2, | ||
82 | &s3c_device_hsmmc3, | ||
83 | &s3c_device_i2c0, | ||
84 | &s3c_device_i2c1, | ||
85 | &s3c_device_i2c2, | ||
86 | &s3c_device_rtc, | ||
87 | &s3c_device_wdt, | ||
88 | }; | ||
89 | |||
90 | static struct i2c_board_info torbreck_i2c_devs0[] __initdata = { | ||
91 | /* To Be Updated */ | ||
92 | }; | ||
93 | |||
94 | static struct i2c_board_info torbreck_i2c_devs1[] __initdata = { | ||
95 | /* To Be Updated */ | ||
96 | }; | ||
97 | |||
98 | static struct i2c_board_info torbreck_i2c_devs2[] __initdata = { | ||
99 | /* To Be Updated */ | ||
100 | }; | ||
101 | |||
102 | static void __init torbreck_map_io(void) | ||
103 | { | ||
104 | s5p_init_io(NULL, 0, S5P_VA_CHIPID); | ||
105 | s3c24xx_init_clocks(24000000); | ||
106 | s3c24xx_init_uarts(torbreck_uartcfgs, ARRAY_SIZE(torbreck_uartcfgs)); | ||
107 | } | ||
108 | |||
109 | static void __init torbreck_machine_init(void) | ||
110 | { | ||
111 | s3c_i2c0_set_platdata(NULL); | ||
112 | s3c_i2c1_set_platdata(NULL); | ||
113 | s3c_i2c2_set_platdata(NULL); | ||
114 | i2c_register_board_info(0, torbreck_i2c_devs0, | ||
115 | ARRAY_SIZE(torbreck_i2c_devs0)); | ||
116 | i2c_register_board_info(1, torbreck_i2c_devs1, | ||
117 | ARRAY_SIZE(torbreck_i2c_devs1)); | ||
118 | i2c_register_board_info(2, torbreck_i2c_devs2, | ||
119 | ARRAY_SIZE(torbreck_i2c_devs2)); | ||
120 | |||
121 | platform_add_devices(torbreck_devices, ARRAY_SIZE(torbreck_devices)); | ||
122 | } | ||
123 | |||
124 | MACHINE_START(TORBRECK, "TORBRECK") | ||
125 | /* Maintainer: Hyunchul Ko <ghcstop@gmail.com> */ | ||
126 | .boot_params = S5P_PA_SDRAM + 0x100, | ||
127 | .init_irq = s5pv210_init_irq, | ||
128 | .map_io = torbreck_map_io, | ||
129 | .init_machine = torbreck_machine_init, | ||
130 | .timer = &s3c24xx_timer, | ||
131 | MACHINE_END | ||
diff --git a/arch/arm/mach-s5pv210/pm.c b/arch/arm/mach-s5pv210/pm.c new file mode 100644 index 000000000000..549d7924fd4c --- /dev/null +++ b/arch/arm/mach-s5pv210/pm.c | |||
@@ -0,0 +1,166 @@ | |||
1 | /* linux/arch/arm/mach-s5pv210/pm.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * S5PV210 - Power Management support | ||
7 | * | ||
8 | * Based on arch/arm/mach-s3c2410/pm.c | ||
9 | * Copyright (c) 2006 Simtec Electronics | ||
10 | * Ben Dooks <ben@simtec.co.uk> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | */ | ||
16 | |||
17 | #include <linux/init.h> | ||
18 | #include <linux/suspend.h> | ||
19 | #include <linux/io.h> | ||
20 | |||
21 | #include <plat/cpu.h> | ||
22 | #include <plat/pm.h> | ||
23 | #include <plat/regs-timer.h> | ||
24 | |||
25 | #include <mach/regs-irq.h> | ||
26 | #include <mach/regs-clock.h> | ||
27 | |||
28 | static struct sleep_save s5pv210_core_save[] = { | ||
29 | /* Clock source */ | ||
30 | SAVE_ITEM(S5P_CLK_SRC0), | ||
31 | SAVE_ITEM(S5P_CLK_SRC1), | ||
32 | SAVE_ITEM(S5P_CLK_SRC2), | ||
33 | SAVE_ITEM(S5P_CLK_SRC3), | ||
34 | SAVE_ITEM(S5P_CLK_SRC4), | ||
35 | SAVE_ITEM(S5P_CLK_SRC5), | ||
36 | SAVE_ITEM(S5P_CLK_SRC6), | ||
37 | |||
38 | /* Clock source Mask */ | ||
39 | SAVE_ITEM(S5P_CLK_SRC_MASK0), | ||
40 | SAVE_ITEM(S5P_CLK_SRC_MASK1), | ||
41 | |||
42 | /* Clock Divider */ | ||
43 | SAVE_ITEM(S5P_CLK_DIV0), | ||
44 | SAVE_ITEM(S5P_CLK_DIV1), | ||
45 | SAVE_ITEM(S5P_CLK_DIV2), | ||
46 | SAVE_ITEM(S5P_CLK_DIV3), | ||
47 | SAVE_ITEM(S5P_CLK_DIV4), | ||
48 | SAVE_ITEM(S5P_CLK_DIV5), | ||
49 | SAVE_ITEM(S5P_CLK_DIV6), | ||
50 | SAVE_ITEM(S5P_CLK_DIV7), | ||
51 | |||
52 | /* Clock Main Gate */ | ||
53 | SAVE_ITEM(S5P_CLKGATE_MAIN0), | ||
54 | SAVE_ITEM(S5P_CLKGATE_MAIN1), | ||
55 | SAVE_ITEM(S5P_CLKGATE_MAIN2), | ||
56 | |||
57 | /* Clock source Peri Gate */ | ||
58 | SAVE_ITEM(S5P_CLKGATE_PERI0), | ||
59 | SAVE_ITEM(S5P_CLKGATE_PERI1), | ||
60 | |||
61 | /* Clock source SCLK Gate */ | ||
62 | SAVE_ITEM(S5P_CLKGATE_SCLK0), | ||
63 | SAVE_ITEM(S5P_CLKGATE_SCLK1), | ||
64 | |||
65 | /* Clock IP Clock gate */ | ||
66 | SAVE_ITEM(S5P_CLKGATE_IP0), | ||
67 | SAVE_ITEM(S5P_CLKGATE_IP1), | ||
68 | SAVE_ITEM(S5P_CLKGATE_IP2), | ||
69 | SAVE_ITEM(S5P_CLKGATE_IP3), | ||
70 | SAVE_ITEM(S5P_CLKGATE_IP4), | ||
71 | |||
72 | /* Clock Blcok and Bus gate */ | ||
73 | SAVE_ITEM(S5P_CLKGATE_BLOCK), | ||
74 | SAVE_ITEM(S5P_CLKGATE_BUS0), | ||
75 | |||
76 | /* Clock ETC */ | ||
77 | SAVE_ITEM(S5P_CLK_OUT), | ||
78 | SAVE_ITEM(S5P_MDNIE_SEL), | ||
79 | |||
80 | /* PWM Register */ | ||
81 | SAVE_ITEM(S3C2410_TCFG0), | ||
82 | SAVE_ITEM(S3C2410_TCFG1), | ||
83 | SAVE_ITEM(S3C64XX_TINT_CSTAT), | ||
84 | SAVE_ITEM(S3C2410_TCON), | ||
85 | SAVE_ITEM(S3C2410_TCNTB(0)), | ||
86 | SAVE_ITEM(S3C2410_TCMPB(0)), | ||
87 | SAVE_ITEM(S3C2410_TCNTO(0)), | ||
88 | }; | ||
89 | |||
90 | void s5pv210_cpu_suspend(void) | ||
91 | { | ||
92 | unsigned long tmp; | ||
93 | |||
94 | /* issue the standby signal into the pm unit. Note, we | ||
95 | * issue a write-buffer drain just in case */ | ||
96 | |||
97 | tmp = 0; | ||
98 | |||
99 | asm("b 1f\n\t" | ||
100 | ".align 5\n\t" | ||
101 | "1:\n\t" | ||
102 | "mcr p15, 0, %0, c7, c10, 5\n\t" | ||
103 | "mcr p15, 0, %0, c7, c10, 4\n\t" | ||
104 | "wfi" : : "r" (tmp)); | ||
105 | |||
106 | /* we should never get past here */ | ||
107 | panic("sleep resumed to originator?"); | ||
108 | } | ||
109 | |||
110 | static void s5pv210_pm_prepare(void) | ||
111 | { | ||
112 | unsigned int tmp; | ||
113 | |||
114 | /* ensure at least INFORM0 has the resume address */ | ||
115 | __raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0); | ||
116 | |||
117 | tmp = __raw_readl(S5P_SLEEP_CFG); | ||
118 | tmp &= ~(S5P_SLEEP_CFG_OSC_EN | S5P_SLEEP_CFG_USBOSC_EN); | ||
119 | __raw_writel(tmp, S5P_SLEEP_CFG); | ||
120 | |||
121 | /* WFI for SLEEP mode configuration by SYSCON */ | ||
122 | tmp = __raw_readl(S5P_PWR_CFG); | ||
123 | tmp &= S5P_CFG_WFI_CLEAN; | ||
124 | tmp |= S5P_CFG_WFI_SLEEP; | ||
125 | __raw_writel(tmp, S5P_PWR_CFG); | ||
126 | |||
127 | /* SYSCON interrupt handling disable */ | ||
128 | tmp = __raw_readl(S5P_OTHERS); | ||
129 | tmp |= S5P_OTHER_SYSC_INTOFF; | ||
130 | __raw_writel(tmp, S5P_OTHERS); | ||
131 | |||
132 | s3c_pm_do_save(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save)); | ||
133 | } | ||
134 | |||
135 | static int s5pv210_pm_add(struct sys_device *sysdev) | ||
136 | { | ||
137 | pm_cpu_prep = s5pv210_pm_prepare; | ||
138 | pm_cpu_sleep = s5pv210_cpu_suspend; | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | static int s5pv210_pm_resume(struct sys_device *dev) | ||
144 | { | ||
145 | u32 tmp; | ||
146 | |||
147 | tmp = __raw_readl(S5P_OTHERS); | ||
148 | tmp |= (S5P_OTHERS_RET_IO | S5P_OTHERS_RET_CF |\ | ||
149 | S5P_OTHERS_RET_MMC | S5P_OTHERS_RET_UART); | ||
150 | __raw_writel(tmp , S5P_OTHERS); | ||
151 | |||
152 | s3c_pm_do_restore_core(s5pv210_core_save, ARRAY_SIZE(s5pv210_core_save)); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static struct sysdev_driver s5pv210_pm_driver = { | ||
158 | .add = s5pv210_pm_add, | ||
159 | .resume = s5pv210_pm_resume, | ||
160 | }; | ||
161 | |||
162 | static __init int s5pv210_pm_drvinit(void) | ||
163 | { | ||
164 | return sysdev_driver_register(&s5pv210_sysclass, &s5pv210_pm_driver); | ||
165 | } | ||
166 | arch_initcall(s5pv210_pm_drvinit); | ||
diff --git a/arch/arm/mach-s5pv210/setup-fb-24bpp.c b/arch/arm/mach-s5pv210/setup-fb-24bpp.c index 928cf1f125fa..e932ebfac56d 100644 --- a/arch/arm/mach-s5pv210/setup-fb-24bpp.c +++ b/arch/arm/mach-s5pv210/setup-fb-24bpp.c | |||
@@ -21,33 +21,21 @@ | |||
21 | #include <mach/regs-clock.h> | 21 | #include <mach/regs-clock.h> |
22 | #include <plat/gpio-cfg.h> | 22 | #include <plat/gpio-cfg.h> |
23 | 23 | ||
24 | void s5pv210_fb_gpio_setup_24bpp(void) | 24 | static void s5pv210_fb_cfg_gpios(unsigned int base, unsigned int nr) |
25 | { | 25 | { |
26 | unsigned int gpio = 0; | 26 | s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(2)); |
27 | |||
28 | for (gpio = S5PV210_GPF0(0); gpio <= S5PV210_GPF0(7); gpio++) { | ||
29 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
30 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
31 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
32 | } | ||
33 | 27 | ||
34 | for (gpio = S5PV210_GPF1(0); gpio <= S5PV210_GPF1(7); gpio++) { | 28 | for (; nr > 0; nr--, base++) |
35 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | 29 | s5p_gpio_set_drvstr(base, S5P_GPIO_DRVSTR_LV4); |
36 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | 30 | } |
37 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
38 | } | ||
39 | 31 | ||
40 | for (gpio = S5PV210_GPF2(0); gpio <= S5PV210_GPF2(7); gpio++) { | ||
41 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
42 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
43 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
44 | } | ||
45 | 32 | ||
46 | for (gpio = S5PV210_GPF3(0); gpio <= S5PV210_GPF3(3); gpio++) { | 33 | void s5pv210_fb_gpio_setup_24bpp(void) |
47 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | 34 | { |
48 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | 35 | s5pv210_fb_cfg_gpios(S5PV210_GPF0(0), 8); |
49 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | 36 | s5pv210_fb_cfg_gpios(S5PV210_GPF1(0), 8); |
50 | } | 37 | s5pv210_fb_cfg_gpios(S5PV210_GPF2(0), 8); |
38 | s5pv210_fb_cfg_gpios(S5PV210_GPF3(0), 4); | ||
51 | 39 | ||
52 | /* Set DISPLAY_CONTROL register for Display path selection. | 40 | /* Set DISPLAY_CONTROL register for Display path selection. |
53 | * | 41 | * |
diff --git a/arch/arm/mach-s5pv210/setup-i2c0.c b/arch/arm/mach-s5pv210/setup-i2c0.c index d38f7cb7e662..0f1cc3a1c1e8 100644 --- a/arch/arm/mach-s5pv210/setup-i2c0.c +++ b/arch/arm/mach-s5pv210/setup-i2c0.c | |||
@@ -23,8 +23,6 @@ struct platform_device; /* don't need the contents */ | |||
23 | 23 | ||
24 | void s3c_i2c0_cfg_gpio(struct platform_device *dev) | 24 | void s3c_i2c0_cfg_gpio(struct platform_device *dev) |
25 | { | 25 | { |
26 | s3c_gpio_cfgpin(S5PV210_GPD1(0), S3C_GPIO_SFN(2)); | 26 | s3c_gpio_cfgall_range(S5PV210_GPD1(0), 2, |
27 | s3c_gpio_setpull(S5PV210_GPD1(0), S3C_GPIO_PULL_UP); | 27 | S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); |
28 | s3c_gpio_cfgpin(S5PV210_GPD1(1), S3C_GPIO_SFN(2)); | ||
29 | s3c_gpio_setpull(S5PV210_GPD1(1), S3C_GPIO_PULL_UP); | ||
30 | } | 28 | } |
diff --git a/arch/arm/mach-s5pv210/setup-i2c1.c b/arch/arm/mach-s5pv210/setup-i2c1.c index 148bb7857d89..f61365a34c56 100644 --- a/arch/arm/mach-s5pv210/setup-i2c1.c +++ b/arch/arm/mach-s5pv210/setup-i2c1.c | |||
@@ -23,8 +23,6 @@ struct platform_device; /* don't need the contents */ | |||
23 | 23 | ||
24 | void s3c_i2c1_cfg_gpio(struct platform_device *dev) | 24 | void s3c_i2c1_cfg_gpio(struct platform_device *dev) |
25 | { | 25 | { |
26 | s3c_gpio_cfgpin(S5PV210_GPD1(2), S3C_GPIO_SFN(2)); | 26 | s3c_gpio_cfgall_range(S5PV210_GPD1(2), 2, |
27 | s3c_gpio_setpull(S5PV210_GPD1(2), S3C_GPIO_PULL_UP); | 27 | S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); |
28 | s3c_gpio_cfgpin(S5PV210_GPD1(3), S3C_GPIO_SFN(2)); | ||
29 | s3c_gpio_setpull(S5PV210_GPD1(3), S3C_GPIO_PULL_UP); | ||
30 | } | 28 | } |
diff --git a/arch/arm/mach-s5pv210/setup-i2c2.c b/arch/arm/mach-s5pv210/setup-i2c2.c index 2396cb8c373e..2f91b5cefbc6 100644 --- a/arch/arm/mach-s5pv210/setup-i2c2.c +++ b/arch/arm/mach-s5pv210/setup-i2c2.c | |||
@@ -23,8 +23,6 @@ struct platform_device; /* don't need the contents */ | |||
23 | 23 | ||
24 | void s3c_i2c2_cfg_gpio(struct platform_device *dev) | 24 | void s3c_i2c2_cfg_gpio(struct platform_device *dev) |
25 | { | 25 | { |
26 | s3c_gpio_cfgpin(S5PV210_GPD1(4), S3C_GPIO_SFN(2)); | 26 | s3c_gpio_cfgall_range(S5PV210_GPD1(4), 2, |
27 | s3c_gpio_setpull(S5PV210_GPD1(4), S3C_GPIO_PULL_UP); | 27 | S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); |
28 | s3c_gpio_cfgpin(S5PV210_GPD1(5), S3C_GPIO_SFN(2)); | ||
29 | s3c_gpio_setpull(S5PV210_GPD1(5), S3C_GPIO_PULL_UP); | ||
30 | } | 28 | } |
diff --git a/arch/arm/mach-s5pv210/setup-ide.c b/arch/arm/mach-s5pv210/setup-ide.c index b558b1cc8d60..ea123d546bd2 100644 --- a/arch/arm/mach-s5pv210/setup-ide.c +++ b/arch/arm/mach-s5pv210/setup-ide.c | |||
@@ -15,36 +15,25 @@ | |||
15 | 15 | ||
16 | #include <plat/gpio-cfg.h> | 16 | #include <plat/gpio-cfg.h> |
17 | 17 | ||
18 | static void s5pv210_ide_cfg_gpios(unsigned int base, unsigned int nr) | ||
19 | { | ||
20 | s3c_gpio_cfgrange_nopull(base, nr, S3C_GPIO_SFN(4)); | ||
21 | |||
22 | for (; nr > 0; nr--, base++) | ||
23 | s5p_gpio_set_drvstr(base, S5P_GPIO_DRVSTR_LV4); | ||
24 | } | ||
25 | |||
18 | void s5pv210_ide_setup_gpio(void) | 26 | void s5pv210_ide_setup_gpio(void) |
19 | { | 27 | { |
20 | unsigned int gpio = 0; | 28 | /* CF_Add[0 - 2], CF_IORDY, CF_INTRQ, CF_DMARQ, CF_DMARST, CF_DMACK */ |
21 | 29 | s5pv210_ide_cfg_gpios(S5PV210_GPJ0(0), 8); | |
22 | for (gpio = S5PV210_GPJ0(0); gpio <= S5PV210_GPJ0(7); gpio++) { | 30 | |
23 | /* CF_Add[0 - 2], CF_IORDY, CF_INTRQ, CF_DMARQ, CF_DMARST, | 31 | /* CF_Data[0 - 7] */ |
24 | CF_DMACK */ | 32 | s5pv210_ide_cfg_gpios(S5PV210_GPJ2(0), 8); |
25 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4)); | 33 | |
26 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | 34 | /* CF_Data[8 - 15] */ |
27 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | 35 | s5pv210_ide_cfg_gpios(S5PV210_GPJ3(0), 8); |
28 | } | 36 | |
29 | 37 | /* CF_CS0, CF_CS1, CF_IORD, CF_IOWR */ | |
30 | for (gpio = S5PV210_GPJ2(0); gpio <= S5PV210_GPJ2(7); gpio++) { | 38 | s5pv210_ide_cfg_gpios(S5PV210_GPJ4(0), 4); |
31 | /*CF_Data[0 - 7] */ | ||
32 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4)); | ||
33 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
34 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
35 | } | ||
36 | |||
37 | for (gpio = S5PV210_GPJ3(0); gpio <= S5PV210_GPJ3(7); gpio++) { | ||
38 | /* CF_Data[8 - 15] */ | ||
39 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4)); | ||
40 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
41 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
42 | } | ||
43 | |||
44 | for (gpio = S5PV210_GPJ4(0); gpio <= S5PV210_GPJ4(3); gpio++) { | ||
45 | /* CF_CS0, CF_CS1, CF_IORD, CF_IOWR */ | ||
46 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4)); | ||
47 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
48 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
49 | } | ||
50 | } | 39 | } |
diff --git a/arch/arm/mach-s5pv210/setup-keypad.c b/arch/arm/mach-s5pv210/setup-keypad.c index 37b2790aafc3..c56420a52f48 100644 --- a/arch/arm/mach-s5pv210/setup-keypad.c +++ b/arch/arm/mach-s5pv210/setup-keypad.c | |||
@@ -16,19 +16,9 @@ | |||
16 | 16 | ||
17 | void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols) | 17 | void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols) |
18 | { | 18 | { |
19 | unsigned int gpio, end; | ||
20 | |||
21 | /* Set all the necessary GPH3 pins to special-function 3: KP_ROW[x] */ | 19 | /* Set all the necessary GPH3 pins to special-function 3: KP_ROW[x] */ |
22 | end = S5PV210_GPH3(rows); | 20 | s3c_gpio_cfgrange_nopull(S5PV210_GPH3(0), rows, S3C_GPIO_SFN(3)); |
23 | for (gpio = S5PV210_GPH3(0); gpio < end; gpio++) { | ||
24 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); | ||
25 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
26 | } | ||
27 | 21 | ||
28 | /* Set all the necessary GPH2 pins to special-function 3: KP_COL[x] */ | 22 | /* Set all the necessary GPH2 pins to special-function 3: KP_COL[x] */ |
29 | end = S5PV210_GPH2(cols); | 23 | s3c_gpio_cfgrange_nopull(S5PV210_GPH2(0), cols, S3C_GPIO_SFN(3)); |
30 | for (gpio = S5PV210_GPH2(0); gpio < end; gpio++) { | ||
31 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); | ||
32 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
33 | } | ||
34 | } | 24 | } |
diff --git a/arch/arm/mach-s5pv210/setup-sdhci-gpio.c b/arch/arm/mach-s5pv210/setup-sdhci-gpio.c index b18587b1ec58..746777d56df9 100644 --- a/arch/arm/mach-s5pv210/setup-sdhci-gpio.c +++ b/arch/arm/mach-s5pv210/setup-sdhci-gpio.c | |||
@@ -26,26 +26,17 @@ | |||
26 | void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) | 26 | void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) |
27 | { | 27 | { |
28 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; | 28 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; |
29 | unsigned int gpio; | ||
30 | 29 | ||
31 | /* Set all the necessary GPG0/GPG1 pins to special-function 2 */ | 30 | /* Set all the necessary GPG0/GPG1 pins to special-function 2 */ |
32 | for (gpio = S5PV210_GPG0(0); gpio < S5PV210_GPG0(2); gpio++) { | 31 | s3c_gpio_cfgrange_nopull(S5PV210_GPG0(0), 2, S3C_GPIO_SFN(2)); |
33 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | 32 | |
34 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
35 | } | ||
36 | switch (width) { | 33 | switch (width) { |
37 | case 8: | 34 | case 8: |
38 | /* GPG1[3:6] special-funtion 3 */ | 35 | /* GPG1[3:6] special-funtion 3 */ |
39 | for (gpio = S5PV210_GPG1(3); gpio <= S5PV210_GPG1(6); gpio++) { | 36 | s3c_gpio_cfgrange_nopull(S5PV210_GPG1(3), 4, S3C_GPIO_SFN(3)); |
40 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); | ||
41 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
42 | } | ||
43 | case 4: | 37 | case 4: |
44 | /* GPG0[3:6] special-funtion 2 */ | 38 | /* GPG0[3:6] special-funtion 2 */ |
45 | for (gpio = S5PV210_GPG0(3); gpio <= S5PV210_GPG0(6); gpio++) { | 39 | s3c_gpio_cfgrange_nopull(S5PV210_GPG0(3), 4, S3C_GPIO_SFN(2)); |
46 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
47 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
48 | } | ||
49 | default: | 40 | default: |
50 | break; | 41 | break; |
51 | } | 42 | } |
@@ -59,19 +50,12 @@ void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) | |||
59 | void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) | 50 | void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) |
60 | { | 51 | { |
61 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; | 52 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; |
62 | unsigned int gpio; | ||
63 | 53 | ||
64 | /* Set all the necessary GPG1[0:1] pins to special-function 2 */ | 54 | /* Set all the necessary GPG1[0:1] pins to special-function 2 */ |
65 | for (gpio = S5PV210_GPG1(0); gpio < S5PV210_GPG1(2); gpio++) { | 55 | s3c_gpio_cfgrange_nopull(S5PV210_GPG1(0), 2, S3C_GPIO_SFN(2)); |
66 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
67 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
68 | } | ||
69 | 56 | ||
70 | /* Data pin GPG1[3:6] to special-function 2 */ | 57 | /* Data pin GPG1[3:6] to special-function 2 */ |
71 | for (gpio = S5PV210_GPG1(3); gpio <= S5PV210_GPG1(6); gpio++) { | 58 | s3c_gpio_cfgrange_nopull(S5PV210_GPG1(3), 4, S3C_GPIO_SFN(2)); |
72 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
73 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
74 | } | ||
75 | 59 | ||
76 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { | 60 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { |
77 | s3c_gpio_setpull(S5PV210_GPG1(2), S3C_GPIO_PULL_UP); | 61 | s3c_gpio_setpull(S5PV210_GPG1(2), S3C_GPIO_PULL_UP); |
@@ -82,27 +66,17 @@ void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) | |||
82 | void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) | 66 | void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) |
83 | { | 67 | { |
84 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; | 68 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; |
85 | unsigned int gpio; | ||
86 | 69 | ||
87 | /* Set all the necessary GPG2[0:1] pins to special-function 2 */ | 70 | /* Set all the necessary GPG2[0:1] pins to special-function 2 */ |
88 | for (gpio = S5PV210_GPG2(0); gpio < S5PV210_GPG2(2); gpio++) { | 71 | s3c_gpio_cfgrange_nopull(S5PV210_GPG2(0), 2, S3C_GPIO_SFN(2)); |
89 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
90 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
91 | } | ||
92 | 72 | ||
93 | switch (width) { | 73 | switch (width) { |
94 | case 8: | 74 | case 8: |
95 | /* Data pin GPG3[3:6] to special-function 3 */ | 75 | /* Data pin GPG3[3:6] to special-function 3 */ |
96 | for (gpio = S5PV210_GPG3(3); gpio <= S5PV210_GPG3(6); gpio++) { | 76 | s3c_gpio_cfgrange_nopull(S5PV210_GPG3(3), 4, S3C_GPIO_SFN(3)); |
97 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); | ||
98 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
99 | } | ||
100 | case 4: | 77 | case 4: |
101 | /* Data pin GPG2[3:6] to special-function 2 */ | 78 | /* Data pin GPG2[3:6] to special-function 2 */ |
102 | for (gpio = S5PV210_GPG2(3); gpio <= S5PV210_GPG2(6); gpio++) { | 79 | s3c_gpio_cfgrange_nopull(S5PV210_GPG2(3), 4, S3C_GPIO_SFN(2)); |
103 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
104 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
105 | } | ||
106 | default: | 80 | default: |
107 | break; | 81 | break; |
108 | } | 82 | } |
@@ -116,19 +90,12 @@ void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) | |||
116 | void s5pv210_setup_sdhci3_cfg_gpio(struct platform_device *dev, int width) | 90 | void s5pv210_setup_sdhci3_cfg_gpio(struct platform_device *dev, int width) |
117 | { | 91 | { |
118 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; | 92 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; |
119 | unsigned int gpio; | ||
120 | 93 | ||
121 | /* Set all the necessary GPG3[0:2] pins to special-function 2 */ | 94 | /* Set all the necessary GPG3[0:1] pins to special-function 2 */ |
122 | for (gpio = S5PV210_GPG3(0); gpio < S5PV210_GPG3(2); gpio++) { | 95 | s3c_gpio_cfgrange_nopull(S5PV210_GPG3(0), 2, S3C_GPIO_SFN(2)); |
123 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
124 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
125 | } | ||
126 | 96 | ||
127 | /* Data pin GPG3[3:6] to special-function 2 */ | 97 | /* Data pin GPG3[3:6] to special-function 2 */ |
128 | for (gpio = S5PV210_GPG3(3); gpio <= S5PV210_GPG3(6); gpio++) { | 98 | s3c_gpio_cfgrange_nopull(S5PV210_GPG3(3), 4, S3C_GPIO_SFN(2)); |
129 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
130 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
131 | } | ||
132 | 99 | ||
133 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { | 100 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { |
134 | s3c_gpio_setpull(S5PV210_GPG3(2), S3C_GPIO_PULL_UP); | 101 | s3c_gpio_setpull(S5PV210_GPG3(2), S3C_GPIO_PULL_UP); |
diff --git a/arch/arm/mach-s5pv210/sleep.S b/arch/arm/mach-s5pv210/sleep.S new file mode 100644 index 000000000000..d4d222b716b4 --- /dev/null +++ b/arch/arm/mach-s5pv210/sleep.S | |||
@@ -0,0 +1,170 @@ | |||
1 | /* linux/arch/arm/plat-s5p/sleep.S | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * S5PV210 power Manager (Suspend-To-RAM) support | ||
7 | * Based on S3C2410 sleep code by: | ||
8 | * Ben Dooks, (c) 2004 Simtec Electronics | ||
9 | * | ||
10 | * Based on PXA/SA1100 sleep code by: | ||
11 | * Nicolas Pitre, (c) 2002 Monta Vista Software Inc | ||
12 | * Cliff Brake, (c) 2001 | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
27 | */ | ||
28 | |||
29 | #include <linux/linkage.h> | ||
30 | #include <asm/assembler.h> | ||
31 | #include <asm/memory.h> | ||
32 | |||
33 | .text | ||
34 | |||
35 | /* s3c_cpu_save | ||
36 | * | ||
37 | * entry: | ||
38 | * r0 = save address (virtual addr of s3c_sleep_save_phys) | ||
39 | */ | ||
40 | |||
41 | ENTRY(s3c_cpu_save) | ||
42 | |||
43 | stmfd sp!, { r3 - r12, lr } | ||
44 | |||
45 | mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID | ||
46 | mrc p15, 0, r5, c3, c0, 0 @ Domain ID | ||
47 | mrc p15, 0, r6, c2, c0, 0 @ Translation Table BASE0 | ||
48 | mrc p15, 0, r7, c2, c0, 1 @ Translation Table BASE1 | ||
49 | mrc p15, 0, r8, c2, c0, 2 @ Translation Table Control | ||
50 | mrc p15, 0, r9, c1, c0, 0 @ Control register | ||
51 | mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register | ||
52 | mrc p15, 0, r11, c1, c0, 2 @ Co-processor access controls | ||
53 | mrc p15, 0, r12, c10, c2, 0 @ Read PRRR | ||
54 | mrc p15, 0, r3, c10, c2, 1 @ READ NMRR | ||
55 | |||
56 | stmia r0, { r3 - r13 } | ||
57 | |||
58 | bl s3c_pm_cb_flushcache | ||
59 | |||
60 | ldr r0, =pm_cpu_sleep | ||
61 | ldr r0, [ r0 ] | ||
62 | mov pc, r0 | ||
63 | |||
64 | resume_with_mmu: | ||
65 | /* | ||
66 | * After MMU is turned on, restore the previous MMU table. | ||
67 | */ | ||
68 | ldr r9 , =(PAGE_OFFSET - PHYS_OFFSET) | ||
69 | add r4, r4, r9 | ||
70 | str r12, [r4] | ||
71 | |||
72 | ldmfd sp!, { r3 - r12, pc } | ||
73 | |||
74 | .ltorg | ||
75 | |||
76 | .data | ||
77 | |||
78 | .global s3c_sleep_save_phys | ||
79 | s3c_sleep_save_phys: | ||
80 | .word 0 | ||
81 | |||
82 | /* sleep magic, to allow the bootloader to check for an valid | ||
83 | * image to resume to. Must be the first word before the | ||
84 | * s3c_cpu_resume entry. | ||
85 | */ | ||
86 | |||
87 | .word 0x2bedf00d | ||
88 | |||
89 | /* s3c_cpu_resume | ||
90 | * | ||
91 | * resume code entry for bootloader to call | ||
92 | * | ||
93 | * we must put this code here in the data segment as we have no | ||
94 | * other way of restoring the stack pointer after sleep, and we | ||
95 | * must not write to the code segment (code is read-only) | ||
96 | */ | ||
97 | |||
98 | ENTRY(s3c_cpu_resume) | ||
99 | mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE | ||
100 | msr cpsr_c, r0 | ||
101 | |||
102 | mov r1, #0 | ||
103 | mcr p15, 0, r1, c8, c7, 0 @ invalidate TLBs | ||
104 | mcr p15, 0, r1, c7, c5, 0 @ invalidate I Cache | ||
105 | |||
106 | ldr r0, s3c_sleep_save_phys @ address of restore block | ||
107 | ldmia r0, { r3 - r13 } | ||
108 | |||
109 | mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID | ||
110 | mcr p15, 0, r5, c3, c0, 0 @ Domain ID | ||
111 | |||
112 | mcr p15, 0, r8, c2, c0, 2 @ Translation Table Control | ||
113 | mcr p15, 0, r7, c2, c0, 1 @ Translation Table BASE1 | ||
114 | mcr p15, 0, r6, c2, c0, 0 @ Translation Table BASE0 | ||
115 | |||
116 | mcr p15, 0, r10, c1, c0, 1 @ Auxiliary control register | ||
117 | |||
118 | mov r0, #0 | ||
119 | mcr p15, 0, r0, c8, c7, 0 @ Invalidate I & D TLB | ||
120 | |||
121 | mov r0, #0 @ restore copro access | ||
122 | mcr p15, 0, r11, c1, c0, 2 @ Co-processor access | ||
123 | mcr p15, 0, r0, c7, c5, 4 | ||
124 | |||
125 | mcr p15, 0, r12, c10, c2, 0 @ write PRRR | ||
126 | mcr p15, 0, r3, c10, c2, 1 @ write NMRR | ||
127 | |||
128 | /* | ||
129 | * In Cortex-A8, when MMU is turned on, the pipeline is flushed. | ||
130 | * And there are no valid entries in the MMU table at this point. | ||
131 | * So before turning on the MMU, the MMU entry for the DRAM address | ||
132 | * range is added. After the MMU is turned on, the other entries | ||
133 | * in the MMU table will be restored. | ||
134 | */ | ||
135 | |||
136 | /* r6 = Translation Table BASE0 */ | ||
137 | mov r4, r6 | ||
138 | mov r4, r4, LSR #14 | ||
139 | mov r4, r4, LSL #14 | ||
140 | |||
141 | /* Load address for adding to MMU table list */ | ||
142 | ldr r11, =0xE010F000 @ INFORM0 reg. | ||
143 | ldr r10, [r11, #0] | ||
144 | mov r10, r10, LSR #18 | ||
145 | bic r10, r10, #0x3 | ||
146 | orr r4, r4, r10 | ||
147 | |||
148 | /* Calculate MMU table entry */ | ||
149 | mov r10, r10, LSL #18 | ||
150 | ldr r5, =0x40E | ||
151 | orr r10, r10, r5 | ||
152 | |||
153 | /* Back up originally data */ | ||
154 | ldr r12, [r4] | ||
155 | |||
156 | /* Add calculated MMU table entry into MMU table list */ | ||
157 | str r10, [r4] | ||
158 | |||
159 | ldr r2, =resume_with_mmu | ||
160 | mcr p15, 0, r9, c1, c0, 0 @ turn on MMU, etc | ||
161 | |||
162 | nop | ||
163 | nop | ||
164 | nop | ||
165 | nop | ||
166 | nop @ second-to-last before mmu | ||
167 | |||
168 | mov pc, r2 @ go back to virtual address | ||
169 | |||
170 | .ltorg | ||
diff --git a/arch/arm/mach-s5pv310/Kconfig b/arch/arm/mach-s5pv310/Kconfig index 331b5bd97aba..1150b360f38c 100644 --- a/arch/arm/mach-s5pv310/Kconfig +++ b/arch/arm/mach-s5pv310/Kconfig | |||
@@ -11,7 +11,6 @@ if ARCH_S5PV310 | |||
11 | 11 | ||
12 | config CPU_S5PV310 | 12 | config CPU_S5PV310 |
13 | bool | 13 | bool |
14 | select PLAT_S5P | ||
15 | help | 14 | help |
16 | Enable S5PV310 CPU support | 15 | Enable S5PV310 CPU support |
17 | 16 | ||
@@ -25,21 +24,105 @@ config S5PV310_SETUP_I2C2 | |||
25 | help | 24 | help |
26 | Common setup code for i2c bus 2. | 25 | Common setup code for i2c bus 2. |
27 | 26 | ||
27 | config S5PV310_SETUP_I2C3 | ||
28 | bool | ||
29 | help | ||
30 | Common setup code for i2c bus 3. | ||
31 | |||
32 | config S5PV310_SETUP_I2C4 | ||
33 | bool | ||
34 | help | ||
35 | Common setup code for i2c bus 4. | ||
36 | |||
37 | config S5PV310_SETUP_I2C5 | ||
38 | bool | ||
39 | help | ||
40 | Common setup code for i2c bus 5. | ||
41 | |||
42 | config S5PV310_SETUP_I2C6 | ||
43 | bool | ||
44 | help | ||
45 | Common setup code for i2c bus 6. | ||
46 | |||
47 | config S5PV310_SETUP_I2C7 | ||
48 | bool | ||
49 | help | ||
50 | Common setup code for i2c bus 7. | ||
51 | |||
52 | config S5PV310_SETUP_SDHCI | ||
53 | bool | ||
54 | select S5PV310_SETUP_SDHCI_GPIO | ||
55 | help | ||
56 | Internal helper functions for S5PV310 based SDHCI systems. | ||
57 | |||
58 | config S5PV310_SETUP_SDHCI_GPIO | ||
59 | bool | ||
60 | help | ||
61 | Common setup code for SDHCI gpio. | ||
62 | |||
28 | # machine support | 63 | # machine support |
29 | 64 | ||
30 | config MACH_SMDKV310 | 65 | menu "S5PC210 Machines" |
31 | bool "SMDKV310" | 66 | |
67 | config MACH_SMDKC210 | ||
68 | bool "SMDKC210" | ||
32 | select CPU_S5PV310 | 69 | select CPU_S5PV310 |
33 | select ARCH_SPARSEMEM_ENABLE | 70 | select S3C_DEV_RTC |
71 | select S3C_DEV_WDT | ||
72 | select S3C_DEV_HSMMC | ||
73 | select S3C_DEV_HSMMC1 | ||
74 | select S3C_DEV_HSMMC2 | ||
75 | select S3C_DEV_HSMMC3 | ||
76 | select S5PV310_SETUP_SDHCI | ||
34 | help | 77 | help |
35 | Machine support for Samsung SMDKV310 | 78 | Machine support for Samsung SMDKC210 |
79 | S5PC210(MCP) is one of package option of S5PV310 | ||
36 | 80 | ||
37 | config MACH_UNIVERSAL_C210 | 81 | config MACH_UNIVERSAL_C210 |
38 | bool "Mobile UNIVERSAL_C210 Board" | 82 | bool "Mobile UNIVERSAL_C210 Board" |
39 | select CPU_S5PV310 | 83 | select CPU_S5PV310 |
40 | select ARCH_SPARSEMEM_ENABLE | 84 | select S5P_DEV_ONENAND |
85 | select S3C_DEV_I2C1 | ||
86 | select S5PV310_SETUP_I2C1 | ||
41 | help | 87 | help |
42 | Machine support for Samsung Mobile Universal S5PC210 Reference | 88 | Machine support for Samsung Mobile Universal S5PC210 Reference |
43 | Board. S5PC210(MCP) is one of package option of S5PV310 | 89 | Board. S5PC210(MCP) is one of package option of S5PV310 |
44 | 90 | ||
91 | endmenu | ||
92 | |||
93 | menu "S5PV310 Machines" | ||
94 | |||
95 | config MACH_SMDKV310 | ||
96 | bool "SMDKV310" | ||
97 | select CPU_S5PV310 | ||
98 | select S3C_DEV_RTC | ||
99 | select S3C_DEV_WDT | ||
100 | select S3C_DEV_HSMMC | ||
101 | select S3C_DEV_HSMMC1 | ||
102 | select S3C_DEV_HSMMC2 | ||
103 | select S3C_DEV_HSMMC3 | ||
104 | select S5PV310_SETUP_SDHCI | ||
105 | help | ||
106 | Machine support for Samsung SMDKV310 | ||
107 | |||
108 | endmenu | ||
109 | |||
110 | comment "Configuration for HSMMC bus width" | ||
111 | |||
112 | menu "Use 8-bit bus width" | ||
113 | |||
114 | config S5PV310_SDHCI_CH0_8BIT | ||
115 | bool "Channel 0 with 8-bit bus" | ||
116 | help | ||
117 | Support HSMMC Channel 0 8-bit bus. | ||
118 | If selected, Channel 1 is disabled. | ||
119 | |||
120 | config S5PV310_SDHCI_CH2_8BIT | ||
121 | bool "Channel 2 with 8-bit bus" | ||
122 | help | ||
123 | Support HSMMC Channel 2 8-bit bus. | ||
124 | If selected, Channel 3 is disabled. | ||
125 | |||
126 | endmenu | ||
127 | |||
45 | endif | 128 | endif |
diff --git a/arch/arm/mach-s5pv310/Makefile b/arch/arm/mach-s5pv310/Makefile index d5b51c72340f..84afc64e7c01 100644 --- a/arch/arm/mach-s5pv310/Makefile +++ b/arch/arm/mach-s5pv310/Makefile | |||
@@ -13,7 +13,7 @@ obj- := | |||
13 | # Core support for S5PV310 system | 13 | # Core support for S5PV310 system |
14 | 14 | ||
15 | obj-$(CONFIG_CPU_S5PV310) += cpu.o init.o clock.o irq-combiner.o | 15 | obj-$(CONFIG_CPU_S5PV310) += cpu.o init.o clock.o irq-combiner.o |
16 | obj-$(CONFIG_CPU_S5PV310) += setup-i2c0.o time.o | 16 | obj-$(CONFIG_CPU_S5PV310) += setup-i2c0.o time.o gpiolib.o irq-eint.o |
17 | 17 | ||
18 | obj-$(CONFIG_SMP) += platsmp.o headsmp.o | 18 | obj-$(CONFIG_SMP) += platsmp.o headsmp.o |
19 | obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o | 19 | obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o |
@@ -21,6 +21,7 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o | |||
21 | 21 | ||
22 | # machine support | 22 | # machine support |
23 | 23 | ||
24 | obj-$(CONFIG_MACH_SMDKC210) += mach-smdkc210.o | ||
24 | obj-$(CONFIG_MACH_SMDKV310) += mach-smdkv310.o | 25 | obj-$(CONFIG_MACH_SMDKV310) += mach-smdkv310.o |
25 | obj-$(CONFIG_MACH_UNIVERSAL_C210) += mach-universal_c210.o | 26 | obj-$(CONFIG_MACH_UNIVERSAL_C210) += mach-universal_c210.o |
26 | 27 | ||
@@ -28,3 +29,10 @@ obj-$(CONFIG_MACH_UNIVERSAL_C210) += mach-universal_c210.o | |||
28 | 29 | ||
29 | obj-$(CONFIG_S5PV310_SETUP_I2C1) += setup-i2c1.o | 30 | obj-$(CONFIG_S5PV310_SETUP_I2C1) += setup-i2c1.o |
30 | obj-$(CONFIG_S5PV310_SETUP_I2C2) += setup-i2c2.o | 31 | obj-$(CONFIG_S5PV310_SETUP_I2C2) += setup-i2c2.o |
32 | obj-$(CONFIG_S5PV310_SETUP_I2C3) += setup-i2c3.o | ||
33 | obj-$(CONFIG_S5PV310_SETUP_I2C4) += setup-i2c4.o | ||
34 | obj-$(CONFIG_S5PV310_SETUP_I2C5) += setup-i2c5.o | ||
35 | obj-$(CONFIG_S5PV310_SETUP_I2C6) += setup-i2c6.o | ||
36 | obj-$(CONFIG_S5PV310_SETUP_I2C7) += setup-i2c7.o | ||
37 | obj-$(CONFIG_S5PV310_SETUP_SDHCI) += setup-sdhci.o | ||
38 | obj-$(CONFIG_S5PV310_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o | ||
diff --git a/arch/arm/mach-s5pv310/clock.c b/arch/arm/mach-s5pv310/clock.c index 26a0f03df8ea..58c9d33f36fe 100644 --- a/arch/arm/mach-s5pv310/clock.c +++ b/arch/arm/mach-s5pv310/clock.c | |||
@@ -30,16 +30,92 @@ static struct clk clk_sclk_hdmi27m = { | |||
30 | .rate = 27000000, | 30 | .rate = 27000000, |
31 | }; | 31 | }; |
32 | 32 | ||
33 | static struct clk clk_sclk_hdmiphy = { | ||
34 | .name = "sclk_hdmiphy", | ||
35 | .id = -1, | ||
36 | }; | ||
37 | |||
38 | static struct clk clk_sclk_usbphy0 = { | ||
39 | .name = "sclk_usbphy0", | ||
40 | .id = -1, | ||
41 | .rate = 27000000, | ||
42 | }; | ||
43 | |||
44 | static struct clk clk_sclk_usbphy1 = { | ||
45 | .name = "sclk_usbphy1", | ||
46 | .id = -1, | ||
47 | }; | ||
48 | |||
49 | static int s5pv310_clksrc_mask_top_ctrl(struct clk *clk, int enable) | ||
50 | { | ||
51 | return s5p_gatectrl(S5P_CLKSRC_MASK_TOP, clk, enable); | ||
52 | } | ||
53 | |||
54 | static int s5pv310_clksrc_mask_cam_ctrl(struct clk *clk, int enable) | ||
55 | { | ||
56 | return s5p_gatectrl(S5P_CLKSRC_MASK_CAM, clk, enable); | ||
57 | } | ||
58 | |||
59 | static int s5pv310_clksrc_mask_lcd0_ctrl(struct clk *clk, int enable) | ||
60 | { | ||
61 | return s5p_gatectrl(S5P_CLKSRC_MASK_LCD0, clk, enable); | ||
62 | } | ||
63 | |||
64 | static int s5pv310_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable) | ||
65 | { | ||
66 | return s5p_gatectrl(S5P_CLKSRC_MASK_LCD1, clk, enable); | ||
67 | } | ||
68 | |||
69 | static int s5pv310_clksrc_mask_fsys_ctrl(struct clk *clk, int enable) | ||
70 | { | ||
71 | return s5p_gatectrl(S5P_CLKSRC_MASK_FSYS, clk, enable); | ||
72 | } | ||
73 | |||
33 | static int s5pv310_clksrc_mask_peril0_ctrl(struct clk *clk, int enable) | 74 | static int s5pv310_clksrc_mask_peril0_ctrl(struct clk *clk, int enable) |
34 | { | 75 | { |
35 | return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL0, clk, enable); | 76 | return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL0, clk, enable); |
36 | } | 77 | } |
37 | 78 | ||
79 | static int s5pv310_clksrc_mask_peril1_ctrl(struct clk *clk, int enable) | ||
80 | { | ||
81 | return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL1, clk, enable); | ||
82 | } | ||
83 | |||
84 | static int s5pv310_clk_ip_cam_ctrl(struct clk *clk, int enable) | ||
85 | { | ||
86 | return s5p_gatectrl(S5P_CLKGATE_IP_CAM, clk, enable); | ||
87 | } | ||
88 | |||
89 | static int s5pv310_clk_ip_image_ctrl(struct clk *clk, int enable) | ||
90 | { | ||
91 | return s5p_gatectrl(S5P_CLKGATE_IP_IMAGE, clk, enable); | ||
92 | } | ||
93 | |||
94 | static int s5pv310_clk_ip_lcd0_ctrl(struct clk *clk, int enable) | ||
95 | { | ||
96 | return s5p_gatectrl(S5P_CLKGATE_IP_LCD0, clk, enable); | ||
97 | } | ||
98 | |||
99 | static int s5pv310_clk_ip_lcd1_ctrl(struct clk *clk, int enable) | ||
100 | { | ||
101 | return s5p_gatectrl(S5P_CLKGATE_IP_LCD1, clk, enable); | ||
102 | } | ||
103 | |||
104 | static int s5pv310_clk_ip_fsys_ctrl(struct clk *clk, int enable) | ||
105 | { | ||
106 | return s5p_gatectrl(S5P_CLKGATE_IP_FSYS, clk, enable); | ||
107 | } | ||
108 | |||
38 | static int s5pv310_clk_ip_peril_ctrl(struct clk *clk, int enable) | 109 | static int s5pv310_clk_ip_peril_ctrl(struct clk *clk, int enable) |
39 | { | 110 | { |
40 | return s5p_gatectrl(S5P_CLKGATE_IP_PERIL, clk, enable); | 111 | return s5p_gatectrl(S5P_CLKGATE_IP_PERIL, clk, enable); |
41 | } | 112 | } |
42 | 113 | ||
114 | static int s5pv310_clk_ip_perir_ctrl(struct clk *clk, int enable) | ||
115 | { | ||
116 | return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable); | ||
117 | } | ||
118 | |||
43 | /* Core list of CMU_CPU side */ | 119 | /* Core list of CMU_CPU side */ |
44 | 120 | ||
45 | static struct clksrc_clk clk_mout_apll = { | 121 | static struct clksrc_clk clk_mout_apll = { |
@@ -79,7 +155,7 @@ static struct clksrc_clk clk_mout_mpll = { | |||
79 | }; | 155 | }; |
80 | 156 | ||
81 | static struct clk *clkset_moutcore_list[] = { | 157 | static struct clk *clkset_moutcore_list[] = { |
82 | [0] = &clk_sclk_apll.clk, | 158 | [0] = &clk_mout_apll.clk, |
83 | [1] = &clk_mout_mpll.clk, | 159 | [1] = &clk_mout_mpll.clk, |
84 | }; | 160 | }; |
85 | 161 | ||
@@ -150,24 +226,6 @@ static struct clksrc_clk clk_periphclk = { | |||
150 | .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 }, | 226 | .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 }, |
151 | }; | 227 | }; |
152 | 228 | ||
153 | static struct clksrc_clk clk_atclk = { | ||
154 | .clk = { | ||
155 | .name = "atclk", | ||
156 | .id = -1, | ||
157 | .parent = &clk_moutcore.clk, | ||
158 | }, | ||
159 | .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 16, .size = 3 }, | ||
160 | }; | ||
161 | |||
162 | static struct clksrc_clk clk_pclk_dbg = { | ||
163 | .clk = { | ||
164 | .name = "pclk_dbg", | ||
165 | .id = -1, | ||
166 | .parent = &clk_atclk.clk, | ||
167 | }, | ||
168 | .reg_div = { .reg = S5P_CLKDIV_CPU, .shift = 20, .size = 3 }, | ||
169 | }; | ||
170 | |||
171 | /* Core list of CMU_CORE side */ | 229 | /* Core list of CMU_CORE side */ |
172 | 230 | ||
173 | static struct clk *clkset_corebus_list[] = { | 231 | static struct clk *clkset_corebus_list[] = { |
@@ -241,7 +299,7 @@ static struct clk *clkset_aclk_top_list[] = { | |||
241 | [1] = &clk_sclk_apll.clk, | 299 | [1] = &clk_sclk_apll.clk, |
242 | }; | 300 | }; |
243 | 301 | ||
244 | static struct clksrc_sources clkset_aclk_200 = { | 302 | static struct clksrc_sources clkset_aclk = { |
245 | .sources = clkset_aclk_top_list, | 303 | .sources = clkset_aclk_top_list, |
246 | .nr_sources = ARRAY_SIZE(clkset_aclk_top_list), | 304 | .nr_sources = ARRAY_SIZE(clkset_aclk_top_list), |
247 | }; | 305 | }; |
@@ -251,52 +309,37 @@ static struct clksrc_clk clk_aclk_200 = { | |||
251 | .name = "aclk_200", | 309 | .name = "aclk_200", |
252 | .id = -1, | 310 | .id = -1, |
253 | }, | 311 | }, |
254 | .sources = &clkset_aclk_200, | 312 | .sources = &clkset_aclk, |
255 | .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 12, .size = 1 }, | 313 | .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 12, .size = 1 }, |
256 | .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 0, .size = 3 }, | 314 | .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 0, .size = 3 }, |
257 | }; | 315 | }; |
258 | 316 | ||
259 | static struct clksrc_sources clkset_aclk_100 = { | ||
260 | .sources = clkset_aclk_top_list, | ||
261 | .nr_sources = ARRAY_SIZE(clkset_aclk_top_list), | ||
262 | }; | ||
263 | |||
264 | static struct clksrc_clk clk_aclk_100 = { | 317 | static struct clksrc_clk clk_aclk_100 = { |
265 | .clk = { | 318 | .clk = { |
266 | .name = "aclk_100", | 319 | .name = "aclk_100", |
267 | .id = -1, | 320 | .id = -1, |
268 | }, | 321 | }, |
269 | .sources = &clkset_aclk_100, | 322 | .sources = &clkset_aclk, |
270 | .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 16, .size = 1 }, | 323 | .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 16, .size = 1 }, |
271 | .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 4, .size = 4 }, | 324 | .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 4, .size = 4 }, |
272 | }; | 325 | }; |
273 | 326 | ||
274 | static struct clksrc_sources clkset_aclk_160 = { | ||
275 | .sources = clkset_aclk_top_list, | ||
276 | .nr_sources = ARRAY_SIZE(clkset_aclk_top_list), | ||
277 | }; | ||
278 | |||
279 | static struct clksrc_clk clk_aclk_160 = { | 327 | static struct clksrc_clk clk_aclk_160 = { |
280 | .clk = { | 328 | .clk = { |
281 | .name = "aclk_160", | 329 | .name = "aclk_160", |
282 | .id = -1, | 330 | .id = -1, |
283 | }, | 331 | }, |
284 | .sources = &clkset_aclk_160, | 332 | .sources = &clkset_aclk, |
285 | .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 20, .size = 1 }, | 333 | .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 20, .size = 1 }, |
286 | .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 8, .size = 3 }, | 334 | .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 8, .size = 3 }, |
287 | }; | 335 | }; |
288 | 336 | ||
289 | static struct clksrc_sources clkset_aclk_133 = { | ||
290 | .sources = clkset_aclk_top_list, | ||
291 | .nr_sources = ARRAY_SIZE(clkset_aclk_top_list), | ||
292 | }; | ||
293 | |||
294 | static struct clksrc_clk clk_aclk_133 = { | 337 | static struct clksrc_clk clk_aclk_133 = { |
295 | .clk = { | 338 | .clk = { |
296 | .name = "aclk_133", | 339 | .name = "aclk_133", |
297 | .id = -1, | 340 | .id = -1, |
298 | }, | 341 | }, |
299 | .sources = &clkset_aclk_133, | 342 | .sources = &clkset_aclk, |
300 | .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 24, .size = 1 }, | 343 | .reg_src = { .reg = S5P_CLKSRC_TOP0, .shift = 24, .size = 1 }, |
301 | .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 12, .size = 3 }, | 344 | .reg_div = { .reg = S5P_CLKDIV_TOP, .shift = 12, .size = 3 }, |
302 | }; | 345 | }; |
@@ -315,6 +358,8 @@ static struct clksrc_clk clk_vpllsrc = { | |||
315 | .clk = { | 358 | .clk = { |
316 | .name = "vpll_src", | 359 | .name = "vpll_src", |
317 | .id = -1, | 360 | .id = -1, |
361 | .enable = s5pv310_clksrc_mask_top_ctrl, | ||
362 | .ctrlbit = (1 << 0), | ||
318 | }, | 363 | }, |
319 | .sources = &clkset_vpllsrc, | 364 | .sources = &clkset_vpllsrc, |
320 | .reg_src = { .reg = S5P_CLKSRC_TOP1, .shift = 0, .size = 1 }, | 365 | .reg_src = { .reg = S5P_CLKSRC_TOP1, .shift = 0, .size = 1 }, |
@@ -346,7 +391,175 @@ static struct clk init_clocks_disable[] = { | |||
346 | .parent = &clk_aclk_100.clk, | 391 | .parent = &clk_aclk_100.clk, |
347 | .enable = s5pv310_clk_ip_peril_ctrl, | 392 | .enable = s5pv310_clk_ip_peril_ctrl, |
348 | .ctrlbit = (1<<24), | 393 | .ctrlbit = (1<<24), |
349 | } | 394 | }, { |
395 | .name = "csis", | ||
396 | .id = 0, | ||
397 | .enable = s5pv310_clk_ip_cam_ctrl, | ||
398 | .ctrlbit = (1 << 4), | ||
399 | }, { | ||
400 | .name = "csis", | ||
401 | .id = 1, | ||
402 | .enable = s5pv310_clk_ip_cam_ctrl, | ||
403 | .ctrlbit = (1 << 5), | ||
404 | }, { | ||
405 | .name = "fimc", | ||
406 | .id = 0, | ||
407 | .enable = s5pv310_clk_ip_cam_ctrl, | ||
408 | .ctrlbit = (1 << 0), | ||
409 | }, { | ||
410 | .name = "fimc", | ||
411 | .id = 1, | ||
412 | .enable = s5pv310_clk_ip_cam_ctrl, | ||
413 | .ctrlbit = (1 << 1), | ||
414 | }, { | ||
415 | .name = "fimc", | ||
416 | .id = 2, | ||
417 | .enable = s5pv310_clk_ip_cam_ctrl, | ||
418 | .ctrlbit = (1 << 2), | ||
419 | }, { | ||
420 | .name = "fimc", | ||
421 | .id = 3, | ||
422 | .enable = s5pv310_clk_ip_cam_ctrl, | ||
423 | .ctrlbit = (1 << 3), | ||
424 | }, { | ||
425 | .name = "fimd", | ||
426 | .id = 0, | ||
427 | .enable = s5pv310_clk_ip_lcd0_ctrl, | ||
428 | .ctrlbit = (1 << 0), | ||
429 | }, { | ||
430 | .name = "fimd", | ||
431 | .id = 1, | ||
432 | .enable = s5pv310_clk_ip_lcd1_ctrl, | ||
433 | .ctrlbit = (1 << 0), | ||
434 | }, { | ||
435 | .name = "hsmmc", | ||
436 | .id = 0, | ||
437 | .parent = &clk_aclk_133.clk, | ||
438 | .enable = s5pv310_clk_ip_fsys_ctrl, | ||
439 | .ctrlbit = (1 << 5), | ||
440 | }, { | ||
441 | .name = "hsmmc", | ||
442 | .id = 1, | ||
443 | .parent = &clk_aclk_133.clk, | ||
444 | .enable = s5pv310_clk_ip_fsys_ctrl, | ||
445 | .ctrlbit = (1 << 6), | ||
446 | }, { | ||
447 | .name = "hsmmc", | ||
448 | .id = 2, | ||
449 | .parent = &clk_aclk_133.clk, | ||
450 | .enable = s5pv310_clk_ip_fsys_ctrl, | ||
451 | .ctrlbit = (1 << 7), | ||
452 | }, { | ||
453 | .name = "hsmmc", | ||
454 | .id = 3, | ||
455 | .parent = &clk_aclk_133.clk, | ||
456 | .enable = s5pv310_clk_ip_fsys_ctrl, | ||
457 | .ctrlbit = (1 << 8), | ||
458 | }, { | ||
459 | .name = "hsmmc", | ||
460 | .id = 4, | ||
461 | .parent = &clk_aclk_133.clk, | ||
462 | .enable = s5pv310_clk_ip_fsys_ctrl, | ||
463 | .ctrlbit = (1 << 9), | ||
464 | }, { | ||
465 | .name = "sata", | ||
466 | .id = -1, | ||
467 | .enable = s5pv310_clk_ip_fsys_ctrl, | ||
468 | .ctrlbit = (1 << 10), | ||
469 | }, { | ||
470 | .name = "adc", | ||
471 | .id = -1, | ||
472 | .enable = s5pv310_clk_ip_peril_ctrl, | ||
473 | .ctrlbit = (1 << 15), | ||
474 | }, { | ||
475 | .name = "rtc", | ||
476 | .id = -1, | ||
477 | .enable = s5pv310_clk_ip_perir_ctrl, | ||
478 | .ctrlbit = (1 << 15), | ||
479 | }, { | ||
480 | .name = "watchdog", | ||
481 | .id = -1, | ||
482 | .enable = s5pv310_clk_ip_perir_ctrl, | ||
483 | .ctrlbit = (1 << 14), | ||
484 | }, { | ||
485 | .name = "usbhost", | ||
486 | .id = -1, | ||
487 | .enable = s5pv310_clk_ip_fsys_ctrl , | ||
488 | .ctrlbit = (1 << 12), | ||
489 | }, { | ||
490 | .name = "otg", | ||
491 | .id = -1, | ||
492 | .enable = s5pv310_clk_ip_fsys_ctrl, | ||
493 | .ctrlbit = (1 << 13), | ||
494 | }, { | ||
495 | .name = "spi", | ||
496 | .id = 0, | ||
497 | .enable = s5pv310_clk_ip_peril_ctrl, | ||
498 | .ctrlbit = (1 << 16), | ||
499 | }, { | ||
500 | .name = "spi", | ||
501 | .id = 1, | ||
502 | .enable = s5pv310_clk_ip_peril_ctrl, | ||
503 | .ctrlbit = (1 << 17), | ||
504 | }, { | ||
505 | .name = "spi", | ||
506 | .id = 2, | ||
507 | .enable = s5pv310_clk_ip_peril_ctrl, | ||
508 | .ctrlbit = (1 << 18), | ||
509 | }, { | ||
510 | .name = "fimg2d", | ||
511 | .id = -1, | ||
512 | .enable = s5pv310_clk_ip_image_ctrl, | ||
513 | .ctrlbit = (1 << 0), | ||
514 | }, { | ||
515 | .name = "i2c", | ||
516 | .id = 0, | ||
517 | .parent = &clk_aclk_100.clk, | ||
518 | .enable = s5pv310_clk_ip_peril_ctrl, | ||
519 | .ctrlbit = (1 << 6), | ||
520 | }, { | ||
521 | .name = "i2c", | ||
522 | .id = 1, | ||
523 | .parent = &clk_aclk_100.clk, | ||
524 | .enable = s5pv310_clk_ip_peril_ctrl, | ||
525 | .ctrlbit = (1 << 7), | ||
526 | }, { | ||
527 | .name = "i2c", | ||
528 | .id = 2, | ||
529 | .parent = &clk_aclk_100.clk, | ||
530 | .enable = s5pv310_clk_ip_peril_ctrl, | ||
531 | .ctrlbit = (1 << 8), | ||
532 | }, { | ||
533 | .name = "i2c", | ||
534 | .id = 3, | ||
535 | .parent = &clk_aclk_100.clk, | ||
536 | .enable = s5pv310_clk_ip_peril_ctrl, | ||
537 | .ctrlbit = (1 << 9), | ||
538 | }, { | ||
539 | .name = "i2c", | ||
540 | .id = 4, | ||
541 | .parent = &clk_aclk_100.clk, | ||
542 | .enable = s5pv310_clk_ip_peril_ctrl, | ||
543 | .ctrlbit = (1 << 10), | ||
544 | }, { | ||
545 | .name = "i2c", | ||
546 | .id = 5, | ||
547 | .parent = &clk_aclk_100.clk, | ||
548 | .enable = s5pv310_clk_ip_peril_ctrl, | ||
549 | .ctrlbit = (1 << 11), | ||
550 | }, { | ||
551 | .name = "i2c", | ||
552 | .id = 6, | ||
553 | .parent = &clk_aclk_100.clk, | ||
554 | .enable = s5pv310_clk_ip_peril_ctrl, | ||
555 | .ctrlbit = (1 << 12), | ||
556 | }, { | ||
557 | .name = "i2c", | ||
558 | .id = 7, | ||
559 | .parent = &clk_aclk_100.clk, | ||
560 | .enable = s5pv310_clk_ip_peril_ctrl, | ||
561 | .ctrlbit = (1 << 13), | ||
562 | }, | ||
350 | }; | 563 | }; |
351 | 564 | ||
352 | static struct clk init_clocks[] = { | 565 | static struct clk init_clocks[] = { |
@@ -387,6 +600,9 @@ static struct clk *clkset_group_list[] = { | |||
387 | [0] = &clk_ext_xtal_mux, | 600 | [0] = &clk_ext_xtal_mux, |
388 | [1] = &clk_xusbxti, | 601 | [1] = &clk_xusbxti, |
389 | [2] = &clk_sclk_hdmi27m, | 602 | [2] = &clk_sclk_hdmi27m, |
603 | [3] = &clk_sclk_usbphy0, | ||
604 | [4] = &clk_sclk_usbphy1, | ||
605 | [5] = &clk_sclk_hdmiphy, | ||
390 | [6] = &clk_mout_mpll.clk, | 606 | [6] = &clk_mout_mpll.clk, |
391 | [7] = &clk_mout_epll.clk, | 607 | [7] = &clk_mout_epll.clk, |
392 | [8] = &clk_sclk_vpll.clk, | 608 | [8] = &clk_sclk_vpll.clk, |
@@ -397,6 +613,104 @@ static struct clksrc_sources clkset_group = { | |||
397 | .nr_sources = ARRAY_SIZE(clkset_group_list), | 613 | .nr_sources = ARRAY_SIZE(clkset_group_list), |
398 | }; | 614 | }; |
399 | 615 | ||
616 | static struct clk *clkset_mout_g2d0_list[] = { | ||
617 | [0] = &clk_mout_mpll.clk, | ||
618 | [1] = &clk_sclk_apll.clk, | ||
619 | }; | ||
620 | |||
621 | static struct clksrc_sources clkset_mout_g2d0 = { | ||
622 | .sources = clkset_mout_g2d0_list, | ||
623 | .nr_sources = ARRAY_SIZE(clkset_mout_g2d0_list), | ||
624 | }; | ||
625 | |||
626 | static struct clksrc_clk clk_mout_g2d0 = { | ||
627 | .clk = { | ||
628 | .name = "mout_g2d0", | ||
629 | .id = -1, | ||
630 | }, | ||
631 | .sources = &clkset_mout_g2d0, | ||
632 | .reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 0, .size = 1 }, | ||
633 | }; | ||
634 | |||
635 | static struct clk *clkset_mout_g2d1_list[] = { | ||
636 | [0] = &clk_mout_epll.clk, | ||
637 | [1] = &clk_sclk_vpll.clk, | ||
638 | }; | ||
639 | |||
640 | static struct clksrc_sources clkset_mout_g2d1 = { | ||
641 | .sources = clkset_mout_g2d1_list, | ||
642 | .nr_sources = ARRAY_SIZE(clkset_mout_g2d1_list), | ||
643 | }; | ||
644 | |||
645 | static struct clksrc_clk clk_mout_g2d1 = { | ||
646 | .clk = { | ||
647 | .name = "mout_g2d1", | ||
648 | .id = -1, | ||
649 | }, | ||
650 | .sources = &clkset_mout_g2d1, | ||
651 | .reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 4, .size = 1 }, | ||
652 | }; | ||
653 | |||
654 | static struct clk *clkset_mout_g2d_list[] = { | ||
655 | [0] = &clk_mout_g2d0.clk, | ||
656 | [1] = &clk_mout_g2d1.clk, | ||
657 | }; | ||
658 | |||
659 | static struct clksrc_sources clkset_mout_g2d = { | ||
660 | .sources = clkset_mout_g2d_list, | ||
661 | .nr_sources = ARRAY_SIZE(clkset_mout_g2d_list), | ||
662 | }; | ||
663 | |||
664 | static struct clksrc_clk clk_dout_mmc0 = { | ||
665 | .clk = { | ||
666 | .name = "dout_mmc0", | ||
667 | .id = -1, | ||
668 | }, | ||
669 | .sources = &clkset_group, | ||
670 | .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 0, .size = 4 }, | ||
671 | .reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 0, .size = 4 }, | ||
672 | }; | ||
673 | |||
674 | static struct clksrc_clk clk_dout_mmc1 = { | ||
675 | .clk = { | ||
676 | .name = "dout_mmc1", | ||
677 | .id = -1, | ||
678 | }, | ||
679 | .sources = &clkset_group, | ||
680 | .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 4, .size = 4 }, | ||
681 | .reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 16, .size = 4 }, | ||
682 | }; | ||
683 | |||
684 | static struct clksrc_clk clk_dout_mmc2 = { | ||
685 | .clk = { | ||
686 | .name = "dout_mmc2", | ||
687 | .id = -1, | ||
688 | }, | ||
689 | .sources = &clkset_group, | ||
690 | .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 8, .size = 4 }, | ||
691 | .reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 0, .size = 4 }, | ||
692 | }; | ||
693 | |||
694 | static struct clksrc_clk clk_dout_mmc3 = { | ||
695 | .clk = { | ||
696 | .name = "dout_mmc3", | ||
697 | .id = -1, | ||
698 | }, | ||
699 | .sources = &clkset_group, | ||
700 | .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 12, .size = 4 }, | ||
701 | .reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 16, .size = 4 }, | ||
702 | }; | ||
703 | |||
704 | static struct clksrc_clk clk_dout_mmc4 = { | ||
705 | .clk = { | ||
706 | .name = "dout_mmc4", | ||
707 | .id = -1, | ||
708 | }, | ||
709 | .sources = &clkset_group, | ||
710 | .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 16, .size = 4 }, | ||
711 | .reg_div = { .reg = S5P_CLKDIV_FSYS3, .shift = 0, .size = 4 }, | ||
712 | }; | ||
713 | |||
400 | static struct clksrc_clk clksrcs[] = { | 714 | static struct clksrc_clk clksrcs[] = { |
401 | { | 715 | { |
402 | .clk = { | 716 | .clk = { |
@@ -448,7 +762,200 @@ static struct clksrc_clk clksrcs[] = { | |||
448 | .sources = &clkset_group, | 762 | .sources = &clkset_group, |
449 | .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 24, .size = 4 }, | 763 | .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 24, .size = 4 }, |
450 | .reg_div = { .reg = S5P_CLKDIV_PERIL3, .shift = 0, .size = 4 }, | 764 | .reg_div = { .reg = S5P_CLKDIV_PERIL3, .shift = 0, .size = 4 }, |
451 | }, | 765 | }, { |
766 | .clk = { | ||
767 | .name = "sclk_csis", | ||
768 | .id = 0, | ||
769 | .enable = s5pv310_clksrc_mask_cam_ctrl, | ||
770 | .ctrlbit = (1 << 24), | ||
771 | }, | ||
772 | .sources = &clkset_group, | ||
773 | .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 24, .size = 4 }, | ||
774 | .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 24, .size = 4 }, | ||
775 | }, { | ||
776 | .clk = { | ||
777 | .name = "sclk_csis", | ||
778 | .id = 1, | ||
779 | .enable = s5pv310_clksrc_mask_cam_ctrl, | ||
780 | .ctrlbit = (1 << 28), | ||
781 | }, | ||
782 | .sources = &clkset_group, | ||
783 | .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 28, .size = 4 }, | ||
784 | .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 28, .size = 4 }, | ||
785 | }, { | ||
786 | .clk = { | ||
787 | .name = "sclk_cam", | ||
788 | .id = 0, | ||
789 | .enable = s5pv310_clksrc_mask_cam_ctrl, | ||
790 | .ctrlbit = (1 << 16), | ||
791 | }, | ||
792 | .sources = &clkset_group, | ||
793 | .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 16, .size = 4 }, | ||
794 | .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 16, .size = 4 }, | ||
795 | }, { | ||
796 | .clk = { | ||
797 | .name = "sclk_cam", | ||
798 | .id = 1, | ||
799 | .enable = s5pv310_clksrc_mask_cam_ctrl, | ||
800 | .ctrlbit = (1 << 20), | ||
801 | }, | ||
802 | .sources = &clkset_group, | ||
803 | .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 20, .size = 4 }, | ||
804 | .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 20, .size = 4 }, | ||
805 | }, { | ||
806 | .clk = { | ||
807 | .name = "sclk_fimc", | ||
808 | .id = 0, | ||
809 | .enable = s5pv310_clksrc_mask_cam_ctrl, | ||
810 | .ctrlbit = (1 << 0), | ||
811 | }, | ||
812 | .sources = &clkset_group, | ||
813 | .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 0, .size = 4 }, | ||
814 | .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 0, .size = 4 }, | ||
815 | }, { | ||
816 | .clk = { | ||
817 | .name = "sclk_fimc", | ||
818 | .id = 1, | ||
819 | .enable = s5pv310_clksrc_mask_cam_ctrl, | ||
820 | .ctrlbit = (1 << 4), | ||
821 | }, | ||
822 | .sources = &clkset_group, | ||
823 | .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 4, .size = 4 }, | ||
824 | .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 4, .size = 4 }, | ||
825 | }, { | ||
826 | .clk = { | ||
827 | .name = "sclk_fimc", | ||
828 | .id = 2, | ||
829 | .enable = s5pv310_clksrc_mask_cam_ctrl, | ||
830 | .ctrlbit = (1 << 8), | ||
831 | }, | ||
832 | .sources = &clkset_group, | ||
833 | .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 8, .size = 4 }, | ||
834 | .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 8, .size = 4 }, | ||
835 | }, { | ||
836 | .clk = { | ||
837 | .name = "sclk_fimc", | ||
838 | .id = 3, | ||
839 | .enable = s5pv310_clksrc_mask_cam_ctrl, | ||
840 | .ctrlbit = (1 << 12), | ||
841 | }, | ||
842 | .sources = &clkset_group, | ||
843 | .reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 12, .size = 4 }, | ||
844 | .reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 12, .size = 4 }, | ||
845 | }, { | ||
846 | .clk = { | ||
847 | .name = "sclk_fimd", | ||
848 | .id = 0, | ||
849 | .enable = s5pv310_clksrc_mask_lcd0_ctrl, | ||
850 | .ctrlbit = (1 << 0), | ||
851 | }, | ||
852 | .sources = &clkset_group, | ||
853 | .reg_src = { .reg = S5P_CLKSRC_LCD0, .shift = 0, .size = 4 }, | ||
854 | .reg_div = { .reg = S5P_CLKDIV_LCD0, .shift = 0, .size = 4 }, | ||
855 | }, { | ||
856 | .clk = { | ||
857 | .name = "sclk_fimd", | ||
858 | .id = 1, | ||
859 | .enable = s5pv310_clksrc_mask_lcd1_ctrl, | ||
860 | .ctrlbit = (1 << 0), | ||
861 | }, | ||
862 | .sources = &clkset_group, | ||
863 | .reg_src = { .reg = S5P_CLKSRC_LCD1, .shift = 0, .size = 4 }, | ||
864 | .reg_div = { .reg = S5P_CLKDIV_LCD1, .shift = 0, .size = 4 }, | ||
865 | }, { | ||
866 | .clk = { | ||
867 | .name = "sclk_sata", | ||
868 | .id = -1, | ||
869 | .enable = s5pv310_clksrc_mask_fsys_ctrl, | ||
870 | .ctrlbit = (1 << 24), | ||
871 | }, | ||
872 | .sources = &clkset_mout_corebus, | ||
873 | .reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 24, .size = 1 }, | ||
874 | .reg_div = { .reg = S5P_CLKDIV_FSYS0, .shift = 20, .size = 4 }, | ||
875 | }, { | ||
876 | .clk = { | ||
877 | .name = "sclk_spi", | ||
878 | .id = 0, | ||
879 | .enable = s5pv310_clksrc_mask_peril1_ctrl, | ||
880 | .ctrlbit = (1 << 16), | ||
881 | }, | ||
882 | .sources = &clkset_group, | ||
883 | .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 16, .size = 4 }, | ||
884 | .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 0, .size = 4 }, | ||
885 | }, { | ||
886 | .clk = { | ||
887 | .name = "sclk_spi", | ||
888 | .id = 1, | ||
889 | .enable = s5pv310_clksrc_mask_peril1_ctrl, | ||
890 | .ctrlbit = (1 << 20), | ||
891 | }, | ||
892 | .sources = &clkset_group, | ||
893 | .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 20, .size = 4 }, | ||
894 | .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 16, .size = 4 }, | ||
895 | }, { | ||
896 | .clk = { | ||
897 | .name = "sclk_spi", | ||
898 | .id = 2, | ||
899 | .enable = s5pv310_clksrc_mask_peril1_ctrl, | ||
900 | .ctrlbit = (1 << 24), | ||
901 | }, | ||
902 | .sources = &clkset_group, | ||
903 | .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 24, .size = 4 }, | ||
904 | .reg_div = { .reg = S5P_CLKDIV_PERIL2, .shift = 0, .size = 4 }, | ||
905 | }, { | ||
906 | .clk = { | ||
907 | .name = "sclk_fimg2d", | ||
908 | .id = -1, | ||
909 | }, | ||
910 | .sources = &clkset_mout_g2d, | ||
911 | .reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 8, .size = 1 }, | ||
912 | .reg_div = { .reg = S5P_CLKDIV_IMAGE, .shift = 0, .size = 4 }, | ||
913 | }, { | ||
914 | .clk = { | ||
915 | .name = "sclk_mmc", | ||
916 | .id = 0, | ||
917 | .parent = &clk_dout_mmc0.clk, | ||
918 | .enable = s5pv310_clksrc_mask_fsys_ctrl, | ||
919 | .ctrlbit = (1 << 0), | ||
920 | }, | ||
921 | .reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 8, .size = 8 }, | ||
922 | }, { | ||
923 | .clk = { | ||
924 | .name = "sclk_mmc", | ||
925 | .id = 1, | ||
926 | .parent = &clk_dout_mmc1.clk, | ||
927 | .enable = s5pv310_clksrc_mask_fsys_ctrl, | ||
928 | .ctrlbit = (1 << 4), | ||
929 | }, | ||
930 | .reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 24, .size = 8 }, | ||
931 | }, { | ||
932 | .clk = { | ||
933 | .name = "sclk_mmc", | ||
934 | .id = 2, | ||
935 | .parent = &clk_dout_mmc2.clk, | ||
936 | .enable = s5pv310_clksrc_mask_fsys_ctrl, | ||
937 | .ctrlbit = (1 << 8), | ||
938 | }, | ||
939 | .reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 8, .size = 8 }, | ||
940 | }, { | ||
941 | .clk = { | ||
942 | .name = "sclk_mmc", | ||
943 | .id = 3, | ||
944 | .parent = &clk_dout_mmc3.clk, | ||
945 | .enable = s5pv310_clksrc_mask_fsys_ctrl, | ||
946 | .ctrlbit = (1 << 12), | ||
947 | }, | ||
948 | .reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 24, .size = 8 }, | ||
949 | }, { | ||
950 | .clk = { | ||
951 | .name = "sclk_mmc", | ||
952 | .id = 4, | ||
953 | .parent = &clk_dout_mmc4.clk, | ||
954 | .enable = s5pv310_clksrc_mask_fsys_ctrl, | ||
955 | .ctrlbit = (1 << 16), | ||
956 | }, | ||
957 | .reg_div = { .reg = S5P_CLKDIV_FSYS3, .shift = 8, .size = 8 }, | ||
958 | } | ||
452 | }; | 959 | }; |
453 | 960 | ||
454 | /* Clock initialization code */ | 961 | /* Clock initialization code */ |
@@ -464,8 +971,6 @@ static struct clksrc_clk *sysclks[] = { | |||
464 | &clk_aclk_cores, | 971 | &clk_aclk_cores, |
465 | &clk_aclk_corem1, | 972 | &clk_aclk_corem1, |
466 | &clk_periphclk, | 973 | &clk_periphclk, |
467 | &clk_atclk, | ||
468 | &clk_pclk_dbg, | ||
469 | &clk_mout_corebus, | 974 | &clk_mout_corebus, |
470 | &clk_sclk_dmc, | 975 | &clk_sclk_dmc, |
471 | &clk_aclk_cored, | 976 | &clk_aclk_cored, |
@@ -478,6 +983,11 @@ static struct clksrc_clk *sysclks[] = { | |||
478 | &clk_aclk_100, | 983 | &clk_aclk_100, |
479 | &clk_aclk_160, | 984 | &clk_aclk_160, |
480 | &clk_aclk_133, | 985 | &clk_aclk_133, |
986 | &clk_dout_mmc0, | ||
987 | &clk_dout_mmc1, | ||
988 | &clk_dout_mmc2, | ||
989 | &clk_dout_mmc3, | ||
990 | &clk_dout_mmc4, | ||
481 | }; | 991 | }; |
482 | 992 | ||
483 | void __init_or_cpufreq s5pv310_setup_clocks(void) | 993 | void __init_or_cpufreq s5pv310_setup_clocks(void) |
@@ -490,15 +1000,11 @@ void __init_or_cpufreq s5pv310_setup_clocks(void) | |||
490 | unsigned long vpllsrc; | 1000 | unsigned long vpllsrc; |
491 | unsigned long xtal; | 1001 | unsigned long xtal; |
492 | unsigned long armclk; | 1002 | unsigned long armclk; |
493 | unsigned long aclk_corem0; | ||
494 | unsigned long aclk_cores; | ||
495 | unsigned long aclk_corem1; | ||
496 | unsigned long periphclk; | ||
497 | unsigned long sclk_dmc; | 1003 | unsigned long sclk_dmc; |
498 | unsigned long aclk_cored; | 1004 | unsigned long aclk_200; |
499 | unsigned long aclk_corep; | 1005 | unsigned long aclk_100; |
500 | unsigned long aclk_acp; | 1006 | unsigned long aclk_160; |
501 | unsigned long pclk_acp; | 1007 | unsigned long aclk_133; |
502 | unsigned int ptr; | 1008 | unsigned int ptr; |
503 | 1009 | ||
504 | printk(KERN_DEBUG "%s: registering clocks\n", __func__); | 1010 | printk(KERN_DEBUG "%s: registering clocks\n", __func__); |
@@ -529,26 +1035,21 @@ void __init_or_cpufreq s5pv310_setup_clocks(void) | |||
529 | apll, mpll, epll, vpll); | 1035 | apll, mpll, epll, vpll); |
530 | 1036 | ||
531 | armclk = clk_get_rate(&clk_armclk.clk); | 1037 | armclk = clk_get_rate(&clk_armclk.clk); |
532 | aclk_corem0 = clk_get_rate(&clk_aclk_corem0.clk); | ||
533 | aclk_cores = clk_get_rate(&clk_aclk_cores.clk); | ||
534 | aclk_corem1 = clk_get_rate(&clk_aclk_corem1.clk); | ||
535 | periphclk = clk_get_rate(&clk_periphclk.clk); | ||
536 | sclk_dmc = clk_get_rate(&clk_sclk_dmc.clk); | 1038 | sclk_dmc = clk_get_rate(&clk_sclk_dmc.clk); |
537 | aclk_cored = clk_get_rate(&clk_aclk_cored.clk); | 1039 | |
538 | aclk_corep = clk_get_rate(&clk_aclk_corep.clk); | 1040 | aclk_200 = clk_get_rate(&clk_aclk_200.clk); |
539 | aclk_acp = clk_get_rate(&clk_aclk_acp.clk); | 1041 | aclk_100 = clk_get_rate(&clk_aclk_100.clk); |
540 | pclk_acp = clk_get_rate(&clk_pclk_acp.clk); | 1042 | aclk_160 = clk_get_rate(&clk_aclk_160.clk); |
541 | 1043 | aclk_133 = clk_get_rate(&clk_aclk_133.clk); | |
542 | printk(KERN_INFO "S5PV310: ARMCLK=%ld, COREM0=%ld, CORES=%ld\n" | 1044 | |
543 | "COREM1=%ld, PERI=%ld, DMC=%ld, CORED=%ld\n" | 1045 | printk(KERN_INFO "S5PV310: ARMCLK=%ld, DMC=%ld, ACLK200=%ld\n" |
544 | "COREP=%ld, ACLK_ACP=%ld, PCLK_ACP=%ld", | 1046 | "ACLK100=%ld, ACLK160=%ld, ACLK133=%ld\n", |
545 | armclk, aclk_corem0, aclk_cores, aclk_corem1, | 1047 | armclk, sclk_dmc, aclk_200, |
546 | periphclk, sclk_dmc, aclk_cored, aclk_corep, | 1048 | aclk_100, aclk_160, aclk_133); |
547 | aclk_acp, pclk_acp); | ||
548 | 1049 | ||
549 | clk_f.rate = armclk; | 1050 | clk_f.rate = armclk; |
550 | clk_h.rate = sclk_dmc; | 1051 | clk_h.rate = sclk_dmc; |
551 | clk_p.rate = periphclk; | 1052 | clk_p.rate = aclk_100; |
552 | 1053 | ||
553 | for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) | 1054 | for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) |
554 | s3c_set_clksrc(&clksrcs[ptr], true); | 1055 | s3c_set_clksrc(&clksrcs[ptr], true); |
diff --git a/arch/arm/mach-s5pv310/cpu.c b/arch/arm/mach-s5pv310/cpu.c index 4add39853ff9..82ce4aa6d61a 100644 --- a/arch/arm/mach-s5pv310/cpu.c +++ b/arch/arm/mach-s5pv310/cpu.c | |||
@@ -15,10 +15,12 @@ | |||
15 | #include <asm/mach/irq.h> | 15 | #include <asm/mach/irq.h> |
16 | 16 | ||
17 | #include <asm/proc-fns.h> | 17 | #include <asm/proc-fns.h> |
18 | #include <asm/hardware/cache-l2x0.h> | ||
18 | 19 | ||
19 | #include <plat/cpu.h> | 20 | #include <plat/cpu.h> |
20 | #include <plat/clock.h> | 21 | #include <plat/clock.h> |
21 | #include <plat/s5pv310.h> | 22 | #include <plat/s5pv310.h> |
23 | #include <plat/sdhci.h> | ||
22 | 24 | ||
23 | #include <mach/regs-irq.h> | 25 | #include <mach/regs-irq.h> |
24 | 26 | ||
@@ -56,15 +58,30 @@ static struct map_desc s5pv310_iodesc[] __initdata = { | |||
56 | .length = SZ_4K, | 58 | .length = SZ_4K, |
57 | .type = MT_DEVICE, | 59 | .type = MT_DEVICE, |
58 | }, { | 60 | }, { |
59 | .virtual = (unsigned long)S5P_VA_GPIO, | 61 | .virtual = (unsigned long)S5P_VA_GPIO1, |
60 | .pfn = __phys_to_pfn(S5PV310_PA_GPIO1), | 62 | .pfn = __phys_to_pfn(S5PV310_PA_GPIO1), |
61 | .length = SZ_4K, | 63 | .length = SZ_4K, |
62 | .type = MT_DEVICE, | 64 | .type = MT_DEVICE, |
63 | }, { | 65 | }, { |
66 | .virtual = (unsigned long)S5P_VA_GPIO2, | ||
67 | .pfn = __phys_to_pfn(S5PV310_PA_GPIO2), | ||
68 | .length = SZ_4K, | ||
69 | .type = MT_DEVICE, | ||
70 | }, { | ||
71 | .virtual = (unsigned long)S5P_VA_GPIO3, | ||
72 | .pfn = __phys_to_pfn(S5PV310_PA_GPIO3), | ||
73 | .length = SZ_256, | ||
74 | .type = MT_DEVICE, | ||
75 | }, { | ||
64 | .virtual = (unsigned long)S3C_VA_UART, | 76 | .virtual = (unsigned long)S3C_VA_UART, |
65 | .pfn = __phys_to_pfn(S3C_PA_UART), | 77 | .pfn = __phys_to_pfn(S3C_PA_UART), |
66 | .length = SZ_512K, | 78 | .length = SZ_512K, |
67 | .type = MT_DEVICE, | 79 | .type = MT_DEVICE, |
80 | }, { | ||
81 | .virtual = (unsigned long)S5P_VA_SROMC, | ||
82 | .pfn = __phys_to_pfn(S5PV310_PA_SROMC), | ||
83 | .length = SZ_4K, | ||
84 | .type = MT_DEVICE, | ||
68 | }, | 85 | }, |
69 | }; | 86 | }; |
70 | 87 | ||
@@ -83,6 +100,12 @@ static void s5pv310_idle(void) | |||
83 | void __init s5pv310_map_io(void) | 100 | void __init s5pv310_map_io(void) |
84 | { | 101 | { |
85 | iotable_init(s5pv310_iodesc, ARRAY_SIZE(s5pv310_iodesc)); | 102 | iotable_init(s5pv310_iodesc, ARRAY_SIZE(s5pv310_iodesc)); |
103 | |||
104 | /* initialize device information early */ | ||
105 | s5pv310_default_sdhci0(); | ||
106 | s5pv310_default_sdhci1(); | ||
107 | s5pv310_default_sdhci2(); | ||
108 | s5pv310_default_sdhci3(); | ||
86 | } | 109 | } |
87 | 110 | ||
88 | void __init s5pv310_init_clocks(int xtal) | 111 | void __init s5pv310_init_clocks(int xtal) |
@@ -131,6 +154,28 @@ static int __init s5pv310_core_init(void) | |||
131 | 154 | ||
132 | core_initcall(s5pv310_core_init); | 155 | core_initcall(s5pv310_core_init); |
133 | 156 | ||
157 | #ifdef CONFIG_CACHE_L2X0 | ||
158 | static int __init s5pv310_l2x0_cache_init(void) | ||
159 | { | ||
160 | /* TAG, Data Latency Control: 2cycle */ | ||
161 | __raw_writel(0x110, S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL); | ||
162 | __raw_writel(0x110, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL); | ||
163 | |||
164 | /* L2X0 Prefetch Control */ | ||
165 | __raw_writel(0x30000007, S5P_VA_L2CC + L2X0_PREFETCH_CTRL); | ||
166 | |||
167 | /* L2X0 Power Control */ | ||
168 | __raw_writel(L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN, | ||
169 | S5P_VA_L2CC + L2X0_POWER_CTRL); | ||
170 | |||
171 | l2x0_init(S5P_VA_L2CC, 0x7C070001, 0xC200ffff); | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | early_initcall(s5pv310_l2x0_cache_init); | ||
177 | #endif | ||
178 | |||
134 | int __init s5pv310_init(void) | 179 | int __init s5pv310_init(void) |
135 | { | 180 | { |
136 | printk(KERN_INFO "S5PV310: Initializing architecture\n"); | 181 | printk(KERN_INFO "S5PV310: Initializing architecture\n"); |
diff --git a/arch/arm/mach-s5pv310/gpiolib.c b/arch/arm/mach-s5pv310/gpiolib.c new file mode 100644 index 000000000000..55217b8923ec --- /dev/null +++ b/arch/arm/mach-s5pv310/gpiolib.c | |||
@@ -0,0 +1,304 @@ | |||
1 | /* linux/arch/arm/mach-s5pv310/gpiolib.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * S5PV310 - GPIOlib support | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/irq.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/gpio.h> | ||
17 | |||
18 | #include <mach/map.h> | ||
19 | |||
20 | #include <plat/gpio-core.h> | ||
21 | #include <plat/gpio-cfg.h> | ||
22 | #include <plat/gpio-cfg-helpers.h> | ||
23 | |||
24 | static struct s3c_gpio_cfg gpio_cfg = { | ||
25 | .set_config = s3c_gpio_setcfg_s3c64xx_4bit, | ||
26 | .set_pull = s3c_gpio_setpull_updown, | ||
27 | .get_pull = s3c_gpio_getpull_updown, | ||
28 | }; | ||
29 | |||
30 | static struct s3c_gpio_cfg gpio_cfg_noint = { | ||
31 | .set_config = s3c_gpio_setcfg_s3c64xx_4bit, | ||
32 | .set_pull = s3c_gpio_setpull_updown, | ||
33 | .get_pull = s3c_gpio_getpull_updown, | ||
34 | }; | ||
35 | |||
36 | /* | ||
37 | * Following are the gpio banks in v310. | ||
38 | * | ||
39 | * The 'config' member when left to NULL, is initialized to the default | ||
40 | * structure gpio_cfg in the init function below. | ||
41 | * | ||
42 | * The 'base' member is also initialized in the init function below. | ||
43 | * Note: The initialization of 'base' member of s3c_gpio_chip structure | ||
44 | * uses the above macro and depends on the banks being listed in order here. | ||
45 | */ | ||
46 | static struct s3c_gpio_chip s5pv310_gpio_part1_4bit[] = { | ||
47 | { | ||
48 | .chip = { | ||
49 | .base = S5PV310_GPA0(0), | ||
50 | .ngpio = S5PV310_GPIO_A0_NR, | ||
51 | .label = "GPA0", | ||
52 | }, | ||
53 | }, { | ||
54 | .chip = { | ||
55 | .base = S5PV310_GPA1(0), | ||
56 | .ngpio = S5PV310_GPIO_A1_NR, | ||
57 | .label = "GPA1", | ||
58 | }, | ||
59 | }, { | ||
60 | .chip = { | ||
61 | .base = S5PV310_GPB(0), | ||
62 | .ngpio = S5PV310_GPIO_B_NR, | ||
63 | .label = "GPB", | ||
64 | }, | ||
65 | }, { | ||
66 | .chip = { | ||
67 | .base = S5PV310_GPC0(0), | ||
68 | .ngpio = S5PV310_GPIO_C0_NR, | ||
69 | .label = "GPC0", | ||
70 | }, | ||
71 | }, { | ||
72 | .chip = { | ||
73 | .base = S5PV310_GPC1(0), | ||
74 | .ngpio = S5PV310_GPIO_C1_NR, | ||
75 | .label = "GPC1", | ||
76 | }, | ||
77 | }, { | ||
78 | .chip = { | ||
79 | .base = S5PV310_GPD0(0), | ||
80 | .ngpio = S5PV310_GPIO_D0_NR, | ||
81 | .label = "GPD0", | ||
82 | }, | ||
83 | }, { | ||
84 | .chip = { | ||
85 | .base = S5PV310_GPD1(0), | ||
86 | .ngpio = S5PV310_GPIO_D1_NR, | ||
87 | .label = "GPD1", | ||
88 | }, | ||
89 | }, { | ||
90 | .chip = { | ||
91 | .base = S5PV310_GPE0(0), | ||
92 | .ngpio = S5PV310_GPIO_E0_NR, | ||
93 | .label = "GPE0", | ||
94 | }, | ||
95 | }, { | ||
96 | .chip = { | ||
97 | .base = S5PV310_GPE1(0), | ||
98 | .ngpio = S5PV310_GPIO_E1_NR, | ||
99 | .label = "GPE1", | ||
100 | }, | ||
101 | }, { | ||
102 | .chip = { | ||
103 | .base = S5PV310_GPE2(0), | ||
104 | .ngpio = S5PV310_GPIO_E2_NR, | ||
105 | .label = "GPE2", | ||
106 | }, | ||
107 | }, { | ||
108 | .chip = { | ||
109 | .base = S5PV310_GPE3(0), | ||
110 | .ngpio = S5PV310_GPIO_E3_NR, | ||
111 | .label = "GPE3", | ||
112 | }, | ||
113 | }, { | ||
114 | .chip = { | ||
115 | .base = S5PV310_GPE4(0), | ||
116 | .ngpio = S5PV310_GPIO_E4_NR, | ||
117 | .label = "GPE4", | ||
118 | }, | ||
119 | }, { | ||
120 | .chip = { | ||
121 | .base = S5PV310_GPF0(0), | ||
122 | .ngpio = S5PV310_GPIO_F0_NR, | ||
123 | .label = "GPF0", | ||
124 | }, | ||
125 | }, { | ||
126 | .chip = { | ||
127 | .base = S5PV310_GPF1(0), | ||
128 | .ngpio = S5PV310_GPIO_F1_NR, | ||
129 | .label = "GPF1", | ||
130 | }, | ||
131 | }, { | ||
132 | .chip = { | ||
133 | .base = S5PV310_GPF2(0), | ||
134 | .ngpio = S5PV310_GPIO_F2_NR, | ||
135 | .label = "GPF2", | ||
136 | }, | ||
137 | }, { | ||
138 | .chip = { | ||
139 | .base = S5PV310_GPF3(0), | ||
140 | .ngpio = S5PV310_GPIO_F3_NR, | ||
141 | .label = "GPF3", | ||
142 | }, | ||
143 | }, | ||
144 | }; | ||
145 | |||
146 | static struct s3c_gpio_chip s5pv310_gpio_part2_4bit[] = { | ||
147 | { | ||
148 | .chip = { | ||
149 | .base = S5PV310_GPJ0(0), | ||
150 | .ngpio = S5PV310_GPIO_J0_NR, | ||
151 | .label = "GPJ0", | ||
152 | }, | ||
153 | }, { | ||
154 | .chip = { | ||
155 | .base = S5PV310_GPJ1(0), | ||
156 | .ngpio = S5PV310_GPIO_J1_NR, | ||
157 | .label = "GPJ1", | ||
158 | }, | ||
159 | }, { | ||
160 | .chip = { | ||
161 | .base = S5PV310_GPK0(0), | ||
162 | .ngpio = S5PV310_GPIO_K0_NR, | ||
163 | .label = "GPK0", | ||
164 | }, | ||
165 | }, { | ||
166 | .chip = { | ||
167 | .base = S5PV310_GPK1(0), | ||
168 | .ngpio = S5PV310_GPIO_K1_NR, | ||
169 | .label = "GPK1", | ||
170 | }, | ||
171 | }, { | ||
172 | .chip = { | ||
173 | .base = S5PV310_GPK2(0), | ||
174 | .ngpio = S5PV310_GPIO_K2_NR, | ||
175 | .label = "GPK2", | ||
176 | }, | ||
177 | }, { | ||
178 | .chip = { | ||
179 | .base = S5PV310_GPK3(0), | ||
180 | .ngpio = S5PV310_GPIO_K3_NR, | ||
181 | .label = "GPK3", | ||
182 | }, | ||
183 | }, { | ||
184 | .chip = { | ||
185 | .base = S5PV310_GPL0(0), | ||
186 | .ngpio = S5PV310_GPIO_L0_NR, | ||
187 | .label = "GPL0", | ||
188 | }, | ||
189 | }, { | ||
190 | .chip = { | ||
191 | .base = S5PV310_GPL1(0), | ||
192 | .ngpio = S5PV310_GPIO_L1_NR, | ||
193 | .label = "GPL1", | ||
194 | }, | ||
195 | }, { | ||
196 | .chip = { | ||
197 | .base = S5PV310_GPL2(0), | ||
198 | .ngpio = S5PV310_GPIO_L2_NR, | ||
199 | .label = "GPL2", | ||
200 | }, | ||
201 | }, { | ||
202 | .base = (S5P_VA_GPIO2 + 0xC00), | ||
203 | .config = &gpio_cfg_noint, | ||
204 | .irq_base = IRQ_EINT(0), | ||
205 | .chip = { | ||
206 | .base = S5PV310_GPX0(0), | ||
207 | .ngpio = S5PV310_GPIO_X0_NR, | ||
208 | .label = "GPX0", | ||
209 | .to_irq = samsung_gpiolib_to_irq, | ||
210 | }, | ||
211 | }, { | ||
212 | .base = (S5P_VA_GPIO2 + 0xC20), | ||
213 | .config = &gpio_cfg_noint, | ||
214 | .irq_base = IRQ_EINT(8), | ||
215 | .chip = { | ||
216 | .base = S5PV310_GPX1(0), | ||
217 | .ngpio = S5PV310_GPIO_X1_NR, | ||
218 | .label = "GPX1", | ||
219 | .to_irq = samsung_gpiolib_to_irq, | ||
220 | }, | ||
221 | }, { | ||
222 | .base = (S5P_VA_GPIO2 + 0xC40), | ||
223 | .config = &gpio_cfg_noint, | ||
224 | .irq_base = IRQ_EINT(16), | ||
225 | .chip = { | ||
226 | .base = S5PV310_GPX2(0), | ||
227 | .ngpio = S5PV310_GPIO_X2_NR, | ||
228 | .label = "GPX2", | ||
229 | .to_irq = samsung_gpiolib_to_irq, | ||
230 | }, | ||
231 | }, { | ||
232 | .base = (S5P_VA_GPIO2 + 0xC60), | ||
233 | .config = &gpio_cfg_noint, | ||
234 | .irq_base = IRQ_EINT(24), | ||
235 | .chip = { | ||
236 | .base = S5PV310_GPX3(0), | ||
237 | .ngpio = S5PV310_GPIO_X3_NR, | ||
238 | .label = "GPX3", | ||
239 | .to_irq = samsung_gpiolib_to_irq, | ||
240 | }, | ||
241 | }, | ||
242 | }; | ||
243 | |||
244 | static struct s3c_gpio_chip s5pv310_gpio_part3_4bit[] = { | ||
245 | { | ||
246 | .chip = { | ||
247 | .base = S5PV310_GPZ(0), | ||
248 | .ngpio = S5PV310_GPIO_Z_NR, | ||
249 | .label = "GPZ", | ||
250 | }, | ||
251 | }, | ||
252 | }; | ||
253 | |||
254 | static __init int s5pv310_gpiolib_init(void) | ||
255 | { | ||
256 | struct s3c_gpio_chip *chip; | ||
257 | int i; | ||
258 | int nr_chips; | ||
259 | |||
260 | /* GPIO part 1 */ | ||
261 | |||
262 | chip = s5pv310_gpio_part1_4bit; | ||
263 | nr_chips = ARRAY_SIZE(s5pv310_gpio_part1_4bit); | ||
264 | |||
265 | for (i = 0; i < nr_chips; i++, chip++) { | ||
266 | if (chip->config == NULL) | ||
267 | chip->config = &gpio_cfg; | ||
268 | if (chip->base == NULL) | ||
269 | chip->base = S5P_VA_GPIO1 + (i) * 0x20; | ||
270 | } | ||
271 | |||
272 | samsung_gpiolib_add_4bit_chips(s5pv310_gpio_part1_4bit, nr_chips); | ||
273 | |||
274 | /* GPIO part 2 */ | ||
275 | |||
276 | chip = s5pv310_gpio_part2_4bit; | ||
277 | nr_chips = ARRAY_SIZE(s5pv310_gpio_part2_4bit); | ||
278 | |||
279 | for (i = 0; i < nr_chips; i++, chip++) { | ||
280 | if (chip->config == NULL) | ||
281 | chip->config = &gpio_cfg; | ||
282 | if (chip->base == NULL) | ||
283 | chip->base = S5P_VA_GPIO2 + (i) * 0x20; | ||
284 | } | ||
285 | |||
286 | samsung_gpiolib_add_4bit_chips(s5pv310_gpio_part2_4bit, nr_chips); | ||
287 | |||
288 | /* GPIO part 3 */ | ||
289 | |||
290 | chip = s5pv310_gpio_part3_4bit; | ||
291 | nr_chips = ARRAY_SIZE(s5pv310_gpio_part3_4bit); | ||
292 | |||
293 | for (i = 0; i < nr_chips; i++, chip++) { | ||
294 | if (chip->config == NULL) | ||
295 | chip->config = &gpio_cfg; | ||
296 | if (chip->base == NULL) | ||
297 | chip->base = S5P_VA_GPIO3 + (i) * 0x20; | ||
298 | } | ||
299 | |||
300 | samsung_gpiolib_add_4bit_chips(s5pv310_gpio_part3_4bit, nr_chips); | ||
301 | |||
302 | return 0; | ||
303 | } | ||
304 | core_initcall(s5pv310_gpiolib_init); | ||
diff --git a/arch/arm/mach-s5pv310/hotplug.c b/arch/arm/mach-s5pv310/hotplug.c new file mode 100644 index 000000000000..03652c3605f6 --- /dev/null +++ b/arch/arm/mach-s5pv310/hotplug.c | |||
@@ -0,0 +1,144 @@ | |||
1 | /* linux arch/arm/mach-s5pv310/hotplug.c | ||
2 | * | ||
3 | * Cloned from linux/arch/arm/mach-realview/hotplug.c | ||
4 | * | ||
5 | * Copyright (C) 2002 ARM Ltd. | ||
6 | * All Rights Reserved | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/smp.h> | ||
16 | #include <linux/completion.h> | ||
17 | |||
18 | #include <asm/cacheflush.h> | ||
19 | |||
20 | extern volatile int pen_release; | ||
21 | |||
22 | static DECLARE_COMPLETION(cpu_killed); | ||
23 | |||
24 | static inline void cpu_enter_lowpower(void) | ||
25 | { | ||
26 | unsigned int v; | ||
27 | |||
28 | flush_cache_all(); | ||
29 | asm volatile( | ||
30 | " mcr p15, 0, %1, c7, c5, 0\n" | ||
31 | " mcr p15, 0, %1, c7, c10, 4\n" | ||
32 | /* | ||
33 | * Turn off coherency | ||
34 | */ | ||
35 | " mrc p15, 0, %0, c1, c0, 1\n" | ||
36 | " bic %0, %0, #0x20\n" | ||
37 | " mcr p15, 0, %0, c1, c0, 1\n" | ||
38 | " mrc p15, 0, %0, c1, c0, 0\n" | ||
39 | " bic %0, %0, #0x04\n" | ||
40 | " mcr p15, 0, %0, c1, c0, 0\n" | ||
41 | : "=&r" (v) | ||
42 | : "r" (0) | ||
43 | : "cc"); | ||
44 | } | ||
45 | |||
46 | static inline void cpu_leave_lowpower(void) | ||
47 | { | ||
48 | unsigned int v; | ||
49 | |||
50 | asm volatile( | ||
51 | "mrc p15, 0, %0, c1, c0, 0\n" | ||
52 | " orr %0, %0, #0x04\n" | ||
53 | " mcr p15, 0, %0, c1, c0, 0\n" | ||
54 | " mrc p15, 0, %0, c1, c0, 1\n" | ||
55 | " orr %0, %0, #0x20\n" | ||
56 | " mcr p15, 0, %0, c1, c0, 1\n" | ||
57 | : "=&r" (v) | ||
58 | : | ||
59 | : "cc"); | ||
60 | } | ||
61 | |||
62 | static inline void platform_do_lowpower(unsigned int cpu) | ||
63 | { | ||
64 | /* | ||
65 | * there is no power-control hardware on this platform, so all | ||
66 | * we can do is put the core into WFI; this is safe as the calling | ||
67 | * code will have already disabled interrupts | ||
68 | */ | ||
69 | for (;;) { | ||
70 | /* | ||
71 | * here's the WFI | ||
72 | */ | ||
73 | asm(".word 0xe320f003\n" | ||
74 | : | ||
75 | : | ||
76 | : "memory", "cc"); | ||
77 | |||
78 | if (pen_release == cpu) { | ||
79 | /* | ||
80 | * OK, proper wakeup, we're done | ||
81 | */ | ||
82 | break; | ||
83 | } | ||
84 | |||
85 | /* | ||
86 | * getting here, means that we have come out of WFI without | ||
87 | * having been woken up - this shouldn't happen | ||
88 | * | ||
89 | * The trouble is, letting people know about this is not really | ||
90 | * possible, since we are currently running incoherently, and | ||
91 | * therefore cannot safely call printk() or anything else | ||
92 | */ | ||
93 | #ifdef DEBUG | ||
94 | printk(KERN_WARN "CPU%u: spurious wakeup call\n", cpu); | ||
95 | #endif | ||
96 | } | ||
97 | } | ||
98 | |||
99 | int platform_cpu_kill(unsigned int cpu) | ||
100 | { | ||
101 | return wait_for_completion_timeout(&cpu_killed, 5000); | ||
102 | } | ||
103 | |||
104 | /* | ||
105 | * platform-specific code to shutdown a CPU | ||
106 | * | ||
107 | * Called with IRQs disabled | ||
108 | */ | ||
109 | void platform_cpu_die(unsigned int cpu) | ||
110 | { | ||
111 | #ifdef DEBUG | ||
112 | unsigned int this_cpu = hard_smp_processor_id(); | ||
113 | |||
114 | if (cpu != this_cpu) { | ||
115 | printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n", | ||
116 | this_cpu, cpu); | ||
117 | BUG(); | ||
118 | } | ||
119 | #endif | ||
120 | |||
121 | printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); | ||
122 | complete(&cpu_killed); | ||
123 | |||
124 | /* | ||
125 | * we're ready for shutdown now, so do it | ||
126 | */ | ||
127 | cpu_enter_lowpower(); | ||
128 | platform_do_lowpower(cpu); | ||
129 | |||
130 | /* | ||
131 | * bring this CPU back into the world of cache | ||
132 | * coherency, and then restore interrupts | ||
133 | */ | ||
134 | cpu_leave_lowpower(); | ||
135 | } | ||
136 | |||
137 | int platform_cpu_disable(unsigned int cpu) | ||
138 | { | ||
139 | /* | ||
140 | * we don't allow CPU 0 to be shutdown (it is still too special | ||
141 | * e.g. clock tick interrupts) | ||
142 | */ | ||
143 | return cpu == 0 ? -EPERM : 0; | ||
144 | } | ||
diff --git a/arch/arm/mach-s5pv310/include/mach/irqs.h b/arch/arm/mach-s5pv310/include/mach/irqs.h index 471fc3bb199a..99e7dad8a85a 100644 --- a/arch/arm/mach-s5pv310/include/mach/irqs.h +++ b/arch/arm/mach-s5pv310/include/mach/irqs.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | 3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. |
4 | * http://www.samsung.com/ | 4 | * http://www.samsung.com/ |
5 | * | 5 | * |
6 | * S5PV210 - IRQ definitions | 6 | * S5PV310 - IRQ definitions |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -60,6 +60,9 @@ | |||
60 | #define IRQ_TIMER3_VIC COMBINER_IRQ(22, 3) | 60 | #define IRQ_TIMER3_VIC COMBINER_IRQ(22, 3) |
61 | #define IRQ_TIMER4_VIC COMBINER_IRQ(22, 4) | 61 | #define IRQ_TIMER4_VIC COMBINER_IRQ(22, 4) |
62 | 62 | ||
63 | #define IRQ_RTC_ALARM COMBINER_IRQ(23, 0) | ||
64 | #define IRQ_RTC_TIC COMBINER_IRQ(23, 1) | ||
65 | |||
63 | #define IRQ_UART0 COMBINER_IRQ(26, 0) | 66 | #define IRQ_UART0 COMBINER_IRQ(26, 0) |
64 | #define IRQ_UART1 COMBINER_IRQ(26, 1) | 67 | #define IRQ_UART1 COMBINER_IRQ(26, 1) |
65 | #define IRQ_UART2 COMBINER_IRQ(26, 2) | 68 | #define IRQ_UART2 COMBINER_IRQ(26, 2) |
@@ -67,13 +70,46 @@ | |||
67 | #define IRQ_UART4 COMBINER_IRQ(26, 4) | 70 | #define IRQ_UART4 COMBINER_IRQ(26, 4) |
68 | 71 | ||
69 | #define IRQ_IIC COMBINER_IRQ(27, 0) | 72 | #define IRQ_IIC COMBINER_IRQ(27, 0) |
73 | #define IRQ_IIC1 COMBINER_IRQ(27, 1) | ||
74 | #define IRQ_IIC2 COMBINER_IRQ(27, 2) | ||
75 | #define IRQ_IIC3 COMBINER_IRQ(27, 3) | ||
76 | #define IRQ_IIC4 COMBINER_IRQ(27, 4) | ||
77 | #define IRQ_IIC5 COMBINER_IRQ(27, 5) | ||
78 | #define IRQ_IIC6 COMBINER_IRQ(27, 6) | ||
79 | #define IRQ_IIC7 COMBINER_IRQ(27, 7) | ||
80 | |||
81 | #define IRQ_HSMMC0 COMBINER_IRQ(29, 0) | ||
82 | #define IRQ_HSMMC1 COMBINER_IRQ(29, 1) | ||
83 | #define IRQ_HSMMC2 COMBINER_IRQ(29, 2) | ||
84 | #define IRQ_HSMMC3 COMBINER_IRQ(29, 3) | ||
70 | 85 | ||
71 | #define IRQ_ONENAND_AUDI COMBINER_IRQ(34, 0) | 86 | #define IRQ_ONENAND_AUDI COMBINER_IRQ(34, 0) |
72 | 87 | ||
73 | /* Set the default NR_IRQS */ | 88 | #define IRQ_EINT4 COMBINER_IRQ(37, 0) |
89 | #define IRQ_EINT5 COMBINER_IRQ(37, 1) | ||
90 | #define IRQ_EINT6 COMBINER_IRQ(37, 2) | ||
91 | #define IRQ_EINT7 COMBINER_IRQ(37, 3) | ||
92 | #define IRQ_EINT8 COMBINER_IRQ(38, 0) | ||
93 | |||
94 | #define IRQ_EINT9 COMBINER_IRQ(38, 1) | ||
95 | #define IRQ_EINT10 COMBINER_IRQ(38, 2) | ||
96 | #define IRQ_EINT11 COMBINER_IRQ(38, 3) | ||
97 | #define IRQ_EINT12 COMBINER_IRQ(38, 4) | ||
98 | #define IRQ_EINT13 COMBINER_IRQ(38, 5) | ||
99 | #define IRQ_EINT14 COMBINER_IRQ(38, 6) | ||
100 | #define IRQ_EINT15 COMBINER_IRQ(38, 7) | ||
101 | |||
102 | #define IRQ_EINT16_31 COMBINER_IRQ(39, 0) | ||
74 | 103 | ||
75 | #define NR_IRQS COMBINER_IRQ(MAX_COMBINER_NR, 0) | 104 | #define MAX_COMBINER_NR 40 |
105 | |||
106 | #define S5P_IRQ_EINT_BASE COMBINER_IRQ(MAX_COMBINER_NR, 0) | ||
107 | |||
108 | #define S5P_EINT_BASE1 (S5P_IRQ_EINT_BASE + 0) | ||
109 | #define S5P_EINT_BASE2 (S5P_IRQ_EINT_BASE + 16) | ||
110 | |||
111 | /* Set the default NR_IRQS */ | ||
76 | 112 | ||
77 | #define MAX_COMBINER_NR 39 | 113 | #define NR_IRQS (S5P_IRQ_EINT_BASE + 32) |
78 | 114 | ||
79 | #endif /* __ASM_ARCH_IRQS_H */ | 115 | #endif /* __ASM_ARCH_IRQS_H */ |
diff --git a/arch/arm/mach-s5pv310/include/mach/map.h b/arch/arm/mach-s5pv310/include/mach/map.h index aff6d23624bb..7acf4e77e92e 100644 --- a/arch/arm/mach-s5pv310/include/mach/map.h +++ b/arch/arm/mach-s5pv310/include/mach/map.h | |||
@@ -25,6 +25,8 @@ | |||
25 | 25 | ||
26 | #define S5PV310_PA_SYSRAM (0x02025000) | 26 | #define S5PV310_PA_SYSRAM (0x02025000) |
27 | 27 | ||
28 | #define S5PV310_PA_SROM_BANK(x) (0x04000000 + ((x) * 0x01000000)) | ||
29 | |||
28 | #define S5PC210_PA_ONENAND (0x0C000000) | 30 | #define S5PC210_PA_ONENAND (0x0C000000) |
29 | #define S5P_PA_ONENAND S5PC210_PA_ONENAND | 31 | #define S5P_PA_ONENAND S5PC210_PA_ONENAND |
30 | 32 | ||
@@ -34,12 +36,13 @@ | |||
34 | #define S5PV310_PA_CHIPID (0x10000000) | 36 | #define S5PV310_PA_CHIPID (0x10000000) |
35 | #define S5P_PA_CHIPID S5PV310_PA_CHIPID | 37 | #define S5P_PA_CHIPID S5PV310_PA_CHIPID |
36 | 38 | ||
37 | #define S5PV310_PA_SYSCON (0x10020000) | 39 | #define S5PV310_PA_SYSCON (0x10010000) |
38 | #define S5P_PA_SYSCON S5PV310_PA_SYSCON | 40 | #define S5P_PA_SYSCON S5PV310_PA_SYSCON |
39 | 41 | ||
40 | #define S5PV310_PA_CMU (0x10030000) | 42 | #define S5PV310_PA_CMU (0x10030000) |
41 | 43 | ||
42 | #define S5PV310_PA_WATCHDOG (0x10060000) | 44 | #define S5PV310_PA_WATCHDOG (0x10060000) |
45 | #define S5PV310_PA_RTC (0x10070000) | ||
43 | 46 | ||
44 | #define S5PV310_PA_COMBINER (0x10448000) | 47 | #define S5PV310_PA_COMBINER (0x10448000) |
45 | 48 | ||
@@ -55,6 +58,8 @@ | |||
55 | 58 | ||
56 | #define S5PV310_PA_HSMMC(x) (0x12510000 + ((x) * 0x10000)) | 59 | #define S5PV310_PA_HSMMC(x) (0x12510000 + ((x) * 0x10000)) |
57 | 60 | ||
61 | #define S5PV310_PA_SROMC (0x12570000) | ||
62 | |||
58 | #define S5PV310_PA_UART (0x13800000) | 63 | #define S5PV310_PA_UART (0x13800000) |
59 | 64 | ||
60 | #define S5P_PA_UART(x) (S5PV310_PA_UART + ((x) * S3C_UART_OFFSET)) | 65 | #define S5P_PA_UART(x) (S5PV310_PA_UART + ((x) * S3C_UART_OFFSET)) |
@@ -66,7 +71,7 @@ | |||
66 | 71 | ||
67 | #define S5P_SZ_UART SZ_256 | 72 | #define S5P_SZ_UART SZ_256 |
68 | 73 | ||
69 | #define S5PV310_PA_IIC0 (0x13860000) | 74 | #define S5PV310_PA_IIC(x) (0x13860000 + ((x) * 0x10000)) |
70 | 75 | ||
71 | #define S5PV310_PA_TIMER (0x139D0000) | 76 | #define S5PV310_PA_TIMER (0x139D0000) |
72 | #define S5P_PA_TIMER S5PV310_PA_TIMER | 77 | #define S5P_PA_TIMER S5PV310_PA_TIMER |
@@ -80,7 +85,15 @@ | |||
80 | #define S3C_PA_HSMMC1 S5PV310_PA_HSMMC(1) | 85 | #define S3C_PA_HSMMC1 S5PV310_PA_HSMMC(1) |
81 | #define S3C_PA_HSMMC2 S5PV310_PA_HSMMC(2) | 86 | #define S3C_PA_HSMMC2 S5PV310_PA_HSMMC(2) |
82 | #define S3C_PA_HSMMC3 S5PV310_PA_HSMMC(3) | 87 | #define S3C_PA_HSMMC3 S5PV310_PA_HSMMC(3) |
83 | #define S3C_PA_IIC S5PV310_PA_IIC0 | 88 | #define S3C_PA_IIC S5PV310_PA_IIC(0) |
89 | #define S3C_PA_IIC1 S5PV310_PA_IIC(1) | ||
90 | #define S3C_PA_IIC2 S5PV310_PA_IIC(2) | ||
91 | #define S3C_PA_IIC3 S5PV310_PA_IIC(3) | ||
92 | #define S3C_PA_IIC4 S5PV310_PA_IIC(4) | ||
93 | #define S3C_PA_IIC5 S5PV310_PA_IIC(5) | ||
94 | #define S3C_PA_IIC6 S5PV310_PA_IIC(6) | ||
95 | #define S3C_PA_IIC7 S5PV310_PA_IIC(7) | ||
96 | #define S3C_PA_RTC S5PV310_PA_RTC | ||
84 | #define S3C_PA_WDT S5PV310_PA_WATCHDOG | 97 | #define S3C_PA_WDT S5PV310_PA_WATCHDOG |
85 | 98 | ||
86 | #endif /* __ASM_ARCH_MAP_H */ | 99 | #endif /* __ASM_ARCH_MAP_H */ |
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-clock.h b/arch/arm/mach-s5pv310/include/mach/regs-clock.h index 4013553cd9be..f1028cad9788 100644 --- a/arch/arm/mach-s5pv310/include/mach/regs-clock.h +++ b/arch/arm/mach-s5pv310/include/mach/regs-clock.h | |||
@@ -26,11 +26,23 @@ | |||
26 | 26 | ||
27 | #define S5P_CLKSRC_TOP0 S5P_CLKREG(0x0C210) | 27 | #define S5P_CLKSRC_TOP0 S5P_CLKREG(0x0C210) |
28 | #define S5P_CLKSRC_TOP1 S5P_CLKREG(0x0C214) | 28 | #define S5P_CLKSRC_TOP1 S5P_CLKREG(0x0C214) |
29 | 29 | #define S5P_CLKSRC_CAM S5P_CLKREG(0x0C220) | |
30 | #define S5P_CLKSRC_IMAGE S5P_CLKREG(0x0C230) | ||
31 | #define S5P_CLKSRC_LCD0 S5P_CLKREG(0x0C234) | ||
32 | #define S5P_CLKSRC_LCD1 S5P_CLKREG(0x0C238) | ||
33 | #define S5P_CLKSRC_FSYS S5P_CLKREG(0x0C240) | ||
30 | #define S5P_CLKSRC_PERIL0 S5P_CLKREG(0x0C250) | 34 | #define S5P_CLKSRC_PERIL0 S5P_CLKREG(0x0C250) |
35 | #define S5P_CLKSRC_PERIL1 S5P_CLKREG(0x0C254) | ||
31 | 36 | ||
32 | #define S5P_CLKDIV_TOP S5P_CLKREG(0x0C510) | 37 | #define S5P_CLKDIV_TOP S5P_CLKREG(0x0C510) |
33 | 38 | #define S5P_CLKDIV_CAM S5P_CLKREG(0x0C520) | |
39 | #define S5P_CLKDIV_IMAGE S5P_CLKREG(0x0C530) | ||
40 | #define S5P_CLKDIV_LCD0 S5P_CLKREG(0x0C534) | ||
41 | #define S5P_CLKDIV_LCD1 S5P_CLKREG(0x0C538) | ||
42 | #define S5P_CLKDIV_FSYS0 S5P_CLKREG(0x0C540) | ||
43 | #define S5P_CLKDIV_FSYS1 S5P_CLKREG(0x0C544) | ||
44 | #define S5P_CLKDIV_FSYS2 S5P_CLKREG(0x0C548) | ||
45 | #define S5P_CLKDIV_FSYS3 S5P_CLKREG(0x0C54C) | ||
34 | #define S5P_CLKDIV_PERIL0 S5P_CLKREG(0x0C550) | 46 | #define S5P_CLKDIV_PERIL0 S5P_CLKREG(0x0C550) |
35 | #define S5P_CLKDIV_PERIL1 S5P_CLKREG(0x0C554) | 47 | #define S5P_CLKDIV_PERIL1 S5P_CLKREG(0x0C554) |
36 | #define S5P_CLKDIV_PERIL2 S5P_CLKREG(0x0C558) | 48 | #define S5P_CLKDIV_PERIL2 S5P_CLKREG(0x0C558) |
@@ -38,9 +50,21 @@ | |||
38 | #define S5P_CLKDIV_PERIL4 S5P_CLKREG(0x0C560) | 50 | #define S5P_CLKDIV_PERIL4 S5P_CLKREG(0x0C560) |
39 | #define S5P_CLKDIV_PERIL5 S5P_CLKREG(0x0C564) | 51 | #define S5P_CLKDIV_PERIL5 S5P_CLKREG(0x0C564) |
40 | 52 | ||
53 | #define S5P_CLKSRC_MASK_TOP S5P_CLKREG(0x0C310) | ||
54 | #define S5P_CLKSRC_MASK_CAM S5P_CLKREG(0x0C320) | ||
55 | #define S5P_CLKSRC_MASK_LCD0 S5P_CLKREG(0x0C334) | ||
56 | #define S5P_CLKSRC_MASK_LCD1 S5P_CLKREG(0x0C338) | ||
57 | #define S5P_CLKSRC_MASK_FSYS S5P_CLKREG(0x0C340) | ||
41 | #define S5P_CLKSRC_MASK_PERIL0 S5P_CLKREG(0x0C350) | 58 | #define S5P_CLKSRC_MASK_PERIL0 S5P_CLKREG(0x0C350) |
59 | #define S5P_CLKSRC_MASK_PERIL1 S5P_CLKREG(0x0C354) | ||
42 | 60 | ||
61 | #define S5P_CLKGATE_IP_CAM S5P_CLKREG(0x0C920) | ||
62 | #define S5P_CLKGATE_IP_IMAGE S5P_CLKREG(0x0C930) | ||
63 | #define S5P_CLKGATE_IP_LCD0 S5P_CLKREG(0x0C934) | ||
64 | #define S5P_CLKGATE_IP_LCD1 S5P_CLKREG(0x0C938) | ||
65 | #define S5P_CLKGATE_IP_FSYS S5P_CLKREG(0x0C940) | ||
43 | #define S5P_CLKGATE_IP_PERIL S5P_CLKREG(0x0C950) | 66 | #define S5P_CLKGATE_IP_PERIL S5P_CLKREG(0x0C950) |
67 | #define S5P_CLKGATE_IP_PERIR S5P_CLKREG(0x0C960) | ||
44 | 68 | ||
45 | #define S5P_CLKSRC_CORE S5P_CLKREG(0x10200) | 69 | #define S5P_CLKSRC_CORE S5P_CLKREG(0x10200) |
46 | #define S5P_CLKDIV_CORE0 S5P_CLKREG(0x10500) | 70 | #define S5P_CLKDIV_CORE0 S5P_CLKREG(0x10500) |
@@ -60,4 +84,8 @@ | |||
60 | 84 | ||
61 | #define S5P_CLKGATE_SCLKCPU S5P_CLKREG(0x14800) | 85 | #define S5P_CLKGATE_SCLKCPU S5P_CLKREG(0x14800) |
62 | 86 | ||
87 | /* Compatibility defines */ | ||
88 | |||
89 | #define S5P_EPLL_CON S5P_EPLL_CON0 | ||
90 | |||
63 | #endif /* __ASM_ARCH_REGS_CLOCK_H */ | 91 | #endif /* __ASM_ARCH_REGS_CLOCK_H */ |
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-gpio.h b/arch/arm/mach-s5pv310/include/mach/regs-gpio.h new file mode 100644 index 000000000000..82e9e0c9d452 --- /dev/null +++ b/arch/arm/mach-s5pv310/include/mach/regs-gpio.h | |||
@@ -0,0 +1,42 @@ | |||
1 | /* linux/arch/arm/mach-s5pv310/include/mach/regs-gpio.h | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * S5PV310 - GPIO (including EINT) register definitions | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __ASM_ARCH_REGS_GPIO_H | ||
14 | #define __ASM_ARCH_REGS_GPIO_H __FILE__ | ||
15 | |||
16 | #include <mach/map.h> | ||
17 | #include <mach/irqs.h> | ||
18 | |||
19 | #define S5PV310_EINT40CON (S5P_VA_GPIO2 + 0xE00) | ||
20 | #define S5P_EINT_CON(x) (S5PV310_EINT40CON + ((x) * 0x4)) | ||
21 | |||
22 | #define S5PV310_EINT40FLTCON0 (S5P_VA_GPIO2 + 0xE80) | ||
23 | #define S5P_EINT_FLTCON(x) (S5PV310_EINT40FLTCON0 + ((x) * 0x4)) | ||
24 | |||
25 | #define S5PV310_EINT40MASK (S5P_VA_GPIO2 + 0xF00) | ||
26 | #define S5P_EINT_MASK(x) (S5PV310_EINT40MASK + ((x) * 0x4)) | ||
27 | |||
28 | #define S5PV310_EINT40PEND (S5P_VA_GPIO2 + 0xF40) | ||
29 | #define S5P_EINT_PEND(x) (S5PV310_EINT40PEND + ((x) * 0x4)) | ||
30 | |||
31 | #define EINT_REG_NR(x) (EINT_OFFSET(x) >> 3) | ||
32 | |||
33 | #define eint_irq_to_bit(irq) (1 << (EINT_OFFSET(irq) & 0x7)) | ||
34 | |||
35 | #define EINT_MODE S3C_GPIO_SFN(0xf) | ||
36 | |||
37 | #define EINT_GPIO_0(x) S5PV310_GPX0(x) | ||
38 | #define EINT_GPIO_1(x) S5PV310_GPX1(x) | ||
39 | #define EINT_GPIO_2(x) S5PV310_GPX2(x) | ||
40 | #define EINT_GPIO_3(x) S5PV310_GPX3(x) | ||
41 | |||
42 | #endif /* __ASM_ARCH_REGS_GPIO_H */ | ||
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-srom.h b/arch/arm/mach-s5pv310/include/mach/regs-srom.h new file mode 100644 index 000000000000..1898b3e10550 --- /dev/null +++ b/arch/arm/mach-s5pv310/include/mach/regs-srom.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /* linux/arch/arm/mach-s5pv310/include/mach/regs-srom.h | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * S5PV310 - SROMC register definitions | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __ASM_ARCH_REGS_SROM_H | ||
14 | #define __ASM_ARCH_REGS_SROM_H __FILE__ | ||
15 | |||
16 | #include <mach/map.h> | ||
17 | |||
18 | #define S5PV310_SROMREG(x) (S5P_VA_SROMC + (x)) | ||
19 | |||
20 | #define S5PV310_SROM_BW S5PV310_SROMREG(0x0) | ||
21 | #define S5PV310_SROM_BC0 S5PV310_SROMREG(0x4) | ||
22 | #define S5PV310_SROM_BC1 S5PV310_SROMREG(0x8) | ||
23 | #define S5PV310_SROM_BC2 S5PV310_SROMREG(0xc) | ||
24 | #define S5PV310_SROM_BC3 S5PV310_SROMREG(0x10) | ||
25 | |||
26 | /* one register BW holds 4 x 4-bit packed settings for NCS0 - NCS3 */ | ||
27 | |||
28 | #define S5PV310_SROM_BW__DATAWIDTH__SHIFT 0 | ||
29 | #define S5PV310_SROM_BW__ADDRMODE__SHIFT 1 | ||
30 | #define S5PV310_SROM_BW__WAITENABLE__SHIFT 2 | ||
31 | #define S5PV310_SROM_BW__BYTEENABLE__SHIFT 3 | ||
32 | |||
33 | #define S5PV310_SROM_BW__CS_MASK 0xf | ||
34 | |||
35 | #define S5PV310_SROM_BW__NCS0__SHIFT 0 | ||
36 | #define S5PV310_SROM_BW__NCS1__SHIFT 4 | ||
37 | #define S5PV310_SROM_BW__NCS2__SHIFT 8 | ||
38 | #define S5PV310_SROM_BW__NCS3__SHIFT 12 | ||
39 | |||
40 | /* applies to same to BCS0 - BCS3 */ | ||
41 | |||
42 | #define S5PV310_SROM_BCX__PMC__SHIFT 0 | ||
43 | #define S5PV310_SROM_BCX__TACP__SHIFT 4 | ||
44 | #define S5PV310_SROM_BCX__TCAH__SHIFT 8 | ||
45 | #define S5PV310_SROM_BCX__TCOH__SHIFT 12 | ||
46 | #define S5PV310_SROM_BCX__TACC__SHIFT 16 | ||
47 | #define S5PV310_SROM_BCX__TCOS__SHIFT 24 | ||
48 | #define S5PV310_SROM_BCX__TACS__SHIFT 28 | ||
49 | |||
50 | #endif /* __ASM_ARCH_REGS_SROM_H */ | ||
diff --git a/arch/arm/mach-s5pv310/include/mach/vmalloc.h b/arch/arm/mach-s5pv310/include/mach/vmalloc.h index 256f221edf3a..65759fb97581 100644 --- a/arch/arm/mach-s5pv310/include/mach/vmalloc.h +++ b/arch/arm/mach-s5pv310/include/mach/vmalloc.h | |||
@@ -17,6 +17,6 @@ | |||
17 | #ifndef __ASM_ARCH_VMALLOC_H | 17 | #ifndef __ASM_ARCH_VMALLOC_H |
18 | #define __ASM_ARCH_VMALLOC_H __FILE__ | 18 | #define __ASM_ARCH_VMALLOC_H __FILE__ |
19 | 19 | ||
20 | #define VMALLOC_END (0xF0000000UL) | 20 | #define VMALLOC_END 0xF6000000UL |
21 | 21 | ||
22 | #endif /* __ASM_ARCH_VMALLOC_H */ | 22 | #endif /* __ASM_ARCH_VMALLOC_H */ |
diff --git a/arch/arm/mach-s5pv310/irq-combiner.c b/arch/arm/mach-s5pv310/irq-combiner.c index 0f7052164f23..c3f88c3faf6c 100644 --- a/arch/arm/mach-s5pv310/irq-combiner.c +++ b/arch/arm/mach-s5pv310/irq-combiner.c | |||
@@ -66,11 +66,7 @@ static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) | |||
66 | if (status == 0) | 66 | if (status == 0) |
67 | goto out; | 67 | goto out; |
68 | 68 | ||
69 | for (combiner_irq = 0; combiner_irq < 32; combiner_irq++) { | 69 | combiner_irq = __ffs(status); |
70 | if (status & 0x1) | ||
71 | break; | ||
72 | status >>= 1; | ||
73 | } | ||
74 | 70 | ||
75 | cascade_irq = combiner_irq + (chip_data->irq_offset & ~31); | 71 | cascade_irq = combiner_irq + (chip_data->irq_offset & ~31); |
76 | if (unlikely(cascade_irq >= NR_IRQS)) | 72 | if (unlikely(cascade_irq >= NR_IRQS)) |
diff --git a/arch/arm/mach-s5pv310/irq-eint.c b/arch/arm/mach-s5pv310/irq-eint.c new file mode 100644 index 000000000000..5877503e92c3 --- /dev/null +++ b/arch/arm/mach-s5pv310/irq-eint.c | |||
@@ -0,0 +1,228 @@ | |||
1 | /* linux/arch/arm/mach-s5pv310/irq-eint.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * S5PV310 - IRQ EINT support | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/irq.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/sysdev.h> | ||
18 | #include <linux/gpio.h> | ||
19 | |||
20 | #include <plat/pm.h> | ||
21 | #include <plat/cpu.h> | ||
22 | #include <plat/gpio-cfg.h> | ||
23 | |||
24 | #include <mach/regs-gpio.h> | ||
25 | |||
26 | static DEFINE_SPINLOCK(eint_lock); | ||
27 | |||
28 | static unsigned int eint0_15_data[16]; | ||
29 | |||
30 | static unsigned int s5pv310_get_irq_nr(unsigned int number) | ||
31 | { | ||
32 | u32 ret = 0; | ||
33 | |||
34 | switch (number) { | ||
35 | case 0 ... 3: | ||
36 | ret = (number + IRQ_EINT0); | ||
37 | break; | ||
38 | case 4 ... 7: | ||
39 | ret = (number + (IRQ_EINT4 - 4)); | ||
40 | break; | ||
41 | case 8 ... 15: | ||
42 | ret = (number + (IRQ_EINT8 - 8)); | ||
43 | break; | ||
44 | default: | ||
45 | printk(KERN_ERR "number available : %d\n", number); | ||
46 | } | ||
47 | |||
48 | return ret; | ||
49 | } | ||
50 | |||
51 | static inline void s5pv310_irq_eint_mask(unsigned int irq) | ||
52 | { | ||
53 | u32 mask; | ||
54 | |||
55 | spin_lock(&eint_lock); | ||
56 | mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(irq))); | ||
57 | mask |= eint_irq_to_bit(irq); | ||
58 | __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(irq))); | ||
59 | spin_unlock(&eint_lock); | ||
60 | } | ||
61 | |||
62 | static void s5pv310_irq_eint_unmask(unsigned int irq) | ||
63 | { | ||
64 | u32 mask; | ||
65 | |||
66 | spin_lock(&eint_lock); | ||
67 | mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(irq))); | ||
68 | mask &= ~(eint_irq_to_bit(irq)); | ||
69 | __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(irq))); | ||
70 | spin_unlock(&eint_lock); | ||
71 | } | ||
72 | |||
73 | static inline void s5pv310_irq_eint_ack(unsigned int irq) | ||
74 | { | ||
75 | __raw_writel(eint_irq_to_bit(irq), S5P_EINT_PEND(EINT_REG_NR(irq))); | ||
76 | } | ||
77 | |||
78 | static void s5pv310_irq_eint_maskack(unsigned int irq) | ||
79 | { | ||
80 | s5pv310_irq_eint_mask(irq); | ||
81 | s5pv310_irq_eint_ack(irq); | ||
82 | } | ||
83 | |||
84 | static int s5pv310_irq_eint_set_type(unsigned int irq, unsigned int type) | ||
85 | { | ||
86 | int offs = EINT_OFFSET(irq); | ||
87 | int shift; | ||
88 | u32 ctrl, mask; | ||
89 | u32 newvalue = 0; | ||
90 | |||
91 | switch (type) { | ||
92 | case IRQ_TYPE_EDGE_RISING: | ||
93 | newvalue = S5P_IRQ_TYPE_EDGE_RISING; | ||
94 | break; | ||
95 | |||
96 | case IRQ_TYPE_EDGE_FALLING: | ||
97 | newvalue = S5P_IRQ_TYPE_EDGE_FALLING; | ||
98 | break; | ||
99 | |||
100 | case IRQ_TYPE_EDGE_BOTH: | ||
101 | newvalue = S5P_IRQ_TYPE_EDGE_BOTH; | ||
102 | break; | ||
103 | |||
104 | case IRQ_TYPE_LEVEL_LOW: | ||
105 | newvalue = S5P_IRQ_TYPE_LEVEL_LOW; | ||
106 | break; | ||
107 | |||
108 | case IRQ_TYPE_LEVEL_HIGH: | ||
109 | newvalue = S5P_IRQ_TYPE_LEVEL_HIGH; | ||
110 | break; | ||
111 | |||
112 | default: | ||
113 | printk(KERN_ERR "No such irq type %d", type); | ||
114 | return -EINVAL; | ||
115 | } | ||
116 | |||
117 | shift = (offs & 0x7) * 4; | ||
118 | mask = 0x7 << shift; | ||
119 | |||
120 | spin_lock(&eint_lock); | ||
121 | ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(irq))); | ||
122 | ctrl &= ~mask; | ||
123 | ctrl |= newvalue << shift; | ||
124 | __raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(irq))); | ||
125 | spin_unlock(&eint_lock); | ||
126 | |||
127 | switch (offs) { | ||
128 | case 0 ... 7: | ||
129 | s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE); | ||
130 | break; | ||
131 | case 8 ... 15: | ||
132 | s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE); | ||
133 | break; | ||
134 | case 16 ... 23: | ||
135 | s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE); | ||
136 | break; | ||
137 | case 24 ... 31: | ||
138 | s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE); | ||
139 | break; | ||
140 | default: | ||
141 | printk(KERN_ERR "No such irq number %d", offs); | ||
142 | } | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static struct irq_chip s5pv310_irq_eint = { | ||
148 | .name = "s5pv310-eint", | ||
149 | .mask = s5pv310_irq_eint_mask, | ||
150 | .unmask = s5pv310_irq_eint_unmask, | ||
151 | .mask_ack = s5pv310_irq_eint_maskack, | ||
152 | .ack = s5pv310_irq_eint_ack, | ||
153 | .set_type = s5pv310_irq_eint_set_type, | ||
154 | #ifdef CONFIG_PM | ||
155 | .set_wake = s3c_irqext_wake, | ||
156 | #endif | ||
157 | }; | ||
158 | |||
159 | /* s5pv310_irq_demux_eint | ||
160 | * | ||
161 | * This function demuxes the IRQ from from EINTs 16 to 31. | ||
162 | * It is designed to be inlined into the specific handler | ||
163 | * s5p_irq_demux_eintX_Y. | ||
164 | * | ||
165 | * Each EINT pend/mask registers handle eight of them. | ||
166 | */ | ||
167 | static inline void s5pv310_irq_demux_eint(unsigned int start) | ||
168 | { | ||
169 | unsigned int irq; | ||
170 | |||
171 | u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start))); | ||
172 | u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start))); | ||
173 | |||
174 | status &= ~mask; | ||
175 | status &= 0xff; | ||
176 | |||
177 | while (status) { | ||
178 | irq = fls(status) - 1; | ||
179 | generic_handle_irq(irq + start); | ||
180 | status &= ~(1 << irq); | ||
181 | } | ||
182 | } | ||
183 | |||
184 | static void s5pv310_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc) | ||
185 | { | ||
186 | s5pv310_irq_demux_eint(IRQ_EINT(16)); | ||
187 | s5pv310_irq_demux_eint(IRQ_EINT(24)); | ||
188 | } | ||
189 | |||
190 | static void s5pv310_irq_eint0_15(unsigned int irq, struct irq_desc *desc) | ||
191 | { | ||
192 | u32 *irq_data = get_irq_data(irq); | ||
193 | struct irq_chip *chip = get_irq_chip(irq); | ||
194 | |||
195 | chip->mask(irq); | ||
196 | |||
197 | if (chip->ack) | ||
198 | chip->ack(irq); | ||
199 | |||
200 | generic_handle_irq(*irq_data); | ||
201 | |||
202 | chip->unmask(irq); | ||
203 | } | ||
204 | |||
205 | int __init s5pv310_init_irq_eint(void) | ||
206 | { | ||
207 | int irq; | ||
208 | |||
209 | for (irq = 0 ; irq <= 31 ; irq++) { | ||
210 | set_irq_chip(IRQ_EINT(irq), &s5pv310_irq_eint); | ||
211 | set_irq_handler(IRQ_EINT(irq), handle_level_irq); | ||
212 | set_irq_flags(IRQ_EINT(irq), IRQF_VALID); | ||
213 | } | ||
214 | |||
215 | set_irq_chained_handler(IRQ_EINT16_31, s5pv310_irq_demux_eint16_31); | ||
216 | |||
217 | for (irq = 0 ; irq <= 15 ; irq++) { | ||
218 | eint0_15_data[irq] = IRQ_EINT(irq); | ||
219 | |||
220 | set_irq_data(s5pv310_get_irq_nr(irq), &eint0_15_data[irq]); | ||
221 | set_irq_chained_handler(s5pv310_get_irq_nr(irq), | ||
222 | s5pv310_irq_eint0_15); | ||
223 | } | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | arch_initcall(s5pv310_init_irq_eint); | ||
diff --git a/arch/arm/mach-s5pv310/mach-smdkc210.c b/arch/arm/mach-s5pv310/mach-smdkc210.c new file mode 100644 index 000000000000..2b8d4fc52d7c --- /dev/null +++ b/arch/arm/mach-s5pv310/mach-smdkc210.c | |||
@@ -0,0 +1,202 @@ | |||
1 | /* linux/arch/arm/mach-s5pv310/mach-smdkc210.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/serial_core.h> | ||
12 | #include <linux/gpio.h> | ||
13 | #include <linux/mmc/host.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/smsc911x.h> | ||
16 | #include <linux/io.h> | ||
17 | |||
18 | #include <asm/mach/arch.h> | ||
19 | #include <asm/mach-types.h> | ||
20 | |||
21 | #include <plat/regs-serial.h> | ||
22 | #include <plat/s5pv310.h> | ||
23 | #include <plat/cpu.h> | ||
24 | #include <plat/devs.h> | ||
25 | #include <plat/sdhci.h> | ||
26 | |||
27 | #include <mach/map.h> | ||
28 | #include <mach/regs-srom.h> | ||
29 | |||
30 | /* Following are default values for UCON, ULCON and UFCON UART registers */ | ||
31 | #define SMDKC210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ | ||
32 | S3C2410_UCON_RXILEVEL | \ | ||
33 | S3C2410_UCON_TXIRQMODE | \ | ||
34 | S3C2410_UCON_RXIRQMODE | \ | ||
35 | S3C2410_UCON_RXFIFO_TOI | \ | ||
36 | S3C2443_UCON_RXERR_IRQEN) | ||
37 | |||
38 | #define SMDKC210_ULCON_DEFAULT S3C2410_LCON_CS8 | ||
39 | |||
40 | #define SMDKC210_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ | ||
41 | S5PV210_UFCON_TXTRIG4 | \ | ||
42 | S5PV210_UFCON_RXTRIG4) | ||
43 | |||
44 | static struct s3c2410_uartcfg smdkc210_uartcfgs[] __initdata = { | ||
45 | [0] = { | ||
46 | .hwport = 0, | ||
47 | .flags = 0, | ||
48 | .ucon = SMDKC210_UCON_DEFAULT, | ||
49 | .ulcon = SMDKC210_ULCON_DEFAULT, | ||
50 | .ufcon = SMDKC210_UFCON_DEFAULT, | ||
51 | }, | ||
52 | [1] = { | ||
53 | .hwport = 1, | ||
54 | .flags = 0, | ||
55 | .ucon = SMDKC210_UCON_DEFAULT, | ||
56 | .ulcon = SMDKC210_ULCON_DEFAULT, | ||
57 | .ufcon = SMDKC210_UFCON_DEFAULT, | ||
58 | }, | ||
59 | [2] = { | ||
60 | .hwport = 2, | ||
61 | .flags = 0, | ||
62 | .ucon = SMDKC210_UCON_DEFAULT, | ||
63 | .ulcon = SMDKC210_ULCON_DEFAULT, | ||
64 | .ufcon = SMDKC210_UFCON_DEFAULT, | ||
65 | }, | ||
66 | [3] = { | ||
67 | .hwport = 3, | ||
68 | .flags = 0, | ||
69 | .ucon = SMDKC210_UCON_DEFAULT, | ||
70 | .ulcon = SMDKC210_ULCON_DEFAULT, | ||
71 | .ufcon = SMDKC210_UFCON_DEFAULT, | ||
72 | }, | ||
73 | }; | ||
74 | |||
75 | static struct s3c_sdhci_platdata smdkc210_hsmmc0_pdata __initdata = { | ||
76 | .cd_type = S3C_SDHCI_CD_GPIO, | ||
77 | .ext_cd_gpio = S5PV310_GPK0(2), | ||
78 | .ext_cd_gpio_invert = 1, | ||
79 | .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, | ||
80 | #ifdef CONFIG_S5PV310_SDHCI_CH0_8BIT | ||
81 | .max_width = 8, | ||
82 | .host_caps = MMC_CAP_8_BIT_DATA, | ||
83 | #endif | ||
84 | }; | ||
85 | |||
86 | static struct s3c_sdhci_platdata smdkc210_hsmmc1_pdata __initdata = { | ||
87 | .cd_type = S3C_SDHCI_CD_GPIO, | ||
88 | .ext_cd_gpio = S5PV310_GPK0(2), | ||
89 | .ext_cd_gpio_invert = 1, | ||
90 | .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, | ||
91 | }; | ||
92 | |||
93 | static struct s3c_sdhci_platdata smdkc210_hsmmc2_pdata __initdata = { | ||
94 | .cd_type = S3C_SDHCI_CD_GPIO, | ||
95 | .ext_cd_gpio = S5PV310_GPK2(2), | ||
96 | .ext_cd_gpio_invert = 1, | ||
97 | .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, | ||
98 | #ifdef CONFIG_S5PV310_SDHCI_CH2_8BIT | ||
99 | .max_width = 8, | ||
100 | .host_caps = MMC_CAP_8_BIT_DATA, | ||
101 | #endif | ||
102 | }; | ||
103 | |||
104 | static struct s3c_sdhci_platdata smdkc210_hsmmc3_pdata __initdata = { | ||
105 | .cd_type = S3C_SDHCI_CD_GPIO, | ||
106 | .ext_cd_gpio = S5PV310_GPK2(2), | ||
107 | .ext_cd_gpio_invert = 1, | ||
108 | .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, | ||
109 | }; | ||
110 | |||
111 | static struct resource smdkc210_smsc911x_resources[] = { | ||
112 | [0] = { | ||
113 | .start = S5PV310_PA_SROM_BANK(1), | ||
114 | .end = S5PV310_PA_SROM_BANK(1) + SZ_64K - 1, | ||
115 | .flags = IORESOURCE_MEM, | ||
116 | }, | ||
117 | [1] = { | ||
118 | .start = IRQ_EINT(5), | ||
119 | .end = IRQ_EINT(5), | ||
120 | .flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW, | ||
121 | }, | ||
122 | }; | ||
123 | |||
124 | static struct smsc911x_platform_config smsc9215_config = { | ||
125 | .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH, | ||
126 | .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, | ||
127 | .flags = SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY, | ||
128 | .phy_interface = PHY_INTERFACE_MODE_MII, | ||
129 | .mac = {0x00, 0x80, 0x00, 0x23, 0x45, 0x67}, | ||
130 | }; | ||
131 | |||
132 | static struct platform_device smdkc210_smsc911x = { | ||
133 | .name = "smsc911x", | ||
134 | .id = -1, | ||
135 | .num_resources = ARRAY_SIZE(smdkc210_smsc911x_resources), | ||
136 | .resource = smdkc210_smsc911x_resources, | ||
137 | .dev = { | ||
138 | .platform_data = &smsc9215_config, | ||
139 | }, | ||
140 | }; | ||
141 | |||
142 | static struct platform_device *smdkc210_devices[] __initdata = { | ||
143 | &s3c_device_hsmmc0, | ||
144 | &s3c_device_hsmmc1, | ||
145 | &s3c_device_hsmmc2, | ||
146 | &s3c_device_hsmmc3, | ||
147 | &s3c_device_rtc, | ||
148 | &s3c_device_wdt, | ||
149 | &smdkc210_smsc911x, | ||
150 | }; | ||
151 | |||
152 | static void __init smdkc210_smsc911x_init(void) | ||
153 | { | ||
154 | u32 cs1; | ||
155 | |||
156 | /* configure nCS1 width to 16 bits */ | ||
157 | cs1 = __raw_readl(S5PV310_SROM_BW) & | ||
158 | ~(S5PV310_SROM_BW__CS_MASK << | ||
159 | S5PV310_SROM_BW__NCS1__SHIFT); | ||
160 | cs1 |= ((1 << S5PV310_SROM_BW__DATAWIDTH__SHIFT) | | ||
161 | (1 << S5PV310_SROM_BW__WAITENABLE__SHIFT) | | ||
162 | (1 << S5PV310_SROM_BW__BYTEENABLE__SHIFT)) << | ||
163 | S5PV310_SROM_BW__NCS1__SHIFT; | ||
164 | __raw_writel(cs1, S5PV310_SROM_BW); | ||
165 | |||
166 | /* set timing for nCS1 suitable for ethernet chip */ | ||
167 | __raw_writel((0x1 << S5PV310_SROM_BCX__PMC__SHIFT) | | ||
168 | (0x9 << S5PV310_SROM_BCX__TACP__SHIFT) | | ||
169 | (0xc << S5PV310_SROM_BCX__TCAH__SHIFT) | | ||
170 | (0x1 << S5PV310_SROM_BCX__TCOH__SHIFT) | | ||
171 | (0x6 << S5PV310_SROM_BCX__TACC__SHIFT) | | ||
172 | (0x1 << S5PV310_SROM_BCX__TCOS__SHIFT) | | ||
173 | (0x1 << S5PV310_SROM_BCX__TACS__SHIFT), S5PV310_SROM_BC1); | ||
174 | } | ||
175 | |||
176 | static void __init smdkc210_map_io(void) | ||
177 | { | ||
178 | s5p_init_io(NULL, 0, S5P_VA_CHIPID); | ||
179 | s3c24xx_init_clocks(24000000); | ||
180 | s3c24xx_init_uarts(smdkc210_uartcfgs, ARRAY_SIZE(smdkc210_uartcfgs)); | ||
181 | } | ||
182 | |||
183 | static void __init smdkc210_machine_init(void) | ||
184 | { | ||
185 | smdkc210_smsc911x_init(); | ||
186 | |||
187 | s3c_sdhci0_set_platdata(&smdkc210_hsmmc0_pdata); | ||
188 | s3c_sdhci1_set_platdata(&smdkc210_hsmmc1_pdata); | ||
189 | s3c_sdhci2_set_platdata(&smdkc210_hsmmc2_pdata); | ||
190 | s3c_sdhci3_set_platdata(&smdkc210_hsmmc3_pdata); | ||
191 | |||
192 | platform_add_devices(smdkc210_devices, ARRAY_SIZE(smdkc210_devices)); | ||
193 | } | ||
194 | |||
195 | MACHINE_START(SMDKC210, "SMDKC210") | ||
196 | /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */ | ||
197 | .boot_params = S5P_PA_SDRAM + 0x100, | ||
198 | .init_irq = s5pv310_init_irq, | ||
199 | .map_io = smdkc210_map_io, | ||
200 | .init_machine = smdkc210_machine_init, | ||
201 | .timer = &s5pv310_timer, | ||
202 | MACHINE_END | ||
diff --git a/arch/arm/mach-s5pv310/mach-smdkv310.c b/arch/arm/mach-s5pv310/mach-smdkv310.c index 46215a14b3bb..35826d66632c 100644 --- a/arch/arm/mach-s5pv310/mach-smdkv310.c +++ b/arch/arm/mach-s5pv310/mach-smdkv310.c | |||
@@ -9,16 +9,23 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/serial_core.h> | 11 | #include <linux/serial_core.h> |
12 | #include <linux/gpio.h> | ||
13 | #include <linux/mmc/host.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/smsc911x.h> | ||
16 | #include <linux/io.h> | ||
12 | 17 | ||
13 | #include <asm/mach/arch.h> | 18 | #include <asm/mach/arch.h> |
14 | #include <asm/mach-types.h> | 19 | #include <asm/mach-types.h> |
15 | #include <asm/hardware/cache-l2x0.h> | ||
16 | 20 | ||
17 | #include <plat/regs-serial.h> | 21 | #include <plat/regs-serial.h> |
18 | #include <plat/s5pv310.h> | 22 | #include <plat/s5pv310.h> |
19 | #include <plat/cpu.h> | 23 | #include <plat/cpu.h> |
24 | #include <plat/devs.h> | ||
25 | #include <plat/sdhci.h> | ||
20 | 26 | ||
21 | #include <mach/map.h> | 27 | #include <mach/map.h> |
28 | #include <mach/regs-srom.h> | ||
22 | 29 | ||
23 | /* Following are default values for UCON, ULCON and UFCON UART registers */ | 30 | /* Following are default values for UCON, ULCON and UFCON UART registers */ |
24 | #define SMDKV310_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ | 31 | #define SMDKV310_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ |
@@ -65,6 +72,107 @@ static struct s3c2410_uartcfg smdkv310_uartcfgs[] __initdata = { | |||
65 | }, | 72 | }, |
66 | }; | 73 | }; |
67 | 74 | ||
75 | static struct s3c_sdhci_platdata smdkv310_hsmmc0_pdata __initdata = { | ||
76 | .cd_type = S3C_SDHCI_CD_GPIO, | ||
77 | .ext_cd_gpio = S5PV310_GPK0(2), | ||
78 | .ext_cd_gpio_invert = 1, | ||
79 | .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, | ||
80 | #ifdef CONFIG_S5PV310_SDHCI_CH0_8BIT | ||
81 | .max_width = 8, | ||
82 | .host_caps = MMC_CAP_8_BIT_DATA, | ||
83 | #endif | ||
84 | }; | ||
85 | |||
86 | static struct s3c_sdhci_platdata smdkv310_hsmmc1_pdata __initdata = { | ||
87 | .cd_type = S3C_SDHCI_CD_GPIO, | ||
88 | .ext_cd_gpio = S5PV310_GPK0(2), | ||
89 | .ext_cd_gpio_invert = 1, | ||
90 | .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, | ||
91 | }; | ||
92 | |||
93 | static struct s3c_sdhci_platdata smdkv310_hsmmc2_pdata __initdata = { | ||
94 | .cd_type = S3C_SDHCI_CD_GPIO, | ||
95 | .ext_cd_gpio = S5PV310_GPK2(2), | ||
96 | .ext_cd_gpio_invert = 1, | ||
97 | .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, | ||
98 | #ifdef CONFIG_S5PV310_SDHCI_CH2_8BIT | ||
99 | .max_width = 8, | ||
100 | .host_caps = MMC_CAP_8_BIT_DATA, | ||
101 | #endif | ||
102 | }; | ||
103 | |||
104 | static struct s3c_sdhci_platdata smdkv310_hsmmc3_pdata __initdata = { | ||
105 | .cd_type = S3C_SDHCI_CD_GPIO, | ||
106 | .ext_cd_gpio = S5PV310_GPK2(2), | ||
107 | .ext_cd_gpio_invert = 1, | ||
108 | .clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL, | ||
109 | }; | ||
110 | |||
111 | static struct resource smdkv310_smsc911x_resources[] = { | ||
112 | [0] = { | ||
113 | .start = S5PV310_PA_SROM_BANK(1), | ||
114 | .end = S5PV310_PA_SROM_BANK(1) + SZ_64K - 1, | ||
115 | .flags = IORESOURCE_MEM, | ||
116 | }, | ||
117 | [1] = { | ||
118 | .start = IRQ_EINT(5), | ||
119 | .end = IRQ_EINT(5), | ||
120 | .flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW, | ||
121 | }, | ||
122 | }; | ||
123 | |||
124 | static struct smsc911x_platform_config smsc9215_config = { | ||
125 | .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH, | ||
126 | .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, | ||
127 | .flags = SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY, | ||
128 | .phy_interface = PHY_INTERFACE_MODE_MII, | ||
129 | .mac = {0x00, 0x80, 0x00, 0x23, 0x45, 0x67}, | ||
130 | }; | ||
131 | |||
132 | static struct platform_device smdkv310_smsc911x = { | ||
133 | .name = "smsc911x", | ||
134 | .id = -1, | ||
135 | .num_resources = ARRAY_SIZE(smdkv310_smsc911x_resources), | ||
136 | .resource = smdkv310_smsc911x_resources, | ||
137 | .dev = { | ||
138 | .platform_data = &smsc9215_config, | ||
139 | }, | ||
140 | }; | ||
141 | |||
142 | static struct platform_device *smdkv310_devices[] __initdata = { | ||
143 | &s3c_device_hsmmc0, | ||
144 | &s3c_device_hsmmc1, | ||
145 | &s3c_device_hsmmc2, | ||
146 | &s3c_device_hsmmc3, | ||
147 | &s3c_device_rtc, | ||
148 | &s3c_device_wdt, | ||
149 | &smdkv310_smsc911x, | ||
150 | }; | ||
151 | |||
152 | static void __init smdkv310_smsc911x_init(void) | ||
153 | { | ||
154 | u32 cs1; | ||
155 | |||
156 | /* configure nCS1 width to 16 bits */ | ||
157 | cs1 = __raw_readl(S5PV310_SROM_BW) & | ||
158 | ~(S5PV310_SROM_BW__CS_MASK << | ||
159 | S5PV310_SROM_BW__NCS1__SHIFT); | ||
160 | cs1 |= ((1 << S5PV310_SROM_BW__DATAWIDTH__SHIFT) | | ||
161 | (1 << S5PV310_SROM_BW__WAITENABLE__SHIFT) | | ||
162 | (1 << S5PV310_SROM_BW__BYTEENABLE__SHIFT)) << | ||
163 | S5PV310_SROM_BW__NCS1__SHIFT; | ||
164 | __raw_writel(cs1, S5PV310_SROM_BW); | ||
165 | |||
166 | /* set timing for nCS1 suitable for ethernet chip */ | ||
167 | __raw_writel((0x1 << S5PV310_SROM_BCX__PMC__SHIFT) | | ||
168 | (0x9 << S5PV310_SROM_BCX__TACP__SHIFT) | | ||
169 | (0xc << S5PV310_SROM_BCX__TCAH__SHIFT) | | ||
170 | (0x1 << S5PV310_SROM_BCX__TCOH__SHIFT) | | ||
171 | (0x6 << S5PV310_SROM_BCX__TACC__SHIFT) | | ||
172 | (0x1 << S5PV310_SROM_BCX__TCOS__SHIFT) | | ||
173 | (0x1 << S5PV310_SROM_BCX__TACS__SHIFT), S5PV310_SROM_BC1); | ||
174 | } | ||
175 | |||
68 | static void __init smdkv310_map_io(void) | 176 | static void __init smdkv310_map_io(void) |
69 | { | 177 | { |
70 | s5p_init_io(NULL, 0, S5P_VA_CHIPID); | 178 | s5p_init_io(NULL, 0, S5P_VA_CHIPID); |
@@ -74,9 +182,14 @@ static void __init smdkv310_map_io(void) | |||
74 | 182 | ||
75 | static void __init smdkv310_machine_init(void) | 183 | static void __init smdkv310_machine_init(void) |
76 | { | 184 | { |
77 | #ifdef CONFIG_CACHE_L2X0 | 185 | smdkv310_smsc911x_init(); |
78 | l2x0_init(S5P_VA_L2CC, 1 << 28, 0xffffffff); | 186 | |
79 | #endif | 187 | s3c_sdhci0_set_platdata(&smdkv310_hsmmc0_pdata); |
188 | s3c_sdhci1_set_platdata(&smdkv310_hsmmc1_pdata); | ||
189 | s3c_sdhci2_set_platdata(&smdkv310_hsmmc2_pdata); | ||
190 | s3c_sdhci3_set_platdata(&smdkv310_hsmmc3_pdata); | ||
191 | |||
192 | platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices)); | ||
80 | } | 193 | } |
81 | 194 | ||
82 | MACHINE_START(SMDKV310, "SMDKV310") | 195 | MACHINE_START(SMDKV310, "SMDKV310") |
diff --git a/arch/arm/mach-s5pv310/mach-universal_c210.c b/arch/arm/mach-s5pv310/mach-universal_c210.c index d7c2ec770f88..16d8fc00cafd 100644 --- a/arch/arm/mach-s5pv310/mach-universal_c210.c +++ b/arch/arm/mach-s5pv310/mach-universal_c210.c | |||
@@ -7,15 +7,20 @@ | |||
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/platform_device.h> | ||
10 | #include <linux/serial_core.h> | 11 | #include <linux/serial_core.h> |
12 | #include <linux/input.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/gpio_keys.h> | ||
15 | #include <linux/gpio.h> | ||
11 | 16 | ||
12 | #include <asm/mach/arch.h> | 17 | #include <asm/mach/arch.h> |
13 | #include <asm/mach-types.h> | 18 | #include <asm/mach-types.h> |
14 | #include <asm/hardware/cache-l2x0.h> | ||
15 | 19 | ||
16 | #include <plat/regs-serial.h> | 20 | #include <plat/regs-serial.h> |
17 | #include <plat/s5pv310.h> | 21 | #include <plat/s5pv310.h> |
18 | #include <plat/cpu.h> | 22 | #include <plat/cpu.h> |
23 | #include <plat/devs.h> | ||
19 | 24 | ||
20 | #include <mach/map.h> | 25 | #include <mach/map.h> |
21 | 26 | ||
@@ -60,6 +65,72 @@ static struct s3c2410_uartcfg universal_uartcfgs[] __initdata = { | |||
60 | }, | 65 | }, |
61 | }; | 66 | }; |
62 | 67 | ||
68 | static struct gpio_keys_button universal_gpio_keys_tables[] = { | ||
69 | { | ||
70 | .code = KEY_VOLUMEUP, | ||
71 | .gpio = S5PV310_GPX2(0), /* XEINT16 */ | ||
72 | .desc = "gpio-keys: KEY_VOLUMEUP", | ||
73 | .type = EV_KEY, | ||
74 | .active_low = 1, | ||
75 | .debounce_interval = 1, | ||
76 | }, { | ||
77 | .code = KEY_VOLUMEDOWN, | ||
78 | .gpio = S5PV310_GPX2(1), /* XEINT17 */ | ||
79 | .desc = "gpio-keys: KEY_VOLUMEDOWN", | ||
80 | .type = EV_KEY, | ||
81 | .active_low = 1, | ||
82 | .debounce_interval = 1, | ||
83 | }, { | ||
84 | .code = KEY_CONFIG, | ||
85 | .gpio = S5PV310_GPX2(2), /* XEINT18 */ | ||
86 | .desc = "gpio-keys: KEY_CONFIG", | ||
87 | .type = EV_KEY, | ||
88 | .active_low = 1, | ||
89 | .debounce_interval = 1, | ||
90 | }, { | ||
91 | .code = KEY_CAMERA, | ||
92 | .gpio = S5PV310_GPX2(3), /* XEINT19 */ | ||
93 | .desc = "gpio-keys: KEY_CAMERA", | ||
94 | .type = EV_KEY, | ||
95 | .active_low = 1, | ||
96 | .debounce_interval = 1, | ||
97 | }, { | ||
98 | .code = KEY_OK, | ||
99 | .gpio = S5PV310_GPX3(5), /* XEINT29 */ | ||
100 | .desc = "gpio-keys: KEY_OK", | ||
101 | .type = EV_KEY, | ||
102 | .active_low = 1, | ||
103 | .debounce_interval = 1, | ||
104 | }, | ||
105 | }; | ||
106 | |||
107 | static struct gpio_keys_platform_data universal_gpio_keys_data = { | ||
108 | .buttons = universal_gpio_keys_tables, | ||
109 | .nbuttons = ARRAY_SIZE(universal_gpio_keys_tables), | ||
110 | }; | ||
111 | |||
112 | static struct platform_device universal_gpio_keys = { | ||
113 | .name = "gpio-keys", | ||
114 | .dev = { | ||
115 | .platform_data = &universal_gpio_keys_data, | ||
116 | }, | ||
117 | }; | ||
118 | |||
119 | /* I2C0 */ | ||
120 | static struct i2c_board_info i2c0_devs[] __initdata = { | ||
121 | /* Camera, To be updated */ | ||
122 | }; | ||
123 | |||
124 | /* I2C1 */ | ||
125 | static struct i2c_board_info i2c1_devs[] __initdata = { | ||
126 | /* Gyro, To be updated */ | ||
127 | }; | ||
128 | |||
129 | static struct platform_device *universal_devices[] __initdata = { | ||
130 | &universal_gpio_keys, | ||
131 | &s5p_device_onenand, | ||
132 | }; | ||
133 | |||
63 | static void __init universal_map_io(void) | 134 | static void __init universal_map_io(void) |
64 | { | 135 | { |
65 | s5p_init_io(NULL, 0, S5P_VA_CHIPID); | 136 | s5p_init_io(NULL, 0, S5P_VA_CHIPID); |
@@ -69,9 +140,11 @@ static void __init universal_map_io(void) | |||
69 | 140 | ||
70 | static void __init universal_machine_init(void) | 141 | static void __init universal_machine_init(void) |
71 | { | 142 | { |
72 | #ifdef CONFIG_CACHE_L2X0 | 143 | i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs)); |
73 | l2x0_init(S5P_VA_L2CC, 1 << 28, 0xffffffff); | 144 | i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs)); |
74 | #endif | 145 | |
146 | /* Last */ | ||
147 | platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices)); | ||
75 | } | 148 | } |
76 | 149 | ||
77 | MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210") | 150 | MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210") |
diff --git a/arch/arm/mach-s5pv310/setup-i2c0.c b/arch/arm/mach-s5pv310/setup-i2c0.c index 436712807383..f47f8f3152ec 100644 --- a/arch/arm/mach-s5pv310/setup-i2c0.c +++ b/arch/arm/mach-s5pv310/setup-i2c0.c | |||
@@ -21,8 +21,6 @@ struct platform_device; /* don't need the contents */ | |||
21 | 21 | ||
22 | void s3c_i2c0_cfg_gpio(struct platform_device *dev) | 22 | void s3c_i2c0_cfg_gpio(struct platform_device *dev) |
23 | { | 23 | { |
24 | s3c_gpio_cfgpin(S5PV310_GPD1(0), S3C_GPIO_SFN(2)); | 24 | s3c_gpio_cfgall_range(S5PV310_GPD1(0), 2, |
25 | s3c_gpio_setpull(S5PV310_GPD1(0), S3C_GPIO_PULL_UP); | 25 | S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); |
26 | s3c_gpio_cfgpin(S5PV310_GPD1(1), S3C_GPIO_SFN(2)); | ||
27 | s3c_gpio_setpull(S5PV310_GPD1(1), S3C_GPIO_PULL_UP); | ||
28 | } | 26 | } |
diff --git a/arch/arm/mach-s5pv310/setup-i2c1.c b/arch/arm/mach-s5pv310/setup-i2c1.c index 1ecd5bc35b5a..9d07e4e2f14c 100644 --- a/arch/arm/mach-s5pv310/setup-i2c1.c +++ b/arch/arm/mach-s5pv310/setup-i2c1.c | |||
@@ -18,8 +18,6 @@ struct platform_device; /* don't need the contents */ | |||
18 | 18 | ||
19 | void s3c_i2c1_cfg_gpio(struct platform_device *dev) | 19 | void s3c_i2c1_cfg_gpio(struct platform_device *dev) |
20 | { | 20 | { |
21 | s3c_gpio_cfgpin(S5PV310_GPD1(2), S3C_GPIO_SFN(2)); | 21 | s3c_gpio_cfgall_range(S5PV310_GPD1(2), 2, |
22 | s3c_gpio_setpull(S5PV310_GPD1(2), S3C_GPIO_PULL_UP); | 22 | S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP); |
23 | s3c_gpio_cfgpin(S5PV310_GPD1(3), S3C_GPIO_SFN(2)); | ||
24 | s3c_gpio_setpull(S5PV310_GPD1(3), S3C_GPIO_PULL_UP); | ||
25 | } | 23 | } |
diff --git a/arch/arm/mach-s5pv310/setup-i2c2.c b/arch/arm/mach-s5pv310/setup-i2c2.c index 4c0d8def660a..4163b1233daf 100644 --- a/arch/arm/mach-s5pv310/setup-i2c2.c +++ b/arch/arm/mach-s5pv310/setup-i2c2.c | |||
@@ -18,8 +18,6 @@ struct platform_device; /* don't need the contents */ | |||
18 | 18 | ||
19 | void s3c_i2c2_cfg_gpio(struct platform_device *dev) | 19 | void s3c_i2c2_cfg_gpio(struct platform_device *dev) |
20 | { | 20 | { |
21 | s3c_gpio_cfgpin(S5PV310_GPA0(6), S3C_GPIO_SFN(3)); | 21 | s3c_gpio_cfgall_range(S5PV310_GPA0(6), 2, |
22 | s3c_gpio_setpull(S5PV310_GPA0(6), S3C_GPIO_PULL_UP); | 22 | S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP); |
23 | s3c_gpio_cfgpin(S5PV310_GPA0(7), S3C_GPIO_SFN(3)); | ||
24 | s3c_gpio_setpull(S5PV310_GPA0(7), S3C_GPIO_PULL_UP); | ||
25 | } | 23 | } |
diff --git a/arch/arm/mach-s5pv310/setup-i2c3.c b/arch/arm/mach-s5pv310/setup-i2c3.c new file mode 100644 index 000000000000..180f153d2a20 --- /dev/null +++ b/arch/arm/mach-s5pv310/setup-i2c3.c | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-s5pv310/setup-i2c3.c | ||
3 | * | ||
4 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
5 | * | ||
6 | * I2C3 GPIO configuration. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | struct platform_device; /* don't need the contents */ | ||
14 | |||
15 | #include <linux/gpio.h> | ||
16 | #include <plat/iic.h> | ||
17 | #include <plat/gpio-cfg.h> | ||
18 | |||
19 | void s3c_i2c3_cfg_gpio(struct platform_device *dev) | ||
20 | { | ||
21 | s3c_gpio_cfgall_range(S5PV310_GPA1(2), 2, | ||
22 | S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP); | ||
23 | } | ||
diff --git a/arch/arm/mach-s5pv310/setup-i2c4.c b/arch/arm/mach-s5pv310/setup-i2c4.c new file mode 100644 index 000000000000..909e8dfc5316 --- /dev/null +++ b/arch/arm/mach-s5pv310/setup-i2c4.c | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-s5pv310/setup-i2c4.c | ||
3 | * | ||
4 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
5 | * | ||
6 | * I2C4 GPIO configuration. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | struct platform_device; /* don't need the contents */ | ||
14 | |||
15 | #include <linux/gpio.h> | ||
16 | #include <plat/iic.h> | ||
17 | #include <plat/gpio-cfg.h> | ||
18 | |||
19 | void s3c_i2c4_cfg_gpio(struct platform_device *dev) | ||
20 | { | ||
21 | s3c_gpio_cfgall_range(S5PV310_GPB(2), 2, | ||
22 | S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP); | ||
23 | } | ||
diff --git a/arch/arm/mach-s5pv310/setup-i2c5.c b/arch/arm/mach-s5pv310/setup-i2c5.c new file mode 100644 index 000000000000..5d0fa4ac0283 --- /dev/null +++ b/arch/arm/mach-s5pv310/setup-i2c5.c | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-s5pv310/setup-i2c5.c | ||
3 | * | ||
4 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
5 | * | ||
6 | * I2C5 GPIO configuration. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | struct platform_device; /* don't need the contents */ | ||
14 | |||
15 | #include <linux/gpio.h> | ||
16 | #include <plat/iic.h> | ||
17 | #include <plat/gpio-cfg.h> | ||
18 | |||
19 | void s3c_i2c5_cfg_gpio(struct platform_device *dev) | ||
20 | { | ||
21 | s3c_gpio_cfgall_range(S5PV310_GPB(6), 2, | ||
22 | S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP); | ||
23 | } | ||
diff --git a/arch/arm/mach-s5pv310/setup-i2c6.c b/arch/arm/mach-s5pv310/setup-i2c6.c new file mode 100644 index 000000000000..34aafab92ac4 --- /dev/null +++ b/arch/arm/mach-s5pv310/setup-i2c6.c | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-s5pv310/setup-i2c6.c | ||
3 | * | ||
4 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
5 | * | ||
6 | * I2C6 GPIO configuration. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | struct platform_device; /* don't need the contents */ | ||
14 | |||
15 | #include <linux/gpio.h> | ||
16 | #include <plat/iic.h> | ||
17 | #include <plat/gpio-cfg.h> | ||
18 | |||
19 | void s3c_i2c6_cfg_gpio(struct platform_device *dev) | ||
20 | { | ||
21 | s3c_gpio_cfgall_range(S5PV310_GPC1(3), 2, | ||
22 | S3C_GPIO_SFN(4), S3C_GPIO_PULL_UP); | ||
23 | } | ||
diff --git a/arch/arm/mach-s5pv310/setup-i2c7.c b/arch/arm/mach-s5pv310/setup-i2c7.c new file mode 100644 index 000000000000..9b25b8d18920 --- /dev/null +++ b/arch/arm/mach-s5pv310/setup-i2c7.c | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-s5pv310/setup-i2c7.c | ||
3 | * | ||
4 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
5 | * | ||
6 | * I2C7 GPIO configuration. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | struct platform_device; /* don't need the contents */ | ||
14 | |||
15 | #include <linux/gpio.h> | ||
16 | #include <plat/iic.h> | ||
17 | #include <plat/gpio-cfg.h> | ||
18 | |||
19 | void s3c_i2c7_cfg_gpio(struct platform_device *dev) | ||
20 | { | ||
21 | s3c_gpio_cfgall_range(S5PV310_GPD0(2), 2, | ||
22 | S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP); | ||
23 | } | ||
diff --git a/arch/arm/mach-s5pv310/setup-sdhci-gpio.c b/arch/arm/mach-s5pv310/setup-sdhci-gpio.c new file mode 100644 index 000000000000..86d38cc49135 --- /dev/null +++ b/arch/arm/mach-s5pv310/setup-sdhci-gpio.c | |||
@@ -0,0 +1,152 @@ | |||
1 | /* linux/arch/arm/mach-s5pv310/setup-sdhci-gpio.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
6 | * S5PV310 - Helper functions for setting up SDHCI device(s) GPIO (HSMMC) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/types.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/gpio.h> | ||
19 | #include <linux/mmc/host.h> | ||
20 | #include <linux/mmc/card.h> | ||
21 | |||
22 | #include <plat/gpio-cfg.h> | ||
23 | #include <plat/regs-sdhci.h> | ||
24 | #include <plat/sdhci.h> | ||
25 | |||
26 | void s5pv310_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) | ||
27 | { | ||
28 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; | ||
29 | unsigned int gpio; | ||
30 | |||
31 | /* Set all the necessary GPK0[0:1] pins to special-function 2 */ | ||
32 | for (gpio = S5PV310_GPK0(0); gpio < S5PV310_GPK0(2); gpio++) { | ||
33 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
34 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
35 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
36 | } | ||
37 | |||
38 | switch (width) { | ||
39 | case 8: | ||
40 | for (gpio = S5PV310_GPK1(3); gpio <= S5PV310_GPK1(6); gpio++) { | ||
41 | /* Data pin GPK1[3:6] to special-funtion 3 */ | ||
42 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); | ||
43 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); | ||
44 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
45 | } | ||
46 | case 4: | ||
47 | for (gpio = S5PV310_GPK0(3); gpio <= S5PV310_GPK0(6); gpio++) { | ||
48 | /* Data pin GPK0[3:6] to special-funtion 2 */ | ||
49 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
50 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); | ||
51 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
52 | } | ||
53 | default: | ||
54 | break; | ||
55 | } | ||
56 | |||
57 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { | ||
58 | s3c_gpio_cfgpin(S5PV310_GPK0(2), S3C_GPIO_SFN(2)); | ||
59 | s3c_gpio_setpull(S5PV310_GPK0(2), S3C_GPIO_PULL_UP); | ||
60 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | void s5pv310_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) | ||
65 | { | ||
66 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; | ||
67 | unsigned int gpio; | ||
68 | |||
69 | /* Set all the necessary GPK1[0:1] pins to special-function 2 */ | ||
70 | for (gpio = S5PV310_GPK1(0); gpio < S5PV310_GPK1(2); gpio++) { | ||
71 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
72 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
73 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
74 | } | ||
75 | |||
76 | for (gpio = S5PV310_GPK1(3); gpio <= S5PV310_GPK1(6); gpio++) { | ||
77 | /* Data pin GPK1[3:6] to special-function 2 */ | ||
78 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
79 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); | ||
80 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
81 | } | ||
82 | |||
83 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { | ||
84 | s3c_gpio_cfgpin(S5PV310_GPK1(2), S3C_GPIO_SFN(2)); | ||
85 | s3c_gpio_setpull(S5PV310_GPK1(2), S3C_GPIO_PULL_UP); | ||
86 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | void s5pv310_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) | ||
91 | { | ||
92 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; | ||
93 | unsigned int gpio; | ||
94 | |||
95 | /* Set all the necessary GPK2[0:1] pins to special-function 2 */ | ||
96 | for (gpio = S5PV310_GPK2(0); gpio < S5PV310_GPK2(2); gpio++) { | ||
97 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
98 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
99 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
100 | } | ||
101 | |||
102 | switch (width) { | ||
103 | case 8: | ||
104 | for (gpio = S5PV310_GPK3(3); gpio <= S5PV310_GPK3(6); gpio++) { | ||
105 | /* Data pin GPK3[3:6] to special-function 3 */ | ||
106 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3)); | ||
107 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); | ||
108 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
109 | } | ||
110 | case 4: | ||
111 | for (gpio = S5PV310_GPK2(3); gpio <= S5PV310_GPK2(6); gpio++) { | ||
112 | /* Data pin GPK2[3:6] to special-function 2 */ | ||
113 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
114 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); | ||
115 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
116 | } | ||
117 | default: | ||
118 | break; | ||
119 | } | ||
120 | |||
121 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { | ||
122 | s3c_gpio_cfgpin(S5PV310_GPK2(2), S3C_GPIO_SFN(2)); | ||
123 | s3c_gpio_setpull(S5PV310_GPK2(2), S3C_GPIO_PULL_UP); | ||
124 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | void s5pv310_setup_sdhci3_cfg_gpio(struct platform_device *dev, int width) | ||
129 | { | ||
130 | struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; | ||
131 | unsigned int gpio; | ||
132 | |||
133 | /* Set all the necessary GPK3[0:1] pins to special-function 2 */ | ||
134 | for (gpio = S5PV310_GPK3(0); gpio < S5PV310_GPK3(2); gpio++) { | ||
135 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
136 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); | ||
137 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
138 | } | ||
139 | |||
140 | for (gpio = S5PV310_GPK3(3); gpio <= S5PV310_GPK3(6); gpio++) { | ||
141 | /* Data pin GPK3[3:6] to special-function 2 */ | ||
142 | s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); | ||
143 | s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP); | ||
144 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
145 | } | ||
146 | |||
147 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { | ||
148 | s3c_gpio_cfgpin(S5PV310_GPK3(2), S3C_GPIO_SFN(2)); | ||
149 | s3c_gpio_setpull(S5PV310_GPK3(2), S3C_GPIO_PULL_UP); | ||
150 | s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4); | ||
151 | } | ||
152 | } | ||
diff --git a/arch/arm/mach-s5pv310/setup-sdhci.c b/arch/arm/mach-s5pv310/setup-sdhci.c new file mode 100644 index 000000000000..db8358fc4662 --- /dev/null +++ b/arch/arm/mach-s5pv310/setup-sdhci.c | |||
@@ -0,0 +1,69 @@ | |||
1 | /* linux/arch/arm/mach-s5pv310/setup-sdhci.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
6 | * S5PV310 - Helper functions for settign up SDHCI device(s) (HSMMC) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/types.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/io.h> | ||
18 | |||
19 | #include <linux/mmc/card.h> | ||
20 | #include <linux/mmc/host.h> | ||
21 | |||
22 | #include <plat/regs-sdhci.h> | ||
23 | |||
24 | /* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */ | ||
25 | |||
26 | char *s5pv310_hsmmc_clksrcs[4] = { | ||
27 | [0] = NULL, | ||
28 | [1] = NULL, | ||
29 | [2] = "sclk_mmc", /* mmc_bus */ | ||
30 | [3] = NULL, | ||
31 | }; | ||
32 | |||
33 | void s5pv310_setup_sdhci_cfg_card(struct platform_device *dev, void __iomem *r, | ||
34 | struct mmc_ios *ios, struct mmc_card *card) | ||
35 | { | ||
36 | u32 ctrl2, ctrl3; | ||
37 | |||
38 | /* don't need to alter anything acording to card-type */ | ||
39 | |||
40 | ctrl2 = readl(r + S3C_SDHCI_CONTROL2); | ||
41 | |||
42 | /* select base clock source to HCLK */ | ||
43 | |||
44 | ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK; | ||
45 | |||
46 | /* | ||
47 | * clear async mode, enable conflict mask, rx feedback ctrl, SD | ||
48 | * clk hold and no use debounce count | ||
49 | */ | ||
50 | |||
51 | ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR | | ||
52 | S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK | | ||
53 | S3C_SDHCI_CTRL2_ENFBCLKRX | | ||
54 | S3C_SDHCI_CTRL2_DFCNT_NONE | | ||
55 | S3C_SDHCI_CTRL2_ENCLKOUTHOLD); | ||
56 | |||
57 | /* Tx and Rx feedback clock delay control */ | ||
58 | |||
59 | if (ios->clock < 25 * 1000000) | ||
60 | ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 | | ||
61 | S3C_SDHCI_CTRL3_FCSEL2 | | ||
62 | S3C_SDHCI_CTRL3_FCSEL1 | | ||
63 | S3C_SDHCI_CTRL3_FCSEL0); | ||
64 | else | ||
65 | ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0); | ||
66 | |||
67 | writel(ctrl2, r + S3C_SDHCI_CONTROL2); | ||
68 | writel(ctrl3, r + S3C_SDHCI_CONTROL3); | ||
69 | } | ||
diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c index c0a13ef5436f..96f7dc103b59 100644 --- a/arch/arm/mach-sa1100/cpu-sa1100.c +++ b/arch/arm/mach-sa1100/cpu-sa1100.c | |||
@@ -184,16 +184,15 @@ static int sa1100_target(struct cpufreq_policy *policy, | |||
184 | { | 184 | { |
185 | unsigned int cur = sa11x0_getspeed(0); | 185 | unsigned int cur = sa11x0_getspeed(0); |
186 | unsigned int new_ppcr; | 186 | unsigned int new_ppcr; |
187 | |||
188 | struct cpufreq_freqs freqs; | 187 | struct cpufreq_freqs freqs; |
188 | |||
189 | new_ppcr = sa11x0_freq_to_ppcr(target_freq); | ||
189 | switch(relation){ | 190 | switch(relation){ |
190 | case CPUFREQ_RELATION_L: | 191 | case CPUFREQ_RELATION_L: |
191 | new_ppcr = sa11x0_freq_to_ppcr(target_freq); | ||
192 | if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max) | 192 | if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max) |
193 | new_ppcr--; | 193 | new_ppcr--; |
194 | break; | 194 | break; |
195 | case CPUFREQ_RELATION_H: | 195 | case CPUFREQ_RELATION_H: |
196 | new_ppcr = sa11x0_freq_to_ppcr(target_freq); | ||
197 | if ((sa11x0_ppcr_to_freq(new_ppcr) > target_freq) && | 196 | if ((sa11x0_ppcr_to_freq(new_ppcr) > target_freq) && |
198 | (sa11x0_ppcr_to_freq(new_ppcr - 1) >= policy->min)) | 197 | (sa11x0_ppcr_to_freq(new_ppcr - 1) >= policy->min)) |
199 | new_ppcr--; | 198 | new_ppcr--; |
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index 22a2b44ddb7b..46ca4d4abf91 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/mtd/mtd.h> | 30 | #include <linux/mtd/mtd.h> |
31 | #include <linux/mtd/partitions.h> | 31 | #include <linux/mtd/partitions.h> |
32 | #include <linux/mtd/physmap.h> | 32 | #include <linux/mtd/physmap.h> |
33 | #include <linux/mmc/host.h> | ||
34 | #include <linux/mmc/sh_mmcif.h> | 33 | #include <linux/mmc/sh_mmcif.h> |
35 | #include <linux/i2c.h> | 34 | #include <linux/i2c.h> |
36 | #include <linux/i2c/tsc2007.h> | 35 | #include <linux/i2c/tsc2007.h> |
@@ -44,6 +43,10 @@ | |||
44 | #include <linux/input/sh_keysc.h> | 43 | #include <linux/input/sh_keysc.h> |
45 | #include <linux/usb/r8a66597.h> | 44 | #include <linux/usb/r8a66597.h> |
46 | 45 | ||
46 | #include <media/sh_mobile_ceu.h> | ||
47 | #include <media/sh_mobile_csi2.h> | ||
48 | #include <media/soc_camera.h> | ||
49 | |||
47 | #include <sound/sh_fsi.h> | 50 | #include <sound/sh_fsi.h> |
48 | 51 | ||
49 | #include <video/sh_mobile_hdmi.h> | 52 | #include <video/sh_mobile_hdmi.h> |
@@ -250,7 +253,7 @@ static int slot_cn7_get_cd(struct platform_device *pdev) | |||
250 | /* SH_MMCIF */ | 253 | /* SH_MMCIF */ |
251 | static struct resource sh_mmcif_resources[] = { | 254 | static struct resource sh_mmcif_resources[] = { |
252 | [0] = { | 255 | [0] = { |
253 | .name = "SH_MMCIF", | 256 | .name = "MMCIF", |
254 | .start = 0xE6BD0000, | 257 | .start = 0xE6BD0000, |
255 | .end = 0xE6BD00FF, | 258 | .end = 0xE6BD00FF, |
256 | .flags = IORESOURCE_MEM, | 259 | .flags = IORESOURCE_MEM, |
@@ -390,10 +393,40 @@ static struct platform_device usb1_host_device = { | |||
390 | .resource = usb1_host_resources, | 393 | .resource = usb1_host_resources, |
391 | }; | 394 | }; |
392 | 395 | ||
396 | const static struct fb_videomode ap4evb_lcdc_modes[] = { | ||
397 | { | ||
398 | #ifdef CONFIG_AP4EVB_QHD | ||
399 | .name = "R63302(QHD)", | ||
400 | .xres = 544, | ||
401 | .yres = 961, | ||
402 | .left_margin = 72, | ||
403 | .right_margin = 600, | ||
404 | .hsync_len = 16, | ||
405 | .upper_margin = 8, | ||
406 | .lower_margin = 8, | ||
407 | .vsync_len = 2, | ||
408 | .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, | ||
409 | #else | ||
410 | .name = "WVGA Panel", | ||
411 | .xres = 800, | ||
412 | .yres = 480, | ||
413 | .left_margin = 220, | ||
414 | .right_margin = 110, | ||
415 | .hsync_len = 70, | ||
416 | .upper_margin = 20, | ||
417 | .lower_margin = 5, | ||
418 | .vsync_len = 5, | ||
419 | .sync = 0, | ||
420 | #endif | ||
421 | }, | ||
422 | }; | ||
423 | |||
393 | static struct sh_mobile_lcdc_info lcdc_info = { | 424 | static struct sh_mobile_lcdc_info lcdc_info = { |
394 | .ch[0] = { | 425 | .ch[0] = { |
395 | .chan = LCDC_CHAN_MAINLCD, | 426 | .chan = LCDC_CHAN_MAINLCD, |
396 | .bpp = 16, | 427 | .bpp = 16, |
428 | .lcd_cfg = ap4evb_lcdc_modes, | ||
429 | .num_cfg = ARRAY_SIZE(ap4evb_lcdc_modes), | ||
397 | } | 430 | } |
398 | }; | 431 | }; |
399 | 432 | ||
@@ -532,27 +565,6 @@ static struct platform_device *qhd_devices[] __initdata = { | |||
532 | 565 | ||
533 | /* FSI */ | 566 | /* FSI */ |
534 | #define IRQ_FSI evt2irq(0x1840) | 567 | #define IRQ_FSI evt2irq(0x1840) |
535 | #define FSIACKCR 0xE6150018 | ||
536 | static void fsiackcr_init(struct clk *clk) | ||
537 | { | ||
538 | u32 status = __raw_readl(clk->enable_reg); | ||
539 | |||
540 | /* use external clock */ | ||
541 | status &= ~0x000000ff; | ||
542 | status |= 0x00000080; | ||
543 | __raw_writel(status, clk->enable_reg); | ||
544 | } | ||
545 | |||
546 | static struct clk_ops fsiackcr_clk_ops = { | ||
547 | .init = fsiackcr_init, | ||
548 | }; | ||
549 | |||
550 | static struct clk fsiackcr_clk = { | ||
551 | .ops = &fsiackcr_clk_ops, | ||
552 | .enable_reg = (void __iomem *)FSIACKCR, | ||
553 | .rate = 0, /* unknown */ | ||
554 | }; | ||
555 | |||
556 | static struct sh_fsi_platform_info fsi_info = { | 568 | static struct sh_fsi_platform_info fsi_info = { |
557 | .porta_flags = SH_FSI_BRS_INV | | 569 | .porta_flags = SH_FSI_BRS_INV | |
558 | SH_FSI_OUT_SLAVE_MODE | | 570 | SH_FSI_OUT_SLAVE_MODE | |
@@ -592,26 +604,6 @@ static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = { | |||
592 | .interface_type = RGB24, | 604 | .interface_type = RGB24, |
593 | .clock_divider = 1, | 605 | .clock_divider = 1, |
594 | .flags = LCDC_FLAGS_DWPOL, | 606 | .flags = LCDC_FLAGS_DWPOL, |
595 | .lcd_cfg = { | ||
596 | .name = "HDMI", | ||
597 | /* So far only 720p is supported */ | ||
598 | .xres = 1280, | ||
599 | .yres = 720, | ||
600 | /* | ||
601 | * If left and right margins are not multiples of 8, | ||
602 | * LDHAJR will be adjusted accordingly by the LCDC | ||
603 | * driver. Until we start using EDID, these values | ||
604 | * might have to be adjusted for different monitors. | ||
605 | */ | ||
606 | .left_margin = 200, | ||
607 | .right_margin = 88, | ||
608 | .hsync_len = 48, | ||
609 | .upper_margin = 20, | ||
610 | .lower_margin = 5, | ||
611 | .vsync_len = 5, | ||
612 | .pixclock = 13468, | ||
613 | .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, | ||
614 | }, | ||
615 | } | 607 | } |
616 | }; | 608 | }; |
617 | 609 | ||
@@ -623,7 +615,7 @@ static struct resource lcdc1_resources[] = { | |||
623 | .flags = IORESOURCE_MEM, | 615 | .flags = IORESOURCE_MEM, |
624 | }, | 616 | }, |
625 | [1] = { | 617 | [1] = { |
626 | .start = intcs_evt2irq(0x17a0), | 618 | .start = intcs_evt2irq(0x1780), |
627 | .flags = IORESOURCE_IRQ, | 619 | .flags = IORESOURCE_IRQ, |
628 | }, | 620 | }, |
629 | }; | 621 | }; |
@@ -704,6 +696,95 @@ static struct platform_device leds_device = { | |||
704 | }, | 696 | }, |
705 | }; | 697 | }; |
706 | 698 | ||
699 | static struct i2c_board_info imx074_info = { | ||
700 | I2C_BOARD_INFO("imx074", 0x1a), | ||
701 | }; | ||
702 | |||
703 | struct soc_camera_link imx074_link = { | ||
704 | .bus_id = 0, | ||
705 | .board_info = &imx074_info, | ||
706 | .i2c_adapter_id = 0, | ||
707 | .module_name = "imx074", | ||
708 | }; | ||
709 | |||
710 | static struct platform_device ap4evb_camera = { | ||
711 | .name = "soc-camera-pdrv", | ||
712 | .id = 0, | ||
713 | .dev = { | ||
714 | .platform_data = &imx074_link, | ||
715 | }, | ||
716 | }; | ||
717 | |||
718 | static struct sh_csi2_client_config csi2_clients[] = { | ||
719 | { | ||
720 | .phy = SH_CSI2_PHY_MAIN, | ||
721 | .lanes = 3, | ||
722 | .channel = 0, | ||
723 | .pdev = &ap4evb_camera, | ||
724 | }, | ||
725 | }; | ||
726 | |||
727 | static struct sh_csi2_pdata csi2_info = { | ||
728 | .type = SH_CSI2C, | ||
729 | .clients = csi2_clients, | ||
730 | .num_clients = ARRAY_SIZE(csi2_clients), | ||
731 | .flags = SH_CSI2_ECC | SH_CSI2_CRC, | ||
732 | }; | ||
733 | |||
734 | static struct resource csi2_resources[] = { | ||
735 | [0] = { | ||
736 | .name = "CSI2", | ||
737 | .start = 0xffc90000, | ||
738 | .end = 0xffc90fff, | ||
739 | .flags = IORESOURCE_MEM, | ||
740 | }, | ||
741 | [1] = { | ||
742 | .start = intcs_evt2irq(0x17a0), | ||
743 | .flags = IORESOURCE_IRQ, | ||
744 | }, | ||
745 | }; | ||
746 | |||
747 | static struct platform_device csi2_device = { | ||
748 | .name = "sh-mobile-csi2", | ||
749 | .id = 0, | ||
750 | .num_resources = ARRAY_SIZE(csi2_resources), | ||
751 | .resource = csi2_resources, | ||
752 | .dev = { | ||
753 | .platform_data = &csi2_info, | ||
754 | }, | ||
755 | }; | ||
756 | |||
757 | static struct sh_mobile_ceu_info sh_mobile_ceu_info = { | ||
758 | .flags = SH_CEU_FLAG_USE_8BIT_BUS, | ||
759 | .csi2_dev = &csi2_device.dev, | ||
760 | }; | ||
761 | |||
762 | static struct resource ceu_resources[] = { | ||
763 | [0] = { | ||
764 | .name = "CEU", | ||
765 | .start = 0xfe910000, | ||
766 | .end = 0xfe91009f, | ||
767 | .flags = IORESOURCE_MEM, | ||
768 | }, | ||
769 | [1] = { | ||
770 | .start = intcs_evt2irq(0x880), | ||
771 | .flags = IORESOURCE_IRQ, | ||
772 | }, | ||
773 | [2] = { | ||
774 | /* place holder for contiguous memory */ | ||
775 | }, | ||
776 | }; | ||
777 | |||
778 | static struct platform_device ceu_device = { | ||
779 | .name = "sh_mobile_ceu", | ||
780 | .id = 0, /* "ceu0" clock */ | ||
781 | .num_resources = ARRAY_SIZE(ceu_resources), | ||
782 | .resource = ceu_resources, | ||
783 | .dev = { | ||
784 | .platform_data = &sh_mobile_ceu_info, | ||
785 | }, | ||
786 | }; | ||
787 | |||
707 | static struct platform_device *ap4evb_devices[] __initdata = { | 788 | static struct platform_device *ap4evb_devices[] __initdata = { |
708 | &leds_device, | 789 | &leds_device, |
709 | &nor_flash_device, | 790 | &nor_flash_device, |
@@ -716,6 +797,9 @@ static struct platform_device *ap4evb_devices[] __initdata = { | |||
716 | &lcdc1_device, | 797 | &lcdc1_device, |
717 | &lcdc_device, | 798 | &lcdc_device, |
718 | &hdmi_device, | 799 | &hdmi_device, |
800 | &csi2_device, | ||
801 | &ceu_device, | ||
802 | &ap4evb_camera, | ||
719 | }; | 803 | }; |
720 | 804 | ||
721 | static int __init hdmi_init_pm_clock(void) | 805 | static int __init hdmi_init_pm_clock(void) |
@@ -730,22 +814,22 @@ static int __init hdmi_init_pm_clock(void) | |||
730 | goto out; | 814 | goto out; |
731 | } | 815 | } |
732 | 816 | ||
733 | ret = clk_set_parent(&pllc2_clk, &dv_clki_div2_clk); | 817 | ret = clk_set_parent(&sh7372_pllc2_clk, &sh7372_dv_clki_div2_clk); |
734 | if (ret < 0) { | 818 | if (ret < 0) { |
735 | pr_err("Cannot set PLLC2 parent: %d, %d users\n", ret, pllc2_clk.usecount); | 819 | pr_err("Cannot set PLLC2 parent: %d, %d users\n", ret, sh7372_pllc2_clk.usecount); |
736 | goto out; | 820 | goto out; |
737 | } | 821 | } |
738 | 822 | ||
739 | pr_debug("PLLC2 initial frequency %lu\n", clk_get_rate(&pllc2_clk)); | 823 | pr_debug("PLLC2 initial frequency %lu\n", clk_get_rate(&sh7372_pllc2_clk)); |
740 | 824 | ||
741 | rate = clk_round_rate(&pllc2_clk, 594000000); | 825 | rate = clk_round_rate(&sh7372_pllc2_clk, 594000000); |
742 | if (rate < 0) { | 826 | if (rate < 0) { |
743 | pr_err("Cannot get suitable rate: %ld\n", rate); | 827 | pr_err("Cannot get suitable rate: %ld\n", rate); |
744 | ret = rate; | 828 | ret = rate; |
745 | goto out; | 829 | goto out; |
746 | } | 830 | } |
747 | 831 | ||
748 | ret = clk_set_rate(&pllc2_clk, rate); | 832 | ret = clk_set_rate(&sh7372_pllc2_clk, rate); |
749 | if (ret < 0) { | 833 | if (ret < 0) { |
750 | pr_err("Cannot set rate %ld: %d\n", rate, ret); | 834 | pr_err("Cannot set rate %ld: %d\n", rate, ret); |
751 | goto out; | 835 | goto out; |
@@ -753,7 +837,7 @@ static int __init hdmi_init_pm_clock(void) | |||
753 | 837 | ||
754 | pr_debug("PLLC2 set frequency %lu\n", rate); | 838 | pr_debug("PLLC2 set frequency %lu\n", rate); |
755 | 839 | ||
756 | ret = clk_set_parent(hdmi_ick, &pllc2_clk); | 840 | ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk); |
757 | if (ret < 0) { | 841 | if (ret < 0) { |
758 | pr_err("Cannot set HDMI parent: %d\n", ret); | 842 | pr_err("Cannot set HDMI parent: %d\n", ret); |
759 | goto out; | 843 | goto out; |
@@ -767,11 +851,51 @@ out: | |||
767 | 851 | ||
768 | device_initcall(hdmi_init_pm_clock); | 852 | device_initcall(hdmi_init_pm_clock); |
769 | 853 | ||
854 | #define FSIACK_DUMMY_RATE 48000 | ||
855 | static int __init fsi_init_pm_clock(void) | ||
856 | { | ||
857 | struct clk *fsia_ick; | ||
858 | int ret; | ||
859 | |||
860 | /* | ||
861 | * FSIACK is connected to AK4642, | ||
862 | * and the rate is depend on playing sound rate. | ||
863 | * So, set dummy rate (= 48k) here | ||
864 | */ | ||
865 | ret = clk_set_rate(&sh7372_fsiack_clk, FSIACK_DUMMY_RATE); | ||
866 | if (ret < 0) { | ||
867 | pr_err("Cannot set FSIACK dummy rate: %d\n", ret); | ||
868 | return ret; | ||
869 | } | ||
870 | |||
871 | fsia_ick = clk_get(&fsi_device.dev, "icka"); | ||
872 | if (IS_ERR(fsia_ick)) { | ||
873 | ret = PTR_ERR(fsia_ick); | ||
874 | pr_err("Cannot get FSI ICK: %d\n", ret); | ||
875 | return ret; | ||
876 | } | ||
877 | |||
878 | ret = clk_set_parent(fsia_ick, &sh7372_fsiack_clk); | ||
879 | if (ret < 0) { | ||
880 | pr_err("Cannot set FSI-A parent: %d\n", ret); | ||
881 | goto out; | ||
882 | } | ||
883 | |||
884 | ret = clk_set_rate(fsia_ick, FSIACK_DUMMY_RATE); | ||
885 | if (ret < 0) | ||
886 | pr_err("Cannot set FSI-A rate: %d\n", ret); | ||
887 | |||
888 | out: | ||
889 | clk_put(fsia_ick); | ||
890 | |||
891 | return ret; | ||
892 | } | ||
893 | device_initcall(fsi_init_pm_clock); | ||
894 | |||
770 | /* | 895 | /* |
771 | * FIXME !! | 896 | * FIXME !! |
772 | * | 897 | * |
773 | * gpio_no_direction | 898 | * gpio_no_direction |
774 | * gpio_pull_up | ||
775 | * are quick_hack. | 899 | * are quick_hack. |
776 | * | 900 | * |
777 | * current gpio frame work doesn't have | 901 | * current gpio frame work doesn't have |
@@ -783,49 +907,37 @@ static void __init gpio_no_direction(u32 addr) | |||
783 | __raw_writeb(0x00, addr); | 907 | __raw_writeb(0x00, addr); |
784 | } | 908 | } |
785 | 909 | ||
786 | static void __init gpio_pull_up(u32 addr) | ||
787 | { | ||
788 | u8 data = __raw_readb(addr); | ||
789 | |||
790 | data &= 0x0F; | ||
791 | data |= 0xC0; | ||
792 | __raw_writeb(data, addr); | ||
793 | } | ||
794 | |||
795 | /* TouchScreen */ | 910 | /* TouchScreen */ |
911 | #ifdef CONFIG_AP4EVB_QHD | ||
912 | # define GPIO_TSC_IRQ GPIO_FN_IRQ28_123 | ||
913 | # define GPIO_TSC_PORT GPIO_PORT123 | ||
914 | #else /* WVGA */ | ||
915 | # define GPIO_TSC_IRQ GPIO_FN_IRQ7_40 | ||
916 | # define GPIO_TSC_PORT GPIO_PORT40 | ||
917 | #endif | ||
918 | |||
796 | #define IRQ28 evt2irq(0x3380) /* IRQ28A */ | 919 | #define IRQ28 evt2irq(0x3380) /* IRQ28A */ |
797 | #define IRQ7 evt2irq(0x02e0) /* IRQ7A */ | 920 | #define IRQ7 evt2irq(0x02e0) /* IRQ7A */ |
798 | static int ts_get_pendown_state(void) | 921 | static int ts_get_pendown_state(void) |
799 | { | 922 | { |
800 | int val1, val2; | 923 | int val; |
801 | 924 | ||
802 | gpio_free(GPIO_FN_IRQ28_123); | 925 | gpio_free(GPIO_TSC_IRQ); |
803 | gpio_free(GPIO_FN_IRQ7_40); | ||
804 | 926 | ||
805 | gpio_request(GPIO_PORT123, NULL); | 927 | gpio_request(GPIO_TSC_PORT, NULL); |
806 | gpio_request(GPIO_PORT40, NULL); | ||
807 | 928 | ||
808 | gpio_direction_input(GPIO_PORT123); | 929 | gpio_direction_input(GPIO_TSC_PORT); |
809 | gpio_direction_input(GPIO_PORT40); | ||
810 | 930 | ||
811 | val1 = gpio_get_value(GPIO_PORT123); | 931 | val = gpio_get_value(GPIO_TSC_PORT); |
812 | val2 = gpio_get_value(GPIO_PORT40); | ||
813 | 932 | ||
814 | gpio_request(GPIO_FN_IRQ28_123, NULL); /* for QHD */ | 933 | gpio_request(GPIO_TSC_IRQ, NULL); |
815 | gpio_request(GPIO_FN_IRQ7_40, NULL); /* for WVGA */ | ||
816 | 934 | ||
817 | return val1 ^ val2; | 935 | return !val; |
818 | } | 936 | } |
819 | 937 | ||
820 | #define PORT40CR 0xE6051028 | ||
821 | #define PORT123CR 0xE605007B | ||
822 | static int ts_init(void) | 938 | static int ts_init(void) |
823 | { | 939 | { |
824 | gpio_request(GPIO_FN_IRQ28_123, NULL); /* for QHD */ | 940 | gpio_request(GPIO_TSC_IRQ, NULL); |
825 | gpio_request(GPIO_FN_IRQ7_40, NULL); /* for WVGA */ | ||
826 | |||
827 | gpio_pull_up(PORT40CR); | ||
828 | gpio_pull_up(PORT123CR); | ||
829 | 941 | ||
830 | return 0; | 942 | return 0; |
831 | } | 943 | } |
@@ -974,14 +1086,6 @@ static void __init ap4evb_init(void) | |||
974 | clk_put(clk); | 1086 | clk_put(clk); |
975 | } | 1087 | } |
976 | 1088 | ||
977 | /* change parent of FSI A */ | ||
978 | clk = clk_get(NULL, "fsia_clk"); | ||
979 | if (!IS_ERR(clk)) { | ||
980 | clk_register(&fsiackcr_clk); | ||
981 | clk_set_parent(clk, &fsiackcr_clk); | ||
982 | clk_put(clk); | ||
983 | } | ||
984 | |||
985 | /* | 1089 | /* |
986 | * set irq priority, to avoid sound chopping | 1090 | * set irq priority, to avoid sound chopping |
987 | * when NFS rootfs is used | 1091 | * when NFS rootfs is used |
@@ -996,8 +1100,10 @@ static void __init ap4evb_init(void) | |||
996 | ARRAY_SIZE(i2c1_devices)); | 1100 | ARRAY_SIZE(i2c1_devices)); |
997 | 1101 | ||
998 | #ifdef CONFIG_AP4EVB_QHD | 1102 | #ifdef CONFIG_AP4EVB_QHD |
1103 | |||
999 | /* | 1104 | /* |
1000 | * QHD | 1105 | * For QHD Panel (MIPI-DSI, CONFIG_AP4EVB_QHD=y) and |
1106 | * IRQ28 for Touch Panel, set dip switches S3, S43 as OFF, ON. | ||
1001 | */ | 1107 | */ |
1002 | 1108 | ||
1003 | /* enable KEYSC */ | 1109 | /* enable KEYSC */ |
@@ -1023,17 +1129,6 @@ static void __init ap4evb_init(void) | |||
1023 | lcdc_info.ch[0].interface_type = RGB24; | 1129 | lcdc_info.ch[0].interface_type = RGB24; |
1024 | lcdc_info.ch[0].clock_divider = 1; | 1130 | lcdc_info.ch[0].clock_divider = 1; |
1025 | lcdc_info.ch[0].flags = LCDC_FLAGS_DWPOL; | 1131 | lcdc_info.ch[0].flags = LCDC_FLAGS_DWPOL; |
1026 | lcdc_info.ch[0].lcd_cfg.name = "R63302(QHD)"; | ||
1027 | lcdc_info.ch[0].lcd_cfg.xres = 544; | ||
1028 | lcdc_info.ch[0].lcd_cfg.yres = 961; | ||
1029 | lcdc_info.ch[0].lcd_cfg.left_margin = 72; | ||
1030 | lcdc_info.ch[0].lcd_cfg.right_margin = 600; | ||
1031 | lcdc_info.ch[0].lcd_cfg.hsync_len = 16; | ||
1032 | lcdc_info.ch[0].lcd_cfg.upper_margin = 8; | ||
1033 | lcdc_info.ch[0].lcd_cfg.lower_margin = 8; | ||
1034 | lcdc_info.ch[0].lcd_cfg.vsync_len = 2; | ||
1035 | lcdc_info.ch[0].lcd_cfg.sync = FB_SYNC_VERT_HIGH_ACT | | ||
1036 | FB_SYNC_HOR_HIGH_ACT; | ||
1037 | lcdc_info.ch[0].lcd_size_cfg.width = 44; | 1132 | lcdc_info.ch[0].lcd_size_cfg.width = 44; |
1038 | lcdc_info.ch[0].lcd_size_cfg.height = 79; | 1133 | lcdc_info.ch[0].lcd_size_cfg.height = 79; |
1039 | 1134 | ||
@@ -1041,8 +1136,10 @@ static void __init ap4evb_init(void) | |||
1041 | 1136 | ||
1042 | #else | 1137 | #else |
1043 | /* | 1138 | /* |
1044 | * WVGA | 1139 | * For WVGA Panel (18-bit RGB, CONFIG_AP4EVB_WVGA=y) and |
1140 | * IRQ7 for Touch Panel, set dip switches S3, S43 to ON, OFF. | ||
1045 | */ | 1141 | */ |
1142 | |||
1046 | gpio_request(GPIO_FN_LCDD17, NULL); | 1143 | gpio_request(GPIO_FN_LCDD17, NULL); |
1047 | gpio_request(GPIO_FN_LCDD16, NULL); | 1144 | gpio_request(GPIO_FN_LCDD16, NULL); |
1048 | gpio_request(GPIO_FN_LCDD15, NULL); | 1145 | gpio_request(GPIO_FN_LCDD15, NULL); |
@@ -1074,16 +1171,6 @@ static void __init ap4evb_init(void) | |||
1074 | lcdc_info.ch[0].interface_type = RGB18; | 1171 | lcdc_info.ch[0].interface_type = RGB18; |
1075 | lcdc_info.ch[0].clock_divider = 2; | 1172 | lcdc_info.ch[0].clock_divider = 2; |
1076 | lcdc_info.ch[0].flags = 0; | 1173 | lcdc_info.ch[0].flags = 0; |
1077 | lcdc_info.ch[0].lcd_cfg.name = "WVGA Panel"; | ||
1078 | lcdc_info.ch[0].lcd_cfg.xres = 800; | ||
1079 | lcdc_info.ch[0].lcd_cfg.yres = 480; | ||
1080 | lcdc_info.ch[0].lcd_cfg.left_margin = 220; | ||
1081 | lcdc_info.ch[0].lcd_cfg.right_margin = 110; | ||
1082 | lcdc_info.ch[0].lcd_cfg.hsync_len = 70; | ||
1083 | lcdc_info.ch[0].lcd_cfg.upper_margin = 20; | ||
1084 | lcdc_info.ch[0].lcd_cfg.lower_margin = 5; | ||
1085 | lcdc_info.ch[0].lcd_cfg.vsync_len = 5; | ||
1086 | lcdc_info.ch[0].lcd_cfg.sync = 0; | ||
1087 | lcdc_info.ch[0].lcd_size_cfg.width = 152; | 1174 | lcdc_info.ch[0].lcd_size_cfg.width = 152; |
1088 | lcdc_info.ch[0].lcd_size_cfg.height = 91; | 1175 | lcdc_info.ch[0].lcd_size_cfg.height = 91; |
1089 | 1176 | ||
@@ -1094,6 +1181,23 @@ static void __init ap4evb_init(void) | |||
1094 | i2c_register_board_info(0, &tsc_device, 1); | 1181 | i2c_register_board_info(0, &tsc_device, 1); |
1095 | #endif /* CONFIG_AP4EVB_QHD */ | 1182 | #endif /* CONFIG_AP4EVB_QHD */ |
1096 | 1183 | ||
1184 | /* CEU */ | ||
1185 | |||
1186 | /* | ||
1187 | * TODO: reserve memory for V4L2 DMA buffers, when a suitable API | ||
1188 | * becomes available | ||
1189 | */ | ||
1190 | |||
1191 | /* MIPI-CSI stuff */ | ||
1192 | gpio_request(GPIO_FN_VIO_CKO, NULL); | ||
1193 | |||
1194 | clk = clk_get(NULL, "vck1_clk"); | ||
1195 | if (!IS_ERR(clk)) { | ||
1196 | clk_set_rate(clk, clk_round_rate(clk, 13000000)); | ||
1197 | clk_enable(clk); | ||
1198 | clk_put(clk); | ||
1199 | } | ||
1200 | |||
1097 | sh7372_add_standard_devices(); | 1201 | sh7372_add_standard_devices(); |
1098 | 1202 | ||
1099 | /* HDMI */ | 1203 | /* HDMI */ |
@@ -1116,7 +1220,7 @@ static void __init ap4evb_timer_init(void) | |||
1116 | shmobile_timer.init(); | 1220 | shmobile_timer.init(); |
1117 | 1221 | ||
1118 | /* External clock source */ | 1222 | /* External clock source */ |
1119 | clk_set_rate(&dv_clki_clk, 27000000); | 1223 | clk_set_rate(&sh7372_dv_clki_clk, 27000000); |
1120 | } | 1224 | } |
1121 | 1225 | ||
1122 | static struct sys_timer ap4evb_timer = { | 1226 | static struct sys_timer ap4evb_timer = { |
diff --git a/arch/arm/mach-shmobile/clock-sh7367.c b/arch/arm/mach-shmobile/clock-sh7367.c index b6454c9f2abb..9f78729098f2 100644 --- a/arch/arm/mach-shmobile/clock-sh7367.c +++ b/arch/arm/mach-shmobile/clock-sh7367.c | |||
@@ -321,7 +321,7 @@ static struct clk_lookup lookups[] = { | |||
321 | CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[SYMSTP001]), /* SCIFA3 */ | 321 | CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[SYMSTP001]), /* SCIFA3 */ |
322 | CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[SYMSTP000]), /* SCIFA4 */ | 322 | CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[SYMSTP000]), /* SCIFA4 */ |
323 | CLKDEV_DEV_ID("sh_siu", &mstp_clks[SYMSTP231]), /* SIU */ | 323 | CLKDEV_DEV_ID("sh_siu", &mstp_clks[SYMSTP231]), /* SIU */ |
324 | CLKDEV_CON_ID("cmt1", &mstp_clks[SYMSTP229]), /* CMT10 */ | 324 | CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[SYMSTP229]), /* CMT10 */ |
325 | CLKDEV_DEV_ID("sh_irda", &mstp_clks[SYMSTP225]), /* IRDA */ | 325 | CLKDEV_DEV_ID("sh_irda", &mstp_clks[SYMSTP225]), /* IRDA */ |
326 | CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[SYMSTP223]), /* IIC1 */ | 326 | CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[SYMSTP223]), /* IIC1 */ |
327 | CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[SYMSTP222]), /* USBHS */ | 327 | CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[SYMSTP222]), /* USBHS */ |
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c index 759468992ad2..8565aefa21fd 100644 --- a/arch/arm/mach-shmobile/clock-sh7372.c +++ b/arch/arm/mach-shmobile/clock-sh7372.c | |||
@@ -51,7 +51,7 @@ | |||
51 | #define SMSTPCR4 0xe6150140 | 51 | #define SMSTPCR4 0xe6150140 |
52 | 52 | ||
53 | /* Platforms must set frequency on their DV_CLKI pin */ | 53 | /* Platforms must set frequency on their DV_CLKI pin */ |
54 | struct clk dv_clki_clk = { | 54 | struct clk sh7372_dv_clki_clk = { |
55 | }; | 55 | }; |
56 | 56 | ||
57 | /* Fixed 32 KHz root clock from EXTALR pin */ | 57 | /* Fixed 32 KHz root clock from EXTALR pin */ |
@@ -86,9 +86,9 @@ static struct clk_ops div2_clk_ops = { | |||
86 | }; | 86 | }; |
87 | 87 | ||
88 | /* Divide dv_clki by two */ | 88 | /* Divide dv_clki by two */ |
89 | struct clk dv_clki_div2_clk = { | 89 | struct clk sh7372_dv_clki_div2_clk = { |
90 | .ops = &div2_clk_ops, | 90 | .ops = &div2_clk_ops, |
91 | .parent = &dv_clki_clk, | 91 | .parent = &sh7372_dv_clki_clk, |
92 | }; | 92 | }; |
93 | 93 | ||
94 | /* Divide extal1 by two */ | 94 | /* Divide extal1 by two */ |
@@ -150,7 +150,7 @@ static struct clk pllc1_div2_clk = { | |||
150 | static struct clk *pllc2_parent[] = { | 150 | static struct clk *pllc2_parent[] = { |
151 | [0] = &extal1_div2_clk, | 151 | [0] = &extal1_div2_clk, |
152 | [1] = &extal2_div2_clk, | 152 | [1] = &extal2_div2_clk, |
153 | [2] = &dv_clki_div2_clk, | 153 | [2] = &sh7372_dv_clki_div2_clk, |
154 | }; | 154 | }; |
155 | 155 | ||
156 | /* Only multipliers 20 * 2 to 46 * 2 are valid, last entry for CPUFREQ_TABLE_END */ | 156 | /* Only multipliers 20 * 2 to 46 * 2 are valid, last entry for CPUFREQ_TABLE_END */ |
@@ -284,7 +284,7 @@ static struct clk_ops pllc2_clk_ops = { | |||
284 | .set_parent = pllc2_set_parent, | 284 | .set_parent = pllc2_set_parent, |
285 | }; | 285 | }; |
286 | 286 | ||
287 | struct clk pllc2_clk = { | 287 | struct clk sh7372_pllc2_clk = { |
288 | .ops = &pllc2_clk_ops, | 288 | .ops = &pllc2_clk_ops, |
289 | .parent = &extal1_div2_clk, | 289 | .parent = &extal1_div2_clk, |
290 | .freq_table = pllc2_freq_table, | 290 | .freq_table = pllc2_freq_table, |
@@ -292,19 +292,28 @@ struct clk pllc2_clk = { | |||
292 | .parent_num = ARRAY_SIZE(pllc2_parent), | 292 | .parent_num = ARRAY_SIZE(pllc2_parent), |
293 | }; | 293 | }; |
294 | 294 | ||
295 | /* External input clock (pin name: FSIACK/FSIBCK ) */ | ||
296 | struct clk sh7372_fsiack_clk = { | ||
297 | }; | ||
298 | |||
299 | struct clk sh7372_fsibck_clk = { | ||
300 | }; | ||
301 | |||
295 | static struct clk *main_clks[] = { | 302 | static struct clk *main_clks[] = { |
296 | &dv_clki_clk, | 303 | &sh7372_dv_clki_clk, |
297 | &r_clk, | 304 | &r_clk, |
298 | &sh7372_extal1_clk, | 305 | &sh7372_extal1_clk, |
299 | &sh7372_extal2_clk, | 306 | &sh7372_extal2_clk, |
300 | &dv_clki_div2_clk, | 307 | &sh7372_dv_clki_div2_clk, |
301 | &extal1_div2_clk, | 308 | &extal1_div2_clk, |
302 | &extal2_div2_clk, | 309 | &extal2_div2_clk, |
303 | &extal2_div4_clk, | 310 | &extal2_div4_clk, |
304 | &pllc0_clk, | 311 | &pllc0_clk, |
305 | &pllc1_clk, | 312 | &pllc1_clk, |
306 | &pllc1_div2_clk, | 313 | &pllc1_div2_clk, |
307 | &pllc2_clk, | 314 | &sh7372_pllc2_clk, |
315 | &sh7372_fsiack_clk, | ||
316 | &sh7372_fsibck_clk, | ||
308 | }; | 317 | }; |
309 | 318 | ||
310 | static void div4_kick(struct clk *clk) | 319 | static void div4_kick(struct clk *clk) |
@@ -357,7 +366,7 @@ static struct clk div4_clks[DIV4_NR] = { | |||
357 | }; | 366 | }; |
358 | 367 | ||
359 | enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_FMSI, DIV6_FMSO, | 368 | enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_FMSI, DIV6_FMSO, |
360 | DIV6_FSIA, DIV6_FSIB, DIV6_SUB, DIV6_SPU, | 369 | DIV6_SUB, DIV6_SPU, |
361 | DIV6_VOU, DIV6_DSIT, DIV6_DSI0P, DIV6_DSI1P, | 370 | DIV6_VOU, DIV6_DSIT, DIV6_DSI0P, DIV6_DSI1P, |
362 | DIV6_NR }; | 371 | DIV6_NR }; |
363 | 372 | ||
@@ -367,8 +376,6 @@ static struct clk div6_clks[DIV6_NR] = { | |||
367 | [DIV6_VCK3] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR3, 0), | 376 | [DIV6_VCK3] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR3, 0), |
368 | [DIV6_FMSI] = SH_CLK_DIV6(&pllc1_div2_clk, FMSICKCR, 0), | 377 | [DIV6_FMSI] = SH_CLK_DIV6(&pllc1_div2_clk, FMSICKCR, 0), |
369 | [DIV6_FMSO] = SH_CLK_DIV6(&pllc1_div2_clk, FMSOCKCR, 0), | 378 | [DIV6_FMSO] = SH_CLK_DIV6(&pllc1_div2_clk, FMSOCKCR, 0), |
370 | [DIV6_FSIA] = SH_CLK_DIV6(&pllc1_div2_clk, FSIACKCR, 0), | ||
371 | [DIV6_FSIB] = SH_CLK_DIV6(&pllc1_div2_clk, FSIBCKCR, 0), | ||
372 | [DIV6_SUB] = SH_CLK_DIV6(&sh7372_extal2_clk, SUBCKCR, 0), | 379 | [DIV6_SUB] = SH_CLK_DIV6(&sh7372_extal2_clk, SUBCKCR, 0), |
373 | [DIV6_SPU] = SH_CLK_DIV6(&pllc1_div2_clk, SPUCKCR, 0), | 380 | [DIV6_SPU] = SH_CLK_DIV6(&pllc1_div2_clk, SPUCKCR, 0), |
374 | [DIV6_VOU] = SH_CLK_DIV6(&pllc1_div2_clk, VOUCKCR, 0), | 381 | [DIV6_VOU] = SH_CLK_DIV6(&pllc1_div2_clk, VOUCKCR, 0), |
@@ -377,24 +384,42 @@ static struct clk div6_clks[DIV6_NR] = { | |||
377 | [DIV6_DSI1P] = SH_CLK_DIV6(&pllc1_div2_clk, DSI1PCKCR, 0), | 384 | [DIV6_DSI1P] = SH_CLK_DIV6(&pllc1_div2_clk, DSI1PCKCR, 0), |
378 | }; | 385 | }; |
379 | 386 | ||
380 | enum { DIV6_HDMI, DIV6_REPARENT_NR }; | 387 | enum { DIV6_HDMI, DIV6_FSIA, DIV6_FSIB, DIV6_REPARENT_NR }; |
381 | 388 | ||
382 | /* Indices are important - they are the actual src selecting values */ | 389 | /* Indices are important - they are the actual src selecting values */ |
383 | static struct clk *hdmi_parent[] = { | 390 | static struct clk *hdmi_parent[] = { |
384 | [0] = &pllc1_div2_clk, | 391 | [0] = &pllc1_div2_clk, |
385 | [1] = &pllc2_clk, | 392 | [1] = &sh7372_pllc2_clk, |
386 | [2] = &dv_clki_clk, | 393 | [2] = &sh7372_dv_clki_clk, |
387 | [3] = NULL, /* pllc2_div4 not implemented yet */ | 394 | [3] = NULL, /* pllc2_div4 not implemented yet */ |
388 | }; | 395 | }; |
389 | 396 | ||
397 | static struct clk *fsiackcr_parent[] = { | ||
398 | [0] = &pllc1_div2_clk, | ||
399 | [1] = &sh7372_pllc2_clk, | ||
400 | [2] = &sh7372_fsiack_clk, /* external input for FSI A */ | ||
401 | [3] = NULL, /* setting prohibited */ | ||
402 | }; | ||
403 | |||
404 | static struct clk *fsibckcr_parent[] = { | ||
405 | [0] = &pllc1_div2_clk, | ||
406 | [1] = &sh7372_pllc2_clk, | ||
407 | [2] = &sh7372_fsibck_clk, /* external input for FSI B */ | ||
408 | [3] = NULL, /* setting prohibited */ | ||
409 | }; | ||
410 | |||
390 | static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { | 411 | static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { |
391 | [DIV6_HDMI] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, HDMICKCR, 0, | 412 | [DIV6_HDMI] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, HDMICKCR, 0, |
392 | hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2), | 413 | hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2), |
414 | [DIV6_FSIA] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, FSIACKCR, 0, | ||
415 | fsiackcr_parent, ARRAY_SIZE(fsiackcr_parent), 6, 2), | ||
416 | [DIV6_FSIB] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, FSIBCKCR, 0, | ||
417 | fsibckcr_parent, ARRAY_SIZE(fsibckcr_parent), 6, 2), | ||
393 | }; | 418 | }; |
394 | 419 | ||
395 | enum { MSTP001, | 420 | enum { MSTP001, |
396 | MSTP131, MSTP130, | 421 | MSTP131, MSTP130, |
397 | MSTP129, MSTP128, MSTP127, MSTP126, | 422 | MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, |
398 | MSTP118, MSTP117, MSTP116, | 423 | MSTP118, MSTP117, MSTP116, |
399 | MSTP106, MSTP101, MSTP100, | 424 | MSTP106, MSTP101, MSTP100, |
400 | MSTP223, | 425 | MSTP223, |
@@ -414,6 +439,7 @@ static struct clk mstp_clks[MSTP_NR] = { | |||
414 | [MSTP128] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 28, 0), /* VEU0 */ | 439 | [MSTP128] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 28, 0), /* VEU0 */ |
415 | [MSTP127] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 27, 0), /* CEU */ | 440 | [MSTP127] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 27, 0), /* CEU */ |
416 | [MSTP126] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 26, 0), /* CSI2 */ | 441 | [MSTP126] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 26, 0), /* CSI2 */ |
442 | [MSTP125] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 25, 0), /* TMU0 */ | ||
417 | [MSTP118] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 18, 0), /* DSITX */ | 443 | [MSTP118] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 18, 0), /* DSITX */ |
418 | [MSTP117] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 17, 0), /* LCDC1 */ | 444 | [MSTP117] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 17, 0), /* LCDC1 */ |
419 | [MSTP116] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */ | 445 | [MSTP116] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */ |
@@ -429,7 +455,7 @@ static struct clk mstp_clks[MSTP_NR] = { | |||
429 | [MSTP201] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */ | 455 | [MSTP201] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */ |
430 | [MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */ | 456 | [MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */ |
431 | [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ | 457 | [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ |
432 | [MSTP328] = MSTP(&div6_clks[DIV6_SPU], SMSTPCR3, 28, 0), /* FSIA */ | 458 | [MSTP328] = MSTP(&div6_clks[DIV6_SPU], SMSTPCR3, 28, 0), /* FSI2 */ |
433 | [MSTP323] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */ | 459 | [MSTP323] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */ |
434 | [MSTP322] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 22, 0), /* USB0 */ | 460 | [MSTP322] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 22, 0), /* USB0 */ |
435 | [MSTP314] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */ | 461 | [MSTP314] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */ |
@@ -445,10 +471,11 @@ static struct clk mstp_clks[MSTP_NR] = { | |||
445 | 471 | ||
446 | #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } | 472 | #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } |
447 | #define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk } | 473 | #define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk } |
474 | #define CLKDEV_ICK_ID(_cid, _did, _clk) { .con_id = _cid, .dev_id = _did, .clk = _clk } | ||
448 | 475 | ||
449 | static struct clk_lookup lookups[] = { | 476 | static struct clk_lookup lookups[] = { |
450 | /* main clocks */ | 477 | /* main clocks */ |
451 | CLKDEV_CON_ID("dv_clki_div2_clk", &dv_clki_div2_clk), | 478 | CLKDEV_CON_ID("dv_clki_div2_clk", &sh7372_dv_clki_div2_clk), |
452 | CLKDEV_CON_ID("r_clk", &r_clk), | 479 | CLKDEV_CON_ID("r_clk", &r_clk), |
453 | CLKDEV_CON_ID("extal1", &sh7372_extal1_clk), | 480 | CLKDEV_CON_ID("extal1", &sh7372_extal1_clk), |
454 | CLKDEV_CON_ID("extal2", &sh7372_extal2_clk), | 481 | CLKDEV_CON_ID("extal2", &sh7372_extal2_clk), |
@@ -458,7 +485,7 @@ static struct clk_lookup lookups[] = { | |||
458 | CLKDEV_CON_ID("pllc0_clk", &pllc0_clk), | 485 | CLKDEV_CON_ID("pllc0_clk", &pllc0_clk), |
459 | CLKDEV_CON_ID("pllc1_clk", &pllc1_clk), | 486 | CLKDEV_CON_ID("pllc1_clk", &pllc1_clk), |
460 | CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk), | 487 | CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk), |
461 | CLKDEV_CON_ID("pllc2_clk", &pllc2_clk), | 488 | CLKDEV_CON_ID("pllc2_clk", &sh7372_pllc2_clk), |
462 | 489 | ||
463 | /* DIV4 clocks */ | 490 | /* DIV4 clocks */ |
464 | CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), | 491 | CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), |
@@ -483,8 +510,8 @@ static struct clk_lookup lookups[] = { | |||
483 | CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]), | 510 | CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]), |
484 | CLKDEV_CON_ID("fmsi_clk", &div6_clks[DIV6_FMSI]), | 511 | CLKDEV_CON_ID("fmsi_clk", &div6_clks[DIV6_FMSI]), |
485 | CLKDEV_CON_ID("fmso_clk", &div6_clks[DIV6_FMSO]), | 512 | CLKDEV_CON_ID("fmso_clk", &div6_clks[DIV6_FMSO]), |
486 | CLKDEV_CON_ID("fsia_clk", &div6_clks[DIV6_FSIA]), | 513 | CLKDEV_CON_ID("fsia_clk", &div6_reparent_clks[DIV6_FSIA]), |
487 | CLKDEV_CON_ID("fsib_clk", &div6_clks[DIV6_FSIB]), | 514 | CLKDEV_CON_ID("fsib_clk", &div6_reparent_clks[DIV6_FSIB]), |
488 | CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]), | 515 | CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]), |
489 | CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]), | 516 | CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]), |
490 | CLKDEV_CON_ID("vou_clk", &div6_clks[DIV6_VOU]), | 517 | CLKDEV_CON_ID("vou_clk", &div6_clks[DIV6_VOU]), |
@@ -501,6 +528,8 @@ static struct clk_lookup lookups[] = { | |||
501 | CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[MSTP128]), /* VEU0 */ | 528 | CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[MSTP128]), /* VEU0 */ |
502 | CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), /* CEU */ | 529 | CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), /* CEU */ |
503 | CLKDEV_DEV_ID("sh-mobile-csi2.0", &mstp_clks[MSTP126]), /* CSI2 */ | 530 | CLKDEV_DEV_ID("sh-mobile-csi2.0", &mstp_clks[MSTP126]), /* CSI2 */ |
531 | CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP125]), /* TMU00 */ | ||
532 | CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP125]), /* TMU01 */ | ||
504 | CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX */ | 533 | CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX */ |
505 | CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), /* LCDC1 */ | 534 | CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), /* LCDC1 */ |
506 | CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */ | 535 | CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */ |
@@ -516,7 +545,7 @@ static struct clk_lookup lookups[] = { | |||
516 | CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), /* SCIFA2 */ | 545 | CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), /* SCIFA2 */ |
517 | CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */ | 546 | CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */ |
518 | CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */ | 547 | CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */ |
519 | CLKDEV_CON_ID("cmt1", &mstp_clks[MSTP329]), /* CMT10 */ | 548 | CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */ |
520 | CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI2 */ | 549 | CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI2 */ |
521 | CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */ | 550 | CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */ |
522 | CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP323]), /* USB0 */ | 551 | CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP323]), /* USB0 */ |
@@ -531,7 +560,10 @@ static struct clk_lookup lookups[] = { | |||
531 | CLKDEV_DEV_ID("r8a66597_hcd.1", &mstp_clks[MSTP406]), /* USB1 */ | 560 | CLKDEV_DEV_ID("r8a66597_hcd.1", &mstp_clks[MSTP406]), /* USB1 */ |
532 | CLKDEV_DEV_ID("r8a66597_udc.1", &mstp_clks[MSTP406]), /* USB1 */ | 561 | CLKDEV_DEV_ID("r8a66597_udc.1", &mstp_clks[MSTP406]), /* USB1 */ |
533 | CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */ | 562 | CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */ |
534 | {.con_id = "ick", .dev_id = "sh-mobile-hdmi", .clk = &div6_reparent_clks[DIV6_HDMI]}, | 563 | |
564 | CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]), | ||
565 | CLKDEV_ICK_ID("icka", "sh_fsi2", &div6_reparent_clks[DIV6_FSIA]), | ||
566 | CLKDEV_ICK_ID("ickb", "sh_fsi2", &div6_reparent_clks[DIV6_FSIB]), | ||
535 | }; | 567 | }; |
536 | 568 | ||
537 | void __init sh7372_clock_init(void) | 569 | void __init sh7372_clock_init(void) |
@@ -548,7 +580,7 @@ void __init sh7372_clock_init(void) | |||
548 | ret = sh_clk_div6_register(div6_clks, DIV6_NR); | 580 | ret = sh_clk_div6_register(div6_clks, DIV6_NR); |
549 | 581 | ||
550 | if (!ret) | 582 | if (!ret) |
551 | ret = sh_clk_div6_reparent_register(div6_reparent_clks, DIV6_NR); | 583 | ret = sh_clk_div6_reparent_register(div6_reparent_clks, DIV6_REPARENT_NR); |
552 | 584 | ||
553 | if (!ret) | 585 | if (!ret) |
554 | ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); | 586 | ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); |
diff --git a/arch/arm/mach-shmobile/clock-sh7377.c b/arch/arm/mach-shmobile/clock-sh7377.c index e007c28cf0a8..f91395aeb9ab 100644 --- a/arch/arm/mach-shmobile/clock-sh7377.c +++ b/arch/arm/mach-shmobile/clock-sh7377.c | |||
@@ -333,7 +333,7 @@ static struct clk_lookup lookups[] = { | |||
333 | CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */ | 333 | CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */ |
334 | CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */ | 334 | CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */ |
335 | CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */ | 335 | CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */ |
336 | CLKDEV_CON_ID("cmt1", &mstp_clks[MSTP329]), /* CMT10 */ | 336 | CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */ |
337 | CLKDEV_DEV_ID("sh_irda", &mstp_clks[MSTP325]), /* IRDA */ | 337 | CLKDEV_DEV_ID("sh_irda", &mstp_clks[MSTP325]), /* IRDA */ |
338 | CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */ | 338 | CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */ |
339 | CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USBHS */ | 339 | CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USBHS */ |
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h index 33e9700ded7e..147775a94bce 100644 --- a/arch/arm/mach-shmobile/include/mach/sh7372.h +++ b/arch/arm/mach-shmobile/include/mach/sh7372.h | |||
@@ -457,8 +457,12 @@ enum { | |||
457 | SHDMA_SLAVE_SDHI2_TX, | 457 | SHDMA_SLAVE_SDHI2_TX, |
458 | }; | 458 | }; |
459 | 459 | ||
460 | extern struct clk dv_clki_clk; | 460 | extern struct clk sh7372_extal1_clk; |
461 | extern struct clk dv_clki_div2_clk; | 461 | extern struct clk sh7372_extal2_clk; |
462 | extern struct clk pllc2_clk; | 462 | extern struct clk sh7372_dv_clki_clk; |
463 | extern struct clk sh7372_dv_clki_div2_clk; | ||
464 | extern struct clk sh7372_pllc2_clk; | ||
465 | extern struct clk sh7372_fsiack_clk; | ||
466 | extern struct clk sh7372_fsibck_clk; | ||
463 | 467 | ||
464 | #endif /* __ASM_SH7372_H__ */ | 468 | #endif /* __ASM_SH7372_H__ */ |
diff --git a/arch/arm/mach-shmobile/intc-sh7372.c b/arch/arm/mach-shmobile/intc-sh7372.c index e3551b56cd03..4cd3cae38e72 100644 --- a/arch/arm/mach-shmobile/intc-sh7372.c +++ b/arch/arm/mach-shmobile/intc-sh7372.c | |||
@@ -369,9 +369,13 @@ enum { | |||
369 | INTCS, | 369 | INTCS, |
370 | 370 | ||
371 | /* interrupt sources INTCS */ | 371 | /* interrupt sources INTCS */ |
372 | |||
373 | /* IRQ0S - IRQ31S */ | ||
372 | VEU_VEU0, VEU_VEU1, VEU_VEU2, VEU_VEU3, | 374 | VEU_VEU0, VEU_VEU1, VEU_VEU2, VEU_VEU3, |
373 | RTDMAC_1_DEI0, RTDMAC_1_DEI1, RTDMAC_1_DEI2, RTDMAC_1_DEI3, | 375 | RTDMAC_1_DEI0, RTDMAC_1_DEI1, RTDMAC_1_DEI2, RTDMAC_1_DEI3, |
374 | CEU, BEU_BEU0, BEU_BEU1, BEU_BEU2, | 376 | CEU, BEU_BEU0, BEU_BEU1, BEU_BEU2, |
377 | /* MFI */ | ||
378 | /* BBIF2 */ | ||
375 | VPU, | 379 | VPU, |
376 | TSIF1, | 380 | TSIF1, |
377 | _3DG_SGX530, | 381 | _3DG_SGX530, |
@@ -379,13 +383,17 @@ enum { | |||
379 | IIC2_ALI2, IIC2_TACKI2, IIC2_WAITI2, IIC2_DTEI2, | 383 | IIC2_ALI2, IIC2_TACKI2, IIC2_WAITI2, IIC2_DTEI2, |
380 | IPMMU_IPMMUR, IPMMU_IPMMUR2, | 384 | IPMMU_IPMMUR, IPMMU_IPMMUR2, |
381 | RTDMAC_2_DEI4, RTDMAC_2_DEI5, RTDMAC_2_DADERR, | 385 | RTDMAC_2_DEI4, RTDMAC_2_DEI5, RTDMAC_2_DADERR, |
386 | /* KEYSC */ | ||
387 | /* TTI20 */ | ||
382 | MSIOF, | 388 | MSIOF, |
383 | IIC0_ALI0, IIC0_TACKI0, IIC0_WAITI0, IIC0_DTEI0, | 389 | IIC0_ALI0, IIC0_TACKI0, IIC0_WAITI0, IIC0_DTEI0, |
384 | TMU_TUNI0, TMU_TUNI1, TMU_TUNI2, | 390 | TMU_TUNI0, TMU_TUNI1, TMU_TUNI2, |
385 | CMT0, | 391 | CMT0, |
386 | TSIF0, | 392 | TSIF0, |
393 | /* CMT2 */ | ||
387 | LMB, | 394 | LMB, |
388 | CTI, | 395 | CTI, |
396 | /* RWDT0 */ | ||
389 | ICB, | 397 | ICB, |
390 | JPU_JPEG, | 398 | JPU_JPEG, |
391 | LCDC, | 399 | LCDC, |
@@ -397,11 +405,17 @@ enum { | |||
397 | CSIRX, | 405 | CSIRX, |
398 | DSITX_DSITX0, | 406 | DSITX_DSITX0, |
399 | DSITX_DSITX1, | 407 | DSITX_DSITX1, |
408 | /* SPU2 */ | ||
409 | /* FSI */ | ||
410 | /* FMSI */ | ||
411 | /* HDMI */ | ||
400 | TMU1_TUNI0, TMU1_TUNI1, TMU1_TUNI2, | 412 | TMU1_TUNI0, TMU1_TUNI1, TMU1_TUNI2, |
401 | CMT4, | 413 | CMT4, |
402 | DSITX1_DSITX1_0, | 414 | DSITX1_DSITX1_0, |
403 | DSITX1_DSITX1_1, | 415 | DSITX1_DSITX1_1, |
416 | /* MFIS2 */ | ||
404 | CPORTS2R, | 417 | CPORTS2R, |
418 | /* CEC */ | ||
405 | JPU6E, | 419 | JPU6E, |
406 | 420 | ||
407 | /* interrupt groups INTCS */ | 421 | /* interrupt groups INTCS */ |
@@ -410,12 +424,15 @@ enum { | |||
410 | }; | 424 | }; |
411 | 425 | ||
412 | static struct intc_vect intcs_vectors[] = { | 426 | static struct intc_vect intcs_vectors[] = { |
427 | /* IRQ0S - IRQ31S */ | ||
413 | INTCS_VECT(VEU_VEU0, 0x700), INTCS_VECT(VEU_VEU1, 0x720), | 428 | INTCS_VECT(VEU_VEU0, 0x700), INTCS_VECT(VEU_VEU1, 0x720), |
414 | INTCS_VECT(VEU_VEU2, 0x740), INTCS_VECT(VEU_VEU3, 0x760), | 429 | INTCS_VECT(VEU_VEU2, 0x740), INTCS_VECT(VEU_VEU3, 0x760), |
415 | INTCS_VECT(RTDMAC_1_DEI0, 0x800), INTCS_VECT(RTDMAC_1_DEI1, 0x820), | 430 | INTCS_VECT(RTDMAC_1_DEI0, 0x800), INTCS_VECT(RTDMAC_1_DEI1, 0x820), |
416 | INTCS_VECT(RTDMAC_1_DEI2, 0x840), INTCS_VECT(RTDMAC_1_DEI3, 0x860), | 431 | INTCS_VECT(RTDMAC_1_DEI2, 0x840), INTCS_VECT(RTDMAC_1_DEI3, 0x860), |
417 | INTCS_VECT(CEU, 0x880), INTCS_VECT(BEU_BEU0, 0x8a0), | 432 | INTCS_VECT(CEU, 0x880), INTCS_VECT(BEU_BEU0, 0x8a0), |
418 | INTCS_VECT(BEU_BEU1, 0x8c0), INTCS_VECT(BEU_BEU2, 0x8e0), | 433 | INTCS_VECT(BEU_BEU1, 0x8c0), INTCS_VECT(BEU_BEU2, 0x8e0), |
434 | /* MFI */ | ||
435 | /* BBIF2 */ | ||
419 | INTCS_VECT(VPU, 0x980), | 436 | INTCS_VECT(VPU, 0x980), |
420 | INTCS_VECT(TSIF1, 0x9a0), | 437 | INTCS_VECT(TSIF1, 0x9a0), |
421 | INTCS_VECT(_3DG_SGX530, 0x9e0), | 438 | INTCS_VECT(_3DG_SGX530, 0x9e0), |
@@ -425,14 +442,19 @@ static struct intc_vect intcs_vectors[] = { | |||
425 | INTCS_VECT(IPMMU_IPMMUR, 0xb00), INTCS_VECT(IPMMU_IPMMUR2, 0xb20), | 442 | INTCS_VECT(IPMMU_IPMMUR, 0xb00), INTCS_VECT(IPMMU_IPMMUR2, 0xb20), |
426 | INTCS_VECT(RTDMAC_2_DEI4, 0xb80), INTCS_VECT(RTDMAC_2_DEI5, 0xba0), | 443 | INTCS_VECT(RTDMAC_2_DEI4, 0xb80), INTCS_VECT(RTDMAC_2_DEI5, 0xba0), |
427 | INTCS_VECT(RTDMAC_2_DADERR, 0xbc0), | 444 | INTCS_VECT(RTDMAC_2_DADERR, 0xbc0), |
445 | /* KEYSC */ | ||
446 | /* TTI20 */ | ||
447 | INTCS_VECT(MSIOF, 0x0d20), | ||
428 | INTCS_VECT(IIC0_ALI0, 0xe00), INTCS_VECT(IIC0_TACKI0, 0xe20), | 448 | INTCS_VECT(IIC0_ALI0, 0xe00), INTCS_VECT(IIC0_TACKI0, 0xe20), |
429 | INTCS_VECT(IIC0_WAITI0, 0xe40), INTCS_VECT(IIC0_DTEI0, 0xe60), | 449 | INTCS_VECT(IIC0_WAITI0, 0xe40), INTCS_VECT(IIC0_DTEI0, 0xe60), |
430 | INTCS_VECT(TMU_TUNI0, 0xe80), INTCS_VECT(TMU_TUNI1, 0xea0), | 450 | INTCS_VECT(TMU_TUNI0, 0xe80), INTCS_VECT(TMU_TUNI1, 0xea0), |
431 | INTCS_VECT(TMU_TUNI2, 0xec0), | 451 | INTCS_VECT(TMU_TUNI2, 0xec0), |
432 | INTCS_VECT(CMT0, 0xf00), | 452 | INTCS_VECT(CMT0, 0xf00), |
433 | INTCS_VECT(TSIF0, 0xf20), | 453 | INTCS_VECT(TSIF0, 0xf20), |
454 | /* CMT2 */ | ||
434 | INTCS_VECT(LMB, 0xf60), | 455 | INTCS_VECT(LMB, 0xf60), |
435 | INTCS_VECT(CTI, 0x400), | 456 | INTCS_VECT(CTI, 0x400), |
457 | /* RWDT0 */ | ||
436 | INTCS_VECT(ICB, 0x480), | 458 | INTCS_VECT(ICB, 0x480), |
437 | INTCS_VECT(JPU_JPEG, 0x560), | 459 | INTCS_VECT(JPU_JPEG, 0x560), |
438 | INTCS_VECT(LCDC, 0x580), | 460 | INTCS_VECT(LCDC, 0x580), |
@@ -446,12 +468,18 @@ static struct intc_vect intcs_vectors[] = { | |||
446 | INTCS_VECT(CSIRX, 0x17a0), | 468 | INTCS_VECT(CSIRX, 0x17a0), |
447 | INTCS_VECT(DSITX_DSITX0, 0x17c0), | 469 | INTCS_VECT(DSITX_DSITX0, 0x17c0), |
448 | INTCS_VECT(DSITX_DSITX1, 0x17e0), | 470 | INTCS_VECT(DSITX_DSITX1, 0x17e0), |
471 | /* SPU2 */ | ||
472 | /* FSI */ | ||
473 | /* FMSI */ | ||
474 | /* HDMI */ | ||
449 | INTCS_VECT(TMU1_TUNI0, 0x1900), INTCS_VECT(TMU1_TUNI1, 0x1920), | 475 | INTCS_VECT(TMU1_TUNI0, 0x1900), INTCS_VECT(TMU1_TUNI1, 0x1920), |
450 | INTCS_VECT(TMU1_TUNI2, 0x1940), | 476 | INTCS_VECT(TMU1_TUNI2, 0x1940), |
451 | INTCS_VECT(CMT4, 0x1980), | 477 | INTCS_VECT(CMT4, 0x1980), |
452 | INTCS_VECT(DSITX1_DSITX1_0, 0x19a0), | 478 | INTCS_VECT(DSITX1_DSITX1_0, 0x19a0), |
453 | INTCS_VECT(DSITX1_DSITX1_1, 0x19c0), | 479 | INTCS_VECT(DSITX1_DSITX1_1, 0x19c0), |
480 | /* MFIS2 */ | ||
454 | INTCS_VECT(CPORTS2R, 0x1a20), | 481 | INTCS_VECT(CPORTS2R, 0x1a20), |
482 | /* CEC */ | ||
455 | INTCS_VECT(JPU6E, 0x1a80), | 483 | INTCS_VECT(JPU6E, 0x1a80), |
456 | 484 | ||
457 | INTC_VECT(INTCS, 0xf80), | 485 | INTC_VECT(INTCS, 0xf80), |
diff --git a/arch/arm/mach-shmobile/pfc-sh7372.c b/arch/arm/mach-shmobile/pfc-sh7372.c index ec420353f8e3..9c265dae138a 100644 --- a/arch/arm/mach-shmobile/pfc-sh7372.c +++ b/arch/arm/mach-shmobile/pfc-sh7372.c | |||
@@ -166,12 +166,12 @@ enum { | |||
166 | MSIOF2_TSYNC_MARK, MSIOF2_TSCK_MARK, MSIOF2_RXD_MARK, | 166 | MSIOF2_TSYNC_MARK, MSIOF2_TSCK_MARK, MSIOF2_RXD_MARK, |
167 | MSIOF2_TXD_MARK, | 167 | MSIOF2_TXD_MARK, |
168 | 168 | ||
169 | /* MSIOF3 */ | 169 | /* BBIF1 */ |
170 | BBIF1_RXD_MARK, BBIF1_TSYNC_MARK, BBIF1_TSCK_MARK, | 170 | BBIF1_RXD_MARK, BBIF1_TSYNC_MARK, BBIF1_TSCK_MARK, |
171 | BBIF1_TXD_MARK, BBIF1_RSCK_MARK, BBIF1_RSYNC_MARK, | 171 | BBIF1_TXD_MARK, BBIF1_RSCK_MARK, BBIF1_RSYNC_MARK, |
172 | BBIF1_FLOW_MARK, BB_RX_FLOW_N_MARK, | 172 | BBIF1_FLOW_MARK, BB_RX_FLOW_N_MARK, |
173 | 173 | ||
174 | /* MSIOF4 */ | 174 | /* BBIF2 */ |
175 | BBIF2_TSCK1_MARK, BBIF2_TSYNC1_MARK, | 175 | BBIF2_TSCK1_MARK, BBIF2_TSYNC1_MARK, |
176 | BBIF2_TXD1_MARK, BBIF2_RXD_MARK, | 176 | BBIF2_TXD1_MARK, BBIF2_RXD_MARK, |
177 | 177 | ||
@@ -976,12 +976,12 @@ static struct pinmux_gpio pinmux_gpios[] = { | |||
976 | GPIO_FN(MSIOF2_TSYNC), GPIO_FN(MSIOF2_TSCK), GPIO_FN(MSIOF2_RXD), | 976 | GPIO_FN(MSIOF2_TSYNC), GPIO_FN(MSIOF2_TSCK), GPIO_FN(MSIOF2_RXD), |
977 | GPIO_FN(MSIOF2_TXD), | 977 | GPIO_FN(MSIOF2_TXD), |
978 | 978 | ||
979 | /* MSIOF3 */ | 979 | /* BBIF1 */ |
980 | GPIO_FN(BBIF1_RXD), GPIO_FN(BBIF1_TSYNC), GPIO_FN(BBIF1_TSCK), | 980 | GPIO_FN(BBIF1_RXD), GPIO_FN(BBIF1_TSYNC), GPIO_FN(BBIF1_TSCK), |
981 | GPIO_FN(BBIF1_TXD), GPIO_FN(BBIF1_RSCK), GPIO_FN(BBIF1_RSYNC), | 981 | GPIO_FN(BBIF1_TXD), GPIO_FN(BBIF1_RSCK), GPIO_FN(BBIF1_RSYNC), |
982 | GPIO_FN(BBIF1_FLOW), GPIO_FN(BB_RX_FLOW_N), | 982 | GPIO_FN(BBIF1_FLOW), GPIO_FN(BB_RX_FLOW_N), |
983 | 983 | ||
984 | /* MSIOF4 */ | 984 | /* BBIF2 */ |
985 | GPIO_FN(BBIF2_TSCK1), GPIO_FN(BBIF2_TSYNC1), | 985 | GPIO_FN(BBIF2_TSCK1), GPIO_FN(BBIF2_TSYNC1), |
986 | GPIO_FN(BBIF2_TXD1), GPIO_FN(BBIF2_RXD), | 986 | GPIO_FN(BBIF2_TXD1), GPIO_FN(BBIF2_RXD), |
987 | 987 | ||
diff --git a/arch/arm/mach-shmobile/setup-sh7367.c b/arch/arm/mach-shmobile/setup-sh7367.c index 3148c11a550e..003008c18360 100644 --- a/arch/arm/mach-shmobile/setup-sh7367.c +++ b/arch/arm/mach-shmobile/setup-sh7367.c | |||
@@ -154,7 +154,6 @@ static struct sh_timer_config cmt10_platform_data = { | |||
154 | .name = "CMT10", | 154 | .name = "CMT10", |
155 | .channel_offset = 0x10, | 155 | .channel_offset = 0x10, |
156 | .timer_bit = 0, | 156 | .timer_bit = 0, |
157 | .clk = "r_clk", | ||
158 | .clockevent_rating = 125, | 157 | .clockevent_rating = 125, |
159 | .clocksource_rating = 125, | 158 | .clocksource_rating = 125, |
160 | }; | 159 | }; |
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c index e26686c9d0b6..564a6d0be473 100644 --- a/arch/arm/mach-shmobile/setup-sh7372.c +++ b/arch/arm/mach-shmobile/setup-sh7372.c | |||
@@ -158,7 +158,6 @@ static struct sh_timer_config cmt10_platform_data = { | |||
158 | .name = "CMT10", | 158 | .name = "CMT10", |
159 | .channel_offset = 0x10, | 159 | .channel_offset = 0x10, |
160 | .timer_bit = 0, | 160 | .timer_bit = 0, |
161 | .clk = "cmt1", | ||
162 | .clockevent_rating = 125, | 161 | .clockevent_rating = 125, |
163 | .clocksource_rating = 125, | 162 | .clocksource_rating = 125, |
164 | }; | 163 | }; |
@@ -186,6 +185,67 @@ static struct platform_device cmt10_device = { | |||
186 | .num_resources = ARRAY_SIZE(cmt10_resources), | 185 | .num_resources = ARRAY_SIZE(cmt10_resources), |
187 | }; | 186 | }; |
188 | 187 | ||
188 | /* TMU */ | ||
189 | static struct sh_timer_config tmu00_platform_data = { | ||
190 | .name = "TMU00", | ||
191 | .channel_offset = 0x4, | ||
192 | .timer_bit = 0, | ||
193 | .clockevent_rating = 200, | ||
194 | }; | ||
195 | |||
196 | static struct resource tmu00_resources[] = { | ||
197 | [0] = { | ||
198 | .name = "TMU00", | ||
199 | .start = 0xfff60008, | ||
200 | .end = 0xfff60013, | ||
201 | .flags = IORESOURCE_MEM, | ||
202 | }, | ||
203 | [1] = { | ||
204 | .start = intcs_evt2irq(0xe80), /* TMU_TUNI0 */ | ||
205 | .flags = IORESOURCE_IRQ, | ||
206 | }, | ||
207 | }; | ||
208 | |||
209 | static struct platform_device tmu00_device = { | ||
210 | .name = "sh_tmu", | ||
211 | .id = 0, | ||
212 | .dev = { | ||
213 | .platform_data = &tmu00_platform_data, | ||
214 | }, | ||
215 | .resource = tmu00_resources, | ||
216 | .num_resources = ARRAY_SIZE(tmu00_resources), | ||
217 | }; | ||
218 | |||
219 | static struct sh_timer_config tmu01_platform_data = { | ||
220 | .name = "TMU01", | ||
221 | .channel_offset = 0x10, | ||
222 | .timer_bit = 1, | ||
223 | .clocksource_rating = 200, | ||
224 | }; | ||
225 | |||
226 | static struct resource tmu01_resources[] = { | ||
227 | [0] = { | ||
228 | .name = "TMU01", | ||
229 | .start = 0xfff60014, | ||
230 | .end = 0xfff6001f, | ||
231 | .flags = IORESOURCE_MEM, | ||
232 | }, | ||
233 | [1] = { | ||
234 | .start = intcs_evt2irq(0xea0), /* TMU_TUNI1 */ | ||
235 | .flags = IORESOURCE_IRQ, | ||
236 | }, | ||
237 | }; | ||
238 | |||
239 | static struct platform_device tmu01_device = { | ||
240 | .name = "sh_tmu", | ||
241 | .id = 1, | ||
242 | .dev = { | ||
243 | .platform_data = &tmu01_platform_data, | ||
244 | }, | ||
245 | .resource = tmu01_resources, | ||
246 | .num_resources = ARRAY_SIZE(tmu01_resources), | ||
247 | }; | ||
248 | |||
189 | /* I2C */ | 249 | /* I2C */ |
190 | static struct resource iic0_resources[] = { | 250 | static struct resource iic0_resources[] = { |
191 | [0] = { | 251 | [0] = { |
@@ -419,14 +479,14 @@ static struct resource sh7372_dmae0_resources[] = { | |||
419 | }, | 479 | }, |
420 | { | 480 | { |
421 | /* DMA error IRQ */ | 481 | /* DMA error IRQ */ |
422 | .start = 246, | 482 | .start = evt2irq(0x20c0), |
423 | .end = 246, | 483 | .end = evt2irq(0x20c0), |
424 | .flags = IORESOURCE_IRQ, | 484 | .flags = IORESOURCE_IRQ, |
425 | }, | 485 | }, |
426 | { | 486 | { |
427 | /* IRQ for channels 0-5 */ | 487 | /* IRQ for channels 0-5 */ |
428 | .start = 240, | 488 | .start = evt2irq(0x2000), |
429 | .end = 245, | 489 | .end = evt2irq(0x20a0), |
430 | .flags = IORESOURCE_IRQ, | 490 | .flags = IORESOURCE_IRQ, |
431 | }, | 491 | }, |
432 | }; | 492 | }; |
@@ -447,14 +507,14 @@ static struct resource sh7372_dmae1_resources[] = { | |||
447 | }, | 507 | }, |
448 | { | 508 | { |
449 | /* DMA error IRQ */ | 509 | /* DMA error IRQ */ |
450 | .start = 254, | 510 | .start = evt2irq(0x21c0), |
451 | .end = 254, | 511 | .end = evt2irq(0x21c0), |
452 | .flags = IORESOURCE_IRQ, | 512 | .flags = IORESOURCE_IRQ, |
453 | }, | 513 | }, |
454 | { | 514 | { |
455 | /* IRQ for channels 0-5 */ | 515 | /* IRQ for channels 0-5 */ |
456 | .start = 248, | 516 | .start = evt2irq(0x2100), |
457 | .end = 253, | 517 | .end = evt2irq(0x21a0), |
458 | .flags = IORESOURCE_IRQ, | 518 | .flags = IORESOURCE_IRQ, |
459 | }, | 519 | }, |
460 | }; | 520 | }; |
@@ -475,14 +535,14 @@ static struct resource sh7372_dmae2_resources[] = { | |||
475 | }, | 535 | }, |
476 | { | 536 | { |
477 | /* DMA error IRQ */ | 537 | /* DMA error IRQ */ |
478 | .start = 262, | 538 | .start = evt2irq(0x22c0), |
479 | .end = 262, | 539 | .end = evt2irq(0x22c0), |
480 | .flags = IORESOURCE_IRQ, | 540 | .flags = IORESOURCE_IRQ, |
481 | }, | 541 | }, |
482 | { | 542 | { |
483 | /* IRQ for channels 0-5 */ | 543 | /* IRQ for channels 0-5 */ |
484 | .start = 256, | 544 | .start = evt2irq(0x2200), |
485 | .end = 261, | 545 | .end = evt2irq(0x22a0), |
486 | .flags = IORESOURCE_IRQ, | 546 | .flags = IORESOURCE_IRQ, |
487 | }, | 547 | }, |
488 | }; | 548 | }; |
@@ -526,6 +586,11 @@ static struct platform_device *sh7372_early_devices[] __initdata = { | |||
526 | &scif5_device, | 586 | &scif5_device, |
527 | &scif6_device, | 587 | &scif6_device, |
528 | &cmt10_device, | 588 | &cmt10_device, |
589 | &tmu00_device, | ||
590 | &tmu01_device, | ||
591 | }; | ||
592 | |||
593 | static struct platform_device *sh7372_late_devices[] __initdata = { | ||
529 | &iic0_device, | 594 | &iic0_device, |
530 | &iic1_device, | 595 | &iic1_device, |
531 | &dma0_device, | 596 | &dma0_device, |
@@ -537,6 +602,9 @@ void __init sh7372_add_standard_devices(void) | |||
537 | { | 602 | { |
538 | platform_add_devices(sh7372_early_devices, | 603 | platform_add_devices(sh7372_early_devices, |
539 | ARRAY_SIZE(sh7372_early_devices)); | 604 | ARRAY_SIZE(sh7372_early_devices)); |
605 | |||
606 | platform_add_devices(sh7372_late_devices, | ||
607 | ARRAY_SIZE(sh7372_late_devices)); | ||
540 | } | 608 | } |
541 | 609 | ||
542 | void __init sh7372_add_early_devices(void) | 610 | void __init sh7372_add_early_devices(void) |
diff --git a/arch/arm/mach-shmobile/setup-sh7377.c b/arch/arm/mach-shmobile/setup-sh7377.c index bb4adf17dbf4..575dbd6c2f1d 100644 --- a/arch/arm/mach-shmobile/setup-sh7377.c +++ b/arch/arm/mach-shmobile/setup-sh7377.c | |||
@@ -172,7 +172,6 @@ static struct sh_timer_config cmt10_platform_data = { | |||
172 | .name = "CMT10", | 172 | .name = "CMT10", |
173 | .channel_offset = 0x10, | 173 | .channel_offset = 0x10, |
174 | .timer_bit = 0, | 174 | .timer_bit = 0, |
175 | .clk = "r_clk", | ||
176 | .clockevent_rating = 125, | 175 | .clockevent_rating = 125, |
177 | .clocksource_rating = 125, | 176 | .clocksource_rating = 125, |
178 | }; | 177 | }; |
diff --git a/arch/arm/mach-u300/clock.c b/arch/arm/mach-u300/clock.c index 60acf9e708ae..7458fc6df5c6 100644 --- a/arch/arm/mach-u300/clock.c +++ b/arch/arm/mach-u300/clock.c | |||
@@ -66,7 +66,7 @@ static DEFINE_SPINLOCK(syscon_resetreg_lock); | |||
66 | * AMBA bus | 66 | * AMBA bus |
67 | * | | 67 | * | |
68 | * +- CPU | 68 | * +- CPU |
69 | * +- NANDIF NAND Flash interface | 69 | * +- FSMC NANDIF NAND Flash interface |
70 | * +- SEMI Shared Memory interface | 70 | * +- SEMI Shared Memory interface |
71 | * +- ISP Image Signal Processor (U335 only) | 71 | * +- ISP Image Signal Processor (U335 only) |
72 | * +- CDS (U335 only) | 72 | * +- CDS (U335 only) |
@@ -726,7 +726,7 @@ static struct clk cpu_clk = { | |||
726 | }; | 726 | }; |
727 | 727 | ||
728 | static struct clk nandif_clk = { | 728 | static struct clk nandif_clk = { |
729 | .name = "NANDIF", | 729 | .name = "FSMC", |
730 | .parent = &amba_clk, | 730 | .parent = &amba_clk, |
731 | .hw_ctrld = false, | 731 | .hw_ctrld = false, |
732 | .reset = true, | 732 | .reset = true, |
@@ -1259,7 +1259,7 @@ static struct clk_lookup lookups[] = { | |||
1259 | /* Connected directly to the AMBA bus */ | 1259 | /* Connected directly to the AMBA bus */ |
1260 | DEF_LOOKUP("amba", &amba_clk), | 1260 | DEF_LOOKUP("amba", &amba_clk), |
1261 | DEF_LOOKUP("cpu", &cpu_clk), | 1261 | DEF_LOOKUP("cpu", &cpu_clk), |
1262 | DEF_LOOKUP("fsmc", &nandif_clk), | 1262 | DEF_LOOKUP("fsmc-nand", &nandif_clk), |
1263 | DEF_LOOKUP("semi", &semi_clk), | 1263 | DEF_LOOKUP("semi", &semi_clk), |
1264 | #ifdef CONFIG_MACH_U300_BS335 | 1264 | #ifdef CONFIG_MACH_U300_BS335 |
1265 | DEF_LOOKUP("isp", &isp_clk), | 1265 | DEF_LOOKUP("isp", &isp_clk), |
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index ea41c236be0f..aa53ee22438f 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c | |||
@@ -21,7 +21,8 @@ | |||
21 | #include <linux/gpio.h> | 21 | #include <linux/gpio.h> |
22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
23 | #include <linux/err.h> | 23 | #include <linux/err.h> |
24 | #include <mach/coh901318.h> | 24 | #include <linux/mtd/nand.h> |
25 | #include <linux/mtd/fsmc.h> | ||
25 | 26 | ||
26 | #include <asm/types.h> | 27 | #include <asm/types.h> |
27 | #include <asm/setup.h> | 28 | #include <asm/setup.h> |
@@ -30,6 +31,7 @@ | |||
30 | #include <asm/mach/map.h> | 31 | #include <asm/mach/map.h> |
31 | #include <asm/mach/irq.h> | 32 | #include <asm/mach/irq.h> |
32 | 33 | ||
34 | #include <mach/coh901318.h> | ||
33 | #include <mach/hardware.h> | 35 | #include <mach/hardware.h> |
34 | #include <mach/syscon.h> | 36 | #include <mach/syscon.h> |
35 | #include <mach/dma_channels.h> | 37 | #include <mach/dma_channels.h> |
@@ -285,6 +287,13 @@ static struct resource rtc_resources[] = { | |||
285 | */ | 287 | */ |
286 | static struct resource fsmc_resources[] = { | 288 | static struct resource fsmc_resources[] = { |
287 | { | 289 | { |
290 | .name = "nand_data", | ||
291 | .start = U300_NAND_CS0_PHYS_BASE, | ||
292 | .end = U300_NAND_CS0_PHYS_BASE + SZ_16K - 1, | ||
293 | .flags = IORESOURCE_MEM, | ||
294 | }, | ||
295 | { | ||
296 | .name = "fsmc_regs", | ||
288 | .start = U300_NAND_IF_PHYS_BASE, | 297 | .start = U300_NAND_IF_PHYS_BASE, |
289 | .end = U300_NAND_IF_PHYS_BASE + SZ_4K - 1, | 298 | .end = U300_NAND_IF_PHYS_BASE + SZ_4K - 1, |
290 | .flags = IORESOURCE_MEM, | 299 | .flags = IORESOURCE_MEM, |
@@ -1429,11 +1438,39 @@ static struct platform_device rtc_device = { | |||
1429 | .resource = rtc_resources, | 1438 | .resource = rtc_resources, |
1430 | }; | 1439 | }; |
1431 | 1440 | ||
1432 | static struct platform_device fsmc_device = { | 1441 | static struct mtd_partition u300_partitions[] = { |
1433 | .name = "nandif", | 1442 | { |
1443 | .name = "bootrecords", | ||
1444 | .offset = 0, | ||
1445 | .size = SZ_128K, | ||
1446 | }, | ||
1447 | { | ||
1448 | .name = "free", | ||
1449 | .offset = SZ_128K, | ||
1450 | .size = 8064 * SZ_1K, | ||
1451 | }, | ||
1452 | { | ||
1453 | .name = "platform", | ||
1454 | .offset = 8192 * SZ_1K, | ||
1455 | .size = 253952 * SZ_1K, | ||
1456 | }, | ||
1457 | }; | ||
1458 | |||
1459 | static struct fsmc_nand_platform_data nand_platform_data = { | ||
1460 | .partitions = u300_partitions, | ||
1461 | .nr_partitions = ARRAY_SIZE(u300_partitions), | ||
1462 | .options = NAND_SKIP_BBTSCAN, | ||
1463 | .width = FSMC_NAND_BW8, | ||
1464 | }; | ||
1465 | |||
1466 | static struct platform_device nand_device = { | ||
1467 | .name = "fsmc-nand", | ||
1434 | .id = -1, | 1468 | .id = -1, |
1435 | .num_resources = ARRAY_SIZE(fsmc_resources), | ||
1436 | .resource = fsmc_resources, | 1469 | .resource = fsmc_resources, |
1470 | .num_resources = ARRAY_SIZE(fsmc_resources), | ||
1471 | .dev = { | ||
1472 | .platform_data = &nand_platform_data, | ||
1473 | }, | ||
1437 | }; | 1474 | }; |
1438 | 1475 | ||
1439 | static struct platform_device ave_device = { | 1476 | static struct platform_device ave_device = { |
@@ -1465,7 +1502,7 @@ static struct platform_device *platform_devs[] __initdata = { | |||
1465 | &keypad_device, | 1502 | &keypad_device, |
1466 | &rtc_device, | 1503 | &rtc_device, |
1467 | &gpio_device, | 1504 | &gpio_device, |
1468 | &fsmc_device, | 1505 | &nand_device, |
1469 | &wdog_device, | 1506 | &wdog_device, |
1470 | &ave_device | 1507 | &ave_device |
1471 | }; | 1508 | }; |
diff --git a/arch/arm/mach-u300/include/mach/u300-regs.h b/arch/arm/mach-u300/include/mach/u300-regs.h index 56721a0cd2af..8b85df4c8d8f 100644 --- a/arch/arm/mach-u300/include/mach/u300-regs.h +++ b/arch/arm/mach-u300/include/mach/u300-regs.h | |||
@@ -20,11 +20,9 @@ | |||
20 | 20 | ||
21 | /* NAND Flash CS0 */ | 21 | /* NAND Flash CS0 */ |
22 | #define U300_NAND_CS0_PHYS_BASE 0x80000000 | 22 | #define U300_NAND_CS0_PHYS_BASE 0x80000000 |
23 | #define U300_NAND_CS0_VIRT_BASE 0xff040000 | ||
24 | 23 | ||
25 | /* NFIF */ | 24 | /* NFIF */ |
26 | #define U300_NAND_IF_PHYS_BASE 0x9f800000 | 25 | #define U300_NAND_IF_PHYS_BASE 0x9f800000 |
27 | #define U300_NAND_IF_VIRT_BASE 0xff030000 | ||
28 | 26 | ||
29 | /* AHB Peripherals */ | 27 | /* AHB Peripherals */ |
30 | #define U300_AHB_PER_PHYS_BASE 0xa0000000 | 28 | #define U300_AHB_PER_PHYS_BASE 0xa0000000 |
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index e0fd747e447a..73fb1a551ec6 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/io.h> | 10 | #include <linux/io.h> |
11 | #include <linux/clk.h> | 11 | #include <linux/clk.h> |
12 | 12 | ||
13 | #include <asm/cacheflush.h> | ||
13 | #include <asm/hardware/cache-l2x0.h> | 14 | #include <asm/hardware/cache-l2x0.h> |
14 | #include <asm/hardware/gic.h> | 15 | #include <asm/hardware/gic.h> |
15 | #include <asm/mach/map.h> | 16 | #include <asm/mach/map.h> |
@@ -71,6 +72,46 @@ void __init ux500_init_irq(void) | |||
71 | } | 72 | } |
72 | 73 | ||
73 | #ifdef CONFIG_CACHE_L2X0 | 74 | #ifdef CONFIG_CACHE_L2X0 |
75 | static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask) | ||
76 | { | ||
77 | /* wait for the operation to complete */ | ||
78 | while (readl(reg) & mask) | ||
79 | ; | ||
80 | } | ||
81 | |||
82 | static inline void ux500_cache_sync(void) | ||
83 | { | ||
84 | void __iomem *base = __io_address(UX500_L2CC_BASE); | ||
85 | writel(0, base + L2X0_CACHE_SYNC); | ||
86 | ux500_cache_wait(base + L2X0_CACHE_SYNC, 1); | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * The L2 cache cannot be turned off in the non-secure world. | ||
91 | * Dummy until a secure service is in place. | ||
92 | */ | ||
93 | static void ux500_l2x0_disable(void) | ||
94 | { | ||
95 | } | ||
96 | |||
97 | /* | ||
98 | * This is only called when doing a kexec, just after turning off the L2 | ||
99 | * and L1 cache, and it is surrounded by a spinlock in the generic version. | ||
100 | * However, we're not really turning off the L2 cache right now and the | ||
101 | * PL310 does not support exclusive accesses (used to implement the spinlock). | ||
102 | * So, the invalidation needs to be done without the spinlock. | ||
103 | */ | ||
104 | static void ux500_l2x0_inv_all(void) | ||
105 | { | ||
106 | void __iomem *l2x0_base = __io_address(UX500_L2CC_BASE); | ||
107 | uint32_t l2x0_way_mask = (1<<16) - 1; /* Bitmask of active ways */ | ||
108 | |||
109 | /* invalidate all ways */ | ||
110 | writel(l2x0_way_mask, l2x0_base + L2X0_INV_WAY); | ||
111 | ux500_cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask); | ||
112 | ux500_cache_sync(); | ||
113 | } | ||
114 | |||
74 | static int ux500_l2x0_init(void) | 115 | static int ux500_l2x0_init(void) |
75 | { | 116 | { |
76 | void __iomem *l2x0_base; | 117 | void __iomem *l2x0_base; |
@@ -80,6 +121,10 @@ static int ux500_l2x0_init(void) | |||
80 | /* 64KB way size, 8 way associativity, force WA */ | 121 | /* 64KB way size, 8 way associativity, force WA */ |
81 | l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff); | 122 | l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff); |
82 | 123 | ||
124 | /* Override invalidate function */ | ||
125 | outer_cache.disable = ux500_l2x0_disable; | ||
126 | outer_cache.inv_all = ux500_l2x0_inv_all; | ||
127 | |||
83 | return 0; | 128 | return 0; |
84 | } | 129 | } |
85 | early_initcall(ux500_l2x0_init); | 130 | early_initcall(ux500_l2x0_init); |
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index a0a2928ae4dd..4414a01e1e8a 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
@@ -779,6 +779,14 @@ config CACHE_L2X0 | |||
779 | help | 779 | help |
780 | This option enables the L2x0 PrimeCell. | 780 | This option enables the L2x0 PrimeCell. |
781 | 781 | ||
782 | config CACHE_PL310 | ||
783 | bool | ||
784 | depends on CACHE_L2X0 | ||
785 | default y if CPU_V7 && !CPU_V6 | ||
786 | help | ||
787 | This option enables optimisations for the PL310 cache | ||
788 | controller. | ||
789 | |||
782 | config CACHE_TAUROS2 | 790 | config CACHE_TAUROS2 |
783 | bool "Enable the Tauros2 L2 cache controller" | 791 | bool "Enable the Tauros2 L2 cache controller" |
784 | depends on (ARCH_DOVE || ARCH_MMP) | 792 | depends on (ARCH_DOVE || ARCH_MMP) |
diff --git a/arch/arm/mm/cache-fa.S b/arch/arm/mm/cache-fa.S index 7148e53e6078..1fa6f71470de 100644 --- a/arch/arm/mm/cache-fa.S +++ b/arch/arm/mm/cache-fa.S | |||
@@ -38,6 +38,17 @@ | |||
38 | #define CACHE_DLIMIT (CACHE_DSIZE * 2) | 38 | #define CACHE_DLIMIT (CACHE_DSIZE * 2) |
39 | 39 | ||
40 | /* | 40 | /* |
41 | * flush_icache_all() | ||
42 | * | ||
43 | * Unconditionally clean and invalidate the entire icache. | ||
44 | */ | ||
45 | ENTRY(fa_flush_icache_all) | ||
46 | mov r0, #0 | ||
47 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache | ||
48 | mov pc, lr | ||
49 | ENDPROC(fa_flush_icache_all) | ||
50 | |||
51 | /* | ||
41 | * flush_user_cache_all() | 52 | * flush_user_cache_all() |
42 | * | 53 | * |
43 | * Clean and invalidate all cache entries in a particular address | 54 | * Clean and invalidate all cache entries in a particular address |
@@ -233,6 +244,7 @@ ENDPROC(fa_dma_unmap_area) | |||
233 | 244 | ||
234 | .type fa_cache_fns, #object | 245 | .type fa_cache_fns, #object |
235 | ENTRY(fa_cache_fns) | 246 | ENTRY(fa_cache_fns) |
247 | .long fa_flush_icache_all | ||
236 | .long fa_flush_kern_cache_all | 248 | .long fa_flush_kern_cache_all |
237 | .long fa_flush_user_cache_all | 249 | .long fa_flush_user_cache_all |
238 | .long fa_flush_user_cache_range | 250 | .long fa_flush_user_cache_range |
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 9982eb385c0f..170c9bb95866 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c | |||
@@ -28,14 +28,24 @@ | |||
28 | static void __iomem *l2x0_base; | 28 | static void __iomem *l2x0_base; |
29 | static DEFINE_SPINLOCK(l2x0_lock); | 29 | static DEFINE_SPINLOCK(l2x0_lock); |
30 | static uint32_t l2x0_way_mask; /* Bitmask of active ways */ | 30 | static uint32_t l2x0_way_mask; /* Bitmask of active ways */ |
31 | static uint32_t l2x0_size; | ||
31 | 32 | ||
32 | static inline void cache_wait(void __iomem *reg, unsigned long mask) | 33 | static inline void cache_wait_way(void __iomem *reg, unsigned long mask) |
33 | { | 34 | { |
34 | /* wait for the operation to complete */ | 35 | /* wait for cache operation by line or way to complete */ |
35 | while (readl_relaxed(reg) & mask) | 36 | while (readl_relaxed(reg) & mask) |
36 | ; | 37 | ; |
37 | } | 38 | } |
38 | 39 | ||
40 | #ifdef CONFIG_CACHE_PL310 | ||
41 | static inline void cache_wait(void __iomem *reg, unsigned long mask) | ||
42 | { | ||
43 | /* cache operations by line are atomic on PL310 */ | ||
44 | } | ||
45 | #else | ||
46 | #define cache_wait cache_wait_way | ||
47 | #endif | ||
48 | |||
39 | static inline void cache_sync(void) | 49 | static inline void cache_sync(void) |
40 | { | 50 | { |
41 | void __iomem *base = l2x0_base; | 51 | void __iomem *base = l2x0_base; |
@@ -103,14 +113,40 @@ static void l2x0_cache_sync(void) | |||
103 | spin_unlock_irqrestore(&l2x0_lock, flags); | 113 | spin_unlock_irqrestore(&l2x0_lock, flags); |
104 | } | 114 | } |
105 | 115 | ||
106 | static inline void l2x0_inv_all(void) | 116 | static void l2x0_flush_all(void) |
117 | { | ||
118 | unsigned long flags; | ||
119 | |||
120 | /* clean all ways */ | ||
121 | spin_lock_irqsave(&l2x0_lock, flags); | ||
122 | writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_INV_WAY); | ||
123 | cache_wait_way(l2x0_base + L2X0_CLEAN_INV_WAY, l2x0_way_mask); | ||
124 | cache_sync(); | ||
125 | spin_unlock_irqrestore(&l2x0_lock, flags); | ||
126 | } | ||
127 | |||
128 | static void l2x0_clean_all(void) | ||
129 | { | ||
130 | unsigned long flags; | ||
131 | |||
132 | /* clean all ways */ | ||
133 | spin_lock_irqsave(&l2x0_lock, flags); | ||
134 | writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_WAY); | ||
135 | cache_wait_way(l2x0_base + L2X0_CLEAN_WAY, l2x0_way_mask); | ||
136 | cache_sync(); | ||
137 | spin_unlock_irqrestore(&l2x0_lock, flags); | ||
138 | } | ||
139 | |||
140 | static void l2x0_inv_all(void) | ||
107 | { | 141 | { |
108 | unsigned long flags; | 142 | unsigned long flags; |
109 | 143 | ||
110 | /* invalidate all ways */ | 144 | /* invalidate all ways */ |
111 | spin_lock_irqsave(&l2x0_lock, flags); | 145 | spin_lock_irqsave(&l2x0_lock, flags); |
146 | /* Invalidating when L2 is enabled is a nono */ | ||
147 | BUG_ON(readl(l2x0_base + L2X0_CTRL) & 1); | ||
112 | writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY); | 148 | writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY); |
113 | cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask); | 149 | cache_wait_way(l2x0_base + L2X0_INV_WAY, l2x0_way_mask); |
114 | cache_sync(); | 150 | cache_sync(); |
115 | spin_unlock_irqrestore(&l2x0_lock, flags); | 151 | spin_unlock_irqrestore(&l2x0_lock, flags); |
116 | } | 152 | } |
@@ -159,6 +195,11 @@ static void l2x0_clean_range(unsigned long start, unsigned long end) | |||
159 | void __iomem *base = l2x0_base; | 195 | void __iomem *base = l2x0_base; |
160 | unsigned long flags; | 196 | unsigned long flags; |
161 | 197 | ||
198 | if ((end - start) >= l2x0_size) { | ||
199 | l2x0_clean_all(); | ||
200 | return; | ||
201 | } | ||
202 | |||
162 | spin_lock_irqsave(&l2x0_lock, flags); | 203 | spin_lock_irqsave(&l2x0_lock, flags); |
163 | start &= ~(CACHE_LINE_SIZE - 1); | 204 | start &= ~(CACHE_LINE_SIZE - 1); |
164 | while (start < end) { | 205 | while (start < end) { |
@@ -184,6 +225,11 @@ static void l2x0_flush_range(unsigned long start, unsigned long end) | |||
184 | void __iomem *base = l2x0_base; | 225 | void __iomem *base = l2x0_base; |
185 | unsigned long flags; | 226 | unsigned long flags; |
186 | 227 | ||
228 | if ((end - start) >= l2x0_size) { | ||
229 | l2x0_flush_all(); | ||
230 | return; | ||
231 | } | ||
232 | |||
187 | spin_lock_irqsave(&l2x0_lock, flags); | 233 | spin_lock_irqsave(&l2x0_lock, flags); |
188 | start &= ~(CACHE_LINE_SIZE - 1); | 234 | start &= ~(CACHE_LINE_SIZE - 1); |
189 | while (start < end) { | 235 | while (start < end) { |
@@ -206,10 +252,20 @@ static void l2x0_flush_range(unsigned long start, unsigned long end) | |||
206 | spin_unlock_irqrestore(&l2x0_lock, flags); | 252 | spin_unlock_irqrestore(&l2x0_lock, flags); |
207 | } | 253 | } |
208 | 254 | ||
255 | static void l2x0_disable(void) | ||
256 | { | ||
257 | unsigned long flags; | ||
258 | |||
259 | spin_lock_irqsave(&l2x0_lock, flags); | ||
260 | writel(0, l2x0_base + L2X0_CTRL); | ||
261 | spin_unlock_irqrestore(&l2x0_lock, flags); | ||
262 | } | ||
263 | |||
209 | void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) | 264 | void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) |
210 | { | 265 | { |
211 | __u32 aux; | 266 | __u32 aux; |
212 | __u32 cache_id; | 267 | __u32 cache_id; |
268 | __u32 way_size = 0; | ||
213 | int ways; | 269 | int ways; |
214 | const char *type; | 270 | const char *type; |
215 | 271 | ||
@@ -244,6 +300,13 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) | |||
244 | l2x0_way_mask = (1 << ways) - 1; | 300 | l2x0_way_mask = (1 << ways) - 1; |
245 | 301 | ||
246 | /* | 302 | /* |
303 | * L2 cache Size = Way size * Number of ways | ||
304 | */ | ||
305 | way_size = (aux & L2X0_AUX_CTRL_WAY_SIZE_MASK) >> 17; | ||
306 | way_size = 1 << (way_size + 3); | ||
307 | l2x0_size = ways * way_size * SZ_1K; | ||
308 | |||
309 | /* | ||
247 | * Check if l2x0 controller is already enabled. | 310 | * Check if l2x0 controller is already enabled. |
248 | * If you are booting from non-secure mode | 311 | * If you are booting from non-secure mode |
249 | * accessing the below registers will fault. | 312 | * accessing the below registers will fault. |
@@ -263,8 +326,11 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) | |||
263 | outer_cache.clean_range = l2x0_clean_range; | 326 | outer_cache.clean_range = l2x0_clean_range; |
264 | outer_cache.flush_range = l2x0_flush_range; | 327 | outer_cache.flush_range = l2x0_flush_range; |
265 | outer_cache.sync = l2x0_cache_sync; | 328 | outer_cache.sync = l2x0_cache_sync; |
329 | outer_cache.flush_all = l2x0_flush_all; | ||
330 | outer_cache.inv_all = l2x0_inv_all; | ||
331 | outer_cache.disable = l2x0_disable; | ||
266 | 332 | ||
267 | printk(KERN_INFO "%s cache controller enabled\n", type); | 333 | printk(KERN_INFO "%s cache controller enabled\n", type); |
268 | printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x\n", | 334 | printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n", |
269 | ways, cache_id, aux); | 335 | ways, cache_id, aux, l2x0_size); |
270 | } | 336 | } |
diff --git a/arch/arm/mm/cache-v3.S b/arch/arm/mm/cache-v3.S index c2ff3c599fee..2e2bc406a18d 100644 --- a/arch/arm/mm/cache-v3.S +++ b/arch/arm/mm/cache-v3.S | |||
@@ -13,6 +13,15 @@ | |||
13 | #include "proc-macros.S" | 13 | #include "proc-macros.S" |
14 | 14 | ||
15 | /* | 15 | /* |
16 | * flush_icache_all() | ||
17 | * | ||
18 | * Unconditionally clean and invalidate the entire icache. | ||
19 | */ | ||
20 | ENTRY(v3_flush_icache_all) | ||
21 | mov pc, lr | ||
22 | ENDPROC(v3_flush_icache_all) | ||
23 | |||
24 | /* | ||
16 | * flush_user_cache_all() | 25 | * flush_user_cache_all() |
17 | * | 26 | * |
18 | * Invalidate all cache entries in a particular address | 27 | * Invalidate all cache entries in a particular address |
@@ -122,6 +131,7 @@ ENDPROC(v3_dma_map_area) | |||
122 | 131 | ||
123 | .type v3_cache_fns, #object | 132 | .type v3_cache_fns, #object |
124 | ENTRY(v3_cache_fns) | 133 | ENTRY(v3_cache_fns) |
134 | .long v3_flush_icache_all | ||
125 | .long v3_flush_kern_cache_all | 135 | .long v3_flush_kern_cache_all |
126 | .long v3_flush_user_cache_all | 136 | .long v3_flush_user_cache_all |
127 | .long v3_flush_user_cache_range | 137 | .long v3_flush_user_cache_range |
diff --git a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S index 4810f7e3e813..a8fefb523f19 100644 --- a/arch/arm/mm/cache-v4.S +++ b/arch/arm/mm/cache-v4.S | |||
@@ -13,6 +13,15 @@ | |||
13 | #include "proc-macros.S" | 13 | #include "proc-macros.S" |
14 | 14 | ||
15 | /* | 15 | /* |
16 | * flush_icache_all() | ||
17 | * | ||
18 | * Unconditionally clean and invalidate the entire icache. | ||
19 | */ | ||
20 | ENTRY(v4_flush_icache_all) | ||
21 | mov pc, lr | ||
22 | ENDPROC(v4_flush_icache_all) | ||
23 | |||
24 | /* | ||
16 | * flush_user_cache_all() | 25 | * flush_user_cache_all() |
17 | * | 26 | * |
18 | * Invalidate all cache entries in a particular address | 27 | * Invalidate all cache entries in a particular address |
@@ -134,6 +143,7 @@ ENDPROC(v4_dma_map_area) | |||
134 | 143 | ||
135 | .type v4_cache_fns, #object | 144 | .type v4_cache_fns, #object |
136 | ENTRY(v4_cache_fns) | 145 | ENTRY(v4_cache_fns) |
146 | .long v4_flush_icache_all | ||
137 | .long v4_flush_kern_cache_all | 147 | .long v4_flush_kern_cache_all |
138 | .long v4_flush_user_cache_all | 148 | .long v4_flush_user_cache_all |
139 | .long v4_flush_user_cache_range | 149 | .long v4_flush_user_cache_range |
diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S index df8368afa102..d3644db467b7 100644 --- a/arch/arm/mm/cache-v4wb.S +++ b/arch/arm/mm/cache-v4wb.S | |||
@@ -51,6 +51,17 @@ flush_base: | |||
51 | .text | 51 | .text |
52 | 52 | ||
53 | /* | 53 | /* |
54 | * flush_icache_all() | ||
55 | * | ||
56 | * Unconditionally clean and invalidate the entire icache. | ||
57 | */ | ||
58 | ENTRY(v4wb_flush_icache_all) | ||
59 | mov r0, #0 | ||
60 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache | ||
61 | mov pc, lr | ||
62 | ENDPROC(v4wb_flush_icache_all) | ||
63 | |||
64 | /* | ||
54 | * flush_user_cache_all() | 65 | * flush_user_cache_all() |
55 | * | 66 | * |
56 | * Clean and invalidate all cache entries in a particular address | 67 | * Clean and invalidate all cache entries in a particular address |
@@ -244,6 +255,7 @@ ENDPROC(v4wb_dma_unmap_area) | |||
244 | 255 | ||
245 | .type v4wb_cache_fns, #object | 256 | .type v4wb_cache_fns, #object |
246 | ENTRY(v4wb_cache_fns) | 257 | ENTRY(v4wb_cache_fns) |
258 | .long v4wb_flush_icache_all | ||
247 | .long v4wb_flush_kern_cache_all | 259 | .long v4wb_flush_kern_cache_all |
248 | .long v4wb_flush_user_cache_all | 260 | .long v4wb_flush_user_cache_all |
249 | .long v4wb_flush_user_cache_range | 261 | .long v4wb_flush_user_cache_range |
diff --git a/arch/arm/mm/cache-v4wt.S b/arch/arm/mm/cache-v4wt.S index 45c70312f43b..49c2b66cf3dd 100644 --- a/arch/arm/mm/cache-v4wt.S +++ b/arch/arm/mm/cache-v4wt.S | |||
@@ -41,6 +41,17 @@ | |||
41 | #define CACHE_DLIMIT 16384 | 41 | #define CACHE_DLIMIT 16384 |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * flush_icache_all() | ||
45 | * | ||
46 | * Unconditionally clean and invalidate the entire icache. | ||
47 | */ | ||
48 | ENTRY(v4wt_flush_icache_all) | ||
49 | mov r0, #0 | ||
50 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache | ||
51 | mov pc, lr | ||
52 | ENDPROC(v4wt_flush_icache_all) | ||
53 | |||
54 | /* | ||
44 | * flush_user_cache_all() | 55 | * flush_user_cache_all() |
45 | * | 56 | * |
46 | * Invalidate all cache entries in a particular address | 57 | * Invalidate all cache entries in a particular address |
@@ -188,6 +199,7 @@ ENDPROC(v4wt_dma_map_area) | |||
188 | 199 | ||
189 | .type v4wt_cache_fns, #object | 200 | .type v4wt_cache_fns, #object |
190 | ENTRY(v4wt_cache_fns) | 201 | ENTRY(v4wt_cache_fns) |
202 | .long v4wt_flush_icache_all | ||
191 | .long v4wt_flush_kern_cache_all | 203 | .long v4wt_flush_kern_cache_all |
192 | .long v4wt_flush_user_cache_all | 204 | .long v4wt_flush_user_cache_all |
193 | .long v4wt_flush_user_cache_range | 205 | .long v4wt_flush_user_cache_range |
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index c493d7244d3d..83e59f870426 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c | |||
@@ -66,6 +66,30 @@ static int do_adjust_pte(struct vm_area_struct *vma, unsigned long address, | |||
66 | return ret; | 66 | return ret; |
67 | } | 67 | } |
68 | 68 | ||
69 | #if USE_SPLIT_PTLOCKS | ||
70 | /* | ||
71 | * If we are using split PTE locks, then we need to take the page | ||
72 | * lock here. Otherwise we are using shared mm->page_table_lock | ||
73 | * which is already locked, thus cannot take it. | ||
74 | */ | ||
75 | static inline void do_pte_lock(spinlock_t *ptl) | ||
76 | { | ||
77 | /* | ||
78 | * Use nested version here to indicate that we are already | ||
79 | * holding one similar spinlock. | ||
80 | */ | ||
81 | spin_lock_nested(ptl, SINGLE_DEPTH_NESTING); | ||
82 | } | ||
83 | |||
84 | static inline void do_pte_unlock(spinlock_t *ptl) | ||
85 | { | ||
86 | spin_unlock(ptl); | ||
87 | } | ||
88 | #else /* !USE_SPLIT_PTLOCKS */ | ||
89 | static inline void do_pte_lock(spinlock_t *ptl) {} | ||
90 | static inline void do_pte_unlock(spinlock_t *ptl) {} | ||
91 | #endif /* USE_SPLIT_PTLOCKS */ | ||
92 | |||
69 | static int adjust_pte(struct vm_area_struct *vma, unsigned long address, | 93 | static int adjust_pte(struct vm_area_struct *vma, unsigned long address, |
70 | unsigned long pfn) | 94 | unsigned long pfn) |
71 | { | 95 | { |
@@ -90,11 +114,11 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address, | |||
90 | */ | 114 | */ |
91 | ptl = pte_lockptr(vma->vm_mm, pmd); | 115 | ptl = pte_lockptr(vma->vm_mm, pmd); |
92 | pte = pte_offset_map(pmd, address); | 116 | pte = pte_offset_map(pmd, address); |
93 | spin_lock(ptl); | 117 | do_pte_lock(ptl); |
94 | 118 | ||
95 | ret = do_adjust_pte(vma, address, pfn, pte); | 119 | ret = do_adjust_pte(vma, address, pfn, pte); |
96 | 120 | ||
97 | spin_unlock(ptl); | 121 | do_pte_unlock(ptl); |
98 | pte_unmap(pte); | 122 | pte_unmap(pte); |
99 | 123 | ||
100 | return ret; | 124 | return ret; |
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 7fd9b5eb177f..5164069ced42 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/highmem.h> | 18 | #include <linux/highmem.h> |
19 | #include <linux/gfp.h> | 19 | #include <linux/gfp.h> |
20 | #include <linux/memblock.h> | 20 | #include <linux/memblock.h> |
21 | #include <linux/sort.h> | ||
21 | 22 | ||
22 | #include <asm/mach-types.h> | 23 | #include <asm/mach-types.h> |
23 | #include <asm/sections.h> | 24 | #include <asm/sections.h> |
@@ -121,9 +122,10 @@ void show_mem(void) | |||
121 | printk("%d pages swap cached\n", cached); | 122 | printk("%d pages swap cached\n", cached); |
122 | } | 123 | } |
123 | 124 | ||
124 | static void __init find_limits(struct meminfo *mi, | 125 | static void __init find_limits(unsigned long *min, unsigned long *max_low, |
125 | unsigned long *min, unsigned long *max_low, unsigned long *max_high) | 126 | unsigned long *max_high) |
126 | { | 127 | { |
128 | struct meminfo *mi = &meminfo; | ||
127 | int i; | 129 | int i; |
128 | 130 | ||
129 | *min = -1UL; | 131 | *min = -1UL; |
@@ -147,14 +149,13 @@ static void __init find_limits(struct meminfo *mi, | |||
147 | } | 149 | } |
148 | } | 150 | } |
149 | 151 | ||
150 | static void __init arm_bootmem_init(struct meminfo *mi, | 152 | static void __init arm_bootmem_init(unsigned long start_pfn, |
151 | unsigned long start_pfn, unsigned long end_pfn) | 153 | unsigned long end_pfn) |
152 | { | 154 | { |
153 | struct memblock_region *reg; | 155 | struct memblock_region *reg; |
154 | unsigned int boot_pages; | 156 | unsigned int boot_pages; |
155 | phys_addr_t bitmap; | 157 | phys_addr_t bitmap; |
156 | pg_data_t *pgdat; | 158 | pg_data_t *pgdat; |
157 | int i; | ||
158 | 159 | ||
159 | /* | 160 | /* |
160 | * Allocate the bootmem bitmap page. This must be in a region | 161 | * Allocate the bootmem bitmap page. This must be in a region |
@@ -172,30 +173,39 @@ static void __init arm_bootmem_init(struct meminfo *mi, | |||
172 | pgdat = NODE_DATA(0); | 173 | pgdat = NODE_DATA(0); |
173 | init_bootmem_node(pgdat, __phys_to_pfn(bitmap), start_pfn, end_pfn); | 174 | init_bootmem_node(pgdat, __phys_to_pfn(bitmap), start_pfn, end_pfn); |
174 | 175 | ||
175 | for_each_bank(i, mi) { | 176 | /* Free the lowmem regions from memblock into bootmem. */ |
176 | struct membank *bank = &mi->bank[i]; | 177 | for_each_memblock(memory, reg) { |
177 | if (!bank->highmem) | 178 | unsigned long start = memblock_region_memory_base_pfn(reg); |
178 | free_bootmem(bank_phys_start(bank), bank_phys_size(bank)); | 179 | unsigned long end = memblock_region_memory_end_pfn(reg); |
180 | |||
181 | if (end >= end_pfn) | ||
182 | end = end_pfn; | ||
183 | if (start >= end) | ||
184 | break; | ||
185 | |||
186 | free_bootmem(__pfn_to_phys(start), (end - start) << PAGE_SHIFT); | ||
179 | } | 187 | } |
180 | 188 | ||
181 | /* | 189 | /* Reserve the lowmem memblock reserved regions in bootmem. */ |
182 | * Reserve the memblock reserved regions in bootmem. | ||
183 | */ | ||
184 | for_each_memblock(reserved, reg) { | 190 | for_each_memblock(reserved, reg) { |
185 | phys_addr_t start = memblock_region_reserved_base_pfn(reg); | 191 | unsigned long start = memblock_region_reserved_base_pfn(reg); |
186 | phys_addr_t end = memblock_region_reserved_end_pfn(reg); | 192 | unsigned long end = memblock_region_reserved_end_pfn(reg); |
187 | if (start >= start_pfn && end <= end_pfn) | 193 | |
188 | reserve_bootmem_node(pgdat, __pfn_to_phys(start), | 194 | if (end >= end_pfn) |
189 | (end - start) << PAGE_SHIFT, | 195 | end = end_pfn; |
190 | BOOTMEM_DEFAULT); | 196 | if (start >= end) |
197 | break; | ||
198 | |||
199 | reserve_bootmem(__pfn_to_phys(start), | ||
200 | (end - start) << PAGE_SHIFT, BOOTMEM_DEFAULT); | ||
191 | } | 201 | } |
192 | } | 202 | } |
193 | 203 | ||
194 | static void __init arm_bootmem_free(struct meminfo *mi, unsigned long min, | 204 | static void __init arm_bootmem_free(unsigned long min, unsigned long max_low, |
195 | unsigned long max_low, unsigned long max_high) | 205 | unsigned long max_high) |
196 | { | 206 | { |
197 | unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES]; | 207 | unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES]; |
198 | int i; | 208 | struct memblock_region *reg; |
199 | 209 | ||
200 | /* | 210 | /* |
201 | * initialise the zones. | 211 | * initialise the zones. |
@@ -217,13 +227,20 @@ static void __init arm_bootmem_free(struct meminfo *mi, unsigned long min, | |||
217 | * holes = node_size - sum(bank_sizes) | 227 | * holes = node_size - sum(bank_sizes) |
218 | */ | 228 | */ |
219 | memcpy(zhole_size, zone_size, sizeof(zhole_size)); | 229 | memcpy(zhole_size, zone_size, sizeof(zhole_size)); |
220 | for_each_bank(i, mi) { | 230 | for_each_memblock(memory, reg) { |
221 | int idx = 0; | 231 | unsigned long start = memblock_region_memory_base_pfn(reg); |
232 | unsigned long end = memblock_region_memory_end_pfn(reg); | ||
233 | |||
234 | if (start < max_low) { | ||
235 | unsigned long low_end = min(end, max_low); | ||
236 | zhole_size[0] -= low_end - start; | ||
237 | } | ||
222 | #ifdef CONFIG_HIGHMEM | 238 | #ifdef CONFIG_HIGHMEM |
223 | if (mi->bank[i].highmem) | 239 | if (end > max_low) { |
224 | idx = ZONE_HIGHMEM; | 240 | unsigned long high_start = max(start, max_low); |
241 | zhole_size[ZONE_HIGHMEM] -= end - high_start; | ||
242 | } | ||
225 | #endif | 243 | #endif |
226 | zhole_size[idx] -= bank_pfn_size(&mi->bank[i]); | ||
227 | } | 244 | } |
228 | 245 | ||
229 | /* | 246 | /* |
@@ -256,10 +273,19 @@ static void arm_memory_present(void) | |||
256 | } | 273 | } |
257 | #endif | 274 | #endif |
258 | 275 | ||
276 | static int __init meminfo_cmp(const void *_a, const void *_b) | ||
277 | { | ||
278 | const struct membank *a = _a, *b = _b; | ||
279 | long cmp = bank_pfn_start(a) - bank_pfn_start(b); | ||
280 | return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; | ||
281 | } | ||
282 | |||
259 | void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc) | 283 | void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc) |
260 | { | 284 | { |
261 | int i; | 285 | int i; |
262 | 286 | ||
287 | sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL); | ||
288 | |||
263 | memblock_init(); | 289 | memblock_init(); |
264 | for (i = 0; i < mi->nr_banks; i++) | 290 | for (i = 0; i < mi->nr_banks; i++) |
265 | memblock_add(mi->bank[i].start, mi->bank[i].size); | 291 | memblock_add(mi->bank[i].start, mi->bank[i].size); |
@@ -292,14 +318,13 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc) | |||
292 | 318 | ||
293 | void __init bootmem_init(void) | 319 | void __init bootmem_init(void) |
294 | { | 320 | { |
295 | struct meminfo *mi = &meminfo; | ||
296 | unsigned long min, max_low, max_high; | 321 | unsigned long min, max_low, max_high; |
297 | 322 | ||
298 | max_low = max_high = 0; | 323 | max_low = max_high = 0; |
299 | 324 | ||
300 | find_limits(mi, &min, &max_low, &max_high); | 325 | find_limits(&min, &max_low, &max_high); |
301 | 326 | ||
302 | arm_bootmem_init(mi, min, max_low); | 327 | arm_bootmem_init(min, max_low); |
303 | 328 | ||
304 | /* | 329 | /* |
305 | * Sparsemem tries to allocate bootmem in memory_present(), | 330 | * Sparsemem tries to allocate bootmem in memory_present(), |
@@ -317,7 +342,7 @@ void __init bootmem_init(void) | |||
317 | * the sparse mem_map arrays initialized by sparse_init() | 342 | * the sparse mem_map arrays initialized by sparse_init() |
318 | * for memmap_init_zone(), otherwise all PFNs are invalid. | 343 | * for memmap_init_zone(), otherwise all PFNs are invalid. |
319 | */ | 344 | */ |
320 | arm_bootmem_free(mi, min, max_low, max_high); | 345 | arm_bootmem_free(min, max_low, max_high); |
321 | 346 | ||
322 | high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1; | 347 | high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1; |
323 | 348 | ||
@@ -411,6 +436,56 @@ static void __init free_unused_memmap(struct meminfo *mi) | |||
411 | } | 436 | } |
412 | } | 437 | } |
413 | 438 | ||
439 | static void __init free_highpages(void) | ||
440 | { | ||
441 | #ifdef CONFIG_HIGHMEM | ||
442 | unsigned long max_low = max_low_pfn + PHYS_PFN_OFFSET; | ||
443 | struct memblock_region *mem, *res; | ||
444 | |||
445 | /* set highmem page free */ | ||
446 | for_each_memblock(memory, mem) { | ||
447 | unsigned long start = memblock_region_memory_base_pfn(mem); | ||
448 | unsigned long end = memblock_region_memory_end_pfn(mem); | ||
449 | |||
450 | /* Ignore complete lowmem entries */ | ||
451 | if (end <= max_low) | ||
452 | continue; | ||
453 | |||
454 | /* Truncate partial highmem entries */ | ||
455 | if (start < max_low) | ||
456 | start = max_low; | ||
457 | |||
458 | /* Find and exclude any reserved regions */ | ||
459 | for_each_memblock(reserved, res) { | ||
460 | unsigned long res_start, res_end; | ||
461 | |||
462 | res_start = memblock_region_reserved_base_pfn(res); | ||
463 | res_end = memblock_region_reserved_end_pfn(res); | ||
464 | |||
465 | if (res_end < start) | ||
466 | continue; | ||
467 | if (res_start < start) | ||
468 | res_start = start; | ||
469 | if (res_start > end) | ||
470 | res_start = end; | ||
471 | if (res_end > end) | ||
472 | res_end = end; | ||
473 | if (res_start != start) | ||
474 | totalhigh_pages += free_area(start, res_start, | ||
475 | NULL); | ||
476 | start = res_end; | ||
477 | if (start == end) | ||
478 | break; | ||
479 | } | ||
480 | |||
481 | /* And now free anything which remains */ | ||
482 | if (start < end) | ||
483 | totalhigh_pages += free_area(start, end, NULL); | ||
484 | } | ||
485 | totalram_pages += totalhigh_pages; | ||
486 | #endif | ||
487 | } | ||
488 | |||
414 | /* | 489 | /* |
415 | * mem_init() marks the free areas in the mem_map and tells us how much | 490 | * mem_init() marks the free areas in the mem_map and tells us how much |
416 | * memory is free. This is done after various parts of the system have | 491 | * memory is free. This is done after various parts of the system have |
@@ -419,6 +494,7 @@ static void __init free_unused_memmap(struct meminfo *mi) | |||
419 | void __init mem_init(void) | 494 | void __init mem_init(void) |
420 | { | 495 | { |
421 | unsigned long reserved_pages, free_pages; | 496 | unsigned long reserved_pages, free_pages; |
497 | struct memblock_region *reg; | ||
422 | int i; | 498 | int i; |
423 | #ifdef CONFIG_HAVE_TCM | 499 | #ifdef CONFIG_HAVE_TCM |
424 | /* These pointers are filled in on TCM detection */ | 500 | /* These pointers are filled in on TCM detection */ |
@@ -439,16 +515,7 @@ void __init mem_init(void) | |||
439 | __phys_to_pfn(__pa(swapper_pg_dir)), NULL); | 515 | __phys_to_pfn(__pa(swapper_pg_dir)), NULL); |
440 | #endif | 516 | #endif |
441 | 517 | ||
442 | #ifdef CONFIG_HIGHMEM | 518 | free_highpages(); |
443 | /* set highmem page free */ | ||
444 | for_each_bank (i, &meminfo) { | ||
445 | unsigned long start = bank_pfn_start(&meminfo.bank[i]); | ||
446 | unsigned long end = bank_pfn_end(&meminfo.bank[i]); | ||
447 | if (start >= max_low_pfn + PHYS_PFN_OFFSET) | ||
448 | totalhigh_pages += free_area(start, end, NULL); | ||
449 | } | ||
450 | totalram_pages += totalhigh_pages; | ||
451 | #endif | ||
452 | 519 | ||
453 | reserved_pages = free_pages = 0; | 520 | reserved_pages = free_pages = 0; |
454 | 521 | ||
@@ -478,9 +545,11 @@ void __init mem_init(void) | |||
478 | */ | 545 | */ |
479 | printk(KERN_INFO "Memory:"); | 546 | printk(KERN_INFO "Memory:"); |
480 | num_physpages = 0; | 547 | num_physpages = 0; |
481 | for (i = 0; i < meminfo.nr_banks; i++) { | 548 | for_each_memblock(memory, reg) { |
482 | num_physpages += bank_pfn_size(&meminfo.bank[i]); | 549 | unsigned long pages = memblock_region_memory_end_pfn(reg) - |
483 | printk(" %ldMB", bank_phys_size(&meminfo.bank[i]) >> 20); | 550 | memblock_region_memory_base_pfn(reg); |
551 | num_physpages += pages; | ||
552 | printk(" %ldMB", pages >> (20 - PAGE_SHIFT)); | ||
484 | } | 553 | } |
485 | printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT)); | 554 | printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT)); |
486 | 555 | ||
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index c32f731d56d3..72ad3e1f56cf 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/mman.h> | 14 | #include <linux/mman.h> |
15 | #include <linux/nodemask.h> | 15 | #include <linux/nodemask.h> |
16 | #include <linux/memblock.h> | 16 | #include <linux/memblock.h> |
17 | #include <linux/sort.h> | ||
18 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
19 | 18 | ||
20 | #include <asm/cputype.h> | 19 | #include <asm/cputype.h> |
@@ -265,17 +264,17 @@ static struct mem_type mem_types[] = { | |||
265 | .domain = DOMAIN_KERNEL, | 264 | .domain = DOMAIN_KERNEL, |
266 | }, | 265 | }, |
267 | [MT_MEMORY_DTCM] = { | 266 | [MT_MEMORY_DTCM] = { |
268 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | | 267 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | |
269 | L_PTE_DIRTY | L_PTE_WRITE, | 268 | L_PTE_WRITE, |
270 | .prot_l1 = PMD_TYPE_TABLE, | 269 | .prot_l1 = PMD_TYPE_TABLE, |
271 | .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN, | 270 | .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN, |
272 | .domain = DOMAIN_KERNEL, | 271 | .domain = DOMAIN_KERNEL, |
273 | }, | 272 | }, |
274 | [MT_MEMORY_ITCM] = { | 273 | [MT_MEMORY_ITCM] = { |
275 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | | 274 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | |
276 | L_PTE_USER | L_PTE_EXEC, | 275 | L_PTE_WRITE | L_PTE_EXEC, |
277 | .prot_l1 = PMD_TYPE_TABLE, | 276 | .prot_l1 = PMD_TYPE_TABLE, |
278 | .domain = DOMAIN_IO, | 277 | .domain = DOMAIN_KERNEL, |
279 | }, | 278 | }, |
280 | }; | 279 | }; |
281 | 280 | ||
@@ -745,13 +744,14 @@ static int __init early_vmalloc(char *arg) | |||
745 | } | 744 | } |
746 | early_param("vmalloc", early_vmalloc); | 745 | early_param("vmalloc", early_vmalloc); |
747 | 746 | ||
748 | phys_addr_t lowmem_end_addr; | 747 | static phys_addr_t lowmem_limit __initdata = 0; |
749 | 748 | ||
750 | static void __init sanity_check_meminfo(void) | 749 | static void __init sanity_check_meminfo(void) |
751 | { | 750 | { |
752 | int i, j, highmem = 0; | 751 | int i, j, highmem = 0; |
753 | 752 | ||
754 | lowmem_end_addr = __pa(vmalloc_min - 1) + 1; | 753 | lowmem_limit = __pa(vmalloc_min - 1) + 1; |
754 | memblock_set_current_limit(lowmem_limit); | ||
755 | 755 | ||
756 | for (i = 0, j = 0; i < meminfo.nr_banks; i++) { | 756 | for (i = 0, j = 0; i < meminfo.nr_banks; i++) { |
757 | struct membank *bank = &meminfo.bank[j]; | 757 | struct membank *bank = &meminfo.bank[j]; |
@@ -852,6 +852,7 @@ static void __init sanity_check_meminfo(void) | |||
852 | static inline void prepare_page_table(void) | 852 | static inline void prepare_page_table(void) |
853 | { | 853 | { |
854 | unsigned long addr; | 854 | unsigned long addr; |
855 | phys_addr_t end; | ||
855 | 856 | ||
856 | /* | 857 | /* |
857 | * Clear out all the mappings below the kernel image. | 858 | * Clear out all the mappings below the kernel image. |
@@ -867,10 +868,17 @@ static inline void prepare_page_table(void) | |||
867 | pmd_clear(pmd_off_k(addr)); | 868 | pmd_clear(pmd_off_k(addr)); |
868 | 869 | ||
869 | /* | 870 | /* |
871 | * Find the end of the first block of lowmem. | ||
872 | */ | ||
873 | end = memblock.memory.regions[0].base + memblock.memory.regions[0].size; | ||
874 | if (end >= lowmem_limit) | ||
875 | end = lowmem_limit; | ||
876 | |||
877 | /* | ||
870 | * Clear out all the kernel space mappings, except for the first | 878 | * Clear out all the kernel space mappings, except for the first |
871 | * memory bank, up to the end of the vmalloc region. | 879 | * memory bank, up to the end of the vmalloc region. |
872 | */ | 880 | */ |
873 | for (addr = __phys_to_virt(bank_phys_end(&meminfo.bank[0])); | 881 | for (addr = __phys_to_virt(end); |
874 | addr < VMALLOC_END; addr += PGDIR_SIZE) | 882 | addr < VMALLOC_END; addr += PGDIR_SIZE) |
875 | pmd_clear(pmd_off_k(addr)); | 883 | pmd_clear(pmd_off_k(addr)); |
876 | } | 884 | } |
@@ -987,37 +995,28 @@ static void __init kmap_init(void) | |||
987 | #endif | 995 | #endif |
988 | } | 996 | } |
989 | 997 | ||
990 | static inline void map_memory_bank(struct membank *bank) | ||
991 | { | ||
992 | struct map_desc map; | ||
993 | |||
994 | map.pfn = bank_pfn_start(bank); | ||
995 | map.virtual = __phys_to_virt(bank_phys_start(bank)); | ||
996 | map.length = bank_phys_size(bank); | ||
997 | map.type = MT_MEMORY; | ||
998 | |||
999 | create_mapping(&map); | ||
1000 | } | ||
1001 | |||
1002 | static void __init map_lowmem(void) | 998 | static void __init map_lowmem(void) |
1003 | { | 999 | { |
1004 | struct meminfo *mi = &meminfo; | 1000 | struct memblock_region *reg; |
1005 | int i; | ||
1006 | 1001 | ||
1007 | /* Map all the lowmem memory banks. */ | 1002 | /* Map all the lowmem memory banks. */ |
1008 | for (i = 0; i < mi->nr_banks; i++) { | 1003 | for_each_memblock(memory, reg) { |
1009 | struct membank *bank = &mi->bank[i]; | 1004 | phys_addr_t start = reg->base; |
1005 | phys_addr_t end = start + reg->size; | ||
1006 | struct map_desc map; | ||
1007 | |||
1008 | if (end > lowmem_limit) | ||
1009 | end = lowmem_limit; | ||
1010 | if (start >= end) | ||
1011 | break; | ||
1010 | 1012 | ||
1011 | if (!bank->highmem) | 1013 | map.pfn = __phys_to_pfn(start); |
1012 | map_memory_bank(bank); | 1014 | map.virtual = __phys_to_virt(start); |
1013 | } | 1015 | map.length = end - start; |
1014 | } | 1016 | map.type = MT_MEMORY; |
1015 | 1017 | ||
1016 | static int __init meminfo_cmp(const void *_a, const void *_b) | 1018 | create_mapping(&map); |
1017 | { | 1019 | } |
1018 | const struct membank *a = _a, *b = _b; | ||
1019 | long cmp = bank_pfn_start(a) - bank_pfn_start(b); | ||
1020 | return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; | ||
1021 | } | 1020 | } |
1022 | 1021 | ||
1023 | /* | 1022 | /* |
@@ -1028,8 +1027,6 @@ void __init paging_init(struct machine_desc *mdesc) | |||
1028 | { | 1027 | { |
1029 | void *zero_page; | 1028 | void *zero_page; |
1030 | 1029 | ||
1031 | sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL); | ||
1032 | |||
1033 | build_mem_type_table(); | 1030 | build_mem_type_table(); |
1034 | sanity_check_meminfo(); | 1031 | sanity_check_meminfo(); |
1035 | prepare_page_table(); | 1032 | prepare_page_table(); |
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S index a6f5f8475b96..bcf748d9f4e2 100644 --- a/arch/arm/mm/proc-arm1020.S +++ b/arch/arm/mm/proc-arm1020.S | |||
@@ -119,6 +119,20 @@ ENTRY(cpu_arm1020_do_idle) | |||
119 | /* ================================= CACHE ================================ */ | 119 | /* ================================= CACHE ================================ */ |
120 | 120 | ||
121 | .align 5 | 121 | .align 5 |
122 | |||
123 | /* | ||
124 | * flush_icache_all() | ||
125 | * | ||
126 | * Unconditionally clean and invalidate the entire icache. | ||
127 | */ | ||
128 | ENTRY(arm1020_flush_icache_all) | ||
129 | #ifndef CONFIG_CPU_ICACHE_DISABLE | ||
130 | mov r0, #0 | ||
131 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache | ||
132 | #endif | ||
133 | mov pc, lr | ||
134 | ENDPROC(arm1020_flush_icache_all) | ||
135 | |||
122 | /* | 136 | /* |
123 | * flush_user_cache_all() | 137 | * flush_user_cache_all() |
124 | * | 138 | * |
@@ -351,6 +365,7 @@ ENTRY(arm1020_dma_unmap_area) | |||
351 | ENDPROC(arm1020_dma_unmap_area) | 365 | ENDPROC(arm1020_dma_unmap_area) |
352 | 366 | ||
353 | ENTRY(arm1020_cache_fns) | 367 | ENTRY(arm1020_cache_fns) |
368 | .long arm1020_flush_icache_all | ||
354 | .long arm1020_flush_kern_cache_all | 369 | .long arm1020_flush_kern_cache_all |
355 | .long arm1020_flush_user_cache_all | 370 | .long arm1020_flush_user_cache_all |
356 | .long arm1020_flush_user_cache_range | 371 | .long arm1020_flush_user_cache_range |
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S index afc06b9c3133..ab7ec26657ea 100644 --- a/arch/arm/mm/proc-arm1020e.S +++ b/arch/arm/mm/proc-arm1020e.S | |||
@@ -119,6 +119,20 @@ ENTRY(cpu_arm1020e_do_idle) | |||
119 | /* ================================= CACHE ================================ */ | 119 | /* ================================= CACHE ================================ */ |
120 | 120 | ||
121 | .align 5 | 121 | .align 5 |
122 | |||
123 | /* | ||
124 | * flush_icache_all() | ||
125 | * | ||
126 | * Unconditionally clean and invalidate the entire icache. | ||
127 | */ | ||
128 | ENTRY(arm1020e_flush_icache_all) | ||
129 | #ifndef CONFIG_CPU_ICACHE_DISABLE | ||
130 | mov r0, #0 | ||
131 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache | ||
132 | #endif | ||
133 | mov pc, lr | ||
134 | ENDPROC(arm1020e_flush_icache_all) | ||
135 | |||
122 | /* | 136 | /* |
123 | * flush_user_cache_all() | 137 | * flush_user_cache_all() |
124 | * | 138 | * |
@@ -337,6 +351,7 @@ ENTRY(arm1020e_dma_unmap_area) | |||
337 | ENDPROC(arm1020e_dma_unmap_area) | 351 | ENDPROC(arm1020e_dma_unmap_area) |
338 | 352 | ||
339 | ENTRY(arm1020e_cache_fns) | 353 | ENTRY(arm1020e_cache_fns) |
354 | .long arm1020e_flush_icache_all | ||
340 | .long arm1020e_flush_kern_cache_all | 355 | .long arm1020e_flush_kern_cache_all |
341 | .long arm1020e_flush_user_cache_all | 356 | .long arm1020e_flush_user_cache_all |
342 | .long arm1020e_flush_user_cache_range | 357 | .long arm1020e_flush_user_cache_range |
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S index 8915e0ba3fe5..831c5e54e22f 100644 --- a/arch/arm/mm/proc-arm1022.S +++ b/arch/arm/mm/proc-arm1022.S | |||
@@ -108,6 +108,20 @@ ENTRY(cpu_arm1022_do_idle) | |||
108 | /* ================================= CACHE ================================ */ | 108 | /* ================================= CACHE ================================ */ |
109 | 109 | ||
110 | .align 5 | 110 | .align 5 |
111 | |||
112 | /* | ||
113 | * flush_icache_all() | ||
114 | * | ||
115 | * Unconditionally clean and invalidate the entire icache. | ||
116 | */ | ||
117 | ENTRY(arm1022_flush_icache_all) | ||
118 | #ifndef CONFIG_CPU_ICACHE_DISABLE | ||
119 | mov r0, #0 | ||
120 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache | ||
121 | #endif | ||
122 | mov pc, lr | ||
123 | ENDPROC(arm1022_flush_icache_all) | ||
124 | |||
111 | /* | 125 | /* |
112 | * flush_user_cache_all() | 126 | * flush_user_cache_all() |
113 | * | 127 | * |
@@ -326,6 +340,7 @@ ENTRY(arm1022_dma_unmap_area) | |||
326 | ENDPROC(arm1022_dma_unmap_area) | 340 | ENDPROC(arm1022_dma_unmap_area) |
327 | 341 | ||
328 | ENTRY(arm1022_cache_fns) | 342 | ENTRY(arm1022_cache_fns) |
343 | .long arm1022_flush_icache_all | ||
329 | .long arm1022_flush_kern_cache_all | 344 | .long arm1022_flush_kern_cache_all |
330 | .long arm1022_flush_user_cache_all | 345 | .long arm1022_flush_user_cache_all |
331 | .long arm1022_flush_user_cache_range | 346 | .long arm1022_flush_user_cache_range |
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S index ff446c5d476f..e3f7e9a166bf 100644 --- a/arch/arm/mm/proc-arm1026.S +++ b/arch/arm/mm/proc-arm1026.S | |||
@@ -108,6 +108,20 @@ ENTRY(cpu_arm1026_do_idle) | |||
108 | /* ================================= CACHE ================================ */ | 108 | /* ================================= CACHE ================================ */ |
109 | 109 | ||
110 | .align 5 | 110 | .align 5 |
111 | |||
112 | /* | ||
113 | * flush_icache_all() | ||
114 | * | ||
115 | * Unconditionally clean and invalidate the entire icache. | ||
116 | */ | ||
117 | ENTRY(arm1026_flush_icache_all) | ||
118 | #ifndef CONFIG_CPU_ICACHE_DISABLE | ||
119 | mov r0, #0 | ||
120 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache | ||
121 | #endif | ||
122 | mov pc, lr | ||
123 | ENDPROC(arm1026_flush_icache_all) | ||
124 | |||
111 | /* | 125 | /* |
112 | * flush_user_cache_all() | 126 | * flush_user_cache_all() |
113 | * | 127 | * |
@@ -320,6 +334,7 @@ ENTRY(arm1026_dma_unmap_area) | |||
320 | ENDPROC(arm1026_dma_unmap_area) | 334 | ENDPROC(arm1026_dma_unmap_area) |
321 | 335 | ||
322 | ENTRY(arm1026_cache_fns) | 336 | ENTRY(arm1026_cache_fns) |
337 | .long arm1026_flush_icache_all | ||
323 | .long arm1026_flush_kern_cache_all | 338 | .long arm1026_flush_kern_cache_all |
324 | .long arm1026_flush_user_cache_all | 339 | .long arm1026_flush_user_cache_all |
325 | .long arm1026_flush_user_cache_range | 340 | .long arm1026_flush_user_cache_range |
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S index fecf570939f3..6109f278a904 100644 --- a/arch/arm/mm/proc-arm920.S +++ b/arch/arm/mm/proc-arm920.S | |||
@@ -110,6 +110,17 @@ ENTRY(cpu_arm920_do_idle) | |||
110 | #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH | 110 | #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH |
111 | 111 | ||
112 | /* | 112 | /* |
113 | * flush_icache_all() | ||
114 | * | ||
115 | * Unconditionally clean and invalidate the entire icache. | ||
116 | */ | ||
117 | ENTRY(arm920_flush_icache_all) | ||
118 | mov r0, #0 | ||
119 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache | ||
120 | mov pc, lr | ||
121 | ENDPROC(arm920_flush_icache_all) | ||
122 | |||
123 | /* | ||
113 | * flush_user_cache_all() | 124 | * flush_user_cache_all() |
114 | * | 125 | * |
115 | * Invalidate all cache entries in a particular address | 126 | * Invalidate all cache entries in a particular address |
@@ -305,6 +316,7 @@ ENTRY(arm920_dma_unmap_area) | |||
305 | ENDPROC(arm920_dma_unmap_area) | 316 | ENDPROC(arm920_dma_unmap_area) |
306 | 317 | ||
307 | ENTRY(arm920_cache_fns) | 318 | ENTRY(arm920_cache_fns) |
319 | .long arm920_flush_icache_all | ||
308 | .long arm920_flush_kern_cache_all | 320 | .long arm920_flush_kern_cache_all |
309 | .long arm920_flush_user_cache_all | 321 | .long arm920_flush_user_cache_all |
310 | .long arm920_flush_user_cache_range | 322 | .long arm920_flush_user_cache_range |
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S index e3cbf87c9480..bb2f0f46a5e6 100644 --- a/arch/arm/mm/proc-arm922.S +++ b/arch/arm/mm/proc-arm922.S | |||
@@ -112,6 +112,17 @@ ENTRY(cpu_arm922_do_idle) | |||
112 | #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH | 112 | #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH |
113 | 113 | ||
114 | /* | 114 | /* |
115 | * flush_icache_all() | ||
116 | * | ||
117 | * Unconditionally clean and invalidate the entire icache. | ||
118 | */ | ||
119 | ENTRY(arm922_flush_icache_all) | ||
120 | mov r0, #0 | ||
121 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache | ||
122 | mov pc, lr | ||
123 | ENDPROC(arm922_flush_icache_all) | ||
124 | |||
125 | /* | ||
115 | * flush_user_cache_all() | 126 | * flush_user_cache_all() |
116 | * | 127 | * |
117 | * Clean and invalidate all cache entries in a particular | 128 | * Clean and invalidate all cache entries in a particular |
@@ -307,6 +318,7 @@ ENTRY(arm922_dma_unmap_area) | |||
307 | ENDPROC(arm922_dma_unmap_area) | 318 | ENDPROC(arm922_dma_unmap_area) |
308 | 319 | ||
309 | ENTRY(arm922_cache_fns) | 320 | ENTRY(arm922_cache_fns) |
321 | .long arm922_flush_icache_all | ||
310 | .long arm922_flush_kern_cache_all | 322 | .long arm922_flush_kern_cache_all |
311 | .long arm922_flush_user_cache_all | 323 | .long arm922_flush_user_cache_all |
312 | .long arm922_flush_user_cache_range | 324 | .long arm922_flush_user_cache_range |
diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S index 572424c867b5..c13e01accfe2 100644 --- a/arch/arm/mm/proc-arm925.S +++ b/arch/arm/mm/proc-arm925.S | |||
@@ -145,6 +145,17 @@ ENTRY(cpu_arm925_do_idle) | |||
145 | mov pc, lr | 145 | mov pc, lr |
146 | 146 | ||
147 | /* | 147 | /* |
148 | * flush_icache_all() | ||
149 | * | ||
150 | * Unconditionally clean and invalidate the entire icache. | ||
151 | */ | ||
152 | ENTRY(arm925_flush_icache_all) | ||
153 | mov r0, #0 | ||
154 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache | ||
155 | mov pc, lr | ||
156 | ENDPROC(arm925_flush_icache_all) | ||
157 | |||
158 | /* | ||
148 | * flush_user_cache_all() | 159 | * flush_user_cache_all() |
149 | * | 160 | * |
150 | * Clean and invalidate all cache entries in a particular | 161 | * Clean and invalidate all cache entries in a particular |
@@ -362,6 +373,7 @@ ENTRY(arm925_dma_unmap_area) | |||
362 | ENDPROC(arm925_dma_unmap_area) | 373 | ENDPROC(arm925_dma_unmap_area) |
363 | 374 | ||
364 | ENTRY(arm925_cache_fns) | 375 | ENTRY(arm925_cache_fns) |
376 | .long arm925_flush_icache_all | ||
365 | .long arm925_flush_kern_cache_all | 377 | .long arm925_flush_kern_cache_all |
366 | .long arm925_flush_user_cache_all | 378 | .long arm925_flush_user_cache_all |
367 | .long arm925_flush_user_cache_range | 379 | .long arm925_flush_user_cache_range |
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S index 63d168b4ebe6..42eb4315740b 100644 --- a/arch/arm/mm/proc-arm926.S +++ b/arch/arm/mm/proc-arm926.S | |||
@@ -111,6 +111,17 @@ ENTRY(cpu_arm926_do_idle) | |||
111 | mov pc, lr | 111 | mov pc, lr |
112 | 112 | ||
113 | /* | 113 | /* |
114 | * flush_icache_all() | ||
115 | * | ||
116 | * Unconditionally clean and invalidate the entire icache. | ||
117 | */ | ||
118 | ENTRY(arm926_flush_icache_all) | ||
119 | mov r0, #0 | ||
120 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache | ||
121 | mov pc, lr | ||
122 | ENDPROC(arm926_flush_icache_all) | ||
123 | |||
124 | /* | ||
114 | * flush_user_cache_all() | 125 | * flush_user_cache_all() |
115 | * | 126 | * |
116 | * Clean and invalidate all cache entries in a particular | 127 | * Clean and invalidate all cache entries in a particular |
@@ -325,6 +336,7 @@ ENTRY(arm926_dma_unmap_area) | |||
325 | ENDPROC(arm926_dma_unmap_area) | 336 | ENDPROC(arm926_dma_unmap_area) |
326 | 337 | ||
327 | ENTRY(arm926_cache_fns) | 338 | ENTRY(arm926_cache_fns) |
339 | .long arm926_flush_icache_all | ||
328 | .long arm926_flush_kern_cache_all | 340 | .long arm926_flush_kern_cache_all |
329 | .long arm926_flush_user_cache_all | 341 | .long arm926_flush_user_cache_all |
330 | .long arm926_flush_user_cache_range | 342 | .long arm926_flush_user_cache_range |
diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S index f6a62822418e..7b11cdb9935f 100644 --- a/arch/arm/mm/proc-arm940.S +++ b/arch/arm/mm/proc-arm940.S | |||
@@ -68,6 +68,17 @@ ENTRY(cpu_arm940_do_idle) | |||
68 | mov pc, lr | 68 | mov pc, lr |
69 | 69 | ||
70 | /* | 70 | /* |
71 | * flush_icache_all() | ||
72 | * | ||
73 | * Unconditionally clean and invalidate the entire icache. | ||
74 | */ | ||
75 | ENTRY(arm940_flush_icache_all) | ||
76 | mov r0, #0 | ||
77 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache | ||
78 | mov pc, lr | ||
79 | ENDPROC(arm940_flush_icache_all) | ||
80 | |||
81 | /* | ||
71 | * flush_user_cache_all() | 82 | * flush_user_cache_all() |
72 | */ | 83 | */ |
73 | ENTRY(arm940_flush_user_cache_all) | 84 | ENTRY(arm940_flush_user_cache_all) |
@@ -254,6 +265,7 @@ ENTRY(arm940_dma_unmap_area) | |||
254 | ENDPROC(arm940_dma_unmap_area) | 265 | ENDPROC(arm940_dma_unmap_area) |
255 | 266 | ||
256 | ENTRY(arm940_cache_fns) | 267 | ENTRY(arm940_cache_fns) |
268 | .long arm940_flush_icache_all | ||
257 | .long arm940_flush_kern_cache_all | 269 | .long arm940_flush_kern_cache_all |
258 | .long arm940_flush_user_cache_all | 270 | .long arm940_flush_user_cache_all |
259 | .long arm940_flush_user_cache_range | 271 | .long arm940_flush_user_cache_range |
diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S index ea2e7f2eb95b..1a5bbf080342 100644 --- a/arch/arm/mm/proc-arm946.S +++ b/arch/arm/mm/proc-arm946.S | |||
@@ -75,6 +75,17 @@ ENTRY(cpu_arm946_do_idle) | |||
75 | mov pc, lr | 75 | mov pc, lr |
76 | 76 | ||
77 | /* | 77 | /* |
78 | * flush_icache_all() | ||
79 | * | ||
80 | * Unconditionally clean and invalidate the entire icache. | ||
81 | */ | ||
82 | ENTRY(arm946_flush_icache_all) | ||
83 | mov r0, #0 | ||
84 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache | ||
85 | mov pc, lr | ||
86 | ENDPROC(arm946_flush_icache_all) | ||
87 | |||
88 | /* | ||
78 | * flush_user_cache_all() | 89 | * flush_user_cache_all() |
79 | */ | 90 | */ |
80 | ENTRY(arm946_flush_user_cache_all) | 91 | ENTRY(arm946_flush_user_cache_all) |
@@ -296,6 +307,7 @@ ENTRY(arm946_dma_unmap_area) | |||
296 | ENDPROC(arm946_dma_unmap_area) | 307 | ENDPROC(arm946_dma_unmap_area) |
297 | 308 | ||
298 | ENTRY(arm946_cache_fns) | 309 | ENTRY(arm946_cache_fns) |
310 | .long arm946_flush_icache_all | ||
299 | .long arm946_flush_kern_cache_all | 311 | .long arm946_flush_kern_cache_all |
300 | .long arm946_flush_user_cache_all | 312 | .long arm946_flush_user_cache_all |
301 | .long arm946_flush_user_cache_range | 313 | .long arm946_flush_user_cache_range |
diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S index 578da69200cf..b4597edbff97 100644 --- a/arch/arm/mm/proc-feroceon.S +++ b/arch/arm/mm/proc-feroceon.S | |||
@@ -124,6 +124,17 @@ ENTRY(cpu_feroceon_do_idle) | |||
124 | mov pc, lr | 124 | mov pc, lr |
125 | 125 | ||
126 | /* | 126 | /* |
127 | * flush_icache_all() | ||
128 | * | ||
129 | * Unconditionally clean and invalidate the entire icache. | ||
130 | */ | ||
131 | ENTRY(feroceon_flush_icache_all) | ||
132 | mov r0, #0 | ||
133 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache | ||
134 | mov pc, lr | ||
135 | ENDPROC(feroceon_flush_icache_all) | ||
136 | |||
137 | /* | ||
127 | * flush_user_cache_all() | 138 | * flush_user_cache_all() |
128 | * | 139 | * |
129 | * Clean and invalidate all cache entries in a particular | 140 | * Clean and invalidate all cache entries in a particular |
@@ -401,6 +412,7 @@ ENTRY(feroceon_dma_unmap_area) | |||
401 | ENDPROC(feroceon_dma_unmap_area) | 412 | ENDPROC(feroceon_dma_unmap_area) |
402 | 413 | ||
403 | ENTRY(feroceon_cache_fns) | 414 | ENTRY(feroceon_cache_fns) |
415 | .long feroceon_flush_icache_all | ||
404 | .long feroceon_flush_kern_cache_all | 416 | .long feroceon_flush_kern_cache_all |
405 | .long feroceon_flush_user_cache_all | 417 | .long feroceon_flush_user_cache_all |
406 | .long feroceon_flush_user_cache_range | 418 | .long feroceon_flush_user_cache_range |
@@ -412,6 +424,7 @@ ENTRY(feroceon_cache_fns) | |||
412 | .long feroceon_dma_flush_range | 424 | .long feroceon_dma_flush_range |
413 | 425 | ||
414 | ENTRY(feroceon_range_cache_fns) | 426 | ENTRY(feroceon_range_cache_fns) |
427 | .long feroceon_flush_icache_all | ||
415 | .long feroceon_flush_kern_cache_all | 428 | .long feroceon_flush_kern_cache_all |
416 | .long feroceon_flush_user_cache_all | 429 | .long feroceon_flush_user_cache_all |
417 | .long feroceon_flush_user_cache_range | 430 | .long feroceon_flush_user_cache_range |
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S index cad07e403044..ec26355cb7c2 100644 --- a/arch/arm/mm/proc-xsc3.S +++ b/arch/arm/mm/proc-xsc3.S | |||
@@ -141,6 +141,17 @@ ENTRY(cpu_xsc3_do_idle) | |||
141 | /* ================================= CACHE ================================ */ | 141 | /* ================================= CACHE ================================ */ |
142 | 142 | ||
143 | /* | 143 | /* |
144 | * flush_icache_all() | ||
145 | * | ||
146 | * Unconditionally clean and invalidate the entire icache. | ||
147 | */ | ||
148 | ENTRY(xsc3_flush_icache_all) | ||
149 | mov r0, #0 | ||
150 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache | ||
151 | mov pc, lr | ||
152 | ENDPROC(xsc3_flush_icache_all) | ||
153 | |||
154 | /* | ||
144 | * flush_user_cache_all() | 155 | * flush_user_cache_all() |
145 | * | 156 | * |
146 | * Invalidate all cache entries in a particular address | 157 | * Invalidate all cache entries in a particular address |
@@ -325,6 +336,7 @@ ENTRY(xsc3_dma_unmap_area) | |||
325 | ENDPROC(xsc3_dma_unmap_area) | 336 | ENDPROC(xsc3_dma_unmap_area) |
326 | 337 | ||
327 | ENTRY(xsc3_cache_fns) | 338 | ENTRY(xsc3_cache_fns) |
339 | .long xsc3_flush_icache_all | ||
328 | .long xsc3_flush_kern_cache_all | 340 | .long xsc3_flush_kern_cache_all |
329 | .long xsc3_flush_user_cache_all | 341 | .long xsc3_flush_user_cache_all |
330 | .long xsc3_flush_user_cache_range | 342 | .long xsc3_flush_user_cache_range |
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index cb245edb2c2b..523408c0bb38 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S | |||
@@ -181,6 +181,17 @@ ENTRY(cpu_xscale_do_idle) | |||
181 | /* ================================= CACHE ================================ */ | 181 | /* ================================= CACHE ================================ */ |
182 | 182 | ||
183 | /* | 183 | /* |
184 | * flush_icache_all() | ||
185 | * | ||
186 | * Unconditionally clean and invalidate the entire icache. | ||
187 | */ | ||
188 | ENTRY(xscale_flush_icache_all) | ||
189 | mov r0, #0 | ||
190 | mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache | ||
191 | mov pc, lr | ||
192 | ENDPROC(xscale_flush_icache_all) | ||
193 | |||
194 | /* | ||
184 | * flush_user_cache_all() | 195 | * flush_user_cache_all() |
185 | * | 196 | * |
186 | * Invalidate all cache entries in a particular address | 197 | * Invalidate all cache entries in a particular address |
@@ -397,6 +408,7 @@ ENTRY(xscale_dma_unmap_area) | |||
397 | ENDPROC(xscale_dma_unmap_area) | 408 | ENDPROC(xscale_dma_unmap_area) |
398 | 409 | ||
399 | ENTRY(xscale_cache_fns) | 410 | ENTRY(xscale_cache_fns) |
411 | .long xscale_flush_icache_all | ||
400 | .long xscale_flush_kern_cache_all | 412 | .long xscale_flush_kern_cache_all |
401 | .long xscale_flush_user_cache_all | 413 | .long xscale_flush_user_cache_all |
402 | .long xscale_flush_user_cache_range | 414 | .long xscale_flush_user_cache_range |
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile index 06875b4dd70f..372670952789 100644 --- a/arch/arm/plat-mxc/Makefile +++ b/arch/arm/plat-mxc/Makefile | |||
@@ -18,6 +18,7 @@ obj-$(CONFIG_MXC_USE_EPIT) += epit.o | |||
18 | obj-$(CONFIG_ARCH_MXC_AUDMUX_V1) += audmux-v1.o | 18 | obj-$(CONFIG_ARCH_MXC_AUDMUX_V1) += audmux-v1.o |
19 | obj-$(CONFIG_ARCH_MXC_AUDMUX_V2) += audmux-v2.o | 19 | obj-$(CONFIG_ARCH_MXC_AUDMUX_V2) += audmux-v2.o |
20 | obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o | 20 | obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o |
21 | obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o | ||
21 | ifdef CONFIG_SND_IMX_SOC | 22 | ifdef CONFIG_SND_IMX_SOC |
22 | obj-y += ssi-fiq.o | 23 | obj-y += ssi-fiq.o |
23 | obj-y += ssi-fiq-ksym.o | 24 | obj-y += ssi-fiq-ksym.o |
diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c new file mode 100644 index 000000000000..039538e68793 --- /dev/null +++ b/arch/arm/plat-mxc/cpufreq.c | |||
@@ -0,0 +1,206 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. | ||
3 | */ | ||
4 | |||
5 | /* | ||
6 | * The code contained herein is licensed under the GNU General Public | ||
7 | * License. You may obtain a copy of the GNU General Public License | ||
8 | * Version 2 or later at the following locations: | ||
9 | * | ||
10 | * http://www.opensource.org/licenses/gpl-license.html | ||
11 | * http://www.gnu.org/copyleft/gpl.html | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * A driver for the Freescale Semiconductor i.MXC CPUfreq module. | ||
16 | * The CPUFREQ driver is for controling CPU frequency. It allows you to change | ||
17 | * the CPU clock speed on the fly. | ||
18 | */ | ||
19 | |||
20 | #include <linux/cpufreq.h> | ||
21 | #include <linux/clk.h> | ||
22 | #include <linux/err.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <mach/hardware.h> | ||
25 | #include <mach/clock.h> | ||
26 | |||
27 | #define CLK32_FREQ 32768 | ||
28 | #define NANOSECOND (1000 * 1000 * 1000) | ||
29 | |||
30 | struct cpu_op *(*get_cpu_op)(int *op); | ||
31 | |||
32 | static int cpu_freq_khz_min; | ||
33 | static int cpu_freq_khz_max; | ||
34 | |||
35 | static struct clk *cpu_clk; | ||
36 | static struct cpufreq_frequency_table *imx_freq_table; | ||
37 | |||
38 | static int cpu_op_nr; | ||
39 | static struct cpu_op *cpu_op_tbl; | ||
40 | |||
41 | static int set_cpu_freq(int freq) | ||
42 | { | ||
43 | int ret = 0; | ||
44 | int org_cpu_rate; | ||
45 | |||
46 | org_cpu_rate = clk_get_rate(cpu_clk); | ||
47 | if (org_cpu_rate == freq) | ||
48 | return ret; | ||
49 | |||
50 | ret = clk_set_rate(cpu_clk, freq); | ||
51 | if (ret != 0) { | ||
52 | printk(KERN_DEBUG "cannot set CPU clock rate\n"); | ||
53 | return ret; | ||
54 | } | ||
55 | |||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | static int mxc_verify_speed(struct cpufreq_policy *policy) | ||
60 | { | ||
61 | if (policy->cpu != 0) | ||
62 | return -EINVAL; | ||
63 | |||
64 | return cpufreq_frequency_table_verify(policy, imx_freq_table); | ||
65 | } | ||
66 | |||
67 | static unsigned int mxc_get_speed(unsigned int cpu) | ||
68 | { | ||
69 | if (cpu) | ||
70 | return 0; | ||
71 | |||
72 | return clk_get_rate(cpu_clk) / 1000; | ||
73 | } | ||
74 | |||
75 | static int mxc_set_target(struct cpufreq_policy *policy, | ||
76 | unsigned int target_freq, unsigned int relation) | ||
77 | { | ||
78 | struct cpufreq_freqs freqs; | ||
79 | int freq_Hz; | ||
80 | int ret = 0; | ||
81 | unsigned int index; | ||
82 | |||
83 | cpufreq_frequency_table_target(policy, imx_freq_table, | ||
84 | target_freq, relation, &index); | ||
85 | freq_Hz = imx_freq_table[index].frequency * 1000; | ||
86 | |||
87 | freqs.old = clk_get_rate(cpu_clk) / 1000; | ||
88 | freqs.new = freq_Hz / 1000; | ||
89 | freqs.cpu = 0; | ||
90 | freqs.flags = 0; | ||
91 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
92 | |||
93 | ret = set_cpu_freq(freq_Hz); | ||
94 | |||
95 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
96 | |||
97 | return ret; | ||
98 | } | ||
99 | |||
100 | static int __init mxc_cpufreq_init(struct cpufreq_policy *policy) | ||
101 | { | ||
102 | int ret; | ||
103 | int i; | ||
104 | |||
105 | printk(KERN_INFO "i.MXC CPU frequency driver\n"); | ||
106 | |||
107 | if (policy->cpu != 0) | ||
108 | return -EINVAL; | ||
109 | |||
110 | if (!get_cpu_op) | ||
111 | return -EINVAL; | ||
112 | |||
113 | cpu_clk = clk_get(NULL, "cpu_clk"); | ||
114 | if (IS_ERR(cpu_clk)) { | ||
115 | printk(KERN_ERR "%s: failed to get cpu clock\n", __func__); | ||
116 | return PTR_ERR(cpu_clk); | ||
117 | } | ||
118 | |||
119 | cpu_op_tbl = get_cpu_op(&cpu_op_nr); | ||
120 | |||
121 | cpu_freq_khz_min = cpu_op_tbl[0].cpu_rate / 1000; | ||
122 | cpu_freq_khz_max = cpu_op_tbl[0].cpu_rate / 1000; | ||
123 | |||
124 | imx_freq_table = kmalloc( | ||
125 | sizeof(struct cpufreq_frequency_table) * (cpu_op_nr + 1), | ||
126 | GFP_KERNEL); | ||
127 | if (!imx_freq_table) { | ||
128 | ret = -ENOMEM; | ||
129 | goto err1; | ||
130 | } | ||
131 | |||
132 | for (i = 0; i < cpu_op_nr; i++) { | ||
133 | imx_freq_table[i].index = i; | ||
134 | imx_freq_table[i].frequency = cpu_op_tbl[i].cpu_rate / 1000; | ||
135 | |||
136 | if ((cpu_op_tbl[i].cpu_rate / 1000) < cpu_freq_khz_min) | ||
137 | cpu_freq_khz_min = cpu_op_tbl[i].cpu_rate / 1000; | ||
138 | |||
139 | if ((cpu_op_tbl[i].cpu_rate / 1000) > cpu_freq_khz_max) | ||
140 | cpu_freq_khz_max = cpu_op_tbl[i].cpu_rate / 1000; | ||
141 | } | ||
142 | |||
143 | imx_freq_table[i].index = i; | ||
144 | imx_freq_table[i].frequency = CPUFREQ_TABLE_END; | ||
145 | |||
146 | policy->cur = clk_get_rate(cpu_clk) / 1000; | ||
147 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
148 | policy->min = policy->cpuinfo.min_freq = cpu_freq_khz_min; | ||
149 | policy->max = policy->cpuinfo.max_freq = cpu_freq_khz_max; | ||
150 | |||
151 | /* Manual states, that PLL stabilizes in two CLK32 periods */ | ||
152 | policy->cpuinfo.transition_latency = 2 * NANOSECOND / CLK32_FREQ; | ||
153 | |||
154 | ret = cpufreq_frequency_table_cpuinfo(policy, imx_freq_table); | ||
155 | |||
156 | if (ret < 0) { | ||
157 | printk(KERN_ERR "%s: failed to register i.MXC CPUfreq \ | ||
158 | with error code %d\n", __func__, ret); | ||
159 | goto err; | ||
160 | } | ||
161 | |||
162 | cpufreq_frequency_table_get_attr(imx_freq_table, policy->cpu); | ||
163 | return 0; | ||
164 | err: | ||
165 | kfree(imx_freq_table); | ||
166 | err1: | ||
167 | clk_put(cpu_clk); | ||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | static int mxc_cpufreq_exit(struct cpufreq_policy *policy) | ||
172 | { | ||
173 | cpufreq_frequency_table_put_attr(policy->cpu); | ||
174 | |||
175 | set_cpu_freq(cpu_freq_khz_max * 1000); | ||
176 | clk_put(cpu_clk); | ||
177 | kfree(imx_freq_table); | ||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | static struct cpufreq_driver mxc_driver = { | ||
182 | .flags = CPUFREQ_STICKY, | ||
183 | .verify = mxc_verify_speed, | ||
184 | .target = mxc_set_target, | ||
185 | .get = mxc_get_speed, | ||
186 | .init = mxc_cpufreq_init, | ||
187 | .exit = mxc_cpufreq_exit, | ||
188 | .name = "imx", | ||
189 | }; | ||
190 | |||
191 | static int __devinit mxc_cpufreq_driver_init(void) | ||
192 | { | ||
193 | return cpufreq_register_driver(&mxc_driver); | ||
194 | } | ||
195 | |||
196 | static void mxc_cpufreq_driver_exit(void) | ||
197 | { | ||
198 | cpufreq_unregister_driver(&mxc_driver); | ||
199 | } | ||
200 | |||
201 | module_init(mxc_cpufreq_driver_init); | ||
202 | module_exit(mxc_cpufreq_driver_exit); | ||
203 | |||
204 | MODULE_AUTHOR("Freescale Semiconductor Inc. Yong Shen <yong.shen@linaro.org>"); | ||
205 | MODULE_DESCRIPTION("CPUfreq driver for i.MX"); | ||
206 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/arm/plat-mxc/devices/Kconfig b/arch/arm/plat-mxc/devices/Kconfig index 404799487f17..9aa6f3ea9012 100644 --- a/arch/arm/plat-mxc/devices/Kconfig +++ b/arch/arm/plat-mxc/devices/Kconfig | |||
@@ -6,9 +6,13 @@ config IMX_HAVE_PLATFORM_FEC | |||
6 | default y if ARCH_MX25 || SOC_IMX27 || ARCH_MX35 || ARCH_MX51 | 6 | default y if ARCH_MX25 || SOC_IMX27 || ARCH_MX35 || ARCH_MX51 |
7 | 7 | ||
8 | config IMX_HAVE_PLATFORM_FLEXCAN | 8 | config IMX_HAVE_PLATFORM_FLEXCAN |
9 | select HAVE_CAN_FLEXCAN | 9 | select HAVE_CAN_FLEXCAN if CAN |
10 | bool | 10 | bool |
11 | 11 | ||
12 | config IMX_HAVE_PLATFORM_GPIO_KEYS | ||
13 | bool | ||
14 | default y if ARCH_MX51 | ||
15 | |||
12 | config IMX_HAVE_PLATFORM_IMX_I2C | 16 | config IMX_HAVE_PLATFORM_IMX_I2C |
13 | bool | 17 | bool |
14 | 18 | ||
diff --git a/arch/arm/plat-mxc/devices/Makefile b/arch/arm/plat-mxc/devices/Makefile index 0a3c1f089413..45aefeb283ba 100644 --- a/arch/arm/plat-mxc/devices/Makefile +++ b/arch/arm/plat-mxc/devices/Makefile | |||
@@ -1,6 +1,7 @@ | |||
1 | obj-$(CONFIG_IMX_HAVE_PLATFORM_ESDHC) += platform-esdhc.o | 1 | obj-$(CONFIG_IMX_HAVE_PLATFORM_ESDHC) += platform-esdhc.o |
2 | obj-$(CONFIG_IMX_HAVE_PLATFORM_FEC) += platform-fec.o | 2 | obj-$(CONFIG_IMX_HAVE_PLATFORM_FEC) += platform-fec.o |
3 | obj-$(CONFIG_IMX_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o | 3 | obj-$(CONFIG_IMX_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o |
4 | obj-$(CONFIG_IMX_HAVE_PLATFORM_GPIO_KEYS) += platform-gpio_keys.o | ||
4 | obj-y += platform-imx-dma.o | 5 | obj-y += platform-imx-dma.o |
5 | obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_I2C) += platform-imx-i2c.o | 6 | obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_I2C) += platform-imx-i2c.o |
6 | obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_SSI) += platform-imx-ssi.o | 7 | obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_SSI) += platform-imx-ssi.o |
diff --git a/arch/arm/plat-mxc/devices/platform-gpio_keys.c b/arch/arm/plat-mxc/devices/platform-gpio_keys.c new file mode 100644 index 000000000000..1c53a532ea0e --- /dev/null +++ b/arch/arm/plat-mxc/devices/platform-gpio_keys.c | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version 2 | ||
7 | * of the License, or (at your option) any later version. | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
16 | * Boston, MA 02110-1301, USA. | ||
17 | */ | ||
18 | #include <asm/sizes.h> | ||
19 | #include <mach/hardware.h> | ||
20 | #include <mach/devices-common.h> | ||
21 | |||
22 | struct platform_device *__init imx_add_gpio_keys( | ||
23 | const struct gpio_keys_platform_data *pdata) | ||
24 | { | ||
25 | return imx_add_platform_device("gpio-keys", -1, NULL, | ||
26 | 0, pdata, sizeof(*pdata)); | ||
27 | } | ||
diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c index 9d38da077edb..9c3e36232b5b 100644 --- a/arch/arm/plat-mxc/gpio.c +++ b/arch/arm/plat-mxc/gpio.c | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/interrupt.h> | ||
23 | #include <linux/io.h> | 24 | #include <linux/io.h> |
24 | #include <linux/irq.h> | 25 | #include <linux/irq.h> |
25 | #include <linux/gpio.h> | 26 | #include <linux/gpio.h> |
@@ -201,11 +202,42 @@ static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc) | |||
201 | } | 202 | } |
202 | } | 203 | } |
203 | 204 | ||
205 | /* | ||
206 | * Set interrupt number "irq" in the GPIO as a wake-up source. | ||
207 | * While system is running, all registered GPIO interrupts need to have | ||
208 | * wake-up enabled. When system is suspended, only selected GPIO interrupts | ||
209 | * need to have wake-up enabled. | ||
210 | * @param irq interrupt source number | ||
211 | * @param enable enable as wake-up if equal to non-zero | ||
212 | * @return This function returns 0 on success. | ||
213 | */ | ||
214 | static int gpio_set_wake_irq(u32 irq, u32 enable) | ||
215 | { | ||
216 | u32 gpio = irq_to_gpio(irq); | ||
217 | u32 gpio_idx = gpio & 0x1F; | ||
218 | struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32]; | ||
219 | |||
220 | if (enable) { | ||
221 | if (port->irq_high && (gpio_idx >= 16)) | ||
222 | enable_irq_wake(port->irq_high); | ||
223 | else | ||
224 | enable_irq_wake(port->irq); | ||
225 | } else { | ||
226 | if (port->irq_high && (gpio_idx >= 16)) | ||
227 | disable_irq_wake(port->irq_high); | ||
228 | else | ||
229 | disable_irq_wake(port->irq); | ||
230 | } | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
204 | static struct irq_chip gpio_irq_chip = { | 235 | static struct irq_chip gpio_irq_chip = { |
205 | .ack = gpio_ack_irq, | 236 | .ack = gpio_ack_irq, |
206 | .mask = gpio_mask_irq, | 237 | .mask = gpio_mask_irq, |
207 | .unmask = gpio_unmask_irq, | 238 | .unmask = gpio_unmask_irq, |
208 | .set_type = gpio_set_irq_type, | 239 | .set_type = gpio_set_irq_type, |
240 | .set_wake = gpio_set_wake_irq, | ||
209 | }; | 241 | }; |
210 | 242 | ||
211 | static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset, | 243 | static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset, |
diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h index 86d7575a564d..8c6896fd1e5f 100644 --- a/arch/arm/plat-mxc/include/mach/devices-common.h +++ b/arch/arm/plat-mxc/include/mach/devices-common.h | |||
@@ -29,6 +29,10 @@ struct platform_device *__init imx_add_flexcan(int id, | |||
29 | resource_size_t irq, | 29 | resource_size_t irq, |
30 | const struct flexcan_platform_data *pdata); | 30 | const struct flexcan_platform_data *pdata); |
31 | 31 | ||
32 | #include <linux/gpio_keys.h> | ||
33 | struct platform_device *__init imx_add_gpio_keys( | ||
34 | const struct gpio_keys_platform_data *pdata); | ||
35 | |||
32 | #include <mach/i2c.h> | 36 | #include <mach/i2c.h> |
33 | struct imx_imx_i2c_data { | 37 | struct imx_imx_i2c_data { |
34 | int id; | 38 | int id; |
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx51.h b/arch/arm/plat-mxc/include/mach/iomux-mx51.h index e46b1c2836d4..d7a41e9a2605 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mx51.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mx51.h | |||
@@ -45,6 +45,8 @@ typedef enum iomux_config { | |||
45 | PAD_CTL_PKE | PAD_CTL_HYS) | 45 | PAD_CTL_PKE | PAD_CTL_HYS) |
46 | #define MX51_GPIO_PAD_CTRL (PAD_CTL_DSE_HIGH | PAD_CTL_PKE | \ | 46 | #define MX51_GPIO_PAD_CTRL (PAD_CTL_DSE_HIGH | PAD_CTL_PKE | \ |
47 | PAD_CTL_SRE_FAST) | 47 | PAD_CTL_SRE_FAST) |
48 | #define MX51_GPIO_PAD_CTRL_2 (PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | \ | ||
49 | PAD_CTL_PUS_100K_UP) | ||
48 | #define MX51_ECSPI_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_DSE_HIGH | \ | 50 | #define MX51_ECSPI_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_DSE_HIGH | \ |
49 | PAD_CTL_SRE_FAST) | 51 | PAD_CTL_SRE_FAST) |
50 | #define MX51_SDHCI_PAD_CTRL (PAD_CTL_DSE_HIGH | PAD_CTL_PUS_47K_UP | \ | 52 | #define MX51_SDHCI_PAD_CTRL (PAD_CTL_DSE_HIGH | PAD_CTL_PUS_47K_UP | \ |
diff --git a/arch/arm/plat-mxc/include/mach/mx31.h b/arch/arm/plat-mxc/include/mach/mx31.h index 03e2afabc9fc..61cfe827498b 100644 --- a/arch/arm/plat-mxc/include/mach/mx31.h +++ b/arch/arm/plat-mxc/include/mach/mx31.h | |||
@@ -240,7 +240,6 @@ static inline void mx31_setup_weimcs(size_t cs, | |||
240 | #define MPEG4_ENC_BASE_ADDR MX31_MPEG4_ENC_BASE_ADDR | 240 | #define MPEG4_ENC_BASE_ADDR MX31_MPEG4_ENC_BASE_ADDR |
241 | #define MXC_INT_MPEG4_ENCODER MX31_INT_MPEG4_ENCODER | 241 | #define MXC_INT_MPEG4_ENCODER MX31_INT_MPEG4_ENCODER |
242 | #define MXC_INT_FIRI MX31_INT_FIRI | 242 | #define MXC_INT_FIRI MX31_INT_FIRI |
243 | #define MXC_INT_MMC_SDHC1 MX31_INT_MMC_SDHC1 | ||
244 | #define MXC_INT_MBX MX31_INT_MBX | 243 | #define MXC_INT_MBX MX31_INT_MBX |
245 | #define MXC_INT_CSPI3 MX31_INT_CSPI3 | 244 | #define MXC_INT_CSPI3 MX31_INT_CSPI3 |
246 | #define MXC_INT_SIM2 MX31_INT_SIM2 | 245 | #define MXC_INT_SIM2 MX31_INT_SIM2 |
diff --git a/arch/arm/plat-mxc/include/mach/mx35.h b/arch/arm/plat-mxc/include/mach/mx35.h index ff905cb32458..6267cff6035d 100644 --- a/arch/arm/plat-mxc/include/mach/mx35.h +++ b/arch/arm/plat-mxc/include/mach/mx35.h | |||
@@ -197,8 +197,6 @@ | |||
197 | /* these should go away */ | 197 | /* these should go away */ |
198 | #define MXC_FEC_BASE_ADDR MX35_FEC_BASE_ADDR | 198 | #define MXC_FEC_BASE_ADDR MX35_FEC_BASE_ADDR |
199 | #define MXC_INT_OWIRE MX35_INT_OWIRE | 199 | #define MXC_INT_OWIRE MX35_INT_OWIRE |
200 | #define MXC_INT_MMC_SDHC2 MX35_INT_MMC_SDHC2 | ||
201 | #define MXC_INT_MMC_SDHC3 MX35_INT_MMC_SDHC3 | ||
202 | #define MXC_INT_GPU2D MX35_INT_GPU2D | 200 | #define MXC_INT_GPU2D MX35_INT_GPU2D |
203 | #define MXC_INT_ASRC MX35_INT_ASRC | 201 | #define MXC_INT_ASRC MX35_INT_ASRC |
204 | #define MXC_INT_USBHS MX35_INT_USBHS | 202 | #define MXC_INT_USBHS MX35_INT_USBHS |
diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h index a790bf212972..a42c7207082d 100644 --- a/arch/arm/plat-mxc/include/mach/mxc.h +++ b/arch/arm/plat-mxc/include/mach/mxc.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. | 2 | * Copyright 2004-2007, 2010 Freescale Semiconductor, Inc. All Rights Reserved. |
3 | * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de) | 3 | * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de) |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -20,6 +20,8 @@ | |||
20 | #ifndef __ASM_ARCH_MXC_H__ | 20 | #ifndef __ASM_ARCH_MXC_H__ |
21 | #define __ASM_ARCH_MXC_H__ | 21 | #define __ASM_ARCH_MXC_H__ |
22 | 22 | ||
23 | #include <linux/types.h> | ||
24 | |||
23 | #ifndef __ASM_ARCH_MXC_HARDWARE_H__ | 25 | #ifndef __ASM_ARCH_MXC_HARDWARE_H__ |
24 | #error "Do not include directly." | 26 | #error "Do not include directly." |
25 | #endif | 27 | #endif |
@@ -133,6 +135,15 @@ extern unsigned int __mxc_cpu_type; | |||
133 | # define cpu_is_mxc91231() (0) | 135 | # define cpu_is_mxc91231() (0) |
134 | #endif | 136 | #endif |
135 | 137 | ||
138 | #ifndef __ASSEMBLY__ | ||
139 | |||
140 | struct cpu_op { | ||
141 | u32 cpu_rate; | ||
142 | }; | ||
143 | |||
144 | extern struct cpu_op *(*get_cpu_op)(int *op); | ||
145 | #endif | ||
146 | |||
136 | #if defined(CONFIG_ARCH_MX3) || defined(CONFIG_ARCH_MX2) | 147 | #if defined(CONFIG_ARCH_MX3) || defined(CONFIG_ARCH_MX2) |
137 | /* These are deprecated, use mx[23][157]_setup_weimcs instead. */ | 148 | /* These are deprecated, use mx[23][157]_setup_weimcs instead. */ |
138 | #define CSCR_U(n) (IO_ADDRESS(WEIM_BASE_ADDR + n * 0x10)) | 149 | #define CSCR_U(n) (IO_ADDRESS(WEIM_BASE_ADDR + n * 0x10)) |
diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h index 3478eae32d8a..01a8448e471c 100644 --- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h +++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | |||
@@ -30,15 +30,15 @@ struct pxa3xx_nand_cmdset { | |||
30 | }; | 30 | }; |
31 | 31 | ||
32 | struct pxa3xx_nand_flash { | 32 | struct pxa3xx_nand_flash { |
33 | const struct pxa3xx_nand_timing *timing; /* NAND Flash timing */ | 33 | uint32_t chip_id; |
34 | const struct pxa3xx_nand_cmdset *cmdset; | 34 | unsigned int page_per_block; /* Pages per block (PG_PER_BLK) */ |
35 | 35 | unsigned int page_size; /* Page size in bytes (PAGE_SZ) */ | |
36 | uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */ | 36 | unsigned int flash_width; /* Width of Flash memory (DWIDTH_M) */ |
37 | uint32_t page_size; /* Page size in bytes (PAGE_SZ) */ | 37 | unsigned int dfc_width; /* Width of flash controller(DWIDTH_C) */ |
38 | uint32_t flash_width; /* Width of Flash memory (DWIDTH_M) */ | 38 | unsigned int num_blocks; /* Number of physical blocks in Flash */ |
39 | uint32_t dfc_width; /* Width of flash controller(DWIDTH_C) */ | 39 | |
40 | uint32_t num_blocks; /* Number of physical blocks in Flash */ | 40 | struct pxa3xx_nand_cmdset *cmdset; /* NAND command set */ |
41 | uint32_t chip_id; | 41 | struct pxa3xx_nand_timing *timing; /* NAND Flash timing */ |
42 | }; | 42 | }; |
43 | 43 | ||
44 | struct pxa3xx_nand_platform_data { | 44 | struct pxa3xx_nand_platform_data { |
diff --git a/arch/arm/plat-s3c24xx/common-smdk.c b/arch/arm/plat-s3c24xx/common-smdk.c index 7b44d0c592b5..bcc43f346272 100644 --- a/arch/arm/plat-s3c24xx/common-smdk.c +++ b/arch/arm/plat-s3c24xx/common-smdk.c | |||
@@ -147,7 +147,7 @@ static struct mtd_partition smdk_default_nand_part[] = { | |||
147 | [7] = { | 147 | [7] = { |
148 | .name = "S3C2410 flash partition 7", | 148 | .name = "S3C2410 flash partition 7", |
149 | .offset = SZ_1M * 48, | 149 | .offset = SZ_1M * 48, |
150 | .size = SZ_16M, | 150 | .size = MTDPART_SIZ_FULL, |
151 | } | 151 | } |
152 | }; | 152 | }; |
153 | 153 | ||
diff --git a/arch/arm/plat-s3c24xx/gpiolib.c b/arch/arm/plat-s3c24xx/gpiolib.c index ae9d3c2403f0..24c6f5a30596 100644 --- a/arch/arm/plat-s3c24xx/gpiolib.c +++ b/arch/arm/plat-s3c24xx/gpiolib.c | |||
@@ -74,11 +74,6 @@ static int s3c24xx_gpiolib_bankf_toirq(struct gpio_chip *chip, unsigned offset) | |||
74 | return -EINVAL; | 74 | return -EINVAL; |
75 | } | 75 | } |
76 | 76 | ||
77 | static int s3c24xx_gpiolib_bankg_toirq(struct gpio_chip *chip, unsigned offset) | ||
78 | { | ||
79 | return IRQ_EINT8 + offset; | ||
80 | } | ||
81 | |||
82 | static struct s3c_gpio_cfg s3c24xx_gpiocfg_banka = { | 77 | static struct s3c_gpio_cfg s3c24xx_gpiocfg_banka = { |
83 | .set_config = s3c_gpio_setcfg_s3c24xx_a, | 78 | .set_config = s3c_gpio_setcfg_s3c24xx_a, |
84 | .get_config = s3c_gpio_getcfg_s3c24xx_a, | 79 | .get_config = s3c_gpio_getcfg_s3c24xx_a, |
@@ -159,12 +154,13 @@ struct s3c_gpio_chip s3c24xx_gpios[] = { | |||
159 | [6] = { | 154 | [6] = { |
160 | .base = S3C2410_GPGCON, | 155 | .base = S3C2410_GPGCON, |
161 | .pm = __gpio_pm(&s3c_gpio_pm_2bit), | 156 | .pm = __gpio_pm(&s3c_gpio_pm_2bit), |
157 | .irq_base = IRQ_EINT8, | ||
162 | .chip = { | 158 | .chip = { |
163 | .base = S3C2410_GPG(0), | 159 | .base = S3C2410_GPG(0), |
164 | .owner = THIS_MODULE, | 160 | .owner = THIS_MODULE, |
165 | .label = "GPIOG", | 161 | .label = "GPIOG", |
166 | .ngpio = 16, | 162 | .ngpio = 16, |
167 | .to_irq = s3c24xx_gpiolib_bankg_toirq, | 163 | .to_irq = samsung_gpiolib_to_irq, |
168 | }, | 164 | }, |
169 | }, { | 165 | }, { |
170 | .base = S3C2410_GPHCON, | 166 | .base = S3C2410_GPHCON, |
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index 25960966af7c..65dbfa8e0a86 100644 --- a/arch/arm/plat-s5p/Kconfig +++ b/arch/arm/plat-s5p/Kconfig | |||
@@ -32,6 +32,11 @@ config S5P_EXT_INT | |||
32 | Use the external interrupts (other than GPIO interrupts.) | 32 | Use the external interrupts (other than GPIO interrupts.) |
33 | Note: Do not choose this for S5P6440 and S5P6450. | 33 | Note: Do not choose this for S5P6440 and S5P6450. |
34 | 34 | ||
35 | config S5P_GPIO_INT | ||
36 | bool | ||
37 | help | ||
38 | Common code for the GPIO interrupts (other than external interrupts.) | ||
39 | |||
35 | config S5P_DEV_FIMC0 | 40 | config S5P_DEV_FIMC0 |
36 | bool | 41 | bool |
37 | help | 42 | help |
diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile index f3e917e27da8..de65238a7aef 100644 --- a/arch/arm/plat-s5p/Makefile +++ b/arch/arm/plat-s5p/Makefile | |||
@@ -18,6 +18,9 @@ obj-y += cpu.o | |||
18 | obj-y += clock.o | 18 | obj-y += clock.o |
19 | obj-y += irq.o | 19 | obj-y += irq.o |
20 | obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o | 20 | obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o |
21 | obj-$(CONFIG_S5P_GPIO_INT) += irq-gpioint.o | ||
22 | obj-$(CONFIG_PM) += pm.o | ||
23 | obj-$(CONFIG_PM) += irq-pm.o | ||
21 | 24 | ||
22 | # devices | 25 | # devices |
23 | 26 | ||
diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c index 8aaf4e6b60c3..8d081d968c58 100644 --- a/arch/arm/plat-s5p/clock.c +++ b/arch/arm/plat-s5p/clock.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | #include <asm/div64.h> | 22 | #include <asm/div64.h> |
23 | 23 | ||
24 | #include <mach/regs-clock.h> | ||
25 | |||
24 | #include <plat/clock.h> | 26 | #include <plat/clock.h> |
25 | #include <plat/clock-clksrc.h> | 27 | #include <plat/clock-clksrc.h> |
26 | #include <plat/s5p-clock.h> | 28 | #include <plat/s5p-clock.h> |
@@ -88,14 +90,6 @@ struct clk clk_fout_vpll = { | |||
88 | .ctrlbit = (1 << 31), | 90 | .ctrlbit = (1 << 31), |
89 | }; | 91 | }; |
90 | 92 | ||
91 | /* ARM clock */ | ||
92 | struct clk clk_arm = { | ||
93 | .name = "armclk", | ||
94 | .id = -1, | ||
95 | .rate = 0, | ||
96 | .ctrlbit = 0, | ||
97 | }; | ||
98 | |||
99 | /* Possible clock sources for APLL Mux */ | 93 | /* Possible clock sources for APLL Mux */ |
100 | static struct clk *clk_src_apll_list[] = { | 94 | static struct clk *clk_src_apll_list[] = { |
101 | [0] = &clk_fin_apll, | 95 | [0] = &clk_fin_apll, |
@@ -156,6 +150,24 @@ int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable) | |||
156 | return 0; | 150 | return 0; |
157 | } | 151 | } |
158 | 152 | ||
153 | int s5p_epll_enable(struct clk *clk, int enable) | ||
154 | { | ||
155 | unsigned int ctrlbit = clk->ctrlbit; | ||
156 | unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit; | ||
157 | |||
158 | if (enable) | ||
159 | __raw_writel(epll_con | ctrlbit, S5P_EPLL_CON); | ||
160 | else | ||
161 | __raw_writel(epll_con, S5P_EPLL_CON); | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | unsigned long s5p_epll_get_rate(struct clk *clk) | ||
167 | { | ||
168 | return clk->rate; | ||
169 | } | ||
170 | |||
159 | static struct clk *s5p_clks[] __initdata = { | 171 | static struct clk *s5p_clks[] __initdata = { |
160 | &clk_ext_xtal_mux, | 172 | &clk_ext_xtal_mux, |
161 | &clk_48m, | 173 | &clk_48m, |
@@ -165,7 +177,6 @@ static struct clk *s5p_clks[] __initdata = { | |||
165 | &clk_fout_epll, | 177 | &clk_fout_epll, |
166 | &clk_fout_dpll, | 178 | &clk_fout_dpll, |
167 | &clk_fout_vpll, | 179 | &clk_fout_vpll, |
168 | &clk_arm, | ||
169 | &clk_vpll, | 180 | &clk_vpll, |
170 | &clk_xusbxti, | 181 | &clk_xusbxti, |
171 | }; | 182 | }; |
diff --git a/arch/arm/plat-s5p/include/plat/irqs.h b/arch/arm/plat-s5p/include/plat/irqs.h index 3fb3a3a17465..ba9121c60a2a 100644 --- a/arch/arm/plat-s5p/include/plat/irqs.h +++ b/arch/arm/plat-s5p/include/plat/irqs.h | |||
@@ -94,4 +94,22 @@ | |||
94 | ((irq) - S5P_EINT_BASE1) : \ | 94 | ((irq) - S5P_EINT_BASE1) : \ |
95 | ((irq) + 16 - S5P_EINT_BASE2)) | 95 | ((irq) + 16 - S5P_EINT_BASE2)) |
96 | 96 | ||
97 | #define IRQ_EINT_BIT(x) EINT_OFFSET(x) | ||
98 | |||
99 | /* Typically only a few gpio chips require gpio interrupt support. | ||
100 | To avoid memory waste irq descriptors are allocated only for | ||
101 | S5P_GPIOINT_GROUP_COUNT chips, each with total number of | ||
102 | S5P_GPIOINT_GROUP_SIZE pins/irqs. Each GPIOINT group can be assiged | ||
103 | to any gpio chip with the s5p_register_gpio_interrupt() function */ | ||
104 | #define S5P_GPIOINT_GROUP_COUNT 4 | ||
105 | #define S5P_GPIOINT_GROUP_SIZE 8 | ||
106 | #define S5P_GPIOINT_COUNT (S5P_GPIOINT_GROUP_COUNT * S5P_GPIOINT_GROUP_SIZE) | ||
107 | |||
108 | /* IRQ types common for all s5p platforms */ | ||
109 | #define S5P_IRQ_TYPE_LEVEL_LOW (0x00) | ||
110 | #define S5P_IRQ_TYPE_LEVEL_HIGH (0x01) | ||
111 | #define S5P_IRQ_TYPE_EDGE_FALLING (0x02) | ||
112 | #define S5P_IRQ_TYPE_EDGE_RISING (0x03) | ||
113 | #define S5P_IRQ_TYPE_EDGE_BOTH (0x04) | ||
114 | |||
97 | #endif /* __ASM_PLAT_S5P_IRQS_H */ | 115 | #endif /* __ASM_PLAT_S5P_IRQS_H */ |
diff --git a/arch/arm/plat-s5p/include/plat/map-s5p.h b/arch/arm/plat-s5p/include/plat/map-s5p.h index c4ff88bf6477..fef353d44513 100644 --- a/arch/arm/plat-s5p/include/plat/map-s5p.h +++ b/arch/arm/plat-s5p/include/plat/map-s5p.h | |||
@@ -13,24 +13,38 @@ | |||
13 | #ifndef __ASM_PLAT_MAP_S5P_H | 13 | #ifndef __ASM_PLAT_MAP_S5P_H |
14 | #define __ASM_PLAT_MAP_S5P_H __FILE__ | 14 | #define __ASM_PLAT_MAP_S5P_H __FILE__ |
15 | 15 | ||
16 | #define S5P_VA_CHIPID S3C_ADDR(0x00700000) | 16 | #define S5P_VA_CHIPID S3C_ADDR(0x02000000) |
17 | #define S5P_VA_GPIO S3C_ADDR(0x00500000) | 17 | #define S5P_VA_CMU S3C_ADDR(0x02100000) |
18 | #define S5P_VA_SYSTIMER S3C_ADDR(0x01200000) | 18 | #define S5P_VA_GPIO S3C_ADDR(0x02200000) |
19 | #define S5P_VA_SROMC S3C_ADDR(0x01100000) | 19 | #define S5P_VA_GPIO1 S5P_VA_GPIO |
20 | #define S5P_VA_SYSRAM S3C_ADDR(0x01180000) | 20 | #define S5P_VA_GPIO2 S3C_ADDR(0x02240000) |
21 | 21 | #define S5P_VA_GPIO3 S3C_ADDR(0x02280000) | |
22 | #define S5P_VA_COMBINER_BASE S3C_ADDR(0x00600000) | 22 | |
23 | #define S5P_VA_SYSRAM S3C_ADDR(0x02400000) | ||
24 | #define S5P_VA_DMC0 S3C_ADDR(0x02440000) | ||
25 | #define S5P_VA_DMC1 S3C_ADDR(0x02480000) | ||
26 | #define S5P_VA_SROMC S3C_ADDR(0x024C0000) | ||
27 | |||
28 | #define S5P_VA_SYSTIMER S3C_ADDR(0x02500000) | ||
29 | #define S5P_VA_L2CC S3C_ADDR(0x02600000) | ||
30 | |||
31 | #define S5P_VA_COMBINER_BASE S3C_ADDR(0x02700000) | ||
23 | #define S5P_VA_COMBINER(x) (S5P_VA_COMBINER_BASE + ((x) >> 2) * 0x10) | 32 | #define S5P_VA_COMBINER(x) (S5P_VA_COMBINER_BASE + ((x) >> 2) * 0x10) |
24 | 33 | ||
25 | #define S5P_VA_COREPERI_BASE S3C_ADDR(0x00800000) | 34 | #define S5P_VA_COREPERI_BASE S3C_ADDR(0x02800000) |
26 | #define S5P_VA_COREPERI(x) (S5P_VA_COREPERI_BASE + (x)) | 35 | #define S5P_VA_COREPERI(x) (S5P_VA_COREPERI_BASE + (x)) |
27 | #define S5P_VA_SCU S5P_VA_COREPERI(0x0) | 36 | #define S5P_VA_SCU S5P_VA_COREPERI(0x0) |
28 | #define S5P_VA_GIC_CPU S5P_VA_COREPERI(0x100) | 37 | #define S5P_VA_GIC_CPU S5P_VA_COREPERI(0x100) |
29 | #define S5P_VA_TWD S5P_VA_COREPERI(0x600) | 38 | #define S5P_VA_TWD S5P_VA_COREPERI(0x600) |
30 | #define S5P_VA_GIC_DIST S5P_VA_COREPERI(0x1000) | 39 | #define S5P_VA_GIC_DIST S5P_VA_COREPERI(0x1000) |
31 | 40 | ||
32 | #define S5P_VA_L2CC S3C_ADDR(0x00900000) | 41 | #define S3C_VA_USB_HSPHY S3C_ADDR(0x02900000) |
33 | #define S5P_VA_CMU S3C_ADDR(0x00920000) | 42 | |
43 | #define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000)) | ||
44 | #define VA_VIC0 VA_VIC(0) | ||
45 | #define VA_VIC1 VA_VIC(1) | ||
46 | #define VA_VIC2 VA_VIC(2) | ||
47 | #define VA_VIC3 VA_VIC(3) | ||
34 | 48 | ||
35 | #define S5P_VA_UART(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET)) | 49 | #define S5P_VA_UART(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET)) |
36 | #define S5P_VA_UART0 S5P_VA_UART(0) | 50 | #define S5P_VA_UART0 S5P_VA_UART(0) |
@@ -42,10 +56,4 @@ | |||
42 | #define S3C_UART_OFFSET (0x400) | 56 | #define S3C_UART_OFFSET (0x400) |
43 | #endif | 57 | #endif |
44 | 58 | ||
45 | #define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000)) | ||
46 | #define VA_VIC0 VA_VIC(0) | ||
47 | #define VA_VIC1 VA_VIC(1) | ||
48 | #define VA_VIC2 VA_VIC(2) | ||
49 | #define VA_VIC3 VA_VIC(3) | ||
50 | |||
51 | #endif /* __ASM_PLAT_MAP_S5P_H */ | 59 | #endif /* __ASM_PLAT_MAP_S5P_H */ |
diff --git a/arch/arm/plat-s5p/include/plat/s5p-clock.h b/arch/arm/plat-s5p/include/plat/s5p-clock.h index 17036c898409..2b6dcff8ab2b 100644 --- a/arch/arm/plat-s5p/include/plat/s5p-clock.h +++ b/arch/arm/plat-s5p/include/plat/s5p-clock.h | |||
@@ -43,4 +43,8 @@ extern struct clksrc_sources clk_src_dpll; | |||
43 | 43 | ||
44 | extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable); | 44 | extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable); |
45 | 45 | ||
46 | /* Common EPLL operations for S5P platform */ | ||
47 | extern int s5p_epll_enable(struct clk *clk, int enable); | ||
48 | extern unsigned long s5p_epll_get_rate(struct clk *clk); | ||
49 | |||
46 | #endif /* __ASM_PLAT_S5P_CLOCK_H */ | 50 | #endif /* __ASM_PLAT_S5P_CLOCK_H */ |
diff --git a/arch/arm/plat-s5p/irq-eint.c b/arch/arm/plat-s5p/irq-eint.c index f36cd3327025..752f1a645f9d 100644 --- a/arch/arm/plat-s5p/irq-eint.c +++ b/arch/arm/plat-s5p/irq-eint.c | |||
@@ -67,23 +67,23 @@ static int s5p_irq_eint_set_type(unsigned int irq, unsigned int type) | |||
67 | 67 | ||
68 | switch (type) { | 68 | switch (type) { |
69 | case IRQ_TYPE_EDGE_RISING: | 69 | case IRQ_TYPE_EDGE_RISING: |
70 | newvalue = S5P_EXTINT_RISEEDGE; | 70 | newvalue = S5P_IRQ_TYPE_EDGE_RISING; |
71 | break; | 71 | break; |
72 | 72 | ||
73 | case IRQ_TYPE_EDGE_FALLING: | 73 | case IRQ_TYPE_EDGE_FALLING: |
74 | newvalue = S5P_EXTINT_FALLEDGE; | 74 | newvalue = S5P_IRQ_TYPE_EDGE_FALLING; |
75 | break; | 75 | break; |
76 | 76 | ||
77 | case IRQ_TYPE_EDGE_BOTH: | 77 | case IRQ_TYPE_EDGE_BOTH: |
78 | newvalue = S5P_EXTINT_BOTHEDGE; | 78 | newvalue = S5P_IRQ_TYPE_EDGE_BOTH; |
79 | break; | 79 | break; |
80 | 80 | ||
81 | case IRQ_TYPE_LEVEL_LOW: | 81 | case IRQ_TYPE_LEVEL_LOW: |
82 | newvalue = S5P_EXTINT_LOWLEV; | 82 | newvalue = S5P_IRQ_TYPE_LEVEL_LOW; |
83 | break; | 83 | break; |
84 | 84 | ||
85 | case IRQ_TYPE_LEVEL_HIGH: | 85 | case IRQ_TYPE_LEVEL_HIGH: |
86 | newvalue = S5P_EXTINT_HILEV; | 86 | newvalue = S5P_IRQ_TYPE_LEVEL_HIGH; |
87 | break; | 87 | break; |
88 | 88 | ||
89 | default: | 89 | default: |
diff --git a/arch/arm/plat-s5p/irq-gpioint.c b/arch/arm/plat-s5p/irq-gpioint.c new file mode 100644 index 000000000000..0e5dc8cbf5e3 --- /dev/null +++ b/arch/arm/plat-s5p/irq-gpioint.c | |||
@@ -0,0 +1,237 @@ | |||
1 | /* linux/arch/arm/plat-s5p/irq-gpioint.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * Author: Kyungmin Park <kyungmin.park@samsung.com> | ||
5 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
6 | * Author: Marek Szyprowski <m.szyprowski@samsung.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/irq.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/gpio.h> | ||
20 | |||
21 | #include <mach/map.h> | ||
22 | #include <plat/gpio-core.h> | ||
23 | #include <plat/gpio-cfg.h> | ||
24 | |||
25 | #define S5P_GPIOREG(x) (S5P_VA_GPIO + (x)) | ||
26 | |||
27 | #define GPIOINT_CON_OFFSET 0x700 | ||
28 | #define GPIOINT_MASK_OFFSET 0x900 | ||
29 | #define GPIOINT_PEND_OFFSET 0xA00 | ||
30 | |||
31 | static struct s3c_gpio_chip *irq_chips[S5P_GPIOINT_GROUP_MAXNR]; | ||
32 | |||
33 | static int s5p_gpioint_get_group(unsigned int irq) | ||
34 | { | ||
35 | struct gpio_chip *chip = get_irq_data(irq); | ||
36 | struct s3c_gpio_chip *s3c_chip = container_of(chip, | ||
37 | struct s3c_gpio_chip, chip); | ||
38 | int group; | ||
39 | |||
40 | for (group = 0; group < S5P_GPIOINT_GROUP_MAXNR; group++) | ||
41 | if (s3c_chip == irq_chips[group]) | ||
42 | break; | ||
43 | |||
44 | return group; | ||
45 | } | ||
46 | |||
47 | static int s5p_gpioint_get_offset(unsigned int irq) | ||
48 | { | ||
49 | struct gpio_chip *chip = get_irq_data(irq); | ||
50 | struct s3c_gpio_chip *s3c_chip = container_of(chip, | ||
51 | struct s3c_gpio_chip, chip); | ||
52 | |||
53 | return irq - s3c_chip->irq_base; | ||
54 | } | ||
55 | |||
56 | static void s5p_gpioint_ack(unsigned int irq) | ||
57 | { | ||
58 | int group, offset, pend_offset; | ||
59 | unsigned int value; | ||
60 | |||
61 | group = s5p_gpioint_get_group(irq); | ||
62 | offset = s5p_gpioint_get_offset(irq); | ||
63 | pend_offset = group << 2; | ||
64 | |||
65 | value = __raw_readl(S5P_GPIOREG(GPIOINT_PEND_OFFSET) + pend_offset); | ||
66 | value |= 1 << offset; | ||
67 | __raw_writel(value, S5P_GPIOREG(GPIOINT_PEND_OFFSET) + pend_offset); | ||
68 | } | ||
69 | |||
70 | static void s5p_gpioint_mask(unsigned int irq) | ||
71 | { | ||
72 | int group, offset, mask_offset; | ||
73 | unsigned int value; | ||
74 | |||
75 | group = s5p_gpioint_get_group(irq); | ||
76 | offset = s5p_gpioint_get_offset(irq); | ||
77 | mask_offset = group << 2; | ||
78 | |||
79 | value = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset); | ||
80 | value |= 1 << offset; | ||
81 | __raw_writel(value, S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset); | ||
82 | } | ||
83 | |||
84 | static void s5p_gpioint_unmask(unsigned int irq) | ||
85 | { | ||
86 | int group, offset, mask_offset; | ||
87 | unsigned int value; | ||
88 | |||
89 | group = s5p_gpioint_get_group(irq); | ||
90 | offset = s5p_gpioint_get_offset(irq); | ||
91 | mask_offset = group << 2; | ||
92 | |||
93 | value = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset); | ||
94 | value &= ~(1 << offset); | ||
95 | __raw_writel(value, S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset); | ||
96 | } | ||
97 | |||
98 | static void s5p_gpioint_mask_ack(unsigned int irq) | ||
99 | { | ||
100 | s5p_gpioint_mask(irq); | ||
101 | s5p_gpioint_ack(irq); | ||
102 | } | ||
103 | |||
104 | static int s5p_gpioint_set_type(unsigned int irq, unsigned int type) | ||
105 | { | ||
106 | int group, offset, con_offset; | ||
107 | unsigned int value; | ||
108 | |||
109 | group = s5p_gpioint_get_group(irq); | ||
110 | offset = s5p_gpioint_get_offset(irq); | ||
111 | con_offset = group << 2; | ||
112 | |||
113 | switch (type) { | ||
114 | case IRQ_TYPE_EDGE_RISING: | ||
115 | type = S5P_IRQ_TYPE_EDGE_RISING; | ||
116 | break; | ||
117 | case IRQ_TYPE_EDGE_FALLING: | ||
118 | type = S5P_IRQ_TYPE_EDGE_FALLING; | ||
119 | break; | ||
120 | case IRQ_TYPE_EDGE_BOTH: | ||
121 | type = S5P_IRQ_TYPE_EDGE_BOTH; | ||
122 | break; | ||
123 | case IRQ_TYPE_LEVEL_HIGH: | ||
124 | type = S5P_IRQ_TYPE_LEVEL_HIGH; | ||
125 | break; | ||
126 | case IRQ_TYPE_LEVEL_LOW: | ||
127 | type = S5P_IRQ_TYPE_LEVEL_LOW; | ||
128 | break; | ||
129 | case IRQ_TYPE_NONE: | ||
130 | default: | ||
131 | printk(KERN_WARNING "No irq type\n"); | ||
132 | return -EINVAL; | ||
133 | } | ||
134 | |||
135 | value = __raw_readl(S5P_GPIOREG(GPIOINT_CON_OFFSET) + con_offset); | ||
136 | value &= ~(0x7 << (offset * 0x4)); | ||
137 | value |= (type << (offset * 0x4)); | ||
138 | __raw_writel(value, S5P_GPIOREG(GPIOINT_CON_OFFSET) + con_offset); | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | struct irq_chip s5p_gpioint = { | ||
144 | .name = "s5p_gpioint", | ||
145 | .ack = s5p_gpioint_ack, | ||
146 | .mask = s5p_gpioint_mask, | ||
147 | .mask_ack = s5p_gpioint_mask_ack, | ||
148 | .unmask = s5p_gpioint_unmask, | ||
149 | .set_type = s5p_gpioint_set_type, | ||
150 | }; | ||
151 | |||
152 | static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc) | ||
153 | { | ||
154 | int group, offset, pend_offset, mask_offset; | ||
155 | int real_irq; | ||
156 | unsigned int pend, mask; | ||
157 | |||
158 | for (group = 0; group < S5P_GPIOINT_GROUP_MAXNR; group++) { | ||
159 | pend_offset = group << 2; | ||
160 | pend = __raw_readl(S5P_GPIOREG(GPIOINT_PEND_OFFSET) + | ||
161 | pend_offset); | ||
162 | if (!pend) | ||
163 | continue; | ||
164 | |||
165 | mask_offset = group << 2; | ||
166 | mask = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) + | ||
167 | mask_offset); | ||
168 | pend &= ~mask; | ||
169 | |||
170 | for (offset = 0; offset < 8; offset++) { | ||
171 | if (pend & (1 << offset)) { | ||
172 | struct s3c_gpio_chip *chip = irq_chips[group]; | ||
173 | if (chip) { | ||
174 | real_irq = chip->irq_base + offset; | ||
175 | generic_handle_irq(real_irq); | ||
176 | } | ||
177 | } | ||
178 | } | ||
179 | } | ||
180 | } | ||
181 | |||
182 | static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip) | ||
183 | { | ||
184 | static int used_gpioint_groups = 0; | ||
185 | static bool handler_registered = 0; | ||
186 | int irq, group = chip->group; | ||
187 | int i; | ||
188 | |||
189 | if (used_gpioint_groups >= S5P_GPIOINT_GROUP_COUNT) | ||
190 | return -ENOMEM; | ||
191 | |||
192 | chip->irq_base = S5P_GPIOINT_BASE + | ||
193 | used_gpioint_groups * S5P_GPIOINT_GROUP_SIZE; | ||
194 | used_gpioint_groups++; | ||
195 | |||
196 | if (!handler_registered) { | ||
197 | set_irq_chained_handler(IRQ_GPIOINT, s5p_gpioint_handler); | ||
198 | handler_registered = 1; | ||
199 | } | ||
200 | |||
201 | irq_chips[group] = chip; | ||
202 | for (i = 0; i < chip->chip.ngpio; i++) { | ||
203 | irq = chip->irq_base + i; | ||
204 | set_irq_chip(irq, &s5p_gpioint); | ||
205 | set_irq_data(irq, &chip->chip); | ||
206 | set_irq_handler(irq, handle_level_irq); | ||
207 | set_irq_flags(irq, IRQF_VALID); | ||
208 | } | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | int __init s5p_register_gpio_interrupt(int pin) | ||
213 | { | ||
214 | struct s3c_gpio_chip *my_chip = s3c_gpiolib_getchip(pin); | ||
215 | int offset, group; | ||
216 | int ret; | ||
217 | |||
218 | if (!my_chip) | ||
219 | return -EINVAL; | ||
220 | |||
221 | offset = pin - my_chip->chip.base; | ||
222 | group = my_chip->group; | ||
223 | |||
224 | /* check if the group has been already registered */ | ||
225 | if (my_chip->irq_base) | ||
226 | return my_chip->irq_base + offset; | ||
227 | |||
228 | /* register gpio group */ | ||
229 | ret = s5p_gpioint_add(my_chip); | ||
230 | if (ret == 0) { | ||
231 | my_chip->chip.to_irq = samsung_gpiolib_to_irq; | ||
232 | printk(KERN_INFO "Registered interrupt support for gpio group %d.\n", | ||
233 | group); | ||
234 | return my_chip->irq_base + offset; | ||
235 | } | ||
236 | return ret; | ||
237 | } | ||
diff --git a/arch/arm/plat-s5p/irq-pm.c b/arch/arm/plat-s5p/irq-pm.c new file mode 100644 index 000000000000..dc33b9ecda45 --- /dev/null +++ b/arch/arm/plat-s5p/irq-pm.c | |||
@@ -0,0 +1,93 @@ | |||
1 | /* linux/arch/arm/plat-s5p/irq-pm.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * Based on arch/arm/plat-s3c24xx/irq-pm.c, | ||
7 | * Copyright (c) 2003,2004 Simtec Electronics | ||
8 | * Ben Dooks <ben@simtec.co.uk> | ||
9 | * http://armlinux.simtec.co.uk/ | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/init.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/sysdev.h> | ||
20 | |||
21 | #include <plat/cpu.h> | ||
22 | #include <plat/irqs.h> | ||
23 | #include <plat/pm.h> | ||
24 | #include <mach/map.h> | ||
25 | |||
26 | #include <mach/regs-gpio.h> | ||
27 | #include <mach/regs-irq.h> | ||
28 | |||
29 | /* state for IRQs over sleep */ | ||
30 | |||
31 | /* default is to allow for EINT0..EINT31, and IRQ_RTC_TIC, IRQ_RTC_ALARM, | ||
32 | * as wakeup sources | ||
33 | * | ||
34 | * set bit to 1 in allow bitfield to enable the wakeup settings on it | ||
35 | */ | ||
36 | |||
37 | unsigned long s3c_irqwake_intallow = 0x00000006L; | ||
38 | unsigned long s3c_irqwake_eintallow = 0xffffffffL; | ||
39 | |||
40 | int s3c_irq_wake(unsigned int irqno, unsigned int state) | ||
41 | { | ||
42 | unsigned long irqbit; | ||
43 | |||
44 | switch (irqno) { | ||
45 | case IRQ_RTC_TIC: | ||
46 | case IRQ_RTC_ALARM: | ||
47 | irqbit = 1 << (irqno + 1 - IRQ_RTC_ALARM); | ||
48 | if (!state) | ||
49 | s3c_irqwake_intmask |= irqbit; | ||
50 | else | ||
51 | s3c_irqwake_intmask &= ~irqbit; | ||
52 | break; | ||
53 | default: | ||
54 | return -ENOENT; | ||
55 | } | ||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | static struct sleep_save eint_save[] = { | ||
60 | SAVE_ITEM(S5P_EINT_CON(0)), | ||
61 | SAVE_ITEM(S5P_EINT_CON(1)), | ||
62 | SAVE_ITEM(S5P_EINT_CON(2)), | ||
63 | SAVE_ITEM(S5P_EINT_CON(3)), | ||
64 | |||
65 | SAVE_ITEM(S5P_EINT_FLTCON(0)), | ||
66 | SAVE_ITEM(S5P_EINT_FLTCON(1)), | ||
67 | SAVE_ITEM(S5P_EINT_FLTCON(2)), | ||
68 | SAVE_ITEM(S5P_EINT_FLTCON(3)), | ||
69 | SAVE_ITEM(S5P_EINT_FLTCON(4)), | ||
70 | SAVE_ITEM(S5P_EINT_FLTCON(5)), | ||
71 | SAVE_ITEM(S5P_EINT_FLTCON(6)), | ||
72 | SAVE_ITEM(S5P_EINT_FLTCON(7)), | ||
73 | |||
74 | SAVE_ITEM(S5P_EINT_MASK(0)), | ||
75 | SAVE_ITEM(S5P_EINT_MASK(1)), | ||
76 | SAVE_ITEM(S5P_EINT_MASK(2)), | ||
77 | SAVE_ITEM(S5P_EINT_MASK(3)), | ||
78 | }; | ||
79 | |||
80 | int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state) | ||
81 | { | ||
82 | s3c_pm_do_save(eint_save, ARRAY_SIZE(eint_save)); | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | int s3c24xx_irq_resume(struct sys_device *dev) | ||
88 | { | ||
89 | s3c_pm_do_restore(eint_save, ARRAY_SIZE(eint_save)); | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
diff --git a/arch/arm/plat-s5p/pm.c b/arch/arm/plat-s5p/pm.c new file mode 100644 index 000000000000..d592b6304b48 --- /dev/null +++ b/arch/arm/plat-s5p/pm.c | |||
@@ -0,0 +1,52 @@ | |||
1 | /* linux/arch/arm/plat-s5p/pm.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * S5P Power Manager (Suspend-To-RAM) support | ||
7 | * | ||
8 | * Based on arch/arm/plat-s3c24xx/pm.c | ||
9 | * Copyright (c) 2004,2006 Simtec Electronics | ||
10 | * Ben Dooks <ben@simtec.co.uk> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | */ | ||
16 | |||
17 | #include <linux/suspend.h> | ||
18 | #include <plat/pm.h> | ||
19 | |||
20 | #define PFX "s5p pm: " | ||
21 | |||
22 | /* s3c_pm_check_resume_pin | ||
23 | * | ||
24 | * check to see if the pin is configured correctly for sleep mode, and | ||
25 | * make any necessary adjustments if it is not | ||
26 | */ | ||
27 | |||
28 | static void s3c_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs) | ||
29 | { | ||
30 | /* nothing here yet */ | ||
31 | } | ||
32 | |||
33 | /* s3c_pm_configure_extint | ||
34 | * | ||
35 | * configure all external interrupt pins | ||
36 | */ | ||
37 | |||
38 | void s3c_pm_configure_extint(void) | ||
39 | { | ||
40 | /* nothing here yet */ | ||
41 | } | ||
42 | |||
43 | void s3c_pm_restore_core(void) | ||
44 | { | ||
45 | /* nothing here yet */ | ||
46 | } | ||
47 | |||
48 | void s3c_pm_save_core(void) | ||
49 | { | ||
50 | /* nothing here yet */ | ||
51 | } | ||
52 | |||
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index 7c0bde781167..dcd6eff4ee53 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig | |||
@@ -180,6 +180,31 @@ config S3C_DEV_I2C2 | |||
180 | help | 180 | help |
181 | Compile in platform device definitions for I2C channel 2 | 181 | Compile in platform device definitions for I2C channel 2 |
182 | 182 | ||
183 | config S3C_DEV_I2C3 | ||
184 | bool | ||
185 | help | ||
186 | Compile in platform device definition for I2C controller 3 | ||
187 | |||
188 | config S3C_DEV_I2C4 | ||
189 | bool | ||
190 | help | ||
191 | Compile in platform device definition for I2C controller 4 | ||
192 | |||
193 | config S3C_DEV_I2C5 | ||
194 | bool | ||
195 | help | ||
196 | Compile in platform device definition for I2C controller 5 | ||
197 | |||
198 | config S3C_DEV_I2C6 | ||
199 | bool | ||
200 | help | ||
201 | Compile in platform device definition for I2C controller 6 | ||
202 | |||
203 | config S3C_DEV_I2C7 | ||
204 | bool | ||
205 | help | ||
206 | Compile in platform device definition for I2C controller 7 | ||
207 | |||
183 | config S3C_DEV_FB | 208 | config S3C_DEV_FB |
184 | bool | 209 | bool |
185 | help | 210 | help |
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 4d8ff923207a..afcce474af8e 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile | |||
@@ -40,6 +40,11 @@ obj-$(CONFIG_S3C_DEV_HWMON) += dev-hwmon.o | |||
40 | obj-y += dev-i2c0.o | 40 | obj-y += dev-i2c0.o |
41 | obj-$(CONFIG_S3C_DEV_I2C1) += dev-i2c1.o | 41 | obj-$(CONFIG_S3C_DEV_I2C1) += dev-i2c1.o |
42 | obj-$(CONFIG_S3C_DEV_I2C2) += dev-i2c2.o | 42 | obj-$(CONFIG_S3C_DEV_I2C2) += dev-i2c2.o |
43 | obj-$(CONFIG_S3C_DEV_I2C3) += dev-i2c3.o | ||
44 | obj-$(CONFIG_S3C_DEV_I2C4) += dev-i2c4.o | ||
45 | obj-$(CONFIG_S3C_DEV_I2C5) += dev-i2c5.o | ||
46 | obj-$(CONFIG_S3C_DEV_I2C6) += dev-i2c6.o | ||
47 | obj-$(CONFIG_S3C_DEV_I2C7) += dev-i2c7.o | ||
43 | obj-$(CONFIG_S3C_DEV_FB) += dev-fb.o | 48 | obj-$(CONFIG_S3C_DEV_FB) += dev-fb.o |
44 | obj-y += dev-uart.o | 49 | obj-y += dev-uart.o |
45 | obj-$(CONFIG_S3C_DEV_USB_HOST) += dev-usb.o | 50 | obj-$(CONFIG_S3C_DEV_USB_HOST) += dev-usb.o |
diff --git a/arch/arm/plat-samsung/dev-hsmmc.c b/arch/arm/plat-samsung/dev-hsmmc.c index 9d2be0941410..db7a65c7f127 100644 --- a/arch/arm/plat-samsung/dev-hsmmc.c +++ b/arch/arm/plat-samsung/dev-hsmmc.c | |||
@@ -41,6 +41,7 @@ struct s3c_sdhci_platdata s3c_hsmmc0_def_platdata = { | |||
41 | .max_width = 4, | 41 | .max_width = 4, |
42 | .host_caps = (MMC_CAP_4_BIT_DATA | | 42 | .host_caps = (MMC_CAP_4_BIT_DATA | |
43 | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), | 43 | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), |
44 | .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL, | ||
44 | }; | 45 | }; |
45 | 46 | ||
46 | struct platform_device s3c_device_hsmmc0 = { | 47 | struct platform_device s3c_device_hsmmc0 = { |
@@ -59,17 +60,20 @@ void s3c_sdhci0_set_platdata(struct s3c_sdhci_platdata *pd) | |||
59 | { | 60 | { |
60 | struct s3c_sdhci_platdata *set = &s3c_hsmmc0_def_platdata; | 61 | struct s3c_sdhci_platdata *set = &s3c_hsmmc0_def_platdata; |
61 | 62 | ||
62 | set->max_width = pd->max_width; | ||
63 | set->cd_type = pd->cd_type; | 63 | set->cd_type = pd->cd_type; |
64 | set->ext_cd_init = pd->ext_cd_init; | 64 | set->ext_cd_init = pd->ext_cd_init; |
65 | set->ext_cd_cleanup = pd->ext_cd_cleanup; | 65 | set->ext_cd_cleanup = pd->ext_cd_cleanup; |
66 | set->ext_cd_gpio = pd->ext_cd_gpio; | 66 | set->ext_cd_gpio = pd->ext_cd_gpio; |
67 | set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert; | 67 | set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert; |
68 | 68 | ||
69 | if (pd->max_width) | ||
70 | set->max_width = pd->max_width; | ||
69 | if (pd->cfg_gpio) | 71 | if (pd->cfg_gpio) |
70 | set->cfg_gpio = pd->cfg_gpio; | 72 | set->cfg_gpio = pd->cfg_gpio; |
71 | if (pd->cfg_card) | 73 | if (pd->cfg_card) |
72 | set->cfg_card = pd->cfg_card; | 74 | set->cfg_card = pd->cfg_card; |
73 | if (pd->host_caps) | 75 | if (pd->host_caps) |
74 | set->host_caps = pd->host_caps; | 76 | set->host_caps |= pd->host_caps; |
77 | if (pd->clk_type) | ||
78 | set->clk_type = pd->clk_type; | ||
75 | } | 79 | } |
diff --git a/arch/arm/plat-samsung/dev-hsmmc1.c b/arch/arm/plat-samsung/dev-hsmmc1.c index a6c8295840af..2497321f08d7 100644 --- a/arch/arm/plat-samsung/dev-hsmmc1.c +++ b/arch/arm/plat-samsung/dev-hsmmc1.c | |||
@@ -41,6 +41,7 @@ struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata = { | |||
41 | .max_width = 4, | 41 | .max_width = 4, |
42 | .host_caps = (MMC_CAP_4_BIT_DATA | | 42 | .host_caps = (MMC_CAP_4_BIT_DATA | |
43 | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), | 43 | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), |
44 | .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL, | ||
44 | }; | 45 | }; |
45 | 46 | ||
46 | struct platform_device s3c_device_hsmmc1 = { | 47 | struct platform_device s3c_device_hsmmc1 = { |
@@ -59,17 +60,20 @@ void s3c_sdhci1_set_platdata(struct s3c_sdhci_platdata *pd) | |||
59 | { | 60 | { |
60 | struct s3c_sdhci_platdata *set = &s3c_hsmmc1_def_platdata; | 61 | struct s3c_sdhci_platdata *set = &s3c_hsmmc1_def_platdata; |
61 | 62 | ||
62 | set->max_width = pd->max_width; | ||
63 | set->cd_type = pd->cd_type; | 63 | set->cd_type = pd->cd_type; |
64 | set->ext_cd_init = pd->ext_cd_init; | 64 | set->ext_cd_init = pd->ext_cd_init; |
65 | set->ext_cd_cleanup = pd->ext_cd_cleanup; | 65 | set->ext_cd_cleanup = pd->ext_cd_cleanup; |
66 | set->ext_cd_gpio = pd->ext_cd_gpio; | 66 | set->ext_cd_gpio = pd->ext_cd_gpio; |
67 | set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert; | 67 | set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert; |
68 | 68 | ||
69 | if (pd->max_width) | ||
70 | set->max_width = pd->max_width; | ||
69 | if (pd->cfg_gpio) | 71 | if (pd->cfg_gpio) |
70 | set->cfg_gpio = pd->cfg_gpio; | 72 | set->cfg_gpio = pd->cfg_gpio; |
71 | if (pd->cfg_card) | 73 | if (pd->cfg_card) |
72 | set->cfg_card = pd->cfg_card; | 74 | set->cfg_card = pd->cfg_card; |
73 | if (pd->host_caps) | 75 | if (pd->host_caps) |
74 | set->host_caps = pd->host_caps; | 76 | set->host_caps |= pd->host_caps; |
77 | if (pd->clk_type) | ||
78 | set->clk_type = pd->clk_type; | ||
75 | } | 79 | } |
diff --git a/arch/arm/plat-samsung/dev-hsmmc2.c b/arch/arm/plat-samsung/dev-hsmmc2.c index cb0d7143381a..f60aedba417c 100644 --- a/arch/arm/plat-samsung/dev-hsmmc2.c +++ b/arch/arm/plat-samsung/dev-hsmmc2.c | |||
@@ -42,6 +42,7 @@ struct s3c_sdhci_platdata s3c_hsmmc2_def_platdata = { | |||
42 | .max_width = 4, | 42 | .max_width = 4, |
43 | .host_caps = (MMC_CAP_4_BIT_DATA | | 43 | .host_caps = (MMC_CAP_4_BIT_DATA | |
44 | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), | 44 | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), |
45 | .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL, | ||
45 | }; | 46 | }; |
46 | 47 | ||
47 | struct platform_device s3c_device_hsmmc2 = { | 48 | struct platform_device s3c_device_hsmmc2 = { |
@@ -60,17 +61,20 @@ void s3c_sdhci2_set_platdata(struct s3c_sdhci_platdata *pd) | |||
60 | { | 61 | { |
61 | struct s3c_sdhci_platdata *set = &s3c_hsmmc2_def_platdata; | 62 | struct s3c_sdhci_platdata *set = &s3c_hsmmc2_def_platdata; |
62 | 63 | ||
63 | set->max_width = pd->max_width; | ||
64 | set->cd_type = pd->cd_type; | 64 | set->cd_type = pd->cd_type; |
65 | set->ext_cd_init = pd->ext_cd_init; | 65 | set->ext_cd_init = pd->ext_cd_init; |
66 | set->ext_cd_cleanup = pd->ext_cd_cleanup; | 66 | set->ext_cd_cleanup = pd->ext_cd_cleanup; |
67 | set->ext_cd_gpio = pd->ext_cd_gpio; | 67 | set->ext_cd_gpio = pd->ext_cd_gpio; |
68 | set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert; | 68 | set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert; |
69 | 69 | ||
70 | if (pd->max_width) | ||
71 | set->max_width = pd->max_width; | ||
70 | if (pd->cfg_gpio) | 72 | if (pd->cfg_gpio) |
71 | set->cfg_gpio = pd->cfg_gpio; | 73 | set->cfg_gpio = pd->cfg_gpio; |
72 | if (pd->cfg_card) | 74 | if (pd->cfg_card) |
73 | set->cfg_card = pd->cfg_card; | 75 | set->cfg_card = pd->cfg_card; |
74 | if (pd->host_caps) | 76 | if (pd->host_caps) |
75 | set->host_caps = pd->host_caps; | 77 | set->host_caps |= pd->host_caps; |
78 | if (pd->clk_type) | ||
79 | set->clk_type = pd->clk_type; | ||
76 | } | 80 | } |
diff --git a/arch/arm/plat-samsung/dev-hsmmc3.c b/arch/arm/plat-samsung/dev-hsmmc3.c index 85aaf0f2842f..ede776f20e62 100644 --- a/arch/arm/plat-samsung/dev-hsmmc3.c +++ b/arch/arm/plat-samsung/dev-hsmmc3.c | |||
@@ -33,8 +33,8 @@ static struct resource s3c_hsmmc3_resource[] = { | |||
33 | .flags = IORESOURCE_MEM, | 33 | .flags = IORESOURCE_MEM, |
34 | }, | 34 | }, |
35 | [1] = { | 35 | [1] = { |
36 | .start = IRQ_MMC3, | 36 | .start = IRQ_HSMMC3, |
37 | .end = IRQ_MMC3, | 37 | .end = IRQ_HSMMC3, |
38 | .flags = IORESOURCE_IRQ, | 38 | .flags = IORESOURCE_IRQ, |
39 | } | 39 | } |
40 | }; | 40 | }; |
@@ -45,6 +45,7 @@ struct s3c_sdhci_platdata s3c_hsmmc3_def_platdata = { | |||
45 | .max_width = 4, | 45 | .max_width = 4, |
46 | .host_caps = (MMC_CAP_4_BIT_DATA | | 46 | .host_caps = (MMC_CAP_4_BIT_DATA | |
47 | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), | 47 | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), |
48 | .clk_type = S3C_SDHCI_CLK_DIV_INTERNAL, | ||
48 | }; | 49 | }; |
49 | 50 | ||
50 | struct platform_device s3c_device_hsmmc3 = { | 51 | struct platform_device s3c_device_hsmmc3 = { |
@@ -63,15 +64,20 @@ void s3c_sdhci3_set_platdata(struct s3c_sdhci_platdata *pd) | |||
63 | { | 64 | { |
64 | struct s3c_sdhci_platdata *set = &s3c_hsmmc3_def_platdata; | 65 | struct s3c_sdhci_platdata *set = &s3c_hsmmc3_def_platdata; |
65 | 66 | ||
66 | set->max_width = pd->max_width; | ||
67 | set->cd_type = pd->cd_type; | 67 | set->cd_type = pd->cd_type; |
68 | set->ext_cd_init = pd->ext_cd_init; | 68 | set->ext_cd_init = pd->ext_cd_init; |
69 | set->ext_cd_cleanup = pd->ext_cd_cleanup; | 69 | set->ext_cd_cleanup = pd->ext_cd_cleanup; |
70 | set->ext_cd_gpio = pd->ext_cd_gpio; | 70 | set->ext_cd_gpio = pd->ext_cd_gpio; |
71 | set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert; | 71 | set->ext_cd_gpio_invert = pd->ext_cd_gpio_invert; |
72 | 72 | ||
73 | if (pd->max_width) | ||
74 | set->max_width = pd->max_width; | ||
73 | if (pd->cfg_gpio) | 75 | if (pd->cfg_gpio) |
74 | set->cfg_gpio = pd->cfg_gpio; | 76 | set->cfg_gpio = pd->cfg_gpio; |
75 | if (pd->cfg_card) | 77 | if (pd->cfg_card) |
76 | set->cfg_card = pd->cfg_card; | 78 | set->cfg_card = pd->cfg_card; |
79 | if (pd->host_caps) | ||
80 | set->host_caps |= pd->host_caps; | ||
81 | if (pd->clk_type) | ||
82 | set->clk_type = pd->clk_type; | ||
77 | } | 83 | } |
diff --git a/arch/arm/plat-samsung/dev-i2c2.c b/arch/arm/plat-samsung/dev-i2c2.c index 07036dee09e7..ff4ba69b6830 100644 --- a/arch/arm/plat-samsung/dev-i2c2.c +++ b/arch/arm/plat-samsung/dev-i2c2.c | |||
@@ -32,8 +32,8 @@ static struct resource s3c_i2c_resource[] = { | |||
32 | .flags = IORESOURCE_MEM, | 32 | .flags = IORESOURCE_MEM, |
33 | }, | 33 | }, |
34 | [1] = { | 34 | [1] = { |
35 | .start = IRQ_CAN0, | 35 | .start = IRQ_IIC2, |
36 | .end = IRQ_CAN0, | 36 | .end = IRQ_IIC2, |
37 | .flags = IORESOURCE_IRQ, | 37 | .flags = IORESOURCE_IRQ, |
38 | }, | 38 | }, |
39 | }; | 39 | }; |
diff --git a/arch/arm/plat-samsung/dev-i2c3.c b/arch/arm/plat-samsung/dev-i2c3.c new file mode 100644 index 000000000000..8586a10014b7 --- /dev/null +++ b/arch/arm/plat-samsung/dev-i2c3.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* linux/arch/arm/plat-samsung/dev-i2c3.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
6 | * S5P series device definition for i2c device 3 | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/gfp.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | |||
18 | #include <mach/irqs.h> | ||
19 | #include <mach/map.h> | ||
20 | |||
21 | #include <plat/regs-iic.h> | ||
22 | #include <plat/iic.h> | ||
23 | #include <plat/devs.h> | ||
24 | #include <plat/cpu.h> | ||
25 | |||
26 | static struct resource s3c_i2c_resource[] = { | ||
27 | [0] = { | ||
28 | .start = S3C_PA_IIC3, | ||
29 | .end = S3C_PA_IIC3 + SZ_4K - 1, | ||
30 | .flags = IORESOURCE_MEM, | ||
31 | }, | ||
32 | [1] = { | ||
33 | .start = IRQ_IIC3, | ||
34 | .end = IRQ_IIC3, | ||
35 | .flags = IORESOURCE_IRQ, | ||
36 | }, | ||
37 | }; | ||
38 | |||
39 | struct platform_device s3c_device_i2c3 = { | ||
40 | .name = "s3c2440-i2c", | ||
41 | .id = 3, | ||
42 | .num_resources = ARRAY_SIZE(s3c_i2c_resource), | ||
43 | .resource = s3c_i2c_resource, | ||
44 | }; | ||
45 | |||
46 | static struct s3c2410_platform_i2c default_i2c_data3 __initdata = { | ||
47 | .flags = 0, | ||
48 | .bus_num = 3, | ||
49 | .slave_addr = 0x10, | ||
50 | .frequency = 100*1000, | ||
51 | .sda_delay = 100, | ||
52 | }; | ||
53 | |||
54 | void __init s3c_i2c3_set_platdata(struct s3c2410_platform_i2c *pd) | ||
55 | { | ||
56 | struct s3c2410_platform_i2c *npd; | ||
57 | |||
58 | if (!pd) | ||
59 | pd = &default_i2c_data3; | ||
60 | |||
61 | npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); | ||
62 | if (!npd) | ||
63 | printk(KERN_ERR "%s: no memory for platform data\n", __func__); | ||
64 | else if (!npd->cfg_gpio) | ||
65 | npd->cfg_gpio = s3c_i2c3_cfg_gpio; | ||
66 | |||
67 | s3c_device_i2c3.dev.platform_data = npd; | ||
68 | } | ||
diff --git a/arch/arm/plat-samsung/dev-i2c4.c b/arch/arm/plat-samsung/dev-i2c4.c new file mode 100644 index 000000000000..df2159e2daa6 --- /dev/null +++ b/arch/arm/plat-samsung/dev-i2c4.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* linux/arch/arm/plat-samsung/dev-i2c4.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
6 | * S5P series device definition for i2c device 3 | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/gfp.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | |||
18 | #include <mach/irqs.h> | ||
19 | #include <mach/map.h> | ||
20 | |||
21 | #include <plat/regs-iic.h> | ||
22 | #include <plat/iic.h> | ||
23 | #include <plat/devs.h> | ||
24 | #include <plat/cpu.h> | ||
25 | |||
26 | static struct resource s3c_i2c_resource[] = { | ||
27 | [0] = { | ||
28 | .start = S3C_PA_IIC4, | ||
29 | .end = S3C_PA_IIC4 + SZ_4K - 1, | ||
30 | .flags = IORESOURCE_MEM, | ||
31 | }, | ||
32 | [1] = { | ||
33 | .start = IRQ_IIC4, | ||
34 | .end = IRQ_IIC4, | ||
35 | .flags = IORESOURCE_IRQ, | ||
36 | }, | ||
37 | }; | ||
38 | |||
39 | struct platform_device s3c_device_i2c4 = { | ||
40 | .name = "s3c2440-i2c", | ||
41 | .id = 4, | ||
42 | .num_resources = ARRAY_SIZE(s3c_i2c_resource), | ||
43 | .resource = s3c_i2c_resource, | ||
44 | }; | ||
45 | |||
46 | static struct s3c2410_platform_i2c default_i2c_data4 __initdata = { | ||
47 | .flags = 0, | ||
48 | .bus_num = 4, | ||
49 | .slave_addr = 0x10, | ||
50 | .frequency = 100*1000, | ||
51 | .sda_delay = 100, | ||
52 | }; | ||
53 | |||
54 | void __init s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *pd) | ||
55 | { | ||
56 | struct s3c2410_platform_i2c *npd; | ||
57 | |||
58 | if (!pd) | ||
59 | pd = &default_i2c_data4; | ||
60 | |||
61 | npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); | ||
62 | if (!npd) | ||
63 | printk(KERN_ERR "%s: no memory for platform data\n", __func__); | ||
64 | else if (!npd->cfg_gpio) | ||
65 | npd->cfg_gpio = s3c_i2c4_cfg_gpio; | ||
66 | |||
67 | s3c_device_i2c4.dev.platform_data = npd; | ||
68 | } | ||
diff --git a/arch/arm/plat-samsung/dev-i2c5.c b/arch/arm/plat-samsung/dev-i2c5.c new file mode 100644 index 000000000000..0499c2c3877b --- /dev/null +++ b/arch/arm/plat-samsung/dev-i2c5.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* linux/arch/arm/plat-samsung/dev-i2c3.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
6 | * S5P series device definition for i2c device 3 | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/gfp.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | |||
18 | #include <mach/irqs.h> | ||
19 | #include <mach/map.h> | ||
20 | |||
21 | #include <plat/regs-iic.h> | ||
22 | #include <plat/iic.h> | ||
23 | #include <plat/devs.h> | ||
24 | #include <plat/cpu.h> | ||
25 | |||
26 | static struct resource s3c_i2c_resource[] = { | ||
27 | [0] = { | ||
28 | .start = S3C_PA_IIC5, | ||
29 | .end = S3C_PA_IIC5 + SZ_4K - 1, | ||
30 | .flags = IORESOURCE_MEM, | ||
31 | }, | ||
32 | [1] = { | ||
33 | .start = IRQ_IIC5, | ||
34 | .end = IRQ_IIC5, | ||
35 | .flags = IORESOURCE_IRQ, | ||
36 | }, | ||
37 | }; | ||
38 | |||
39 | struct platform_device s3c_device_i2c5 = { | ||
40 | .name = "s3c2440-i2c", | ||
41 | .id = 5, | ||
42 | .num_resources = ARRAY_SIZE(s3c_i2c_resource), | ||
43 | .resource = s3c_i2c_resource, | ||
44 | }; | ||
45 | |||
46 | static struct s3c2410_platform_i2c default_i2c_data5 __initdata = { | ||
47 | .flags = 0, | ||
48 | .bus_num = 5, | ||
49 | .slave_addr = 0x10, | ||
50 | .frequency = 100*1000, | ||
51 | .sda_delay = 100, | ||
52 | }; | ||
53 | |||
54 | void __init s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *pd) | ||
55 | { | ||
56 | struct s3c2410_platform_i2c *npd; | ||
57 | |||
58 | if (!pd) | ||
59 | pd = &default_i2c_data5; | ||
60 | |||
61 | npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); | ||
62 | if (!npd) | ||
63 | printk(KERN_ERR "%s: no memory for platform data\n", __func__); | ||
64 | else if (!npd->cfg_gpio) | ||
65 | npd->cfg_gpio = s3c_i2c5_cfg_gpio; | ||
66 | |||
67 | s3c_device_i2c5.dev.platform_data = npd; | ||
68 | } | ||
diff --git a/arch/arm/plat-samsung/dev-i2c6.c b/arch/arm/plat-samsung/dev-i2c6.c new file mode 100644 index 000000000000..4083108908a8 --- /dev/null +++ b/arch/arm/plat-samsung/dev-i2c6.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* linux/arch/arm/plat-samsung/dev-i2c6.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
6 | * S5P series device definition for i2c device 6 | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/gfp.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | |||
18 | #include <mach/irqs.h> | ||
19 | #include <mach/map.h> | ||
20 | |||
21 | #include <plat/regs-iic.h> | ||
22 | #include <plat/iic.h> | ||
23 | #include <plat/devs.h> | ||
24 | #include <plat/cpu.h> | ||
25 | |||
26 | static struct resource s3c_i2c_resource[] = { | ||
27 | [0] = { | ||
28 | .start = S3C_PA_IIC6, | ||
29 | .end = S3C_PA_IIC6 + SZ_4K - 1, | ||
30 | .flags = IORESOURCE_MEM, | ||
31 | }, | ||
32 | [1] = { | ||
33 | .start = IRQ_IIC6, | ||
34 | .end = IRQ_IIC6, | ||
35 | .flags = IORESOURCE_IRQ, | ||
36 | }, | ||
37 | }; | ||
38 | |||
39 | struct platform_device s3c_device_i2c6 = { | ||
40 | .name = "s3c2440-i2c", | ||
41 | .id = 6, | ||
42 | .num_resources = ARRAY_SIZE(s3c_i2c_resource), | ||
43 | .resource = s3c_i2c_resource, | ||
44 | }; | ||
45 | |||
46 | static struct s3c2410_platform_i2c default_i2c_data6 __initdata = { | ||
47 | .flags = 0, | ||
48 | .bus_num = 6, | ||
49 | .slave_addr = 0x10, | ||
50 | .frequency = 100*1000, | ||
51 | .sda_delay = 100, | ||
52 | }; | ||
53 | |||
54 | void __init s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *pd) | ||
55 | { | ||
56 | struct s3c2410_platform_i2c *npd; | ||
57 | |||
58 | if (!pd) | ||
59 | pd = &default_i2c_data6; | ||
60 | |||
61 | npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); | ||
62 | if (!npd) | ||
63 | printk(KERN_ERR "%s: no memory for platform data\n", __func__); | ||
64 | else if (!npd->cfg_gpio) | ||
65 | npd->cfg_gpio = s3c_i2c6_cfg_gpio; | ||
66 | |||
67 | s3c_device_i2c6.dev.platform_data = npd; | ||
68 | } | ||
diff --git a/arch/arm/plat-samsung/dev-i2c7.c b/arch/arm/plat-samsung/dev-i2c7.c new file mode 100644 index 000000000000..1182451d7dce --- /dev/null +++ b/arch/arm/plat-samsung/dev-i2c7.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* linux/arch/arm/plat-samsung/dev-i2c7.c | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
6 | * S5P series device definition for i2c device 7 | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/gfp.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | |||
18 | #include <mach/irqs.h> | ||
19 | #include <mach/map.h> | ||
20 | |||
21 | #include <plat/regs-iic.h> | ||
22 | #include <plat/iic.h> | ||
23 | #include <plat/devs.h> | ||
24 | #include <plat/cpu.h> | ||
25 | |||
26 | static struct resource s3c_i2c_resource[] = { | ||
27 | [0] = { | ||
28 | .start = S3C_PA_IIC7, | ||
29 | .end = S3C_PA_IIC7 + SZ_4K - 1, | ||
30 | .flags = IORESOURCE_MEM, | ||
31 | }, | ||
32 | [1] = { | ||
33 | .start = IRQ_IIC7, | ||
34 | .end = IRQ_IIC7, | ||
35 | .flags = IORESOURCE_IRQ, | ||
36 | }, | ||
37 | }; | ||
38 | |||
39 | struct platform_device s3c_device_i2c7 = { | ||
40 | .name = "s3c2440-i2c", | ||
41 | .id = 7, | ||
42 | .num_resources = ARRAY_SIZE(s3c_i2c_resource), | ||
43 | .resource = s3c_i2c_resource, | ||
44 | }; | ||
45 | |||
46 | static struct s3c2410_platform_i2c default_i2c_data7 __initdata = { | ||
47 | .flags = 0, | ||
48 | .bus_num = 7, | ||
49 | .slave_addr = 0x10, | ||
50 | .frequency = 100*1000, | ||
51 | .sda_delay = 100, | ||
52 | }; | ||
53 | |||
54 | void __init s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *pd) | ||
55 | { | ||
56 | struct s3c2410_platform_i2c *npd; | ||
57 | |||
58 | if (!pd) | ||
59 | pd = &default_i2c_data7; | ||
60 | |||
61 | npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); | ||
62 | if (!npd) | ||
63 | printk(KERN_ERR "%s: no memory for platform data\n", __func__); | ||
64 | else if (!npd->cfg_gpio) | ||
65 | npd->cfg_gpio = s3c_i2c7_cfg_gpio; | ||
66 | |||
67 | s3c_device_i2c7.dev.platform_data = npd; | ||
68 | } | ||
diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c index e3d41eaed1ff..b732b773b9af 100644 --- a/arch/arm/plat-samsung/gpio-config.c +++ b/arch/arm/plat-samsung/gpio-config.c | |||
@@ -41,6 +41,37 @@ int s3c_gpio_cfgpin(unsigned int pin, unsigned int config) | |||
41 | } | 41 | } |
42 | EXPORT_SYMBOL(s3c_gpio_cfgpin); | 42 | EXPORT_SYMBOL(s3c_gpio_cfgpin); |
43 | 43 | ||
44 | int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr, | ||
45 | unsigned int cfg) | ||
46 | { | ||
47 | int ret; | ||
48 | |||
49 | for (; nr > 0; nr--, start++) { | ||
50 | ret = s3c_gpio_cfgpin(start, cfg); | ||
51 | if (ret != 0) | ||
52 | return ret; | ||
53 | } | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range); | ||
58 | |||
59 | int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr, | ||
60 | unsigned int cfg, s3c_gpio_pull_t pull) | ||
61 | { | ||
62 | int ret; | ||
63 | |||
64 | for (; nr > 0; nr--, start++) { | ||
65 | s3c_gpio_setpull(start, pull); | ||
66 | ret = s3c_gpio_cfgpin(start, cfg); | ||
67 | if (ret != 0) | ||
68 | return ret; | ||
69 | } | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range); | ||
74 | |||
44 | unsigned s3c_gpio_getcfg(unsigned int pin) | 75 | unsigned s3c_gpio_getcfg(unsigned int pin) |
45 | { | 76 | { |
46 | struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); | 77 | struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); |
@@ -80,6 +111,25 @@ int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull) | |||
80 | } | 111 | } |
81 | EXPORT_SYMBOL(s3c_gpio_setpull); | 112 | EXPORT_SYMBOL(s3c_gpio_setpull); |
82 | 113 | ||
114 | s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin) | ||
115 | { | ||
116 | struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); | ||
117 | unsigned long flags; | ||
118 | int offset; | ||
119 | u32 pup = 0; | ||
120 | |||
121 | if (chip) { | ||
122 | offset = pin - chip->chip.base; | ||
123 | |||
124 | s3c_gpio_lock(chip, flags); | ||
125 | pup = s3c_gpio_do_getpull(chip, offset); | ||
126 | s3c_gpio_unlock(chip, flags); | ||
127 | } | ||
128 | |||
129 | return (__force s3c_gpio_pull_t)pup; | ||
130 | } | ||
131 | EXPORT_SYMBOL(s3c_gpio_getpull); | ||
132 | |||
83 | #ifdef CONFIG_S3C_GPIO_CFG_S3C24XX | 133 | #ifdef CONFIG_S3C_GPIO_CFG_S3C24XX |
84 | int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip, | 134 | int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip, |
85 | unsigned int off, unsigned int cfg) | 135 | unsigned int off, unsigned int cfg) |
diff --git a/arch/arm/plat-samsung/gpio.c b/arch/arm/plat-samsung/gpio.c index b83a83351cea..7743c4b8b2fb 100644 --- a/arch/arm/plat-samsung/gpio.c +++ b/arch/arm/plat-samsung/gpio.c | |||
@@ -157,3 +157,11 @@ __init void s3c_gpiolib_add(struct s3c_gpio_chip *chip) | |||
157 | if (ret >= 0) | 157 | if (ret >= 0) |
158 | s3c_gpiolib_track(chip); | 158 | s3c_gpiolib_track(chip); |
159 | } | 159 | } |
160 | |||
161 | int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset) | ||
162 | { | ||
163 | struct s3c_gpio_chip *s3c_chip = container_of(chip, | ||
164 | struct s3c_gpio_chip, chip); | ||
165 | |||
166 | return s3c_chip->irq_base + offset; | ||
167 | } | ||
diff --git a/arch/arm/plat-samsung/include/plat/audio.h b/arch/arm/plat-samsung/include/plat/audio.h index e32f9edfd4b7..7712ff6336f4 100644 --- a/arch/arm/plat-samsung/include/plat/audio.h +++ b/arch/arm/plat-samsung/include/plat/audio.h | |||
@@ -16,6 +16,15 @@ | |||
16 | #define S3C64XX_AC97_GPE 1 | 16 | #define S3C64XX_AC97_GPE 1 |
17 | extern void s3c64xx_ac97_setup_gpio(int); | 17 | extern void s3c64xx_ac97_setup_gpio(int); |
18 | 18 | ||
19 | /* | ||
20 | * The machine init code calls s5p*_spdif_setup_gpio with | ||
21 | * one of these defines in order to select appropriate bank | ||
22 | * of GPIO for S/PDIF pins | ||
23 | */ | ||
24 | #define S5PC100_SPDIF_GPD 0 | ||
25 | #define S5PC100_SPDIF_GPG3 1 | ||
26 | extern void s5pc100_spdif_setup_gpio(int); | ||
27 | |||
19 | /** | 28 | /** |
20 | * struct s3c_audio_pdata - common platform data for audio device drivers | 29 | * struct s3c_audio_pdata - common platform data for audio device drivers |
21 | * @cfg_gpio: Callback function to setup mux'ed pins in I2S/PCM/AC97 mode | 30 | * @cfg_gpio: Callback function to setup mux'ed pins in I2S/PCM/AC97 mode |
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index c8b94279bad1..2d82a6cb1444 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h | |||
@@ -48,6 +48,11 @@ extern struct platform_device s3c_device_wdt; | |||
48 | extern struct platform_device s3c_device_i2c0; | 48 | extern struct platform_device s3c_device_i2c0; |
49 | extern struct platform_device s3c_device_i2c1; | 49 | extern struct platform_device s3c_device_i2c1; |
50 | extern struct platform_device s3c_device_i2c2; | 50 | extern struct platform_device s3c_device_i2c2; |
51 | extern struct platform_device s3c_device_i2c3; | ||
52 | extern struct platform_device s3c_device_i2c4; | ||
53 | extern struct platform_device s3c_device_i2c5; | ||
54 | extern struct platform_device s3c_device_i2c6; | ||
55 | extern struct platform_device s3c_device_i2c7; | ||
51 | extern struct platform_device s3c_device_rtc; | 56 | extern struct platform_device s3c_device_rtc; |
52 | extern struct platform_device s3c_device_adc; | 57 | extern struct platform_device s3c_device_adc; |
53 | extern struct platform_device s3c_device_sdi; | 58 | extern struct platform_device s3c_device_sdi; |
@@ -89,6 +94,7 @@ extern struct platform_device s5pv210_device_pcm2; | |||
89 | extern struct platform_device s5pv210_device_iis0; | 94 | extern struct platform_device s5pv210_device_iis0; |
90 | extern struct platform_device s5pv210_device_iis1; | 95 | extern struct platform_device s5pv210_device_iis1; |
91 | extern struct platform_device s5pv210_device_iis2; | 96 | extern struct platform_device s5pv210_device_iis2; |
97 | extern struct platform_device s5pv210_device_spdif; | ||
92 | 98 | ||
93 | extern struct platform_device s5p6442_device_pcm0; | 99 | extern struct platform_device s5p6442_device_pcm0; |
94 | extern struct platform_device s5p6442_device_pcm1; | 100 | extern struct platform_device s5p6442_device_pcm1; |
@@ -108,6 +114,7 @@ extern struct platform_device s5pc100_device_pcm1; | |||
108 | extern struct platform_device s5pc100_device_iis0; | 114 | extern struct platform_device s5pc100_device_iis0; |
109 | extern struct platform_device s5pc100_device_iis1; | 115 | extern struct platform_device s5pc100_device_iis1; |
110 | extern struct platform_device s5pc100_device_iis2; | 116 | extern struct platform_device s5pc100_device_iis2; |
117 | extern struct platform_device s5pc100_device_spdif; | ||
111 | 118 | ||
112 | extern struct platform_device samsung_device_keypad; | 119 | extern struct platform_device samsung_device_keypad; |
113 | 120 | ||
diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h index 3e21c75feefa..8fd65d8b5863 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h +++ b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h | |||
@@ -42,6 +42,12 @@ static inline int s3c_gpio_do_setpull(struct s3c_gpio_chip *chip, | |||
42 | return (chip->config->set_pull)(chip, off, pull); | 42 | return (chip->config->set_pull)(chip, off, pull); |
43 | } | 43 | } |
44 | 44 | ||
45 | static inline s3c_gpio_pull_t s3c_gpio_do_getpull(struct s3c_gpio_chip *chip, | ||
46 | unsigned int off) | ||
47 | { | ||
48 | return chip->config->get_pull(chip, off); | ||
49 | } | ||
50 | |||
45 | /** | 51 | /** |
46 | * s3c_gpio_setcfg_s3c24xx - S3C24XX style GPIO configuration. | 52 | * s3c_gpio_setcfg_s3c24xx - S3C24XX style GPIO configuration. |
47 | * @chip: The gpio chip that is being configured. | 53 | * @chip: The gpio chip that is being configured. |
diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg.h b/arch/arm/plat-samsung/include/plat/gpio-cfg.h index 1c6b92947c5d..e4b5cf126fa9 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-cfg.h +++ b/arch/arm/plat-samsung/include/plat/gpio-cfg.h | |||
@@ -108,6 +108,19 @@ extern int s3c_gpio_cfgpin(unsigned int pin, unsigned int to); | |||
108 | */ | 108 | */ |
109 | extern unsigned s3c_gpio_getcfg(unsigned int pin); | 109 | extern unsigned s3c_gpio_getcfg(unsigned int pin); |
110 | 110 | ||
111 | /** | ||
112 | * s3c_gpio_cfgpin_range() - Change the GPIO function for configuring pin range | ||
113 | * @start: The pin number to start at | ||
114 | * @nr: The number of pins to configure from @start. | ||
115 | * @cfg: The configuration for the pin's function | ||
116 | * | ||
117 | * Call s3c_gpio_cfgpin() for the @nr pins starting at @start. | ||
118 | * | ||
119 | * @sa s3c_gpio_cfgpin. | ||
120 | */ | ||
121 | extern int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr, | ||
122 | unsigned int cfg); | ||
123 | |||
111 | /* Define values for the pull-{up,down} available for each gpio pin. | 124 | /* Define values for the pull-{up,down} available for each gpio pin. |
112 | * | 125 | * |
113 | * These values control the state of the weak pull-{up,down} resistors | 126 | * These values control the state of the weak pull-{up,down} resistors |
@@ -140,6 +153,31 @@ extern int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull); | |||
140 | */ | 153 | */ |
141 | extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin); | 154 | extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin); |
142 | 155 | ||
156 | /* configure `all` aspects of an gpio */ | ||
157 | |||
158 | /** | ||
159 | * s3c_gpio_cfgall_range() - configure range of gpio functtion and pull. | ||
160 | * @start: The gpio number to start at. | ||
161 | * @nr: The number of gpio to configure from @start. | ||
162 | * @cfg: The configuration to use | ||
163 | * @pull: The pull setting to use. | ||
164 | * | ||
165 | * Run s3c_gpio_cfgpin() and s3c_gpio_setpull() over the gpio range starting | ||
166 | * @gpio and running for @size. | ||
167 | * | ||
168 | * @sa s3c_gpio_cfgpin | ||
169 | * @sa s3c_gpio_setpull | ||
170 | * @sa s3c_gpio_cfgpin_range | ||
171 | */ | ||
172 | extern int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr, | ||
173 | unsigned int cfg, s3c_gpio_pull_t pull); | ||
174 | |||
175 | static inline int s3c_gpio_cfgrange_nopull(unsigned int pin, unsigned int size, | ||
176 | unsigned int cfg) | ||
177 | { | ||
178 | return s3c_gpio_cfgall_range(pin, size, cfg, S3C_GPIO_PULL_NONE); | ||
179 | } | ||
180 | |||
143 | /* Define values for the drvstr available for each gpio pin. | 181 | /* Define values for the drvstr available for each gpio pin. |
144 | * | 182 | * |
145 | * These values control the value of the output signal driver strength, | 183 | * These values control the value of the output signal driver strength, |
@@ -169,4 +207,22 @@ extern s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin); | |||
169 | */ | 207 | */ |
170 | extern int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr); | 208 | extern int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr); |
171 | 209 | ||
210 | /** | ||
211 | * s5p_register_gpio_interrupt() - register interrupt support for a gpio group | ||
212 | * @pin: The pin number from the group to be registered | ||
213 | * | ||
214 | * This function registers gpio interrupt support for the group that the | ||
215 | * specified pin belongs to. | ||
216 | * | ||
217 | * The total number of gpio pins is quite large ob s5p series. Registering | ||
218 | * irq support for all of them would be a resource waste. Because of that the | ||
219 | * interrupt support for standard gpio pins is registered dynamically. | ||
220 | * | ||
221 | * It will return the irq number of the interrupt that has been registered | ||
222 | * or -ENOMEM if no more gpio interrupts can be registered. It is allowed | ||
223 | * to call this function more than once for the same gpio group (the group | ||
224 | * will be registered only once). | ||
225 | */ | ||
226 | extern int s5p_register_gpio_interrupt(int pin); | ||
227 | |||
172 | #endif /* __PLAT_GPIO_CFG_H */ | 228 | #endif /* __PLAT_GPIO_CFG_H */ |
diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h index e358c7da8480..13a22b8861ef 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-core.h +++ b/arch/arm/plat-samsung/include/plat/gpio-core.h | |||
@@ -43,6 +43,8 @@ struct s3c_gpio_cfg; | |||
43 | * struct s3c_gpio_chip - wrapper for specific implementation of gpio | 43 | * struct s3c_gpio_chip - wrapper for specific implementation of gpio |
44 | * @chip: The chip structure to be exported via gpiolib. | 44 | * @chip: The chip structure to be exported via gpiolib. |
45 | * @base: The base pointer to the gpio configuration registers. | 45 | * @base: The base pointer to the gpio configuration registers. |
46 | * @group: The group register number for gpio interrupt support. | ||
47 | * @irq_base: The base irq number. | ||
46 | * @config: special function and pull-resistor control information. | 48 | * @config: special function and pull-resistor control information. |
47 | * @lock: Lock for exclusive access to this gpio bank. | 49 | * @lock: Lock for exclusive access to this gpio bank. |
48 | * @pm_save: Save information for suspend/resume support. | 50 | * @pm_save: Save information for suspend/resume support. |
@@ -63,6 +65,8 @@ struct s3c_gpio_chip { | |||
63 | struct s3c_gpio_cfg *config; | 65 | struct s3c_gpio_cfg *config; |
64 | struct s3c_gpio_pm *pm; | 66 | struct s3c_gpio_pm *pm; |
65 | void __iomem *base; | 67 | void __iomem *base; |
68 | int irq_base; | ||
69 | int group; | ||
66 | spinlock_t lock; | 70 | spinlock_t lock; |
67 | #ifdef CONFIG_PM | 71 | #ifdef CONFIG_PM |
68 | u32 pm_save[4]; | 72 | u32 pm_save[4]; |
@@ -118,6 +122,17 @@ extern void samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip, | |||
118 | extern void samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip); | 122 | extern void samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip); |
119 | extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip); | 123 | extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip); |
120 | 124 | ||
125 | |||
126 | /** | ||
127 | * samsung_gpiolib_to_irq - convert gpio pin to irq number | ||
128 | * @chip: The gpio chip that the pin belongs to. | ||
129 | * @offset: The offset of the pin in the chip. | ||
130 | * | ||
131 | * This helper returns the irq number calculated from the chip->irq_base and | ||
132 | * the provided offset. | ||
133 | */ | ||
134 | extern int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset); | ||
135 | |||
121 | /* exported for core SoC support to change */ | 136 | /* exported for core SoC support to change */ |
122 | extern struct s3c_gpio_cfg s3c24xx_gpiocfg_default; | 137 | extern struct s3c_gpio_cfg s3c24xx_gpiocfg_default; |
123 | 138 | ||
diff --git a/arch/arm/plat-samsung/include/plat/iic.h b/arch/arm/plat-samsung/include/plat/iic.h index 133308bf595d..1543da8f85c1 100644 --- a/arch/arm/plat-samsung/include/plat/iic.h +++ b/arch/arm/plat-samsung/include/plat/iic.h | |||
@@ -55,10 +55,20 @@ struct s3c2410_platform_i2c { | |||
55 | extern void s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *i2c); | 55 | extern void s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *i2c); |
56 | extern void s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *i2c); | 56 | extern void s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *i2c); |
57 | extern void s3c_i2c2_set_platdata(struct s3c2410_platform_i2c *i2c); | 57 | extern void s3c_i2c2_set_platdata(struct s3c2410_platform_i2c *i2c); |
58 | extern void s3c_i2c3_set_platdata(struct s3c2410_platform_i2c *i2c); | ||
59 | extern void s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *i2c); | ||
60 | extern void s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *i2c); | ||
61 | extern void s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *i2c); | ||
62 | extern void s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *i2c); | ||
58 | 63 | ||
59 | /* defined by architecture to configure gpio */ | 64 | /* defined by architecture to configure gpio */ |
60 | extern void s3c_i2c0_cfg_gpio(struct platform_device *dev); | 65 | extern void s3c_i2c0_cfg_gpio(struct platform_device *dev); |
61 | extern void s3c_i2c1_cfg_gpio(struct platform_device *dev); | 66 | extern void s3c_i2c1_cfg_gpio(struct platform_device *dev); |
62 | extern void s3c_i2c2_cfg_gpio(struct platform_device *dev); | 67 | extern void s3c_i2c2_cfg_gpio(struct platform_device *dev); |
68 | extern void s3c_i2c3_cfg_gpio(struct platform_device *dev); | ||
69 | extern void s3c_i2c4_cfg_gpio(struct platform_device *dev); | ||
70 | extern void s3c_i2c5_cfg_gpio(struct platform_device *dev); | ||
71 | extern void s3c_i2c6_cfg_gpio(struct platform_device *dev); | ||
72 | extern void s3c_i2c7_cfg_gpio(struct platform_device *dev); | ||
63 | 73 | ||
64 | #endif /* __ASM_ARCH_IIC_H */ | 74 | #endif /* __ASM_ARCH_IIC_H */ |
diff --git a/arch/arm/plat-samsung/include/plat/map-base.h b/arch/arm/plat-samsung/include/plat/map-base.h index 250be311c85b..3ffac4d2e4f0 100644 --- a/arch/arm/plat-samsung/include/plat/map-base.h +++ b/arch/arm/plat-samsung/include/plat/map-base.h | |||
@@ -14,7 +14,7 @@ | |||
14 | #ifndef __ASM_PLAT_MAP_H | 14 | #ifndef __ASM_PLAT_MAP_H |
15 | #define __ASM_PLAT_MAP_H __FILE__ | 15 | #define __ASM_PLAT_MAP_H __FILE__ |
16 | 16 | ||
17 | /* Fit all our registers in at 0xF4000000 upwards, trying to use as | 17 | /* Fit all our registers in at 0xF6000000 upwards, trying to use as |
18 | * little of the VA space as possible so vmalloc and friends have a | 18 | * little of the VA space as possible so vmalloc and friends have a |
19 | * better chance of getting memory. | 19 | * better chance of getting memory. |
20 | * | 20 | * |
@@ -22,7 +22,7 @@ | |||
22 | * an single MOVS instruction (ie, only 8 bits of set data) | 22 | * an single MOVS instruction (ie, only 8 bits of set data) |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #define S3C_ADDR_BASE (0xF4000000) | 25 | #define S3C_ADDR_BASE 0xF6000000 |
26 | 26 | ||
27 | #ifndef __ASSEMBLY__ | 27 | #ifndef __ASSEMBLY__ |
28 | #define S3C_ADDR(x) ((void __iomem __force *)S3C_ADDR_BASE + (x)) | 28 | #define S3C_ADDR(x) ((void __iomem __force *)S3C_ADDR_BASE + (x)) |
diff --git a/arch/arm/plat-samsung/include/plat/nand-core.h b/arch/arm/plat-samsung/include/plat/nand-core.h new file mode 100644 index 000000000000..6de20789a95e --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/nand-core.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /* arch/arm/plat-samsung/include/plat/nand-core.h | ||
2 | * | ||
3 | * Copyright (c) 2010 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com/ | ||
5 | * | ||
6 | * S3C - Nand Controller core functions | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __ASM_ARCH_NAND_CORE_H | ||
14 | #define __ASM_ARCH_NAND_CORE_H __FILE__ | ||
15 | |||
16 | /* These functions are only for use with the core support code, such as | ||
17 | * the cpu specific initialisation code | ||
18 | */ | ||
19 | |||
20 | /* re-define device name depending on support. */ | ||
21 | static inline void s3c_nand_setname(char *name) | ||
22 | { | ||
23 | #ifdef CONFIG_S3C_DEV_NAND | ||
24 | s3c_device_nand.name = name; | ||
25 | #endif | ||
26 | } | ||
27 | |||
28 | #endif /* __ASM_ARCH_NAND_CORE_H */ | ||
diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h index 30844c263d03..85853f8c4c5d 100644 --- a/arch/arm/plat-samsung/include/plat/sdhci.h +++ b/arch/arm/plat-samsung/include/plat/sdhci.h | |||
@@ -28,11 +28,17 @@ enum cd_types { | |||
28 | S3C_SDHCI_CD_PERMANENT, /* no CD line, card permanently wired to host */ | 28 | S3C_SDHCI_CD_PERMANENT, /* no CD line, card permanently wired to host */ |
29 | }; | 29 | }; |
30 | 30 | ||
31 | enum clk_types { | ||
32 | S3C_SDHCI_CLK_DIV_INTERNAL, /* use mmc internal clock divider */ | ||
33 | S3C_SDHCI_CLK_DIV_EXTERNAL, /* use external clock divider */ | ||
34 | }; | ||
35 | |||
31 | /** | 36 | /** |
32 | * struct s3c_sdhci_platdata() - Platform device data for Samsung SDHCI | 37 | * struct s3c_sdhci_platdata() - Platform device data for Samsung SDHCI |
33 | * @max_width: The maximum number of data bits supported. | 38 | * @max_width: The maximum number of data bits supported. |
34 | * @host_caps: Standard MMC host capabilities bit field. | 39 | * @host_caps: Standard MMC host capabilities bit field. |
35 | * @cd_type: Type of Card Detection method (see cd_types enum above) | 40 | * @cd_type: Type of Card Detection method (see cd_types enum above) |
41 | * @clk_type: Type of clock divider method (see clk_types enum above) | ||
36 | * @ext_cd_init: Initialize external card detect subsystem. Called on | 42 | * @ext_cd_init: Initialize external card detect subsystem. Called on |
37 | * sdhci-s3c driver probe when cd_type == S3C_SDHCI_CD_EXTERNAL. | 43 | * sdhci-s3c driver probe when cd_type == S3C_SDHCI_CD_EXTERNAL. |
38 | * notify_func argument is a callback to the sdhci-s3c driver | 44 | * notify_func argument is a callback to the sdhci-s3c driver |
@@ -59,6 +65,7 @@ struct s3c_sdhci_platdata { | |||
59 | unsigned int max_width; | 65 | unsigned int max_width; |
60 | unsigned int host_caps; | 66 | unsigned int host_caps; |
61 | enum cd_types cd_type; | 67 | enum cd_types cd_type; |
68 | enum clk_types clk_type; | ||
62 | 69 | ||
63 | char **clocks; /* set of clock sources */ | 70 | char **clocks; /* set of clock sources */ |
64 | 71 | ||
@@ -110,6 +117,10 @@ extern void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *, int w); | |||
110 | extern void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *, int w); | 117 | extern void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *, int w); |
111 | extern void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *, int w); | 118 | extern void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *, int w); |
112 | extern void s5pv210_setup_sdhci3_cfg_gpio(struct platform_device *, int w); | 119 | extern void s5pv210_setup_sdhci3_cfg_gpio(struct platform_device *, int w); |
120 | extern void s5pv310_setup_sdhci0_cfg_gpio(struct platform_device *, int w); | ||
121 | extern void s5pv310_setup_sdhci1_cfg_gpio(struct platform_device *, int w); | ||
122 | extern void s5pv310_setup_sdhci2_cfg_gpio(struct platform_device *, int w); | ||
123 | extern void s5pv310_setup_sdhci3_cfg_gpio(struct platform_device *, int w); | ||
113 | 124 | ||
114 | /* S3C64XX SDHCI setup */ | 125 | /* S3C64XX SDHCI setup */ |
115 | 126 | ||
@@ -288,4 +299,57 @@ static inline void s5pv210_default_sdhci3(void) { } | |||
288 | 299 | ||
289 | #endif /* CONFIG_S5PV210_SETUP_SDHCI */ | 300 | #endif /* CONFIG_S5PV210_SETUP_SDHCI */ |
290 | 301 | ||
302 | /* S5PV310 SDHCI setup */ | ||
303 | #ifdef CONFIG_S5PV310_SETUP_SDHCI | ||
304 | extern char *s5pv310_hsmmc_clksrcs[4]; | ||
305 | |||
306 | extern void s5pv310_setup_sdhci_cfg_card(struct platform_device *dev, | ||
307 | void __iomem *r, | ||
308 | struct mmc_ios *ios, | ||
309 | struct mmc_card *card); | ||
310 | |||
311 | static inline void s5pv310_default_sdhci0(void) | ||
312 | { | ||
313 | #ifdef CONFIG_S3C_DEV_HSMMC | ||
314 | s3c_hsmmc0_def_platdata.clocks = s5pv310_hsmmc_clksrcs; | ||
315 | s3c_hsmmc0_def_platdata.cfg_gpio = s5pv310_setup_sdhci0_cfg_gpio; | ||
316 | s3c_hsmmc0_def_platdata.cfg_card = s5pv310_setup_sdhci_cfg_card; | ||
317 | #endif | ||
318 | } | ||
319 | |||
320 | static inline void s5pv310_default_sdhci1(void) | ||
321 | { | ||
322 | #ifdef CONFIG_S3C_DEV_HSMMC1 | ||
323 | s3c_hsmmc1_def_platdata.clocks = s5pv310_hsmmc_clksrcs; | ||
324 | s3c_hsmmc1_def_platdata.cfg_gpio = s5pv310_setup_sdhci1_cfg_gpio; | ||
325 | s3c_hsmmc1_def_platdata.cfg_card = s5pv310_setup_sdhci_cfg_card; | ||
326 | #endif | ||
327 | } | ||
328 | |||
329 | static inline void s5pv310_default_sdhci2(void) | ||
330 | { | ||
331 | #ifdef CONFIG_S3C_DEV_HSMMC2 | ||
332 | s3c_hsmmc2_def_platdata.clocks = s5pv310_hsmmc_clksrcs; | ||
333 | s3c_hsmmc2_def_platdata.cfg_gpio = s5pv310_setup_sdhci2_cfg_gpio; | ||
334 | s3c_hsmmc2_def_platdata.cfg_card = s5pv310_setup_sdhci_cfg_card; | ||
335 | #endif | ||
336 | } | ||
337 | |||
338 | static inline void s5pv310_default_sdhci3(void) | ||
339 | { | ||
340 | #ifdef CONFIG_S3C_DEV_HSMMC3 | ||
341 | s3c_hsmmc3_def_platdata.clocks = s5pv310_hsmmc_clksrcs; | ||
342 | s3c_hsmmc3_def_platdata.cfg_gpio = s5pv310_setup_sdhci3_cfg_gpio; | ||
343 | s3c_hsmmc3_def_platdata.cfg_card = s5pv310_setup_sdhci_cfg_card; | ||
344 | #endif | ||
345 | } | ||
346 | |||
347 | #else | ||
348 | static inline void s5pv310_default_sdhci0(void) { } | ||
349 | static inline void s5pv310_default_sdhci1(void) { } | ||
350 | static inline void s5pv310_default_sdhci2(void) { } | ||
351 | static inline void s5pv310_default_sdhci3(void) { } | ||
352 | |||
353 | #endif /* CONFIG_S5PV310_SETUP_SDHCI */ | ||
354 | |||
291 | #endif /* __PLAT_S3C_SDHCI_H */ | 355 | #endif /* __PLAT_S3C_SDHCI_H */ |
diff --git a/arch/arm/plat-samsung/pm-gpio.c b/arch/arm/plat-samsung/pm-gpio.c index 7df03f87fbfa..96528200eb79 100644 --- a/arch/arm/plat-samsung/pm-gpio.c +++ b/arch/arm/plat-samsung/pm-gpio.c | |||
@@ -192,7 +192,7 @@ struct s3c_gpio_pm s3c_gpio_pm_2bit = { | |||
192 | .resume = s3c_gpio_pm_2bit_resume, | 192 | .resume = s3c_gpio_pm_2bit_resume, |
193 | }; | 193 | }; |
194 | 194 | ||
195 | #ifdef CONFIG_ARCH_S3C64XX | 195 | #if defined(CONFIG_ARCH_S3C64XX) || defined(CONFIG_PLAT_S5P) |
196 | static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip) | 196 | static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip) |
197 | { | 197 | { |
198 | chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON); | 198 | chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON); |
@@ -302,7 +302,7 @@ struct s3c_gpio_pm s3c_gpio_pm_4bit = { | |||
302 | .save = s3c_gpio_pm_4bit_save, | 302 | .save = s3c_gpio_pm_4bit_save, |
303 | .resume = s3c_gpio_pm_4bit_resume, | 303 | .resume = s3c_gpio_pm_4bit_resume, |
304 | }; | 304 | }; |
305 | #endif /* CONFIG_ARCH_S3C64XX */ | 305 | #endif /* CONFIG_ARCH_S3C64XX || CONFIG_PLAT_S5P */ |
306 | 306 | ||
307 | /** | 307 | /** |
308 | * s3c_pm_save_gpio() - save gpio chip data for suspend | 308 | * s3c_pm_save_gpio() - save gpio chip data for suspend |
diff --git a/arch/arm/plat-samsung/s3c-pl330.c b/arch/arm/plat-samsung/s3c-pl330.c index a91305a60aed..b4ff8d74ac40 100644 --- a/arch/arm/plat-samsung/s3c-pl330.c +++ b/arch/arm/plat-samsung/s3c-pl330.c | |||
@@ -15,6 +15,8 @@ | |||
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/clk.h> | ||
19 | #include <linux/err.h> | ||
18 | 20 | ||
19 | #include <asm/hardware/pl330.h> | 21 | #include <asm/hardware/pl330.h> |
20 | 22 | ||
@@ -27,6 +29,7 @@ | |||
27 | * @node: To attach to the global list of DMACs. | 29 | * @node: To attach to the global list of DMACs. |
28 | * @pi: PL330 configuration info for the DMAC. | 30 | * @pi: PL330 configuration info for the DMAC. |
29 | * @kmcache: Pool to quickly allocate xfers for all channels in the dmac. | 31 | * @kmcache: Pool to quickly allocate xfers for all channels in the dmac. |
32 | * @clk: Pointer of DMAC operation clock. | ||
30 | */ | 33 | */ |
31 | struct s3c_pl330_dmac { | 34 | struct s3c_pl330_dmac { |
32 | unsigned busy_chan; | 35 | unsigned busy_chan; |
@@ -34,6 +37,7 @@ struct s3c_pl330_dmac { | |||
34 | struct list_head node; | 37 | struct list_head node; |
35 | struct pl330_info *pi; | 38 | struct pl330_info *pi; |
36 | struct kmem_cache *kmcache; | 39 | struct kmem_cache *kmcache; |
40 | struct clk *clk; | ||
37 | }; | 41 | }; |
38 | 42 | ||
39 | /** | 43 | /** |
@@ -1072,16 +1076,25 @@ static int pl330_probe(struct platform_device *pdev) | |||
1072 | if (ret) | 1076 | if (ret) |
1073 | goto probe_err4; | 1077 | goto probe_err4; |
1074 | 1078 | ||
1075 | ret = pl330_add(pl330_info); | ||
1076 | if (ret) | ||
1077 | goto probe_err5; | ||
1078 | |||
1079 | /* Allocate a new DMAC */ | 1079 | /* Allocate a new DMAC */ |
1080 | s3c_pl330_dmac = kmalloc(sizeof(*s3c_pl330_dmac), GFP_KERNEL); | 1080 | s3c_pl330_dmac = kmalloc(sizeof(*s3c_pl330_dmac), GFP_KERNEL); |
1081 | if (!s3c_pl330_dmac) { | 1081 | if (!s3c_pl330_dmac) { |
1082 | ret = -ENOMEM; | 1082 | ret = -ENOMEM; |
1083 | goto probe_err5; | ||
1084 | } | ||
1085 | |||
1086 | /* Get operation clock and enable it */ | ||
1087 | s3c_pl330_dmac->clk = clk_get(&pdev->dev, "pdma"); | ||
1088 | if (IS_ERR(s3c_pl330_dmac->clk)) { | ||
1089 | dev_err(&pdev->dev, "Cannot get operation clock.\n"); | ||
1090 | ret = -EINVAL; | ||
1083 | goto probe_err6; | 1091 | goto probe_err6; |
1084 | } | 1092 | } |
1093 | clk_enable(s3c_pl330_dmac->clk); | ||
1094 | |||
1095 | ret = pl330_add(pl330_info); | ||
1096 | if (ret) | ||
1097 | goto probe_err7; | ||
1085 | 1098 | ||
1086 | /* Hook the info */ | 1099 | /* Hook the info */ |
1087 | s3c_pl330_dmac->pi = pl330_info; | 1100 | s3c_pl330_dmac->pi = pl330_info; |
@@ -1094,7 +1107,7 @@ static int pl330_probe(struct platform_device *pdev) | |||
1094 | 1107 | ||
1095 | if (!s3c_pl330_dmac->kmcache) { | 1108 | if (!s3c_pl330_dmac->kmcache) { |
1096 | ret = -ENOMEM; | 1109 | ret = -ENOMEM; |
1097 | goto probe_err7; | 1110 | goto probe_err8; |
1098 | } | 1111 | } |
1099 | 1112 | ||
1100 | /* Get the list of peripherals */ | 1113 | /* Get the list of peripherals */ |
@@ -1120,10 +1133,13 @@ static int pl330_probe(struct platform_device *pdev) | |||
1120 | 1133 | ||
1121 | return 0; | 1134 | return 0; |
1122 | 1135 | ||
1136 | probe_err8: | ||
1137 | pl330_del(pl330_info); | ||
1123 | probe_err7: | 1138 | probe_err7: |
1124 | kfree(s3c_pl330_dmac); | 1139 | clk_disable(s3c_pl330_dmac->clk); |
1140 | clk_put(s3c_pl330_dmac->clk); | ||
1125 | probe_err6: | 1141 | probe_err6: |
1126 | pl330_del(pl330_info); | 1142 | kfree(s3c_pl330_dmac); |
1127 | probe_err5: | 1143 | probe_err5: |
1128 | free_irq(irq, pl330_info); | 1144 | free_irq(irq, pl330_info); |
1129 | probe_err4: | 1145 | probe_err4: |
@@ -1188,6 +1204,10 @@ static int pl330_remove(struct platform_device *pdev) | |||
1188 | } | 1204 | } |
1189 | } | 1205 | } |
1190 | 1206 | ||
1207 | /* Disable operation clock */ | ||
1208 | clk_disable(dmac->clk); | ||
1209 | clk_put(dmac->clk); | ||
1210 | |||
1191 | /* Remove the DMAC */ | 1211 | /* Remove the DMAC */ |
1192 | list_del(&dmac->node); | 1212 | list_del(&dmac->node); |
1193 | kfree(dmac); | 1213 | kfree(dmac); |
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h b/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h new file mode 100644 index 000000000000..5325084d5c48 --- /dev/null +++ b/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h | |||
@@ -0,0 +1,97 @@ | |||
1 | #ifndef __BCM963XX_TAG_H | ||
2 | #define __BCM963XX_TAG_H | ||
3 | |||
4 | #define TAGVER_LEN 4 /* Length of Tag Version */ | ||
5 | #define TAGLAYOUT_LEN 4 /* Length of FlashLayoutVer */ | ||
6 | #define SIG1_LEN 20 /* Company Signature 1 Length */ | ||
7 | #define SIG2_LEN 14 /* Company Signature 2 Lenght */ | ||
8 | #define BOARDID_LEN 16 /* Length of BoardId */ | ||
9 | #define ENDIANFLAG_LEN 2 /* Endian Flag Length */ | ||
10 | #define CHIPID_LEN 6 /* Chip Id Length */ | ||
11 | #define IMAGE_LEN 10 /* Length of Length Field */ | ||
12 | #define ADDRESS_LEN 12 /* Length of Address field */ | ||
13 | #define DUALFLAG_LEN 2 /* Dual Image flag Length */ | ||
14 | #define INACTIVEFLAG_LEN 2 /* Inactie Flag Length */ | ||
15 | #define RSASIG_LEN 20 /* Length of RSA Signature in tag */ | ||
16 | #define TAGINFO1_LEN 30 /* Length of vendor information field1 in tag */ | ||
17 | #define FLASHLAYOUTVER_LEN 4 /* Length of Flash Layout Version String tag */ | ||
18 | #define TAGINFO2_LEN 16 /* Length of vendor information field2 in tag */ | ||
19 | #define CRC_LEN 4 /* Length of CRC in bytes */ | ||
20 | #define ALTTAGINFO_LEN 54 /* Alternate length for vendor information; Pirelli */ | ||
21 | |||
22 | #define NUM_PIRELLI 2 | ||
23 | #define IMAGETAG_CRC_START 0xFFFFFFFF | ||
24 | |||
25 | #define PIRELLI_BOARDS { \ | ||
26 | "AGPF-S0", \ | ||
27 | "DWV-S0", \ | ||
28 | } | ||
29 | |||
30 | /* | ||
31 | * The broadcom firmware assumes the rootfs starts the image, | ||
32 | * therefore uses the rootfs start (flash_image_address) | ||
33 | * to determine where to flash the image. Since we have the kernel first | ||
34 | * we have to give it the kernel address, but the crc uses the length | ||
35 | * associated with this address (root_length), which is added to the kernel | ||
36 | * length (kernel_length) to determine the length of image to flash and thus | ||
37 | * needs to be rootfs + deadcode (jffs2 EOF marker) | ||
38 | */ | ||
39 | |||
40 | struct bcm_tag { | ||
41 | /* 0-3: Version of the image tag */ | ||
42 | char tag_version[TAGVER_LEN]; | ||
43 | /* 4-23: Company Line 1 */ | ||
44 | char sig_1[SIG1_LEN]; | ||
45 | /* 24-37: Company Line 2 */ | ||
46 | char sig_2[SIG2_LEN]; | ||
47 | /* 38-43: Chip this image is for */ | ||
48 | char chip_id[CHIPID_LEN]; | ||
49 | /* 44-59: Board name */ | ||
50 | char board_id[BOARDID_LEN]; | ||
51 | /* 60-61: Map endianness -- 1 BE 0 LE */ | ||
52 | char big_endian[ENDIANFLAG_LEN]; | ||
53 | /* 62-71: Total length of image */ | ||
54 | char total_length[IMAGE_LEN]; | ||
55 | /* 72-83: Address in memory of CFE */ | ||
56 | char cfe__address[ADDRESS_LEN]; | ||
57 | /* 84-93: Size of CFE */ | ||
58 | char cfe_length[IMAGE_LEN]; | ||
59 | /* 94-105: Address in memory of image start | ||
60 | * (kernel for OpenWRT, rootfs for stock firmware) | ||
61 | */ | ||
62 | char flash_image_start[ADDRESS_LEN]; | ||
63 | /* 106-115: Size of rootfs */ | ||
64 | char root_length[IMAGE_LEN]; | ||
65 | /* 116-127: Address in memory of kernel */ | ||
66 | char kernel_address[ADDRESS_LEN]; | ||
67 | /* 128-137: Size of kernel */ | ||
68 | char kernel_length[IMAGE_LEN]; | ||
69 | /* 138-139: Unused at the moment */ | ||
70 | char dual_image[DUALFLAG_LEN]; | ||
71 | /* 140-141: Unused at the moment */ | ||
72 | char inactive_flag[INACTIVEFLAG_LEN]; | ||
73 | /* 142-161: RSA Signature (not used; some vendors may use this) */ | ||
74 | char rsa_signature[RSASIG_LEN]; | ||
75 | /* 162-191: Compilation and related information (not used in OpenWrt) */ | ||
76 | char information1[TAGINFO1_LEN]; | ||
77 | /* 192-195: Version flash layout */ | ||
78 | char flash_layout_ver[FLASHLAYOUTVER_LEN]; | ||
79 | /* 196-199: kernel+rootfs CRC32 */ | ||
80 | char fskernel_crc[CRC_LEN]; | ||
81 | /* 200-215: Unused except on Alice Gate where is is information */ | ||
82 | char information2[TAGINFO2_LEN]; | ||
83 | /* 216-219: CRC32 of image less imagetag (kernel for Alice Gate) */ | ||
84 | char image_crc[CRC_LEN]; | ||
85 | /* 220-223: CRC32 of rootfs partition */ | ||
86 | char rootfs_crc[CRC_LEN]; | ||
87 | /* 224-227: CRC32 of kernel partition */ | ||
88 | char kernel_crc[CRC_LEN]; | ||
89 | /* 228-235: Unused at present */ | ||
90 | char reserved1[8]; | ||
91 | /* 236-239: CRC32 of header excluding tagVersion */ | ||
92 | char header_crc[CRC_LEN]; | ||
93 | /* 240-255: Unused at present */ | ||
94 | char reserved2[16]; | ||
95 | }; | ||
96 | |||
97 | #endif /* __BCM63XX_TAG_H */ | ||
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index c7e40b37aa65..b6447190e1a2 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -682,9 +682,12 @@ config 4xx_SOC | |||
682 | bool | 682 | bool |
683 | 683 | ||
684 | config FSL_LBC | 684 | config FSL_LBC |
685 | bool | 685 | bool "Freescale Local Bus support" |
686 | depends on FSL_SOC | ||
686 | help | 687 | help |
687 | Freescale Localbus support | 688 | Enables reporting of errors from the Freescale local bus |
689 | controller. Also contains some common code used by | ||
690 | drivers for specific local bus peripherals. | ||
688 | 691 | ||
689 | config FSL_GTM | 692 | config FSL_GTM |
690 | bool | 693 | bool |
diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h index 1b5a21041f9b..5c1bf3466749 100644 --- a/arch/powerpc/include/asm/fsl_lbc.h +++ b/arch/powerpc/include/asm/fsl_lbc.h | |||
@@ -1,9 +1,10 @@ | |||
1 | /* Freescale Local Bus Controller | 1 | /* Freescale Local Bus Controller |
2 | * | 2 | * |
3 | * Copyright (c) 2006-2007 Freescale Semiconductor | 3 | * Copyright © 2006-2007, 2010 Freescale Semiconductor |
4 | * | 4 | * |
5 | * Authors: Nick Spence <nick.spence@freescale.com>, | 5 | * Authors: Nick Spence <nick.spence@freescale.com>, |
6 | * Scott Wood <scottwood@freescale.com> | 6 | * Scott Wood <scottwood@freescale.com> |
7 | * Jack Lan <jack.lan@freescale.com> | ||
7 | * | 8 | * |
8 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
@@ -26,6 +27,8 @@ | |||
26 | #include <linux/compiler.h> | 27 | #include <linux/compiler.h> |
27 | #include <linux/types.h> | 28 | #include <linux/types.h> |
28 | #include <linux/io.h> | 29 | #include <linux/io.h> |
30 | #include <linux/device.h> | ||
31 | #include <linux/spinlock.h> | ||
29 | 32 | ||
30 | struct fsl_lbc_bank { | 33 | struct fsl_lbc_bank { |
31 | __be32 br; /**< Base Register */ | 34 | __be32 br; /**< Base Register */ |
@@ -125,13 +128,23 @@ struct fsl_lbc_regs { | |||
125 | #define LTESR_ATMW 0x00800000 | 128 | #define LTESR_ATMW 0x00800000 |
126 | #define LTESR_ATMR 0x00400000 | 129 | #define LTESR_ATMR 0x00400000 |
127 | #define LTESR_CS 0x00080000 | 130 | #define LTESR_CS 0x00080000 |
131 | #define LTESR_UPM 0x00000002 | ||
128 | #define LTESR_CC 0x00000001 | 132 | #define LTESR_CC 0x00000001 |
129 | #define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC) | 133 | #define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC) |
134 | #define LTESR_MASK (LTESR_BM | LTESR_FCT | LTESR_PAR | LTESR_WP \ | ||
135 | | LTESR_ATMW | LTESR_ATMR | LTESR_CS | LTESR_UPM \ | ||
136 | | LTESR_CC) | ||
137 | #define LTESR_CLEAR 0xFFFFFFFF | ||
138 | #define LTECCR_CLEAR 0xFFFFFFFF | ||
139 | #define LTESR_STATUS LTESR_MASK | ||
140 | #define LTEIR_ENABLE LTESR_MASK | ||
141 | #define LTEDR_ENABLE 0x00000000 | ||
130 | __be32 ltedr; /**< Transfer Error Disable Register */ | 142 | __be32 ltedr; /**< Transfer Error Disable Register */ |
131 | __be32 lteir; /**< Transfer Error Interrupt Register */ | 143 | __be32 lteir; /**< Transfer Error Interrupt Register */ |
132 | __be32 lteatr; /**< Transfer Error Attributes Register */ | 144 | __be32 lteatr; /**< Transfer Error Attributes Register */ |
133 | __be32 ltear; /**< Transfer Error Address Register */ | 145 | __be32 ltear; /**< Transfer Error Address Register */ |
134 | u8 res6[0xC]; | 146 | __be32 lteccr; /**< Transfer Error ECC Register */ |
147 | u8 res6[0x8]; | ||
135 | __be32 lbcr; /**< Configuration Register */ | 148 | __be32 lbcr; /**< Configuration Register */ |
136 | #define LBCR_LDIS 0x80000000 | 149 | #define LBCR_LDIS 0x80000000 |
137 | #define LBCR_LDIS_SHIFT 31 | 150 | #define LBCR_LDIS_SHIFT 31 |
@@ -235,6 +248,7 @@ struct fsl_upm { | |||
235 | int width; | 248 | int width; |
236 | }; | 249 | }; |
237 | 250 | ||
251 | extern u32 fsl_lbc_addr(phys_addr_t addr_base); | ||
238 | extern int fsl_lbc_find(phys_addr_t addr_base); | 252 | extern int fsl_lbc_find(phys_addr_t addr_base); |
239 | extern int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm); | 253 | extern int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm); |
240 | 254 | ||
@@ -265,7 +279,23 @@ static inline void fsl_upm_end_pattern(struct fsl_upm *upm) | |||
265 | cpu_relax(); | 279 | cpu_relax(); |
266 | } | 280 | } |
267 | 281 | ||
282 | /* overview of the fsl lbc controller */ | ||
283 | |||
284 | struct fsl_lbc_ctrl { | ||
285 | /* device info */ | ||
286 | struct device *dev; | ||
287 | struct fsl_lbc_regs __iomem *regs; | ||
288 | int irq; | ||
289 | wait_queue_head_t irq_wait; | ||
290 | spinlock_t lock; | ||
291 | void *nand; | ||
292 | |||
293 | /* status read from LTESR by irq handler */ | ||
294 | unsigned int irq_status; | ||
295 | }; | ||
296 | |||
268 | extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, | 297 | extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, |
269 | u32 mar); | 298 | u32 mar); |
299 | extern struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev; | ||
270 | 300 | ||
271 | #endif /* __ASM_FSL_LBC_H */ | 301 | #endif /* __ASM_FSL_LBC_H */ |
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c index dceb8d1a843d..4fcb5a4e60dd 100644 --- a/arch/powerpc/sysdev/fsl_lbc.c +++ b/arch/powerpc/sysdev/fsl_lbc.c | |||
@@ -1,9 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | * Freescale LBC and UPM routines. | 2 | * Freescale LBC and UPM routines. |
3 | * | 3 | * |
4 | * Copyright (c) 2007-2008 MontaVista Software, Inc. | 4 | * Copyright © 2007-2008 MontaVista Software, Inc. |
5 | * Copyright © 2010 Freescale Semiconductor | ||
5 | * | 6 | * |
6 | * Author: Anton Vorontsov <avorontsov@ru.mvista.com> | 7 | * Author: Anton Vorontsov <avorontsov@ru.mvista.com> |
8 | * Author: Jack Lan <Jack.Lan@freescale.com> | ||
9 | * Author: Roy Zang <tie-fei.zang@freescale.com> | ||
7 | * | 10 | * |
8 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 12 | * it under the terms of the GNU General Public License as published by |
@@ -19,39 +22,37 @@ | |||
19 | #include <linux/types.h> | 22 | #include <linux/types.h> |
20 | #include <linux/io.h> | 23 | #include <linux/io.h> |
21 | #include <linux/of.h> | 24 | #include <linux/of.h> |
25 | #include <linux/slab.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/mod_devicetable.h> | ||
22 | #include <asm/prom.h> | 29 | #include <asm/prom.h> |
23 | #include <asm/fsl_lbc.h> | 30 | #include <asm/fsl_lbc.h> |
24 | 31 | ||
25 | static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock); | 32 | static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock); |
26 | static struct fsl_lbc_regs __iomem *fsl_lbc_regs; | 33 | struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev; |
34 | EXPORT_SYMBOL(fsl_lbc_ctrl_dev); | ||
27 | 35 | ||
28 | static char __initdata *compat_lbc[] = { | 36 | /** |
29 | "fsl,pq2-localbus", | 37 | * fsl_lbc_addr - convert the base address |
30 | "fsl,pq2pro-localbus", | 38 | * @addr_base: base address of the memory bank |
31 | "fsl,pq3-localbus", | 39 | * |
32 | "fsl,elbc", | 40 | * This function converts a base address of lbc into the right format for the |
33 | }; | 41 | * BR register. If the SOC has eLBC then it returns 32bit physical address |
34 | 42 | * else it convers a 34bit local bus physical address to correct format of | |
35 | static int __init fsl_lbc_init(void) | 43 | * 32bit address for BR register (Example: MPC8641). |
44 | */ | ||
45 | u32 fsl_lbc_addr(phys_addr_t addr_base) | ||
36 | { | 46 | { |
37 | struct device_node *lbus; | 47 | struct device_node *np = fsl_lbc_ctrl_dev->dev->of_node; |
38 | int i; | 48 | u32 addr = addr_base & 0xffff8000; |
39 | 49 | ||
40 | for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) { | 50 | if (of_device_is_compatible(np, "fsl,elbc")) |
41 | lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]); | 51 | return addr; |
42 | if (lbus) | ||
43 | goto found; | ||
44 | } | ||
45 | return -ENODEV; | ||
46 | 52 | ||
47 | found: | 53 | return addr | ((addr_base & 0x300000000ull) >> 19); |
48 | fsl_lbc_regs = of_iomap(lbus, 0); | ||
49 | of_node_put(lbus); | ||
50 | if (!fsl_lbc_regs) | ||
51 | return -ENOMEM; | ||
52 | return 0; | ||
53 | } | 54 | } |
54 | arch_initcall(fsl_lbc_init); | 55 | EXPORT_SYMBOL(fsl_lbc_addr); |
55 | 56 | ||
56 | /** | 57 | /** |
57 | * fsl_lbc_find - find Localbus bank | 58 | * fsl_lbc_find - find Localbus bank |
@@ -65,15 +66,17 @@ arch_initcall(fsl_lbc_init); | |||
65 | int fsl_lbc_find(phys_addr_t addr_base) | 66 | int fsl_lbc_find(phys_addr_t addr_base) |
66 | { | 67 | { |
67 | int i; | 68 | int i; |
69 | struct fsl_lbc_regs __iomem *lbc; | ||
68 | 70 | ||
69 | if (!fsl_lbc_regs) | 71 | if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) |
70 | return -ENODEV; | 72 | return -ENODEV; |
71 | 73 | ||
72 | for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) { | 74 | lbc = fsl_lbc_ctrl_dev->regs; |
73 | __be32 br = in_be32(&fsl_lbc_regs->bank[i].br); | 75 | for (i = 0; i < ARRAY_SIZE(lbc->bank); i++) { |
74 | __be32 or = in_be32(&fsl_lbc_regs->bank[i].or); | 76 | __be32 br = in_be32(&lbc->bank[i].br); |
77 | __be32 or = in_be32(&lbc->bank[i].or); | ||
75 | 78 | ||
76 | if (br & BR_V && (br & or & BR_BA) == addr_base) | 79 | if (br & BR_V && (br & or & BR_BA) == fsl_lbc_addr(addr_base)) |
77 | return i; | 80 | return i; |
78 | } | 81 | } |
79 | 82 | ||
@@ -94,22 +97,27 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm) | |||
94 | { | 97 | { |
95 | int bank; | 98 | int bank; |
96 | __be32 br; | 99 | __be32 br; |
100 | struct fsl_lbc_regs __iomem *lbc; | ||
97 | 101 | ||
98 | bank = fsl_lbc_find(addr_base); | 102 | bank = fsl_lbc_find(addr_base); |
99 | if (bank < 0) | 103 | if (bank < 0) |
100 | return bank; | 104 | return bank; |
101 | 105 | ||
102 | br = in_be32(&fsl_lbc_regs->bank[bank].br); | 106 | if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) |
107 | return -ENODEV; | ||
108 | |||
109 | lbc = fsl_lbc_ctrl_dev->regs; | ||
110 | br = in_be32(&lbc->bank[bank].br); | ||
103 | 111 | ||
104 | switch (br & BR_MSEL) { | 112 | switch (br & BR_MSEL) { |
105 | case BR_MS_UPMA: | 113 | case BR_MS_UPMA: |
106 | upm->mxmr = &fsl_lbc_regs->mamr; | 114 | upm->mxmr = &lbc->mamr; |
107 | break; | 115 | break; |
108 | case BR_MS_UPMB: | 116 | case BR_MS_UPMB: |
109 | upm->mxmr = &fsl_lbc_regs->mbmr; | 117 | upm->mxmr = &lbc->mbmr; |
110 | break; | 118 | break; |
111 | case BR_MS_UPMC: | 119 | case BR_MS_UPMC: |
112 | upm->mxmr = &fsl_lbc_regs->mcmr; | 120 | upm->mxmr = &lbc->mcmr; |
113 | break; | 121 | break; |
114 | default: | 122 | default: |
115 | return -EINVAL; | 123 | return -EINVAL; |
@@ -148,9 +156,12 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar) | |||
148 | int ret = 0; | 156 | int ret = 0; |
149 | unsigned long flags; | 157 | unsigned long flags; |
150 | 158 | ||
159 | if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) | ||
160 | return -ENODEV; | ||
161 | |||
151 | spin_lock_irqsave(&fsl_lbc_lock, flags); | 162 | spin_lock_irqsave(&fsl_lbc_lock, flags); |
152 | 163 | ||
153 | out_be32(&fsl_lbc_regs->mar, mar); | 164 | out_be32(&fsl_lbc_ctrl_dev->regs->mar, mar); |
154 | 165 | ||
155 | switch (upm->width) { | 166 | switch (upm->width) { |
156 | case 8: | 167 | case 8: |
@@ -172,3 +183,166 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar) | |||
172 | return ret; | 183 | return ret; |
173 | } | 184 | } |
174 | EXPORT_SYMBOL(fsl_upm_run_pattern); | 185 | EXPORT_SYMBOL(fsl_upm_run_pattern); |
186 | |||
187 | static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl) | ||
188 | { | ||
189 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | ||
190 | |||
191 | /* clear event registers */ | ||
192 | setbits32(&lbc->ltesr, LTESR_CLEAR); | ||
193 | out_be32(&lbc->lteatr, 0); | ||
194 | out_be32(&lbc->ltear, 0); | ||
195 | out_be32(&lbc->lteccr, LTECCR_CLEAR); | ||
196 | out_be32(&lbc->ltedr, LTEDR_ENABLE); | ||
197 | |||
198 | /* Enable interrupts for any detected events */ | ||
199 | out_be32(&lbc->lteir, LTEIR_ENABLE); | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | /* | ||
205 | * NOTE: This interrupt is used to report localbus events of various kinds, | ||
206 | * such as transaction errors on the chipselects. | ||
207 | */ | ||
208 | |||
209 | static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data) | ||
210 | { | ||
211 | struct fsl_lbc_ctrl *ctrl = data; | ||
212 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | ||
213 | u32 status; | ||
214 | |||
215 | status = in_be32(&lbc->ltesr); | ||
216 | if (!status) | ||
217 | return IRQ_NONE; | ||
218 | |||
219 | out_be32(&lbc->ltesr, LTESR_CLEAR); | ||
220 | out_be32(&lbc->lteatr, 0); | ||
221 | out_be32(&lbc->ltear, 0); | ||
222 | ctrl->irq_status = status; | ||
223 | |||
224 | if (status & LTESR_BM) | ||
225 | dev_err(ctrl->dev, "Local bus monitor time-out: " | ||
226 | "LTESR 0x%08X\n", status); | ||
227 | if (status & LTESR_WP) | ||
228 | dev_err(ctrl->dev, "Write protect error: " | ||
229 | "LTESR 0x%08X\n", status); | ||
230 | if (status & LTESR_ATMW) | ||
231 | dev_err(ctrl->dev, "Atomic write error: " | ||
232 | "LTESR 0x%08X\n", status); | ||
233 | if (status & LTESR_ATMR) | ||
234 | dev_err(ctrl->dev, "Atomic read error: " | ||
235 | "LTESR 0x%08X\n", status); | ||
236 | if (status & LTESR_CS) | ||
237 | dev_err(ctrl->dev, "Chip select error: " | ||
238 | "LTESR 0x%08X\n", status); | ||
239 | if (status & LTESR_UPM) | ||
240 | ; | ||
241 | if (status & LTESR_FCT) { | ||
242 | dev_err(ctrl->dev, "FCM command time-out: " | ||
243 | "LTESR 0x%08X\n", status); | ||
244 | smp_wmb(); | ||
245 | wake_up(&ctrl->irq_wait); | ||
246 | } | ||
247 | if (status & LTESR_PAR) { | ||
248 | dev_err(ctrl->dev, "Parity or Uncorrectable ECC error: " | ||
249 | "LTESR 0x%08X\n", status); | ||
250 | smp_wmb(); | ||
251 | wake_up(&ctrl->irq_wait); | ||
252 | } | ||
253 | if (status & LTESR_CC) { | ||
254 | smp_wmb(); | ||
255 | wake_up(&ctrl->irq_wait); | ||
256 | } | ||
257 | if (status & ~LTESR_MASK) | ||
258 | dev_err(ctrl->dev, "Unknown error: " | ||
259 | "LTESR 0x%08X\n", status); | ||
260 | return IRQ_HANDLED; | ||
261 | } | ||
262 | |||
263 | /* | ||
264 | * fsl_lbc_ctrl_probe | ||
265 | * | ||
266 | * called by device layer when it finds a device matching | ||
267 | * one our driver can handled. This code allocates all of | ||
268 | * the resources needed for the controller only. The | ||
269 | * resources for the NAND banks themselves are allocated | ||
270 | * in the chip probe function. | ||
271 | */ | ||
272 | |||
273 | static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev) | ||
274 | { | ||
275 | int ret; | ||
276 | |||
277 | if (!dev->dev.of_node) { | ||
278 | dev_err(&dev->dev, "Device OF-Node is NULL"); | ||
279 | return -EFAULT; | ||
280 | } | ||
281 | |||
282 | fsl_lbc_ctrl_dev = kzalloc(sizeof(*fsl_lbc_ctrl_dev), GFP_KERNEL); | ||
283 | if (!fsl_lbc_ctrl_dev) | ||
284 | return -ENOMEM; | ||
285 | |||
286 | dev_set_drvdata(&dev->dev, fsl_lbc_ctrl_dev); | ||
287 | |||
288 | spin_lock_init(&fsl_lbc_ctrl_dev->lock); | ||
289 | init_waitqueue_head(&fsl_lbc_ctrl_dev->irq_wait); | ||
290 | |||
291 | fsl_lbc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0); | ||
292 | if (!fsl_lbc_ctrl_dev->regs) { | ||
293 | dev_err(&dev->dev, "failed to get memory region\n"); | ||
294 | ret = -ENODEV; | ||
295 | goto err; | ||
296 | } | ||
297 | |||
298 | fsl_lbc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0); | ||
299 | if (fsl_lbc_ctrl_dev->irq == NO_IRQ) { | ||
300 | dev_err(&dev->dev, "failed to get irq resource\n"); | ||
301 | ret = -ENODEV; | ||
302 | goto err; | ||
303 | } | ||
304 | |||
305 | fsl_lbc_ctrl_dev->dev = &dev->dev; | ||
306 | |||
307 | ret = fsl_lbc_ctrl_init(fsl_lbc_ctrl_dev); | ||
308 | if (ret < 0) | ||
309 | goto err; | ||
310 | |||
311 | ret = request_irq(fsl_lbc_ctrl_dev->irq, fsl_lbc_ctrl_irq, 0, | ||
312 | "fsl-lbc", fsl_lbc_ctrl_dev); | ||
313 | if (ret != 0) { | ||
314 | dev_err(&dev->dev, "failed to install irq (%d)\n", | ||
315 | fsl_lbc_ctrl_dev->irq); | ||
316 | ret = fsl_lbc_ctrl_dev->irq; | ||
317 | goto err; | ||
318 | } | ||
319 | |||
320 | return 0; | ||
321 | |||
322 | err: | ||
323 | iounmap(fsl_lbc_ctrl_dev->regs); | ||
324 | kfree(fsl_lbc_ctrl_dev); | ||
325 | return ret; | ||
326 | } | ||
327 | |||
328 | static const struct of_device_id fsl_lbc_match[] = { | ||
329 | { .compatible = "fsl,elbc", }, | ||
330 | { .compatible = "fsl,pq3-localbus", }, | ||
331 | { .compatible = "fsl,pq2-localbus", }, | ||
332 | { .compatible = "fsl,pq2pro-localbus", }, | ||
333 | {}, | ||
334 | }; | ||
335 | |||
336 | static struct platform_driver fsl_lbc_ctrl_driver = { | ||
337 | .driver = { | ||
338 | .name = "fsl-lbc", | ||
339 | .of_match_table = fsl_lbc_match, | ||
340 | }, | ||
341 | .probe = fsl_lbc_ctrl_probe, | ||
342 | }; | ||
343 | |||
344 | static int __init fsl_lbc_init(void) | ||
345 | { | ||
346 | return platform_driver_register(&fsl_lbc_ctrl_driver); | ||
347 | } | ||
348 | module_init(fsl_lbc_init); | ||
diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c index 881a3a5f5647..07ea908c510d 100644 --- a/arch/sh/boards/mach-ap325rxa/setup.c +++ b/arch/sh/boards/mach-ap325rxa/setup.c | |||
@@ -176,6 +176,21 @@ static void ap320_wvga_power_off(void *board_data) | |||
176 | __raw_writew(0, FPGA_LCDREG); | 176 | __raw_writew(0, FPGA_LCDREG); |
177 | } | 177 | } |
178 | 178 | ||
179 | const static struct fb_videomode ap325rxa_lcdc_modes[] = { | ||
180 | { | ||
181 | .name = "LB070WV1", | ||
182 | .xres = 800, | ||
183 | .yres = 480, | ||
184 | .left_margin = 32, | ||
185 | .right_margin = 160, | ||
186 | .hsync_len = 8, | ||
187 | .upper_margin = 63, | ||
188 | .lower_margin = 80, | ||
189 | .vsync_len = 1, | ||
190 | .sync = 0, /* hsync and vsync are active low */ | ||
191 | }, | ||
192 | }; | ||
193 | |||
179 | static struct sh_mobile_lcdc_info lcdc_info = { | 194 | static struct sh_mobile_lcdc_info lcdc_info = { |
180 | .clock_source = LCDC_CLK_EXTERNAL, | 195 | .clock_source = LCDC_CLK_EXTERNAL, |
181 | .ch[0] = { | 196 | .ch[0] = { |
@@ -183,18 +198,8 @@ static struct sh_mobile_lcdc_info lcdc_info = { | |||
183 | .bpp = 16, | 198 | .bpp = 16, |
184 | .interface_type = RGB18, | 199 | .interface_type = RGB18, |
185 | .clock_divider = 1, | 200 | .clock_divider = 1, |
186 | .lcd_cfg = { | 201 | .lcd_cfg = ap325rxa_lcdc_modes, |
187 | .name = "LB070WV1", | 202 | .num_cfg = ARRAY_SIZE(ap325rxa_lcdc_modes), |
188 | .xres = 800, | ||
189 | .yres = 480, | ||
190 | .left_margin = 32, | ||
191 | .right_margin = 160, | ||
192 | .hsync_len = 8, | ||
193 | .upper_margin = 63, | ||
194 | .lower_margin = 80, | ||
195 | .vsync_len = 1, | ||
196 | .sync = 0, /* hsync and vsync are active low */ | ||
197 | }, | ||
198 | .lcd_size_cfg = { /* 7.0 inch */ | 203 | .lcd_size_cfg = { /* 7.0 inch */ |
199 | .width = 152, | 204 | .width = 152, |
200 | .height = 91, | 205 | .height = 91, |
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index ddc7e4e4d2a0..2eaeb9e59585 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c | |||
@@ -231,14 +231,41 @@ static struct platform_device usb1_common_device = { | |||
231 | }; | 231 | }; |
232 | 232 | ||
233 | /* LCDC */ | 233 | /* LCDC */ |
234 | const static struct fb_videomode ecovec_lcd_modes[] = { | ||
235 | { | ||
236 | .name = "Panel", | ||
237 | .xres = 800, | ||
238 | .yres = 480, | ||
239 | .left_margin = 220, | ||
240 | .right_margin = 110, | ||
241 | .hsync_len = 70, | ||
242 | .upper_margin = 20, | ||
243 | .lower_margin = 5, | ||
244 | .vsync_len = 5, | ||
245 | .sync = 0, /* hsync and vsync are active low */ | ||
246 | }, | ||
247 | }; | ||
248 | |||
249 | const static struct fb_videomode ecovec_dvi_modes[] = { | ||
250 | { | ||
251 | .name = "DVI", | ||
252 | .xres = 1280, | ||
253 | .yres = 720, | ||
254 | .left_margin = 220, | ||
255 | .right_margin = 110, | ||
256 | .hsync_len = 40, | ||
257 | .upper_margin = 20, | ||
258 | .lower_margin = 5, | ||
259 | .vsync_len = 5, | ||
260 | .sync = 0, /* hsync and vsync are active low */ | ||
261 | }, | ||
262 | }; | ||
263 | |||
234 | static struct sh_mobile_lcdc_info lcdc_info = { | 264 | static struct sh_mobile_lcdc_info lcdc_info = { |
235 | .ch[0] = { | 265 | .ch[0] = { |
236 | .interface_type = RGB18, | 266 | .interface_type = RGB18, |
237 | .chan = LCDC_CHAN_MAINLCD, | 267 | .chan = LCDC_CHAN_MAINLCD, |
238 | .bpp = 16, | 268 | .bpp = 16, |
239 | .lcd_cfg = { | ||
240 | .sync = 0, /* hsync and vsync are active low */ | ||
241 | }, | ||
242 | .lcd_size_cfg = { /* 7.0 inch */ | 269 | .lcd_size_cfg = { /* 7.0 inch */ |
243 | .width = 152, | 270 | .width = 152, |
244 | .height = 91, | 271 | .height = 91, |
@@ -1075,33 +1102,18 @@ static int __init arch_setup(void) | |||
1075 | if (gpio_get_value(GPIO_PTE6)) { | 1102 | if (gpio_get_value(GPIO_PTE6)) { |
1076 | /* DVI */ | 1103 | /* DVI */ |
1077 | lcdc_info.clock_source = LCDC_CLK_EXTERNAL; | 1104 | lcdc_info.clock_source = LCDC_CLK_EXTERNAL; |
1078 | lcdc_info.ch[0].clock_divider = 1, | 1105 | lcdc_info.ch[0].clock_divider = 1; |
1079 | lcdc_info.ch[0].lcd_cfg.name = "DVI"; | 1106 | lcdc_info.ch[0].lcd_cfg = ecovec_dvi_modes; |
1080 | lcdc_info.ch[0].lcd_cfg.xres = 1280; | 1107 | lcdc_info.ch[0].num_cfg = ARRAY_SIZE(ecovec_dvi_modes); |
1081 | lcdc_info.ch[0].lcd_cfg.yres = 720; | ||
1082 | lcdc_info.ch[0].lcd_cfg.left_margin = 220; | ||
1083 | lcdc_info.ch[0].lcd_cfg.right_margin = 110; | ||
1084 | lcdc_info.ch[0].lcd_cfg.hsync_len = 40; | ||
1085 | lcdc_info.ch[0].lcd_cfg.upper_margin = 20; | ||
1086 | lcdc_info.ch[0].lcd_cfg.lower_margin = 5; | ||
1087 | lcdc_info.ch[0].lcd_cfg.vsync_len = 5; | ||
1088 | 1108 | ||
1089 | gpio_set_value(GPIO_PTA2, 1); | 1109 | gpio_set_value(GPIO_PTA2, 1); |
1090 | gpio_set_value(GPIO_PTU1, 1); | 1110 | gpio_set_value(GPIO_PTU1, 1); |
1091 | } else { | 1111 | } else { |
1092 | /* Panel */ | 1112 | /* Panel */ |
1093 | |||
1094 | lcdc_info.clock_source = LCDC_CLK_PERIPHERAL; | 1113 | lcdc_info.clock_source = LCDC_CLK_PERIPHERAL; |
1095 | lcdc_info.ch[0].clock_divider = 2, | 1114 | lcdc_info.ch[0].clock_divider = 2; |
1096 | lcdc_info.ch[0].lcd_cfg.name = "Panel"; | 1115 | lcdc_info.ch[0].lcd_cfg = ecovec_lcd_modes; |
1097 | lcdc_info.ch[0].lcd_cfg.xres = 800; | 1116 | lcdc_info.ch[0].num_cfg = ARRAY_SIZE(ecovec_lcd_modes); |
1098 | lcdc_info.ch[0].lcd_cfg.yres = 480; | ||
1099 | lcdc_info.ch[0].lcd_cfg.left_margin = 220; | ||
1100 | lcdc_info.ch[0].lcd_cfg.right_margin = 110; | ||
1101 | lcdc_info.ch[0].lcd_cfg.hsync_len = 70; | ||
1102 | lcdc_info.ch[0].lcd_cfg.upper_margin = 20; | ||
1103 | lcdc_info.ch[0].lcd_cfg.lower_margin = 5; | ||
1104 | lcdc_info.ch[0].lcd_cfg.vsync_len = 5; | ||
1105 | 1117 | ||
1106 | gpio_set_value(GPIO_PTR1, 1); | 1118 | gpio_set_value(GPIO_PTR1, 1); |
1107 | 1119 | ||
diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c index 1742849db648..9b60eaabf8f3 100644 --- a/arch/sh/boards/mach-kfr2r09/setup.c +++ b/arch/sh/boards/mach-kfr2r09/setup.c | |||
@@ -126,6 +126,21 @@ static struct platform_device kfr2r09_sh_keysc_device = { | |||
126 | }, | 126 | }, |
127 | }; | 127 | }; |
128 | 128 | ||
129 | const static struct fb_videomode kfr2r09_lcdc_modes[] = { | ||
130 | { | ||
131 | .name = "TX07D34VM0AAA", | ||
132 | .xres = 240, | ||
133 | .yres = 400, | ||
134 | .left_margin = 0, | ||
135 | .right_margin = 16, | ||
136 | .hsync_len = 8, | ||
137 | .upper_margin = 0, | ||
138 | .lower_margin = 1, | ||
139 | .vsync_len = 1, | ||
140 | .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
141 | }, | ||
142 | }; | ||
143 | |||
129 | static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = { | 144 | static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = { |
130 | .clock_source = LCDC_CLK_BUS, | 145 | .clock_source = LCDC_CLK_BUS, |
131 | .ch[0] = { | 146 | .ch[0] = { |
@@ -134,18 +149,8 @@ static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = { | |||
134 | .interface_type = SYS18, | 149 | .interface_type = SYS18, |
135 | .clock_divider = 6, | 150 | .clock_divider = 6, |
136 | .flags = LCDC_FLAGS_DWPOL, | 151 | .flags = LCDC_FLAGS_DWPOL, |
137 | .lcd_cfg = { | 152 | .lcd_cfg = kfr2r09_lcdc_modes, |
138 | .name = "TX07D34VM0AAA", | 153 | .num_cfg = ARRAY_SIZE(kfr2r09_lcdc_modes), |
139 | .xres = 240, | ||
140 | .yres = 400, | ||
141 | .left_margin = 0, | ||
142 | .right_margin = 16, | ||
143 | .hsync_len = 8, | ||
144 | .upper_margin = 0, | ||
145 | .lower_margin = 1, | ||
146 | .vsync_len = 1, | ||
147 | .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
148 | }, | ||
149 | .lcd_size_cfg = { | 154 | .lcd_size_cfg = { |
150 | .width = 35, | 155 | .width = 35, |
151 | .height = 58, | 156 | .height = 58, |
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c index 03af84842559..c8acfec98695 100644 --- a/arch/sh/boards/mach-migor/setup.c +++ b/arch/sh/boards/mach-migor/setup.c | |||
@@ -213,51 +213,55 @@ static struct platform_device migor_nand_flash_device = { | |||
213 | } | 213 | } |
214 | }; | 214 | }; |
215 | 215 | ||
216 | const static struct fb_videomode migor_lcd_modes[] = { | ||
217 | { | ||
218 | #if defined(CONFIG_SH_MIGOR_RTA_WVGA) | ||
219 | .name = "LB070WV1", | ||
220 | .xres = 800, | ||
221 | .yres = 480, | ||
222 | .left_margin = 64, | ||
223 | .right_margin = 16, | ||
224 | .hsync_len = 120, | ||
225 | .sync = 0, | ||
226 | #elif defined(CONFIG_SH_MIGOR_QVGA) | ||
227 | .name = "PH240320T", | ||
228 | .xres = 320, | ||
229 | .yres = 240, | ||
230 | .left_margin = 0, | ||
231 | .right_margin = 16, | ||
232 | .hsync_len = 8, | ||
233 | .sync = FB_SYNC_HOR_HIGH_ACT, | ||
234 | #endif | ||
235 | .upper_margin = 1, | ||
236 | .lower_margin = 17, | ||
237 | .vsync_len = 2, | ||
238 | }, | ||
239 | }; | ||
240 | |||
216 | static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = { | 241 | static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = { |
217 | #ifdef CONFIG_SH_MIGOR_RTA_WVGA | 242 | #if defined(CONFIG_SH_MIGOR_RTA_WVGA) |
218 | .clock_source = LCDC_CLK_BUS, | 243 | .clock_source = LCDC_CLK_BUS, |
219 | .ch[0] = { | 244 | .ch[0] = { |
220 | .chan = LCDC_CHAN_MAINLCD, | 245 | .chan = LCDC_CHAN_MAINLCD, |
221 | .bpp = 16, | 246 | .bpp = 16, |
222 | .interface_type = RGB16, | 247 | .interface_type = RGB16, |
223 | .clock_divider = 2, | 248 | .clock_divider = 2, |
224 | .lcd_cfg = { | 249 | .lcd_cfg = migor_lcd_modes, |
225 | .name = "LB070WV1", | 250 | .num_cfg = ARRAY_SIZE(migor_lcd_modes), |
226 | .xres = 800, | ||
227 | .yres = 480, | ||
228 | .left_margin = 64, | ||
229 | .right_margin = 16, | ||
230 | .hsync_len = 120, | ||
231 | .upper_margin = 1, | ||
232 | .lower_margin = 17, | ||
233 | .vsync_len = 2, | ||
234 | .sync = 0, | ||
235 | }, | ||
236 | .lcd_size_cfg = { /* 7.0 inch */ | 251 | .lcd_size_cfg = { /* 7.0 inch */ |
237 | .width = 152, | 252 | .width = 152, |
238 | .height = 91, | 253 | .height = 91, |
239 | }, | 254 | }, |
240 | } | 255 | } |
241 | #endif | 256 | #elif defined(CONFIG_SH_MIGOR_QVGA) |
242 | #ifdef CONFIG_SH_MIGOR_QVGA | ||
243 | .clock_source = LCDC_CLK_PERIPHERAL, | 257 | .clock_source = LCDC_CLK_PERIPHERAL, |
244 | .ch[0] = { | 258 | .ch[0] = { |
245 | .chan = LCDC_CHAN_MAINLCD, | 259 | .chan = LCDC_CHAN_MAINLCD, |
246 | .bpp = 16, | 260 | .bpp = 16, |
247 | .interface_type = SYS16A, | 261 | .interface_type = SYS16A, |
248 | .clock_divider = 10, | 262 | .clock_divider = 10, |
249 | .lcd_cfg = { | 263 | .lcd_cfg = migor_lcd_modes, |
250 | .name = "PH240320T", | 264 | .num_cfg = ARRAY_SIZE(migor_lcd_modes), |
251 | .xres = 320, | ||
252 | .yres = 240, | ||
253 | .left_margin = 0, | ||
254 | .right_margin = 16, | ||
255 | .hsync_len = 8, | ||
256 | .upper_margin = 1, | ||
257 | .lower_margin = 17, | ||
258 | .vsync_len = 2, | ||
259 | .sync = FB_SYNC_HOR_HIGH_ACT, | ||
260 | }, | ||
261 | .lcd_size_cfg = { /* 2.4 inch */ | 265 | .lcd_size_cfg = { /* 2.4 inch */ |
262 | .width = 49, | 266 | .width = 49, |
263 | .height = 37, | 267 | .height = 37, |
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index 8cc1d7295d85..c31d228fdfc6 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c | |||
@@ -144,16 +144,42 @@ static struct platform_device nor_flash_device = { | |||
144 | }; | 144 | }; |
145 | 145 | ||
146 | /* LCDC */ | 146 | /* LCDC */ |
147 | const static struct fb_videomode lcdc_720p_modes[] = { | ||
148 | { | ||
149 | .name = "LB070WV1", | ||
150 | .sync = 0, /* hsync and vsync are active low */ | ||
151 | .xres = 1280, | ||
152 | .yres = 720, | ||
153 | .left_margin = 220, | ||
154 | .right_margin = 110, | ||
155 | .hsync_len = 40, | ||
156 | .upper_margin = 20, | ||
157 | .lower_margin = 5, | ||
158 | .vsync_len = 5, | ||
159 | }, | ||
160 | }; | ||
161 | |||
162 | const static struct fb_videomode lcdc_vga_modes[] = { | ||
163 | { | ||
164 | .name = "LB070WV1", | ||
165 | .sync = 0, /* hsync and vsync are active low */ | ||
166 | .xres = 640, | ||
167 | .yres = 480, | ||
168 | .left_margin = 105, | ||
169 | .right_margin = 50, | ||
170 | .hsync_len = 96, | ||
171 | .upper_margin = 33, | ||
172 | .lower_margin = 10, | ||
173 | .vsync_len = 2, | ||
174 | }, | ||
175 | }; | ||
176 | |||
147 | static struct sh_mobile_lcdc_info lcdc_info = { | 177 | static struct sh_mobile_lcdc_info lcdc_info = { |
148 | .clock_source = LCDC_CLK_EXTERNAL, | 178 | .clock_source = LCDC_CLK_EXTERNAL, |
149 | .ch[0] = { | 179 | .ch[0] = { |
150 | .chan = LCDC_CHAN_MAINLCD, | 180 | .chan = LCDC_CHAN_MAINLCD, |
151 | .bpp = 16, | 181 | .bpp = 16, |
152 | .clock_divider = 1, | 182 | .clock_divider = 1, |
153 | .lcd_cfg = { | ||
154 | .name = "LB070WV1", | ||
155 | .sync = 0, /* hsync and vsync are active low */ | ||
156 | }, | ||
157 | .lcd_size_cfg = { /* 7.0 inch */ | 183 | .lcd_size_cfg = { /* 7.0 inch */ |
158 | .width = 152, | 184 | .width = 152, |
159 | .height = 91, | 185 | .height = 91, |
@@ -908,24 +934,12 @@ static int __init devices_setup(void) | |||
908 | 934 | ||
909 | if (sw & SW41_B) { | 935 | if (sw & SW41_B) { |
910 | /* 720p */ | 936 | /* 720p */ |
911 | lcdc_info.ch[0].lcd_cfg.xres = 1280; | 937 | lcdc_info.ch[0].lcd_cfg = lcdc_720p_modes; |
912 | lcdc_info.ch[0].lcd_cfg.yres = 720; | 938 | lcdc_info.ch[0].num_cfg = ARRAY_SIZE(lcdc_720p_modes); |
913 | lcdc_info.ch[0].lcd_cfg.left_margin = 220; | ||
914 | lcdc_info.ch[0].lcd_cfg.right_margin = 110; | ||
915 | lcdc_info.ch[0].lcd_cfg.hsync_len = 40; | ||
916 | lcdc_info.ch[0].lcd_cfg.upper_margin = 20; | ||
917 | lcdc_info.ch[0].lcd_cfg.lower_margin = 5; | ||
918 | lcdc_info.ch[0].lcd_cfg.vsync_len = 5; | ||
919 | } else { | 939 | } else { |
920 | /* VGA */ | 940 | /* VGA */ |
921 | lcdc_info.ch[0].lcd_cfg.xres = 640; | 941 | lcdc_info.ch[0].lcd_cfg = lcdc_vga_modes; |
922 | lcdc_info.ch[0].lcd_cfg.yres = 480; | 942 | lcdc_info.ch[0].num_cfg = ARRAY_SIZE(lcdc_vga_modes); |
923 | lcdc_info.ch[0].lcd_cfg.left_margin = 105; | ||
924 | lcdc_info.ch[0].lcd_cfg.right_margin = 50; | ||
925 | lcdc_info.ch[0].lcd_cfg.hsync_len = 96; | ||
926 | lcdc_info.ch[0].lcd_cfg.upper_margin = 33; | ||
927 | lcdc_info.ch[0].lcd_cfg.lower_margin = 10; | ||
928 | lcdc_info.ch[0].lcd_cfg.vsync_len = 2; | ||
929 | } | 943 | } |
930 | 944 | ||
931 | if (sw & SW41_A) { | 945 | if (sw & SW41_A) { |
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 9e2b7e9e0ad9..ad9268b44416 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c | |||
@@ -1496,7 +1496,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, | |||
1496 | 1496 | ||
1497 | switch (mode) { | 1497 | switch (mode) { |
1498 | case FL_WRITING: | 1498 | case FL_WRITING: |
1499 | write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0x40) : CMD(0x41); | 1499 | write_cmd = (cfi->cfiq->P_ID != P_ID_INTEL_PERFORMANCE) ? CMD(0x40) : CMD(0x41); |
1500 | break; | 1500 | break; |
1501 | case FL_OTP_WRITE: | 1501 | case FL_OTP_WRITE: |
1502 | write_cmd = CMD(0xc0); | 1502 | write_cmd = CMD(0xc0); |
@@ -1661,7 +1661,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
1661 | cmd_adr = adr & ~(wbufsize-1); | 1661 | cmd_adr = adr & ~(wbufsize-1); |
1662 | 1662 | ||
1663 | /* Let's determine this according to the interleave only once */ | 1663 | /* Let's determine this according to the interleave only once */ |
1664 | write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0xe8) : CMD(0xe9); | 1664 | write_cmd = (cfi->cfiq->P_ID != P_ID_INTEL_PERFORMANCE) ? CMD(0xe8) : CMD(0xe9); |
1665 | 1665 | ||
1666 | mutex_lock(&chip->mutex); | 1666 | mutex_lock(&chip->mutex); |
1667 | ret = get_chip(map, chip, cmd_adr, FL_WRITING); | 1667 | ret = get_chip(map, chip, cmd_adr, FL_WRITING); |
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index ba29d2f0ffd7..3b8e32d87977 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | |||
@@ -291,6 +291,23 @@ static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param) | |||
291 | 291 | ||
292 | cfi->addr_unlock1 = 0x555; | 292 | cfi->addr_unlock1 = 0x555; |
293 | cfi->addr_unlock2 = 0x2AA; | 293 | cfi->addr_unlock2 = 0x2AA; |
294 | |||
295 | cfi->sector_erase_cmd = CMD(0x50); | ||
296 | } | ||
297 | |||
298 | static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd, void *param) | ||
299 | { | ||
300 | struct map_info *map = mtd->priv; | ||
301 | struct cfi_private *cfi = map->fldrv_priv; | ||
302 | |||
303 | fixup_sst39vf_rev_b(mtd, param); | ||
304 | |||
305 | /* | ||
306 | * CFI reports 1024 sectors (0x03ff+1) of 64KBytes (0x0100*256) where | ||
307 | * it should report a size of 8KBytes (0x0020*256). | ||
308 | */ | ||
309 | cfi->cfiq->EraseRegionInfo[0] = 0x002003ff; | ||
310 | pr_warning("%s: Bad 38VF640x CFI data; adjusting sector size from 64 to 8KiB\n", mtd->name); | ||
294 | } | 311 | } |
295 | 312 | ||
296 | static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param) | 313 | static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param) |
@@ -317,14 +334,14 @@ static void fixup_s29gl032n_sectors(struct mtd_info *mtd, void *param) | |||
317 | 334 | ||
318 | /* Used to fix CFI-Tables of chips without Extended Query Tables */ | 335 | /* Used to fix CFI-Tables of chips without Extended Query Tables */ |
319 | static struct cfi_fixup cfi_nopri_fixup_table[] = { | 336 | static struct cfi_fixup cfi_nopri_fixup_table[] = { |
320 | { CFI_MFR_SST, 0x234A, fixup_sst39vf, NULL, }, // SST39VF1602 | 337 | { CFI_MFR_SST, 0x234A, fixup_sst39vf, NULL, }, /* SST39VF1602 */ |
321 | { CFI_MFR_SST, 0x234B, fixup_sst39vf, NULL, }, // SST39VF1601 | 338 | { CFI_MFR_SST, 0x234B, fixup_sst39vf, NULL, }, /* SST39VF1601 */ |
322 | { CFI_MFR_SST, 0x235A, fixup_sst39vf, NULL, }, // SST39VF3202 | 339 | { CFI_MFR_SST, 0x235A, fixup_sst39vf, NULL, }, /* SST39VF3202 */ |
323 | { CFI_MFR_SST, 0x235B, fixup_sst39vf, NULL, }, // SST39VF3201 | 340 | { CFI_MFR_SST, 0x235B, fixup_sst39vf, NULL, }, /* SST39VF3201 */ |
324 | { CFI_MFR_SST, 0x235C, fixup_sst39vf_rev_b, NULL, }, // SST39VF3202B | 341 | { CFI_MFR_SST, 0x235C, fixup_sst39vf_rev_b, NULL, }, /* SST39VF3202B */ |
325 | { CFI_MFR_SST, 0x235D, fixup_sst39vf_rev_b, NULL, }, // SST39VF3201B | 342 | { CFI_MFR_SST, 0x235D, fixup_sst39vf_rev_b, NULL, }, /* SST39VF3201B */ |
326 | { CFI_MFR_SST, 0x236C, fixup_sst39vf_rev_b, NULL, }, // SST39VF6402B | 343 | { CFI_MFR_SST, 0x236C, fixup_sst39vf_rev_b, NULL, }, /* SST39VF6402B */ |
327 | { CFI_MFR_SST, 0x236D, fixup_sst39vf_rev_b, NULL, }, // SST39VF6401B | 344 | { CFI_MFR_SST, 0x236D, fixup_sst39vf_rev_b, NULL, }, /* SST39VF6401B */ |
328 | { 0, 0, NULL, NULL } | 345 | { 0, 0, NULL, NULL } |
329 | }; | 346 | }; |
330 | 347 | ||
@@ -344,6 +361,10 @@ static struct cfi_fixup cfi_fixup_table[] = { | |||
344 | { CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, }, | 361 | { CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, }, |
345 | { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, }, | 362 | { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, }, |
346 | { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, }, | 363 | { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, }, |
364 | { CFI_MFR_SST, 0x536A, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6402 */ | ||
365 | { CFI_MFR_SST, 0x536B, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6401 */ | ||
366 | { CFI_MFR_SST, 0x536C, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6404 */ | ||
367 | { CFI_MFR_SST, 0x536D, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6403 */ | ||
347 | #if !FORCE_WORD_WRITE | 368 | #if !FORCE_WORD_WRITE |
348 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, }, | 369 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, }, |
349 | #endif | 370 | #endif |
@@ -374,6 +395,13 @@ static void cfi_fixup_major_minor(struct cfi_private *cfi, | |||
374 | if (cfi->mfr == CFI_MFR_SAMSUNG && cfi->id == 0x257e && | 395 | if (cfi->mfr == CFI_MFR_SAMSUNG && cfi->id == 0x257e && |
375 | extp->MajorVersion == '0') | 396 | extp->MajorVersion == '0') |
376 | extp->MajorVersion = '1'; | 397 | extp->MajorVersion = '1'; |
398 | /* | ||
399 | * SST 38VF640x chips report major=0xFF / minor=0xFF. | ||
400 | */ | ||
401 | if (cfi->mfr == CFI_MFR_SST && (cfi->id >> 4) == 0x0536) { | ||
402 | extp->MajorVersion = '1'; | ||
403 | extp->MinorVersion = '0'; | ||
404 | } | ||
377 | } | 405 | } |
378 | 406 | ||
379 | struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) | 407 | struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) |
@@ -545,15 +573,6 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) | |||
545 | printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize); | 573 | printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize); |
546 | goto setup_err; | 574 | goto setup_err; |
547 | } | 575 | } |
548 | #if 0 | ||
549 | // debug | ||
550 | for (i=0; i<mtd->numeraseregions;i++){ | ||
551 | printk("%d: offset=0x%x,size=0x%x,blocks=%d\n", | ||
552 | i,mtd->eraseregions[i].offset, | ||
553 | mtd->eraseregions[i].erasesize, | ||
554 | mtd->eraseregions[i].numblocks); | ||
555 | } | ||
556 | #endif | ||
557 | 576 | ||
558 | __module_get(THIS_MODULE); | 577 | __module_get(THIS_MODULE); |
559 | register_reboot_notifier(&mtd->reboot_notifier); | 578 | register_reboot_notifier(&mtd->reboot_notifier); |
@@ -674,7 +693,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr | |||
674 | * there was an error (so leave the erase | 693 | * there was an error (so leave the erase |
675 | * routine to recover from it) or we trying to | 694 | * routine to recover from it) or we trying to |
676 | * use the erase-in-progress sector. */ | 695 | * use the erase-in-progress sector. */ |
677 | map_write(map, CMD(0x30), chip->in_progress_block_addr); | 696 | map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr); |
678 | chip->state = FL_ERASING; | 697 | chip->state = FL_ERASING; |
679 | chip->oldstate = FL_READY; | 698 | chip->oldstate = FL_READY; |
680 | printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__); | 699 | printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__); |
@@ -727,7 +746,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad | |||
727 | switch(chip->oldstate) { | 746 | switch(chip->oldstate) { |
728 | case FL_ERASING: | 747 | case FL_ERASING: |
729 | chip->state = chip->oldstate; | 748 | chip->state = chip->oldstate; |
730 | map_write(map, CMD(0x30), chip->in_progress_block_addr); | 749 | map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr); |
731 | chip->oldstate = FL_READY; | 750 | chip->oldstate = FL_READY; |
732 | chip->state = FL_ERASING; | 751 | chip->state = FL_ERASING; |
733 | break; | 752 | break; |
@@ -870,7 +889,7 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip, | |||
870 | local_irq_disable(); | 889 | local_irq_disable(); |
871 | 890 | ||
872 | /* Resume the write or erase operation */ | 891 | /* Resume the write or erase operation */ |
873 | map_write(map, CMD(0x30), adr); | 892 | map_write(map, cfi->sector_erase_cmd, adr); |
874 | chip->state = oldstate; | 893 | chip->state = oldstate; |
875 | start = xip_currtime(); | 894 | start = xip_currtime(); |
876 | } else if (usec >= 1000000/HZ) { | 895 | } else if (usec >= 1000000/HZ) { |
@@ -1025,9 +1044,6 @@ static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chi | |||
1025 | mutex_lock(&chip->mutex); | 1044 | mutex_lock(&chip->mutex); |
1026 | 1045 | ||
1027 | if (chip->state != FL_READY){ | 1046 | if (chip->state != FL_READY){ |
1028 | #if 0 | ||
1029 | printk(KERN_DEBUG "Waiting for chip to read, status = %d\n", chip->state); | ||
1030 | #endif | ||
1031 | set_current_state(TASK_UNINTERRUPTIBLE); | 1047 | set_current_state(TASK_UNINTERRUPTIBLE); |
1032 | add_wait_queue(&chip->wq, &wait); | 1048 | add_wait_queue(&chip->wq, &wait); |
1033 | 1049 | ||
@@ -1035,10 +1051,6 @@ static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chi | |||
1035 | 1051 | ||
1036 | schedule(); | 1052 | schedule(); |
1037 | remove_wait_queue(&chip->wq, &wait); | 1053 | remove_wait_queue(&chip->wq, &wait); |
1038 | #if 0 | ||
1039 | if(signal_pending(current)) | ||
1040 | return -EINTR; | ||
1041 | #endif | ||
1042 | timeo = jiffies + HZ; | 1054 | timeo = jiffies + HZ; |
1043 | 1055 | ||
1044 | goto retry; | 1056 | goto retry; |
@@ -1246,9 +1258,6 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, | |||
1246 | mutex_lock(&cfi->chips[chipnum].mutex); | 1258 | mutex_lock(&cfi->chips[chipnum].mutex); |
1247 | 1259 | ||
1248 | if (cfi->chips[chipnum].state != FL_READY) { | 1260 | if (cfi->chips[chipnum].state != FL_READY) { |
1249 | #if 0 | ||
1250 | printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state); | ||
1251 | #endif | ||
1252 | set_current_state(TASK_UNINTERRUPTIBLE); | 1261 | set_current_state(TASK_UNINTERRUPTIBLE); |
1253 | add_wait_queue(&cfi->chips[chipnum].wq, &wait); | 1262 | add_wait_queue(&cfi->chips[chipnum].wq, &wait); |
1254 | 1263 | ||
@@ -1256,10 +1265,6 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, | |||
1256 | 1265 | ||
1257 | schedule(); | 1266 | schedule(); |
1258 | remove_wait_queue(&cfi->chips[chipnum].wq, &wait); | 1267 | remove_wait_queue(&cfi->chips[chipnum].wq, &wait); |
1259 | #if 0 | ||
1260 | if(signal_pending(current)) | ||
1261 | return -EINTR; | ||
1262 | #endif | ||
1263 | goto retry; | 1268 | goto retry; |
1264 | } | 1269 | } |
1265 | 1270 | ||
@@ -1324,9 +1329,6 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, | |||
1324 | mutex_lock(&cfi->chips[chipnum].mutex); | 1329 | mutex_lock(&cfi->chips[chipnum].mutex); |
1325 | 1330 | ||
1326 | if (cfi->chips[chipnum].state != FL_READY) { | 1331 | if (cfi->chips[chipnum].state != FL_READY) { |
1327 | #if 0 | ||
1328 | printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state); | ||
1329 | #endif | ||
1330 | set_current_state(TASK_UNINTERRUPTIBLE); | 1332 | set_current_state(TASK_UNINTERRUPTIBLE); |
1331 | add_wait_queue(&cfi->chips[chipnum].wq, &wait); | 1333 | add_wait_queue(&cfi->chips[chipnum].wq, &wait); |
1332 | 1334 | ||
@@ -1334,10 +1336,6 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len, | |||
1334 | 1336 | ||
1335 | schedule(); | 1337 | schedule(); |
1336 | remove_wait_queue(&cfi->chips[chipnum].wq, &wait); | 1338 | remove_wait_queue(&cfi->chips[chipnum].wq, &wait); |
1337 | #if 0 | ||
1338 | if(signal_pending(current)) | ||
1339 | return -EINTR; | ||
1340 | #endif | ||
1341 | goto retry1; | 1339 | goto retry1; |
1342 | } | 1340 | } |
1343 | 1341 | ||
@@ -1396,7 +1394,6 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | |||
1396 | 1394 | ||
1397 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | 1395 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); |
1398 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); | 1396 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); |
1399 | //cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | ||
1400 | 1397 | ||
1401 | /* Write Buffer Load */ | 1398 | /* Write Buffer Load */ |
1402 | map_write(map, CMD(0x25), cmd_adr); | 1399 | map_write(map, CMD(0x25), cmd_adr); |
@@ -1675,7 +1672,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, | |||
1675 | cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | 1672 | cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); |
1676 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); | 1673 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); |
1677 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); | 1674 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); |
1678 | map_write(map, CMD(0x30), adr); | 1675 | map_write(map, cfi->sector_erase_cmd, adr); |
1679 | 1676 | ||
1680 | chip->state = FL_ERASING; | 1677 | chip->state = FL_ERASING; |
1681 | chip->erase_suspended = 0; | 1678 | chip->erase_suspended = 0; |
diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c index 8f5b96aa87a0..d25535279404 100644 --- a/drivers/mtd/chips/cfi_probe.c +++ b/drivers/mtd/chips/cfi_probe.c | |||
@@ -177,6 +177,8 @@ static int __xipram cfi_chip_setup(struct map_info *map, | |||
177 | 177 | ||
178 | cfi->cfi_mode = CFI_MODE_CFI; | 178 | cfi->cfi_mode = CFI_MODE_CFI; |
179 | 179 | ||
180 | cfi->sector_erase_cmd = CMD(0x30); | ||
181 | |||
180 | /* Read the CFI info structure */ | 182 | /* Read the CFI info structure */ |
181 | xip_disable_qry(base, map, cfi); | 183 | xip_disable_qry(base, map, cfi); |
182 | for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++) | 184 | for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++) |
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c index e503b2ca894d..360525c637d2 100644 --- a/drivers/mtd/chips/cfi_util.c +++ b/drivers/mtd/chips/cfi_util.c | |||
@@ -77,6 +77,13 @@ int __xipram cfi_qry_mode_on(uint32_t base, struct map_info *map, | |||
77 | cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL); | 77 | cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL); |
78 | if (cfi_qry_present(map, base, cfi)) | 78 | if (cfi_qry_present(map, base, cfi)) |
79 | return 1; | 79 | return 1; |
80 | /* SST 39VF640xB */ | ||
81 | cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); | ||
82 | cfi_send_gen_cmd(0xAA, 0x555, base, map, cfi, cfi->device_type, NULL); | ||
83 | cfi_send_gen_cmd(0x55, 0x2AA, base, map, cfi, cfi->device_type, NULL); | ||
84 | cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL); | ||
85 | if (cfi_qry_present(map, base, cfi)) | ||
86 | return 1; | ||
80 | /* QRY not found */ | 87 | /* QRY not found */ |
81 | return 0; | 88 | return 0; |
82 | } | 89 | } |
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 93651865ddbe..2cf0cc6a4189 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c | |||
@@ -91,7 +91,6 @@ static int block2mtd_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
91 | } else | 91 | } else |
92 | instr->state = MTD_ERASE_DONE; | 92 | instr->state = MTD_ERASE_DONE; |
93 | 93 | ||
94 | instr->state = MTD_ERASE_DONE; | ||
95 | mtd_erase_callback(instr); | 94 | mtd_erase_callback(instr); |
96 | return err; | 95 | return err; |
97 | } | 96 | } |
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index ea22520c0406..bf5a002209bd 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -661,11 +661,14 @@ static const struct spi_device_id m25p_ids[] = { | |||
661 | { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) }, | 661 | { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) }, |
662 | { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) }, | 662 | { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) }, |
663 | { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) }, | 663 | { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) }, |
664 | { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SECT_4K) }, | ||
664 | { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) }, | 665 | { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) }, |
665 | { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, | 666 | { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, |
666 | { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, | 667 | { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, |
667 | { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, | 668 | { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, |
668 | { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) }, | 669 | { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) }, |
670 | { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) }, | ||
671 | { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, | ||
669 | 672 | ||
670 | /* SST -- large erase sizes are "overlays", "sectors" are 4K */ | 673 | /* SST -- large erase sizes are "overlays", "sectors" are 4K */ |
671 | { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K) }, | 674 | { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K) }, |
@@ -714,6 +717,7 @@ static const struct spi_device_id m25p_ids[] = { | |||
714 | { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, | 717 | { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, |
715 | { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, | 718 | { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, |
716 | { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, | 719 | { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, |
720 | { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, | ||
717 | 721 | ||
718 | /* Catalyst / On Semiconductor -- non-JEDEC */ | 722 | /* Catalyst / On Semiconductor -- non-JEDEC */ |
719 | { "cat25c11", CAT25_INFO( 16, 8, 16, 1) }, | 723 | { "cat25c11", CAT25_INFO( 16, 8, 16, 1) }, |
@@ -924,7 +928,7 @@ static int __devinit m25p_probe(struct spi_device *spi) | |||
924 | nr_parts = data->nr_parts; | 928 | nr_parts = data->nr_parts; |
925 | } | 929 | } |
926 | 930 | ||
927 | #ifdef CONFIG_OF | 931 | #ifdef CONFIG_MTD_OF_PARTS |
928 | if (nr_parts <= 0 && spi->dev.of_node) { | 932 | if (nr_parts <= 0 && spi->dev.of_node) { |
929 | nr_parts = of_mtd_parse_partitions(&spi->dev, | 933 | nr_parts = of_mtd_parse_partitions(&spi->dev, |
930 | spi->dev.of_node, &parts); | 934 | spi->dev.of_node, &parts); |
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c index 1696bbecaa7e..52393282eaf1 100644 --- a/drivers/mtd/devices/phram.c +++ b/drivers/mtd/devices/phram.c | |||
@@ -15,7 +15,7 @@ | |||
15 | * phram=swap,64Mi,128Mi phram=test,900Mi,1Mi | 15 | * phram=swap,64Mi,128Mi phram=test,900Mi,1Mi |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #define pr_fmt(fmt) "phram: " fmt | 18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
19 | 19 | ||
20 | #include <asm/io.h> | 20 | #include <asm/io.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 962212628f6e..a0dd7bba9481 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
@@ -251,6 +251,15 @@ config MTD_NETtel | |||
251 | help | 251 | help |
252 | Support for flash chips on NETtel/SecureEdge/SnapGear boards. | 252 | Support for flash chips on NETtel/SecureEdge/SnapGear boards. |
253 | 253 | ||
254 | config MTD_BCM963XX | ||
255 | tristate "Map driver for Broadcom BCM963xx boards" | ||
256 | depends on BCM63XX | ||
257 | select MTD_MAP_BANK_WIDTH_2 | ||
258 | select MTD_CFI_I1 | ||
259 | help | ||
260 | Support for parsing CFE image tag and creating MTD partitions on | ||
261 | Broadcom BCM63xx boards. | ||
262 | |||
254 | config MTD_DILNETPC | 263 | config MTD_DILNETPC |
255 | tristate "CFI Flash device mapped on DIL/Net PC" | 264 | tristate "CFI Flash device mapped on DIL/Net PC" |
256 | depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN | 265 | depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN |
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index f216bb573713..c7869c7a6b18 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile | |||
@@ -58,3 +58,4 @@ obj-$(CONFIG_MTD_BFIN_ASYNC) += bfin-async-flash.o | |||
58 | obj-$(CONFIG_MTD_RBTX4939) += rbtx4939-flash.o | 58 | obj-$(CONFIG_MTD_RBTX4939) += rbtx4939-flash.o |
59 | obj-$(CONFIG_MTD_VMU) += vmu-flash.o | 59 | obj-$(CONFIG_MTD_VMU) += vmu-flash.o |
60 | obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o | 60 | obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o |
61 | obj-$(CONFIG_MTD_BCM963XX) += bcm963xx-flash.o | ||
diff --git a/drivers/mtd/maps/bcm963xx-flash.c b/drivers/mtd/maps/bcm963xx-flash.c new file mode 100644 index 000000000000..d175c120ee84 --- /dev/null +++ b/drivers/mtd/maps/bcm963xx-flash.c | |||
@@ -0,0 +1,271 @@ | |||
1 | /* | ||
2 | * Copyright © 2006-2008 Florian Fainelli <florian@openwrt.org> | ||
3 | * Mike Albon <malbon@openwrt.org> | ||
4 | * Copyright © 2009-2010 Daniel Dickinson <openwrt@cshore.neomailbox.net> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/init.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/mtd/map.h> | ||
25 | #include <linux/mtd/mtd.h> | ||
26 | #include <linux/mtd/partitions.h> | ||
27 | #include <linux/vmalloc.h> | ||
28 | #include <linux/platform_device.h> | ||
29 | #include <linux/io.h> | ||
30 | |||
31 | #include <asm/mach-bcm63xx/bcm963xx_tag.h> | ||
32 | |||
33 | #define BCM63XX_BUSWIDTH 2 /* Buswidth */ | ||
34 | #define BCM63XX_EXTENDED_SIZE 0xBFC00000 /* Extended flash address */ | ||
35 | |||
36 | #define PFX KBUILD_MODNAME ": " | ||
37 | |||
38 | static struct mtd_partition *parsed_parts; | ||
39 | |||
40 | static struct mtd_info *bcm963xx_mtd_info; | ||
41 | |||
42 | static struct map_info bcm963xx_map = { | ||
43 | .name = "bcm963xx", | ||
44 | .bankwidth = BCM63XX_BUSWIDTH, | ||
45 | }; | ||
46 | |||
47 | static int parse_cfe_partitions(struct mtd_info *master, | ||
48 | struct mtd_partition **pparts) | ||
49 | { | ||
50 | /* CFE, NVRAM and global Linux are always present */ | ||
51 | int nrparts = 3, curpart = 0; | ||
52 | struct bcm_tag *buf; | ||
53 | struct mtd_partition *parts; | ||
54 | int ret; | ||
55 | size_t retlen; | ||
56 | unsigned int rootfsaddr, kerneladdr, spareaddr; | ||
57 | unsigned int rootfslen, kernellen, sparelen, totallen; | ||
58 | int namelen = 0; | ||
59 | int i; | ||
60 | char *boardid; | ||
61 | char *tagversion; | ||
62 | |||
63 | /* Allocate memory for buffer */ | ||
64 | buf = vmalloc(sizeof(struct bcm_tag)); | ||
65 | if (!buf) | ||
66 | return -ENOMEM; | ||
67 | |||
68 | /* Get the tag */ | ||
69 | ret = master->read(master, master->erasesize, sizeof(struct bcm_tag), | ||
70 | &retlen, (void *)buf); | ||
71 | if (retlen != sizeof(struct bcm_tag)) { | ||
72 | vfree(buf); | ||
73 | return -EIO; | ||
74 | } | ||
75 | |||
76 | sscanf(buf->kernel_address, "%u", &kerneladdr); | ||
77 | sscanf(buf->kernel_length, "%u", &kernellen); | ||
78 | sscanf(buf->total_length, "%u", &totallen); | ||
79 | tagversion = &(buf->tag_version[0]); | ||
80 | boardid = &(buf->board_id[0]); | ||
81 | |||
82 | printk(KERN_INFO PFX "CFE boot tag found with version %s " | ||
83 | "and board type %s\n", tagversion, boardid); | ||
84 | |||
85 | kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE; | ||
86 | rootfsaddr = kerneladdr + kernellen; | ||
87 | spareaddr = roundup(totallen, master->erasesize) + master->erasesize; | ||
88 | sparelen = master->size - spareaddr - master->erasesize; | ||
89 | rootfslen = spareaddr - rootfsaddr; | ||
90 | |||
91 | /* Determine number of partitions */ | ||
92 | namelen = 8; | ||
93 | if (rootfslen > 0) { | ||
94 | nrparts++; | ||
95 | namelen += 6; | ||
96 | }; | ||
97 | if (kernellen > 0) { | ||
98 | nrparts++; | ||
99 | namelen += 6; | ||
100 | }; | ||
101 | |||
102 | /* Ask kernel for more memory */ | ||
103 | parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL); | ||
104 | if (!parts) { | ||
105 | vfree(buf); | ||
106 | return -ENOMEM; | ||
107 | }; | ||
108 | |||
109 | /* Start building partition list */ | ||
110 | parts[curpart].name = "CFE"; | ||
111 | parts[curpart].offset = 0; | ||
112 | parts[curpart].size = master->erasesize; | ||
113 | curpart++; | ||
114 | |||
115 | if (kernellen > 0) { | ||
116 | parts[curpart].name = "kernel"; | ||
117 | parts[curpart].offset = kerneladdr; | ||
118 | parts[curpart].size = kernellen; | ||
119 | curpart++; | ||
120 | }; | ||
121 | |||
122 | if (rootfslen > 0) { | ||
123 | parts[curpart].name = "rootfs"; | ||
124 | parts[curpart].offset = rootfsaddr; | ||
125 | parts[curpart].size = rootfslen; | ||
126 | if (sparelen > 0) | ||
127 | parts[curpart].size += sparelen; | ||
128 | curpart++; | ||
129 | }; | ||
130 | |||
131 | parts[curpart].name = "nvram"; | ||
132 | parts[curpart].offset = master->size - master->erasesize; | ||
133 | parts[curpart].size = master->erasesize; | ||
134 | |||
135 | /* Global partition "linux" to make easy firmware upgrade */ | ||
136 | curpart++; | ||
137 | parts[curpart].name = "linux"; | ||
138 | parts[curpart].offset = parts[0].size; | ||
139 | parts[curpart].size = master->size - parts[0].size - parts[3].size; | ||
140 | |||
141 | for (i = 0; i < nrparts; i++) | ||
142 | printk(KERN_INFO PFX "Partition %d is %s offset %lx and " | ||
143 | "length %lx\n", i, parts[i].name, | ||
144 | (long unsigned int)(parts[i].offset), | ||
145 | (long unsigned int)(parts[i].size)); | ||
146 | |||
147 | printk(KERN_INFO PFX "Spare partition is %x offset and length %x\n", | ||
148 | spareaddr, sparelen); | ||
149 | *pparts = parts; | ||
150 | vfree(buf); | ||
151 | |||
152 | return nrparts; | ||
153 | }; | ||
154 | |||
155 | static int bcm963xx_detect_cfe(struct mtd_info *master) | ||
156 | { | ||
157 | int idoffset = 0x4e0; | ||
158 | static char idstring[8] = "CFE1CFE1"; | ||
159 | char buf[9]; | ||
160 | int ret; | ||
161 | size_t retlen; | ||
162 | |||
163 | ret = master->read(master, idoffset, 8, &retlen, (void *)buf); | ||
164 | buf[retlen] = 0; | ||
165 | printk(KERN_INFO PFX "Read Signature value of %s\n", buf); | ||
166 | |||
167 | return strncmp(idstring, buf, 8); | ||
168 | } | ||
169 | |||
170 | static int bcm963xx_probe(struct platform_device *pdev) | ||
171 | { | ||
172 | int err = 0; | ||
173 | int parsed_nr_parts = 0; | ||
174 | char *part_type; | ||
175 | struct resource *r; | ||
176 | |||
177 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
178 | if (!r) { | ||
179 | dev_err(&pdev->dev, "no resource supplied\n"); | ||
180 | return -ENODEV; | ||
181 | } | ||
182 | |||
183 | bcm963xx_map.phys = r->start; | ||
184 | bcm963xx_map.size = resource_size(r); | ||
185 | bcm963xx_map.virt = ioremap(r->start, resource_size(r)); | ||
186 | if (!bcm963xx_map.virt) { | ||
187 | dev_err(&pdev->dev, "failed to ioremap\n"); | ||
188 | return -EIO; | ||
189 | } | ||
190 | |||
191 | dev_info(&pdev->dev, "0x%08lx at 0x%08x\n", | ||
192 | bcm963xx_map.size, bcm963xx_map.phys); | ||
193 | |||
194 | simple_map_init(&bcm963xx_map); | ||
195 | |||
196 | bcm963xx_mtd_info = do_map_probe("cfi_probe", &bcm963xx_map); | ||
197 | if (!bcm963xx_mtd_info) { | ||
198 | dev_err(&pdev->dev, "failed to probe using CFI\n"); | ||
199 | err = -EIO; | ||
200 | goto err_probe; | ||
201 | } | ||
202 | |||
203 | bcm963xx_mtd_info->owner = THIS_MODULE; | ||
204 | |||
205 | /* This is mutually exclusive */ | ||
206 | if (bcm963xx_detect_cfe(bcm963xx_mtd_info) == 0) { | ||
207 | dev_info(&pdev->dev, "CFE bootloader detected\n"); | ||
208 | if (parsed_nr_parts == 0) { | ||
209 | int ret = parse_cfe_partitions(bcm963xx_mtd_info, | ||
210 | &parsed_parts); | ||
211 | if (ret > 0) { | ||
212 | part_type = "CFE"; | ||
213 | parsed_nr_parts = ret; | ||
214 | } | ||
215 | } | ||
216 | } else { | ||
217 | dev_info(&pdev->dev, "unsupported bootloader\n"); | ||
218 | err = -ENODEV; | ||
219 | goto err_probe; | ||
220 | } | ||
221 | |||
222 | return add_mtd_partitions(bcm963xx_mtd_info, parsed_parts, | ||
223 | parsed_nr_parts); | ||
224 | |||
225 | err_probe: | ||
226 | iounmap(bcm963xx_map.virt); | ||
227 | return err; | ||
228 | } | ||
229 | |||
230 | static int bcm963xx_remove(struct platform_device *pdev) | ||
231 | { | ||
232 | if (bcm963xx_mtd_info) { | ||
233 | del_mtd_partitions(bcm963xx_mtd_info); | ||
234 | map_destroy(bcm963xx_mtd_info); | ||
235 | } | ||
236 | |||
237 | if (bcm963xx_map.virt) { | ||
238 | iounmap(bcm963xx_map.virt); | ||
239 | bcm963xx_map.virt = 0; | ||
240 | } | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static struct platform_driver bcm63xx_mtd_dev = { | ||
246 | .probe = bcm963xx_probe, | ||
247 | .remove = bcm963xx_remove, | ||
248 | .driver = { | ||
249 | .name = "bcm963xx-flash", | ||
250 | .owner = THIS_MODULE, | ||
251 | }, | ||
252 | }; | ||
253 | |||
254 | static int __init bcm963xx_mtd_init(void) | ||
255 | { | ||
256 | return platform_driver_register(&bcm63xx_mtd_dev); | ||
257 | } | ||
258 | |||
259 | static void __exit bcm963xx_mtd_exit(void) | ||
260 | { | ||
261 | platform_driver_unregister(&bcm63xx_mtd_dev); | ||
262 | } | ||
263 | |||
264 | module_init(bcm963xx_mtd_init); | ||
265 | module_exit(bcm963xx_mtd_exit); | ||
266 | |||
267 | MODULE_LICENSE("GPL"); | ||
268 | MODULE_DESCRIPTION("Broadcom BCM63xx MTD driver for CFE and RedBoot"); | ||
269 | MODULE_AUTHOR("Daniel Dickinson <openwrt@cshore.neomailbox.net>"); | ||
270 | MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); | ||
271 | MODULE_AUTHOR("Mike Albon <malbon@openwrt.org>"); | ||
diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c index 32e89d773b4e..af5707a80205 100644 --- a/drivers/mtd/maps/gpio-addr-flash.c +++ b/drivers/mtd/maps/gpio-addr-flash.c | |||
@@ -208,10 +208,14 @@ static int __devinit gpio_flash_probe(struct platform_device *pdev) | |||
208 | if (!state) | 208 | if (!state) |
209 | return -ENOMEM; | 209 | return -ENOMEM; |
210 | 210 | ||
211 | /* | ||
212 | * We cast start/end to known types in the boards file, so cast | ||
213 | * away their pointer types here to the known types (gpios->xxx). | ||
214 | */ | ||
211 | state->gpio_count = gpios->end; | 215 | state->gpio_count = gpios->end; |
212 | state->gpio_addrs = (void *)gpios->start; | 216 | state->gpio_addrs = (void *)(unsigned long)gpios->start; |
213 | state->gpio_values = (void *)(state + 1); | 217 | state->gpio_values = (void *)(state + 1); |
214 | state->win_size = memory->end - memory->start + 1; | 218 | state->win_size = resource_size(memory); |
215 | memset(state->gpio_values, 0xff, arr_size); | 219 | memset(state->gpio_values, 0xff, arr_size); |
216 | 220 | ||
217 | state->map.name = DRIVER_NAME; | 221 | state->map.name = DRIVER_NAME; |
@@ -221,7 +225,7 @@ static int __devinit gpio_flash_probe(struct platform_device *pdev) | |||
221 | state->map.copy_to = gf_copy_to; | 225 | state->map.copy_to = gf_copy_to; |
222 | state->map.bankwidth = pdata->width; | 226 | state->map.bankwidth = pdata->width; |
223 | state->map.size = state->win_size * (1 << state->gpio_count); | 227 | state->map.size = state->win_size * (1 << state->gpio_count); |
224 | state->map.virt = (void __iomem *)memory->start; | 228 | state->map.virt = ioremap_nocache(memory->start, state->map.size); |
225 | state->map.phys = NO_XIP; | 229 | state->map.phys = NO_XIP; |
226 | state->map.map_priv_1 = (unsigned long)state; | 230 | state->map.map_priv_1 = (unsigned long)state; |
227 | 231 | ||
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index 57a1acfe22c4..917022948399 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c | |||
@@ -640,10 +640,6 @@ static int pcmciamtd_config(struct pcmcia_device *link) | |||
640 | } | 640 | } |
641 | dev_info(&dev->p_dev->dev, "mtd%d: %s\n", mtd->index, mtd->name); | 641 | dev_info(&dev->p_dev->dev, "mtd%d: %s\n", mtd->index, mtd->name); |
642 | return 0; | 642 | return 0; |
643 | |||
644 | dev_err(&dev->p_dev->dev, "CS Error, exiting\n"); | ||
645 | pcmciamtd_release(link); | ||
646 | return -ENODEV; | ||
647 | } | 643 | } |
648 | 644 | ||
649 | 645 | ||
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index ec3edf6e68b4..9861814aa027 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c | |||
@@ -50,7 +50,7 @@ static int parse_obsolete_partitions(struct platform_device *dev, | |||
50 | { | 50 | { |
51 | int i, plen, nr_parts; | 51 | int i, plen, nr_parts; |
52 | const struct { | 52 | const struct { |
53 | u32 offset, len; | 53 | __be32 offset, len; |
54 | } *part; | 54 | } *part; |
55 | const char *names; | 55 | const char *names; |
56 | 56 | ||
@@ -69,9 +69,9 @@ static int parse_obsolete_partitions(struct platform_device *dev, | |||
69 | names = of_get_property(dp, "partition-names", &plen); | 69 | names = of_get_property(dp, "partition-names", &plen); |
70 | 70 | ||
71 | for (i = 0; i < nr_parts; i++) { | 71 | for (i = 0; i < nr_parts; i++) { |
72 | info->parts[i].offset = part->offset; | 72 | info->parts[i].offset = be32_to_cpu(part->offset); |
73 | info->parts[i].size = part->len & ~1; | 73 | info->parts[i].size = be32_to_cpu(part->len) & ~1; |
74 | if (part->len & 1) /* bit 0 set signifies read only partition */ | 74 | if (be32_to_cpu(part->len) & 1) /* bit 0 set signifies read only partition */ |
75 | info->parts[i].mask_flags = MTD_WRITEABLE; | 75 | info->parts[i].mask_flags = MTD_WRITEABLE; |
76 | 76 | ||
77 | if (names && (plen > 0)) { | 77 | if (names && (plen > 0)) { |
@@ -226,11 +226,11 @@ static int __devinit of_flash_probe(struct platform_device *dev, | |||
226 | struct resource res; | 226 | struct resource res; |
227 | struct of_flash *info; | 227 | struct of_flash *info; |
228 | const char *probe_type = match->data; | 228 | const char *probe_type = match->data; |
229 | const u32 *width; | 229 | const __be32 *width; |
230 | int err; | 230 | int err; |
231 | int i; | 231 | int i; |
232 | int count; | 232 | int count; |
233 | const u32 *p; | 233 | const __be32 *p; |
234 | int reg_tuple_size; | 234 | int reg_tuple_size; |
235 | struct mtd_info **mtd_list = NULL; | 235 | struct mtd_info **mtd_list = NULL; |
236 | resource_size_t res_size; | 236 | resource_size_t res_size; |
@@ -267,9 +267,11 @@ static int __devinit of_flash_probe(struct platform_device *dev, | |||
267 | for (i = 0; i < count; i++) { | 267 | for (i = 0; i < count; i++) { |
268 | err = -ENXIO; | 268 | err = -ENXIO; |
269 | if (of_address_to_resource(dp, i, &res)) { | 269 | if (of_address_to_resource(dp, i, &res)) { |
270 | dev_err(&dev->dev, "Can't get IO address from device" | 270 | /* |
271 | " tree\n"); | 271 | * Continue with next register tuple if this |
272 | goto err_out; | 272 | * one is not mappable |
273 | */ | ||
274 | continue; | ||
273 | } | 275 | } |
274 | 276 | ||
275 | dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n", | 277 | dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n", |
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 50ab431b24eb..cb20c67995d8 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c | |||
@@ -37,7 +37,6 @@ | |||
37 | 37 | ||
38 | #include "mtdcore.h" | 38 | #include "mtdcore.h" |
39 | 39 | ||
40 | static DEFINE_MUTEX(mtd_blkdevs_mutex); | ||
41 | static LIST_HEAD(blktrans_majors); | 40 | static LIST_HEAD(blktrans_majors); |
42 | static DEFINE_MUTEX(blktrans_ref_mutex); | 41 | static DEFINE_MUTEX(blktrans_ref_mutex); |
43 | 42 | ||
@@ -133,6 +132,10 @@ static int mtd_blktrans_thread(void *arg) | |||
133 | 132 | ||
134 | if (!req && !(req = blk_fetch_request(rq))) { | 133 | if (!req && !(req = blk_fetch_request(rq))) { |
135 | set_current_state(TASK_INTERRUPTIBLE); | 134 | set_current_state(TASK_INTERRUPTIBLE); |
135 | |||
136 | if (kthread_should_stop()) | ||
137 | set_current_state(TASK_RUNNING); | ||
138 | |||
136 | spin_unlock_irq(rq->queue_lock); | 139 | spin_unlock_irq(rq->queue_lock); |
137 | schedule(); | 140 | schedule(); |
138 | spin_lock_irq(rq->queue_lock); | 141 | spin_lock_irq(rq->queue_lock); |
@@ -176,54 +179,53 @@ static void mtd_blktrans_request(struct request_queue *rq) | |||
176 | static int blktrans_open(struct block_device *bdev, fmode_t mode) | 179 | static int blktrans_open(struct block_device *bdev, fmode_t mode) |
177 | { | 180 | { |
178 | struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk); | 181 | struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk); |
179 | int ret; | 182 | int ret = 0; |
180 | 183 | ||
181 | if (!dev) | 184 | if (!dev) |
182 | return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/ | 185 | return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/ |
183 | 186 | ||
184 | mutex_lock(&mtd_blkdevs_mutex); | ||
185 | mutex_lock(&dev->lock); | 187 | mutex_lock(&dev->lock); |
186 | 188 | ||
187 | if (!dev->mtd) { | 189 | if (dev->open++) |
188 | ret = -ENXIO; | ||
189 | goto unlock; | 190 | goto unlock; |
190 | } | ||
191 | 191 | ||
192 | ret = !dev->open++ && dev->tr->open ? dev->tr->open(dev) : 0; | 192 | kref_get(&dev->ref); |
193 | __module_get(dev->tr->owner); | ||
194 | |||
195 | if (dev->mtd) { | ||
196 | ret = dev->tr->open ? dev->tr->open(dev) : 0; | ||
197 | __get_mtd_device(dev->mtd); | ||
198 | } | ||
193 | 199 | ||
194 | /* Take another reference on the device so it won't go away till | ||
195 | last release */ | ||
196 | if (!ret) | ||
197 | kref_get(&dev->ref); | ||
198 | unlock: | 200 | unlock: |
199 | mutex_unlock(&dev->lock); | 201 | mutex_unlock(&dev->lock); |
200 | blktrans_dev_put(dev); | 202 | blktrans_dev_put(dev); |
201 | mutex_unlock(&mtd_blkdevs_mutex); | ||
202 | return ret; | 203 | return ret; |
203 | } | 204 | } |
204 | 205 | ||
205 | static int blktrans_release(struct gendisk *disk, fmode_t mode) | 206 | static int blktrans_release(struct gendisk *disk, fmode_t mode) |
206 | { | 207 | { |
207 | struct mtd_blktrans_dev *dev = blktrans_dev_get(disk); | 208 | struct mtd_blktrans_dev *dev = blktrans_dev_get(disk); |
208 | int ret = -ENXIO; | 209 | int ret = 0; |
209 | 210 | ||
210 | if (!dev) | 211 | if (!dev) |
211 | return ret; | 212 | return ret; |
212 | 213 | ||
213 | mutex_lock(&mtd_blkdevs_mutex); | ||
214 | mutex_lock(&dev->lock); | 214 | mutex_lock(&dev->lock); |
215 | 215 | ||
216 | /* Release one reference, we sure its not the last one here*/ | 216 | if (--dev->open) |
217 | kref_put(&dev->ref, blktrans_dev_release); | ||
218 | |||
219 | if (!dev->mtd) | ||
220 | goto unlock; | 217 | goto unlock; |
221 | 218 | ||
222 | ret = !--dev->open && dev->tr->release ? dev->tr->release(dev) : 0; | 219 | kref_put(&dev->ref, blktrans_dev_release); |
220 | module_put(dev->tr->owner); | ||
221 | |||
222 | if (dev->mtd) { | ||
223 | ret = dev->tr->release ? dev->tr->release(dev) : 0; | ||
224 | __put_mtd_device(dev->mtd); | ||
225 | } | ||
223 | unlock: | 226 | unlock: |
224 | mutex_unlock(&dev->lock); | 227 | mutex_unlock(&dev->lock); |
225 | blktrans_dev_put(dev); | 228 | blktrans_dev_put(dev); |
226 | mutex_unlock(&mtd_blkdevs_mutex); | ||
227 | return ret; | 229 | return ret; |
228 | } | 230 | } |
229 | 231 | ||
@@ -256,7 +258,6 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode, | |||
256 | if (!dev) | 258 | if (!dev) |
257 | return ret; | 259 | return ret; |
258 | 260 | ||
259 | mutex_lock(&mtd_blkdevs_mutex); | ||
260 | mutex_lock(&dev->lock); | 261 | mutex_lock(&dev->lock); |
261 | 262 | ||
262 | if (!dev->mtd) | 263 | if (!dev->mtd) |
@@ -271,7 +272,6 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode, | |||
271 | } | 272 | } |
272 | unlock: | 273 | unlock: |
273 | mutex_unlock(&dev->lock); | 274 | mutex_unlock(&dev->lock); |
274 | mutex_unlock(&mtd_blkdevs_mutex); | ||
275 | blktrans_dev_put(dev); | 275 | blktrans_dev_put(dev); |
276 | return ret; | 276 | return ret; |
277 | } | 277 | } |
@@ -385,9 +385,6 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) | |||
385 | 385 | ||
386 | gd->queue = new->rq; | 386 | gd->queue = new->rq; |
387 | 387 | ||
388 | __get_mtd_device(new->mtd); | ||
389 | __module_get(tr->owner); | ||
390 | |||
391 | /* Create processing thread */ | 388 | /* Create processing thread */ |
392 | /* TODO: workqueue ? */ | 389 | /* TODO: workqueue ? */ |
393 | new->thread = kthread_run(mtd_blktrans_thread, new, | 390 | new->thread = kthread_run(mtd_blktrans_thread, new, |
@@ -410,8 +407,6 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) | |||
410 | } | 407 | } |
411 | return 0; | 408 | return 0; |
412 | error4: | 409 | error4: |
413 | module_put(tr->owner); | ||
414 | __put_mtd_device(new->mtd); | ||
415 | blk_cleanup_queue(new->rq); | 410 | blk_cleanup_queue(new->rq); |
416 | error3: | 411 | error3: |
417 | put_disk(new->disk); | 412 | put_disk(new->disk); |
@@ -448,17 +443,15 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) | |||
448 | blk_start_queue(old->rq); | 443 | blk_start_queue(old->rq); |
449 | spin_unlock_irqrestore(&old->queue_lock, flags); | 444 | spin_unlock_irqrestore(&old->queue_lock, flags); |
450 | 445 | ||
451 | /* Ask trans driver for release to the mtd device */ | 446 | /* If the device is currently open, tell trans driver to close it, |
447 | then put mtd device, and don't touch it again */ | ||
452 | mutex_lock(&old->lock); | 448 | mutex_lock(&old->lock); |
453 | if (old->open && old->tr->release) { | 449 | if (old->open) { |
454 | old->tr->release(old); | 450 | if (old->tr->release) |
455 | old->open = 0; | 451 | old->tr->release(old); |
452 | __put_mtd_device(old->mtd); | ||
456 | } | 453 | } |
457 | 454 | ||
458 | __put_mtd_device(old->mtd); | ||
459 | module_put(old->tr->owner); | ||
460 | |||
461 | /* At that point, we don't touch the mtd anymore */ | ||
462 | old->mtd = NULL; | 455 | old->mtd = NULL; |
463 | 456 | ||
464 | mutex_unlock(&old->lock); | 457 | mutex_unlock(&old->lock); |
@@ -508,13 +501,16 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) | |||
508 | mutex_lock(&mtd_table_mutex); | 501 | mutex_lock(&mtd_table_mutex); |
509 | 502 | ||
510 | ret = register_blkdev(tr->major, tr->name); | 503 | ret = register_blkdev(tr->major, tr->name); |
511 | if (ret) { | 504 | if (ret < 0) { |
512 | printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n", | 505 | printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n", |
513 | tr->name, tr->major, ret); | 506 | tr->name, tr->major, ret); |
514 | mutex_unlock(&mtd_table_mutex); | 507 | mutex_unlock(&mtd_table_mutex); |
515 | return ret; | 508 | return ret; |
516 | } | 509 | } |
517 | 510 | ||
511 | if (ret) | ||
512 | tr->major = ret; | ||
513 | |||
518 | tr->blkshift = ffs(tr->blksize) - 1; | 514 | tr->blkshift = ffs(tr->blksize) - 1; |
519 | 515 | ||
520 | INIT_LIST_HEAD(&tr->devs); | 516 | INIT_LIST_HEAD(&tr->devs); |
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index a34a0fe14884..4759d827e8c7 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c | |||
@@ -30,8 +30,9 @@ | |||
30 | #include <linux/backing-dev.h> | 30 | #include <linux/backing-dev.h> |
31 | #include <linux/compat.h> | 31 | #include <linux/compat.h> |
32 | #include <linux/mount.h> | 32 | #include <linux/mount.h> |
33 | 33 | #include <linux/blkpg.h> | |
34 | #include <linux/mtd/mtd.h> | 34 | #include <linux/mtd/mtd.h> |
35 | #include <linux/mtd/partitions.h> | ||
35 | #include <linux/mtd/map.h> | 36 | #include <linux/mtd/map.h> |
36 | 37 | ||
37 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
@@ -478,6 +479,78 @@ static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start, | |||
478 | return ret; | 479 | return ret; |
479 | } | 480 | } |
480 | 481 | ||
482 | /* | ||
483 | * Copies (and truncates, if necessary) data from the larger struct, | ||
484 | * nand_ecclayout, to the smaller, deprecated layout struct, | ||
485 | * nand_ecclayout_user. This is necessary only to suppport the deprecated | ||
486 | * API ioctl ECCGETLAYOUT while allowing all new functionality to use | ||
487 | * nand_ecclayout flexibly (i.e. the struct may change size in new | ||
488 | * releases without requiring major rewrites). | ||
489 | */ | ||
490 | static int shrink_ecclayout(const struct nand_ecclayout *from, | ||
491 | struct nand_ecclayout_user *to) | ||
492 | { | ||
493 | int i; | ||
494 | |||
495 | if (!from || !to) | ||
496 | return -EINVAL; | ||
497 | |||
498 | memset(to, 0, sizeof(*to)); | ||
499 | |||
500 | to->eccbytes = min((int)from->eccbytes, MTD_MAX_ECCPOS_ENTRIES); | ||
501 | for (i = 0; i < to->eccbytes; i++) | ||
502 | to->eccpos[i] = from->eccpos[i]; | ||
503 | |||
504 | for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES; i++) { | ||
505 | if (from->oobfree[i].length == 0 && | ||
506 | from->oobfree[i].offset == 0) | ||
507 | break; | ||
508 | to->oobavail += from->oobfree[i].length; | ||
509 | to->oobfree[i] = from->oobfree[i]; | ||
510 | } | ||
511 | |||
512 | return 0; | ||
513 | } | ||
514 | |||
515 | #ifdef CONFIG_MTD_PARTITIONS | ||
516 | static int mtd_blkpg_ioctl(struct mtd_info *mtd, | ||
517 | struct blkpg_ioctl_arg __user *arg) | ||
518 | { | ||
519 | struct blkpg_ioctl_arg a; | ||
520 | struct blkpg_partition p; | ||
521 | |||
522 | if (!capable(CAP_SYS_ADMIN)) | ||
523 | return -EPERM; | ||
524 | |||
525 | /* Only master mtd device must be used to control partitions */ | ||
526 | if (!mtd_is_master(mtd)) | ||
527 | return -EINVAL; | ||
528 | |||
529 | if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg))) | ||
530 | return -EFAULT; | ||
531 | |||
532 | if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition))) | ||
533 | return -EFAULT; | ||
534 | |||
535 | switch (a.op) { | ||
536 | case BLKPG_ADD_PARTITION: | ||
537 | |||
538 | return mtd_add_partition(mtd, p.devname, p.start, p.length); | ||
539 | |||
540 | case BLKPG_DEL_PARTITION: | ||
541 | |||
542 | if (p.pno < 0) | ||
543 | return -EINVAL; | ||
544 | |||
545 | return mtd_del_partition(mtd, p.pno); | ||
546 | |||
547 | default: | ||
548 | return -EINVAL; | ||
549 | } | ||
550 | } | ||
551 | #endif | ||
552 | |||
553 | |||
481 | static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | 554 | static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) |
482 | { | 555 | { |
483 | struct mtd_file_info *mfi = file->private_data; | 556 | struct mtd_file_info *mfi = file->private_data; |
@@ -514,6 +587,9 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
514 | if (get_user(ur_idx, &(ur->regionindex))) | 587 | if (get_user(ur_idx, &(ur->regionindex))) |
515 | return -EFAULT; | 588 | return -EFAULT; |
516 | 589 | ||
590 | if (ur_idx >= mtd->numeraseregions) | ||
591 | return -EINVAL; | ||
592 | |||
517 | kr = &(mtd->eraseregions[ur_idx]); | 593 | kr = &(mtd->eraseregions[ur_idx]); |
518 | 594 | ||
519 | if (put_user(kr->offset, &(ur->offset)) | 595 | if (put_user(kr->offset, &(ur->offset)) |
@@ -813,14 +889,23 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
813 | } | 889 | } |
814 | #endif | 890 | #endif |
815 | 891 | ||
892 | /* This ioctl is being deprecated - it truncates the ecc layout */ | ||
816 | case ECCGETLAYOUT: | 893 | case ECCGETLAYOUT: |
817 | { | 894 | { |
895 | struct nand_ecclayout_user *usrlay; | ||
896 | |||
818 | if (!mtd->ecclayout) | 897 | if (!mtd->ecclayout) |
819 | return -EOPNOTSUPP; | 898 | return -EOPNOTSUPP; |
820 | 899 | ||
821 | if (copy_to_user(argp, mtd->ecclayout, | 900 | usrlay = kmalloc(sizeof(*usrlay), GFP_KERNEL); |
822 | sizeof(struct nand_ecclayout))) | 901 | if (!usrlay) |
823 | return -EFAULT; | 902 | return -ENOMEM; |
903 | |||
904 | shrink_ecclayout(mtd->ecclayout, usrlay); | ||
905 | |||
906 | if (copy_to_user(argp, usrlay, sizeof(*usrlay))) | ||
907 | ret = -EFAULT; | ||
908 | kfree(usrlay); | ||
824 | break; | 909 | break; |
825 | } | 910 | } |
826 | 911 | ||
@@ -856,6 +941,22 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
856 | break; | 941 | break; |
857 | } | 942 | } |
858 | 943 | ||
944 | #ifdef CONFIG_MTD_PARTITIONS | ||
945 | case BLKPG: | ||
946 | { | ||
947 | ret = mtd_blkpg_ioctl(mtd, | ||
948 | (struct blkpg_ioctl_arg __user *)arg); | ||
949 | break; | ||
950 | } | ||
951 | |||
952 | case BLKRRPART: | ||
953 | { | ||
954 | /* No reread partition feature. Just return ok */ | ||
955 | ret = 0; | ||
956 | break; | ||
957 | } | ||
958 | #endif | ||
959 | |||
859 | default: | 960 | default: |
860 | ret = -ENOTTY; | 961 | ret = -ENOTTY; |
861 | } | 962 | } |
@@ -1033,7 +1134,7 @@ static const struct file_operations mtd_fops = { | |||
1033 | static struct dentry *mtd_inodefs_mount(struct file_system_type *fs_type, | 1134 | static struct dentry *mtd_inodefs_mount(struct file_system_type *fs_type, |
1034 | int flags, const char *dev_name, void *data) | 1135 | int flags, const char *dev_name, void *data) |
1035 | { | 1136 | { |
1036 | return mount_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC); | 1137 | return mount_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC); |
1037 | } | 1138 | } |
1038 | 1139 | ||
1039 | static struct file_system_type mtd_inodefs_type = { | 1140 | static struct file_system_type mtd_inodefs_type = { |
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index dc6558568876..79e3689f1e16 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c | |||
@@ -29,9 +29,11 @@ | |||
29 | #include <linux/kmod.h> | 29 | #include <linux/kmod.h> |
30 | #include <linux/mtd/mtd.h> | 30 | #include <linux/mtd/mtd.h> |
31 | #include <linux/mtd/partitions.h> | 31 | #include <linux/mtd/partitions.h> |
32 | #include <linux/err.h> | ||
32 | 33 | ||
33 | /* Our partition linked list */ | 34 | /* Our partition linked list */ |
34 | static LIST_HEAD(mtd_partitions); | 35 | static LIST_HEAD(mtd_partitions); |
36 | static DEFINE_MUTEX(mtd_partitions_mutex); | ||
35 | 37 | ||
36 | /* Our partition node structure */ | 38 | /* Our partition node structure */ |
37 | struct mtd_part { | 39 | struct mtd_part { |
@@ -326,6 +328,12 @@ static int part_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
326 | return res; | 328 | return res; |
327 | } | 329 | } |
328 | 330 | ||
331 | static inline void free_partition(struct mtd_part *p) | ||
332 | { | ||
333 | kfree(p->mtd.name); | ||
334 | kfree(p); | ||
335 | } | ||
336 | |||
329 | /* | 337 | /* |
330 | * This function unregisters and destroy all slave MTD objects which are | 338 | * This function unregisters and destroy all slave MTD objects which are |
331 | * attached to the given master MTD object. | 339 | * attached to the given master MTD object. |
@@ -334,33 +342,42 @@ static int part_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
334 | int del_mtd_partitions(struct mtd_info *master) | 342 | int del_mtd_partitions(struct mtd_info *master) |
335 | { | 343 | { |
336 | struct mtd_part *slave, *next; | 344 | struct mtd_part *slave, *next; |
345 | int ret, err = 0; | ||
337 | 346 | ||
347 | mutex_lock(&mtd_partitions_mutex); | ||
338 | list_for_each_entry_safe(slave, next, &mtd_partitions, list) | 348 | list_for_each_entry_safe(slave, next, &mtd_partitions, list) |
339 | if (slave->master == master) { | 349 | if (slave->master == master) { |
350 | ret = del_mtd_device(&slave->mtd); | ||
351 | if (ret < 0) { | ||
352 | err = ret; | ||
353 | continue; | ||
354 | } | ||
340 | list_del(&slave->list); | 355 | list_del(&slave->list); |
341 | del_mtd_device(&slave->mtd); | 356 | free_partition(slave); |
342 | kfree(slave); | ||
343 | } | 357 | } |
358 | mutex_unlock(&mtd_partitions_mutex); | ||
344 | 359 | ||
345 | return 0; | 360 | return err; |
346 | } | 361 | } |
347 | EXPORT_SYMBOL(del_mtd_partitions); | 362 | EXPORT_SYMBOL(del_mtd_partitions); |
348 | 363 | ||
349 | static struct mtd_part *add_one_partition(struct mtd_info *master, | 364 | static struct mtd_part *allocate_partition(struct mtd_info *master, |
350 | const struct mtd_partition *part, int partno, | 365 | const struct mtd_partition *part, int partno, |
351 | uint64_t cur_offset) | 366 | uint64_t cur_offset) |
352 | { | 367 | { |
353 | struct mtd_part *slave; | 368 | struct mtd_part *slave; |
369 | char *name; | ||
354 | 370 | ||
355 | /* allocate the partition structure */ | 371 | /* allocate the partition structure */ |
356 | slave = kzalloc(sizeof(*slave), GFP_KERNEL); | 372 | slave = kzalloc(sizeof(*slave), GFP_KERNEL); |
357 | if (!slave) { | 373 | name = kstrdup(part->name, GFP_KERNEL); |
374 | if (!name || !slave) { | ||
358 | printk(KERN_ERR"memory allocation error while creating partitions for \"%s\"\n", | 375 | printk(KERN_ERR"memory allocation error while creating partitions for \"%s\"\n", |
359 | master->name); | 376 | master->name); |
360 | del_mtd_partitions(master); | 377 | kfree(name); |
361 | return NULL; | 378 | kfree(slave); |
379 | return ERR_PTR(-ENOMEM); | ||
362 | } | 380 | } |
363 | list_add(&slave->list, &mtd_partitions); | ||
364 | 381 | ||
365 | /* set up the MTD object for this partition */ | 382 | /* set up the MTD object for this partition */ |
366 | slave->mtd.type = master->type; | 383 | slave->mtd.type = master->type; |
@@ -371,7 +388,7 @@ static struct mtd_part *add_one_partition(struct mtd_info *master, | |||
371 | slave->mtd.oobavail = master->oobavail; | 388 | slave->mtd.oobavail = master->oobavail; |
372 | slave->mtd.subpage_sft = master->subpage_sft; | 389 | slave->mtd.subpage_sft = master->subpage_sft; |
373 | 390 | ||
374 | slave->mtd.name = part->name; | 391 | slave->mtd.name = name; |
375 | slave->mtd.owner = master->owner; | 392 | slave->mtd.owner = master->owner; |
376 | slave->mtd.backing_dev_info = master->backing_dev_info; | 393 | slave->mtd.backing_dev_info = master->backing_dev_info; |
377 | 394 | ||
@@ -518,12 +535,89 @@ static struct mtd_part *add_one_partition(struct mtd_info *master, | |||
518 | } | 535 | } |
519 | 536 | ||
520 | out_register: | 537 | out_register: |
521 | /* register our partition */ | ||
522 | add_mtd_device(&slave->mtd); | ||
523 | |||
524 | return slave; | 538 | return slave; |
525 | } | 539 | } |
526 | 540 | ||
541 | int mtd_add_partition(struct mtd_info *master, char *name, | ||
542 | long long offset, long long length) | ||
543 | { | ||
544 | struct mtd_partition part; | ||
545 | struct mtd_part *p, *new; | ||
546 | uint64_t start, end; | ||
547 | int ret = 0; | ||
548 | |||
549 | /* the direct offset is expected */ | ||
550 | if (offset == MTDPART_OFS_APPEND || | ||
551 | offset == MTDPART_OFS_NXTBLK) | ||
552 | return -EINVAL; | ||
553 | |||
554 | if (length == MTDPART_SIZ_FULL) | ||
555 | length = master->size - offset; | ||
556 | |||
557 | if (length <= 0) | ||
558 | return -EINVAL; | ||
559 | |||
560 | part.name = name; | ||
561 | part.size = length; | ||
562 | part.offset = offset; | ||
563 | part.mask_flags = 0; | ||
564 | part.ecclayout = NULL; | ||
565 | |||
566 | new = allocate_partition(master, &part, -1, offset); | ||
567 | if (IS_ERR(new)) | ||
568 | return PTR_ERR(new); | ||
569 | |||
570 | start = offset; | ||
571 | end = offset + length; | ||
572 | |||
573 | mutex_lock(&mtd_partitions_mutex); | ||
574 | list_for_each_entry(p, &mtd_partitions, list) | ||
575 | if (p->master == master) { | ||
576 | if ((start >= p->offset) && | ||
577 | (start < (p->offset + p->mtd.size))) | ||
578 | goto err_inv; | ||
579 | |||
580 | if ((end >= p->offset) && | ||
581 | (end < (p->offset + p->mtd.size))) | ||
582 | goto err_inv; | ||
583 | } | ||
584 | |||
585 | list_add(&new->list, &mtd_partitions); | ||
586 | mutex_unlock(&mtd_partitions_mutex); | ||
587 | |||
588 | add_mtd_device(&new->mtd); | ||
589 | |||
590 | return ret; | ||
591 | err_inv: | ||
592 | mutex_unlock(&mtd_partitions_mutex); | ||
593 | free_partition(new); | ||
594 | return -EINVAL; | ||
595 | } | ||
596 | EXPORT_SYMBOL_GPL(mtd_add_partition); | ||
597 | |||
598 | int mtd_del_partition(struct mtd_info *master, int partno) | ||
599 | { | ||
600 | struct mtd_part *slave, *next; | ||
601 | int ret = -EINVAL; | ||
602 | |||
603 | mutex_lock(&mtd_partitions_mutex); | ||
604 | list_for_each_entry_safe(slave, next, &mtd_partitions, list) | ||
605 | if ((slave->master == master) && | ||
606 | (slave->mtd.index == partno)) { | ||
607 | ret = del_mtd_device(&slave->mtd); | ||
608 | if (ret < 0) | ||
609 | break; | ||
610 | |||
611 | list_del(&slave->list); | ||
612 | free_partition(slave); | ||
613 | break; | ||
614 | } | ||
615 | mutex_unlock(&mtd_partitions_mutex); | ||
616 | |||
617 | return ret; | ||
618 | } | ||
619 | EXPORT_SYMBOL_GPL(mtd_del_partition); | ||
620 | |||
527 | /* | 621 | /* |
528 | * This function, given a master MTD object and a partition table, creates | 622 | * This function, given a master MTD object and a partition table, creates |
529 | * and registers slave MTD objects which are bound to the master according to | 623 | * and registers slave MTD objects which are bound to the master according to |
@@ -544,9 +638,16 @@ int add_mtd_partitions(struct mtd_info *master, | |||
544 | printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); | 638 | printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); |
545 | 639 | ||
546 | for (i = 0; i < nbparts; i++) { | 640 | for (i = 0; i < nbparts; i++) { |
547 | slave = add_one_partition(master, parts + i, i, cur_offset); | 641 | slave = allocate_partition(master, parts + i, i, cur_offset); |
548 | if (!slave) | 642 | if (IS_ERR(slave)) |
549 | return -ENOMEM; | 643 | return PTR_ERR(slave); |
644 | |||
645 | mutex_lock(&mtd_partitions_mutex); | ||
646 | list_add(&slave->list, &mtd_partitions); | ||
647 | mutex_unlock(&mtd_partitions_mutex); | ||
648 | |||
649 | add_mtd_device(&slave->mtd); | ||
650 | |||
550 | cur_offset = slave->offset + slave->mtd.size; | 651 | cur_offset = slave->offset + slave->mtd.size; |
551 | } | 652 | } |
552 | 653 | ||
@@ -618,3 +719,20 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types, | |||
618 | return ret; | 719 | return ret; |
619 | } | 720 | } |
620 | EXPORT_SYMBOL_GPL(parse_mtd_partitions); | 721 | EXPORT_SYMBOL_GPL(parse_mtd_partitions); |
722 | |||
723 | int mtd_is_master(struct mtd_info *mtd) | ||
724 | { | ||
725 | struct mtd_part *part; | ||
726 | int nopart = 0; | ||
727 | |||
728 | mutex_lock(&mtd_partitions_mutex); | ||
729 | list_for_each_entry(part, &mtd_partitions, list) | ||
730 | if (&part->mtd == mtd) { | ||
731 | nopart = 1; | ||
732 | break; | ||
733 | } | ||
734 | mutex_unlock(&mtd_partitions_mutex); | ||
735 | |||
736 | return nopart; | ||
737 | } | ||
738 | EXPORT_SYMBOL_GPL(mtd_is_master); | ||
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 8b4b67c8a391..8229802b4346 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -400,13 +400,6 @@ config MTD_NAND_PXA3xx | |||
400 | This enables the driver for the NAND flash device found on | 400 | This enables the driver for the NAND flash device found on |
401 | PXA3xx processors | 401 | PXA3xx processors |
402 | 402 | ||
403 | config MTD_NAND_PXA3xx_BUILTIN | ||
404 | bool "Use builtin definitions for some NAND chips (deprecated)" | ||
405 | depends on MTD_NAND_PXA3xx | ||
406 | help | ||
407 | This enables builtin definitions for some NAND chips. This | ||
408 | is deprecated in favor of platform specific data. | ||
409 | |||
410 | config MTD_NAND_CM_X270 | 403 | config MTD_NAND_CM_X270 |
411 | tristate "Support for NAND Flash on CM-X270 modules" | 404 | tristate "Support for NAND Flash on CM-X270 modules" |
412 | depends on MACH_ARMCORE | 405 | depends on MACH_ARMCORE |
@@ -458,6 +451,7 @@ config MTD_NAND_ORION | |||
458 | config MTD_NAND_FSL_ELBC | 451 | config MTD_NAND_FSL_ELBC |
459 | tristate "NAND support for Freescale eLBC controllers" | 452 | tristate "NAND support for Freescale eLBC controllers" |
460 | depends on PPC_OF | 453 | depends on PPC_OF |
454 | select FSL_LBC | ||
461 | help | 455 | help |
462 | Various Freescale chips, including the 8313, include a NAND Flash | 456 | Various Freescale chips, including the 8313, include a NAND Flash |
463 | Controller Module with built-in hardware ECC capabilities. | 457 | Controller Module with built-in hardware ECC capabilities. |
@@ -531,4 +525,11 @@ config MTD_NAND_JZ4740 | |||
531 | help | 525 | help |
532 | Enables support for NAND Flash on JZ4740 SoC based boards. | 526 | Enables support for NAND Flash on JZ4740 SoC based boards. |
533 | 527 | ||
528 | config MTD_NAND_FSMC | ||
529 | tristate "Support for NAND on ST Micros FSMC" | ||
530 | depends on PLAT_SPEAR || PLAT_NOMADIK || MACH_U300 | ||
531 | help | ||
532 | Enables support for NAND Flash chips on the ST Microelectronics | ||
533 | Flexible Static Memory Controller (FSMC) | ||
534 | |||
534 | endif # MTD_NAND | 535 | endif # MTD_NAND |
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index ac83dcdac5d6..8ad6faec72cb 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile | |||
@@ -19,6 +19,7 @@ obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o | |||
19 | obj-$(CONFIG_MTD_NAND_S3C2410) += s3c2410.o | 19 | obj-$(CONFIG_MTD_NAND_S3C2410) += s3c2410.o |
20 | obj-$(CONFIG_MTD_NAND_DAVINCI) += davinci_nand.o | 20 | obj-$(CONFIG_MTD_NAND_DAVINCI) += davinci_nand.o |
21 | obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o | 21 | obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o |
22 | obj-$(CONFIG_MTD_NAND_FSMC) += fsmc_nand.o | ||
22 | obj-$(CONFIG_MTD_NAND_H1900) += h1910.o | 23 | obj-$(CONFIG_MTD_NAND_H1900) += h1910.o |
23 | obj-$(CONFIG_MTD_NAND_RTC_FROM4) += rtc_from4.o | 24 | obj-$(CONFIG_MTD_NAND_RTC_FROM4) += rtc_from4.o |
24 | obj-$(CONFIG_MTD_NAND_SHARPSL) += sharpsl.o | 25 | obj-$(CONFIG_MTD_NAND_SHARPSL) += sharpsl.o |
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index 6fbeefa3a766..79947bea4d57 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c | |||
@@ -110,15 +110,6 @@ static const unsigned short bfin_nfc_pin_req[] = | |||
110 | 0}; | 110 | 0}; |
111 | 111 | ||
112 | #ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC | 112 | #ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC |
113 | static uint8_t bbt_pattern[] = { 0xff }; | ||
114 | |||
115 | static struct nand_bbt_descr bootrom_bbt = { | ||
116 | .options = 0, | ||
117 | .offs = 63, | ||
118 | .len = 1, | ||
119 | .pattern = bbt_pattern, | ||
120 | }; | ||
121 | |||
122 | static struct nand_ecclayout bootrom_ecclayout = { | 113 | static struct nand_ecclayout bootrom_ecclayout = { |
123 | .eccbytes = 24, | 114 | .eccbytes = 24, |
124 | .eccpos = { | 115 | .eccpos = { |
@@ -809,7 +800,6 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev) | |||
809 | /* setup hardware ECC data struct */ | 800 | /* setup hardware ECC data struct */ |
810 | if (hardware_ecc) { | 801 | if (hardware_ecc) { |
811 | #ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC | 802 | #ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC |
812 | chip->badblock_pattern = &bootrom_bbt; | ||
813 | chip->ecc.layout = &bootrom_ecclayout; | 803 | chip->ecc.layout = &bootrom_ecclayout; |
814 | #endif | 804 | #endif |
815 | chip->read_buf = bf5xx_nand_dma_read_buf; | 805 | chip->read_buf = bf5xx_nand_dma_read_buf; |
@@ -830,6 +820,10 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev) | |||
830 | goto out_err_nand_scan; | 820 | goto out_err_nand_scan; |
831 | } | 821 | } |
832 | 822 | ||
823 | #ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC | ||
824 | chip->badblockpos = 63; | ||
825 | #endif | ||
826 | |||
833 | /* add NAND partition */ | 827 | /* add NAND partition */ |
834 | bf5xx_nand_add_partition(info); | 828 | bf5xx_nand_add_partition(info); |
835 | 829 | ||
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 8beb0d0233b5..a90fde3ede28 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c | |||
@@ -316,7 +316,7 @@ static int nand_davinci_correct_4bit(struct mtd_info *mtd, | |||
316 | u32 syndrome[4]; | 316 | u32 syndrome[4]; |
317 | u32 ecc_state; | 317 | u32 ecc_state; |
318 | unsigned num_errors, corrected; | 318 | unsigned num_errors, corrected; |
319 | unsigned long timeo = jiffies + msecs_to_jiffies(100); | 319 | unsigned long timeo; |
320 | 320 | ||
321 | /* All bytes 0xff? It's an erased page; ignore its ECC. */ | 321 | /* All bytes 0xff? It's an erased page; ignore its ECC. */ |
322 | for (i = 0; i < 10; i++) { | 322 | for (i = 0; i < 10; i++) { |
@@ -372,9 +372,11 @@ compare: | |||
372 | * after setting the 4BITECC_ADD_CALC_START bit. So if you immediately | 372 | * after setting the 4BITECC_ADD_CALC_START bit. So if you immediately |
373 | * begin trying to poll for the state, you may fall right out of your | 373 | * begin trying to poll for the state, you may fall right out of your |
374 | * loop without any of the correction calculations having taken place. | 374 | * loop without any of the correction calculations having taken place. |
375 | * The recommendation from the hardware team is to wait till ECC_STATE | 375 | * The recommendation from the hardware team is to initially delay as |
376 | * reads less than 4, which means ECC HW has entered correction state. | 376 | * long as ECC_STATE reads less than 4. After that, ECC HW has entered |
377 | * correction state. | ||
377 | */ | 378 | */ |
379 | timeo = jiffies + usecs_to_jiffies(100); | ||
378 | do { | 380 | do { |
379 | ecc_state = (davinci_nand_readl(info, | 381 | ecc_state = (davinci_nand_readl(info, |
380 | NANDFSR_OFFSET) >> 8) & 0x0f; | 382 | NANDFSR_OFFSET) >> 8) & 0x0f; |
@@ -733,6 +735,9 @@ static int __init nand_davinci_probe(struct platform_device *pdev) | |||
733 | * breaks userspace ioctl interface with mtd-utils. Once we | 735 | * breaks userspace ioctl interface with mtd-utils. Once we |
734 | * resolve this issue, NAND_ECC_HW_OOB_FIRST mode can be used | 736 | * resolve this issue, NAND_ECC_HW_OOB_FIRST mode can be used |
735 | * for the 4KiB page chips. | 737 | * for the 4KiB page chips. |
738 | * | ||
739 | * TODO: Note that nand_ecclayout has now been expanded and can | ||
740 | * hold plenty of OOB entries. | ||
736 | */ | 741 | */ |
737 | dev_warn(&pdev->dev, "no 4-bit ECC support yet " | 742 | dev_warn(&pdev->dev, "no 4-bit ECC support yet " |
738 | "for 4KiB-page NAND\n"); | 743 | "for 4KiB-page NAND\n"); |
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 532fe07cf886..8c8d3c86c0e8 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c | |||
@@ -1292,6 +1292,7 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, | |||
1292 | read_status(denali); | 1292 | read_status(denali); |
1293 | break; | 1293 | break; |
1294 | case NAND_CMD_READID: | 1294 | case NAND_CMD_READID: |
1295 | case NAND_CMD_PARAM: | ||
1295 | reset_buf(denali); | 1296 | reset_buf(denali); |
1296 | /*sometimes ManufactureId read from register is not right | 1297 | /*sometimes ManufactureId read from register is not right |
1297 | * e.g. some of Micron MT29F32G08QAA MLC NAND chips | 1298 | * e.g. some of Micron MT29F32G08QAA MLC NAND chips |
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 80de0bff6c3a..c141b07b25d1 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c | |||
@@ -1,9 +1,11 @@ | |||
1 | /* Freescale Enhanced Local Bus Controller NAND driver | 1 | /* Freescale Enhanced Local Bus Controller NAND driver |
2 | * | 2 | * |
3 | * Copyright (c) 2006-2007 Freescale Semiconductor | 3 | * Copyright © 2006-2007, 2010 Freescale Semiconductor |
4 | * | 4 | * |
5 | * Authors: Nick Spence <nick.spence@freescale.com>, | 5 | * Authors: Nick Spence <nick.spence@freescale.com>, |
6 | * Scott Wood <scottwood@freescale.com> | 6 | * Scott Wood <scottwood@freescale.com> |
7 | * Jack Lan <jack.lan@freescale.com> | ||
8 | * Roy Zang <tie-fei.zang@freescale.com> | ||
7 | * | 9 | * |
8 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
@@ -27,6 +29,7 @@ | |||
27 | #include <linux/string.h> | 29 | #include <linux/string.h> |
28 | #include <linux/ioport.h> | 30 | #include <linux/ioport.h> |
29 | #include <linux/of_platform.h> | 31 | #include <linux/of_platform.h> |
32 | #include <linux/platform_device.h> | ||
30 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
31 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
32 | 35 | ||
@@ -42,14 +45,12 @@ | |||
42 | #define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */ | 45 | #define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */ |
43 | #define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */ | 46 | #define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */ |
44 | 47 | ||
45 | struct fsl_elbc_ctrl; | ||
46 | |||
47 | /* mtd information per set */ | 48 | /* mtd information per set */ |
48 | 49 | ||
49 | struct fsl_elbc_mtd { | 50 | struct fsl_elbc_mtd { |
50 | struct mtd_info mtd; | 51 | struct mtd_info mtd; |
51 | struct nand_chip chip; | 52 | struct nand_chip chip; |
52 | struct fsl_elbc_ctrl *ctrl; | 53 | struct fsl_lbc_ctrl *ctrl; |
53 | 54 | ||
54 | struct device *dev; | 55 | struct device *dev; |
55 | int bank; /* Chip select bank number */ | 56 | int bank; /* Chip select bank number */ |
@@ -58,18 +59,12 @@ struct fsl_elbc_mtd { | |||
58 | unsigned int fmr; /* FCM Flash Mode Register value */ | 59 | unsigned int fmr; /* FCM Flash Mode Register value */ |
59 | }; | 60 | }; |
60 | 61 | ||
61 | /* overview of the fsl elbc controller */ | 62 | /* Freescale eLBC FCM controller infomation */ |
62 | 63 | ||
63 | struct fsl_elbc_ctrl { | 64 | struct fsl_elbc_fcm_ctrl { |
64 | struct nand_hw_control controller; | 65 | struct nand_hw_control controller; |
65 | struct fsl_elbc_mtd *chips[MAX_BANKS]; | 66 | struct fsl_elbc_mtd *chips[MAX_BANKS]; |
66 | 67 | ||
67 | /* device info */ | ||
68 | struct device *dev; | ||
69 | struct fsl_lbc_regs __iomem *regs; | ||
70 | int irq; | ||
71 | wait_queue_head_t irq_wait; | ||
72 | unsigned int irq_status; /* status read from LTESR by irq handler */ | ||
73 | u8 __iomem *addr; /* Address of assigned FCM buffer */ | 68 | u8 __iomem *addr; /* Address of assigned FCM buffer */ |
74 | unsigned int page; /* Last page written to / read from */ | 69 | unsigned int page; /* Last page written to / read from */ |
75 | unsigned int read_bytes; /* Number of bytes read during command */ | 70 | unsigned int read_bytes; /* Number of bytes read during command */ |
@@ -79,6 +74,7 @@ struct fsl_elbc_ctrl { | |||
79 | unsigned int mdr; /* UPM/FCM Data Register value */ | 74 | unsigned int mdr; /* UPM/FCM Data Register value */ |
80 | unsigned int use_mdr; /* Non zero if the MDR is to be set */ | 75 | unsigned int use_mdr; /* Non zero if the MDR is to be set */ |
81 | unsigned int oob; /* Non zero if operating on OOB data */ | 76 | unsigned int oob; /* Non zero if operating on OOB data */ |
77 | unsigned int counter; /* counter for the initializations */ | ||
82 | char *oob_poi; /* Place to write ECC after read back */ | 78 | char *oob_poi; /* Place to write ECC after read back */ |
83 | }; | 79 | }; |
84 | 80 | ||
@@ -164,11 +160,12 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) | |||
164 | { | 160 | { |
165 | struct nand_chip *chip = mtd->priv; | 161 | struct nand_chip *chip = mtd->priv; |
166 | struct fsl_elbc_mtd *priv = chip->priv; | 162 | struct fsl_elbc_mtd *priv = chip->priv; |
167 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 163 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
168 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | 164 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
165 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; | ||
169 | int buf_num; | 166 | int buf_num; |
170 | 167 | ||
171 | ctrl->page = page_addr; | 168 | elbc_fcm_ctrl->page = page_addr; |
172 | 169 | ||
173 | out_be32(&lbc->fbar, | 170 | out_be32(&lbc->fbar, |
174 | page_addr >> (chip->phys_erase_shift - chip->page_shift)); | 171 | page_addr >> (chip->phys_erase_shift - chip->page_shift)); |
@@ -185,16 +182,18 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) | |||
185 | buf_num = page_addr & 7; | 182 | buf_num = page_addr & 7; |
186 | } | 183 | } |
187 | 184 | ||
188 | ctrl->addr = priv->vbase + buf_num * 1024; | 185 | elbc_fcm_ctrl->addr = priv->vbase + buf_num * 1024; |
189 | ctrl->index = column; | 186 | elbc_fcm_ctrl->index = column; |
190 | 187 | ||
191 | /* for OOB data point to the second half of the buffer */ | 188 | /* for OOB data point to the second half of the buffer */ |
192 | if (oob) | 189 | if (oob) |
193 | ctrl->index += priv->page_size ? 2048 : 512; | 190 | elbc_fcm_ctrl->index += priv->page_size ? 2048 : 512; |
194 | 191 | ||
195 | dev_vdbg(ctrl->dev, "set_addr: bank=%d, ctrl->addr=0x%p (0x%p), " | 192 | dev_vdbg(priv->dev, "set_addr: bank=%d, " |
193 | "elbc_fcm_ctrl->addr=0x%p (0x%p), " | ||
196 | "index %x, pes %d ps %d\n", | 194 | "index %x, pes %d ps %d\n", |
197 | buf_num, ctrl->addr, priv->vbase, ctrl->index, | 195 | buf_num, elbc_fcm_ctrl->addr, priv->vbase, |
196 | elbc_fcm_ctrl->index, | ||
198 | chip->phys_erase_shift, chip->page_shift); | 197 | chip->phys_erase_shift, chip->page_shift); |
199 | } | 198 | } |
200 | 199 | ||
@@ -205,18 +204,19 @@ static int fsl_elbc_run_command(struct mtd_info *mtd) | |||
205 | { | 204 | { |
206 | struct nand_chip *chip = mtd->priv; | 205 | struct nand_chip *chip = mtd->priv; |
207 | struct fsl_elbc_mtd *priv = chip->priv; | 206 | struct fsl_elbc_mtd *priv = chip->priv; |
208 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 207 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
208 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; | ||
209 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | 209 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
210 | 210 | ||
211 | /* Setup the FMR[OP] to execute without write protection */ | 211 | /* Setup the FMR[OP] to execute without write protection */ |
212 | out_be32(&lbc->fmr, priv->fmr | 3); | 212 | out_be32(&lbc->fmr, priv->fmr | 3); |
213 | if (ctrl->use_mdr) | 213 | if (elbc_fcm_ctrl->use_mdr) |
214 | out_be32(&lbc->mdr, ctrl->mdr); | 214 | out_be32(&lbc->mdr, elbc_fcm_ctrl->mdr); |
215 | 215 | ||
216 | dev_vdbg(ctrl->dev, | 216 | dev_vdbg(priv->dev, |
217 | "fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n", | 217 | "fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n", |
218 | in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr)); | 218 | in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr)); |
219 | dev_vdbg(ctrl->dev, | 219 | dev_vdbg(priv->dev, |
220 | "fsl_elbc_run_command: fbar=%08x fpar=%08x " | 220 | "fsl_elbc_run_command: fbar=%08x fpar=%08x " |
221 | "fbcr=%08x bank=%d\n", | 221 | "fbcr=%08x bank=%d\n", |
222 | in_be32(&lbc->fbar), in_be32(&lbc->fpar), | 222 | in_be32(&lbc->fbar), in_be32(&lbc->fpar), |
@@ -229,19 +229,18 @@ static int fsl_elbc_run_command(struct mtd_info *mtd) | |||
229 | /* wait for FCM complete flag or timeout */ | 229 | /* wait for FCM complete flag or timeout */ |
230 | wait_event_timeout(ctrl->irq_wait, ctrl->irq_status, | 230 | wait_event_timeout(ctrl->irq_wait, ctrl->irq_status, |
231 | FCM_TIMEOUT_MSECS * HZ/1000); | 231 | FCM_TIMEOUT_MSECS * HZ/1000); |
232 | ctrl->status = ctrl->irq_status; | 232 | elbc_fcm_ctrl->status = ctrl->irq_status; |
233 | |||
234 | /* store mdr value in case it was needed */ | 233 | /* store mdr value in case it was needed */ |
235 | if (ctrl->use_mdr) | 234 | if (elbc_fcm_ctrl->use_mdr) |
236 | ctrl->mdr = in_be32(&lbc->mdr); | 235 | elbc_fcm_ctrl->mdr = in_be32(&lbc->mdr); |
237 | 236 | ||
238 | ctrl->use_mdr = 0; | 237 | elbc_fcm_ctrl->use_mdr = 0; |
239 | 238 | ||
240 | if (ctrl->status != LTESR_CC) { | 239 | if (elbc_fcm_ctrl->status != LTESR_CC) { |
241 | dev_info(ctrl->dev, | 240 | dev_info(priv->dev, |
242 | "command failed: fir %x fcr %x status %x mdr %x\n", | 241 | "command failed: fir %x fcr %x status %x mdr %x\n", |
243 | in_be32(&lbc->fir), in_be32(&lbc->fcr), | 242 | in_be32(&lbc->fir), in_be32(&lbc->fcr), |
244 | ctrl->status, ctrl->mdr); | 243 | elbc_fcm_ctrl->status, elbc_fcm_ctrl->mdr); |
245 | return -EIO; | 244 | return -EIO; |
246 | } | 245 | } |
247 | 246 | ||
@@ -251,7 +250,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd) | |||
251 | static void fsl_elbc_do_read(struct nand_chip *chip, int oob) | 250 | static void fsl_elbc_do_read(struct nand_chip *chip, int oob) |
252 | { | 251 | { |
253 | struct fsl_elbc_mtd *priv = chip->priv; | 252 | struct fsl_elbc_mtd *priv = chip->priv; |
254 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 253 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
255 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | 254 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
256 | 255 | ||
257 | if (priv->page_size) { | 256 | if (priv->page_size) { |
@@ -284,15 +283,16 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
284 | { | 283 | { |
285 | struct nand_chip *chip = mtd->priv; | 284 | struct nand_chip *chip = mtd->priv; |
286 | struct fsl_elbc_mtd *priv = chip->priv; | 285 | struct fsl_elbc_mtd *priv = chip->priv; |
287 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 286 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
287 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; | ||
288 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | 288 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
289 | 289 | ||
290 | ctrl->use_mdr = 0; | 290 | elbc_fcm_ctrl->use_mdr = 0; |
291 | 291 | ||
292 | /* clear the read buffer */ | 292 | /* clear the read buffer */ |
293 | ctrl->read_bytes = 0; | 293 | elbc_fcm_ctrl->read_bytes = 0; |
294 | if (command != NAND_CMD_PAGEPROG) | 294 | if (command != NAND_CMD_PAGEPROG) |
295 | ctrl->index = 0; | 295 | elbc_fcm_ctrl->index = 0; |
296 | 296 | ||
297 | switch (command) { | 297 | switch (command) { |
298 | /* READ0 and READ1 read the entire buffer to use hardware ECC. */ | 298 | /* READ0 and READ1 read the entire buffer to use hardware ECC. */ |
@@ -301,7 +301,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
301 | 301 | ||
302 | /* fall-through */ | 302 | /* fall-through */ |
303 | case NAND_CMD_READ0: | 303 | case NAND_CMD_READ0: |
304 | dev_dbg(ctrl->dev, | 304 | dev_dbg(priv->dev, |
305 | "fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:" | 305 | "fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:" |
306 | " 0x%x, column: 0x%x.\n", page_addr, column); | 306 | " 0x%x, column: 0x%x.\n", page_addr, column); |
307 | 307 | ||
@@ -309,8 +309,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
309 | out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */ | 309 | out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */ |
310 | set_addr(mtd, 0, page_addr, 0); | 310 | set_addr(mtd, 0, page_addr, 0); |
311 | 311 | ||
312 | ctrl->read_bytes = mtd->writesize + mtd->oobsize; | 312 | elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize; |
313 | ctrl->index += column; | 313 | elbc_fcm_ctrl->index += column; |
314 | 314 | ||
315 | fsl_elbc_do_read(chip, 0); | 315 | fsl_elbc_do_read(chip, 0); |
316 | fsl_elbc_run_command(mtd); | 316 | fsl_elbc_run_command(mtd); |
@@ -318,14 +318,14 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
318 | 318 | ||
319 | /* READOOB reads only the OOB because no ECC is performed. */ | 319 | /* READOOB reads only the OOB because no ECC is performed. */ |
320 | case NAND_CMD_READOOB: | 320 | case NAND_CMD_READOOB: |
321 | dev_vdbg(ctrl->dev, | 321 | dev_vdbg(priv->dev, |
322 | "fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:" | 322 | "fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:" |
323 | " 0x%x, column: 0x%x.\n", page_addr, column); | 323 | " 0x%x, column: 0x%x.\n", page_addr, column); |
324 | 324 | ||
325 | out_be32(&lbc->fbcr, mtd->oobsize - column); | 325 | out_be32(&lbc->fbcr, mtd->oobsize - column); |
326 | set_addr(mtd, column, page_addr, 1); | 326 | set_addr(mtd, column, page_addr, 1); |
327 | 327 | ||
328 | ctrl->read_bytes = mtd->writesize + mtd->oobsize; | 328 | elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize; |
329 | 329 | ||
330 | fsl_elbc_do_read(chip, 1); | 330 | fsl_elbc_do_read(chip, 1); |
331 | fsl_elbc_run_command(mtd); | 331 | fsl_elbc_run_command(mtd); |
@@ -333,7 +333,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
333 | 333 | ||
334 | /* READID must read all 5 possible bytes while CEB is active */ | 334 | /* READID must read all 5 possible bytes while CEB is active */ |
335 | case NAND_CMD_READID: | 335 | case NAND_CMD_READID: |
336 | dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n"); | 336 | dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n"); |
337 | 337 | ||
338 | out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) | | 338 | out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) | |
339 | (FIR_OP_UA << FIR_OP1_SHIFT) | | 339 | (FIR_OP_UA << FIR_OP1_SHIFT) | |
@@ -341,9 +341,9 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
341 | out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT); | 341 | out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT); |
342 | /* 5 bytes for manuf, device and exts */ | 342 | /* 5 bytes for manuf, device and exts */ |
343 | out_be32(&lbc->fbcr, 5); | 343 | out_be32(&lbc->fbcr, 5); |
344 | ctrl->read_bytes = 5; | 344 | elbc_fcm_ctrl->read_bytes = 5; |
345 | ctrl->use_mdr = 1; | 345 | elbc_fcm_ctrl->use_mdr = 1; |
346 | ctrl->mdr = 0; | 346 | elbc_fcm_ctrl->mdr = 0; |
347 | 347 | ||
348 | set_addr(mtd, 0, 0, 0); | 348 | set_addr(mtd, 0, 0, 0); |
349 | fsl_elbc_run_command(mtd); | 349 | fsl_elbc_run_command(mtd); |
@@ -351,7 +351,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
351 | 351 | ||
352 | /* ERASE1 stores the block and page address */ | 352 | /* ERASE1 stores the block and page address */ |
353 | case NAND_CMD_ERASE1: | 353 | case NAND_CMD_ERASE1: |
354 | dev_vdbg(ctrl->dev, | 354 | dev_vdbg(priv->dev, |
355 | "fsl_elbc_cmdfunc: NAND_CMD_ERASE1, " | 355 | "fsl_elbc_cmdfunc: NAND_CMD_ERASE1, " |
356 | "page_addr: 0x%x.\n", page_addr); | 356 | "page_addr: 0x%x.\n", page_addr); |
357 | set_addr(mtd, 0, page_addr, 0); | 357 | set_addr(mtd, 0, page_addr, 0); |
@@ -359,7 +359,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
359 | 359 | ||
360 | /* ERASE2 uses the block and page address from ERASE1 */ | 360 | /* ERASE2 uses the block and page address from ERASE1 */ |
361 | case NAND_CMD_ERASE2: | 361 | case NAND_CMD_ERASE2: |
362 | dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n"); | 362 | dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n"); |
363 | 363 | ||
364 | out_be32(&lbc->fir, | 364 | out_be32(&lbc->fir, |
365 | (FIR_OP_CM0 << FIR_OP0_SHIFT) | | 365 | (FIR_OP_CM0 << FIR_OP0_SHIFT) | |
@@ -374,8 +374,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
374 | (NAND_CMD_ERASE2 << FCR_CMD2_SHIFT)); | 374 | (NAND_CMD_ERASE2 << FCR_CMD2_SHIFT)); |
375 | 375 | ||
376 | out_be32(&lbc->fbcr, 0); | 376 | out_be32(&lbc->fbcr, 0); |
377 | ctrl->read_bytes = 0; | 377 | elbc_fcm_ctrl->read_bytes = 0; |
378 | ctrl->use_mdr = 1; | 378 | elbc_fcm_ctrl->use_mdr = 1; |
379 | 379 | ||
380 | fsl_elbc_run_command(mtd); | 380 | fsl_elbc_run_command(mtd); |
381 | return; | 381 | return; |
@@ -383,14 +383,12 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
383 | /* SEQIN sets up the addr buffer and all registers except the length */ | 383 | /* SEQIN sets up the addr buffer and all registers except the length */ |
384 | case NAND_CMD_SEQIN: { | 384 | case NAND_CMD_SEQIN: { |
385 | __be32 fcr; | 385 | __be32 fcr; |
386 | dev_vdbg(ctrl->dev, | 386 | dev_vdbg(priv->dev, |
387 | "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, " | 387 | "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, " |
388 | "page_addr: 0x%x, column: 0x%x.\n", | 388 | "page_addr: 0x%x, column: 0x%x.\n", |
389 | page_addr, column); | 389 | page_addr, column); |
390 | 390 | ||
391 | ctrl->column = column; | 391 | elbc_fcm_ctrl->use_mdr = 1; |
392 | ctrl->oob = 0; | ||
393 | ctrl->use_mdr = 1; | ||
394 | 392 | ||
395 | fcr = (NAND_CMD_STATUS << FCR_CMD1_SHIFT) | | 393 | fcr = (NAND_CMD_STATUS << FCR_CMD1_SHIFT) | |
396 | (NAND_CMD_SEQIN << FCR_CMD2_SHIFT) | | 394 | (NAND_CMD_SEQIN << FCR_CMD2_SHIFT) | |
@@ -420,7 +418,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
420 | /* OOB area --> READOOB */ | 418 | /* OOB area --> READOOB */ |
421 | column -= mtd->writesize; | 419 | column -= mtd->writesize; |
422 | fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT; | 420 | fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT; |
423 | ctrl->oob = 1; | 421 | elbc_fcm_ctrl->oob = 1; |
424 | } else { | 422 | } else { |
425 | WARN_ON(column != 0); | 423 | WARN_ON(column != 0); |
426 | /* First 256 bytes --> READ0 */ | 424 | /* First 256 bytes --> READ0 */ |
@@ -429,24 +427,24 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
429 | } | 427 | } |
430 | 428 | ||
431 | out_be32(&lbc->fcr, fcr); | 429 | out_be32(&lbc->fcr, fcr); |
432 | set_addr(mtd, column, page_addr, ctrl->oob); | 430 | set_addr(mtd, column, page_addr, elbc_fcm_ctrl->oob); |
433 | return; | 431 | return; |
434 | } | 432 | } |
435 | 433 | ||
436 | /* PAGEPROG reuses all of the setup from SEQIN and adds the length */ | 434 | /* PAGEPROG reuses all of the setup from SEQIN and adds the length */ |
437 | case NAND_CMD_PAGEPROG: { | 435 | case NAND_CMD_PAGEPROG: { |
438 | int full_page; | 436 | int full_page; |
439 | dev_vdbg(ctrl->dev, | 437 | dev_vdbg(priv->dev, |
440 | "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG " | 438 | "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG " |
441 | "writing %d bytes.\n", ctrl->index); | 439 | "writing %d bytes.\n", elbc_fcm_ctrl->index); |
442 | 440 | ||
443 | /* if the write did not start at 0 or is not a full page | 441 | /* if the write did not start at 0 or is not a full page |
444 | * then set the exact length, otherwise use a full page | 442 | * then set the exact length, otherwise use a full page |
445 | * write so the HW generates the ECC. | 443 | * write so the HW generates the ECC. |
446 | */ | 444 | */ |
447 | if (ctrl->oob || ctrl->column != 0 || | 445 | if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 || |
448 | ctrl->index != mtd->writesize + mtd->oobsize) { | 446 | elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize) { |
449 | out_be32(&lbc->fbcr, ctrl->index); | 447 | out_be32(&lbc->fbcr, elbc_fcm_ctrl->index); |
450 | full_page = 0; | 448 | full_page = 0; |
451 | } else { | 449 | } else { |
452 | out_be32(&lbc->fbcr, 0); | 450 | out_be32(&lbc->fbcr, 0); |
@@ -458,21 +456,21 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
458 | /* Read back the page in order to fill in the ECC for the | 456 | /* Read back the page in order to fill in the ECC for the |
459 | * caller. Is this really needed? | 457 | * caller. Is this really needed? |
460 | */ | 458 | */ |
461 | if (full_page && ctrl->oob_poi) { | 459 | if (full_page && elbc_fcm_ctrl->oob_poi) { |
462 | out_be32(&lbc->fbcr, 3); | 460 | out_be32(&lbc->fbcr, 3); |
463 | set_addr(mtd, 6, page_addr, 1); | 461 | set_addr(mtd, 6, page_addr, 1); |
464 | 462 | ||
465 | ctrl->read_bytes = mtd->writesize + 9; | 463 | elbc_fcm_ctrl->read_bytes = mtd->writesize + 9; |
466 | 464 | ||
467 | fsl_elbc_do_read(chip, 1); | 465 | fsl_elbc_do_read(chip, 1); |
468 | fsl_elbc_run_command(mtd); | 466 | fsl_elbc_run_command(mtd); |
469 | 467 | ||
470 | memcpy_fromio(ctrl->oob_poi + 6, | 468 | memcpy_fromio(elbc_fcm_ctrl->oob_poi + 6, |
471 | &ctrl->addr[ctrl->index], 3); | 469 | &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], 3); |
472 | ctrl->index += 3; | 470 | elbc_fcm_ctrl->index += 3; |
473 | } | 471 | } |
474 | 472 | ||
475 | ctrl->oob_poi = NULL; | 473 | elbc_fcm_ctrl->oob_poi = NULL; |
476 | return; | 474 | return; |
477 | } | 475 | } |
478 | 476 | ||
@@ -485,26 +483,26 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
485 | out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT); | 483 | out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT); |
486 | out_be32(&lbc->fbcr, 1); | 484 | out_be32(&lbc->fbcr, 1); |
487 | set_addr(mtd, 0, 0, 0); | 485 | set_addr(mtd, 0, 0, 0); |
488 | ctrl->read_bytes = 1; | 486 | elbc_fcm_ctrl->read_bytes = 1; |
489 | 487 | ||
490 | fsl_elbc_run_command(mtd); | 488 | fsl_elbc_run_command(mtd); |
491 | 489 | ||
492 | /* The chip always seems to report that it is | 490 | /* The chip always seems to report that it is |
493 | * write-protected, even when it is not. | 491 | * write-protected, even when it is not. |
494 | */ | 492 | */ |
495 | setbits8(ctrl->addr, NAND_STATUS_WP); | 493 | setbits8(elbc_fcm_ctrl->addr, NAND_STATUS_WP); |
496 | return; | 494 | return; |
497 | 495 | ||
498 | /* RESET without waiting for the ready line */ | 496 | /* RESET without waiting for the ready line */ |
499 | case NAND_CMD_RESET: | 497 | case NAND_CMD_RESET: |
500 | dev_dbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n"); | 498 | dev_dbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n"); |
501 | out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT); | 499 | out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT); |
502 | out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT); | 500 | out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT); |
503 | fsl_elbc_run_command(mtd); | 501 | fsl_elbc_run_command(mtd); |
504 | return; | 502 | return; |
505 | 503 | ||
506 | default: | 504 | default: |
507 | dev_err(ctrl->dev, | 505 | dev_err(priv->dev, |
508 | "fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n", | 506 | "fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n", |
509 | command); | 507 | command); |
510 | } | 508 | } |
@@ -524,24 +522,24 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) | |||
524 | { | 522 | { |
525 | struct nand_chip *chip = mtd->priv; | 523 | struct nand_chip *chip = mtd->priv; |
526 | struct fsl_elbc_mtd *priv = chip->priv; | 524 | struct fsl_elbc_mtd *priv = chip->priv; |
527 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 525 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
528 | unsigned int bufsize = mtd->writesize + mtd->oobsize; | 526 | unsigned int bufsize = mtd->writesize + mtd->oobsize; |
529 | 527 | ||
530 | if (len <= 0) { | 528 | if (len <= 0) { |
531 | dev_err(ctrl->dev, "write_buf of %d bytes", len); | 529 | dev_err(priv->dev, "write_buf of %d bytes", len); |
532 | ctrl->status = 0; | 530 | elbc_fcm_ctrl->status = 0; |
533 | return; | 531 | return; |
534 | } | 532 | } |
535 | 533 | ||
536 | if ((unsigned int)len > bufsize - ctrl->index) { | 534 | if ((unsigned int)len > bufsize - elbc_fcm_ctrl->index) { |
537 | dev_err(ctrl->dev, | 535 | dev_err(priv->dev, |
538 | "write_buf beyond end of buffer " | 536 | "write_buf beyond end of buffer " |
539 | "(%d requested, %u available)\n", | 537 | "(%d requested, %u available)\n", |
540 | len, bufsize - ctrl->index); | 538 | len, bufsize - elbc_fcm_ctrl->index); |
541 | len = bufsize - ctrl->index; | 539 | len = bufsize - elbc_fcm_ctrl->index; |
542 | } | 540 | } |
543 | 541 | ||
544 | memcpy_toio(&ctrl->addr[ctrl->index], buf, len); | 542 | memcpy_toio(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], buf, len); |
545 | /* | 543 | /* |
546 | * This is workaround for the weird elbc hangs during nand write, | 544 | * This is workaround for the weird elbc hangs during nand write, |
547 | * Scott Wood says: "...perhaps difference in how long it takes a | 545 | * Scott Wood says: "...perhaps difference in how long it takes a |
@@ -549,9 +547,9 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) | |||
549 | * is causing problems, and sync isn't helping for some reason." | 547 | * is causing problems, and sync isn't helping for some reason." |
550 | * Reading back the last byte helps though. | 548 | * Reading back the last byte helps though. |
551 | */ | 549 | */ |
552 | in_8(&ctrl->addr[ctrl->index] + len - 1); | 550 | in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index] + len - 1); |
553 | 551 | ||
554 | ctrl->index += len; | 552 | elbc_fcm_ctrl->index += len; |
555 | } | 553 | } |
556 | 554 | ||
557 | /* | 555 | /* |
@@ -562,13 +560,13 @@ static u8 fsl_elbc_read_byte(struct mtd_info *mtd) | |||
562 | { | 560 | { |
563 | struct nand_chip *chip = mtd->priv; | 561 | struct nand_chip *chip = mtd->priv; |
564 | struct fsl_elbc_mtd *priv = chip->priv; | 562 | struct fsl_elbc_mtd *priv = chip->priv; |
565 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 563 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
566 | 564 | ||
567 | /* If there are still bytes in the FCM, then use the next byte. */ | 565 | /* If there are still bytes in the FCM, then use the next byte. */ |
568 | if (ctrl->index < ctrl->read_bytes) | 566 | if (elbc_fcm_ctrl->index < elbc_fcm_ctrl->read_bytes) |
569 | return in_8(&ctrl->addr[ctrl->index++]); | 567 | return in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index++]); |
570 | 568 | ||
571 | dev_err(ctrl->dev, "read_byte beyond end of buffer\n"); | 569 | dev_err(priv->dev, "read_byte beyond end of buffer\n"); |
572 | return ERR_BYTE; | 570 | return ERR_BYTE; |
573 | } | 571 | } |
574 | 572 | ||
@@ -579,18 +577,19 @@ static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len) | |||
579 | { | 577 | { |
580 | struct nand_chip *chip = mtd->priv; | 578 | struct nand_chip *chip = mtd->priv; |
581 | struct fsl_elbc_mtd *priv = chip->priv; | 579 | struct fsl_elbc_mtd *priv = chip->priv; |
582 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 580 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
583 | int avail; | 581 | int avail; |
584 | 582 | ||
585 | if (len < 0) | 583 | if (len < 0) |
586 | return; | 584 | return; |
587 | 585 | ||
588 | avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index); | 586 | avail = min((unsigned int)len, |
589 | memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail); | 587 | elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index); |
590 | ctrl->index += avail; | 588 | memcpy_fromio(buf, &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], avail); |
589 | elbc_fcm_ctrl->index += avail; | ||
591 | 590 | ||
592 | if (len > avail) | 591 | if (len > avail) |
593 | dev_err(ctrl->dev, | 592 | dev_err(priv->dev, |
594 | "read_buf beyond end of buffer " | 593 | "read_buf beyond end of buffer " |
595 | "(%d requested, %d available)\n", | 594 | "(%d requested, %d available)\n", |
596 | len, avail); | 595 | len, avail); |
@@ -603,30 +602,32 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) | |||
603 | { | 602 | { |
604 | struct nand_chip *chip = mtd->priv; | 603 | struct nand_chip *chip = mtd->priv; |
605 | struct fsl_elbc_mtd *priv = chip->priv; | 604 | struct fsl_elbc_mtd *priv = chip->priv; |
606 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 605 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
607 | int i; | 606 | int i; |
608 | 607 | ||
609 | if (len < 0) { | 608 | if (len < 0) { |
610 | dev_err(ctrl->dev, "write_buf of %d bytes", len); | 609 | dev_err(priv->dev, "write_buf of %d bytes", len); |
611 | return -EINVAL; | 610 | return -EINVAL; |
612 | } | 611 | } |
613 | 612 | ||
614 | if ((unsigned int)len > ctrl->read_bytes - ctrl->index) { | 613 | if ((unsigned int)len > |
615 | dev_err(ctrl->dev, | 614 | elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index) { |
616 | "verify_buf beyond end of buffer " | 615 | dev_err(priv->dev, |
617 | "(%d requested, %u available)\n", | 616 | "verify_buf beyond end of buffer " |
618 | len, ctrl->read_bytes - ctrl->index); | 617 | "(%d requested, %u available)\n", |
618 | len, elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index); | ||
619 | 619 | ||
620 | ctrl->index = ctrl->read_bytes; | 620 | elbc_fcm_ctrl->index = elbc_fcm_ctrl->read_bytes; |
621 | return -EINVAL; | 621 | return -EINVAL; |
622 | } | 622 | } |
623 | 623 | ||
624 | for (i = 0; i < len; i++) | 624 | for (i = 0; i < len; i++) |
625 | if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i]) | 625 | if (in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index + i]) |
626 | != buf[i]) | ||
626 | break; | 627 | break; |
627 | 628 | ||
628 | ctrl->index += len; | 629 | elbc_fcm_ctrl->index += len; |
629 | return i == len && ctrl->status == LTESR_CC ? 0 : -EIO; | 630 | return i == len && elbc_fcm_ctrl->status == LTESR_CC ? 0 : -EIO; |
630 | } | 631 | } |
631 | 632 | ||
632 | /* This function is called after Program and Erase Operations to | 633 | /* This function is called after Program and Erase Operations to |
@@ -635,22 +636,22 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) | |||
635 | static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip) | 636 | static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip) |
636 | { | 637 | { |
637 | struct fsl_elbc_mtd *priv = chip->priv; | 638 | struct fsl_elbc_mtd *priv = chip->priv; |
638 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 639 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
639 | 640 | ||
640 | if (ctrl->status != LTESR_CC) | 641 | if (elbc_fcm_ctrl->status != LTESR_CC) |
641 | return NAND_STATUS_FAIL; | 642 | return NAND_STATUS_FAIL; |
642 | 643 | ||
643 | /* The chip always seems to report that it is | 644 | /* The chip always seems to report that it is |
644 | * write-protected, even when it is not. | 645 | * write-protected, even when it is not. |
645 | */ | 646 | */ |
646 | return (ctrl->mdr & 0xff) | NAND_STATUS_WP; | 647 | return (elbc_fcm_ctrl->mdr & 0xff) | NAND_STATUS_WP; |
647 | } | 648 | } |
648 | 649 | ||
649 | static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) | 650 | static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) |
650 | { | 651 | { |
651 | struct nand_chip *chip = mtd->priv; | 652 | struct nand_chip *chip = mtd->priv; |
652 | struct fsl_elbc_mtd *priv = chip->priv; | 653 | struct fsl_elbc_mtd *priv = chip->priv; |
653 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 654 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
654 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | 655 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
655 | unsigned int al; | 656 | unsigned int al; |
656 | 657 | ||
@@ -665,41 +666,41 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) | |||
665 | priv->fmr |= (12 << FMR_CWTO_SHIFT) | /* Timeout > 12 ms */ | 666 | priv->fmr |= (12 << FMR_CWTO_SHIFT) | /* Timeout > 12 ms */ |
666 | (al << FMR_AL_SHIFT); | 667 | (al << FMR_AL_SHIFT); |
667 | 668 | ||
668 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->numchips = %d\n", | 669 | dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n", |
669 | chip->numchips); | 670 | chip->numchips); |
670 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chipsize = %lld\n", | 671 | dev_dbg(priv->dev, "fsl_elbc_init: nand->chipsize = %lld\n", |
671 | chip->chipsize); | 672 | chip->chipsize); |
672 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->pagemask = %8x\n", | 673 | dev_dbg(priv->dev, "fsl_elbc_init: nand->pagemask = %8x\n", |
673 | chip->pagemask); | 674 | chip->pagemask); |
674 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_delay = %d\n", | 675 | dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_delay = %d\n", |
675 | chip->chip_delay); | 676 | chip->chip_delay); |
676 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->badblockpos = %d\n", | 677 | dev_dbg(priv->dev, "fsl_elbc_init: nand->badblockpos = %d\n", |
677 | chip->badblockpos); | 678 | chip->badblockpos); |
678 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_shift = %d\n", | 679 | dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_shift = %d\n", |
679 | chip->chip_shift); | 680 | chip->chip_shift); |
680 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->page_shift = %d\n", | 681 | dev_dbg(priv->dev, "fsl_elbc_init: nand->page_shift = %d\n", |
681 | chip->page_shift); | 682 | chip->page_shift); |
682 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n", | 683 | dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n", |
683 | chip->phys_erase_shift); | 684 | chip->phys_erase_shift); |
684 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecclayout = %p\n", | 685 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecclayout = %p\n", |
685 | chip->ecclayout); | 686 | chip->ecclayout); |
686 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.mode = %d\n", | 687 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n", |
687 | chip->ecc.mode); | 688 | chip->ecc.mode); |
688 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.steps = %d\n", | 689 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n", |
689 | chip->ecc.steps); | 690 | chip->ecc.steps); |
690 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n", | 691 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n", |
691 | chip->ecc.bytes); | 692 | chip->ecc.bytes); |
692 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.total = %d\n", | 693 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n", |
693 | chip->ecc.total); | 694 | chip->ecc.total); |
694 | dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.layout = %p\n", | 695 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.layout = %p\n", |
695 | chip->ecc.layout); | 696 | chip->ecc.layout); |
696 | dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags); | 697 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags); |
697 | dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size); | 698 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size); |
698 | dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->erasesize = %d\n", | 699 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->erasesize = %d\n", |
699 | mtd->erasesize); | 700 | mtd->erasesize); |
700 | dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->writesize = %d\n", | 701 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->writesize = %d\n", |
701 | mtd->writesize); | 702 | mtd->writesize); |
702 | dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->oobsize = %d\n", | 703 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->oobsize = %d\n", |
703 | mtd->oobsize); | 704 | mtd->oobsize); |
704 | 705 | ||
705 | /* adjust Option Register and ECC to match Flash page size */ | 706 | /* adjust Option Register and ECC to match Flash page size */ |
@@ -719,7 +720,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) | |||
719 | chip->badblock_pattern = &largepage_memorybased; | 720 | chip->badblock_pattern = &largepage_memorybased; |
720 | } | 721 | } |
721 | } else { | 722 | } else { |
722 | dev_err(ctrl->dev, | 723 | dev_err(priv->dev, |
723 | "fsl_elbc_init: page size %d is not supported\n", | 724 | "fsl_elbc_init: page size %d is not supported\n", |
724 | mtd->writesize); | 725 | mtd->writesize); |
725 | return -1; | 726 | return -1; |
@@ -750,18 +751,19 @@ static void fsl_elbc_write_page(struct mtd_info *mtd, | |||
750 | const uint8_t *buf) | 751 | const uint8_t *buf) |
751 | { | 752 | { |
752 | struct fsl_elbc_mtd *priv = chip->priv; | 753 | struct fsl_elbc_mtd *priv = chip->priv; |
753 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 754 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
754 | 755 | ||
755 | fsl_elbc_write_buf(mtd, buf, mtd->writesize); | 756 | fsl_elbc_write_buf(mtd, buf, mtd->writesize); |
756 | fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); | 757 | fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); |
757 | 758 | ||
758 | ctrl->oob_poi = chip->oob_poi; | 759 | elbc_fcm_ctrl->oob_poi = chip->oob_poi; |
759 | } | 760 | } |
760 | 761 | ||
761 | static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) | 762 | static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) |
762 | { | 763 | { |
763 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 764 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
764 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | 765 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
766 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; | ||
765 | struct nand_chip *chip = &priv->chip; | 767 | struct nand_chip *chip = &priv->chip; |
766 | 768 | ||
767 | dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank); | 769 | dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank); |
@@ -790,7 +792,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) | |||
790 | chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR | | 792 | chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR | |
791 | NAND_USE_FLASH_BBT; | 793 | NAND_USE_FLASH_BBT; |
792 | 794 | ||
793 | chip->controller = &ctrl->controller; | 795 | chip->controller = &elbc_fcm_ctrl->controller; |
794 | chip->priv = priv; | 796 | chip->priv = priv; |
795 | 797 | ||
796 | chip->ecc.read_page = fsl_elbc_read_page; | 798 | chip->ecc.read_page = fsl_elbc_read_page; |
@@ -815,8 +817,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) | |||
815 | 817 | ||
816 | static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv) | 818 | static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv) |
817 | { | 819 | { |
818 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 820 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
819 | |||
820 | nand_release(&priv->mtd); | 821 | nand_release(&priv->mtd); |
821 | 822 | ||
822 | kfree(priv->mtd.name); | 823 | kfree(priv->mtd.name); |
@@ -824,18 +825,21 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv) | |||
824 | if (priv->vbase) | 825 | if (priv->vbase) |
825 | iounmap(priv->vbase); | 826 | iounmap(priv->vbase); |
826 | 827 | ||
827 | ctrl->chips[priv->bank] = NULL; | 828 | elbc_fcm_ctrl->chips[priv->bank] = NULL; |
828 | kfree(priv); | 829 | kfree(priv); |
829 | 830 | kfree(elbc_fcm_ctrl); | |
830 | return 0; | 831 | return 0; |
831 | } | 832 | } |
832 | 833 | ||
833 | static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl, | 834 | static DEFINE_MUTEX(fsl_elbc_nand_mutex); |
834 | struct device_node *node) | 835 | |
836 | static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev) | ||
835 | { | 837 | { |
836 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | 838 | struct fsl_lbc_regs __iomem *lbc; |
837 | struct fsl_elbc_mtd *priv; | 839 | struct fsl_elbc_mtd *priv; |
838 | struct resource res; | 840 | struct resource res; |
841 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl; | ||
842 | |||
839 | #ifdef CONFIG_MTD_PARTITIONS | 843 | #ifdef CONFIG_MTD_PARTITIONS |
840 | static const char *part_probe_types[] | 844 | static const char *part_probe_types[] |
841 | = { "cmdlinepart", "RedBoot", NULL }; | 845 | = { "cmdlinepart", "RedBoot", NULL }; |
@@ -843,11 +847,18 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl, | |||
843 | #endif | 847 | #endif |
844 | int ret; | 848 | int ret; |
845 | int bank; | 849 | int bank; |
850 | struct device *dev; | ||
851 | struct device_node *node = pdev->dev.of_node; | ||
852 | |||
853 | if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) | ||
854 | return -ENODEV; | ||
855 | lbc = fsl_lbc_ctrl_dev->regs; | ||
856 | dev = fsl_lbc_ctrl_dev->dev; | ||
846 | 857 | ||
847 | /* get, allocate and map the memory resource */ | 858 | /* get, allocate and map the memory resource */ |
848 | ret = of_address_to_resource(node, 0, &res); | 859 | ret = of_address_to_resource(node, 0, &res); |
849 | if (ret) { | 860 | if (ret) { |
850 | dev_err(ctrl->dev, "failed to get resource\n"); | 861 | dev_err(dev, "failed to get resource\n"); |
851 | return ret; | 862 | return ret; |
852 | } | 863 | } |
853 | 864 | ||
@@ -857,11 +868,11 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl, | |||
857 | (in_be32(&lbc->bank[bank].br) & BR_MSEL) == BR_MS_FCM && | 868 | (in_be32(&lbc->bank[bank].br) & BR_MSEL) == BR_MS_FCM && |
858 | (in_be32(&lbc->bank[bank].br) & | 869 | (in_be32(&lbc->bank[bank].br) & |
859 | in_be32(&lbc->bank[bank].or) & BR_BA) | 870 | in_be32(&lbc->bank[bank].or) & BR_BA) |
860 | == res.start) | 871 | == fsl_lbc_addr(res.start)) |
861 | break; | 872 | break; |
862 | 873 | ||
863 | if (bank >= MAX_BANKS) { | 874 | if (bank >= MAX_BANKS) { |
864 | dev_err(ctrl->dev, "address did not match any chip selects\n"); | 875 | dev_err(dev, "address did not match any chip selects\n"); |
865 | return -ENODEV; | 876 | return -ENODEV; |
866 | } | 877 | } |
867 | 878 | ||
@@ -869,14 +880,33 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl, | |||
869 | if (!priv) | 880 | if (!priv) |
870 | return -ENOMEM; | 881 | return -ENOMEM; |
871 | 882 | ||
872 | ctrl->chips[bank] = priv; | 883 | mutex_lock(&fsl_elbc_nand_mutex); |
884 | if (!fsl_lbc_ctrl_dev->nand) { | ||
885 | elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL); | ||
886 | if (!elbc_fcm_ctrl) { | ||
887 | dev_err(dev, "failed to allocate memory\n"); | ||
888 | mutex_unlock(&fsl_elbc_nand_mutex); | ||
889 | ret = -ENOMEM; | ||
890 | goto err; | ||
891 | } | ||
892 | elbc_fcm_ctrl->counter++; | ||
893 | |||
894 | spin_lock_init(&elbc_fcm_ctrl->controller.lock); | ||
895 | init_waitqueue_head(&elbc_fcm_ctrl->controller.wq); | ||
896 | fsl_lbc_ctrl_dev->nand = elbc_fcm_ctrl; | ||
897 | } else { | ||
898 | elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand; | ||
899 | } | ||
900 | mutex_unlock(&fsl_elbc_nand_mutex); | ||
901 | |||
902 | elbc_fcm_ctrl->chips[bank] = priv; | ||
873 | priv->bank = bank; | 903 | priv->bank = bank; |
874 | priv->ctrl = ctrl; | 904 | priv->ctrl = fsl_lbc_ctrl_dev; |
875 | priv->dev = ctrl->dev; | 905 | priv->dev = dev; |
876 | 906 | ||
877 | priv->vbase = ioremap(res.start, resource_size(&res)); | 907 | priv->vbase = ioremap(res.start, resource_size(&res)); |
878 | if (!priv->vbase) { | 908 | if (!priv->vbase) { |
879 | dev_err(ctrl->dev, "failed to map chip region\n"); | 909 | dev_err(dev, "failed to map chip region\n"); |
880 | ret = -ENOMEM; | 910 | ret = -ENOMEM; |
881 | goto err; | 911 | goto err; |
882 | } | 912 | } |
@@ -933,171 +963,53 @@ err: | |||
933 | return ret; | 963 | return ret; |
934 | } | 964 | } |
935 | 965 | ||
936 | static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl) | 966 | static int fsl_elbc_nand_remove(struct platform_device *pdev) |
937 | { | 967 | { |
938 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | ||
939 | |||
940 | /* | ||
941 | * NAND transactions can tie up the bus for a long time, so set the | ||
942 | * bus timeout to max by clearing LBCR[BMT] (highest base counter | ||
943 | * value) and setting LBCR[BMTPS] to the highest prescaler value. | ||
944 | */ | ||
945 | clrsetbits_be32(&lbc->lbcr, LBCR_BMT, 15); | ||
946 | |||
947 | /* clear event registers */ | ||
948 | setbits32(&lbc->ltesr, LTESR_NAND_MASK); | ||
949 | out_be32(&lbc->lteatr, 0); | ||
950 | |||
951 | /* Enable interrupts for any detected events */ | ||
952 | out_be32(&lbc->lteir, LTESR_NAND_MASK); | ||
953 | |||
954 | ctrl->read_bytes = 0; | ||
955 | ctrl->index = 0; | ||
956 | ctrl->addr = NULL; | ||
957 | |||
958 | return 0; | ||
959 | } | ||
960 | |||
961 | static int fsl_elbc_ctrl_remove(struct platform_device *ofdev) | ||
962 | { | ||
963 | struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev); | ||
964 | int i; | 968 | int i; |
965 | 969 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand; | |
966 | for (i = 0; i < MAX_BANKS; i++) | 970 | for (i = 0; i < MAX_BANKS; i++) |
967 | if (ctrl->chips[i]) | 971 | if (elbc_fcm_ctrl->chips[i]) |
968 | fsl_elbc_chip_remove(ctrl->chips[i]); | 972 | fsl_elbc_chip_remove(elbc_fcm_ctrl->chips[i]); |
969 | 973 | ||
970 | if (ctrl->irq) | 974 | mutex_lock(&fsl_elbc_nand_mutex); |
971 | free_irq(ctrl->irq, ctrl); | 975 | elbc_fcm_ctrl->counter--; |
972 | 976 | if (!elbc_fcm_ctrl->counter) { | |
973 | if (ctrl->regs) | 977 | fsl_lbc_ctrl_dev->nand = NULL; |
974 | iounmap(ctrl->regs); | 978 | kfree(elbc_fcm_ctrl); |
975 | |||
976 | dev_set_drvdata(&ofdev->dev, NULL); | ||
977 | kfree(ctrl); | ||
978 | return 0; | ||
979 | } | ||
980 | |||
981 | /* NOTE: This interrupt is also used to report other localbus events, | ||
982 | * such as transaction errors on other chipselects. If we want to | ||
983 | * capture those, we'll need to move the IRQ code into a shared | ||
984 | * LBC driver. | ||
985 | */ | ||
986 | |||
987 | static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data) | ||
988 | { | ||
989 | struct fsl_elbc_ctrl *ctrl = data; | ||
990 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; | ||
991 | __be32 status = in_be32(&lbc->ltesr) & LTESR_NAND_MASK; | ||
992 | |||
993 | if (status) { | ||
994 | out_be32(&lbc->ltesr, status); | ||
995 | out_be32(&lbc->lteatr, 0); | ||
996 | |||
997 | ctrl->irq_status = status; | ||
998 | smp_wmb(); | ||
999 | wake_up(&ctrl->irq_wait); | ||
1000 | |||
1001 | return IRQ_HANDLED; | ||
1002 | } | 979 | } |
1003 | 980 | mutex_unlock(&fsl_elbc_nand_mutex); | |
1004 | return IRQ_NONE; | ||
1005 | } | ||
1006 | |||
1007 | /* fsl_elbc_ctrl_probe | ||
1008 | * | ||
1009 | * called by device layer when it finds a device matching | ||
1010 | * one our driver can handled. This code allocates all of | ||
1011 | * the resources needed for the controller only. The | ||
1012 | * resources for the NAND banks themselves are allocated | ||
1013 | * in the chip probe function. | ||
1014 | */ | ||
1015 | |||
1016 | static int __devinit fsl_elbc_ctrl_probe(struct platform_device *ofdev, | ||
1017 | const struct of_device_id *match) | ||
1018 | { | ||
1019 | struct device_node *child; | ||
1020 | struct fsl_elbc_ctrl *ctrl; | ||
1021 | int ret; | ||
1022 | |||
1023 | ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); | ||
1024 | if (!ctrl) | ||
1025 | return -ENOMEM; | ||
1026 | |||
1027 | dev_set_drvdata(&ofdev->dev, ctrl); | ||
1028 | |||
1029 | spin_lock_init(&ctrl->controller.lock); | ||
1030 | init_waitqueue_head(&ctrl->controller.wq); | ||
1031 | init_waitqueue_head(&ctrl->irq_wait); | ||
1032 | |||
1033 | ctrl->regs = of_iomap(ofdev->dev.of_node, 0); | ||
1034 | if (!ctrl->regs) { | ||
1035 | dev_err(&ofdev->dev, "failed to get memory region\n"); | ||
1036 | ret = -ENODEV; | ||
1037 | goto err; | ||
1038 | } | ||
1039 | |||
1040 | ctrl->irq = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); | ||
1041 | if (ctrl->irq == NO_IRQ) { | ||
1042 | dev_err(&ofdev->dev, "failed to get irq resource\n"); | ||
1043 | ret = -ENODEV; | ||
1044 | goto err; | ||
1045 | } | ||
1046 | |||
1047 | ctrl->dev = &ofdev->dev; | ||
1048 | |||
1049 | ret = fsl_elbc_ctrl_init(ctrl); | ||
1050 | if (ret < 0) | ||
1051 | goto err; | ||
1052 | |||
1053 | ret = request_irq(ctrl->irq, fsl_elbc_ctrl_irq, 0, "fsl-elbc", ctrl); | ||
1054 | if (ret != 0) { | ||
1055 | dev_err(&ofdev->dev, "failed to install irq (%d)\n", | ||
1056 | ctrl->irq); | ||
1057 | ret = ctrl->irq; | ||
1058 | goto err; | ||
1059 | } | ||
1060 | |||
1061 | for_each_child_of_node(ofdev->dev.of_node, child) | ||
1062 | if (of_device_is_compatible(child, "fsl,elbc-fcm-nand")) | ||
1063 | fsl_elbc_chip_probe(ctrl, child); | ||
1064 | 981 | ||
1065 | return 0; | 982 | return 0; |
1066 | 983 | ||
1067 | err: | ||
1068 | fsl_elbc_ctrl_remove(ofdev); | ||
1069 | return ret; | ||
1070 | } | 984 | } |
1071 | 985 | ||
1072 | static const struct of_device_id fsl_elbc_match[] = { | 986 | static const struct of_device_id fsl_elbc_nand_match[] = { |
1073 | { | 987 | { .compatible = "fsl,elbc-fcm-nand", }, |
1074 | .compatible = "fsl,elbc", | ||
1075 | }, | ||
1076 | {} | 988 | {} |
1077 | }; | 989 | }; |
1078 | 990 | ||
1079 | static struct of_platform_driver fsl_elbc_ctrl_driver = { | 991 | static struct platform_driver fsl_elbc_nand_driver = { |
1080 | .driver = { | 992 | .driver = { |
1081 | .name = "fsl-elbc", | 993 | .name = "fsl,elbc-fcm-nand", |
1082 | .owner = THIS_MODULE, | 994 | .owner = THIS_MODULE, |
1083 | .of_match_table = fsl_elbc_match, | 995 | .of_match_table = fsl_elbc_nand_match, |
1084 | }, | 996 | }, |
1085 | .probe = fsl_elbc_ctrl_probe, | 997 | .probe = fsl_elbc_nand_probe, |
1086 | .remove = fsl_elbc_ctrl_remove, | 998 | .remove = fsl_elbc_nand_remove, |
1087 | }; | 999 | }; |
1088 | 1000 | ||
1089 | static int __init fsl_elbc_init(void) | 1001 | static int __init fsl_elbc_nand_init(void) |
1090 | { | 1002 | { |
1091 | return of_register_platform_driver(&fsl_elbc_ctrl_driver); | 1003 | return platform_driver_register(&fsl_elbc_nand_driver); |
1092 | } | 1004 | } |
1093 | 1005 | ||
1094 | static void __exit fsl_elbc_exit(void) | 1006 | static void __exit fsl_elbc_nand_exit(void) |
1095 | { | 1007 | { |
1096 | of_unregister_platform_driver(&fsl_elbc_ctrl_driver); | 1008 | platform_driver_unregister(&fsl_elbc_nand_driver); |
1097 | } | 1009 | } |
1098 | 1010 | ||
1099 | module_init(fsl_elbc_init); | 1011 | module_init(fsl_elbc_nand_init); |
1100 | module_exit(fsl_elbc_exit); | 1012 | module_exit(fsl_elbc_nand_exit); |
1101 | 1013 | ||
1102 | MODULE_LICENSE("GPL"); | 1014 | MODULE_LICENSE("GPL"); |
1103 | MODULE_AUTHOR("Freescale"); | 1015 | MODULE_AUTHOR("Freescale"); |
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c index 4eff8b25e5af..efdcca94ce55 100644 --- a/drivers/mtd/nand/fsl_upm.c +++ b/drivers/mtd/nand/fsl_upm.c | |||
@@ -186,7 +186,7 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun, | |||
186 | if (!flash_np) | 186 | if (!flash_np) |
187 | return -ENODEV; | 187 | return -ENODEV; |
188 | 188 | ||
189 | fun->mtd.name = kasprintf(GFP_KERNEL, "%x.%s", io_res->start, | 189 | fun->mtd.name = kasprintf(GFP_KERNEL, "0x%llx.%s", (u64)io_res->start, |
190 | flash_np->name); | 190 | flash_np->name); |
191 | if (!fun->mtd.name) { | 191 | if (!fun->mtd.name) { |
192 | ret = -ENOMEM; | 192 | ret = -ENOMEM; |
@@ -222,7 +222,7 @@ static int __devinit fun_probe(struct platform_device *ofdev, | |||
222 | { | 222 | { |
223 | struct fsl_upm_nand *fun; | 223 | struct fsl_upm_nand *fun; |
224 | struct resource io_res; | 224 | struct resource io_res; |
225 | const uint32_t *prop; | 225 | const __be32 *prop; |
226 | int rnb_gpio; | 226 | int rnb_gpio; |
227 | int ret; | 227 | int ret; |
228 | int size; | 228 | int size; |
@@ -270,7 +270,7 @@ static int __devinit fun_probe(struct platform_device *ofdev, | |||
270 | goto err1; | 270 | goto err1; |
271 | } | 271 | } |
272 | for (i = 0; i < fun->mchip_count; i++) | 272 | for (i = 0; i < fun->mchip_count; i++) |
273 | fun->mchip_offsets[i] = prop[i]; | 273 | fun->mchip_offsets[i] = be32_to_cpu(prop[i]); |
274 | } else { | 274 | } else { |
275 | fun->mchip_count = 1; | 275 | fun->mchip_count = 1; |
276 | } | 276 | } |
@@ -295,13 +295,13 @@ static int __devinit fun_probe(struct platform_device *ofdev, | |||
295 | 295 | ||
296 | prop = of_get_property(ofdev->dev.of_node, "chip-delay", NULL); | 296 | prop = of_get_property(ofdev->dev.of_node, "chip-delay", NULL); |
297 | if (prop) | 297 | if (prop) |
298 | fun->chip_delay = *prop; | 298 | fun->chip_delay = be32_to_cpup(prop); |
299 | else | 299 | else |
300 | fun->chip_delay = 50; | 300 | fun->chip_delay = 50; |
301 | 301 | ||
302 | prop = of_get_property(ofdev->dev.of_node, "fsl,upm-wait-flags", &size); | 302 | prop = of_get_property(ofdev->dev.of_node, "fsl,upm-wait-flags", &size); |
303 | if (prop && size == sizeof(uint32_t)) | 303 | if (prop && size == sizeof(uint32_t)) |
304 | fun->wait_flags = *prop; | 304 | fun->wait_flags = be32_to_cpup(prop); |
305 | else | 305 | else |
306 | fun->wait_flags = FSL_UPM_WAIT_RUN_PATTERN | | 306 | fun->wait_flags = FSL_UPM_WAIT_RUN_PATTERN | |
307 | FSL_UPM_WAIT_WRITE_BYTE; | 307 | FSL_UPM_WAIT_WRITE_BYTE; |
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c new file mode 100644 index 000000000000..02edfba25b0c --- /dev/null +++ b/drivers/mtd/nand/fsmc_nand.c | |||
@@ -0,0 +1,866 @@ | |||
1 | /* | ||
2 | * drivers/mtd/nand/fsmc_nand.c | ||
3 | * | ||
4 | * ST Microelectronics | ||
5 | * Flexible Static Memory Controller (FSMC) | ||
6 | * Driver for NAND portions | ||
7 | * | ||
8 | * Copyright © 2010 ST Microelectronics | ||
9 | * Vipin Kumar <vipin.kumar@st.com> | ||
10 | * Ashish Priyadarshi | ||
11 | * | ||
12 | * Based on drivers/mtd/nand/nomadik_nand.c | ||
13 | * | ||
14 | * This file is licensed under the terms of the GNU General Public | ||
15 | * License version 2. This program is licensed "as is" without any | ||
16 | * warranty of any kind, whether express or implied. | ||
17 | */ | ||
18 | |||
19 | #include <linux/clk.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/resource.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <linux/types.h> | ||
26 | #include <linux/mtd/mtd.h> | ||
27 | #include <linux/mtd/nand.h> | ||
28 | #include <linux/mtd/nand_ecc.h> | ||
29 | #include <linux/platform_device.h> | ||
30 | #include <linux/mtd/partitions.h> | ||
31 | #include <linux/io.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <linux/mtd/fsmc.h> | ||
34 | #include <mtd/mtd-abi.h> | ||
35 | |||
36 | static struct nand_ecclayout fsmc_ecc1_layout = { | ||
37 | .eccbytes = 24, | ||
38 | .eccpos = {2, 3, 4, 18, 19, 20, 34, 35, 36, 50, 51, 52, | ||
39 | 66, 67, 68, 82, 83, 84, 98, 99, 100, 114, 115, 116}, | ||
40 | .oobfree = { | ||
41 | {.offset = 8, .length = 8}, | ||
42 | {.offset = 24, .length = 8}, | ||
43 | {.offset = 40, .length = 8}, | ||
44 | {.offset = 56, .length = 8}, | ||
45 | {.offset = 72, .length = 8}, | ||
46 | {.offset = 88, .length = 8}, | ||
47 | {.offset = 104, .length = 8}, | ||
48 | {.offset = 120, .length = 8} | ||
49 | } | ||
50 | }; | ||
51 | |||
52 | static struct nand_ecclayout fsmc_ecc4_lp_layout = { | ||
53 | .eccbytes = 104, | ||
54 | .eccpos = { 2, 3, 4, 5, 6, 7, 8, | ||
55 | 9, 10, 11, 12, 13, 14, | ||
56 | 18, 19, 20, 21, 22, 23, 24, | ||
57 | 25, 26, 27, 28, 29, 30, | ||
58 | 34, 35, 36, 37, 38, 39, 40, | ||
59 | 41, 42, 43, 44, 45, 46, | ||
60 | 50, 51, 52, 53, 54, 55, 56, | ||
61 | 57, 58, 59, 60, 61, 62, | ||
62 | 66, 67, 68, 69, 70, 71, 72, | ||
63 | 73, 74, 75, 76, 77, 78, | ||
64 | 82, 83, 84, 85, 86, 87, 88, | ||
65 | 89, 90, 91, 92, 93, 94, | ||
66 | 98, 99, 100, 101, 102, 103, 104, | ||
67 | 105, 106, 107, 108, 109, 110, | ||
68 | 114, 115, 116, 117, 118, 119, 120, | ||
69 | 121, 122, 123, 124, 125, 126 | ||
70 | }, | ||
71 | .oobfree = { | ||
72 | {.offset = 15, .length = 3}, | ||
73 | {.offset = 31, .length = 3}, | ||
74 | {.offset = 47, .length = 3}, | ||
75 | {.offset = 63, .length = 3}, | ||
76 | {.offset = 79, .length = 3}, | ||
77 | {.offset = 95, .length = 3}, | ||
78 | {.offset = 111, .length = 3}, | ||
79 | {.offset = 127, .length = 1} | ||
80 | } | ||
81 | }; | ||
82 | |||
83 | /* | ||
84 | * ECC placement definitions in oobfree type format. | ||
85 | * There are 13 bytes of ecc for every 512 byte block and it has to be read | ||
86 | * consecutively and immediately after the 512 byte data block for hardware to | ||
87 | * generate the error bit offsets in 512 byte data. | ||
88 | * Managing the ecc bytes in the following way makes it easier for software to | ||
89 | * read ecc bytes consecutive to data bytes. This way is similar to | ||
90 | * oobfree structure maintained already in generic nand driver | ||
91 | */ | ||
92 | static struct fsmc_eccplace fsmc_ecc4_lp_place = { | ||
93 | .eccplace = { | ||
94 | {.offset = 2, .length = 13}, | ||
95 | {.offset = 18, .length = 13}, | ||
96 | {.offset = 34, .length = 13}, | ||
97 | {.offset = 50, .length = 13}, | ||
98 | {.offset = 66, .length = 13}, | ||
99 | {.offset = 82, .length = 13}, | ||
100 | {.offset = 98, .length = 13}, | ||
101 | {.offset = 114, .length = 13} | ||
102 | } | ||
103 | }; | ||
104 | |||
105 | static struct nand_ecclayout fsmc_ecc4_sp_layout = { | ||
106 | .eccbytes = 13, | ||
107 | .eccpos = { 0, 1, 2, 3, 6, 7, 8, | ||
108 | 9, 10, 11, 12, 13, 14 | ||
109 | }, | ||
110 | .oobfree = { | ||
111 | {.offset = 15, .length = 1}, | ||
112 | } | ||
113 | }; | ||
114 | |||
115 | static struct fsmc_eccplace fsmc_ecc4_sp_place = { | ||
116 | .eccplace = { | ||
117 | {.offset = 0, .length = 4}, | ||
118 | {.offset = 6, .length = 9} | ||
119 | } | ||
120 | }; | ||
121 | |||
122 | /* | ||
123 | * Default partition tables to be used if the partition information not | ||
124 | * provided through platform data | ||
125 | */ | ||
126 | #define PARTITION(n, off, sz) {.name = n, .offset = off, .size = sz} | ||
127 | |||
128 | /* | ||
129 | * Default partition layout for small page(= 512 bytes) devices | ||
130 | * Size for "Root file system" is updated in driver based on actual device size | ||
131 | */ | ||
132 | static struct mtd_partition partition_info_16KB_blk[] = { | ||
133 | PARTITION("X-loader", 0, 4 * 0x4000), | ||
134 | PARTITION("U-Boot", 0x10000, 20 * 0x4000), | ||
135 | PARTITION("Kernel", 0x60000, 256 * 0x4000), | ||
136 | PARTITION("Root File System", 0x460000, 0), | ||
137 | }; | ||
138 | |||
139 | /* | ||
140 | * Default partition layout for large page(> 512 bytes) devices | ||
141 | * Size for "Root file system" is updated in driver based on actual device size | ||
142 | */ | ||
143 | static struct mtd_partition partition_info_128KB_blk[] = { | ||
144 | PARTITION("X-loader", 0, 4 * 0x20000), | ||
145 | PARTITION("U-Boot", 0x80000, 12 * 0x20000), | ||
146 | PARTITION("Kernel", 0x200000, 48 * 0x20000), | ||
147 | PARTITION("Root File System", 0x800000, 0), | ||
148 | }; | ||
149 | |||
150 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
151 | const char *part_probes[] = { "cmdlinepart", NULL }; | ||
152 | #endif | ||
153 | |||
154 | /** | ||
155 | * struct fsmc_nand_data - atructure for FSMC NAND device state | ||
156 | * | ||
157 | * @mtd: MTD info for a NAND flash. | ||
158 | * @nand: Chip related info for a NAND flash. | ||
159 | * @partitions: Partition info for a NAND Flash. | ||
160 | * @nr_partitions: Total number of partition of a NAND flash. | ||
161 | * | ||
162 | * @ecc_place: ECC placing locations in oobfree type format. | ||
163 | * @bank: Bank number for probed device. | ||
164 | * @clk: Clock structure for FSMC. | ||
165 | * | ||
166 | * @data_va: NAND port for Data. | ||
167 | * @cmd_va: NAND port for Command. | ||
168 | * @addr_va: NAND port for Address. | ||
169 | * @regs_va: FSMC regs base address. | ||
170 | */ | ||
171 | struct fsmc_nand_data { | ||
172 | struct mtd_info mtd; | ||
173 | struct nand_chip nand; | ||
174 | struct mtd_partition *partitions; | ||
175 | unsigned int nr_partitions; | ||
176 | |||
177 | struct fsmc_eccplace *ecc_place; | ||
178 | unsigned int bank; | ||
179 | struct clk *clk; | ||
180 | |||
181 | struct resource *resregs; | ||
182 | struct resource *rescmd; | ||
183 | struct resource *resaddr; | ||
184 | struct resource *resdata; | ||
185 | |||
186 | void __iomem *data_va; | ||
187 | void __iomem *cmd_va; | ||
188 | void __iomem *addr_va; | ||
189 | void __iomem *regs_va; | ||
190 | |||
191 | void (*select_chip)(uint32_t bank, uint32_t busw); | ||
192 | }; | ||
193 | |||
194 | /* Assert CS signal based on chipnr */ | ||
195 | static void fsmc_select_chip(struct mtd_info *mtd, int chipnr) | ||
196 | { | ||
197 | struct nand_chip *chip = mtd->priv; | ||
198 | struct fsmc_nand_data *host; | ||
199 | |||
200 | host = container_of(mtd, struct fsmc_nand_data, mtd); | ||
201 | |||
202 | switch (chipnr) { | ||
203 | case -1: | ||
204 | chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE); | ||
205 | break; | ||
206 | case 0: | ||
207 | case 1: | ||
208 | case 2: | ||
209 | case 3: | ||
210 | if (host->select_chip) | ||
211 | host->select_chip(chipnr, | ||
212 | chip->options & NAND_BUSWIDTH_16); | ||
213 | break; | ||
214 | |||
215 | default: | ||
216 | BUG(); | ||
217 | } | ||
218 | } | ||
219 | |||
220 | /* | ||
221 | * fsmc_cmd_ctrl - For facilitaing Hardware access | ||
222 | * This routine allows hardware specific access to control-lines(ALE,CLE) | ||
223 | */ | ||
224 | static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) | ||
225 | { | ||
226 | struct nand_chip *this = mtd->priv; | ||
227 | struct fsmc_nand_data *host = container_of(mtd, | ||
228 | struct fsmc_nand_data, mtd); | ||
229 | struct fsmc_regs *regs = host->regs_va; | ||
230 | unsigned int bank = host->bank; | ||
231 | |||
232 | if (ctrl & NAND_CTRL_CHANGE) { | ||
233 | if (ctrl & NAND_CLE) { | ||
234 | this->IO_ADDR_R = (void __iomem *)host->cmd_va; | ||
235 | this->IO_ADDR_W = (void __iomem *)host->cmd_va; | ||
236 | } else if (ctrl & NAND_ALE) { | ||
237 | this->IO_ADDR_R = (void __iomem *)host->addr_va; | ||
238 | this->IO_ADDR_W = (void __iomem *)host->addr_va; | ||
239 | } else { | ||
240 | this->IO_ADDR_R = (void __iomem *)host->data_va; | ||
241 | this->IO_ADDR_W = (void __iomem *)host->data_va; | ||
242 | } | ||
243 | |||
244 | if (ctrl & NAND_NCE) { | ||
245 | writel(readl(®s->bank_regs[bank].pc) | FSMC_ENABLE, | ||
246 | ®s->bank_regs[bank].pc); | ||
247 | } else { | ||
248 | writel(readl(®s->bank_regs[bank].pc) & ~FSMC_ENABLE, | ||
249 | ®s->bank_regs[bank].pc); | ||
250 | } | ||
251 | } | ||
252 | |||
253 | mb(); | ||
254 | |||
255 | if (cmd != NAND_CMD_NONE) | ||
256 | writeb(cmd, this->IO_ADDR_W); | ||
257 | } | ||
258 | |||
259 | /* | ||
260 | * fsmc_nand_setup - FSMC (Flexible Static Memory Controller) init routine | ||
261 | * | ||
262 | * This routine initializes timing parameters related to NAND memory access in | ||
263 | * FSMC registers | ||
264 | */ | ||
265 | static void __init fsmc_nand_setup(struct fsmc_regs *regs, uint32_t bank, | ||
266 | uint32_t busw) | ||
267 | { | ||
268 | uint32_t value = FSMC_DEVTYPE_NAND | FSMC_ENABLE | FSMC_WAITON; | ||
269 | |||
270 | if (busw) | ||
271 | writel(value | FSMC_DEVWID_16, ®s->bank_regs[bank].pc); | ||
272 | else | ||
273 | writel(value | FSMC_DEVWID_8, ®s->bank_regs[bank].pc); | ||
274 | |||
275 | writel(readl(®s->bank_regs[bank].pc) | FSMC_TCLR_1 | FSMC_TAR_1, | ||
276 | ®s->bank_regs[bank].pc); | ||
277 | writel(FSMC_THIZ_1 | FSMC_THOLD_4 | FSMC_TWAIT_6 | FSMC_TSET_0, | ||
278 | ®s->bank_regs[bank].comm); | ||
279 | writel(FSMC_THIZ_1 | FSMC_THOLD_4 | FSMC_TWAIT_6 | FSMC_TSET_0, | ||
280 | ®s->bank_regs[bank].attrib); | ||
281 | } | ||
282 | |||
283 | /* | ||
284 | * fsmc_enable_hwecc - Enables Hardware ECC through FSMC registers | ||
285 | */ | ||
286 | static void fsmc_enable_hwecc(struct mtd_info *mtd, int mode) | ||
287 | { | ||
288 | struct fsmc_nand_data *host = container_of(mtd, | ||
289 | struct fsmc_nand_data, mtd); | ||
290 | struct fsmc_regs *regs = host->regs_va; | ||
291 | uint32_t bank = host->bank; | ||
292 | |||
293 | writel(readl(®s->bank_regs[bank].pc) & ~FSMC_ECCPLEN_256, | ||
294 | ®s->bank_regs[bank].pc); | ||
295 | writel(readl(®s->bank_regs[bank].pc) & ~FSMC_ECCEN, | ||
296 | ®s->bank_regs[bank].pc); | ||
297 | writel(readl(®s->bank_regs[bank].pc) | FSMC_ECCEN, | ||
298 | ®s->bank_regs[bank].pc); | ||
299 | } | ||
300 | |||
301 | /* | ||
302 | * fsmc_read_hwecc_ecc4 - Hardware ECC calculator for ecc4 option supported by | ||
303 | * FSMC. ECC is 13 bytes for 512 bytes of data (supports error correction upto | ||
304 | * max of 8-bits) | ||
305 | */ | ||
306 | static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data, | ||
307 | uint8_t *ecc) | ||
308 | { | ||
309 | struct fsmc_nand_data *host = container_of(mtd, | ||
310 | struct fsmc_nand_data, mtd); | ||
311 | struct fsmc_regs *regs = host->regs_va; | ||
312 | uint32_t bank = host->bank; | ||
313 | uint32_t ecc_tmp; | ||
314 | unsigned long deadline = jiffies + FSMC_BUSY_WAIT_TIMEOUT; | ||
315 | |||
316 | do { | ||
317 | if (readl(®s->bank_regs[bank].sts) & FSMC_CODE_RDY) | ||
318 | break; | ||
319 | else | ||
320 | cond_resched(); | ||
321 | } while (!time_after_eq(jiffies, deadline)); | ||
322 | |||
323 | ecc_tmp = readl(®s->bank_regs[bank].ecc1); | ||
324 | ecc[0] = (uint8_t) (ecc_tmp >> 0); | ||
325 | ecc[1] = (uint8_t) (ecc_tmp >> 8); | ||
326 | ecc[2] = (uint8_t) (ecc_tmp >> 16); | ||
327 | ecc[3] = (uint8_t) (ecc_tmp >> 24); | ||
328 | |||
329 | ecc_tmp = readl(®s->bank_regs[bank].ecc2); | ||
330 | ecc[4] = (uint8_t) (ecc_tmp >> 0); | ||
331 | ecc[5] = (uint8_t) (ecc_tmp >> 8); | ||
332 | ecc[6] = (uint8_t) (ecc_tmp >> 16); | ||
333 | ecc[7] = (uint8_t) (ecc_tmp >> 24); | ||
334 | |||
335 | ecc_tmp = readl(®s->bank_regs[bank].ecc3); | ||
336 | ecc[8] = (uint8_t) (ecc_tmp >> 0); | ||
337 | ecc[9] = (uint8_t) (ecc_tmp >> 8); | ||
338 | ecc[10] = (uint8_t) (ecc_tmp >> 16); | ||
339 | ecc[11] = (uint8_t) (ecc_tmp >> 24); | ||
340 | |||
341 | ecc_tmp = readl(®s->bank_regs[bank].sts); | ||
342 | ecc[12] = (uint8_t) (ecc_tmp >> 16); | ||
343 | |||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | /* | ||
348 | * fsmc_read_hwecc_ecc1 - Hardware ECC calculator for ecc1 option supported by | ||
349 | * FSMC. ECC is 3 bytes for 512 bytes of data (supports error correction upto | ||
350 | * max of 1-bit) | ||
351 | */ | ||
352 | static int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data, | ||
353 | uint8_t *ecc) | ||
354 | { | ||
355 | struct fsmc_nand_data *host = container_of(mtd, | ||
356 | struct fsmc_nand_data, mtd); | ||
357 | struct fsmc_regs *regs = host->regs_va; | ||
358 | uint32_t bank = host->bank; | ||
359 | uint32_t ecc_tmp; | ||
360 | |||
361 | ecc_tmp = readl(®s->bank_regs[bank].ecc1); | ||
362 | ecc[0] = (uint8_t) (ecc_tmp >> 0); | ||
363 | ecc[1] = (uint8_t) (ecc_tmp >> 8); | ||
364 | ecc[2] = (uint8_t) (ecc_tmp >> 16); | ||
365 | |||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | /* | ||
370 | * fsmc_read_page_hwecc | ||
371 | * @mtd: mtd info structure | ||
372 | * @chip: nand chip info structure | ||
373 | * @buf: buffer to store read data | ||
374 | * @page: page number to read | ||
375 | * | ||
376 | * This routine is needed for fsmc verison 8 as reading from NAND chip has to be | ||
377 | * performed in a strict sequence as follows: | ||
378 | * data(512 byte) -> ecc(13 byte) | ||
379 | * After this read, fsmc hardware generates and reports error data bits(upto a | ||
380 | * max of 8 bits) | ||
381 | */ | ||
382 | static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, | ||
383 | uint8_t *buf, int page) | ||
384 | { | ||
385 | struct fsmc_nand_data *host = container_of(mtd, | ||
386 | struct fsmc_nand_data, mtd); | ||
387 | struct fsmc_eccplace *ecc_place = host->ecc_place; | ||
388 | int i, j, s, stat, eccsize = chip->ecc.size; | ||
389 | int eccbytes = chip->ecc.bytes; | ||
390 | int eccsteps = chip->ecc.steps; | ||
391 | uint8_t *p = buf; | ||
392 | uint8_t *ecc_calc = chip->buffers->ecccalc; | ||
393 | uint8_t *ecc_code = chip->buffers->ecccode; | ||
394 | int off, len, group = 0; | ||
395 | /* | ||
396 | * ecc_oob is intentionally taken as uint16_t. In 16bit devices, we | ||
397 | * end up reading 14 bytes (7 words) from oob. The local array is | ||
398 | * to maintain word alignment | ||
399 | */ | ||
400 | uint16_t ecc_oob[7]; | ||
401 | uint8_t *oob = (uint8_t *)&ecc_oob[0]; | ||
402 | |||
403 | for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) { | ||
404 | |||
405 | chip->cmdfunc(mtd, NAND_CMD_READ0, s * eccsize, page); | ||
406 | chip->ecc.hwctl(mtd, NAND_ECC_READ); | ||
407 | chip->read_buf(mtd, p, eccsize); | ||
408 | |||
409 | for (j = 0; j < eccbytes;) { | ||
410 | off = ecc_place->eccplace[group].offset; | ||
411 | len = ecc_place->eccplace[group].length; | ||
412 | group++; | ||
413 | |||
414 | /* | ||
415 | * length is intentionally kept a higher multiple of 2 | ||
416 | * to read at least 13 bytes even in case of 16 bit NAND | ||
417 | * devices | ||
418 | */ | ||
419 | len = roundup(len, 2); | ||
420 | chip->cmdfunc(mtd, NAND_CMD_READOOB, off, page); | ||
421 | chip->read_buf(mtd, oob + j, len); | ||
422 | j += len; | ||
423 | } | ||
424 | |||
425 | memcpy(&ecc_code[i], oob, 13); | ||
426 | chip->ecc.calculate(mtd, p, &ecc_calc[i]); | ||
427 | |||
428 | stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); | ||
429 | if (stat < 0) | ||
430 | mtd->ecc_stats.failed++; | ||
431 | else | ||
432 | mtd->ecc_stats.corrected += stat; | ||
433 | } | ||
434 | |||
435 | return 0; | ||
436 | } | ||
437 | |||
438 | /* | ||
439 | * fsmc_correct_data | ||
440 | * @mtd: mtd info structure | ||
441 | * @dat: buffer of read data | ||
442 | * @read_ecc: ecc read from device spare area | ||
443 | * @calc_ecc: ecc calculated from read data | ||
444 | * | ||
445 | * calc_ecc is a 104 bit information containing maximum of 8 error | ||
446 | * offset informations of 13 bits each in 512 bytes of read data. | ||
447 | */ | ||
448 | static int fsmc_correct_data(struct mtd_info *mtd, uint8_t *dat, | ||
449 | uint8_t *read_ecc, uint8_t *calc_ecc) | ||
450 | { | ||
451 | struct fsmc_nand_data *host = container_of(mtd, | ||
452 | struct fsmc_nand_data, mtd); | ||
453 | struct fsmc_regs *regs = host->regs_va; | ||
454 | unsigned int bank = host->bank; | ||
455 | uint16_t err_idx[8]; | ||
456 | uint64_t ecc_data[2]; | ||
457 | uint32_t num_err, i; | ||
458 | |||
459 | /* The calculated ecc is actually the correction index in data */ | ||
460 | memcpy(ecc_data, calc_ecc, 13); | ||
461 | |||
462 | /* | ||
463 | * ------------------- calc_ecc[] bit wise -----------|--13 bits--| | ||
464 | * |---idx[7]--|--.....-----|---idx[2]--||---idx[1]--||---idx[0]--| | ||
465 | * | ||
466 | * calc_ecc is a 104 bit information containing maximum of 8 error | ||
467 | * offset informations of 13 bits each. calc_ecc is copied into a | ||
468 | * uint64_t array and error offset indexes are populated in err_idx | ||
469 | * array | ||
470 | */ | ||
471 | for (i = 0; i < 8; i++) { | ||
472 | if (i == 4) { | ||
473 | err_idx[4] = ((ecc_data[1] & 0x1) << 12) | ecc_data[0]; | ||
474 | ecc_data[1] >>= 1; | ||
475 | continue; | ||
476 | } | ||
477 | err_idx[i] = (ecc_data[i/4] & 0x1FFF); | ||
478 | ecc_data[i/4] >>= 13; | ||
479 | } | ||
480 | |||
481 | num_err = (readl(®s->bank_regs[bank].sts) >> 10) & 0xF; | ||
482 | |||
483 | if (num_err == 0xF) | ||
484 | return -EBADMSG; | ||
485 | |||
486 | i = 0; | ||
487 | while (num_err--) { | ||
488 | change_bit(0, (unsigned long *)&err_idx[i]); | ||
489 | change_bit(1, (unsigned long *)&err_idx[i]); | ||
490 | |||
491 | if (err_idx[i] <= 512 * 8) { | ||
492 | change_bit(err_idx[i], (unsigned long *)dat); | ||
493 | i++; | ||
494 | } | ||
495 | } | ||
496 | return i; | ||
497 | } | ||
498 | |||
499 | /* | ||
500 | * fsmc_nand_probe - Probe function | ||
501 | * @pdev: platform device structure | ||
502 | */ | ||
503 | static int __init fsmc_nand_probe(struct platform_device *pdev) | ||
504 | { | ||
505 | struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); | ||
506 | struct fsmc_nand_data *host; | ||
507 | struct mtd_info *mtd; | ||
508 | struct nand_chip *nand; | ||
509 | struct fsmc_regs *regs; | ||
510 | struct resource *res; | ||
511 | int nr_parts, ret = 0; | ||
512 | |||
513 | if (!pdata) { | ||
514 | dev_err(&pdev->dev, "platform data is NULL\n"); | ||
515 | return -EINVAL; | ||
516 | } | ||
517 | |||
518 | /* Allocate memory for the device structure (and zero it) */ | ||
519 | host = kzalloc(sizeof(*host), GFP_KERNEL); | ||
520 | if (!host) { | ||
521 | dev_err(&pdev->dev, "failed to allocate device structure\n"); | ||
522 | return -ENOMEM; | ||
523 | } | ||
524 | |||
525 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_data"); | ||
526 | if (!res) { | ||
527 | ret = -EIO; | ||
528 | goto err_probe1; | ||
529 | } | ||
530 | |||
531 | host->resdata = request_mem_region(res->start, resource_size(res), | ||
532 | pdev->name); | ||
533 | if (!host->resdata) { | ||
534 | ret = -EIO; | ||
535 | goto err_probe1; | ||
536 | } | ||
537 | |||
538 | host->data_va = ioremap(res->start, resource_size(res)); | ||
539 | if (!host->data_va) { | ||
540 | ret = -EIO; | ||
541 | goto err_probe1; | ||
542 | } | ||
543 | |||
544 | host->resaddr = request_mem_region(res->start + PLAT_NAND_ALE, | ||
545 | resource_size(res), pdev->name); | ||
546 | if (!host->resaddr) { | ||
547 | ret = -EIO; | ||
548 | goto err_probe1; | ||
549 | } | ||
550 | |||
551 | host->addr_va = ioremap(res->start + PLAT_NAND_ALE, resource_size(res)); | ||
552 | if (!host->addr_va) { | ||
553 | ret = -EIO; | ||
554 | goto err_probe1; | ||
555 | } | ||
556 | |||
557 | host->rescmd = request_mem_region(res->start + PLAT_NAND_CLE, | ||
558 | resource_size(res), pdev->name); | ||
559 | if (!host->rescmd) { | ||
560 | ret = -EIO; | ||
561 | goto err_probe1; | ||
562 | } | ||
563 | |||
564 | host->cmd_va = ioremap(res->start + PLAT_NAND_CLE, resource_size(res)); | ||
565 | if (!host->cmd_va) { | ||
566 | ret = -EIO; | ||
567 | goto err_probe1; | ||
568 | } | ||
569 | |||
570 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fsmc_regs"); | ||
571 | if (!res) { | ||
572 | ret = -EIO; | ||
573 | goto err_probe1; | ||
574 | } | ||
575 | |||
576 | host->resregs = request_mem_region(res->start, resource_size(res), | ||
577 | pdev->name); | ||
578 | if (!host->resregs) { | ||
579 | ret = -EIO; | ||
580 | goto err_probe1; | ||
581 | } | ||
582 | |||
583 | host->regs_va = ioremap(res->start, resource_size(res)); | ||
584 | if (!host->regs_va) { | ||
585 | ret = -EIO; | ||
586 | goto err_probe1; | ||
587 | } | ||
588 | |||
589 | host->clk = clk_get(&pdev->dev, NULL); | ||
590 | if (IS_ERR(host->clk)) { | ||
591 | dev_err(&pdev->dev, "failed to fetch block clock\n"); | ||
592 | ret = PTR_ERR(host->clk); | ||
593 | host->clk = NULL; | ||
594 | goto err_probe1; | ||
595 | } | ||
596 | |||
597 | ret = clk_enable(host->clk); | ||
598 | if (ret) | ||
599 | goto err_probe1; | ||
600 | |||
601 | host->bank = pdata->bank; | ||
602 | host->select_chip = pdata->select_bank; | ||
603 | regs = host->regs_va; | ||
604 | |||
605 | /* Link all private pointers */ | ||
606 | mtd = &host->mtd; | ||
607 | nand = &host->nand; | ||
608 | mtd->priv = nand; | ||
609 | nand->priv = host; | ||
610 | |||
611 | host->mtd.owner = THIS_MODULE; | ||
612 | nand->IO_ADDR_R = host->data_va; | ||
613 | nand->IO_ADDR_W = host->data_va; | ||
614 | nand->cmd_ctrl = fsmc_cmd_ctrl; | ||
615 | nand->chip_delay = 30; | ||
616 | |||
617 | nand->ecc.mode = NAND_ECC_HW; | ||
618 | nand->ecc.hwctl = fsmc_enable_hwecc; | ||
619 | nand->ecc.size = 512; | ||
620 | nand->options = pdata->options; | ||
621 | nand->select_chip = fsmc_select_chip; | ||
622 | |||
623 | if (pdata->width == FSMC_NAND_BW16) | ||
624 | nand->options |= NAND_BUSWIDTH_16; | ||
625 | |||
626 | fsmc_nand_setup(regs, host->bank, nand->options & NAND_BUSWIDTH_16); | ||
627 | |||
628 | if (get_fsmc_version(host->regs_va) == FSMC_VER8) { | ||
629 | nand->ecc.read_page = fsmc_read_page_hwecc; | ||
630 | nand->ecc.calculate = fsmc_read_hwecc_ecc4; | ||
631 | nand->ecc.correct = fsmc_correct_data; | ||
632 | nand->ecc.bytes = 13; | ||
633 | } else { | ||
634 | nand->ecc.calculate = fsmc_read_hwecc_ecc1; | ||
635 | nand->ecc.correct = nand_correct_data; | ||
636 | nand->ecc.bytes = 3; | ||
637 | } | ||
638 | |||
639 | /* | ||
640 | * Scan to find existance of the device | ||
641 | */ | ||
642 | if (nand_scan_ident(&host->mtd, 1, NULL)) { | ||
643 | ret = -ENXIO; | ||
644 | dev_err(&pdev->dev, "No NAND Device found!\n"); | ||
645 | goto err_probe; | ||
646 | } | ||
647 | |||
648 | if (get_fsmc_version(host->regs_va) == FSMC_VER8) { | ||
649 | if (host->mtd.writesize == 512) { | ||
650 | nand->ecc.layout = &fsmc_ecc4_sp_layout; | ||
651 | host->ecc_place = &fsmc_ecc4_sp_place; | ||
652 | } else { | ||
653 | nand->ecc.layout = &fsmc_ecc4_lp_layout; | ||
654 | host->ecc_place = &fsmc_ecc4_lp_place; | ||
655 | } | ||
656 | } else { | ||
657 | nand->ecc.layout = &fsmc_ecc1_layout; | ||
658 | } | ||
659 | |||
660 | /* Second stage of scan to fill MTD data-structures */ | ||
661 | if (nand_scan_tail(&host->mtd)) { | ||
662 | ret = -ENXIO; | ||
663 | goto err_probe; | ||
664 | } | ||
665 | |||
666 | /* | ||
667 | * The partition information can is accessed by (in the same precedence) | ||
668 | * | ||
669 | * command line through Bootloader, | ||
670 | * platform data, | ||
671 | * default partition information present in driver. | ||
672 | */ | ||
673 | #ifdef CONFIG_MTD_PARTITIONS | ||
674 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
675 | /* | ||
676 | * Check if partition info passed via command line | ||
677 | */ | ||
678 | host->mtd.name = "nand"; | ||
679 | nr_parts = parse_mtd_partitions(&host->mtd, part_probes, | ||
680 | &host->partitions, 0); | ||
681 | if (nr_parts > 0) { | ||
682 | host->nr_partitions = nr_parts; | ||
683 | } else { | ||
684 | #endif | ||
685 | /* | ||
686 | * Check if partition info passed via command line | ||
687 | */ | ||
688 | if (pdata->partitions) { | ||
689 | host->partitions = pdata->partitions; | ||
690 | host->nr_partitions = pdata->nr_partitions; | ||
691 | } else { | ||
692 | struct mtd_partition *partition; | ||
693 | int i; | ||
694 | |||
695 | /* Select the default partitions info */ | ||
696 | switch (host->mtd.size) { | ||
697 | case 0x01000000: | ||
698 | case 0x02000000: | ||
699 | case 0x04000000: | ||
700 | host->partitions = partition_info_16KB_blk; | ||
701 | host->nr_partitions = | ||
702 | sizeof(partition_info_16KB_blk) / | ||
703 | sizeof(struct mtd_partition); | ||
704 | break; | ||
705 | case 0x08000000: | ||
706 | case 0x10000000: | ||
707 | case 0x20000000: | ||
708 | case 0x40000000: | ||
709 | host->partitions = partition_info_128KB_blk; | ||
710 | host->nr_partitions = | ||
711 | sizeof(partition_info_128KB_blk) / | ||
712 | sizeof(struct mtd_partition); | ||
713 | break; | ||
714 | default: | ||
715 | ret = -ENXIO; | ||
716 | pr_err("Unsupported NAND size\n"); | ||
717 | goto err_probe; | ||
718 | } | ||
719 | |||
720 | partition = host->partitions; | ||
721 | for (i = 0; i < host->nr_partitions; i++, partition++) { | ||
722 | if (partition->size == 0) { | ||
723 | partition->size = host->mtd.size - | ||
724 | partition->offset; | ||
725 | break; | ||
726 | } | ||
727 | } | ||
728 | } | ||
729 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
730 | } | ||
731 | #endif | ||
732 | |||
733 | if (host->partitions) { | ||
734 | ret = add_mtd_partitions(&host->mtd, host->partitions, | ||
735 | host->nr_partitions); | ||
736 | if (ret) | ||
737 | goto err_probe; | ||
738 | } | ||
739 | #else | ||
740 | dev_info(&pdev->dev, "Registering %s as whole device\n", mtd->name); | ||
741 | if (!add_mtd_device(mtd)) { | ||
742 | ret = -ENXIO; | ||
743 | goto err_probe; | ||
744 | } | ||
745 | #endif | ||
746 | |||
747 | platform_set_drvdata(pdev, host); | ||
748 | dev_info(&pdev->dev, "FSMC NAND driver registration successful\n"); | ||
749 | return 0; | ||
750 | |||
751 | err_probe: | ||
752 | clk_disable(host->clk); | ||
753 | err_probe1: | ||
754 | if (host->clk) | ||
755 | clk_put(host->clk); | ||
756 | if (host->regs_va) | ||
757 | iounmap(host->regs_va); | ||
758 | if (host->resregs) | ||
759 | release_mem_region(host->resregs->start, | ||
760 | resource_size(host->resregs)); | ||
761 | if (host->cmd_va) | ||
762 | iounmap(host->cmd_va); | ||
763 | if (host->rescmd) | ||
764 | release_mem_region(host->rescmd->start, | ||
765 | resource_size(host->rescmd)); | ||
766 | if (host->addr_va) | ||
767 | iounmap(host->addr_va); | ||
768 | if (host->resaddr) | ||
769 | release_mem_region(host->resaddr->start, | ||
770 | resource_size(host->resaddr)); | ||
771 | if (host->data_va) | ||
772 | iounmap(host->data_va); | ||
773 | if (host->resdata) | ||
774 | release_mem_region(host->resdata->start, | ||
775 | resource_size(host->resdata)); | ||
776 | |||
777 | kfree(host); | ||
778 | return ret; | ||
779 | } | ||
780 | |||
781 | /* | ||
782 | * Clean up routine | ||
783 | */ | ||
784 | static int fsmc_nand_remove(struct platform_device *pdev) | ||
785 | { | ||
786 | struct fsmc_nand_data *host = platform_get_drvdata(pdev); | ||
787 | |||
788 | platform_set_drvdata(pdev, NULL); | ||
789 | |||
790 | if (host) { | ||
791 | #ifdef CONFIG_MTD_PARTITIONS | ||
792 | del_mtd_partitions(&host->mtd); | ||
793 | #else | ||
794 | del_mtd_device(&host->mtd); | ||
795 | #endif | ||
796 | clk_disable(host->clk); | ||
797 | clk_put(host->clk); | ||
798 | |||
799 | iounmap(host->regs_va); | ||
800 | release_mem_region(host->resregs->start, | ||
801 | resource_size(host->resregs)); | ||
802 | iounmap(host->cmd_va); | ||
803 | release_mem_region(host->rescmd->start, | ||
804 | resource_size(host->rescmd)); | ||
805 | iounmap(host->addr_va); | ||
806 | release_mem_region(host->resaddr->start, | ||
807 | resource_size(host->resaddr)); | ||
808 | iounmap(host->data_va); | ||
809 | release_mem_region(host->resdata->start, | ||
810 | resource_size(host->resdata)); | ||
811 | |||
812 | kfree(host); | ||
813 | } | ||
814 | return 0; | ||
815 | } | ||
816 | |||
817 | #ifdef CONFIG_PM | ||
818 | static int fsmc_nand_suspend(struct device *dev) | ||
819 | { | ||
820 | struct fsmc_nand_data *host = dev_get_drvdata(dev); | ||
821 | if (host) | ||
822 | clk_disable(host->clk); | ||
823 | return 0; | ||
824 | } | ||
825 | |||
826 | static int fsmc_nand_resume(struct device *dev) | ||
827 | { | ||
828 | struct fsmc_nand_data *host = dev_get_drvdata(dev); | ||
829 | if (host) | ||
830 | clk_enable(host->clk); | ||
831 | return 0; | ||
832 | } | ||
833 | |||
834 | static const struct dev_pm_ops fsmc_nand_pm_ops = { | ||
835 | .suspend = fsmc_nand_suspend, | ||
836 | .resume = fsmc_nand_resume, | ||
837 | }; | ||
838 | #endif | ||
839 | |||
840 | static struct platform_driver fsmc_nand_driver = { | ||
841 | .remove = fsmc_nand_remove, | ||
842 | .driver = { | ||
843 | .owner = THIS_MODULE, | ||
844 | .name = "fsmc-nand", | ||
845 | #ifdef CONFIG_PM | ||
846 | .pm = &fsmc_nand_pm_ops, | ||
847 | #endif | ||
848 | }, | ||
849 | }; | ||
850 | |||
851 | static int __init fsmc_nand_init(void) | ||
852 | { | ||
853 | return platform_driver_probe(&fsmc_nand_driver, | ||
854 | fsmc_nand_probe); | ||
855 | } | ||
856 | module_init(fsmc_nand_init); | ||
857 | |||
858 | static void __exit fsmc_nand_exit(void) | ||
859 | { | ||
860 | platform_driver_unregister(&fsmc_nand_driver); | ||
861 | } | ||
862 | module_exit(fsmc_nand_exit); | ||
863 | |||
864 | MODULE_LICENSE("GPL"); | ||
865 | MODULE_AUTHOR("Vipin Kumar <vipin.kumar@st.com>, Ashish Priyadarshi"); | ||
866 | MODULE_DESCRIPTION("NAND driver for SPEAr Platforms"); | ||
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index df0c1da4ff49..469e649c911c 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c | |||
@@ -568,6 +568,7 @@ static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd) | |||
568 | uint rcw_width; | 568 | uint rcw_width; |
569 | uint rcwh; | 569 | uint rcwh; |
570 | uint romloc, ps; | 570 | uint romloc, ps; |
571 | int ret = 0; | ||
571 | 572 | ||
572 | rmnode = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-reset"); | 573 | rmnode = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-reset"); |
573 | if (!rmnode) { | 574 | if (!rmnode) { |
@@ -579,7 +580,8 @@ static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd) | |||
579 | rm = of_iomap(rmnode, 0); | 580 | rm = of_iomap(rmnode, 0); |
580 | if (!rm) { | 581 | if (!rm) { |
581 | dev_err(prv->dev, "Error mapping reset module node!\n"); | 582 | dev_err(prv->dev, "Error mapping reset module node!\n"); |
582 | return -EBUSY; | 583 | ret = -EBUSY; |
584 | goto out; | ||
583 | } | 585 | } |
584 | 586 | ||
585 | rcwh = in_be32(&rm->rcwhr); | 587 | rcwh = in_be32(&rm->rcwhr); |
@@ -628,8 +630,9 @@ static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd) | |||
628 | rcw_width * 8, rcw_pagesize, | 630 | rcw_width * 8, rcw_pagesize, |
629 | rcw_sparesize); | 631 | rcw_sparesize); |
630 | iounmap(rm); | 632 | iounmap(rm); |
633 | out: | ||
631 | of_node_put(rmnode); | 634 | of_node_put(rmnode); |
632 | return 0; | 635 | return ret; |
633 | } | 636 | } |
634 | 637 | ||
635 | /* Free driver resources */ | 638 | /* Free driver resources */ |
@@ -660,7 +663,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op, | |||
660 | #endif | 663 | #endif |
661 | struct nand_chip *chip; | 664 | struct nand_chip *chip; |
662 | unsigned long regs_paddr, regs_size; | 665 | unsigned long regs_paddr, regs_size; |
663 | const uint *chips_no; | 666 | const __be32 *chips_no; |
664 | int resettime = 0; | 667 | int resettime = 0; |
665 | int retval = 0; | 668 | int retval = 0; |
666 | int rev, len; | 669 | int rev, len; |
@@ -803,7 +806,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op, | |||
803 | } | 806 | } |
804 | 807 | ||
805 | /* Detect NAND chips */ | 808 | /* Detect NAND chips */ |
806 | if (nand_scan(mtd, *chips_no)) { | 809 | if (nand_scan(mtd, be32_to_cpup(chips_no))) { |
807 | dev_err(dev, "NAND Flash not found !\n"); | 810 | dev_err(dev, "NAND Flash not found !\n"); |
808 | devm_free_irq(dev, prv->irq, mtd); | 811 | devm_free_irq(dev, prv->irq, mtd); |
809 | retval = -ENXIO; | 812 | retval = -ENXIO; |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index d551ddd9537a..1f75a1b1f7c3 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -45,7 +45,7 @@ | |||
45 | #include <linux/interrupt.h> | 45 | #include <linux/interrupt.h> |
46 | #include <linux/bitops.h> | 46 | #include <linux/bitops.h> |
47 | #include <linux/leds.h> | 47 | #include <linux/leds.h> |
48 | #include <asm/io.h> | 48 | #include <linux/io.h> |
49 | 49 | ||
50 | #ifdef CONFIG_MTD_PARTITIONS | 50 | #ifdef CONFIG_MTD_PARTITIONS |
51 | #include <linux/mtd/partitions.h> | 51 | #include <linux/mtd/partitions.h> |
@@ -59,7 +59,7 @@ static struct nand_ecclayout nand_oob_8 = { | |||
59 | {.offset = 3, | 59 | {.offset = 3, |
60 | .length = 2}, | 60 | .length = 2}, |
61 | {.offset = 6, | 61 | {.offset = 6, |
62 | .length = 2}} | 62 | .length = 2} } |
63 | }; | 63 | }; |
64 | 64 | ||
65 | static struct nand_ecclayout nand_oob_16 = { | 65 | static struct nand_ecclayout nand_oob_16 = { |
@@ -67,7 +67,7 @@ static struct nand_ecclayout nand_oob_16 = { | |||
67 | .eccpos = {0, 1, 2, 3, 6, 7}, | 67 | .eccpos = {0, 1, 2, 3, 6, 7}, |
68 | .oobfree = { | 68 | .oobfree = { |
69 | {.offset = 8, | 69 | {.offset = 8, |
70 | . length = 8}} | 70 | . length = 8} } |
71 | }; | 71 | }; |
72 | 72 | ||
73 | static struct nand_ecclayout nand_oob_64 = { | 73 | static struct nand_ecclayout nand_oob_64 = { |
@@ -78,7 +78,7 @@ static struct nand_ecclayout nand_oob_64 = { | |||
78 | 56, 57, 58, 59, 60, 61, 62, 63}, | 78 | 56, 57, 58, 59, 60, 61, 62, 63}, |
79 | .oobfree = { | 79 | .oobfree = { |
80 | {.offset = 2, | 80 | {.offset = 2, |
81 | .length = 38}} | 81 | .length = 38} } |
82 | }; | 82 | }; |
83 | 83 | ||
84 | static struct nand_ecclayout nand_oob_128 = { | 84 | static struct nand_ecclayout nand_oob_128 = { |
@@ -92,7 +92,7 @@ static struct nand_ecclayout nand_oob_128 = { | |||
92 | 120, 121, 122, 123, 124, 125, 126, 127}, | 92 | 120, 121, 122, 123, 124, 125, 126, 127}, |
93 | .oobfree = { | 93 | .oobfree = { |
94 | {.offset = 2, | 94 | {.offset = 2, |
95 | .length = 78}} | 95 | .length = 78} } |
96 | }; | 96 | }; |
97 | 97 | ||
98 | static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, | 98 | static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, |
@@ -612,7 +612,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, | |||
612 | NAND_CTRL_CLE | NAND_CTRL_CHANGE); | 612 | NAND_CTRL_CLE | NAND_CTRL_CHANGE); |
613 | chip->cmd_ctrl(mtd, | 613 | chip->cmd_ctrl(mtd, |
614 | NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); | 614 | NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); |
615 | while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ; | 615 | while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) |
616 | ; | ||
616 | return; | 617 | return; |
617 | 618 | ||
618 | /* This applies to read commands */ | 619 | /* This applies to read commands */ |
@@ -718,7 +719,8 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, | |||
718 | NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); | 719 | NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); |
719 | chip->cmd_ctrl(mtd, NAND_CMD_NONE, | 720 | chip->cmd_ctrl(mtd, NAND_CMD_NONE, |
720 | NAND_NCE | NAND_CTRL_CHANGE); | 721 | NAND_NCE | NAND_CTRL_CHANGE); |
721 | while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ; | 722 | while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) |
723 | ; | ||
722 | return; | 724 | return; |
723 | 725 | ||
724 | case NAND_CMD_RNDOUT: | 726 | case NAND_CMD_RNDOUT: |
@@ -784,7 +786,7 @@ nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state) | |||
784 | spinlock_t *lock = &chip->controller->lock; | 786 | spinlock_t *lock = &chip->controller->lock; |
785 | wait_queue_head_t *wq = &chip->controller->wq; | 787 | wait_queue_head_t *wq = &chip->controller->wq; |
786 | DECLARE_WAITQUEUE(wait, current); | 788 | DECLARE_WAITQUEUE(wait, current); |
787 | retry: | 789 | retry: |
788 | spin_lock(lock); | 790 | spin_lock(lock); |
789 | 791 | ||
790 | /* Hardware controller shared among independent devices */ | 792 | /* Hardware controller shared among independent devices */ |
@@ -834,7 +836,7 @@ static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip, | |||
834 | break; | 836 | break; |
835 | } | 837 | } |
836 | mdelay(1); | 838 | mdelay(1); |
837 | } | 839 | } |
838 | } | 840 | } |
839 | 841 | ||
840 | /** | 842 | /** |
@@ -980,6 +982,7 @@ out: | |||
980 | 982 | ||
981 | return ret; | 983 | return ret; |
982 | } | 984 | } |
985 | EXPORT_SYMBOL(nand_unlock); | ||
983 | 986 | ||
984 | /** | 987 | /** |
985 | * nand_lock - [REPLACEABLE] locks all blocks present in the device | 988 | * nand_lock - [REPLACEABLE] locks all blocks present in the device |
@@ -1049,6 +1052,7 @@ out: | |||
1049 | 1052 | ||
1050 | return ret; | 1053 | return ret; |
1051 | } | 1054 | } |
1055 | EXPORT_SYMBOL(nand_lock); | ||
1052 | 1056 | ||
1053 | /** | 1057 | /** |
1054 | * nand_read_page_raw - [Intern] read raw page data without ecc | 1058 | * nand_read_page_raw - [Intern] read raw page data without ecc |
@@ -1076,8 +1080,9 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | |||
1076 | * | 1080 | * |
1077 | * We need a special oob layout and handling even when OOB isn't used. | 1081 | * We need a special oob layout and handling even when OOB isn't used. |
1078 | */ | 1082 | */ |
1079 | static int nand_read_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | 1083 | static int nand_read_page_raw_syndrome(struct mtd_info *mtd, |
1080 | uint8_t *buf, int page) | 1084 | struct nand_chip *chip, |
1085 | uint8_t *buf, int page) | ||
1081 | { | 1086 | { |
1082 | int eccsize = chip->ecc.size; | 1087 | int eccsize = chip->ecc.size; |
1083 | int eccbytes = chip->ecc.bytes; | 1088 | int eccbytes = chip->ecc.bytes; |
@@ -1158,7 +1163,8 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | |||
1158 | * @readlen: data length | 1163 | * @readlen: data length |
1159 | * @bufpoi: buffer to store read data | 1164 | * @bufpoi: buffer to store read data |
1160 | */ | 1165 | */ |
1161 | static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi) | 1166 | static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, |
1167 | uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi) | ||
1162 | { | 1168 | { |
1163 | int start_step, end_step, num_steps; | 1169 | int start_step, end_step, num_steps; |
1164 | uint32_t *eccpos = chip->ecc.layout->eccpos; | 1170 | uint32_t *eccpos = chip->ecc.layout->eccpos; |
@@ -1166,6 +1172,7 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint3 | |||
1166 | int data_col_addr, i, gaps = 0; | 1172 | int data_col_addr, i, gaps = 0; |
1167 | int datafrag_len, eccfrag_len, aligned_len, aligned_pos; | 1173 | int datafrag_len, eccfrag_len, aligned_len, aligned_pos; |
1168 | int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; | 1174 | int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; |
1175 | int index = 0; | ||
1169 | 1176 | ||
1170 | /* Column address wihin the page aligned to ECC size (256bytes). */ | 1177 | /* Column address wihin the page aligned to ECC size (256bytes). */ |
1171 | start_step = data_offs / chip->ecc.size; | 1178 | start_step = data_offs / chip->ecc.size; |
@@ -1204,26 +1211,30 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint3 | |||
1204 | } else { | 1211 | } else { |
1205 | /* send the command to read the particular ecc bytes */ | 1212 | /* send the command to read the particular ecc bytes */ |
1206 | /* take care about buswidth alignment in read_buf */ | 1213 | /* take care about buswidth alignment in read_buf */ |
1207 | aligned_pos = eccpos[start_step * chip->ecc.bytes] & ~(busw - 1); | 1214 | index = start_step * chip->ecc.bytes; |
1215 | |||
1216 | aligned_pos = eccpos[index] & ~(busw - 1); | ||
1208 | aligned_len = eccfrag_len; | 1217 | aligned_len = eccfrag_len; |
1209 | if (eccpos[start_step * chip->ecc.bytes] & (busw - 1)) | 1218 | if (eccpos[index] & (busw - 1)) |
1210 | aligned_len++; | 1219 | aligned_len++; |
1211 | if (eccpos[(start_step + num_steps) * chip->ecc.bytes] & (busw - 1)) | 1220 | if (eccpos[index + (num_steps * chip->ecc.bytes)] & (busw - 1)) |
1212 | aligned_len++; | 1221 | aligned_len++; |
1213 | 1222 | ||
1214 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize + aligned_pos, -1); | 1223 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, |
1224 | mtd->writesize + aligned_pos, -1); | ||
1215 | chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len); | 1225 | chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len); |
1216 | } | 1226 | } |
1217 | 1227 | ||
1218 | for (i = 0; i < eccfrag_len; i++) | 1228 | for (i = 0; i < eccfrag_len; i++) |
1219 | chip->buffers->ecccode[i] = chip->oob_poi[eccpos[i + start_step * chip->ecc.bytes]]; | 1229 | chip->buffers->ecccode[i] = chip->oob_poi[eccpos[i + index]]; |
1220 | 1230 | ||
1221 | p = bufpoi + data_col_addr; | 1231 | p = bufpoi + data_col_addr; |
1222 | for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) { | 1232 | for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) { |
1223 | int stat; | 1233 | int stat; |
1224 | 1234 | ||
1225 | stat = chip->ecc.correct(mtd, p, &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]); | 1235 | stat = chip->ecc.correct(mtd, p, |
1226 | if (stat == -1) | 1236 | &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]); |
1237 | if (stat < 0) | ||
1227 | mtd->ecc_stats.failed++; | 1238 | mtd->ecc_stats.failed++; |
1228 | else | 1239 | else |
1229 | mtd->ecc_stats.corrected += stat; | 1240 | mtd->ecc_stats.corrected += stat; |
@@ -1390,7 +1401,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | |||
1390 | static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, | 1401 | static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, |
1391 | struct mtd_oob_ops *ops, size_t len) | 1402 | struct mtd_oob_ops *ops, size_t len) |
1392 | { | 1403 | { |
1393 | switch(ops->mode) { | 1404 | switch (ops->mode) { |
1394 | 1405 | ||
1395 | case MTD_OOB_PLACE: | 1406 | case MTD_OOB_PLACE: |
1396 | case MTD_OOB_RAW: | 1407 | case MTD_OOB_RAW: |
@@ -1402,7 +1413,7 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, | |||
1402 | uint32_t boffs = 0, roffs = ops->ooboffs; | 1413 | uint32_t boffs = 0, roffs = ops->ooboffs; |
1403 | size_t bytes = 0; | 1414 | size_t bytes = 0; |
1404 | 1415 | ||
1405 | for(; free->length && len; free++, len -= bytes) { | 1416 | for (; free->length && len; free++, len -= bytes) { |
1406 | /* Read request not from offset 0 ? */ | 1417 | /* Read request not from offset 0 ? */ |
1407 | if (unlikely(roffs)) { | 1418 | if (unlikely(roffs)) { |
1408 | if (roffs >= free->length) { | 1419 | if (roffs >= free->length) { |
@@ -1466,7 +1477,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1466 | buf = ops->datbuf; | 1477 | buf = ops->datbuf; |
1467 | oob = ops->oobbuf; | 1478 | oob = ops->oobbuf; |
1468 | 1479 | ||
1469 | while(1) { | 1480 | while (1) { |
1470 | bytes = min(mtd->writesize - col, readlen); | 1481 | bytes = min(mtd->writesize - col, readlen); |
1471 | aligned = (bytes == mtd->writesize); | 1482 | aligned = (bytes == mtd->writesize); |
1472 | 1483 | ||
@@ -1484,7 +1495,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1484 | ret = chip->ecc.read_page_raw(mtd, chip, | 1495 | ret = chip->ecc.read_page_raw(mtd, chip, |
1485 | bufpoi, page); | 1496 | bufpoi, page); |
1486 | else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob) | 1497 | else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob) |
1487 | ret = chip->ecc.read_subpage(mtd, chip, col, bytes, bufpoi); | 1498 | ret = chip->ecc.read_subpage(mtd, chip, |
1499 | col, bytes, bufpoi); | ||
1488 | else | 1500 | else |
1489 | ret = chip->ecc.read_page(mtd, chip, bufpoi, | 1501 | ret = chip->ecc.read_page(mtd, chip, bufpoi, |
1490 | page); | 1502 | page); |
@@ -1493,7 +1505,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1493 | 1505 | ||
1494 | /* Transfer not aligned data */ | 1506 | /* Transfer not aligned data */ |
1495 | if (!aligned) { | 1507 | if (!aligned) { |
1496 | if (!NAND_SUBPAGE_READ(chip) && !oob) | 1508 | if (!NAND_SUBPAGE_READ(chip) && !oob && |
1509 | !(mtd->ecc_stats.failed - stats.failed)) | ||
1497 | chip->pagebuf = realpage; | 1510 | chip->pagebuf = realpage; |
1498 | memcpy(buf, chip->buffers->databuf + col, bytes); | 1511 | memcpy(buf, chip->buffers->databuf + col, bytes); |
1499 | } | 1512 | } |
@@ -1791,7 +1804,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, | |||
1791 | realpage = (int)(from >> chip->page_shift); | 1804 | realpage = (int)(from >> chip->page_shift); |
1792 | page = realpage & chip->pagemask; | 1805 | page = realpage & chip->pagemask; |
1793 | 1806 | ||
1794 | while(1) { | 1807 | while (1) { |
1795 | sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); | 1808 | sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); |
1796 | 1809 | ||
1797 | len = min(len, readlen); | 1810 | len = min(len, readlen); |
@@ -1861,7 +1874,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, | |||
1861 | 1874 | ||
1862 | nand_get_device(chip, mtd, FL_READING); | 1875 | nand_get_device(chip, mtd, FL_READING); |
1863 | 1876 | ||
1864 | switch(ops->mode) { | 1877 | switch (ops->mode) { |
1865 | case MTD_OOB_PLACE: | 1878 | case MTD_OOB_PLACE: |
1866 | case MTD_OOB_AUTO: | 1879 | case MTD_OOB_AUTO: |
1867 | case MTD_OOB_RAW: | 1880 | case MTD_OOB_RAW: |
@@ -1876,7 +1889,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from, | |||
1876 | else | 1889 | else |
1877 | ret = nand_do_read_ops(mtd, from, ops); | 1890 | ret = nand_do_read_ops(mtd, from, ops); |
1878 | 1891 | ||
1879 | out: | 1892 | out: |
1880 | nand_release_device(mtd); | 1893 | nand_release_device(mtd); |
1881 | return ret; | 1894 | return ret; |
1882 | } | 1895 | } |
@@ -1905,8 +1918,9 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, | |||
1905 | * | 1918 | * |
1906 | * We need a special oob layout and handling even when ECC isn't checked. | 1919 | * We need a special oob layout and handling even when ECC isn't checked. |
1907 | */ | 1920 | */ |
1908 | static void nand_write_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip, | 1921 | static void nand_write_page_raw_syndrome(struct mtd_info *mtd, |
1909 | const uint8_t *buf) | 1922 | struct nand_chip *chip, |
1923 | const uint8_t *buf) | ||
1910 | { | 1924 | { |
1911 | int eccsize = chip->ecc.size; | 1925 | int eccsize = chip->ecc.size; |
1912 | int eccbytes = chip->ecc.bytes; | 1926 | int eccbytes = chip->ecc.bytes; |
@@ -2099,7 +2113,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, | |||
2099 | static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len, | 2113 | static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len, |
2100 | struct mtd_oob_ops *ops) | 2114 | struct mtd_oob_ops *ops) |
2101 | { | 2115 | { |
2102 | switch(ops->mode) { | 2116 | switch (ops->mode) { |
2103 | 2117 | ||
2104 | case MTD_OOB_PLACE: | 2118 | case MTD_OOB_PLACE: |
2105 | case MTD_OOB_RAW: | 2119 | case MTD_OOB_RAW: |
@@ -2111,7 +2125,7 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len, | |||
2111 | uint32_t boffs = 0, woffs = ops->ooboffs; | 2125 | uint32_t boffs = 0, woffs = ops->ooboffs; |
2112 | size_t bytes = 0; | 2126 | size_t bytes = 0; |
2113 | 2127 | ||
2114 | for(; free->length && len; free++, len -= bytes) { | 2128 | for (; free->length && len; free++, len -= bytes) { |
2115 | /* Write request not from offset 0 ? */ | 2129 | /* Write request not from offset 0 ? */ |
2116 | if (unlikely(woffs)) { | 2130 | if (unlikely(woffs)) { |
2117 | if (woffs >= free->length) { | 2131 | if (woffs >= free->length) { |
@@ -2137,7 +2151,7 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len, | |||
2137 | return NULL; | 2151 | return NULL; |
2138 | } | 2152 | } |
2139 | 2153 | ||
2140 | #define NOTALIGNED(x) (x & (chip->subpagesize - 1)) != 0 | 2154 | #define NOTALIGNED(x) ((x & (chip->subpagesize - 1)) != 0) |
2141 | 2155 | ||
2142 | /** | 2156 | /** |
2143 | * nand_do_write_ops - [Internal] NAND write with ECC | 2157 | * nand_do_write_ops - [Internal] NAND write with ECC |
@@ -2200,10 +2214,10 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, | |||
2200 | memset(chip->oob_poi, 0xff, mtd->oobsize); | 2214 | memset(chip->oob_poi, 0xff, mtd->oobsize); |
2201 | 2215 | ||
2202 | /* Don't allow multipage oob writes with offset */ | 2216 | /* Don't allow multipage oob writes with offset */ |
2203 | if (ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen)) | 2217 | if (oob && ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen)) |
2204 | return -EINVAL; | 2218 | return -EINVAL; |
2205 | 2219 | ||
2206 | while(1) { | 2220 | while (1) { |
2207 | int bytes = mtd->writesize; | 2221 | int bytes = mtd->writesize; |
2208 | int cached = writelen > bytes && page != blockmask; | 2222 | int cached = writelen > bytes && page != blockmask; |
2209 | uint8_t *wbuf = buf; | 2223 | uint8_t *wbuf = buf; |
@@ -2431,7 +2445,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, | |||
2431 | 2445 | ||
2432 | nand_get_device(chip, mtd, FL_WRITING); | 2446 | nand_get_device(chip, mtd, FL_WRITING); |
2433 | 2447 | ||
2434 | switch(ops->mode) { | 2448 | switch (ops->mode) { |
2435 | case MTD_OOB_PLACE: | 2449 | case MTD_OOB_PLACE: |
2436 | case MTD_OOB_AUTO: | 2450 | case MTD_OOB_AUTO: |
2437 | case MTD_OOB_RAW: | 2451 | case MTD_OOB_RAW: |
@@ -2446,7 +2460,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, | |||
2446 | else | 2460 | else |
2447 | ret = nand_do_write_ops(mtd, to, ops); | 2461 | ret = nand_do_write_ops(mtd, to, ops); |
2448 | 2462 | ||
2449 | out: | 2463 | out: |
2450 | nand_release_device(mtd); | 2464 | nand_release_device(mtd); |
2451 | return ret; | 2465 | return ret; |
2452 | } | 2466 | } |
@@ -2511,7 +2525,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, | |||
2511 | { | 2525 | { |
2512 | int page, status, pages_per_block, ret, chipnr; | 2526 | int page, status, pages_per_block, ret, chipnr; |
2513 | struct nand_chip *chip = mtd->priv; | 2527 | struct nand_chip *chip = mtd->priv; |
2514 | loff_t rewrite_bbt[NAND_MAX_CHIPS]={0}; | 2528 | loff_t rewrite_bbt[NAND_MAX_CHIPS] = {0}; |
2515 | unsigned int bbt_masked_page = 0xffffffff; | 2529 | unsigned int bbt_masked_page = 0xffffffff; |
2516 | loff_t len; | 2530 | loff_t len; |
2517 | 2531 | ||
@@ -2632,7 +2646,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, | |||
2632 | } | 2646 | } |
2633 | instr->state = MTD_ERASE_DONE; | 2647 | instr->state = MTD_ERASE_DONE; |
2634 | 2648 | ||
2635 | erase_exit: | 2649 | erase_exit: |
2636 | 2650 | ||
2637 | ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO; | 2651 | ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO; |
2638 | 2652 | ||
@@ -2706,7 +2720,8 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
2706 | struct nand_chip *chip = mtd->priv; | 2720 | struct nand_chip *chip = mtd->priv; |
2707 | int ret; | 2721 | int ret; |
2708 | 2722 | ||
2709 | if ((ret = nand_block_isbad(mtd, ofs))) { | 2723 | ret = nand_block_isbad(mtd, ofs); |
2724 | if (ret) { | ||
2710 | /* If it was bad already, return success and do nothing. */ | 2725 | /* If it was bad already, return success and do nothing. */ |
2711 | if (ret > 0) | 2726 | if (ret > 0) |
2712 | return 0; | 2727 | return 0; |
@@ -2787,15 +2802,115 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) | |||
2787 | } | 2802 | } |
2788 | 2803 | ||
2789 | /* | 2804 | /* |
2805 | * sanitize ONFI strings so we can safely print them | ||
2806 | */ | ||
2807 | static void sanitize_string(uint8_t *s, size_t len) | ||
2808 | { | ||
2809 | ssize_t i; | ||
2810 | |||
2811 | /* null terminate */ | ||
2812 | s[len - 1] = 0; | ||
2813 | |||
2814 | /* remove non printable chars */ | ||
2815 | for (i = 0; i < len - 1; i++) { | ||
2816 | if (s[i] < ' ' || s[i] > 127) | ||
2817 | s[i] = '?'; | ||
2818 | } | ||
2819 | |||
2820 | /* remove trailing spaces */ | ||
2821 | strim(s); | ||
2822 | } | ||
2823 | |||
2824 | static u16 onfi_crc16(u16 crc, u8 const *p, size_t len) | ||
2825 | { | ||
2826 | int i; | ||
2827 | while (len--) { | ||
2828 | crc ^= *p++ << 8; | ||
2829 | for (i = 0; i < 8; i++) | ||
2830 | crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0); | ||
2831 | } | ||
2832 | |||
2833 | return crc; | ||
2834 | } | ||
2835 | |||
2836 | /* | ||
2837 | * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise | ||
2838 | */ | ||
2839 | static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, | ||
2840 | int busw) | ||
2841 | { | ||
2842 | struct nand_onfi_params *p = &chip->onfi_params; | ||
2843 | int i; | ||
2844 | int val; | ||
2845 | |||
2846 | /* try ONFI for unknow chip or LP */ | ||
2847 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1); | ||
2848 | if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' || | ||
2849 | chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I') | ||
2850 | return 0; | ||
2851 | |||
2852 | printk(KERN_INFO "ONFI flash detected\n"); | ||
2853 | chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1); | ||
2854 | for (i = 0; i < 3; i++) { | ||
2855 | chip->read_buf(mtd, (uint8_t *)p, sizeof(*p)); | ||
2856 | if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) == | ||
2857 | le16_to_cpu(p->crc)) { | ||
2858 | printk(KERN_INFO "ONFI param page %d valid\n", i); | ||
2859 | break; | ||
2860 | } | ||
2861 | } | ||
2862 | |||
2863 | if (i == 3) | ||
2864 | return 0; | ||
2865 | |||
2866 | /* check version */ | ||
2867 | val = le16_to_cpu(p->revision); | ||
2868 | if (val == 1 || val > (1 << 4)) { | ||
2869 | printk(KERN_INFO "%s: unsupported ONFI version: %d\n", | ||
2870 | __func__, val); | ||
2871 | return 0; | ||
2872 | } | ||
2873 | |||
2874 | if (val & (1 << 4)) | ||
2875 | chip->onfi_version = 22; | ||
2876 | else if (val & (1 << 3)) | ||
2877 | chip->onfi_version = 21; | ||
2878 | else if (val & (1 << 2)) | ||
2879 | chip->onfi_version = 20; | ||
2880 | else | ||
2881 | chip->onfi_version = 10; | ||
2882 | |||
2883 | sanitize_string(p->manufacturer, sizeof(p->manufacturer)); | ||
2884 | sanitize_string(p->model, sizeof(p->model)); | ||
2885 | if (!mtd->name) | ||
2886 | mtd->name = p->model; | ||
2887 | mtd->writesize = le32_to_cpu(p->byte_per_page); | ||
2888 | mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize; | ||
2889 | mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page); | ||
2890 | chip->chipsize = le32_to_cpu(p->blocks_per_lun) * mtd->erasesize; | ||
2891 | busw = 0; | ||
2892 | if (le16_to_cpu(p->features) & 1) | ||
2893 | busw = NAND_BUSWIDTH_16; | ||
2894 | |||
2895 | chip->options &= ~NAND_CHIPOPTIONS_MSK; | ||
2896 | chip->options |= (NAND_NO_READRDY | | ||
2897 | NAND_NO_AUTOINCR) & NAND_CHIPOPTIONS_MSK; | ||
2898 | |||
2899 | return 1; | ||
2900 | } | ||
2901 | |||
2902 | /* | ||
2790 | * Get the flash and manufacturer id and lookup if the type is supported | 2903 | * Get the flash and manufacturer id and lookup if the type is supported |
2791 | */ | 2904 | */ |
2792 | static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | 2905 | static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, |
2793 | struct nand_chip *chip, | 2906 | struct nand_chip *chip, |
2794 | int busw, int *maf_id, | 2907 | int busw, |
2908 | int *maf_id, int *dev_id, | ||
2795 | struct nand_flash_dev *type) | 2909 | struct nand_flash_dev *type) |
2796 | { | 2910 | { |
2797 | int i, dev_id, maf_idx; | 2911 | int i, maf_idx; |
2798 | u8 id_data[8]; | 2912 | u8 id_data[8]; |
2913 | int ret; | ||
2799 | 2914 | ||
2800 | /* Select the device */ | 2915 | /* Select the device */ |
2801 | chip->select_chip(mtd, 0); | 2916 | chip->select_chip(mtd, 0); |
@@ -2811,7 +2926,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2811 | 2926 | ||
2812 | /* Read manufacturer and device IDs */ | 2927 | /* Read manufacturer and device IDs */ |
2813 | *maf_id = chip->read_byte(mtd); | 2928 | *maf_id = chip->read_byte(mtd); |
2814 | dev_id = chip->read_byte(mtd); | 2929 | *dev_id = chip->read_byte(mtd); |
2815 | 2930 | ||
2816 | /* Try again to make sure, as some systems the bus-hold or other | 2931 | /* Try again to make sure, as some systems the bus-hold or other |
2817 | * interface concerns can cause random data which looks like a | 2932 | * interface concerns can cause random data which looks like a |
@@ -2821,15 +2936,13 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2821 | 2936 | ||
2822 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); | 2937 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); |
2823 | 2938 | ||
2824 | /* Read entire ID string */ | 2939 | for (i = 0; i < 2; i++) |
2825 | |||
2826 | for (i = 0; i < 8; i++) | ||
2827 | id_data[i] = chip->read_byte(mtd); | 2940 | id_data[i] = chip->read_byte(mtd); |
2828 | 2941 | ||
2829 | if (id_data[0] != *maf_id || id_data[1] != dev_id) { | 2942 | if (id_data[0] != *maf_id || id_data[1] != *dev_id) { |
2830 | printk(KERN_INFO "%s: second ID read did not match " | 2943 | printk(KERN_INFO "%s: second ID read did not match " |
2831 | "%02x,%02x against %02x,%02x\n", __func__, | 2944 | "%02x,%02x against %02x,%02x\n", __func__, |
2832 | *maf_id, dev_id, id_data[0], id_data[1]); | 2945 | *maf_id, *dev_id, id_data[0], id_data[1]); |
2833 | return ERR_PTR(-ENODEV); | 2946 | return ERR_PTR(-ENODEV); |
2834 | } | 2947 | } |
2835 | 2948 | ||
@@ -2837,8 +2950,23 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2837 | type = nand_flash_ids; | 2950 | type = nand_flash_ids; |
2838 | 2951 | ||
2839 | for (; type->name != NULL; type++) | 2952 | for (; type->name != NULL; type++) |
2840 | if (dev_id == type->id) | 2953 | if (*dev_id == type->id) |
2841 | break; | 2954 | break; |
2955 | |||
2956 | chip->onfi_version = 0; | ||
2957 | if (!type->name || !type->pagesize) { | ||
2958 | /* Check is chip is ONFI compliant */ | ||
2959 | ret = nand_flash_detect_onfi(mtd, chip, busw); | ||
2960 | if (ret) | ||
2961 | goto ident_done; | ||
2962 | } | ||
2963 | |||
2964 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); | ||
2965 | |||
2966 | /* Read entire ID string */ | ||
2967 | |||
2968 | for (i = 0; i < 8; i++) | ||
2969 | id_data[i] = chip->read_byte(mtd); | ||
2842 | 2970 | ||
2843 | if (!type->name) | 2971 | if (!type->name) |
2844 | return ERR_PTR(-ENODEV); | 2972 | return ERR_PTR(-ENODEV); |
@@ -2848,8 +2976,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2848 | 2976 | ||
2849 | chip->chipsize = (uint64_t)type->chipsize << 20; | 2977 | chip->chipsize = (uint64_t)type->chipsize << 20; |
2850 | 2978 | ||
2851 | /* Newer devices have all the information in additional id bytes */ | 2979 | if (!type->pagesize && chip->init_size) { |
2852 | if (!type->pagesize) { | 2980 | /* set the pagesize, oobsize, erasesize by the driver*/ |
2981 | busw = chip->init_size(mtd, chip, id_data); | ||
2982 | } else if (!type->pagesize) { | ||
2853 | int extid; | 2983 | int extid; |
2854 | /* The 3rd id byte holds MLC / multichip data */ | 2984 | /* The 3rd id byte holds MLC / multichip data */ |
2855 | chip->cellinfo = id_data[2]; | 2985 | chip->cellinfo = id_data[2]; |
@@ -2859,7 +2989,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2859 | /* | 2989 | /* |
2860 | * Field definitions are in the following datasheets: | 2990 | * Field definitions are in the following datasheets: |
2861 | * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) | 2991 | * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) |
2862 | * New style (6 byte ID): Samsung K9GAG08U0D (p.40) | 2992 | * New style (6 byte ID): Samsung K9GBG08U0M (p.40) |
2863 | * | 2993 | * |
2864 | * Check for wraparound + Samsung ID + nonzero 6th byte | 2994 | * Check for wraparound + Samsung ID + nonzero 6th byte |
2865 | * to decide what to do. | 2995 | * to decide what to do. |
@@ -2872,7 +3002,20 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2872 | mtd->writesize = 2048 << (extid & 0x03); | 3002 | mtd->writesize = 2048 << (extid & 0x03); |
2873 | extid >>= 2; | 3003 | extid >>= 2; |
2874 | /* Calc oobsize */ | 3004 | /* Calc oobsize */ |
2875 | mtd->oobsize = (extid & 0x03) == 0x01 ? 128 : 218; | 3005 | switch (extid & 0x03) { |
3006 | case 1: | ||
3007 | mtd->oobsize = 128; | ||
3008 | break; | ||
3009 | case 2: | ||
3010 | mtd->oobsize = 218; | ||
3011 | break; | ||
3012 | case 3: | ||
3013 | mtd->oobsize = 400; | ||
3014 | break; | ||
3015 | default: | ||
3016 | mtd->oobsize = 436; | ||
3017 | break; | ||
3018 | } | ||
2876 | extid >>= 2; | 3019 | extid >>= 2; |
2877 | /* Calc blocksize */ | 3020 | /* Calc blocksize */ |
2878 | mtd->erasesize = (128 * 1024) << | 3021 | mtd->erasesize = (128 * 1024) << |
@@ -2900,7 +3043,35 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2900 | mtd->writesize = type->pagesize; | 3043 | mtd->writesize = type->pagesize; |
2901 | mtd->oobsize = mtd->writesize / 32; | 3044 | mtd->oobsize = mtd->writesize / 32; |
2902 | busw = type->options & NAND_BUSWIDTH_16; | 3045 | busw = type->options & NAND_BUSWIDTH_16; |
3046 | |||
3047 | /* | ||
3048 | * Check for Spansion/AMD ID + repeating 5th, 6th byte since | ||
3049 | * some Spansion chips have erasesize that conflicts with size | ||
3050 | * listed in nand_ids table | ||
3051 | * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39) | ||
3052 | */ | ||
3053 | if (*maf_id == NAND_MFR_AMD && id_data[4] != 0x00 && | ||
3054 | id_data[5] == 0x00 && id_data[6] == 0x00 && | ||
3055 | id_data[7] == 0x00 && mtd->writesize == 512) { | ||
3056 | mtd->erasesize = 128 * 1024; | ||
3057 | mtd->erasesize <<= ((id_data[3] & 0x03) << 1); | ||
3058 | } | ||
2903 | } | 3059 | } |
3060 | /* Get chip options, preserve non chip based options */ | ||
3061 | chip->options &= ~NAND_CHIPOPTIONS_MSK; | ||
3062 | chip->options |= type->options & NAND_CHIPOPTIONS_MSK; | ||
3063 | |||
3064 | /* Check if chip is a not a samsung device. Do not clear the | ||
3065 | * options for chips which are not having an extended id. | ||
3066 | */ | ||
3067 | if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize) | ||
3068 | chip->options &= ~NAND_SAMSUNG_LP_OPTIONS; | ||
3069 | ident_done: | ||
3070 | |||
3071 | /* | ||
3072 | * Set chip as a default. Board drivers can override it, if necessary | ||
3073 | */ | ||
3074 | chip->options |= NAND_NO_AUTOINCR; | ||
2904 | 3075 | ||
2905 | /* Try to identify manufacturer */ | 3076 | /* Try to identify manufacturer */ |
2906 | for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) { | 3077 | for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) { |
@@ -2915,7 +3086,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2915 | if (busw != (chip->options & NAND_BUSWIDTH_16)) { | 3086 | if (busw != (chip->options & NAND_BUSWIDTH_16)) { |
2916 | printk(KERN_INFO "NAND device: Manufacturer ID:" | 3087 | printk(KERN_INFO "NAND device: Manufacturer ID:" |
2917 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, | 3088 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, |
2918 | dev_id, nand_manuf_ids[maf_idx].name, mtd->name); | 3089 | *dev_id, nand_manuf_ids[maf_idx].name, mtd->name); |
2919 | printk(KERN_WARNING "NAND bus width %d instead %d bit\n", | 3090 | printk(KERN_WARNING "NAND bus width %d instead %d bit\n", |
2920 | (chip->options & NAND_BUSWIDTH_16) ? 16 : 8, | 3091 | (chip->options & NAND_BUSWIDTH_16) ? 16 : 8, |
2921 | busw ? 16 : 8); | 3092 | busw ? 16 : 8); |
@@ -2931,8 +3102,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2931 | ffs(mtd->erasesize) - 1; | 3102 | ffs(mtd->erasesize) - 1; |
2932 | if (chip->chipsize & 0xffffffff) | 3103 | if (chip->chipsize & 0xffffffff) |
2933 | chip->chip_shift = ffs((unsigned)chip->chipsize) - 1; | 3104 | chip->chip_shift = ffs((unsigned)chip->chipsize) - 1; |
2934 | else | 3105 | else { |
2935 | chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1; | 3106 | chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)); |
3107 | chip->chip_shift += 32 - 1; | ||
3108 | } | ||
2936 | 3109 | ||
2937 | /* Set the bad block position */ | 3110 | /* Set the bad block position */ |
2938 | if (mtd->writesize > 512 || (busw & NAND_BUSWIDTH_16)) | 3111 | if (mtd->writesize > 512 || (busw & NAND_BUSWIDTH_16)) |
@@ -2940,27 +3113,12 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2940 | else | 3113 | else |
2941 | chip->badblockpos = NAND_SMALL_BADBLOCK_POS; | 3114 | chip->badblockpos = NAND_SMALL_BADBLOCK_POS; |
2942 | 3115 | ||
2943 | /* Get chip options, preserve non chip based options */ | ||
2944 | chip->options &= ~NAND_CHIPOPTIONS_MSK; | ||
2945 | chip->options |= type->options & NAND_CHIPOPTIONS_MSK; | ||
2946 | |||
2947 | /* | ||
2948 | * Set chip as a default. Board drivers can override it, if necessary | ||
2949 | */ | ||
2950 | chip->options |= NAND_NO_AUTOINCR; | ||
2951 | |||
2952 | /* Check if chip is a not a samsung device. Do not clear the | ||
2953 | * options for chips which are not having an extended id. | ||
2954 | */ | ||
2955 | if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize) | ||
2956 | chip->options &= ~NAND_SAMSUNG_LP_OPTIONS; | ||
2957 | |||
2958 | /* | 3116 | /* |
2959 | * Bad block marker is stored in the last page of each block | 3117 | * Bad block marker is stored in the last page of each block |
2960 | * on Samsung and Hynix MLC devices; stored in first two pages | 3118 | * on Samsung and Hynix MLC devices; stored in first two pages |
2961 | * of each block on Micron devices with 2KiB pages and on | 3119 | * of each block on Micron devices with 2KiB pages and on |
2962 | * SLC Samsung, Hynix, and AMD/Spansion. All others scan only | 3120 | * SLC Samsung, Hynix, Toshiba and AMD/Spansion. All others scan |
2963 | * the first page. | 3121 | * only the first page. |
2964 | */ | 3122 | */ |
2965 | if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && | 3123 | if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && |
2966 | (*maf_id == NAND_MFR_SAMSUNG || | 3124 | (*maf_id == NAND_MFR_SAMSUNG || |
@@ -2969,6 +3127,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2969 | else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) && | 3127 | else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) && |
2970 | (*maf_id == NAND_MFR_SAMSUNG || | 3128 | (*maf_id == NAND_MFR_SAMSUNG || |
2971 | *maf_id == NAND_MFR_HYNIX || | 3129 | *maf_id == NAND_MFR_HYNIX || |
3130 | *maf_id == NAND_MFR_TOSHIBA || | ||
2972 | *maf_id == NAND_MFR_AMD)) || | 3131 | *maf_id == NAND_MFR_AMD)) || |
2973 | (mtd->writesize == 2048 && | 3132 | (mtd->writesize == 2048 && |
2974 | *maf_id == NAND_MFR_MICRON)) | 3133 | *maf_id == NAND_MFR_MICRON)) |
@@ -2994,9 +3153,11 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2994 | if (mtd->writesize > 512 && chip->cmdfunc == nand_command) | 3153 | if (mtd->writesize > 512 && chip->cmdfunc == nand_command) |
2995 | chip->cmdfunc = nand_command_lp; | 3154 | chip->cmdfunc = nand_command_lp; |
2996 | 3155 | ||
3156 | /* TODO onfi flash name */ | ||
2997 | printk(KERN_INFO "NAND device: Manufacturer ID:" | 3157 | printk(KERN_INFO "NAND device: Manufacturer ID:" |
2998 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id, | 3158 | " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id, |
2999 | nand_manuf_ids[maf_idx].name, type->name); | 3159 | nand_manuf_ids[maf_idx].name, |
3160 | chip->onfi_version ? type->name : chip->onfi_params.model); | ||
3000 | 3161 | ||
3001 | return type; | 3162 | return type; |
3002 | } | 3163 | } |
@@ -3015,7 +3176,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
3015 | int nand_scan_ident(struct mtd_info *mtd, int maxchips, | 3176 | int nand_scan_ident(struct mtd_info *mtd, int maxchips, |
3016 | struct nand_flash_dev *table) | 3177 | struct nand_flash_dev *table) |
3017 | { | 3178 | { |
3018 | int i, busw, nand_maf_id; | 3179 | int i, busw, nand_maf_id, nand_dev_id; |
3019 | struct nand_chip *chip = mtd->priv; | 3180 | struct nand_chip *chip = mtd->priv; |
3020 | struct nand_flash_dev *type; | 3181 | struct nand_flash_dev *type; |
3021 | 3182 | ||
@@ -3025,7 +3186,8 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, | |||
3025 | nand_set_defaults(chip, busw); | 3186 | nand_set_defaults(chip, busw); |
3026 | 3187 | ||
3027 | /* Read the flash type */ | 3188 | /* Read the flash type */ |
3028 | type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id, table); | 3189 | type = nand_get_flash_type(mtd, chip, busw, |
3190 | &nand_maf_id, &nand_dev_id, table); | ||
3029 | 3191 | ||
3030 | if (IS_ERR(type)) { | 3192 | if (IS_ERR(type)) { |
3031 | if (!(chip->options & NAND_SCAN_SILENT_NODEV)) | 3193 | if (!(chip->options & NAND_SCAN_SILENT_NODEV)) |
@@ -3043,7 +3205,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, | |||
3043 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); | 3205 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); |
3044 | /* Read manufacturer and device IDs */ | 3206 | /* Read manufacturer and device IDs */ |
3045 | if (nand_maf_id != chip->read_byte(mtd) || | 3207 | if (nand_maf_id != chip->read_byte(mtd) || |
3046 | type->id != chip->read_byte(mtd)) | 3208 | nand_dev_id != chip->read_byte(mtd)) |
3047 | break; | 3209 | break; |
3048 | } | 3210 | } |
3049 | if (i > 1) | 3211 | if (i > 1) |
@@ -3055,6 +3217,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, | |||
3055 | 3217 | ||
3056 | return 0; | 3218 | return 0; |
3057 | } | 3219 | } |
3220 | EXPORT_SYMBOL(nand_scan_ident); | ||
3058 | 3221 | ||
3059 | 3222 | ||
3060 | /** | 3223 | /** |
@@ -3219,7 +3382,7 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3219 | * mode | 3382 | * mode |
3220 | */ | 3383 | */ |
3221 | chip->ecc.steps = mtd->writesize / chip->ecc.size; | 3384 | chip->ecc.steps = mtd->writesize / chip->ecc.size; |
3222 | if(chip->ecc.steps * chip->ecc.size != mtd->writesize) { | 3385 | if (chip->ecc.steps * chip->ecc.size != mtd->writesize) { |
3223 | printk(KERN_WARNING "Invalid ecc parameters\n"); | 3386 | printk(KERN_WARNING "Invalid ecc parameters\n"); |
3224 | BUG(); | 3387 | BUG(); |
3225 | } | 3388 | } |
@@ -3231,7 +3394,7 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3231 | */ | 3394 | */ |
3232 | if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && | 3395 | if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && |
3233 | !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) { | 3396 | !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) { |
3234 | switch(chip->ecc.steps) { | 3397 | switch (chip->ecc.steps) { |
3235 | case 2: | 3398 | case 2: |
3236 | mtd->subpage_sft = 1; | 3399 | mtd->subpage_sft = 1; |
3237 | break; | 3400 | break; |
@@ -3283,10 +3446,11 @@ int nand_scan_tail(struct mtd_info *mtd) | |||
3283 | /* Build bad block table */ | 3446 | /* Build bad block table */ |
3284 | return chip->scan_bbt(mtd); | 3447 | return chip->scan_bbt(mtd); |
3285 | } | 3448 | } |
3449 | EXPORT_SYMBOL(nand_scan_tail); | ||
3286 | 3450 | ||
3287 | /* is_module_text_address() isn't exported, and it's mostly a pointless | 3451 | /* is_module_text_address() isn't exported, and it's mostly a pointless |
3288 | test if this is a module _anyway_ -- they'd have to try _really_ hard | 3452 | * test if this is a module _anyway_ -- they'd have to try _really_ hard |
3289 | to call us from in-kernel code if the core NAND support is modular. */ | 3453 | * to call us from in-kernel code if the core NAND support is modular. */ |
3290 | #ifdef MODULE | 3454 | #ifdef MODULE |
3291 | #define caller_is_module() (1) | 3455 | #define caller_is_module() (1) |
3292 | #else | 3456 | #else |
@@ -3322,6 +3486,7 @@ int nand_scan(struct mtd_info *mtd, int maxchips) | |||
3322 | ret = nand_scan_tail(mtd); | 3486 | ret = nand_scan_tail(mtd); |
3323 | return ret; | 3487 | return ret; |
3324 | } | 3488 | } |
3489 | EXPORT_SYMBOL(nand_scan); | ||
3325 | 3490 | ||
3326 | /** | 3491 | /** |
3327 | * nand_release - [NAND Interface] Free resources held by the NAND device | 3492 | * nand_release - [NAND Interface] Free resources held by the NAND device |
@@ -3348,12 +3513,6 @@ void nand_release(struct mtd_info *mtd) | |||
3348 | & NAND_BBT_DYNAMICSTRUCT) | 3513 | & NAND_BBT_DYNAMICSTRUCT) |
3349 | kfree(chip->badblock_pattern); | 3514 | kfree(chip->badblock_pattern); |
3350 | } | 3515 | } |
3351 | |||
3352 | EXPORT_SYMBOL_GPL(nand_lock); | ||
3353 | EXPORT_SYMBOL_GPL(nand_unlock); | ||
3354 | EXPORT_SYMBOL_GPL(nand_scan); | ||
3355 | EXPORT_SYMBOL_GPL(nand_scan_ident); | ||
3356 | EXPORT_SYMBOL_GPL(nand_scan_tail); | ||
3357 | EXPORT_SYMBOL_GPL(nand_release); | 3516 | EXPORT_SYMBOL_GPL(nand_release); |
3358 | 3517 | ||
3359 | static int __init nand_base_init(void) | 3518 | static int __init nand_base_init(void) |
@@ -3371,5 +3530,6 @@ module_init(nand_base_init); | |||
3371 | module_exit(nand_base_exit); | 3530 | module_exit(nand_base_exit); |
3372 | 3531 | ||
3373 | MODULE_LICENSE("GPL"); | 3532 | MODULE_LICENSE("GPL"); |
3374 | MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>"); | 3533 | MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>"); |
3534 | MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>"); | ||
3375 | MODULE_DESCRIPTION("Generic NAND flash driver code"); | 3535 | MODULE_DESCRIPTION("Generic NAND flash driver code"); |
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 5fedf4a74f16..586b981f0e61 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c | |||
@@ -13,28 +13,37 @@ | |||
13 | * Description: | 13 | * Description: |
14 | * | 14 | * |
15 | * When nand_scan_bbt is called, then it tries to find the bad block table | 15 | * When nand_scan_bbt is called, then it tries to find the bad block table |
16 | * depending on the options in the bbt descriptor(s). If a bbt is found | 16 | * depending on the options in the BBT descriptor(s). If no flash based BBT |
17 | * then the contents are read and the memory based bbt is created. If a | 17 | * (NAND_USE_FLASH_BBT) is specified then the device is scanned for factory |
18 | * mirrored bbt is selected then the mirror is searched too and the | 18 | * marked good / bad blocks. This information is used to create a memory BBT. |
19 | * versions are compared. If the mirror has a greater version number | 19 | * Once a new bad block is discovered then the "factory" information is updated |
20 | * than the mirror bbt is used to build the memory based bbt. | 20 | * on the device. |
21 | * If a flash based BBT is specified then the function first tries to find the | ||
22 | * BBT on flash. If a BBT is found then the contents are read and the memory | ||
23 | * based BBT is created. If a mirrored BBT is selected then the mirror is | ||
24 | * searched too and the versions are compared. If the mirror has a greater | ||
25 | * version number than the mirror BBT is used to build the memory based BBT. | ||
21 | * If the tables are not versioned, then we "or" the bad block information. | 26 | * If the tables are not versioned, then we "or" the bad block information. |
22 | * If one of the bbt's is out of date or does not exist it is (re)created. | 27 | * If one of the BBTs is out of date or does not exist it is (re)created. |
23 | * If no bbt exists at all then the device is scanned for factory marked | 28 | * If no BBT exists at all then the device is scanned for factory marked |
24 | * good / bad blocks and the bad block tables are created. | 29 | * good / bad blocks and the bad block tables are created. |
25 | * | 30 | * |
26 | * For manufacturer created bbts like the one found on M-SYS DOC devices | 31 | * For manufacturer created BBTs like the one found on M-SYS DOC devices |
27 | * the bbt is searched and read but never created | 32 | * the BBT is searched and read but never created |
28 | * | 33 | * |
29 | * The autogenerated bad block table is located in the last good blocks | 34 | * The auto generated bad block table is located in the last good blocks |
30 | * of the device. The table is mirrored, so it can be updated eventually. | 35 | * of the device. The table is mirrored, so it can be updated eventually. |
31 | * The table is marked in the oob area with an ident pattern and a version | 36 | * The table is marked in the OOB area with an ident pattern and a version |
32 | * number which indicates which of both tables is more up to date. | 37 | * number which indicates which of both tables is more up to date. If the NAND |
38 | * controller needs the complete OOB area for the ECC information then the | ||
39 | * option NAND_USE_FLASH_BBT_NO_OOB should be used: it moves the ident pattern | ||
40 | * and the version byte into the data area and the OOB area will remain | ||
41 | * untouched. | ||
33 | * | 42 | * |
34 | * The table uses 2 bits per block | 43 | * The table uses 2 bits per block |
35 | * 11b: block is good | 44 | * 11b: block is good |
36 | * 00b: block is factory marked bad | 45 | * 00b: block is factory marked bad |
37 | * 01b, 10b: block is marked bad due to wear | 46 | * 01b, 10b: block is marked bad due to wear |
38 | * | 47 | * |
39 | * The memory bad block table uses the following scheme: | 48 | * The memory bad block table uses the following scheme: |
40 | * 00b: block is good | 49 | * 00b: block is good |
@@ -59,6 +68,16 @@ | |||
59 | #include <linux/delay.h> | 68 | #include <linux/delay.h> |
60 | #include <linux/vmalloc.h> | 69 | #include <linux/vmalloc.h> |
61 | 70 | ||
71 | static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td) | ||
72 | { | ||
73 | int ret; | ||
74 | |||
75 | ret = memcmp(buf, td->pattern, td->len); | ||
76 | if (!ret) | ||
77 | return ret; | ||
78 | return -1; | ||
79 | } | ||
80 | |||
62 | /** | 81 | /** |
63 | * check_pattern - [GENERIC] check if a pattern is in the buffer | 82 | * check_pattern - [GENERIC] check if a pattern is in the buffer |
64 | * @buf: the buffer to search | 83 | * @buf: the buffer to search |
@@ -77,6 +96,9 @@ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_desc | |||
77 | int i, end = 0; | 96 | int i, end = 0; |
78 | uint8_t *p = buf; | 97 | uint8_t *p = buf; |
79 | 98 | ||
99 | if (td->options & NAND_BBT_NO_OOB) | ||
100 | return check_pattern_no_oob(buf, td); | ||
101 | |||
80 | end = paglen + td->offs; | 102 | end = paglen + td->offs; |
81 | if (td->options & NAND_BBT_SCANEMPTY) { | 103 | if (td->options & NAND_BBT_SCANEMPTY) { |
82 | for (i = 0; i < end; i++) { | 104 | for (i = 0; i < end; i++) { |
@@ -156,32 +178,63 @@ static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td) | |||
156 | } | 178 | } |
157 | 179 | ||
158 | /** | 180 | /** |
181 | * add_marker_len - compute the length of the marker in data area | ||
182 | * @td: BBT descriptor used for computation | ||
183 | * | ||
184 | * The length will be 0 if the markeris located in OOB area. | ||
185 | */ | ||
186 | static u32 add_marker_len(struct nand_bbt_descr *td) | ||
187 | { | ||
188 | u32 len; | ||
189 | |||
190 | if (!(td->options & NAND_BBT_NO_OOB)) | ||
191 | return 0; | ||
192 | |||
193 | len = td->len; | ||
194 | if (td->options & NAND_BBT_VERSION) | ||
195 | len++; | ||
196 | return len; | ||
197 | } | ||
198 | |||
199 | /** | ||
159 | * read_bbt - [GENERIC] Read the bad block table starting from page | 200 | * read_bbt - [GENERIC] Read the bad block table starting from page |
160 | * @mtd: MTD device structure | 201 | * @mtd: MTD device structure |
161 | * @buf: temporary buffer | 202 | * @buf: temporary buffer |
162 | * @page: the starting page | 203 | * @page: the starting page |
163 | * @num: the number of bbt descriptors to read | 204 | * @num: the number of bbt descriptors to read |
164 | * @bits: number of bits per block | 205 | * @td: the bbt describtion table |
165 | * @offs: offset in the memory table | 206 | * @offs: offset in the memory table |
166 | * @reserved_block_code: Pattern to identify reserved blocks | ||
167 | * | 207 | * |
168 | * Read the bad block table starting from page. | 208 | * Read the bad block table starting from page. |
169 | * | 209 | * |
170 | */ | 210 | */ |
171 | static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, | 211 | static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, |
172 | int bits, int offs, int reserved_block_code) | 212 | struct nand_bbt_descr *td, int offs) |
173 | { | 213 | { |
174 | int res, i, j, act = 0; | 214 | int res, i, j, act = 0; |
175 | struct nand_chip *this = mtd->priv; | 215 | struct nand_chip *this = mtd->priv; |
176 | size_t retlen, len, totlen; | 216 | size_t retlen, len, totlen; |
177 | loff_t from; | 217 | loff_t from; |
218 | int bits = td->options & NAND_BBT_NRBITS_MSK; | ||
178 | uint8_t msk = (uint8_t) ((1 << bits) - 1); | 219 | uint8_t msk = (uint8_t) ((1 << bits) - 1); |
220 | u32 marker_len; | ||
221 | int reserved_block_code = td->reserved_block_code; | ||
179 | 222 | ||
180 | totlen = (num * bits) >> 3; | 223 | totlen = (num * bits) >> 3; |
224 | marker_len = add_marker_len(td); | ||
181 | from = ((loff_t) page) << this->page_shift; | 225 | from = ((loff_t) page) << this->page_shift; |
182 | 226 | ||
183 | while (totlen) { | 227 | while (totlen) { |
184 | len = min(totlen, (size_t) (1 << this->bbt_erase_shift)); | 228 | len = min(totlen, (size_t) (1 << this->bbt_erase_shift)); |
229 | if (marker_len) { | ||
230 | /* | ||
231 | * In case the BBT marker is not in the OOB area it | ||
232 | * will be just in the first page. | ||
233 | */ | ||
234 | len -= marker_len; | ||
235 | from += marker_len; | ||
236 | marker_len = 0; | ||
237 | } | ||
185 | res = mtd->read(mtd, from, len, &retlen, buf); | 238 | res = mtd->read(mtd, from, len, &retlen, buf); |
186 | if (res < 0) { | 239 | if (res < 0) { |
187 | if (retlen != len) { | 240 | if (retlen != len) { |
@@ -238,20 +291,21 @@ static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc | |||
238 | { | 291 | { |
239 | struct nand_chip *this = mtd->priv; | 292 | struct nand_chip *this = mtd->priv; |
240 | int res = 0, i; | 293 | int res = 0, i; |
241 | int bits; | ||
242 | 294 | ||
243 | bits = td->options & NAND_BBT_NRBITS_MSK; | ||
244 | if (td->options & NAND_BBT_PERCHIP) { | 295 | if (td->options & NAND_BBT_PERCHIP) { |
245 | int offs = 0; | 296 | int offs = 0; |
246 | for (i = 0; i < this->numchips; i++) { | 297 | for (i = 0; i < this->numchips; i++) { |
247 | if (chip == -1 || chip == i) | 298 | if (chip == -1 || chip == i) |
248 | res = read_bbt (mtd, buf, td->pages[i], this->chipsize >> this->bbt_erase_shift, bits, offs, td->reserved_block_code); | 299 | res = read_bbt(mtd, buf, td->pages[i], |
300 | this->chipsize >> this->bbt_erase_shift, | ||
301 | td, offs); | ||
249 | if (res) | 302 | if (res) |
250 | return res; | 303 | return res; |
251 | offs += this->chipsize >> (this->bbt_erase_shift + 2); | 304 | offs += this->chipsize >> (this->bbt_erase_shift + 2); |
252 | } | 305 | } |
253 | } else { | 306 | } else { |
254 | res = read_bbt (mtd, buf, td->pages[0], mtd->size >> this->bbt_erase_shift, bits, 0, td->reserved_block_code); | 307 | res = read_bbt(mtd, buf, td->pages[0], |
308 | mtd->size >> this->bbt_erase_shift, td, 0); | ||
255 | if (res) | 309 | if (res) |
256 | return res; | 310 | return res; |
257 | } | 311 | } |
@@ -259,9 +313,25 @@ static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc | |||
259 | } | 313 | } |
260 | 314 | ||
261 | /* | 315 | /* |
316 | * BBT marker is in the first page, no OOB. | ||
317 | */ | ||
318 | static int scan_read_raw_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs, | ||
319 | struct nand_bbt_descr *td) | ||
320 | { | ||
321 | size_t retlen; | ||
322 | size_t len; | ||
323 | |||
324 | len = td->len; | ||
325 | if (td->options & NAND_BBT_VERSION) | ||
326 | len++; | ||
327 | |||
328 | return mtd->read(mtd, offs, len, &retlen, buf); | ||
329 | } | ||
330 | |||
331 | /* | ||
262 | * Scan read raw data from flash | 332 | * Scan read raw data from flash |
263 | */ | 333 | */ |
264 | static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t offs, | 334 | static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs, |
265 | size_t len) | 335 | size_t len) |
266 | { | 336 | { |
267 | struct mtd_oob_ops ops; | 337 | struct mtd_oob_ops ops; |
@@ -294,6 +364,15 @@ static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t offs, | |||
294 | return 0; | 364 | return 0; |
295 | } | 365 | } |
296 | 366 | ||
367 | static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t offs, | ||
368 | size_t len, struct nand_bbt_descr *td) | ||
369 | { | ||
370 | if (td->options & NAND_BBT_NO_OOB) | ||
371 | return scan_read_raw_data(mtd, buf, offs, td); | ||
372 | else | ||
373 | return scan_read_raw_oob(mtd, buf, offs, len); | ||
374 | } | ||
375 | |||
297 | /* | 376 | /* |
298 | * Scan write data with oob to flash | 377 | * Scan write data with oob to flash |
299 | */ | 378 | */ |
@@ -312,6 +391,15 @@ static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len, | |||
312 | return mtd->write_oob(mtd, offs, &ops); | 391 | return mtd->write_oob(mtd, offs, &ops); |
313 | } | 392 | } |
314 | 393 | ||
394 | static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td) | ||
395 | { | ||
396 | u32 ver_offs = td->veroffs; | ||
397 | |||
398 | if (!(td->options & NAND_BBT_NO_OOB)) | ||
399 | ver_offs += mtd->writesize; | ||
400 | return ver_offs; | ||
401 | } | ||
402 | |||
315 | /** | 403 | /** |
316 | * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page | 404 | * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page |
317 | * @mtd: MTD device structure | 405 | * @mtd: MTD device structure |
@@ -331,8 +419,8 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, | |||
331 | /* Read the primary version, if available */ | 419 | /* Read the primary version, if available */ |
332 | if (td->options & NAND_BBT_VERSION) { | 420 | if (td->options & NAND_BBT_VERSION) { |
333 | scan_read_raw(mtd, buf, (loff_t)td->pages[0] << this->page_shift, | 421 | scan_read_raw(mtd, buf, (loff_t)td->pages[0] << this->page_shift, |
334 | mtd->writesize); | 422 | mtd->writesize, td); |
335 | td->version[0] = buf[mtd->writesize + td->veroffs]; | 423 | td->version[0] = buf[bbt_get_ver_offs(mtd, td)]; |
336 | printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", | 424 | printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", |
337 | td->pages[0], td->version[0]); | 425 | td->pages[0], td->version[0]); |
338 | } | 426 | } |
@@ -340,8 +428,8 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, | |||
340 | /* Read the mirror version, if available */ | 428 | /* Read the mirror version, if available */ |
341 | if (md && (md->options & NAND_BBT_VERSION)) { | 429 | if (md && (md->options & NAND_BBT_VERSION)) { |
342 | scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift, | 430 | scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift, |
343 | mtd->writesize); | 431 | mtd->writesize, td); |
344 | md->version[0] = buf[mtd->writesize + md->veroffs]; | 432 | md->version[0] = buf[bbt_get_ver_offs(mtd, md)]; |
345 | printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", | 433 | printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", |
346 | md->pages[0], md->version[0]); | 434 | md->pages[0], md->version[0]); |
347 | } | 435 | } |
@@ -357,7 +445,7 @@ static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd, | |||
357 | { | 445 | { |
358 | int ret, j; | 446 | int ret, j; |
359 | 447 | ||
360 | ret = scan_read_raw(mtd, buf, offs, readlen); | 448 | ret = scan_read_raw_oob(mtd, buf, offs, readlen); |
361 | if (ret) | 449 | if (ret) |
362 | return ret; | 450 | return ret; |
363 | 451 | ||
@@ -464,6 +552,8 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
464 | for (i = startblock; i < numblocks;) { | 552 | for (i = startblock; i < numblocks;) { |
465 | int ret; | 553 | int ret; |
466 | 554 | ||
555 | BUG_ON(bd->options & NAND_BBT_NO_OOB); | ||
556 | |||
467 | if (bd->options & NAND_BBT_SCANALLPAGES) | 557 | if (bd->options & NAND_BBT_SCANALLPAGES) |
468 | ret = scan_block_full(mtd, bd, from, buf, readlen, | 558 | ret = scan_block_full(mtd, bd, from, buf, readlen, |
469 | scanlen, len); | 559 | scanlen, len); |
@@ -545,11 +635,12 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
545 | loff_t offs = (loff_t)actblock << this->bbt_erase_shift; | 635 | loff_t offs = (loff_t)actblock << this->bbt_erase_shift; |
546 | 636 | ||
547 | /* Read first page */ | 637 | /* Read first page */ |
548 | scan_read_raw(mtd, buf, offs, mtd->writesize); | 638 | scan_read_raw(mtd, buf, offs, mtd->writesize, td); |
549 | if (!check_pattern(buf, scanlen, mtd->writesize, td)) { | 639 | if (!check_pattern(buf, scanlen, mtd->writesize, td)) { |
550 | td->pages[i] = actblock << blocktopage; | 640 | td->pages[i] = actblock << blocktopage; |
551 | if (td->options & NAND_BBT_VERSION) { | 641 | if (td->options & NAND_BBT_VERSION) { |
552 | td->version[i] = buf[mtd->writesize + td->veroffs]; | 642 | offs = bbt_get_ver_offs(mtd, td); |
643 | td->version[i] = buf[offs]; | ||
553 | } | 644 | } |
554 | break; | 645 | break; |
555 | } | 646 | } |
@@ -733,12 +824,26 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
733 | memset(&buf[offs], 0xff, (size_t) (numblocks >> sft)); | 824 | memset(&buf[offs], 0xff, (size_t) (numblocks >> sft)); |
734 | ooboffs = len + (pageoffs * mtd->oobsize); | 825 | ooboffs = len + (pageoffs * mtd->oobsize); |
735 | 826 | ||
827 | } else if (td->options & NAND_BBT_NO_OOB) { | ||
828 | ooboffs = 0; | ||
829 | offs = td->len; | ||
830 | /* the version byte */ | ||
831 | if (td->options & NAND_BBT_VERSION) | ||
832 | offs++; | ||
833 | /* Calc length */ | ||
834 | len = (size_t) (numblocks >> sft); | ||
835 | len += offs; | ||
836 | /* Make it page aligned ! */ | ||
837 | len = ALIGN(len, mtd->writesize); | ||
838 | /* Preset the buffer with 0xff */ | ||
839 | memset(buf, 0xff, len); | ||
840 | /* Pattern is located at the begin of first page */ | ||
841 | memcpy(buf, td->pattern, td->len); | ||
736 | } else { | 842 | } else { |
737 | /* Calc length */ | 843 | /* Calc length */ |
738 | len = (size_t) (numblocks >> sft); | 844 | len = (size_t) (numblocks >> sft); |
739 | /* Make it page aligned ! */ | 845 | /* Make it page aligned ! */ |
740 | len = (len + (mtd->writesize - 1)) & | 846 | len = ALIGN(len, mtd->writesize); |
741 | ~(mtd->writesize - 1); | ||
742 | /* Preset the buffer with 0xff */ | 847 | /* Preset the buffer with 0xff */ |
743 | memset(buf, 0xff, len + | 848 | memset(buf, 0xff, len + |
744 | (len >> this->page_shift)* mtd->oobsize); | 849 | (len >> this->page_shift)* mtd->oobsize); |
@@ -772,7 +877,9 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, | |||
772 | if (res < 0) | 877 | if (res < 0) |
773 | goto outerr; | 878 | goto outerr; |
774 | 879 | ||
775 | res = scan_write_bbt(mtd, to, len, buf, &buf[len]); | 880 | res = scan_write_bbt(mtd, to, len, buf, |
881 | td->options & NAND_BBT_NO_OOB ? NULL : | ||
882 | &buf[len]); | ||
776 | if (res < 0) | 883 | if (res < 0) |
777 | goto outerr; | 884 | goto outerr; |
778 | 885 | ||
@@ -892,7 +999,8 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc | |||
892 | continue; | 999 | continue; |
893 | 1000 | ||
894 | /* Create the table in memory by scanning the chip(s) */ | 1001 | /* Create the table in memory by scanning the chip(s) */ |
895 | create_bbt(mtd, buf, bd, chipsel); | 1002 | if (!(this->options & NAND_CREATE_EMPTY_BBT)) |
1003 | create_bbt(mtd, buf, bd, chipsel); | ||
896 | 1004 | ||
897 | td->version[i] = 1; | 1005 | td->version[i] = 1; |
898 | if (md) | 1006 | if (md) |
@@ -983,6 +1091,49 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) | |||
983 | } | 1091 | } |
984 | 1092 | ||
985 | /** | 1093 | /** |
1094 | * verify_bbt_descr - verify the bad block description | ||
1095 | * @bd: the table to verify | ||
1096 | * | ||
1097 | * This functions performs a few sanity checks on the bad block description | ||
1098 | * table. | ||
1099 | */ | ||
1100 | static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd) | ||
1101 | { | ||
1102 | struct nand_chip *this = mtd->priv; | ||
1103 | u32 pattern_len = bd->len; | ||
1104 | u32 bits = bd->options & NAND_BBT_NRBITS_MSK; | ||
1105 | u32 table_size; | ||
1106 | |||
1107 | if (!bd) | ||
1108 | return; | ||
1109 | BUG_ON((this->options & NAND_USE_FLASH_BBT_NO_OOB) && | ||
1110 | !(this->options & NAND_USE_FLASH_BBT)); | ||
1111 | BUG_ON(!bits); | ||
1112 | |||
1113 | if (bd->options & NAND_BBT_VERSION) | ||
1114 | pattern_len++; | ||
1115 | |||
1116 | if (bd->options & NAND_BBT_NO_OOB) { | ||
1117 | BUG_ON(!(this->options & NAND_USE_FLASH_BBT)); | ||
1118 | BUG_ON(!(this->options & NAND_USE_FLASH_BBT_NO_OOB)); | ||
1119 | BUG_ON(bd->offs); | ||
1120 | if (bd->options & NAND_BBT_VERSION) | ||
1121 | BUG_ON(bd->veroffs != bd->len); | ||
1122 | BUG_ON(bd->options & NAND_BBT_SAVECONTENT); | ||
1123 | } | ||
1124 | |||
1125 | if (bd->options & NAND_BBT_PERCHIP) | ||
1126 | table_size = this->chipsize >> this->bbt_erase_shift; | ||
1127 | else | ||
1128 | table_size = mtd->size >> this->bbt_erase_shift; | ||
1129 | table_size >>= 3; | ||
1130 | table_size *= bits; | ||
1131 | if (bd->options & NAND_BBT_NO_OOB) | ||
1132 | table_size += pattern_len; | ||
1133 | BUG_ON(table_size > (1 << this->bbt_erase_shift)); | ||
1134 | } | ||
1135 | |||
1136 | /** | ||
986 | * nand_scan_bbt - [NAND Interface] scan, find, read and maybe create bad block table(s) | 1137 | * nand_scan_bbt - [NAND Interface] scan, find, read and maybe create bad block table(s) |
987 | * @mtd: MTD device structure | 1138 | * @mtd: MTD device structure |
988 | * @bd: descriptor for the good/bad block search pattern | 1139 | * @bd: descriptor for the good/bad block search pattern |
@@ -1023,6 +1174,8 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) | |||
1023 | } | 1174 | } |
1024 | return res; | 1175 | return res; |
1025 | } | 1176 | } |
1177 | verify_bbt_descr(mtd, td); | ||
1178 | verify_bbt_descr(mtd, md); | ||
1026 | 1179 | ||
1027 | /* Allocate a temporary buffer for one eraseblock incl. oob */ | 1180 | /* Allocate a temporary buffer for one eraseblock incl. oob */ |
1028 | len = (1 << this->bbt_erase_shift); | 1181 | len = (1 << this->bbt_erase_shift); |
@@ -1166,6 +1319,26 @@ static struct nand_bbt_descr bbt_mirror_descr = { | |||
1166 | .pattern = mirror_pattern | 1319 | .pattern = mirror_pattern |
1167 | }; | 1320 | }; |
1168 | 1321 | ||
1322 | static struct nand_bbt_descr bbt_main_no_bbt_descr = { | ||
1323 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | ||
1324 | | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP | ||
1325 | | NAND_BBT_NO_OOB, | ||
1326 | .len = 4, | ||
1327 | .veroffs = 4, | ||
1328 | .maxblocks = 4, | ||
1329 | .pattern = bbt_pattern | ||
1330 | }; | ||
1331 | |||
1332 | static struct nand_bbt_descr bbt_mirror_no_bbt_descr = { | ||
1333 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | ||
1334 | | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP | ||
1335 | | NAND_BBT_NO_OOB, | ||
1336 | .len = 4, | ||
1337 | .veroffs = 4, | ||
1338 | .maxblocks = 4, | ||
1339 | .pattern = mirror_pattern | ||
1340 | }; | ||
1341 | |||
1169 | #define BBT_SCAN_OPTIONS (NAND_BBT_SCANLASTPAGE | NAND_BBT_SCAN2NDPAGE | \ | 1342 | #define BBT_SCAN_OPTIONS (NAND_BBT_SCANLASTPAGE | NAND_BBT_SCAN2NDPAGE | \ |
1170 | NAND_BBT_SCANBYTE1AND6) | 1343 | NAND_BBT_SCANBYTE1AND6) |
1171 | /** | 1344 | /** |
@@ -1236,8 +1409,13 @@ int nand_default_bbt(struct mtd_info *mtd) | |||
1236 | if (this->options & NAND_USE_FLASH_BBT) { | 1409 | if (this->options & NAND_USE_FLASH_BBT) { |
1237 | /* Use the default pattern descriptors */ | 1410 | /* Use the default pattern descriptors */ |
1238 | if (!this->bbt_td) { | 1411 | if (!this->bbt_td) { |
1239 | this->bbt_td = &bbt_main_descr; | 1412 | if (this->options & NAND_USE_FLASH_BBT_NO_OOB) { |
1240 | this->bbt_md = &bbt_mirror_descr; | 1413 | this->bbt_td = &bbt_main_no_bbt_descr; |
1414 | this->bbt_md = &bbt_mirror_no_bbt_descr; | ||
1415 | } else { | ||
1416 | this->bbt_td = &bbt_main_descr; | ||
1417 | this->bbt_md = &bbt_mirror_descr; | ||
1418 | } | ||
1241 | } | 1419 | } |
1242 | if (!this->badblock_pattern) { | 1420 | if (!this->badblock_pattern) { |
1243 | this->badblock_pattern = (mtd->writesize > 512) ? &largepage_flashbased : &smallpage_flashbased; | 1421 | this->badblock_pattern = (mtd->writesize > 512) ? &largepage_flashbased : &smallpage_flashbased; |
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index c65f19074bc8..00cf1b0d6053 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c | |||
@@ -75,9 +75,13 @@ struct nand_flash_dev nand_flash_ids[] = { | |||
75 | 75 | ||
76 | /*512 Megabit */ | 76 | /*512 Megabit */ |
77 | {"NAND 64MiB 1,8V 8-bit", 0xA2, 0, 64, 0, LP_OPTIONS}, | 77 | {"NAND 64MiB 1,8V 8-bit", 0xA2, 0, 64, 0, LP_OPTIONS}, |
78 | {"NAND 64MiB 1,8V 8-bit", 0xA0, 0, 64, 0, LP_OPTIONS}, | ||
78 | {"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, LP_OPTIONS}, | 79 | {"NAND 64MiB 3,3V 8-bit", 0xF2, 0, 64, 0, LP_OPTIONS}, |
80 | {"NAND 64MiB 3,3V 8-bit", 0xD0, 0, 64, 0, LP_OPTIONS}, | ||
79 | {"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, LP_OPTIONS16}, | 81 | {"NAND 64MiB 1,8V 16-bit", 0xB2, 0, 64, 0, LP_OPTIONS16}, |
82 | {"NAND 64MiB 1,8V 16-bit", 0xB0, 0, 64, 0, LP_OPTIONS16}, | ||
80 | {"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, LP_OPTIONS16}, | 83 | {"NAND 64MiB 3,3V 16-bit", 0xC2, 0, 64, 0, LP_OPTIONS16}, |
84 | {"NAND 64MiB 3,3V 16-bit", 0xC0, 0, 64, 0, LP_OPTIONS16}, | ||
81 | 85 | ||
82 | /* 1 Gigabit */ | 86 | /* 1 Gigabit */ |
83 | {"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, LP_OPTIONS}, | 87 | {"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, LP_OPTIONS}, |
@@ -112,7 +116,34 @@ struct nand_flash_dev nand_flash_ids[] = { | |||
112 | {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16}, | 116 | {"NAND 2GiB 3,3V 16-bit", 0xC5, 0, 2048, 0, LP_OPTIONS16}, |
113 | 117 | ||
114 | /* 32 Gigabit */ | 118 | /* 32 Gigabit */ |
119 | {"NAND 4GiB 1,8V 8-bit", 0xA7, 0, 4096, 0, LP_OPTIONS}, | ||
115 | {"NAND 4GiB 3,3V 8-bit", 0xD7, 0, 4096, 0, LP_OPTIONS}, | 120 | {"NAND 4GiB 3,3V 8-bit", 0xD7, 0, 4096, 0, LP_OPTIONS}, |
121 | {"NAND 4GiB 1,8V 16-bit", 0xB7, 0, 4096, 0, LP_OPTIONS16}, | ||
122 | {"NAND 4GiB 3,3V 16-bit", 0xC7, 0, 4096, 0, LP_OPTIONS16}, | ||
123 | |||
124 | /* 64 Gigabit */ | ||
125 | {"NAND 8GiB 1,8V 8-bit", 0xAE, 0, 8192, 0, LP_OPTIONS}, | ||
126 | {"NAND 8GiB 3,3V 8-bit", 0xDE, 0, 8192, 0, LP_OPTIONS}, | ||
127 | {"NAND 8GiB 1,8V 16-bit", 0xBE, 0, 8192, 0, LP_OPTIONS16}, | ||
128 | {"NAND 8GiB 3,3V 16-bit", 0xCE, 0, 8192, 0, LP_OPTIONS16}, | ||
129 | |||
130 | /* 128 Gigabit */ | ||
131 | {"NAND 16GiB 1,8V 8-bit", 0x1A, 0, 16384, 0, LP_OPTIONS}, | ||
132 | {"NAND 16GiB 3,3V 8-bit", 0x3A, 0, 16384, 0, LP_OPTIONS}, | ||
133 | {"NAND 16GiB 1,8V 16-bit", 0x2A, 0, 16384, 0, LP_OPTIONS16}, | ||
134 | {"NAND 16GiB 3,3V 16-bit", 0x4A, 0, 16384, 0, LP_OPTIONS16}, | ||
135 | |||
136 | /* 256 Gigabit */ | ||
137 | {"NAND 32GiB 1,8V 8-bit", 0x1C, 0, 32768, 0, LP_OPTIONS}, | ||
138 | {"NAND 32GiB 3,3V 8-bit", 0x3C, 0, 32768, 0, LP_OPTIONS}, | ||
139 | {"NAND 32GiB 1,8V 16-bit", 0x2C, 0, 32768, 0, LP_OPTIONS16}, | ||
140 | {"NAND 32GiB 3,3V 16-bit", 0x4C, 0, 32768, 0, LP_OPTIONS16}, | ||
141 | |||
142 | /* 512 Gigabit */ | ||
143 | {"NAND 64GiB 1,8V 8-bit", 0x1E, 0, 65536, 0, LP_OPTIONS}, | ||
144 | {"NAND 64GiB 3,3V 8-bit", 0x3E, 0, 65536, 0, LP_OPTIONS}, | ||
145 | {"NAND 64GiB 1,8V 16-bit", 0x2E, 0, 65536, 0, LP_OPTIONS16}, | ||
146 | {"NAND 64GiB 3,3V 16-bit", 0x4E, 0, 65536, 0, LP_OPTIONS16}, | ||
116 | 147 | ||
117 | /* | 148 | /* |
118 | * Renesas AND 1 Gigabit. Those chips do not support extended id and | 149 | * Renesas AND 1 Gigabit. Those chips do not support extended id and |
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index c25648bb5793..a6a73aab1253 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c | |||
@@ -107,6 +107,7 @@ static char *gravepages = NULL; | |||
107 | static unsigned int rptwear = 0; | 107 | static unsigned int rptwear = 0; |
108 | static unsigned int overridesize = 0; | 108 | static unsigned int overridesize = 0; |
109 | static char *cache_file = NULL; | 109 | static char *cache_file = NULL; |
110 | static unsigned int bbt; | ||
110 | 111 | ||
111 | module_param(first_id_byte, uint, 0400); | 112 | module_param(first_id_byte, uint, 0400); |
112 | module_param(second_id_byte, uint, 0400); | 113 | module_param(second_id_byte, uint, 0400); |
@@ -130,6 +131,7 @@ module_param(gravepages, charp, 0400); | |||
130 | module_param(rptwear, uint, 0400); | 131 | module_param(rptwear, uint, 0400); |
131 | module_param(overridesize, uint, 0400); | 132 | module_param(overridesize, uint, 0400); |
132 | module_param(cache_file, charp, 0400); | 133 | module_param(cache_file, charp, 0400); |
134 | module_param(bbt, uint, 0400); | ||
133 | 135 | ||
134 | MODULE_PARM_DESC(first_id_byte, "The first byte returned by NAND Flash 'read ID' command (manufacturer ID)"); | 136 | MODULE_PARM_DESC(first_id_byte, "The first byte returned by NAND Flash 'read ID' command (manufacturer ID)"); |
135 | MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)"); | 137 | MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)"); |
@@ -162,6 +164,7 @@ MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size overriding the I | |||
162 | "The size is specified in erase blocks and as the exponent of a power of two" | 164 | "The size is specified in erase blocks and as the exponent of a power of two" |
163 | " e.g. 5 means a size of 32 erase blocks"); | 165 | " e.g. 5 means a size of 32 erase blocks"); |
164 | MODULE_PARM_DESC(cache_file, "File to use to cache nand pages instead of memory"); | 166 | MODULE_PARM_DESC(cache_file, "File to use to cache nand pages instead of memory"); |
167 | MODULE_PARM_DESC(bbt, "0 OOB, 1 BBT with marker in OOB, 2 BBT with marker in data area"); | ||
165 | 168 | ||
166 | /* The largest possible page size */ | 169 | /* The largest possible page size */ |
167 | #define NS_LARGEST_PAGE_SIZE 4096 | 170 | #define NS_LARGEST_PAGE_SIZE 4096 |
@@ -2264,6 +2267,18 @@ static int __init ns_init_module(void) | |||
2264 | /* and 'badblocks' parameters to work */ | 2267 | /* and 'badblocks' parameters to work */ |
2265 | chip->options |= NAND_SKIP_BBTSCAN; | 2268 | chip->options |= NAND_SKIP_BBTSCAN; |
2266 | 2269 | ||
2270 | switch (bbt) { | ||
2271 | case 2: | ||
2272 | chip->options |= NAND_USE_FLASH_BBT_NO_OOB; | ||
2273 | case 1: | ||
2274 | chip->options |= NAND_USE_FLASH_BBT; | ||
2275 | case 0: | ||
2276 | break; | ||
2277 | default: | ||
2278 | NS_ERR("bbt has to be 0..2\n"); | ||
2279 | retval = -EINVAL; | ||
2280 | goto error; | ||
2281 | } | ||
2267 | /* | 2282 | /* |
2268 | * Perform minimum nandsim structure initialization to handle | 2283 | * Perform minimum nandsim structure initialization to handle |
2269 | * the initial ID read command correctly | 2284 | * the initial ID read command correctly |
@@ -2321,10 +2336,10 @@ static int __init ns_init_module(void) | |||
2321 | if ((retval = init_nandsim(nsmtd)) != 0) | 2336 | if ((retval = init_nandsim(nsmtd)) != 0) |
2322 | goto err_exit; | 2337 | goto err_exit; |
2323 | 2338 | ||
2324 | if ((retval = parse_badblocks(nand, nsmtd)) != 0) | 2339 | if ((retval = nand_default_bbt(nsmtd)) != 0) |
2325 | goto err_exit; | 2340 | goto err_exit; |
2326 | 2341 | ||
2327 | if ((retval = nand_default_bbt(nsmtd)) != 0) | 2342 | if ((retval = parse_badblocks(nand, nsmtd)) != 0) |
2328 | goto err_exit; | 2343 | goto err_exit; |
2329 | 2344 | ||
2330 | /* Register NAND partitions */ | 2345 | /* Register NAND partitions */ |
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index 510554e6c115..c9ae0a5023b6 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c | |||
@@ -229,7 +229,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev, | |||
229 | const struct of_device_id *match) | 229 | const struct of_device_id *match) |
230 | { | 230 | { |
231 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 231 | struct ndfc_controller *ndfc = &ndfc_ctrl; |
232 | const u32 *reg; | 232 | const __be32 *reg; |
233 | u32 ccr; | 233 | u32 ccr; |
234 | int err, len; | 234 | int err, len; |
235 | 235 | ||
@@ -244,7 +244,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev, | |||
244 | dev_err(&ofdev->dev, "unable read reg property (%d)\n", len); | 244 | dev_err(&ofdev->dev, "unable read reg property (%d)\n", len); |
245 | return -ENOENT; | 245 | return -ENOENT; |
246 | } | 246 | } |
247 | ndfc->chip_select = reg[0]; | 247 | ndfc->chip_select = be32_to_cpu(reg[0]); |
248 | 248 | ||
249 | ndfc->ndfcbase = of_iomap(ofdev->dev.of_node, 0); | 249 | ndfc->ndfcbase = of_iomap(ofdev->dev.of_node, 0); |
250 | if (!ndfc->ndfcbase) { | 250 | if (!ndfc->ndfcbase) { |
@@ -257,7 +257,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev, | |||
257 | /* It is ok if ccr does not exist - just default to 0 */ | 257 | /* It is ok if ccr does not exist - just default to 0 */ |
258 | reg = of_get_property(ofdev->dev.of_node, "ccr", NULL); | 258 | reg = of_get_property(ofdev->dev.of_node, "ccr", NULL); |
259 | if (reg) | 259 | if (reg) |
260 | ccr |= *reg; | 260 | ccr |= be32_to_cpup(reg); |
261 | 261 | ||
262 | out_be32(ndfc->ndfcbase + NDFC_CCR, ccr); | 262 | out_be32(ndfc->ndfcbase + NDFC_CCR, ccr); |
263 | 263 | ||
@@ -265,7 +265,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev, | |||
265 | reg = of_get_property(ofdev->dev.of_node, "bank-settings", NULL); | 265 | reg = of_get_property(ofdev->dev.of_node, "bank-settings", NULL); |
266 | if (reg) { | 266 | if (reg) { |
267 | int offset = NDFC_BCFG0 + (ndfc->chip_select << 2); | 267 | int offset = NDFC_BCFG0 + (ndfc->chip_select << 2); |
268 | out_be32(ndfc->ndfcbase + offset, *reg); | 268 | out_be32(ndfc->ndfcbase + offset, be32_to_cpup(reg)); |
269 | } | 269 | } |
270 | 270 | ||
271 | err = ndfc_chip_init(ndfc, ofdev->dev.of_node); | 271 | err = ndfc_chip_init(ndfc, ofdev->dev.of_node); |
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 513e0a76a4a7..cd41c58b5bbd 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c | |||
@@ -111,11 +111,11 @@ static int use_dma = 1; | |||
111 | module_param(use_dma, bool, 0); | 111 | module_param(use_dma, bool, 0); |
112 | MODULE_PARM_DESC(use_dma, "enable/disable use of DMA"); | 112 | MODULE_PARM_DESC(use_dma, "enable/disable use of DMA"); |
113 | #else | 113 | #else |
114 | const int use_dma; | 114 | static const int use_dma; |
115 | #endif | 115 | #endif |
116 | #else | 116 | #else |
117 | const int use_prefetch; | 117 | const int use_prefetch; |
118 | const int use_dma; | 118 | static const int use_dma; |
119 | #endif | 119 | #endif |
120 | 120 | ||
121 | struct omap_nand_info { | 121 | struct omap_nand_info { |
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 4d01cda68844..17f8518cc5eb 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
@@ -117,7 +117,7 @@ struct pxa3xx_nand_info { | |||
117 | struct nand_chip nand_chip; | 117 | struct nand_chip nand_chip; |
118 | 118 | ||
119 | struct platform_device *pdev; | 119 | struct platform_device *pdev; |
120 | const struct pxa3xx_nand_flash *flash_info; | 120 | struct pxa3xx_nand_cmdset *cmdset; |
121 | 121 | ||
122 | struct clk *clk; | 122 | struct clk *clk; |
123 | void __iomem *mmio_base; | 123 | void __iomem *mmio_base; |
@@ -131,6 +131,7 @@ struct pxa3xx_nand_info { | |||
131 | int drcmr_cmd; | 131 | int drcmr_cmd; |
132 | 132 | ||
133 | unsigned char *data_buff; | 133 | unsigned char *data_buff; |
134 | unsigned char *oob_buff; | ||
134 | dma_addr_t data_buff_phys; | 135 | dma_addr_t data_buff_phys; |
135 | size_t data_buff_size; | 136 | size_t data_buff_size; |
136 | int data_dma_ch; | 137 | int data_dma_ch; |
@@ -149,7 +150,8 @@ struct pxa3xx_nand_info { | |||
149 | int use_ecc; /* use HW ECC ? */ | 150 | int use_ecc; /* use HW ECC ? */ |
150 | int use_dma; /* use DMA ? */ | 151 | int use_dma; /* use DMA ? */ |
151 | 152 | ||
152 | size_t data_size; /* data size in FIFO */ | 153 | unsigned int page_size; /* page size of attached chip */ |
154 | unsigned int data_size; /* data size in FIFO */ | ||
153 | int retcode; | 155 | int retcode; |
154 | struct completion cmd_complete; | 156 | struct completion cmd_complete; |
155 | 157 | ||
@@ -158,6 +160,10 @@ struct pxa3xx_nand_info { | |||
158 | uint32_t ndcb1; | 160 | uint32_t ndcb1; |
159 | uint32_t ndcb2; | 161 | uint32_t ndcb2; |
160 | 162 | ||
163 | /* timing calcuted from setting */ | ||
164 | uint32_t ndtr0cs0; | ||
165 | uint32_t ndtr1cs0; | ||
166 | |||
161 | /* calculated from pxa3xx_nand_flash data */ | 167 | /* calculated from pxa3xx_nand_flash data */ |
162 | size_t oob_size; | 168 | size_t oob_size; |
163 | size_t read_id_bytes; | 169 | size_t read_id_bytes; |
@@ -174,23 +180,7 @@ MODULE_PARM_DESC(use_dma, "enable DMA for data transfering to/from NAND HW"); | |||
174 | * Default NAND flash controller configuration setup by the | 180 | * Default NAND flash controller configuration setup by the |
175 | * bootloader. This configuration is used only when pdata->keep_config is set | 181 | * bootloader. This configuration is used only when pdata->keep_config is set |
176 | */ | 182 | */ |
177 | static struct pxa3xx_nand_timing default_timing; | 183 | static struct pxa3xx_nand_cmdset default_cmdset = { |
178 | static struct pxa3xx_nand_flash default_flash; | ||
179 | |||
180 | static struct pxa3xx_nand_cmdset smallpage_cmdset = { | ||
181 | .read1 = 0x0000, | ||
182 | .read2 = 0x0050, | ||
183 | .program = 0x1080, | ||
184 | .read_status = 0x0070, | ||
185 | .read_id = 0x0090, | ||
186 | .erase = 0xD060, | ||
187 | .reset = 0x00FF, | ||
188 | .lock = 0x002A, | ||
189 | .unlock = 0x2423, | ||
190 | .lock_status = 0x007A, | ||
191 | }; | ||
192 | |||
193 | static struct pxa3xx_nand_cmdset largepage_cmdset = { | ||
194 | .read1 = 0x3000, | 184 | .read1 = 0x3000, |
195 | .read2 = 0x0050, | 185 | .read2 = 0x0050, |
196 | .program = 0x1080, | 186 | .program = 0x1080, |
@@ -203,142 +193,27 @@ static struct pxa3xx_nand_cmdset largepage_cmdset = { | |||
203 | .lock_status = 0x007A, | 193 | .lock_status = 0x007A, |
204 | }; | 194 | }; |
205 | 195 | ||
206 | #ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN | 196 | static struct pxa3xx_nand_timing timing[] = { |
207 | static struct pxa3xx_nand_timing samsung512MbX16_timing = { | 197 | { 40, 80, 60, 100, 80, 100, 90000, 400, 40, }, |
208 | .tCH = 10, | 198 | { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, |
209 | .tCS = 0, | 199 | { 10, 25, 15, 25, 15, 30, 25000, 60, 10, }, |
210 | .tWH = 20, | 200 | { 10, 35, 15, 25, 15, 25, 25000, 60, 10, }, |
211 | .tWP = 40, | ||
212 | .tRH = 30, | ||
213 | .tRP = 40, | ||
214 | .tR = 11123, | ||
215 | .tWHR = 110, | ||
216 | .tAR = 10, | ||
217 | }; | ||
218 | |||
219 | static struct pxa3xx_nand_flash samsung512MbX16 = { | ||
220 | .timing = &samsung512MbX16_timing, | ||
221 | .cmdset = &smallpage_cmdset, | ||
222 | .page_per_block = 32, | ||
223 | .page_size = 512, | ||
224 | .flash_width = 16, | ||
225 | .dfc_width = 16, | ||
226 | .num_blocks = 4096, | ||
227 | .chip_id = 0x46ec, | ||
228 | }; | ||
229 | |||
230 | static struct pxa3xx_nand_flash samsung2GbX8 = { | ||
231 | .timing = &samsung512MbX16_timing, | ||
232 | .cmdset = &smallpage_cmdset, | ||
233 | .page_per_block = 64, | ||
234 | .page_size = 2048, | ||
235 | .flash_width = 8, | ||
236 | .dfc_width = 8, | ||
237 | .num_blocks = 2048, | ||
238 | .chip_id = 0xdaec, | ||
239 | }; | 201 | }; |
240 | 202 | ||
241 | static struct pxa3xx_nand_flash samsung32GbX8 = { | 203 | static struct pxa3xx_nand_flash builtin_flash_types[] = { |
242 | .timing = &samsung512MbX16_timing, | 204 | { 0, 0, 2048, 8, 8, 0, &default_cmdset, &timing[0] }, |
243 | .cmdset = &smallpage_cmdset, | 205 | { 0x46ec, 32, 512, 16, 16, 4096, &default_cmdset, &timing[1] }, |
244 | .page_per_block = 128, | 206 | { 0xdaec, 64, 2048, 8, 8, 2048, &default_cmdset, &timing[1] }, |
245 | .page_size = 4096, | 207 | { 0xd7ec, 128, 4096, 8, 8, 8192, &default_cmdset, &timing[1] }, |
246 | .flash_width = 8, | 208 | { 0xa12c, 64, 2048, 8, 8, 1024, &default_cmdset, &timing[2] }, |
247 | .dfc_width = 8, | 209 | { 0xb12c, 64, 2048, 16, 16, 1024, &default_cmdset, &timing[2] }, |
248 | .num_blocks = 8192, | 210 | { 0xdc2c, 64, 2048, 8, 8, 4096, &default_cmdset, &timing[2] }, |
249 | .chip_id = 0xd7ec, | 211 | { 0xcc2c, 64, 2048, 16, 16, 4096, &default_cmdset, &timing[2] }, |
212 | { 0xba20, 64, 2048, 16, 16, 2048, &default_cmdset, &timing[3] }, | ||
250 | }; | 213 | }; |
251 | 214 | ||
252 | static struct pxa3xx_nand_timing micron_timing = { | 215 | /* Define a default flash type setting serve as flash detecting only */ |
253 | .tCH = 10, | 216 | #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0]) |
254 | .tCS = 25, | ||
255 | .tWH = 15, | ||
256 | .tWP = 25, | ||
257 | .tRH = 15, | ||
258 | .tRP = 30, | ||
259 | .tR = 25000, | ||
260 | .tWHR = 60, | ||
261 | .tAR = 10, | ||
262 | }; | ||
263 | |||
264 | static struct pxa3xx_nand_flash micron1GbX8 = { | ||
265 | .timing = µn_timing, | ||
266 | .cmdset = &largepage_cmdset, | ||
267 | .page_per_block = 64, | ||
268 | .page_size = 2048, | ||
269 | .flash_width = 8, | ||
270 | .dfc_width = 8, | ||
271 | .num_blocks = 1024, | ||
272 | .chip_id = 0xa12c, | ||
273 | }; | ||
274 | |||
275 | static struct pxa3xx_nand_flash micron1GbX16 = { | ||
276 | .timing = µn_timing, | ||
277 | .cmdset = &largepage_cmdset, | ||
278 | .page_per_block = 64, | ||
279 | .page_size = 2048, | ||
280 | .flash_width = 16, | ||
281 | .dfc_width = 16, | ||
282 | .num_blocks = 1024, | ||
283 | .chip_id = 0xb12c, | ||
284 | }; | ||
285 | |||
286 | static struct pxa3xx_nand_flash micron4GbX8 = { | ||
287 | .timing = µn_timing, | ||
288 | .cmdset = &largepage_cmdset, | ||
289 | .page_per_block = 64, | ||
290 | .page_size = 2048, | ||
291 | .flash_width = 8, | ||
292 | .dfc_width = 8, | ||
293 | .num_blocks = 4096, | ||
294 | .chip_id = 0xdc2c, | ||
295 | }; | ||
296 | |||
297 | static struct pxa3xx_nand_flash micron4GbX16 = { | ||
298 | .timing = µn_timing, | ||
299 | .cmdset = &largepage_cmdset, | ||
300 | .page_per_block = 64, | ||
301 | .page_size = 2048, | ||
302 | .flash_width = 16, | ||
303 | .dfc_width = 16, | ||
304 | .num_blocks = 4096, | ||
305 | .chip_id = 0xcc2c, | ||
306 | }; | ||
307 | |||
308 | static struct pxa3xx_nand_timing stm2GbX16_timing = { | ||
309 | .tCH = 10, | ||
310 | .tCS = 35, | ||
311 | .tWH = 15, | ||
312 | .tWP = 25, | ||
313 | .tRH = 15, | ||
314 | .tRP = 25, | ||
315 | .tR = 25000, | ||
316 | .tWHR = 60, | ||
317 | .tAR = 10, | ||
318 | }; | ||
319 | |||
320 | static struct pxa3xx_nand_flash stm2GbX16 = { | ||
321 | .timing = &stm2GbX16_timing, | ||
322 | .cmdset = &largepage_cmdset, | ||
323 | .page_per_block = 64, | ||
324 | .page_size = 2048, | ||
325 | .flash_width = 16, | ||
326 | .dfc_width = 16, | ||
327 | .num_blocks = 2048, | ||
328 | .chip_id = 0xba20, | ||
329 | }; | ||
330 | |||
331 | static struct pxa3xx_nand_flash *builtin_flash_types[] = { | ||
332 | &samsung512MbX16, | ||
333 | &samsung2GbX8, | ||
334 | &samsung32GbX8, | ||
335 | µn1GbX8, | ||
336 | µn1GbX16, | ||
337 | µn4GbX8, | ||
338 | µn4GbX16, | ||
339 | &stm2GbX16, | ||
340 | }; | ||
341 | #endif /* CONFIG_MTD_NAND_PXA3xx_BUILTIN */ | ||
342 | 217 | ||
343 | #define NDTR0_tCH(c) (min((c), 7) << 19) | 218 | #define NDTR0_tCH(c) (min((c), 7) << 19) |
344 | #define NDTR0_tCS(c) (min((c), 7) << 16) | 219 | #define NDTR0_tCS(c) (min((c), 7) << 16) |
@@ -351,23 +226,9 @@ static struct pxa3xx_nand_flash *builtin_flash_types[] = { | |||
351 | #define NDTR1_tWHR(c) (min((c), 15) << 4) | 226 | #define NDTR1_tWHR(c) (min((c), 15) << 4) |
352 | #define NDTR1_tAR(c) (min((c), 15) << 0) | 227 | #define NDTR1_tAR(c) (min((c), 15) << 0) |
353 | 228 | ||
354 | #define tCH_NDTR0(r) (((r) >> 19) & 0x7) | ||
355 | #define tCS_NDTR0(r) (((r) >> 16) & 0x7) | ||
356 | #define tWH_NDTR0(r) (((r) >> 11) & 0x7) | ||
357 | #define tWP_NDTR0(r) (((r) >> 8) & 0x7) | ||
358 | #define tRH_NDTR0(r) (((r) >> 3) & 0x7) | ||
359 | #define tRP_NDTR0(r) (((r) >> 0) & 0x7) | ||
360 | |||
361 | #define tR_NDTR1(r) (((r) >> 16) & 0xffff) | ||
362 | #define tWHR_NDTR1(r) (((r) >> 4) & 0xf) | ||
363 | #define tAR_NDTR1(r) (((r) >> 0) & 0xf) | ||
364 | |||
365 | /* convert nano-seconds to nand flash controller clock cycles */ | 229 | /* convert nano-seconds to nand flash controller clock cycles */ |
366 | #define ns2cycle(ns, clk) (int)((ns) * (clk / 1000000) / 1000) | 230 | #define ns2cycle(ns, clk) (int)((ns) * (clk / 1000000) / 1000) |
367 | 231 | ||
368 | /* convert nand flash controller clock cycles to nano-seconds */ | ||
369 | #define cycle2ns(c, clk) ((((c) + 1) * 1000000 + clk / 500) / (clk / 1000)) | ||
370 | |||
371 | static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, | 232 | static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, |
372 | const struct pxa3xx_nand_timing *t) | 233 | const struct pxa3xx_nand_timing *t) |
373 | { | 234 | { |
@@ -385,6 +246,8 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, | |||
385 | NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) | | 246 | NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) | |
386 | NDTR1_tAR(ns2cycle(t->tAR, nand_clk)); | 247 | NDTR1_tAR(ns2cycle(t->tAR, nand_clk)); |
387 | 248 | ||
249 | info->ndtr0cs0 = ndtr0; | ||
250 | info->ndtr1cs0 = ndtr1; | ||
388 | nand_writel(info, NDTR0CS0, ndtr0); | 251 | nand_writel(info, NDTR0CS0, ndtr0); |
389 | nand_writel(info, NDTR1CS0, ndtr1); | 252 | nand_writel(info, NDTR1CS0, ndtr1); |
390 | } | 253 | } |
@@ -408,23 +271,31 @@ static int wait_for_event(struct pxa3xx_nand_info *info, uint32_t event) | |||
408 | return -ETIMEDOUT; | 271 | return -ETIMEDOUT; |
409 | } | 272 | } |
410 | 273 | ||
411 | static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info, | 274 | static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) |
412 | uint16_t cmd, int column, int page_addr) | ||
413 | { | 275 | { |
414 | const struct pxa3xx_nand_flash *f = info->flash_info; | 276 | int oob_enable = info->reg_ndcr & NDCR_SPARE_EN; |
415 | const struct pxa3xx_nand_cmdset *cmdset = f->cmdset; | ||
416 | 277 | ||
417 | /* calculate data size */ | 278 | info->data_size = info->page_size; |
418 | switch (f->page_size) { | 279 | if (!oob_enable) { |
280 | info->oob_size = 0; | ||
281 | return; | ||
282 | } | ||
283 | |||
284 | switch (info->page_size) { | ||
419 | case 2048: | 285 | case 2048: |
420 | info->data_size = (info->use_ecc) ? 2088 : 2112; | 286 | info->oob_size = (info->use_ecc) ? 40 : 64; |
421 | break; | 287 | break; |
422 | case 512: | 288 | case 512: |
423 | info->data_size = (info->use_ecc) ? 520 : 528; | 289 | info->oob_size = (info->use_ecc) ? 8 : 16; |
424 | break; | 290 | break; |
425 | default: | ||
426 | return -EINVAL; | ||
427 | } | 291 | } |
292 | } | ||
293 | |||
294 | static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info, | ||
295 | uint16_t cmd, int column, int page_addr) | ||
296 | { | ||
297 | const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; | ||
298 | pxa3xx_set_datasize(info); | ||
428 | 299 | ||
429 | /* generate values for NDCBx registers */ | 300 | /* generate values for NDCBx registers */ |
430 | info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); | 301 | info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); |
@@ -463,12 +334,13 @@ static int prepare_erase_cmd(struct pxa3xx_nand_info *info, | |||
463 | 334 | ||
464 | static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) | 335 | static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) |
465 | { | 336 | { |
466 | const struct pxa3xx_nand_cmdset *cmdset = info->flash_info->cmdset; | 337 | const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; |
467 | 338 | ||
468 | info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); | 339 | info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); |
469 | info->ndcb1 = 0; | 340 | info->ndcb1 = 0; |
470 | info->ndcb2 = 0; | 341 | info->ndcb2 = 0; |
471 | 342 | ||
343 | info->oob_size = 0; | ||
472 | if (cmd == cmdset->read_id) { | 344 | if (cmd == cmdset->read_id) { |
473 | info->ndcb0 |= NDCB0_CMD_TYPE(3); | 345 | info->ndcb0 |= NDCB0_CMD_TYPE(3); |
474 | info->data_size = 8; | 346 | info->data_size = 8; |
@@ -537,6 +409,9 @@ static int handle_data_pio(struct pxa3xx_nand_info *info) | |||
537 | case STATE_PIO_WRITING: | 409 | case STATE_PIO_WRITING: |
538 | __raw_writesl(info->mmio_base + NDDB, info->data_buff, | 410 | __raw_writesl(info->mmio_base + NDDB, info->data_buff, |
539 | DIV_ROUND_UP(info->data_size, 4)); | 411 | DIV_ROUND_UP(info->data_size, 4)); |
412 | if (info->oob_size > 0) | ||
413 | __raw_writesl(info->mmio_base + NDDB, info->oob_buff, | ||
414 | DIV_ROUND_UP(info->oob_size, 4)); | ||
540 | 415 | ||
541 | enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); | 416 | enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); |
542 | 417 | ||
@@ -549,6 +424,9 @@ static int handle_data_pio(struct pxa3xx_nand_info *info) | |||
549 | case STATE_PIO_READING: | 424 | case STATE_PIO_READING: |
550 | __raw_readsl(info->mmio_base + NDDB, info->data_buff, | 425 | __raw_readsl(info->mmio_base + NDDB, info->data_buff, |
551 | DIV_ROUND_UP(info->data_size, 4)); | 426 | DIV_ROUND_UP(info->data_size, 4)); |
427 | if (info->oob_size > 0) | ||
428 | __raw_readsl(info->mmio_base + NDDB, info->oob_buff, | ||
429 | DIV_ROUND_UP(info->oob_size, 4)); | ||
552 | break; | 430 | break; |
553 | default: | 431 | default: |
554 | printk(KERN_ERR "%s: invalid state %d\n", __func__, | 432 | printk(KERN_ERR "%s: invalid state %d\n", __func__, |
@@ -563,7 +441,7 @@ static int handle_data_pio(struct pxa3xx_nand_info *info) | |||
563 | static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out) | 441 | static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out) |
564 | { | 442 | { |
565 | struct pxa_dma_desc *desc = info->data_desc; | 443 | struct pxa_dma_desc *desc = info->data_desc; |
566 | int dma_len = ALIGN(info->data_size, 32); | 444 | int dma_len = ALIGN(info->data_size + info->oob_size, 32); |
567 | 445 | ||
568 | desc->ddadr = DDADR_STOP; | 446 | desc->ddadr = DDADR_STOP; |
569 | desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len; | 447 | desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len; |
@@ -700,8 +578,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
700 | int column, int page_addr) | 578 | int column, int page_addr) |
701 | { | 579 | { |
702 | struct pxa3xx_nand_info *info = mtd->priv; | 580 | struct pxa3xx_nand_info *info = mtd->priv; |
703 | const struct pxa3xx_nand_flash *flash_info = info->flash_info; | 581 | const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; |
704 | const struct pxa3xx_nand_cmdset *cmdset = flash_info->cmdset; | ||
705 | int ret; | 582 | int ret; |
706 | 583 | ||
707 | info->use_dma = (use_dma) ? 1 : 0; | 584 | info->use_dma = (use_dma) ? 1 : 0; |
@@ -925,8 +802,7 @@ static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd, | |||
925 | 802 | ||
926 | static int __readid(struct pxa3xx_nand_info *info, uint32_t *id) | 803 | static int __readid(struct pxa3xx_nand_info *info, uint32_t *id) |
927 | { | 804 | { |
928 | const struct pxa3xx_nand_flash *f = info->flash_info; | 805 | const struct pxa3xx_nand_cmdset *cmdset = info->cmdset; |
929 | const struct pxa3xx_nand_cmdset *cmdset = f->cmdset; | ||
930 | uint32_t ndcr; | 806 | uint32_t ndcr; |
931 | uint8_t id_buff[8]; | 807 | uint8_t id_buff[8]; |
932 | 808 | ||
@@ -968,7 +844,9 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, | |||
968 | return -EINVAL; | 844 | return -EINVAL; |
969 | 845 | ||
970 | /* calculate flash information */ | 846 | /* calculate flash information */ |
971 | info->oob_size = (f->page_size == 2048) ? 64 : 16; | 847 | info->cmdset = f->cmdset; |
848 | info->page_size = f->page_size; | ||
849 | info->oob_buff = info->data_buff + f->page_size; | ||
972 | info->read_id_bytes = (f->page_size == 2048) ? 4 : 2; | 850 | info->read_id_bytes = (f->page_size == 2048) ? 4 : 2; |
973 | 851 | ||
974 | /* calculate addressing information */ | 852 | /* calculate addressing information */ |
@@ -992,49 +870,20 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, | |||
992 | info->reg_ndcr = ndcr; | 870 | info->reg_ndcr = ndcr; |
993 | 871 | ||
994 | pxa3xx_nand_set_timing(info, f->timing); | 872 | pxa3xx_nand_set_timing(info, f->timing); |
995 | info->flash_info = f; | ||
996 | return 0; | 873 | return 0; |
997 | } | 874 | } |
998 | 875 | ||
999 | static void pxa3xx_nand_detect_timing(struct pxa3xx_nand_info *info, | ||
1000 | struct pxa3xx_nand_timing *t) | ||
1001 | { | ||
1002 | unsigned long nand_clk = clk_get_rate(info->clk); | ||
1003 | uint32_t ndtr0 = nand_readl(info, NDTR0CS0); | ||
1004 | uint32_t ndtr1 = nand_readl(info, NDTR1CS0); | ||
1005 | |||
1006 | t->tCH = cycle2ns(tCH_NDTR0(ndtr0), nand_clk); | ||
1007 | t->tCS = cycle2ns(tCS_NDTR0(ndtr0), nand_clk); | ||
1008 | t->tWH = cycle2ns(tWH_NDTR0(ndtr0), nand_clk); | ||
1009 | t->tWP = cycle2ns(tWP_NDTR0(ndtr0), nand_clk); | ||
1010 | t->tRH = cycle2ns(tRH_NDTR0(ndtr0), nand_clk); | ||
1011 | t->tRP = cycle2ns(tRP_NDTR0(ndtr0), nand_clk); | ||
1012 | |||
1013 | t->tR = cycle2ns(tR_NDTR1(ndtr1), nand_clk); | ||
1014 | t->tWHR = cycle2ns(tWHR_NDTR1(ndtr1), nand_clk); | ||
1015 | t->tAR = cycle2ns(tAR_NDTR1(ndtr1), nand_clk); | ||
1016 | } | ||
1017 | |||
1018 | static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) | 876 | static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) |
1019 | { | 877 | { |
1020 | uint32_t ndcr = nand_readl(info, NDCR); | 878 | uint32_t ndcr = nand_readl(info, NDCR); |
1021 | struct nand_flash_dev *type = NULL; | 879 | struct nand_flash_dev *type = NULL; |
1022 | uint32_t id = -1; | 880 | uint32_t id = -1, page_per_block, num_blocks; |
1023 | int i; | 881 | int i; |
1024 | 882 | ||
1025 | default_flash.page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32; | 883 | page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32; |
1026 | default_flash.page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512; | 884 | info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512; |
1027 | default_flash.flash_width = ndcr & NDCR_DWIDTH_M ? 16 : 8; | ||
1028 | default_flash.dfc_width = ndcr & NDCR_DWIDTH_C ? 16 : 8; | ||
1029 | |||
1030 | if (default_flash.page_size == 2048) | ||
1031 | default_flash.cmdset = &largepage_cmdset; | ||
1032 | else | ||
1033 | default_flash.cmdset = &smallpage_cmdset; | ||
1034 | |||
1035 | /* set info fields needed to __readid */ | 885 | /* set info fields needed to __readid */ |
1036 | info->flash_info = &default_flash; | 886 | info->read_id_bytes = (info->page_size == 2048) ? 4 : 2; |
1037 | info->read_id_bytes = (default_flash.page_size == 2048) ? 4 : 2; | ||
1038 | info->reg_ndcr = ndcr; | 887 | info->reg_ndcr = ndcr; |
1039 | 888 | ||
1040 | if (__readid(info, &id)) | 889 | if (__readid(info, &id)) |
@@ -1053,21 +902,20 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) | |||
1053 | return -ENODEV; | 902 | return -ENODEV; |
1054 | 903 | ||
1055 | /* fill the missing flash information */ | 904 | /* fill the missing flash information */ |
1056 | i = __ffs(default_flash.page_per_block * default_flash.page_size); | 905 | i = __ffs(page_per_block * info->page_size); |
1057 | default_flash.num_blocks = type->chipsize << (20 - i); | 906 | num_blocks = type->chipsize << (20 - i); |
1058 | |||
1059 | info->oob_size = (default_flash.page_size == 2048) ? 64 : 16; | ||
1060 | 907 | ||
1061 | /* calculate addressing information */ | 908 | /* calculate addressing information */ |
1062 | info->col_addr_cycles = (default_flash.page_size == 2048) ? 2 : 1; | 909 | info->col_addr_cycles = (info->page_size == 2048) ? 2 : 1; |
1063 | 910 | ||
1064 | if (default_flash.num_blocks * default_flash.page_per_block > 65536) | 911 | if (num_blocks * page_per_block > 65536) |
1065 | info->row_addr_cycles = 3; | 912 | info->row_addr_cycles = 3; |
1066 | else | 913 | else |
1067 | info->row_addr_cycles = 2; | 914 | info->row_addr_cycles = 2; |
1068 | 915 | ||
1069 | pxa3xx_nand_detect_timing(info, &default_timing); | 916 | info->ndtr0cs0 = nand_readl(info, NDTR0CS0); |
1070 | default_flash.timing = &default_timing; | 917 | info->ndtr1cs0 = nand_readl(info, NDTR1CS0); |
918 | info->cmdset = &default_cmdset; | ||
1071 | 919 | ||
1072 | return 0; | 920 | return 0; |
1073 | } | 921 | } |
@@ -1083,38 +931,29 @@ static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info, | |||
1083 | if (pxa3xx_nand_detect_config(info) == 0) | 931 | if (pxa3xx_nand_detect_config(info) == 0) |
1084 | return 0; | 932 | return 0; |
1085 | 933 | ||
1086 | for (i = 0; i<pdata->num_flash; ++i) { | 934 | /* we use default timing to detect id */ |
1087 | f = pdata->flash + i; | 935 | f = DEFAULT_FLASH_TYPE; |
1088 | 936 | pxa3xx_nand_config_flash(info, f); | |
1089 | if (pxa3xx_nand_config_flash(info, f)) | 937 | if (__readid(info, &id)) |
1090 | continue; | 938 | goto fail_detect; |
1091 | 939 | ||
1092 | if (__readid(info, &id)) | 940 | for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) { |
1093 | continue; | 941 | /* we first choose the flash definition from platfrom */ |
1094 | 942 | if (i < pdata->num_flash) | |
1095 | if (id == f->chip_id) | 943 | f = pdata->flash + i; |
1096 | return 0; | 944 | else |
1097 | } | 945 | f = &builtin_flash_types[i - pdata->num_flash + 1]; |
1098 | 946 | if (f->chip_id == id) { | |
1099 | #ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN | 947 | dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id); |
1100 | for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) { | 948 | pxa3xx_nand_config_flash(info, f); |
1101 | |||
1102 | f = builtin_flash_types[i]; | ||
1103 | |||
1104 | if (pxa3xx_nand_config_flash(info, f)) | ||
1105 | continue; | ||
1106 | |||
1107 | if (__readid(info, &id)) | ||
1108 | continue; | ||
1109 | |||
1110 | if (id == f->chip_id) | ||
1111 | return 0; | 949 | return 0; |
950 | } | ||
1112 | } | 951 | } |
1113 | #endif | ||
1114 | 952 | ||
1115 | dev_warn(&info->pdev->dev, | 953 | dev_warn(&info->pdev->dev, |
1116 | "failed to detect configured nand flash; found %04x instead of\n", | 954 | "failed to detect configured nand flash; found %04x instead of\n", |
1117 | id); | 955 | id); |
956 | fail_detect: | ||
1118 | return -ENODEV; | 957 | return -ENODEV; |
1119 | } | 958 | } |
1120 | 959 | ||
@@ -1177,10 +1016,9 @@ static struct nand_ecclayout hw_largepage_ecclayout = { | |||
1177 | static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, | 1016 | static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, |
1178 | struct pxa3xx_nand_info *info) | 1017 | struct pxa3xx_nand_info *info) |
1179 | { | 1018 | { |
1180 | const struct pxa3xx_nand_flash *f = info->flash_info; | ||
1181 | struct nand_chip *this = &info->nand_chip; | 1019 | struct nand_chip *this = &info->nand_chip; |
1182 | 1020 | ||
1183 | this->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0; | 1021 | this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0; |
1184 | 1022 | ||
1185 | this->waitfunc = pxa3xx_nand_waitfunc; | 1023 | this->waitfunc = pxa3xx_nand_waitfunc; |
1186 | this->select_chip = pxa3xx_nand_select_chip; | 1024 | this->select_chip = pxa3xx_nand_select_chip; |
@@ -1196,9 +1034,9 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, | |||
1196 | this->ecc.hwctl = pxa3xx_nand_ecc_hwctl; | 1034 | this->ecc.hwctl = pxa3xx_nand_ecc_hwctl; |
1197 | this->ecc.calculate = pxa3xx_nand_ecc_calculate; | 1035 | this->ecc.calculate = pxa3xx_nand_ecc_calculate; |
1198 | this->ecc.correct = pxa3xx_nand_ecc_correct; | 1036 | this->ecc.correct = pxa3xx_nand_ecc_correct; |
1199 | this->ecc.size = f->page_size; | 1037 | this->ecc.size = info->page_size; |
1200 | 1038 | ||
1201 | if (f->page_size == 2048) | 1039 | if (info->page_size == 2048) |
1202 | this->ecc.layout = &hw_largepage_ecclayout; | 1040 | this->ecc.layout = &hw_largepage_ecclayout; |
1203 | else | 1041 | else |
1204 | this->ecc.layout = &hw_smallpage_ecclayout; | 1042 | this->ecc.layout = &hw_smallpage_ecclayout; |
@@ -1411,9 +1249,11 @@ static int pxa3xx_nand_resume(struct platform_device *pdev) | |||
1411 | struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev); | 1249 | struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev); |
1412 | struct pxa3xx_nand_info *info = mtd->priv; | 1250 | struct pxa3xx_nand_info *info = mtd->priv; |
1413 | 1251 | ||
1252 | nand_writel(info, NDTR0CS0, info->ndtr0cs0); | ||
1253 | nand_writel(info, NDTR1CS0, info->ndtr1cs0); | ||
1414 | clk_enable(info->clk); | 1254 | clk_enable(info->clk); |
1415 | 1255 | ||
1416 | return pxa3xx_nand_config_flash(info, info->flash_info); | 1256 | return 0; |
1417 | } | 1257 | } |
1418 | #else | 1258 | #else |
1419 | #define pxa3xx_nand_suspend NULL | 1259 | #define pxa3xx_nand_suspend NULL |
diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index 5169ca6a66bc..d9d7efbc77cc 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c | |||
@@ -757,11 +757,6 @@ static irqreturn_t r852_irq(int irq, void *data) | |||
757 | 757 | ||
758 | spin_lock_irqsave(&dev->irqlock, flags); | 758 | spin_lock_irqsave(&dev->irqlock, flags); |
759 | 759 | ||
760 | /* We can recieve shared interrupt while pci is suspended | ||
761 | in that case reads will return 0xFFFFFFFF.... */ | ||
762 | if (dev->insuspend) | ||
763 | goto out; | ||
764 | |||
765 | /* handle card detection interrupts first */ | 760 | /* handle card detection interrupts first */ |
766 | card_status = r852_read_reg(dev, R852_CARD_IRQ_STA); | 761 | card_status = r852_read_reg(dev, R852_CARD_IRQ_STA); |
767 | r852_write_reg(dev, R852_CARD_IRQ_STA, card_status); | 762 | r852_write_reg(dev, R852_CARD_IRQ_STA, card_status); |
@@ -1035,7 +1030,6 @@ void r852_shutdown(struct pci_dev *pci_dev) | |||
1035 | int r852_suspend(struct device *device) | 1030 | int r852_suspend(struct device *device) |
1036 | { | 1031 | { |
1037 | struct r852_device *dev = pci_get_drvdata(to_pci_dev(device)); | 1032 | struct r852_device *dev = pci_get_drvdata(to_pci_dev(device)); |
1038 | unsigned long flags; | ||
1039 | 1033 | ||
1040 | if (dev->ctlreg & R852_CTL_CARDENABLE) | 1034 | if (dev->ctlreg & R852_CTL_CARDENABLE) |
1041 | return -EBUSY; | 1035 | return -EBUSY; |
@@ -1047,43 +1041,22 @@ int r852_suspend(struct device *device) | |||
1047 | r852_disable_irqs(dev); | 1041 | r852_disable_irqs(dev); |
1048 | r852_engine_disable(dev); | 1042 | r852_engine_disable(dev); |
1049 | 1043 | ||
1050 | spin_lock_irqsave(&dev->irqlock, flags); | ||
1051 | dev->insuspend = 1; | ||
1052 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1053 | |||
1054 | /* At that point, even if interrupt handler is running, it will quit */ | ||
1055 | /* So wait for this to happen explictly */ | ||
1056 | synchronize_irq(dev->irq); | ||
1057 | |||
1058 | /* If card was pulled off just during the suspend, which is very | 1044 | /* If card was pulled off just during the suspend, which is very |
1059 | unlikely, we will remove it on resume, it too late now | 1045 | unlikely, we will remove it on resume, it too late now |
1060 | anyway... */ | 1046 | anyway... */ |
1061 | dev->card_unstable = 0; | 1047 | dev->card_unstable = 0; |
1062 | 1048 | return 0; | |
1063 | pci_save_state(to_pci_dev(device)); | ||
1064 | return pci_prepare_to_sleep(to_pci_dev(device)); | ||
1065 | } | 1049 | } |
1066 | 1050 | ||
1067 | int r852_resume(struct device *device) | 1051 | int r852_resume(struct device *device) |
1068 | { | 1052 | { |
1069 | struct r852_device *dev = pci_get_drvdata(to_pci_dev(device)); | 1053 | struct r852_device *dev = pci_get_drvdata(to_pci_dev(device)); |
1070 | unsigned long flags; | ||
1071 | |||
1072 | /* Turn on the hardware */ | ||
1073 | pci_back_from_sleep(to_pci_dev(device)); | ||
1074 | pci_restore_state(to_pci_dev(device)); | ||
1075 | 1054 | ||
1076 | r852_disable_irqs(dev); | 1055 | r852_disable_irqs(dev); |
1077 | r852_card_update_present(dev); | 1056 | r852_card_update_present(dev); |
1078 | r852_engine_disable(dev); | 1057 | r852_engine_disable(dev); |
1079 | 1058 | ||
1080 | 1059 | ||
1081 | /* Now its safe for IRQ to run */ | ||
1082 | spin_lock_irqsave(&dev->irqlock, flags); | ||
1083 | dev->insuspend = 0; | ||
1084 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
1085 | |||
1086 | |||
1087 | /* If card status changed, just do the work */ | 1060 | /* If card status changed, just do the work */ |
1088 | if (dev->card_detected != dev->card_registred) { | 1061 | if (dev->card_detected != dev->card_registred) { |
1089 | dbg("card was %s during low power state", | 1062 | dbg("card was %s during low power state", |
@@ -1121,7 +1094,6 @@ MODULE_DEVICE_TABLE(pci, r852_pci_id_tbl); | |||
1121 | 1094 | ||
1122 | SIMPLE_DEV_PM_OPS(r852_pm_ops, r852_suspend, r852_resume); | 1095 | SIMPLE_DEV_PM_OPS(r852_pm_ops, r852_suspend, r852_resume); |
1123 | 1096 | ||
1124 | |||
1125 | static struct pci_driver r852_pci_driver = { | 1097 | static struct pci_driver r852_pci_driver = { |
1126 | .name = DRV_NAME, | 1098 | .name = DRV_NAME, |
1127 | .id_table = r852_pci_id_tbl, | 1099 | .id_table = r852_pci_id_tbl, |
diff --git a/drivers/mtd/nand/r852.h b/drivers/mtd/nand/r852.h index 8096cc280c73..e6a21d9d22c6 100644 --- a/drivers/mtd/nand/r852.h +++ b/drivers/mtd/nand/r852.h | |||
@@ -140,8 +140,6 @@ struct r852_device { | |||
140 | /* interrupt handling */ | 140 | /* interrupt handling */ |
141 | spinlock_t irqlock; /* IRQ protecting lock */ | 141 | spinlock_t irqlock; /* IRQ protecting lock */ |
142 | int irq; /* irq num */ | 142 | int irq; /* irq num */ |
143 | int insuspend; /* device is suspended */ | ||
144 | |||
145 | /* misc */ | 143 | /* misc */ |
146 | void *tmp_buffer; /* temporary buffer */ | 144 | void *tmp_buffer; /* temporary buffer */ |
147 | uint8_t ctlreg; /* cached contents of control reg */ | 145 | uint8_t ctlreg; /* cached contents of control reg */ |
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index 7bd171eefd21..a996718fa6b0 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c | |||
@@ -44,7 +44,7 @@ int __devinit of_mtd_parse_partitions(struct device *dev, | |||
44 | pp = NULL; | 44 | pp = NULL; |
45 | i = 0; | 45 | i = 0; |
46 | while ((pp = of_get_next_child(node, pp))) { | 46 | while ((pp = of_get_next_child(node, pp))) { |
47 | const u32 *reg; | 47 | const __be32 *reg; |
48 | int len; | 48 | int len; |
49 | 49 | ||
50 | reg = of_get_property(pp, "reg", &len); | 50 | reg = of_get_property(pp, "reg", &len); |
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig index 3f32289fdbb5..4dbd0f58eebf 100644 --- a/drivers/mtd/onenand/Kconfig +++ b/drivers/mtd/onenand/Kconfig | |||
@@ -32,10 +32,11 @@ config MTD_ONENAND_OMAP2 | |||
32 | 32 | ||
33 | config MTD_ONENAND_SAMSUNG | 33 | config MTD_ONENAND_SAMSUNG |
34 | tristate "OneNAND on Samsung SOC controller support" | 34 | tristate "OneNAND on Samsung SOC controller support" |
35 | depends on ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 | 35 | depends on ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5PV310 |
36 | help | 36 | help |
37 | Support for a OneNAND flash device connected to an Samsung SOC | 37 | Support for a OneNAND flash device connected to an Samsung SOC. |
38 | S3C64XX/S5PC1XX controller. | 38 | S3C64XX/S5PC100 use command mapping method. |
39 | S5PC110/S5PC210 use generic OneNAND method. | ||
39 | 40 | ||
40 | config MTD_ONENAND_OTP | 41 | config MTD_ONENAND_OTP |
41 | bool "OneNAND OTP Support" | 42 | bool "OneNAND OTP Support" |
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index a2bb520286f8..6b3a875647c9 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c | |||
@@ -3365,18 +3365,19 @@ static int onenand_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, | |||
3365 | static void onenand_check_features(struct mtd_info *mtd) | 3365 | static void onenand_check_features(struct mtd_info *mtd) |
3366 | { | 3366 | { |
3367 | struct onenand_chip *this = mtd->priv; | 3367 | struct onenand_chip *this = mtd->priv; |
3368 | unsigned int density, process; | 3368 | unsigned int density, process, numbufs; |
3369 | 3369 | ||
3370 | /* Lock scheme depends on density and process */ | 3370 | /* Lock scheme depends on density and process */ |
3371 | density = onenand_get_density(this->device_id); | 3371 | density = onenand_get_density(this->device_id); |
3372 | process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT; | 3372 | process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT; |
3373 | numbufs = this->read_word(this->base + ONENAND_REG_NUM_BUFFERS) >> 8; | ||
3373 | 3374 | ||
3374 | /* Lock scheme */ | 3375 | /* Lock scheme */ |
3375 | switch (density) { | 3376 | switch (density) { |
3376 | case ONENAND_DEVICE_DENSITY_4Gb: | 3377 | case ONENAND_DEVICE_DENSITY_4Gb: |
3377 | if (ONENAND_IS_DDP(this)) | 3378 | if (ONENAND_IS_DDP(this)) |
3378 | this->options |= ONENAND_HAS_2PLANE; | 3379 | this->options |= ONENAND_HAS_2PLANE; |
3379 | else | 3380 | else if (numbufs == 1) |
3380 | this->options |= ONENAND_HAS_4KB_PAGE; | 3381 | this->options |= ONENAND_HAS_4KB_PAGE; |
3381 | 3382 | ||
3382 | case ONENAND_DEVICE_DENSITY_2Gb: | 3383 | case ONENAND_DEVICE_DENSITY_2Gb: |
@@ -4027,7 +4028,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) | |||
4027 | mtd->ecclayout = this->ecclayout; | 4028 | mtd->ecclayout = this->ecclayout; |
4028 | 4029 | ||
4029 | /* Fill in remaining MTD driver data */ | 4030 | /* Fill in remaining MTD driver data */ |
4030 | mtd->type = MTD_NANDFLASH; | 4031 | mtd->type = ONENAND_IS_MLC(this) ? MTD_MLCNANDFLASH : MTD_NANDFLASH; |
4031 | mtd->flags = MTD_CAP_NANDFLASH; | 4032 | mtd->flags = MTD_CAP_NANDFLASH; |
4032 | mtd->erase = onenand_erase; | 4033 | mtd->erase = onenand_erase; |
4033 | mtd->point = NULL; | 4034 | mtd->point = NULL; |
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c index a460f1b748c2..0de7a05e6de0 100644 --- a/drivers/mtd/onenand/samsung.c +++ b/drivers/mtd/onenand/samsung.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/mtd/onenand.h> | 22 | #include <linux/mtd/onenand.h> |
23 | #include <linux/mtd/partitions.h> | 23 | #include <linux/mtd/partitions.h> |
24 | #include <linux/dma-mapping.h> | 24 | #include <linux/dma-mapping.h> |
25 | #include <linux/interrupt.h> | ||
25 | 26 | ||
26 | #include <asm/mach/flash.h> | 27 | #include <asm/mach/flash.h> |
27 | #include <plat/regs-onenand.h> | 28 | #include <plat/regs-onenand.h> |
@@ -58,7 +59,7 @@ enum soc_type { | |||
58 | #define MAP_11 (0x3) | 59 | #define MAP_11 (0x3) |
59 | 60 | ||
60 | #define S3C64XX_CMD_MAP_SHIFT 24 | 61 | #define S3C64XX_CMD_MAP_SHIFT 24 |
61 | #define S5PC1XX_CMD_MAP_SHIFT 26 | 62 | #define S5PC100_CMD_MAP_SHIFT 26 |
62 | 63 | ||
63 | #define S3C6400_FBA_SHIFT 10 | 64 | #define S3C6400_FBA_SHIFT 10 |
64 | #define S3C6400_FPA_SHIFT 4 | 65 | #define S3C6400_FPA_SHIFT 4 |
@@ -81,6 +82,17 @@ enum soc_type { | |||
81 | #define S5PC110_DMA_TRANS_CMD 0x418 | 82 | #define S5PC110_DMA_TRANS_CMD 0x418 |
82 | #define S5PC110_DMA_TRANS_STATUS 0x41C | 83 | #define S5PC110_DMA_TRANS_STATUS 0x41C |
83 | #define S5PC110_DMA_TRANS_DIR 0x420 | 84 | #define S5PC110_DMA_TRANS_DIR 0x420 |
85 | #define S5PC110_INTC_DMA_CLR 0x1004 | ||
86 | #define S5PC110_INTC_ONENAND_CLR 0x1008 | ||
87 | #define S5PC110_INTC_DMA_MASK 0x1024 | ||
88 | #define S5PC110_INTC_ONENAND_MASK 0x1028 | ||
89 | #define S5PC110_INTC_DMA_PEND 0x1044 | ||
90 | #define S5PC110_INTC_ONENAND_PEND 0x1048 | ||
91 | #define S5PC110_INTC_DMA_STATUS 0x1064 | ||
92 | #define S5PC110_INTC_ONENAND_STATUS 0x1068 | ||
93 | |||
94 | #define S5PC110_INTC_DMA_TD (1 << 24) | ||
95 | #define S5PC110_INTC_DMA_TE (1 << 16) | ||
84 | 96 | ||
85 | #define S5PC110_DMA_CFG_SINGLE (0x0 << 16) | 97 | #define S5PC110_DMA_CFG_SINGLE (0x0 << 16) |
86 | #define S5PC110_DMA_CFG_4BURST (0x2 << 16) | 98 | #define S5PC110_DMA_CFG_4BURST (0x2 << 16) |
@@ -134,6 +146,7 @@ struct s3c_onenand { | |||
134 | void __iomem *dma_addr; | 146 | void __iomem *dma_addr; |
135 | struct resource *dma_res; | 147 | struct resource *dma_res; |
136 | unsigned long phys_base; | 148 | unsigned long phys_base; |
149 | struct completion complete; | ||
137 | #ifdef CONFIG_MTD_PARTITIONS | 150 | #ifdef CONFIG_MTD_PARTITIONS |
138 | struct mtd_partition *parts; | 151 | struct mtd_partition *parts; |
139 | #endif | 152 | #endif |
@@ -191,7 +204,7 @@ static unsigned int s3c64xx_cmd_map(unsigned type, unsigned val) | |||
191 | 204 | ||
192 | static unsigned int s5pc1xx_cmd_map(unsigned type, unsigned val) | 205 | static unsigned int s5pc1xx_cmd_map(unsigned type, unsigned val) |
193 | { | 206 | { |
194 | return (type << S5PC1XX_CMD_MAP_SHIFT) | val; | 207 | return (type << S5PC100_CMD_MAP_SHIFT) | val; |
195 | } | 208 | } |
196 | 209 | ||
197 | static unsigned int s3c6400_mem_addr(int fba, int fpa, int fsa) | 210 | static unsigned int s3c6400_mem_addr(int fba, int fpa, int fsa) |
@@ -531,10 +544,13 @@ static int onenand_write_bufferram(struct mtd_info *mtd, int area, | |||
531 | return 0; | 544 | return 0; |
532 | } | 545 | } |
533 | 546 | ||
534 | static int s5pc110_dma_ops(void *dst, void *src, size_t count, int direction) | 547 | static int (*s5pc110_dma_ops)(void *dst, void *src, size_t count, int direction); |
548 | |||
549 | static int s5pc110_dma_poll(void *dst, void *src, size_t count, int direction) | ||
535 | { | 550 | { |
536 | void __iomem *base = onenand->dma_addr; | 551 | void __iomem *base = onenand->dma_addr; |
537 | int status; | 552 | int status; |
553 | unsigned long timeout; | ||
538 | 554 | ||
539 | writel(src, base + S5PC110_DMA_SRC_ADDR); | 555 | writel(src, base + S5PC110_DMA_SRC_ADDR); |
540 | writel(dst, base + S5PC110_DMA_DST_ADDR); | 556 | writel(dst, base + S5PC110_DMA_DST_ADDR); |
@@ -552,6 +568,13 @@ static int s5pc110_dma_ops(void *dst, void *src, size_t count, int direction) | |||
552 | 568 | ||
553 | writel(S5PC110_DMA_TRANS_CMD_TR, base + S5PC110_DMA_TRANS_CMD); | 569 | writel(S5PC110_DMA_TRANS_CMD_TR, base + S5PC110_DMA_TRANS_CMD); |
554 | 570 | ||
571 | /* | ||
572 | * There's no exact timeout values at Spec. | ||
573 | * In real case it takes under 1 msec. | ||
574 | * So 20 msecs are enough. | ||
575 | */ | ||
576 | timeout = jiffies + msecs_to_jiffies(20); | ||
577 | |||
555 | do { | 578 | do { |
556 | status = readl(base + S5PC110_DMA_TRANS_STATUS); | 579 | status = readl(base + S5PC110_DMA_TRANS_STATUS); |
557 | if (status & S5PC110_DMA_TRANS_STATUS_TE) { | 580 | if (status & S5PC110_DMA_TRANS_STATUS_TE) { |
@@ -559,13 +582,68 @@ static int s5pc110_dma_ops(void *dst, void *src, size_t count, int direction) | |||
559 | base + S5PC110_DMA_TRANS_CMD); | 582 | base + S5PC110_DMA_TRANS_CMD); |
560 | return -EIO; | 583 | return -EIO; |
561 | } | 584 | } |
562 | } while (!(status & S5PC110_DMA_TRANS_STATUS_TD)); | 585 | } while (!(status & S5PC110_DMA_TRANS_STATUS_TD) && |
586 | time_before(jiffies, timeout)); | ||
563 | 587 | ||
564 | writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD); | 588 | writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD); |
565 | 589 | ||
566 | return 0; | 590 | return 0; |
567 | } | 591 | } |
568 | 592 | ||
593 | static irqreturn_t s5pc110_onenand_irq(int irq, void *data) | ||
594 | { | ||
595 | void __iomem *base = onenand->dma_addr; | ||
596 | int status, cmd = 0; | ||
597 | |||
598 | status = readl(base + S5PC110_INTC_DMA_STATUS); | ||
599 | |||
600 | if (likely(status & S5PC110_INTC_DMA_TD)) | ||
601 | cmd = S5PC110_DMA_TRANS_CMD_TDC; | ||
602 | |||
603 | if (unlikely(status & S5PC110_INTC_DMA_TE)) | ||
604 | cmd = S5PC110_DMA_TRANS_CMD_TEC; | ||
605 | |||
606 | writel(cmd, base + S5PC110_DMA_TRANS_CMD); | ||
607 | writel(status, base + S5PC110_INTC_DMA_CLR); | ||
608 | |||
609 | if (!onenand->complete.done) | ||
610 | complete(&onenand->complete); | ||
611 | |||
612 | return IRQ_HANDLED; | ||
613 | } | ||
614 | |||
615 | static int s5pc110_dma_irq(void *dst, void *src, size_t count, int direction) | ||
616 | { | ||
617 | void __iomem *base = onenand->dma_addr; | ||
618 | int status; | ||
619 | |||
620 | status = readl(base + S5PC110_INTC_DMA_MASK); | ||
621 | if (status) { | ||
622 | status &= ~(S5PC110_INTC_DMA_TD | S5PC110_INTC_DMA_TE); | ||
623 | writel(status, base + S5PC110_INTC_DMA_MASK); | ||
624 | } | ||
625 | |||
626 | writel(src, base + S5PC110_DMA_SRC_ADDR); | ||
627 | writel(dst, base + S5PC110_DMA_DST_ADDR); | ||
628 | |||
629 | if (direction == S5PC110_DMA_DIR_READ) { | ||
630 | writel(S5PC110_DMA_SRC_CFG_READ, base + S5PC110_DMA_SRC_CFG); | ||
631 | writel(S5PC110_DMA_DST_CFG_READ, base + S5PC110_DMA_DST_CFG); | ||
632 | } else { | ||
633 | writel(S5PC110_DMA_SRC_CFG_WRITE, base + S5PC110_DMA_SRC_CFG); | ||
634 | writel(S5PC110_DMA_DST_CFG_WRITE, base + S5PC110_DMA_DST_CFG); | ||
635 | } | ||
636 | |||
637 | writel(count, base + S5PC110_DMA_TRANS_SIZE); | ||
638 | writel(direction, base + S5PC110_DMA_TRANS_DIR); | ||
639 | |||
640 | writel(S5PC110_DMA_TRANS_CMD_TR, base + S5PC110_DMA_TRANS_CMD); | ||
641 | |||
642 | wait_for_completion_timeout(&onenand->complete, msecs_to_jiffies(20)); | ||
643 | |||
644 | return 0; | ||
645 | } | ||
646 | |||
569 | static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, | 647 | static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, |
570 | unsigned char *buffer, int offset, size_t count) | 648 | unsigned char *buffer, int offset, size_t count) |
571 | { | 649 | { |
@@ -573,7 +651,8 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, | |||
573 | void __iomem *p; | 651 | void __iomem *p; |
574 | void *buf = (void *) buffer; | 652 | void *buf = (void *) buffer; |
575 | dma_addr_t dma_src, dma_dst; | 653 | dma_addr_t dma_src, dma_dst; |
576 | int err; | 654 | int err, page_dma = 0; |
655 | struct device *dev = &onenand->pdev->dev; | ||
577 | 656 | ||
578 | p = this->base + area; | 657 | p = this->base + area; |
579 | if (ONENAND_CURRENT_BUFFERRAM(this)) { | 658 | if (ONENAND_CURRENT_BUFFERRAM(this)) { |
@@ -597,21 +676,27 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, | |||
597 | page = vmalloc_to_page(buf); | 676 | page = vmalloc_to_page(buf); |
598 | if (!page) | 677 | if (!page) |
599 | goto normal; | 678 | goto normal; |
600 | buf = page_address(page) + ((size_t) buf & ~PAGE_MASK); | ||
601 | } | ||
602 | 679 | ||
603 | /* DMA routine */ | 680 | page_dma = 1; |
604 | dma_src = onenand->phys_base + (p - this->base); | 681 | /* DMA routine */ |
605 | dma_dst = dma_map_single(&onenand->pdev->dev, | 682 | dma_src = onenand->phys_base + (p - this->base); |
606 | buf, count, DMA_FROM_DEVICE); | 683 | dma_dst = dma_map_page(dev, page, 0, count, DMA_FROM_DEVICE); |
607 | if (dma_mapping_error(&onenand->pdev->dev, dma_dst)) { | 684 | } else { |
608 | dev_err(&onenand->pdev->dev, | 685 | /* DMA routine */ |
609 | "Couldn't map a %d byte buffer for DMA\n", count); | 686 | dma_src = onenand->phys_base + (p - this->base); |
687 | dma_dst = dma_map_single(dev, buf, count, DMA_FROM_DEVICE); | ||
688 | } | ||
689 | if (dma_mapping_error(dev, dma_dst)) { | ||
690 | dev_err(dev, "Couldn't map a %d byte buffer for DMA\n", count); | ||
610 | goto normal; | 691 | goto normal; |
611 | } | 692 | } |
612 | err = s5pc110_dma_ops((void *) dma_dst, (void *) dma_src, | 693 | err = s5pc110_dma_ops((void *) dma_dst, (void *) dma_src, |
613 | count, S5PC110_DMA_DIR_READ); | 694 | count, S5PC110_DMA_DIR_READ); |
614 | dma_unmap_single(&onenand->pdev->dev, dma_dst, count, DMA_FROM_DEVICE); | 695 | |
696 | if (page_dma) | ||
697 | dma_unmap_page(dev, dma_dst, count, DMA_FROM_DEVICE); | ||
698 | else | ||
699 | dma_unmap_single(dev, dma_dst, count, DMA_FROM_DEVICE); | ||
615 | 700 | ||
616 | if (!err) | 701 | if (!err) |
617 | return 0; | 702 | return 0; |
@@ -759,7 +844,6 @@ static void s3c_onenand_setup(struct mtd_info *mtd) | |||
759 | onenand->cmd_map = s5pc1xx_cmd_map; | 844 | onenand->cmd_map = s5pc1xx_cmd_map; |
760 | } else if (onenand->type == TYPE_S5PC110) { | 845 | } else if (onenand->type == TYPE_S5PC110) { |
761 | /* Use generic onenand functions */ | 846 | /* Use generic onenand functions */ |
762 | onenand->cmd_map = s5pc1xx_cmd_map; | ||
763 | this->read_bufferram = s5pc110_read_bufferram; | 847 | this->read_bufferram = s5pc110_read_bufferram; |
764 | this->chip_probe = s5pc110_chip_probe; | 848 | this->chip_probe = s5pc110_chip_probe; |
765 | return; | 849 | return; |
@@ -904,6 +988,20 @@ static int s3c_onenand_probe(struct platform_device *pdev) | |||
904 | } | 988 | } |
905 | 989 | ||
906 | onenand->phys_base = onenand->base_res->start; | 990 | onenand->phys_base = onenand->base_res->start; |
991 | |||
992 | s5pc110_dma_ops = s5pc110_dma_poll; | ||
993 | /* Interrupt support */ | ||
994 | r = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
995 | if (r) { | ||
996 | init_completion(&onenand->complete); | ||
997 | s5pc110_dma_ops = s5pc110_dma_irq; | ||
998 | err = request_irq(r->start, s5pc110_onenand_irq, | ||
999 | IRQF_SHARED, "onenand", &onenand); | ||
1000 | if (err) { | ||
1001 | dev_err(&pdev->dev, "failed to get irq\n"); | ||
1002 | goto scan_failed; | ||
1003 | } | ||
1004 | } | ||
907 | } | 1005 | } |
908 | 1006 | ||
909 | if (onenand_scan(mtd, 1)) { | 1007 | if (onenand_scan(mtd, 1)) { |
@@ -1000,7 +1098,7 @@ static int s3c_pm_ops_suspend(struct device *dev) | |||
1000 | struct onenand_chip *this = mtd->priv; | 1098 | struct onenand_chip *this = mtd->priv; |
1001 | 1099 | ||
1002 | this->wait(mtd, FL_PM_SUSPENDED); | 1100 | this->wait(mtd, FL_PM_SUSPENDED); |
1003 | return mtd->suspend(mtd); | 1101 | return 0; |
1004 | } | 1102 | } |
1005 | 1103 | ||
1006 | static int s3c_pm_ops_resume(struct device *dev) | 1104 | static int s3c_pm_ops_resume(struct device *dev) |
@@ -1009,7 +1107,6 @@ static int s3c_pm_ops_resume(struct device *dev) | |||
1009 | struct mtd_info *mtd = platform_get_drvdata(pdev); | 1107 | struct mtd_info *mtd = platform_get_drvdata(pdev); |
1010 | struct onenand_chip *this = mtd->priv; | 1108 | struct onenand_chip *this = mtd->priv; |
1011 | 1109 | ||
1012 | mtd->resume(mtd); | ||
1013 | this->unlock_all(mtd); | 1110 | this->unlock_all(mtd); |
1014 | return 0; | 1111 | return 0; |
1015 | } | 1112 | } |
diff --git a/drivers/mtd/sm_ftl.h b/drivers/mtd/sm_ftl.h index e30e48e7f63d..43bb7300785b 100644 --- a/drivers/mtd/sm_ftl.h +++ b/drivers/mtd/sm_ftl.h | |||
@@ -20,7 +20,7 @@ | |||
20 | 20 | ||
21 | 21 | ||
22 | struct ftl_zone { | 22 | struct ftl_zone { |
23 | int initialized; | 23 | bool initialized; |
24 | int16_t *lba_to_phys_table; /* LBA to physical table */ | 24 | int16_t *lba_to_phys_table; /* LBA to physical table */ |
25 | struct kfifo free_sectors; /* queue of free sectors */ | 25 | struct kfifo free_sectors; /* queue of free sectors */ |
26 | }; | 26 | }; |
@@ -37,8 +37,8 @@ struct sm_ftl { | |||
37 | int zone_count; /* number of zones */ | 37 | int zone_count; /* number of zones */ |
38 | int max_lba; /* maximum lba in a zone */ | 38 | int max_lba; /* maximum lba in a zone */ |
39 | int smallpagenand; /* 256 bytes/page nand */ | 39 | int smallpagenand; /* 256 bytes/page nand */ |
40 | int readonly; /* is FS readonly */ | 40 | bool readonly; /* is FS readonly */ |
41 | int unstable; | 41 | bool unstable; |
42 | int cis_block; /* CIS block location */ | 42 | int cis_block; /* CIS block location */ |
43 | int cis_boffset; /* CIS offset in the block */ | 43 | int cis_boffset; /* CIS offset in the block */ |
44 | int cis_page_offset; /* CIS offset in the page */ | 44 | int cis_page_offset; /* CIS offset in the page */ |
@@ -49,7 +49,7 @@ struct sm_ftl { | |||
49 | int cache_zone; /* zone of cached block */ | 49 | int cache_zone; /* zone of cached block */ |
50 | unsigned char *cache_data; /* cached block data */ | 50 | unsigned char *cache_data; /* cached block data */ |
51 | long unsigned int cache_data_invalid_bitmap; | 51 | long unsigned int cache_data_invalid_bitmap; |
52 | int cache_clean; | 52 | bool cache_clean; |
53 | struct work_struct flush_work; | 53 | struct work_struct flush_work; |
54 | struct timer_list timer; | 54 | struct timer_list timer; |
55 | 55 | ||
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c index 5699ce0c1780..3f3d431033ca 100644 --- a/drivers/video/sh_mipi_dsi.c +++ b/drivers/video/sh_mipi_dsi.c | |||
@@ -123,83 +123,87 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, | |||
123 | u32 linelength; | 123 | u32 linelength; |
124 | bool yuv; | 124 | bool yuv; |
125 | 125 | ||
126 | /* Select data format */ | 126 | /* |
127 | * Select data format. MIPI DSI is not hot-pluggable, so, we just use | ||
128 | * the default videomode. If this ever becomes a problem, We'll have to | ||
129 | * move this to mipi_display_on() above and use info->var.xres | ||
130 | */ | ||
127 | switch (pdata->data_format) { | 131 | switch (pdata->data_format) { |
128 | case MIPI_RGB888: | 132 | case MIPI_RGB888: |
129 | pctype = 0; | 133 | pctype = 0; |
130 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; | 134 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; |
131 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; | 135 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; |
132 | linelength = ch->lcd_cfg.xres * 3; | 136 | linelength = ch->lcd_cfg[0].xres * 3; |
133 | yuv = false; | 137 | yuv = false; |
134 | break; | 138 | break; |
135 | case MIPI_RGB565: | 139 | case MIPI_RGB565: |
136 | pctype = 1; | 140 | pctype = 1; |
137 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; | 141 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; |
138 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; | 142 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; |
139 | linelength = ch->lcd_cfg.xres * 2; | 143 | linelength = ch->lcd_cfg[0].xres * 2; |
140 | yuv = false; | 144 | yuv = false; |
141 | break; | 145 | break; |
142 | case MIPI_RGB666_LP: | 146 | case MIPI_RGB666_LP: |
143 | pctype = 2; | 147 | pctype = 2; |
144 | datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; | 148 | datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; |
145 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; | 149 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; |
146 | linelength = ch->lcd_cfg.xres * 3; | 150 | linelength = ch->lcd_cfg[0].xres * 3; |
147 | yuv = false; | 151 | yuv = false; |
148 | break; | 152 | break; |
149 | case MIPI_RGB666: | 153 | case MIPI_RGB666: |
150 | pctype = 3; | 154 | pctype = 3; |
151 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; | 155 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; |
152 | pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; | 156 | pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; |
153 | linelength = (ch->lcd_cfg.xres * 18 + 7) / 8; | 157 | linelength = (ch->lcd_cfg[0].xres * 18 + 7) / 8; |
154 | yuv = false; | 158 | yuv = false; |
155 | break; | 159 | break; |
156 | case MIPI_BGR888: | 160 | case MIPI_BGR888: |
157 | pctype = 8; | 161 | pctype = 8; |
158 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; | 162 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; |
159 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; | 163 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; |
160 | linelength = ch->lcd_cfg.xres * 3; | 164 | linelength = ch->lcd_cfg[0].xres * 3; |
161 | yuv = false; | 165 | yuv = false; |
162 | break; | 166 | break; |
163 | case MIPI_BGR565: | 167 | case MIPI_BGR565: |
164 | pctype = 9; | 168 | pctype = 9; |
165 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; | 169 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; |
166 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; | 170 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; |
167 | linelength = ch->lcd_cfg.xres * 2; | 171 | linelength = ch->lcd_cfg[0].xres * 2; |
168 | yuv = false; | 172 | yuv = false; |
169 | break; | 173 | break; |
170 | case MIPI_BGR666_LP: | 174 | case MIPI_BGR666_LP: |
171 | pctype = 0xa; | 175 | pctype = 0xa; |
172 | datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; | 176 | datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; |
173 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; | 177 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; |
174 | linelength = ch->lcd_cfg.xres * 3; | 178 | linelength = ch->lcd_cfg[0].xres * 3; |
175 | yuv = false; | 179 | yuv = false; |
176 | break; | 180 | break; |
177 | case MIPI_BGR666: | 181 | case MIPI_BGR666: |
178 | pctype = 0xb; | 182 | pctype = 0xb; |
179 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; | 183 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; |
180 | pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; | 184 | pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; |
181 | linelength = (ch->lcd_cfg.xres * 18 + 7) / 8; | 185 | linelength = (ch->lcd_cfg[0].xres * 18 + 7) / 8; |
182 | yuv = false; | 186 | yuv = false; |
183 | break; | 187 | break; |
184 | case MIPI_YUYV: | 188 | case MIPI_YUYV: |
185 | pctype = 4; | 189 | pctype = 4; |
186 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; | 190 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; |
187 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; | 191 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; |
188 | linelength = ch->lcd_cfg.xres * 2; | 192 | linelength = ch->lcd_cfg[0].xres * 2; |
189 | yuv = true; | 193 | yuv = true; |
190 | break; | 194 | break; |
191 | case MIPI_UYVY: | 195 | case MIPI_UYVY: |
192 | pctype = 5; | 196 | pctype = 5; |
193 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; | 197 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; |
194 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; | 198 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; |
195 | linelength = ch->lcd_cfg.xres * 2; | 199 | linelength = ch->lcd_cfg[0].xres * 2; |
196 | yuv = true; | 200 | yuv = true; |
197 | break; | 201 | break; |
198 | case MIPI_YUV420_L: | 202 | case MIPI_YUV420_L: |
199 | pctype = 6; | 203 | pctype = 6; |
200 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; | 204 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; |
201 | pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; | 205 | pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; |
202 | linelength = (ch->lcd_cfg.xres * 12 + 7) / 8; | 206 | linelength = (ch->lcd_cfg[0].xres * 12 + 7) / 8; |
203 | yuv = true; | 207 | yuv = true; |
204 | break; | 208 | break; |
205 | case MIPI_YUV420: | 209 | case MIPI_YUV420: |
@@ -207,7 +211,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, | |||
207 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; | 211 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; |
208 | pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; | 212 | pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; |
209 | /* Length of U/V line */ | 213 | /* Length of U/V line */ |
210 | linelength = (ch->lcd_cfg.xres + 1) / 2; | 214 | linelength = (ch->lcd_cfg[0].xres + 1) / 2; |
211 | yuv = true; | 215 | yuv = true; |
212 | break; | 216 | break; |
213 | default: | 217 | default: |
@@ -281,7 +285,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi, | |||
281 | iowrite32(0x00e00000, base + 0x8024); /* VMCTR2 */ | 285 | iowrite32(0x00e00000, base + 0x8024); /* VMCTR2 */ |
282 | /* | 286 | /* |
283 | * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see | 287 | * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see |
284 | * sh_mobile_lcdc_info.ch[0].lcd_cfg.xres), HSALEN = 1 - default | 288 | * sh_mobile_lcdc_info.ch[0].lcd_cfg[0].xres), HSALEN = 1 - default |
285 | * (unused, since VMCTR2[HSABM] = 0) | 289 | * (unused, since VMCTR2[HSABM] = 0) |
286 | */ | 290 | */ |
287 | iowrite32(1 | (linelength << 16), base + 0x8028); /* VMLEN1 */ | 291 | iowrite32(1 | (linelength << 16), base + 0x8028); /* VMLEN1 */ |
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c index ef989d94511c..55b3077ff6ff 100644 --- a/drivers/video/sh_mobile_hdmi.c +++ b/drivers/video/sh_mobile_hdmi.c | |||
@@ -28,6 +28,8 @@ | |||
28 | #include <video/sh_mobile_hdmi.h> | 28 | #include <video/sh_mobile_hdmi.h> |
29 | #include <video/sh_mobile_lcdc.h> | 29 | #include <video/sh_mobile_lcdc.h> |
30 | 30 | ||
31 | #include "sh_mobile_lcdcfb.h" | ||
32 | |||
31 | #define HDMI_SYSTEM_CTRL 0x00 /* System control */ | 33 | #define HDMI_SYSTEM_CTRL 0x00 /* System control */ |
32 | #define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control, | 34 | #define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control, |
33 | bits 19..16 of 20-bit N for Audio Clock Regeneration packet */ | 35 | bits 19..16 of 20-bit N for Audio Clock Regeneration packet */ |
@@ -206,12 +208,15 @@ enum hotplug_state { | |||
206 | 208 | ||
207 | struct sh_hdmi { | 209 | struct sh_hdmi { |
208 | void __iomem *base; | 210 | void __iomem *base; |
209 | enum hotplug_state hp_state; | 211 | enum hotplug_state hp_state; /* hot-plug status */ |
212 | bool preprogrammed_mode; /* use a pre-programmed VIC or the external mode */ | ||
210 | struct clk *hdmi_clk; | 213 | struct clk *hdmi_clk; |
211 | struct device *dev; | 214 | struct device *dev; |
212 | struct fb_info *info; | 215 | struct fb_info *info; |
216 | struct mutex mutex; /* Protect the info pointer */ | ||
213 | struct delayed_work edid_work; | 217 | struct delayed_work edid_work; |
214 | struct fb_var_screeninfo var; | 218 | struct fb_var_screeninfo var; |
219 | struct fb_monspecs monspec; | ||
215 | }; | 220 | }; |
216 | 221 | ||
217 | static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg) | 222 | static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg) |
@@ -277,7 +282,7 @@ static struct snd_soc_codec_driver soc_codec_dev_sh_hdmi = { | |||
277 | */ | 282 | */ |
278 | 283 | ||
279 | /* External video parameter settings */ | 284 | /* External video parameter settings */ |
280 | static void hdmi_external_video_param(struct sh_hdmi *hdmi) | 285 | static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi) |
281 | { | 286 | { |
282 | struct fb_var_screeninfo *var = &hdmi->var; | 287 | struct fb_var_screeninfo *var = &hdmi->var; |
283 | u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset; | 288 | u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset; |
@@ -309,9 +314,9 @@ static void hdmi_external_video_param(struct sh_hdmi *hdmi) | |||
309 | if (var->sync & FB_SYNC_VERT_HIGH_ACT) | 314 | if (var->sync & FB_SYNC_VERT_HIGH_ACT) |
310 | sync |= 8; | 315 | sync |= 8; |
311 | 316 | ||
312 | pr_debug("H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n", | 317 | dev_dbg(hdmi->dev, "H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n", |
313 | htotal, hblank, hdelay, var->hsync_len, | 318 | htotal, hblank, hdelay, var->hsync_len, |
314 | vtotal, vblank, vdelay, var->vsync_len, sync); | 319 | vtotal, vblank, vdelay, var->vsync_len, sync); |
315 | 320 | ||
316 | hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS); | 321 | hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS); |
317 | 322 | ||
@@ -336,7 +341,10 @@ static void hdmi_external_video_param(struct sh_hdmi *hdmi) | |||
336 | 341 | ||
337 | hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION); | 342 | hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION); |
338 | 343 | ||
339 | /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for manual mode */ | 344 | /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for external mode */ |
345 | if (!hdmi->preprogrammed_mode) | ||
346 | hdmi_write(hdmi, sync | 1 | (voffset << 4), | ||
347 | HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS); | ||
340 | } | 348 | } |
341 | 349 | ||
342 | /** | 350 | /** |
@@ -454,21 +462,61 @@ static void sh_hdmi_audio_config(struct sh_hdmi *hdmi) | |||
454 | } | 462 | } |
455 | 463 | ||
456 | /** | 464 | /** |
457 | * sh_hdmi_phy_config() | 465 | * sh_hdmi_phy_config() - configure the HDMI PHY for the used video mode |
458 | */ | 466 | */ |
459 | static void sh_hdmi_phy_config(struct sh_hdmi *hdmi) | 467 | static void sh_hdmi_phy_config(struct sh_hdmi *hdmi) |
460 | { | 468 | { |
461 | /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */ | 469 | if (hdmi->var.yres > 480) { |
462 | hdmi_write(hdmi, 0x19, HDMI_SLIPHDMIT_PARAM_SETTINGS_1); | 470 | /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */ |
463 | hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2); | 471 | /* |
464 | hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3); | 472 | * [1:0] Speed_A |
465 | /* PLLA_CONFIG[7:0]: VCO gain, VCO offset, LPF resistance[0] */ | 473 | * [3:2] Speed_B |
466 | hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5); | 474 | * [4] PLLA_Bypass |
467 | hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6); | 475 | * [6] DRV_TEST_EN |
468 | hdmi_write(hdmi, 0x4A, HDMI_SLIPHDMIT_PARAM_SETTINGS_7); | 476 | * [7] DRV_TEST_IN |
469 | hdmi_write(hdmi, 0x0E, HDMI_SLIPHDMIT_PARAM_SETTINGS_8); | 477 | */ |
470 | hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9); | 478 | hdmi_write(hdmi, 0x0f, HDMI_SLIPHDMIT_PARAM_SETTINGS_1); |
471 | hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10); | 479 | /* PLLB_CONFIG[17], PLLA_CONFIG[17] - not in PHY datasheet */ |
480 | hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2); | ||
481 | /* | ||
482 | * [2:0] BGR_I_OFFSET | ||
483 | * [6:4] BGR_V_OFFSET | ||
484 | */ | ||
485 | hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3); | ||
486 | /* PLLA_CONFIG[7:0]: VCO gain, VCO offset, LPF resistance[0] */ | ||
487 | hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5); | ||
488 | /* | ||
489 | * PLLA_CONFIG[15:8]: regulator voltage[0], CP current, | ||
490 | * LPF capacitance, LPF resistance[1] | ||
491 | */ | ||
492 | hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6); | ||
493 | /* PLLB_CONFIG[7:0]: LPF resistance[0], VCO offset, VCO gain */ | ||
494 | hdmi_write(hdmi, 0x4A, HDMI_SLIPHDMIT_PARAM_SETTINGS_7); | ||
495 | /* | ||
496 | * PLLB_CONFIG[15:8]: regulator voltage[0], CP current, | ||
497 | * LPF capacitance, LPF resistance[1] | ||
498 | */ | ||
499 | hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_8); | ||
500 | /* DRV_CONFIG, PE_CONFIG */ | ||
501 | hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9); | ||
502 | /* | ||
503 | * [2:0] AMON_SEL (4 == LPF voltage) | ||
504 | * [4] PLLA_CONFIG[16] | ||
505 | * [5] PLLB_CONFIG[16] | ||
506 | */ | ||
507 | hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10); | ||
508 | } else { | ||
509 | /* for 480p8bit 27MHz */ | ||
510 | hdmi_write(hdmi, 0x19, HDMI_SLIPHDMIT_PARAM_SETTINGS_1); | ||
511 | hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2); | ||
512 | hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3); | ||
513 | hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5); | ||
514 | hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6); | ||
515 | hdmi_write(hdmi, 0x48, HDMI_SLIPHDMIT_PARAM_SETTINGS_7); | ||
516 | hdmi_write(hdmi, 0x0F, HDMI_SLIPHDMIT_PARAM_SETTINGS_8); | ||
517 | hdmi_write(hdmi, 0x20, HDMI_SLIPHDMIT_PARAM_SETTINGS_9); | ||
518 | hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10); | ||
519 | } | ||
472 | } | 520 | } |
473 | 521 | ||
474 | /** | 522 | /** |
@@ -476,6 +524,8 @@ static void sh_hdmi_phy_config(struct sh_hdmi *hdmi) | |||
476 | */ | 524 | */ |
477 | static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi) | 525 | static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi) |
478 | { | 526 | { |
527 | u8 vic; | ||
528 | |||
479 | /* AVI InfoFrame */ | 529 | /* AVI InfoFrame */ |
480 | hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_INDEX); | 530 | hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_INDEX); |
481 | 531 | ||
@@ -500,9 +550,9 @@ static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi) | |||
500 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1); | 550 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1); |
501 | 551 | ||
502 | /* | 552 | /* |
503 | * C = No Data | 553 | * [7:6] C = Colorimetry: no data |
504 | * M = 16:9 Picture Aspect Ratio | 554 | * [5:4] M = 2: 16:9, 1: 4:3 Picture Aspect Ratio |
505 | * R = Same as picture aspect ratio | 555 | * [3:0] R = 8: Active Frame Aspect Ratio: same as picture aspect ratio |
506 | */ | 556 | */ |
507 | hdmi_write(hdmi, 0x28, HDMI_CTRL_PKT_BUF_ACCESS_PB2); | 557 | hdmi_write(hdmi, 0x28, HDMI_CTRL_PKT_BUF_ACCESS_PB2); |
508 | 558 | ||
@@ -516,9 +566,15 @@ static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi) | |||
516 | 566 | ||
517 | /* | 567 | /* |
518 | * VIC = 1280 x 720p: ignored if external config is used | 568 | * VIC = 1280 x 720p: ignored if external config is used |
519 | * Send 2 for 720 x 480p, 16 for 1080p | 569 | * Send 2 for 720 x 480p, 16 for 1080p, ignored in external mode |
520 | */ | 570 | */ |
521 | hdmi_write(hdmi, 4, HDMI_CTRL_PKT_BUF_ACCESS_PB4); | 571 | if (hdmi->var.yres == 1080 && hdmi->var.xres == 1920) |
572 | vic = 16; | ||
573 | else if (hdmi->var.yres == 480 && hdmi->var.xres == 720) | ||
574 | vic = 2; | ||
575 | else | ||
576 | vic = 4; | ||
577 | hdmi_write(hdmi, vic, HDMI_CTRL_PKT_BUF_ACCESS_PB4); | ||
522 | 578 | ||
523 | /* PR = No Repetition */ | 579 | /* PR = No Repetition */ |
524 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5); | 580 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5); |
@@ -592,100 +648,6 @@ static void sh_hdmi_audio_infoframe_setup(struct sh_hdmi *hdmi) | |||
592 | } | 648 | } |
593 | 649 | ||
594 | /** | 650 | /** |
595 | * sh_hdmi_gamut_metadata_setup() - Gamut Metadata Packet of CONTROL PACKET | ||
596 | */ | ||
597 | static void sh_hdmi_gamut_metadata_setup(struct sh_hdmi *hdmi) | ||
598 | { | ||
599 | int i; | ||
600 | |||
601 | /* Gamut Metadata Packet */ | ||
602 | hdmi_write(hdmi, 0x04, HDMI_CTRL_PKT_BUF_INDEX); | ||
603 | |||
604 | /* Packet Type = 0x0A */ | ||
605 | hdmi_write(hdmi, 0x0A, HDMI_CTRL_PKT_BUF_ACCESS_HB0); | ||
606 | /* Gamut Packet is not used, so default value */ | ||
607 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1); | ||
608 | /* Gamut Packet is not used, so default value */ | ||
609 | hdmi_write(hdmi, 0x10, HDMI_CTRL_PKT_BUF_ACCESS_HB2); | ||
610 | |||
611 | /* GBD bytes 0 through 27 */ | ||
612 | for (i = 0; i <= 27; i++) | ||
613 | /* HDMI_CTRL_PKT_BUF_ACCESS_PB0_63H - PB27_7EH */ | ||
614 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i); | ||
615 | } | ||
616 | |||
617 | /** | ||
618 | * sh_hdmi_acp_setup() - Audio Content Protection Packet (ACP) | ||
619 | */ | ||
620 | static void sh_hdmi_acp_setup(struct sh_hdmi *hdmi) | ||
621 | { | ||
622 | int i; | ||
623 | |||
624 | /* Audio Content Protection Packet (ACP) */ | ||
625 | hdmi_write(hdmi, 0x01, HDMI_CTRL_PKT_BUF_INDEX); | ||
626 | |||
627 | /* Packet Type = 0x04 */ | ||
628 | hdmi_write(hdmi, 0x04, HDMI_CTRL_PKT_BUF_ACCESS_HB0); | ||
629 | /* ACP_Type */ | ||
630 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1); | ||
631 | /* Reserved (0) */ | ||
632 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2); | ||
633 | |||
634 | /* GBD bytes 0 through 27 */ | ||
635 | for (i = 0; i <= 27; i++) | ||
636 | /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */ | ||
637 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i); | ||
638 | } | ||
639 | |||
640 | /** | ||
641 | * sh_hdmi_isrc1_setup() - ISRC1 Packet | ||
642 | */ | ||
643 | static void sh_hdmi_isrc1_setup(struct sh_hdmi *hdmi) | ||
644 | { | ||
645 | int i; | ||
646 | |||
647 | /* ISRC1 Packet */ | ||
648 | hdmi_write(hdmi, 0x02, HDMI_CTRL_PKT_BUF_INDEX); | ||
649 | |||
650 | /* Packet Type = 0x05 */ | ||
651 | hdmi_write(hdmi, 0x05, HDMI_CTRL_PKT_BUF_ACCESS_HB0); | ||
652 | /* ISRC_Cont, ISRC_Valid, Reserved (0), ISRC_Status */ | ||
653 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1); | ||
654 | /* Reserved (0) */ | ||
655 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2); | ||
656 | |||
657 | /* PB0 UPC_EAN_ISRC_0-15 */ | ||
658 | /* Bytes PB16-PB27 shall be set to a value of 0. */ | ||
659 | for (i = 0; i <= 27; i++) | ||
660 | /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */ | ||
661 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i); | ||
662 | } | ||
663 | |||
664 | /** | ||
665 | * sh_hdmi_isrc2_setup() - ISRC2 Packet | ||
666 | */ | ||
667 | static void sh_hdmi_isrc2_setup(struct sh_hdmi *hdmi) | ||
668 | { | ||
669 | int i; | ||
670 | |||
671 | /* ISRC2 Packet */ | ||
672 | hdmi_write(hdmi, 0x03, HDMI_CTRL_PKT_BUF_INDEX); | ||
673 | |||
674 | /* HB0 Packet Type = 0x06 */ | ||
675 | hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_ACCESS_HB0); | ||
676 | /* Reserved (0) */ | ||
677 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1); | ||
678 | /* Reserved (0) */ | ||
679 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2); | ||
680 | |||
681 | /* PB0 UPC_EAN_ISRC_16-31 */ | ||
682 | /* Bytes PB16-PB27 shall be set to a value of 0. */ | ||
683 | for (i = 0; i <= 27; i++) | ||
684 | /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */ | ||
685 | hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i); | ||
686 | } | ||
687 | |||
688 | /** | ||
689 | * sh_hdmi_configure() - Initialise HDMI for output | 651 | * sh_hdmi_configure() - Initialise HDMI for output |
690 | */ | 652 | */ |
691 | static void sh_hdmi_configure(struct sh_hdmi *hdmi) | 653 | static void sh_hdmi_configure(struct sh_hdmi *hdmi) |
@@ -705,18 +667,6 @@ static void sh_hdmi_configure(struct sh_hdmi *hdmi) | |||
705 | /* Audio InfoFrame */ | 667 | /* Audio InfoFrame */ |
706 | sh_hdmi_audio_infoframe_setup(hdmi); | 668 | sh_hdmi_audio_infoframe_setup(hdmi); |
707 | 669 | ||
708 | /* Gamut Metadata packet */ | ||
709 | sh_hdmi_gamut_metadata_setup(hdmi); | ||
710 | |||
711 | /* Audio Content Protection (ACP) Packet */ | ||
712 | sh_hdmi_acp_setup(hdmi); | ||
713 | |||
714 | /* ISRC1 Packet */ | ||
715 | sh_hdmi_isrc1_setup(hdmi); | ||
716 | |||
717 | /* ISRC2 Packet */ | ||
718 | sh_hdmi_isrc2_setup(hdmi); | ||
719 | |||
720 | /* | 670 | /* |
721 | * Control packet auto send with VSYNC control: auto send | 671 | * Control packet auto send with VSYNC control: auto send |
722 | * General control, Gamut metadata, ISRC, and ACP packets | 672 | * General control, Gamut metadata, ISRC, and ACP packets |
@@ -734,17 +684,42 @@ static void sh_hdmi_configure(struct sh_hdmi *hdmi) | |||
734 | hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL); | 684 | hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL); |
735 | } | 685 | } |
736 | 686 | ||
737 | static void sh_hdmi_read_edid(struct sh_hdmi *hdmi) | 687 | static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi, |
688 | const struct fb_videomode *mode) | ||
738 | { | 689 | { |
739 | struct fb_var_screeninfo *var = &hdmi->var; | 690 | long target = PICOS2KHZ(mode->pixclock) * 1000, |
740 | struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; | 691 | rate = clk_round_rate(hdmi->hdmi_clk, target); |
741 | struct fb_videomode *lcd_cfg = &pdata->lcd_chan->lcd_cfg; | 692 | unsigned long rate_error = rate > 0 ? abs(rate - target) : ULONG_MAX; |
742 | unsigned long height = var->height, width = var->width; | 693 | |
743 | int i; | 694 | dev_dbg(hdmi->dev, "%u-%u-%u-%u x %u-%u-%u-%u\n", |
695 | mode->left_margin, mode->xres, | ||
696 | mode->right_margin, mode->hsync_len, | ||
697 | mode->upper_margin, mode->yres, | ||
698 | mode->lower_margin, mode->vsync_len); | ||
699 | |||
700 | dev_dbg(hdmi->dev, "\t@%lu(+/-%lu)Hz, e=%lu / 1000, r=%uHz\n", target, | ||
701 | rate_error, rate_error ? 10000 / (10 * target / rate_error) : 0, | ||
702 | mode->refresh); | ||
703 | |||
704 | return rate_error; | ||
705 | } | ||
706 | |||
707 | static int sh_hdmi_read_edid(struct sh_hdmi *hdmi) | ||
708 | { | ||
709 | struct fb_var_screeninfo tmpvar; | ||
710 | struct fb_var_screeninfo *var = &tmpvar; | ||
711 | const struct fb_videomode *mode, *found = NULL; | ||
712 | struct fb_info *info = hdmi->info; | ||
713 | struct fb_modelist *modelist = NULL; | ||
714 | unsigned int f_width = 0, f_height = 0, f_refresh = 0; | ||
715 | unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */ | ||
716 | bool exact_match = false; | ||
744 | u8 edid[128]; | 717 | u8 edid[128]; |
718 | char *forced; | ||
719 | int i; | ||
745 | 720 | ||
746 | /* Read EDID */ | 721 | /* Read EDID */ |
747 | pr_debug("Read back EDID code:"); | 722 | dev_dbg(hdmi->dev, "Read back EDID code:"); |
748 | for (i = 0; i < 128; i++) { | 723 | for (i = 0; i < 128; i++) { |
749 | edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW); | 724 | edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW); |
750 | #ifdef DEBUG | 725 | #ifdef DEBUG |
@@ -759,29 +734,97 @@ static void sh_hdmi_read_edid(struct sh_hdmi *hdmi) | |||
759 | #ifdef DEBUG | 734 | #ifdef DEBUG |
760 | printk(KERN_CONT "\n"); | 735 | printk(KERN_CONT "\n"); |
761 | #endif | 736 | #endif |
762 | fb_parse_edid(edid, var); | 737 | |
763 | pr_debug("%u-%u-%u-%u x %u-%u-%u-%u @ %lu kHz monitor detected\n", | 738 | fb_edid_to_monspecs(edid, &hdmi->monspec); |
764 | var->left_margin, var->xres, var->right_margin, var->hsync_len, | 739 | |
765 | var->upper_margin, var->yres, var->lower_margin, var->vsync_len, | 740 | fb_get_options("sh_mobile_lcdc", &forced); |
766 | PICOS2KHZ(var->pixclock)); | 741 | if (forced && *forced) { |
767 | 742 | /* Only primitive parsing so far */ | |
768 | /* FIXME: Use user-provided configuration instead of EDID */ | 743 | i = sscanf(forced, "%ux%u@%u", |
769 | var->width = width; | 744 | &f_width, &f_height, &f_refresh); |
770 | var->xres = lcd_cfg->xres; | 745 | if (i < 2) { |
771 | var->xres_virtual = lcd_cfg->xres; | 746 | f_width = 0; |
772 | var->left_margin = lcd_cfg->left_margin; | 747 | f_height = 0; |
773 | var->right_margin = lcd_cfg->right_margin; | 748 | } |
774 | var->hsync_len = lcd_cfg->hsync_len; | 749 | dev_dbg(hdmi->dev, "Forced mode %ux%u@%uHz\n", |
775 | var->height = height; | 750 | f_width, f_height, f_refresh); |
776 | var->yres = lcd_cfg->yres; | 751 | } |
777 | var->yres_virtual = lcd_cfg->yres * 2; | 752 | |
778 | var->upper_margin = lcd_cfg->upper_margin; | 753 | /* Walk monitor modes to find the best or the exact match */ |
779 | var->lower_margin = lcd_cfg->lower_margin; | 754 | for (i = 0, mode = hdmi->monspec.modedb; |
780 | var->vsync_len = lcd_cfg->vsync_len; | 755 | f_width && f_height && i < hdmi->monspec.modedb_len && !exact_match; |
781 | var->sync = lcd_cfg->sync; | 756 | i++, mode++) { |
782 | var->pixclock = lcd_cfg->pixclock; | 757 | unsigned long rate_error = sh_hdmi_rate_error(hdmi, mode); |
783 | 758 | ||
784 | hdmi_external_video_param(hdmi); | 759 | /* No interest in unmatching modes */ |
760 | if (f_width != mode->xres || f_height != mode->yres) | ||
761 | continue; | ||
762 | if (f_refresh == mode->refresh || (!f_refresh && !rate_error)) | ||
763 | /* | ||
764 | * Exact match if either the refresh rate matches or it | ||
765 | * hasn't been specified and we've found a mode, for | ||
766 | * which we can configure the clock precisely | ||
767 | */ | ||
768 | exact_match = true; | ||
769 | else if (found && found_rate_error <= rate_error) | ||
770 | /* | ||
771 | * We otherwise search for the closest matching clock | ||
772 | * rate - either if no refresh rate has been specified | ||
773 | * or we cannot find an exactly matching one | ||
774 | */ | ||
775 | continue; | ||
776 | |||
777 | /* Check if supported: sufficient fb memory, supported clock-rate */ | ||
778 | fb_videomode_to_var(var, mode); | ||
779 | |||
780 | if (info && info->fbops->fb_check_var && | ||
781 | info->fbops->fb_check_var(var, info)) { | ||
782 | exact_match = false; | ||
783 | continue; | ||
784 | } | ||
785 | |||
786 | found = mode; | ||
787 | found_rate_error = rate_error; | ||
788 | } | ||
789 | |||
790 | /* | ||
791 | * TODO 1: if no ->info is present, postpone running the config until | ||
792 | * after ->info first gets registered. | ||
793 | * TODO 2: consider registering the HDMI platform device from the LCDC | ||
794 | * driver, and passing ->info with HDMI platform data. | ||
795 | */ | ||
796 | if (info && !found) { | ||
797 | modelist = hdmi->info->modelist.next && | ||
798 | !list_empty(&hdmi->info->modelist) ? | ||
799 | list_entry(hdmi->info->modelist.next, | ||
800 | struct fb_modelist, list) : | ||
801 | NULL; | ||
802 | |||
803 | if (modelist) { | ||
804 | found = &modelist->mode; | ||
805 | found_rate_error = sh_hdmi_rate_error(hdmi, found); | ||
806 | } | ||
807 | } | ||
808 | |||
809 | /* No cookie today */ | ||
810 | if (!found) | ||
811 | return -ENXIO; | ||
812 | |||
813 | dev_info(hdmi->dev, "Using %s mode %ux%u@%uHz (%luHz), clock error %luHz\n", | ||
814 | modelist ? "default" : "EDID", found->xres, found->yres, | ||
815 | found->refresh, PICOS2KHZ(found->pixclock) * 1000, found_rate_error); | ||
816 | |||
817 | if ((found->xres == 720 && found->yres == 480) || | ||
818 | (found->xres == 1280 && found->yres == 720) || | ||
819 | (found->xres == 1920 && found->yres == 1080)) | ||
820 | hdmi->preprogrammed_mode = true; | ||
821 | else | ||
822 | hdmi->preprogrammed_mode = false; | ||
823 | |||
824 | fb_videomode_to_var(&hdmi->var, found); | ||
825 | sh_hdmi_external_video_param(hdmi); | ||
826 | |||
827 | return 0; | ||
785 | } | 828 | } |
786 | 829 | ||
787 | static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id) | 830 | static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id) |
@@ -809,8 +852,8 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id) | |||
809 | hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_2); | 852 | hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_2); |
810 | 853 | ||
811 | if (printk_ratelimit()) | 854 | if (printk_ratelimit()) |
812 | pr_debug("IRQ #%d: Status #1: 0x%x & 0x%x, #2: 0x%x & 0x%x\n", | 855 | dev_dbg(hdmi->dev, "IRQ #%d: Status #1: 0x%x & 0x%x, #2: 0x%x & 0x%x\n", |
813 | irq, status1, mask1, status2, mask2); | 856 | irq, status1, mask1, status2, mask2); |
814 | 857 | ||
815 | if (!((status1 & mask1) | (status2 & mask2))) { | 858 | if (!((status1 & mask1) | (status2 & mask2))) { |
816 | return IRQ_NONE; | 859 | return IRQ_NONE; |
@@ -821,7 +864,7 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id) | |||
821 | udelay(500); | 864 | udelay(500); |
822 | 865 | ||
823 | msens = hdmi_read(hdmi, HDMI_HOT_PLUG_MSENS_STATUS); | 866 | msens = hdmi_read(hdmi, HDMI_HOT_PLUG_MSENS_STATUS); |
824 | pr_debug("MSENS 0x%x\n", msens); | 867 | dev_dbg(hdmi->dev, "MSENS 0x%x\n", msens); |
825 | /* Check, if hot plug & MSENS pin status are both high */ | 868 | /* Check, if hot plug & MSENS pin status are both high */ |
826 | if ((msens & 0xC0) == 0xC0) { | 869 | if ((msens & 0xC0) == 0xC0) { |
827 | /* Display plug in */ | 870 | /* Display plug in */ |
@@ -857,83 +900,176 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id) | |||
857 | return IRQ_HANDLED; | 900 | return IRQ_HANDLED; |
858 | } | 901 | } |
859 | 902 | ||
860 | static void hdmi_display_on(void *arg, struct fb_info *info) | 903 | /* locking: called with info->lock held, or before register_framebuffer() */ |
904 | static void sh_hdmi_display_on(void *arg, struct fb_info *info) | ||
861 | { | 905 | { |
906 | /* | ||
907 | * info is guaranteed to be valid, when we are called, because our | ||
908 | * FB_EVENT_FB_UNBIND notify is also called with info->lock held | ||
909 | */ | ||
862 | struct sh_hdmi *hdmi = arg; | 910 | struct sh_hdmi *hdmi = arg; |
863 | struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; | 911 | struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; |
912 | struct sh_mobile_lcdc_chan *ch = info->par; | ||
864 | 913 | ||
865 | if (info->var.xres != 1280 || info->var.yres != 720) { | 914 | dev_dbg(hdmi->dev, "%s(%p): state %x\n", __func__, |
866 | dev_warn(info->device, "Unsupported framebuffer geometry %ux%u\n", | 915 | pdata->lcd_dev, info->state); |
867 | info->var.xres, info->var.yres); | 916 | |
868 | return; | 917 | /* No need to lock */ |
869 | } | 918 | hdmi->info = info; |
870 | 919 | ||
871 | pr_debug("%s(%p): state %x\n", __func__, pdata->lcd_dev, info->state); | ||
872 | /* | 920 | /* |
873 | * FIXME: not a good place to store fb_info. And we cannot nullify it | 921 | * hp_state can be set to |
874 | * even on monitor disconnect. What should the lifecycle be? | 922 | * HDMI_HOTPLUG_DISCONNECTED: on monitor unplug |
923 | * HDMI_HOTPLUG_CONNECTED: on monitor plug-in | ||
924 | * HDMI_HOTPLUG_EDID_DONE: on EDID read completion | ||
875 | */ | 925 | */ |
876 | hdmi->info = info; | ||
877 | switch (hdmi->hp_state) { | 926 | switch (hdmi->hp_state) { |
878 | case HDMI_HOTPLUG_EDID_DONE: | 927 | case HDMI_HOTPLUG_EDID_DONE: |
879 | /* PS mode d->e. All functions are active */ | 928 | /* PS mode d->e. All functions are active */ |
880 | hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL); | 929 | hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL); |
881 | pr_debug("HDMI running\n"); | 930 | dev_dbg(hdmi->dev, "HDMI running\n"); |
882 | break; | 931 | break; |
883 | case HDMI_HOTPLUG_DISCONNECTED: | 932 | case HDMI_HOTPLUG_DISCONNECTED: |
884 | info->state = FBINFO_STATE_SUSPENDED; | 933 | info->state = FBINFO_STATE_SUSPENDED; |
885 | default: | 934 | default: |
886 | hdmi->var = info->var; | 935 | hdmi->var = ch->display_var; |
887 | } | 936 | } |
888 | } | 937 | } |
889 | 938 | ||
890 | static void hdmi_display_off(void *arg) | 939 | /* locking: called with info->lock held */ |
940 | static void sh_hdmi_display_off(void *arg) | ||
891 | { | 941 | { |
892 | struct sh_hdmi *hdmi = arg; | 942 | struct sh_hdmi *hdmi = arg; |
893 | struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; | 943 | struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; |
894 | 944 | ||
895 | pr_debug("%s(%p)\n", __func__, pdata->lcd_dev); | 945 | dev_dbg(hdmi->dev, "%s(%p)\n", __func__, pdata->lcd_dev); |
896 | /* PS mode e->a */ | 946 | /* PS mode e->a */ |
897 | hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL); | 947 | hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL); |
898 | } | 948 | } |
899 | 949 | ||
950 | static bool sh_hdmi_must_reconfigure(struct sh_hdmi *hdmi) | ||
951 | { | ||
952 | struct fb_info *info = hdmi->info; | ||
953 | struct sh_mobile_lcdc_chan *ch = info->par; | ||
954 | struct fb_var_screeninfo *new_var = &hdmi->var, *old_var = &ch->display_var; | ||
955 | struct fb_videomode mode1, mode2; | ||
956 | |||
957 | fb_var_to_videomode(&mode1, old_var); | ||
958 | fb_var_to_videomode(&mode2, new_var); | ||
959 | |||
960 | dev_dbg(info->dev, "Old %ux%u, new %ux%u\n", | ||
961 | mode1.xres, mode1.yres, mode2.xres, mode2.yres); | ||
962 | |||
963 | if (fb_mode_is_equal(&mode1, &mode2)) | ||
964 | return false; | ||
965 | |||
966 | dev_dbg(info->dev, "Switching %u -> %u lines\n", | ||
967 | mode1.yres, mode2.yres); | ||
968 | *old_var = *new_var; | ||
969 | |||
970 | return true; | ||
971 | } | ||
972 | |||
973 | /** | ||
974 | * sh_hdmi_clk_configure() - set HDMI clock frequency and enable the clock | ||
975 | * @hdmi: driver context | ||
976 | * @pixclock: pixel clock period in picoseconds | ||
977 | * return: configured positive rate if successful | ||
978 | * 0 if couldn't set the rate, but managed to enable the clock | ||
979 | * negative error, if couldn't enable the clock | ||
980 | */ | ||
981 | static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long pixclock) | ||
982 | { | ||
983 | long rate; | ||
984 | int ret; | ||
985 | |||
986 | rate = PICOS2KHZ(pixclock) * 1000; | ||
987 | rate = clk_round_rate(hdmi->hdmi_clk, rate); | ||
988 | if (rate > 0) { | ||
989 | ret = clk_set_rate(hdmi->hdmi_clk, rate); | ||
990 | if (ret < 0) { | ||
991 | dev_warn(hdmi->dev, "Cannot set rate %ld: %d\n", rate, ret); | ||
992 | rate = 0; | ||
993 | } else { | ||
994 | dev_dbg(hdmi->dev, "HDMI set frequency %lu\n", rate); | ||
995 | } | ||
996 | } else { | ||
997 | rate = 0; | ||
998 | dev_warn(hdmi->dev, "Cannot get suitable rate: %ld\n", rate); | ||
999 | } | ||
1000 | |||
1001 | ret = clk_enable(hdmi->hdmi_clk); | ||
1002 | if (ret < 0) { | ||
1003 | dev_err(hdmi->dev, "Cannot enable clock: %d\n", ret); | ||
1004 | return ret; | ||
1005 | } | ||
1006 | |||
1007 | return rate; | ||
1008 | } | ||
1009 | |||
900 | /* Hotplug interrupt occurred, read EDID */ | 1010 | /* Hotplug interrupt occurred, read EDID */ |
901 | static void edid_work_fn(struct work_struct *work) | 1011 | static void sh_hdmi_edid_work_fn(struct work_struct *work) |
902 | { | 1012 | { |
903 | struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work); | 1013 | struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work); |
904 | struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; | 1014 | struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; |
1015 | struct sh_mobile_lcdc_chan *ch; | ||
1016 | int ret; | ||
905 | 1017 | ||
906 | pr_debug("%s(%p): begin, hotplug status %d\n", __func__, | 1018 | dev_dbg(hdmi->dev, "%s(%p): begin, hotplug status %d\n", __func__, |
907 | pdata->lcd_dev, hdmi->hp_state); | 1019 | pdata->lcd_dev, hdmi->hp_state); |
908 | 1020 | ||
909 | if (!pdata->lcd_dev) | 1021 | if (!pdata->lcd_dev) |
910 | return; | 1022 | return; |
911 | 1023 | ||
1024 | mutex_lock(&hdmi->mutex); | ||
1025 | |||
912 | if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) { | 1026 | if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) { |
913 | pm_runtime_get_sync(hdmi->dev); | ||
914 | /* A device has been plugged in */ | 1027 | /* A device has been plugged in */ |
915 | sh_hdmi_read_edid(hdmi); | 1028 | pm_runtime_get_sync(hdmi->dev); |
1029 | |||
1030 | ret = sh_hdmi_read_edid(hdmi); | ||
1031 | if (ret < 0) | ||
1032 | goto out; | ||
1033 | |||
1034 | /* Reconfigure the clock */ | ||
1035 | clk_disable(hdmi->hdmi_clk); | ||
1036 | ret = sh_hdmi_clk_configure(hdmi, hdmi->var.pixclock); | ||
1037 | if (ret < 0) | ||
1038 | goto out; | ||
1039 | |||
916 | msleep(10); | 1040 | msleep(10); |
917 | sh_hdmi_configure(hdmi); | 1041 | sh_hdmi_configure(hdmi); |
918 | /* Switched to another (d) power-save mode */ | 1042 | /* Switched to another (d) power-save mode */ |
919 | msleep(10); | 1043 | msleep(10); |
920 | 1044 | ||
921 | if (!hdmi->info) | 1045 | if (!hdmi->info) |
922 | return; | 1046 | goto out; |
1047 | |||
1048 | ch = hdmi->info->par; | ||
923 | 1049 | ||
924 | acquire_console_sem(); | 1050 | acquire_console_sem(); |
925 | 1051 | ||
926 | /* HDMI plug in */ | 1052 | /* HDMI plug in */ |
927 | hdmi->info->var = hdmi->var; | 1053 | if (!sh_hdmi_must_reconfigure(hdmi) && |
928 | if (hdmi->info->state != FBINFO_STATE_RUNNING) | 1054 | hdmi->info->state == FBINFO_STATE_RUNNING) { |
1055 | /* | ||
1056 | * First activation with the default monitor - just turn | ||
1057 | * on, if we run a resume here, the logo disappears | ||
1058 | */ | ||
1059 | if (lock_fb_info(hdmi->info)) { | ||
1060 | sh_hdmi_display_on(hdmi, hdmi->info); | ||
1061 | unlock_fb_info(hdmi->info); | ||
1062 | } | ||
1063 | } else { | ||
1064 | /* New monitor or have to wake up */ | ||
929 | fb_set_suspend(hdmi->info, 0); | 1065 | fb_set_suspend(hdmi->info, 0); |
930 | else | 1066 | } |
931 | hdmi_display_on(hdmi, hdmi->info); | ||
932 | 1067 | ||
933 | release_console_sem(); | 1068 | release_console_sem(); |
934 | } else { | 1069 | } else { |
1070 | ret = 0; | ||
935 | if (!hdmi->info) | 1071 | if (!hdmi->info) |
936 | return; | 1072 | goto out; |
937 | 1073 | ||
938 | acquire_console_sem(); | 1074 | acquire_console_sem(); |
939 | 1075 | ||
@@ -942,15 +1078,67 @@ static void edid_work_fn(struct work_struct *work) | |||
942 | 1078 | ||
943 | release_console_sem(); | 1079 | release_console_sem(); |
944 | pm_runtime_put(hdmi->dev); | 1080 | pm_runtime_put(hdmi->dev); |
1081 | fb_destroy_modedb(hdmi->monspec.modedb); | ||
945 | } | 1082 | } |
946 | 1083 | ||
947 | pr_debug("%s(%p): end\n", __func__, pdata->lcd_dev); | 1084 | out: |
1085 | if (ret < 0) | ||
1086 | hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED; | ||
1087 | mutex_unlock(&hdmi->mutex); | ||
1088 | |||
1089 | dev_dbg(hdmi->dev, "%s(%p): end\n", __func__, pdata->lcd_dev); | ||
1090 | } | ||
1091 | |||
1092 | static int sh_hdmi_notify(struct notifier_block *nb, | ||
1093 | unsigned long action, void *data); | ||
1094 | |||
1095 | static struct notifier_block sh_hdmi_notifier = { | ||
1096 | .notifier_call = sh_hdmi_notify, | ||
1097 | }; | ||
1098 | |||
1099 | static int sh_hdmi_notify(struct notifier_block *nb, | ||
1100 | unsigned long action, void *data) | ||
1101 | { | ||
1102 | struct fb_event *event = data; | ||
1103 | struct fb_info *info = event->info; | ||
1104 | struct sh_mobile_lcdc_chan *ch = info->par; | ||
1105 | struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg; | ||
1106 | struct sh_hdmi *hdmi = board_cfg->board_data; | ||
1107 | |||
1108 | if (nb != &sh_hdmi_notifier || !hdmi || hdmi->info != info) | ||
1109 | return NOTIFY_DONE; | ||
1110 | |||
1111 | switch(action) { | ||
1112 | case FB_EVENT_FB_REGISTERED: | ||
1113 | /* Unneeded, activation taken care by sh_hdmi_display_on() */ | ||
1114 | break; | ||
1115 | case FB_EVENT_FB_UNREGISTERED: | ||
1116 | /* | ||
1117 | * We are called from unregister_framebuffer() with the | ||
1118 | * info->lock held. This is bad for us, because we can race with | ||
1119 | * the scheduled work, which has to call fb_set_suspend(), which | ||
1120 | * takes info->lock internally, so, sh_hdmi_edid_work_fn() | ||
1121 | * cannot take and hold info->lock for the whole function | ||
1122 | * duration. Using an additional lock creates a classical AB-BA | ||
1123 | * lock up. Therefore, we have to release the info->lock | ||
1124 | * temporarily, synchronise with the work queue and re-acquire | ||
1125 | * the info->lock. | ||
1126 | */ | ||
1127 | unlock_fb_info(hdmi->info); | ||
1128 | mutex_lock(&hdmi->mutex); | ||
1129 | hdmi->info = NULL; | ||
1130 | mutex_unlock(&hdmi->mutex); | ||
1131 | lock_fb_info(hdmi->info); | ||
1132 | return NOTIFY_OK; | ||
1133 | } | ||
1134 | return NOTIFY_DONE; | ||
948 | } | 1135 | } |
949 | 1136 | ||
950 | static int __init sh_hdmi_probe(struct platform_device *pdev) | 1137 | static int __init sh_hdmi_probe(struct platform_device *pdev) |
951 | { | 1138 | { |
952 | struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; | 1139 | struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; |
953 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1140 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1141 | struct sh_mobile_lcdc_board_cfg *board_cfg; | ||
954 | int irq = platform_get_irq(pdev, 0), ret; | 1142 | int irq = platform_get_irq(pdev, 0), ret; |
955 | struct sh_hdmi *hdmi; | 1143 | struct sh_hdmi *hdmi; |
956 | long rate; | 1144 | long rate; |
@@ -964,10 +1152,7 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) | |||
964 | return -ENOMEM; | 1152 | return -ENOMEM; |
965 | } | 1153 | } |
966 | 1154 | ||
967 | ret = snd_soc_register_codec(&pdev->dev, | 1155 | mutex_init(&hdmi->mutex); |
968 | &soc_codec_dev_sh_hdmi, &sh_hdmi_dai, 1); | ||
969 | if (ret < 0) | ||
970 | goto esndreg; | ||
971 | 1156 | ||
972 | hdmi->dev = &pdev->dev; | 1157 | hdmi->dev = &pdev->dev; |
973 | 1158 | ||
@@ -978,30 +1163,14 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) | |||
978 | goto egetclk; | 1163 | goto egetclk; |
979 | } | 1164 | } |
980 | 1165 | ||
981 | rate = PICOS2KHZ(pdata->lcd_chan->lcd_cfg.pixclock) * 1000; | 1166 | /* Some arbitrary relaxed pixclock just to get things started */ |
982 | 1167 | rate = sh_hdmi_clk_configure(hdmi, 37037); | |
983 | rate = clk_round_rate(hdmi->hdmi_clk, rate); | ||
984 | if (rate < 0) { | 1168 | if (rate < 0) { |
985 | ret = rate; | 1169 | ret = rate; |
986 | dev_err(&pdev->dev, "Cannot get suitable rate: %ld\n", rate); | ||
987 | goto erate; | 1170 | goto erate; |
988 | } | 1171 | } |
989 | 1172 | ||
990 | ret = clk_set_rate(hdmi->hdmi_clk, rate); | 1173 | dev_dbg(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate); |
991 | if (ret < 0) { | ||
992 | dev_err(&pdev->dev, "Cannot set rate %ld: %d\n", rate, ret); | ||
993 | goto erate; | ||
994 | } | ||
995 | |||
996 | pr_debug("HDMI set frequency %lu\n", rate); | ||
997 | |||
998 | ret = clk_enable(hdmi->hdmi_clk); | ||
999 | if (ret < 0) { | ||
1000 | dev_err(&pdev->dev, "Cannot enable clock: %d\n", ret); | ||
1001 | goto eclkenable; | ||
1002 | } | ||
1003 | |||
1004 | dev_info(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate); | ||
1005 | 1174 | ||
1006 | if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) { | 1175 | if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) { |
1007 | dev_err(&pdev->dev, "HDMI register region already claimed\n"); | 1176 | dev_err(&pdev->dev, "HDMI register region already claimed\n"); |
@@ -1018,18 +1187,18 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) | |||
1018 | 1187 | ||
1019 | platform_set_drvdata(pdev, hdmi); | 1188 | platform_set_drvdata(pdev, hdmi); |
1020 | 1189 | ||
1021 | #if 1 | ||
1022 | /* Product and revision IDs are 0 in sh-mobile version */ | 1190 | /* Product and revision IDs are 0 in sh-mobile version */ |
1023 | dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n", | 1191 | dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n", |
1024 | hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID)); | 1192 | hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID)); |
1025 | #endif | ||
1026 | 1193 | ||
1027 | /* Set up LCDC callbacks */ | 1194 | /* Set up LCDC callbacks */ |
1028 | pdata->lcd_chan->board_cfg.board_data = hdmi; | 1195 | board_cfg = &pdata->lcd_chan->board_cfg; |
1029 | pdata->lcd_chan->board_cfg.display_on = hdmi_display_on; | 1196 | board_cfg->owner = THIS_MODULE; |
1030 | pdata->lcd_chan->board_cfg.display_off = hdmi_display_off; | 1197 | board_cfg->board_data = hdmi; |
1198 | board_cfg->display_on = sh_hdmi_display_on; | ||
1199 | board_cfg->display_off = sh_hdmi_display_off; | ||
1031 | 1200 | ||
1032 | INIT_DELAYED_WORK(&hdmi->edid_work, edid_work_fn); | 1201 | INIT_DELAYED_WORK(&hdmi->edid_work, sh_hdmi_edid_work_fn); |
1033 | 1202 | ||
1034 | pm_runtime_enable(&pdev->dev); | 1203 | pm_runtime_enable(&pdev->dev); |
1035 | pm_runtime_resume(&pdev->dev); | 1204 | pm_runtime_resume(&pdev->dev); |
@@ -1041,8 +1210,17 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) | |||
1041 | goto ereqirq; | 1210 | goto ereqirq; |
1042 | } | 1211 | } |
1043 | 1212 | ||
1213 | ret = snd_soc_register_codec(&pdev->dev, | ||
1214 | &soc_codec_dev_sh_hdmi, &sh_hdmi_dai, 1); | ||
1215 | if (ret < 0) { | ||
1216 | dev_err(&pdev->dev, "codec registration failed\n"); | ||
1217 | goto ecodec; | ||
1218 | } | ||
1219 | |||
1044 | return 0; | 1220 | return 0; |
1045 | 1221 | ||
1222 | ecodec: | ||
1223 | free_irq(irq, hdmi); | ||
1046 | ereqirq: | 1224 | ereqirq: |
1047 | pm_runtime_disable(&pdev->dev); | 1225 | pm_runtime_disable(&pdev->dev); |
1048 | iounmap(hdmi->base); | 1226 | iounmap(hdmi->base); |
@@ -1050,12 +1228,10 @@ emap: | |||
1050 | release_mem_region(res->start, resource_size(res)); | 1228 | release_mem_region(res->start, resource_size(res)); |
1051 | ereqreg: | 1229 | ereqreg: |
1052 | clk_disable(hdmi->hdmi_clk); | 1230 | clk_disable(hdmi->hdmi_clk); |
1053 | eclkenable: | ||
1054 | erate: | 1231 | erate: |
1055 | clk_put(hdmi->hdmi_clk); | 1232 | clk_put(hdmi->hdmi_clk); |
1056 | egetclk: | 1233 | egetclk: |
1057 | snd_soc_unregister_codec(&pdev->dev); | 1234 | mutex_destroy(&hdmi->mutex); |
1058 | esndreg: | ||
1059 | kfree(hdmi); | 1235 | kfree(hdmi); |
1060 | 1236 | ||
1061 | return ret; | 1237 | return ret; |
@@ -1066,21 +1242,26 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev) | |||
1066 | struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; | 1242 | struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; |
1067 | struct sh_hdmi *hdmi = platform_get_drvdata(pdev); | 1243 | struct sh_hdmi *hdmi = platform_get_drvdata(pdev); |
1068 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1244 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1245 | struct sh_mobile_lcdc_board_cfg *board_cfg = &pdata->lcd_chan->board_cfg; | ||
1069 | int irq = platform_get_irq(pdev, 0); | 1246 | int irq = platform_get_irq(pdev, 0); |
1070 | 1247 | ||
1071 | snd_soc_unregister_codec(&pdev->dev); | 1248 | snd_soc_unregister_codec(&pdev->dev); |
1072 | 1249 | ||
1073 | pdata->lcd_chan->board_cfg.display_on = NULL; | 1250 | board_cfg->display_on = NULL; |
1074 | pdata->lcd_chan->board_cfg.display_off = NULL; | 1251 | board_cfg->display_off = NULL; |
1075 | pdata->lcd_chan->board_cfg.board_data = NULL; | 1252 | board_cfg->board_data = NULL; |
1253 | board_cfg->owner = NULL; | ||
1076 | 1254 | ||
1255 | /* No new work will be scheduled, wait for running ISR */ | ||
1077 | free_irq(irq, hdmi); | 1256 | free_irq(irq, hdmi); |
1078 | pm_runtime_disable(&pdev->dev); | 1257 | /* Wait for already scheduled work */ |
1079 | cancel_delayed_work_sync(&hdmi->edid_work); | 1258 | cancel_delayed_work_sync(&hdmi->edid_work); |
1259 | pm_runtime_disable(&pdev->dev); | ||
1080 | clk_disable(hdmi->hdmi_clk); | 1260 | clk_disable(hdmi->hdmi_clk); |
1081 | clk_put(hdmi->hdmi_clk); | 1261 | clk_put(hdmi->hdmi_clk); |
1082 | iounmap(hdmi->base); | 1262 | iounmap(hdmi->base); |
1083 | release_mem_region(res->start, resource_size(res)); | 1263 | release_mem_region(res->start, resource_size(res)); |
1264 | mutex_destroy(&hdmi->mutex); | ||
1084 | kfree(hdmi); | 1265 | kfree(hdmi); |
1085 | 1266 | ||
1086 | return 0; | 1267 | return 0; |
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 7a1419279c8f..50963739a409 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
14 | #include <linux/mm.h> | 14 | #include <linux/mm.h> |
15 | #include <linux/fb.h> | ||
16 | #include <linux/clk.h> | 15 | #include <linux/clk.h> |
17 | #include <linux/pm_runtime.h> | 16 | #include <linux/pm_runtime.h> |
18 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
@@ -21,10 +20,12 @@ | |||
21 | #include <linux/vmalloc.h> | 20 | #include <linux/vmalloc.h> |
22 | #include <linux/ioctl.h> | 21 | #include <linux/ioctl.h> |
23 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/console.h> | ||
24 | #include <video/sh_mobile_lcdc.h> | 24 | #include <video/sh_mobile_lcdc.h> |
25 | #include <asm/atomic.h> | 25 | #include <asm/atomic.h> |
26 | 26 | ||
27 | #define PALETTE_NR 16 | 27 | #include "sh_mobile_lcdcfb.h" |
28 | |||
28 | #define SIDE_B_OFFSET 0x1000 | 29 | #define SIDE_B_OFFSET 0x1000 |
29 | #define MIRROR_OFFSET 0x2000 | 30 | #define MIRROR_OFFSET 0x2000 |
30 | 31 | ||
@@ -53,11 +54,8 @@ static int lcdc_shared_regs[] = { | |||
53 | }; | 54 | }; |
54 | #define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs) | 55 | #define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs) |
55 | 56 | ||
56 | /* per-channel registers */ | 57 | #define DEFAULT_XRES 1280 |
57 | enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R, | 58 | #define DEFAULT_YRES 1024 |
58 | LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR, | ||
59 | LDHAJR, | ||
60 | NR_CH_REGS }; | ||
61 | 59 | ||
62 | static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { | 60 | static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { |
63 | [LDDCKPAT1R] = 0x400, | 61 | [LDDCKPAT1R] = 0x400, |
@@ -112,23 +110,21 @@ static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = { | |||
112 | #define LDRCNTR_MRC 0x00000001 | 110 | #define LDRCNTR_MRC 0x00000001 |
113 | #define LDSR_MRS 0x00000100 | 111 | #define LDSR_MRS 0x00000100 |
114 | 112 | ||
115 | struct sh_mobile_lcdc_priv; | 113 | static const struct fb_videomode default_720p = { |
116 | struct sh_mobile_lcdc_chan { | 114 | .name = "HDMI 720p", |
117 | struct sh_mobile_lcdc_priv *lcdc; | 115 | .xres = 1280, |
118 | unsigned long *reg_offs; | 116 | .yres = 720, |
119 | unsigned long ldmt1r_value; | 117 | |
120 | unsigned long enabled; /* ME and SE in LDCNT2R */ | 118 | .left_margin = 200, |
121 | struct sh_mobile_lcdc_chan_cfg cfg; | 119 | .right_margin = 88, |
122 | u32 pseudo_palette[PALETTE_NR]; | 120 | .hsync_len = 48, |
123 | unsigned long saved_ch_regs[NR_CH_REGS]; | 121 | |
124 | struct fb_info *info; | 122 | .upper_margin = 20, |
125 | dma_addr_t dma_handle; | 123 | .lower_margin = 5, |
126 | struct fb_deferred_io defio; | 124 | .vsync_len = 5, |
127 | struct scatterlist *sglist; | 125 | |
128 | unsigned long frame_end; | 126 | .pixclock = 13468, |
129 | unsigned long pan_offset; | 127 | .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, |
130 | wait_queue_head_t frame_end_wait; | ||
131 | struct completion vsync_completion; | ||
132 | }; | 128 | }; |
133 | 129 | ||
134 | struct sh_mobile_lcdc_priv { | 130 | struct sh_mobile_lcdc_priv { |
@@ -409,8 +405,8 @@ static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv, | |||
409 | 405 | ||
410 | static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) | 406 | static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) |
411 | { | 407 | { |
412 | struct fb_var_screeninfo *var = &ch->info->var; | 408 | struct fb_var_screeninfo *var = &ch->info->var, *display_var = &ch->display_var; |
413 | unsigned long h_total, hsync_pos; | 409 | unsigned long h_total, hsync_pos, display_h_total; |
414 | u32 tmp; | 410 | u32 tmp; |
415 | 411 | ||
416 | tmp = ch->ldmt1r_value; | 412 | tmp = ch->ldmt1r_value; |
@@ -428,31 +424,33 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) | |||
428 | lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r); | 424 | lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r); |
429 | 425 | ||
430 | /* horizontal configuration */ | 426 | /* horizontal configuration */ |
431 | h_total = var->xres + var->hsync_len + | 427 | h_total = display_var->xres + display_var->hsync_len + |
432 | var->left_margin + var->right_margin; | 428 | display_var->left_margin + display_var->right_margin; |
433 | tmp = h_total / 8; /* HTCN */ | 429 | tmp = h_total / 8; /* HTCN */ |
434 | tmp |= (var->xres / 8) << 16; /* HDCN */ | 430 | tmp |= (min(display_var->xres, var->xres) / 8) << 16; /* HDCN */ |
435 | lcdc_write_chan(ch, LDHCNR, tmp); | 431 | lcdc_write_chan(ch, LDHCNR, tmp); |
436 | 432 | ||
437 | hsync_pos = var->xres + var->right_margin; | 433 | hsync_pos = display_var->xres + display_var->right_margin; |
438 | tmp = hsync_pos / 8; /* HSYNP */ | 434 | tmp = hsync_pos / 8; /* HSYNP */ |
439 | tmp |= (var->hsync_len / 8) << 16; /* HSYNW */ | 435 | tmp |= (display_var->hsync_len / 8) << 16; /* HSYNW */ |
440 | lcdc_write_chan(ch, LDHSYNR, tmp); | 436 | lcdc_write_chan(ch, LDHSYNR, tmp); |
441 | 437 | ||
442 | /* vertical configuration */ | 438 | /* vertical configuration */ |
443 | tmp = var->yres + var->vsync_len + | 439 | tmp = display_var->yres + display_var->vsync_len + |
444 | var->upper_margin + var->lower_margin; /* VTLN */ | 440 | display_var->upper_margin + display_var->lower_margin; /* VTLN */ |
445 | tmp |= var->yres << 16; /* VDLN */ | 441 | tmp |= min(display_var->yres, var->yres) << 16; /* VDLN */ |
446 | lcdc_write_chan(ch, LDVLNR, tmp); | 442 | lcdc_write_chan(ch, LDVLNR, tmp); |
447 | 443 | ||
448 | tmp = var->yres + var->lower_margin; /* VSYNP */ | 444 | tmp = display_var->yres + display_var->lower_margin; /* VSYNP */ |
449 | tmp |= var->vsync_len << 16; /* VSYNW */ | 445 | tmp |= display_var->vsync_len << 16; /* VSYNW */ |
450 | lcdc_write_chan(ch, LDVSYNR, tmp); | 446 | lcdc_write_chan(ch, LDVSYNR, tmp); |
451 | 447 | ||
452 | /* Adjust horizontal synchronisation for HDMI */ | 448 | /* Adjust horizontal synchronisation for HDMI */ |
453 | tmp = ((var->xres & 7) << 24) | | 449 | display_h_total = display_var->xres + display_var->hsync_len + |
454 | ((h_total & 7) << 16) | | 450 | display_var->left_margin + display_var->right_margin; |
455 | ((var->hsync_len & 7) << 8) | | 451 | tmp = ((display_var->xres & 7) << 24) | |
452 | ((display_h_total & 7) << 16) | | ||
453 | ((display_var->hsync_len & 7) << 8) | | ||
456 | hsync_pos; | 454 | hsync_pos; |
457 | lcdc_write_chan(ch, LDHAJR, tmp); | 455 | lcdc_write_chan(ch, LDHAJR, tmp); |
458 | } | 456 | } |
@@ -460,7 +458,6 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) | |||
460 | static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) | 458 | static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) |
461 | { | 459 | { |
462 | struct sh_mobile_lcdc_chan *ch; | 460 | struct sh_mobile_lcdc_chan *ch; |
463 | struct fb_videomode *lcd_cfg; | ||
464 | struct sh_mobile_lcdc_board_cfg *board_cfg; | 461 | struct sh_mobile_lcdc_board_cfg *board_cfg; |
465 | unsigned long tmp; | 462 | unsigned long tmp; |
466 | int k, m; | 463 | int k, m; |
@@ -503,7 +500,8 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) | |||
503 | m = 1 << 6; | 500 | m = 1 << 6; |
504 | tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0); | 501 | tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0); |
505 | 502 | ||
506 | lcdc_write_chan(ch, LDDCKPAT1R, 0x00000000); | 503 | /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider denominator */ |
504 | lcdc_write_chan(ch, LDDCKPAT1R, 0); | ||
507 | lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1); | 505 | lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1); |
508 | } | 506 | } |
509 | 507 | ||
@@ -518,7 +516,6 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) | |||
518 | 516 | ||
519 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | 517 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { |
520 | ch = &priv->ch[k]; | 518 | ch = &priv->ch[k]; |
521 | lcd_cfg = &ch->cfg.lcd_cfg; | ||
522 | 519 | ||
523 | if (!ch->enabled) | 520 | if (!ch->enabled) |
524 | continue; | 521 | continue; |
@@ -547,7 +544,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) | |||
547 | 544 | ||
548 | /* set bpp format in PKF[4:0] */ | 545 | /* set bpp format in PKF[4:0] */ |
549 | tmp = lcdc_read_chan(ch, LDDFR); | 546 | tmp = lcdc_read_chan(ch, LDDFR); |
550 | tmp &= ~(0x0001001f); | 547 | tmp &= ~0x0001001f; |
551 | tmp |= (ch->info->var.bits_per_pixel == 16) ? 3 : 0; | 548 | tmp |= (ch->info->var.bits_per_pixel == 16) ? 3 : 0; |
552 | lcdc_write_chan(ch, LDDFR, tmp); | 549 | lcdc_write_chan(ch, LDDFR, tmp); |
553 | 550 | ||
@@ -591,8 +588,10 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) | |||
591 | continue; | 588 | continue; |
592 | 589 | ||
593 | board_cfg = &ch->cfg.board_cfg; | 590 | board_cfg = &ch->cfg.board_cfg; |
594 | if (board_cfg->display_on) | 591 | if (try_module_get(board_cfg->owner) && board_cfg->display_on) { |
595 | board_cfg->display_on(board_cfg->board_data, ch->info); | 592 | board_cfg->display_on(board_cfg->board_data, ch->info); |
593 | module_put(board_cfg->owner); | ||
594 | } | ||
596 | } | 595 | } |
597 | 596 | ||
598 | return 0; | 597 | return 0; |
@@ -614,7 +613,7 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) | |||
614 | * flush frame, and wait for frame end interrupt | 613 | * flush frame, and wait for frame end interrupt |
615 | * clean up deferred io and enable clock | 614 | * clean up deferred io and enable clock |
616 | */ | 615 | */ |
617 | if (ch->info->fbdefio) { | 616 | if (ch->info && ch->info->fbdefio) { |
618 | ch->frame_end = 0; | 617 | ch->frame_end = 0; |
619 | schedule_delayed_work(&ch->info->deferred_work, 0); | 618 | schedule_delayed_work(&ch->info->deferred_work, 0); |
620 | wait_event(ch->frame_end_wait, ch->frame_end); | 619 | wait_event(ch->frame_end_wait, ch->frame_end); |
@@ -624,8 +623,10 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) | |||
624 | } | 623 | } |
625 | 624 | ||
626 | board_cfg = &ch->cfg.board_cfg; | 625 | board_cfg = &ch->cfg.board_cfg; |
627 | if (board_cfg->display_off) | 626 | if (try_module_get(board_cfg->owner) && board_cfg->display_off) { |
628 | board_cfg->display_off(board_cfg->board_data); | 627 | board_cfg->display_off(board_cfg->board_data); |
628 | module_put(board_cfg->owner); | ||
629 | } | ||
629 | } | 630 | } |
630 | 631 | ||
631 | /* stop the lcdc */ | 632 | /* stop the lcdc */ |
@@ -704,7 +705,6 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev, | |||
704 | return PTR_ERR(priv->dot_clk); | 705 | return PTR_ERR(priv->dot_clk); |
705 | } | 706 | } |
706 | } | 707 | } |
707 | atomic_set(&priv->hw_usecnt, -1); | ||
708 | 708 | ||
709 | /* Runtime PM support involves two step for this driver: | 709 | /* Runtime PM support involves two step for this driver: |
710 | * 1) Enable Runtime PM | 710 | * 1) Enable Runtime PM |
@@ -837,6 +837,102 @@ static int sh_mobile_ioctl(struct fb_info *info, unsigned int cmd, | |||
837 | return retval; | 837 | return retval; |
838 | } | 838 | } |
839 | 839 | ||
840 | static void sh_mobile_fb_reconfig(struct fb_info *info) | ||
841 | { | ||
842 | struct sh_mobile_lcdc_chan *ch = info->par; | ||
843 | struct fb_videomode mode1, mode2; | ||
844 | struct fb_event event; | ||
845 | int evnt = FB_EVENT_MODE_CHANGE_ALL; | ||
846 | |||
847 | if (ch->use_count > 1 || (ch->use_count == 1 && !info->fbcon_par)) | ||
848 | /* More framebuffer users are active */ | ||
849 | return; | ||
850 | |||
851 | fb_var_to_videomode(&mode1, &ch->display_var); | ||
852 | fb_var_to_videomode(&mode2, &info->var); | ||
853 | |||
854 | if (fb_mode_is_equal(&mode1, &mode2)) | ||
855 | return; | ||
856 | |||
857 | /* Display has been re-plugged, framebuffer is free now, reconfigure */ | ||
858 | if (fb_set_var(info, &ch->display_var) < 0) | ||
859 | /* Couldn't reconfigure, hopefully, can continue as before */ | ||
860 | return; | ||
861 | |||
862 | info->fix.line_length = mode2.xres * (ch->cfg.bpp / 8); | ||
863 | |||
864 | /* | ||
865 | * fb_set_var() calls the notifier change internally, only if | ||
866 | * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a | ||
867 | * user event, we have to call the chain ourselves. | ||
868 | */ | ||
869 | event.info = info; | ||
870 | event.data = &mode2; | ||
871 | fb_notifier_call_chain(evnt, &event); | ||
872 | } | ||
873 | |||
874 | /* | ||
875 | * Locking: both .fb_release() and .fb_open() are called with info->lock held if | ||
876 | * user == 1, or with console sem held, if user == 0. | ||
877 | */ | ||
878 | static int sh_mobile_release(struct fb_info *info, int user) | ||
879 | { | ||
880 | struct sh_mobile_lcdc_chan *ch = info->par; | ||
881 | |||
882 | mutex_lock(&ch->open_lock); | ||
883 | dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count); | ||
884 | |||
885 | ch->use_count--; | ||
886 | |||
887 | /* Nothing to reconfigure, when called from fbcon */ | ||
888 | if (user) { | ||
889 | acquire_console_sem(); | ||
890 | sh_mobile_fb_reconfig(info); | ||
891 | release_console_sem(); | ||
892 | } | ||
893 | |||
894 | mutex_unlock(&ch->open_lock); | ||
895 | |||
896 | return 0; | ||
897 | } | ||
898 | |||
899 | static int sh_mobile_open(struct fb_info *info, int user) | ||
900 | { | ||
901 | struct sh_mobile_lcdc_chan *ch = info->par; | ||
902 | |||
903 | mutex_lock(&ch->open_lock); | ||
904 | ch->use_count++; | ||
905 | |||
906 | dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count); | ||
907 | mutex_unlock(&ch->open_lock); | ||
908 | |||
909 | return 0; | ||
910 | } | ||
911 | |||
912 | static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | ||
913 | { | ||
914 | struct sh_mobile_lcdc_chan *ch = info->par; | ||
915 | |||
916 | if (var->xres < 160 || var->xres > 1920 || | ||
917 | var->yres < 120 || var->yres > 1080 || | ||
918 | var->left_margin < 32 || var->left_margin > 320 || | ||
919 | var->right_margin < 12 || var->right_margin > 240 || | ||
920 | var->upper_margin < 12 || var->upper_margin > 120 || | ||
921 | var->lower_margin < 1 || var->lower_margin > 64 || | ||
922 | var->hsync_len < 32 || var->hsync_len > 240 || | ||
923 | var->vsync_len < 2 || var->vsync_len > 64 || | ||
924 | var->pixclock < 6000 || var->pixclock > 40000 || | ||
925 | var->xres * var->yres * (ch->cfg.bpp / 8) * 2 > info->fix.smem_len) { | ||
926 | dev_warn(info->dev, "Invalid info: %u %u %u %u %u %u %u %u %u!\n", | ||
927 | var->xres, var->yres, | ||
928 | var->left_margin, var->right_margin, | ||
929 | var->upper_margin, var->lower_margin, | ||
930 | var->hsync_len, var->vsync_len, | ||
931 | var->pixclock); | ||
932 | return -EINVAL; | ||
933 | } | ||
934 | return 0; | ||
935 | } | ||
840 | 936 | ||
841 | static struct fb_ops sh_mobile_lcdc_ops = { | 937 | static struct fb_ops sh_mobile_lcdc_ops = { |
842 | .owner = THIS_MODULE, | 938 | .owner = THIS_MODULE, |
@@ -848,6 +944,9 @@ static struct fb_ops sh_mobile_lcdc_ops = { | |||
848 | .fb_imageblit = sh_mobile_lcdc_imageblit, | 944 | .fb_imageblit = sh_mobile_lcdc_imageblit, |
849 | .fb_pan_display = sh_mobile_fb_pan_display, | 945 | .fb_pan_display = sh_mobile_fb_pan_display, |
850 | .fb_ioctl = sh_mobile_ioctl, | 946 | .fb_ioctl = sh_mobile_ioctl, |
947 | .fb_open = sh_mobile_open, | ||
948 | .fb_release = sh_mobile_release, | ||
949 | .fb_check_var = sh_mobile_check_var, | ||
851 | }; | 950 | }; |
852 | 951 | ||
853 | static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp) | 952 | static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp) |
@@ -958,6 +1057,7 @@ static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = { | |||
958 | .runtime_resume = sh_mobile_lcdc_runtime_resume, | 1057 | .runtime_resume = sh_mobile_lcdc_runtime_resume, |
959 | }; | 1058 | }; |
960 | 1059 | ||
1060 | /* locking: called with info->lock held */ | ||
961 | static int sh_mobile_lcdc_notify(struct notifier_block *nb, | 1061 | static int sh_mobile_lcdc_notify(struct notifier_block *nb, |
962 | unsigned long action, void *data) | 1062 | unsigned long action, void *data) |
963 | { | 1063 | { |
@@ -965,53 +1065,40 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb, | |||
965 | struct fb_info *info = event->info; | 1065 | struct fb_info *info = event->info; |
966 | struct sh_mobile_lcdc_chan *ch = info->par; | 1066 | struct sh_mobile_lcdc_chan *ch = info->par; |
967 | struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg; | 1067 | struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg; |
968 | struct fb_var_screeninfo *var; | 1068 | int ret; |
969 | 1069 | ||
970 | if (&ch->lcdc->notifier != nb) | 1070 | if (&ch->lcdc->notifier != nb) |
971 | return 0; | 1071 | return NOTIFY_DONE; |
972 | 1072 | ||
973 | dev_dbg(info->dev, "%s(): action = %lu, data = %p\n", | 1073 | dev_dbg(info->dev, "%s(): action = %lu, data = %p\n", |
974 | __func__, action, event->data); | 1074 | __func__, action, event->data); |
975 | 1075 | ||
976 | switch(action) { | 1076 | switch(action) { |
977 | case FB_EVENT_SUSPEND: | 1077 | case FB_EVENT_SUSPEND: |
978 | if (board_cfg->display_off) | 1078 | if (try_module_get(board_cfg->owner) && board_cfg->display_off) { |
979 | board_cfg->display_off(board_cfg->board_data); | 1079 | board_cfg->display_off(board_cfg->board_data); |
1080 | module_put(board_cfg->owner); | ||
1081 | } | ||
980 | pm_runtime_put(info->device); | 1082 | pm_runtime_put(info->device); |
1083 | sh_mobile_lcdc_stop(ch->lcdc); | ||
981 | break; | 1084 | break; |
982 | case FB_EVENT_RESUME: | 1085 | case FB_EVENT_RESUME: |
983 | var = &info->var; | 1086 | mutex_lock(&ch->open_lock); |
1087 | sh_mobile_fb_reconfig(info); | ||
1088 | mutex_unlock(&ch->open_lock); | ||
984 | 1089 | ||
985 | /* HDMI must be enabled before LCDC configuration */ | 1090 | /* HDMI must be enabled before LCDC configuration */ |
986 | if (board_cfg->display_on) | 1091 | if (try_module_get(board_cfg->owner) && board_cfg->display_on) { |
987 | board_cfg->display_on(board_cfg->board_data, ch->info); | 1092 | board_cfg->display_on(board_cfg->board_data, info); |
988 | 1093 | module_put(board_cfg->owner); | |
989 | /* Check if the new display is not in our modelist */ | ||
990 | if (ch->info->modelist.next && | ||
991 | !fb_match_mode(var, &ch->info->modelist)) { | ||
992 | struct fb_videomode mode; | ||
993 | int ret; | ||
994 | |||
995 | /* Can we handle this display? */ | ||
996 | if (var->xres > ch->cfg.lcd_cfg.xres || | ||
997 | var->yres > ch->cfg.lcd_cfg.yres) | ||
998 | return -ENOMEM; | ||
999 | |||
1000 | /* Add to the modelist */ | ||
1001 | fb_var_to_videomode(&mode, var); | ||
1002 | ret = fb_add_videomode(&mode, &ch->info->modelist); | ||
1003 | if (ret < 0) | ||
1004 | return ret; | ||
1005 | } | 1094 | } |
1006 | 1095 | ||
1007 | pm_runtime_get_sync(info->device); | 1096 | ret = sh_mobile_lcdc_start(ch->lcdc); |
1008 | 1097 | if (!ret) | |
1009 | sh_mobile_lcdc_geometry(ch); | 1098 | pm_runtime_get_sync(info->device); |
1010 | |||
1011 | break; | ||
1012 | } | 1099 | } |
1013 | 1100 | ||
1014 | return 0; | 1101 | return NOTIFY_OK; |
1015 | } | 1102 | } |
1016 | 1103 | ||
1017 | static int sh_mobile_lcdc_remove(struct platform_device *pdev); | 1104 | static int sh_mobile_lcdc_remove(struct platform_device *pdev); |
@@ -1020,14 +1107,13 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
1020 | { | 1107 | { |
1021 | struct fb_info *info; | 1108 | struct fb_info *info; |
1022 | struct sh_mobile_lcdc_priv *priv; | 1109 | struct sh_mobile_lcdc_priv *priv; |
1023 | struct sh_mobile_lcdc_info *pdata; | 1110 | struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data; |
1024 | struct sh_mobile_lcdc_chan_cfg *cfg; | ||
1025 | struct resource *res; | 1111 | struct resource *res; |
1026 | int error; | 1112 | int error; |
1027 | void *buf; | 1113 | void *buf; |
1028 | int i, j; | 1114 | int i, j; |
1029 | 1115 | ||
1030 | if (!pdev->dev.platform_data) { | 1116 | if (!pdata) { |
1031 | dev_err(&pdev->dev, "no platform data defined\n"); | 1117 | dev_err(&pdev->dev, "no platform data defined\n"); |
1032 | return -EINVAL; | 1118 | return -EINVAL; |
1033 | } | 1119 | } |
@@ -1055,31 +1141,33 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
1055 | } | 1141 | } |
1056 | 1142 | ||
1057 | priv->irq = i; | 1143 | priv->irq = i; |
1058 | pdata = pdev->dev.platform_data; | 1144 | atomic_set(&priv->hw_usecnt, -1); |
1059 | 1145 | ||
1060 | j = 0; | 1146 | j = 0; |
1061 | for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) { | 1147 | for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) { |
1062 | priv->ch[j].lcdc = priv; | 1148 | struct sh_mobile_lcdc_chan *ch = priv->ch + j; |
1063 | memcpy(&priv->ch[j].cfg, &pdata->ch[i], sizeof(pdata->ch[i])); | 1149 | |
1150 | ch->lcdc = priv; | ||
1151 | memcpy(&ch->cfg, &pdata->ch[i], sizeof(pdata->ch[i])); | ||
1064 | 1152 | ||
1065 | error = sh_mobile_lcdc_check_interface(&priv->ch[j]); | 1153 | error = sh_mobile_lcdc_check_interface(ch); |
1066 | if (error) { | 1154 | if (error) { |
1067 | dev_err(&pdev->dev, "unsupported interface type\n"); | 1155 | dev_err(&pdev->dev, "unsupported interface type\n"); |
1068 | goto err1; | 1156 | goto err1; |
1069 | } | 1157 | } |
1070 | init_waitqueue_head(&priv->ch[j].frame_end_wait); | 1158 | init_waitqueue_head(&ch->frame_end_wait); |
1071 | init_completion(&priv->ch[j].vsync_completion); | 1159 | init_completion(&ch->vsync_completion); |
1072 | priv->ch[j].pan_offset = 0; | 1160 | ch->pan_offset = 0; |
1073 | 1161 | ||
1074 | switch (pdata->ch[i].chan) { | 1162 | switch (pdata->ch[i].chan) { |
1075 | case LCDC_CHAN_MAINLCD: | 1163 | case LCDC_CHAN_MAINLCD: |
1076 | priv->ch[j].enabled = 1 << 1; | 1164 | ch->enabled = 1 << 1; |
1077 | priv->ch[j].reg_offs = lcdc_offs_mainlcd; | 1165 | ch->reg_offs = lcdc_offs_mainlcd; |
1078 | j++; | 1166 | j++; |
1079 | break; | 1167 | break; |
1080 | case LCDC_CHAN_SUBLCD: | 1168 | case LCDC_CHAN_SUBLCD: |
1081 | priv->ch[j].enabled = 1 << 2; | 1169 | ch->enabled = 1 << 2; |
1082 | priv->ch[j].reg_offs = lcdc_offs_sublcd; | 1170 | ch->reg_offs = lcdc_offs_sublcd; |
1083 | j++; | 1171 | j++; |
1084 | break; | 1172 | break; |
1085 | } | 1173 | } |
@@ -1103,69 +1191,83 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
1103 | 1191 | ||
1104 | for (i = 0; i < j; i++) { | 1192 | for (i = 0; i < j; i++) { |
1105 | struct fb_var_screeninfo *var; | 1193 | struct fb_var_screeninfo *var; |
1106 | struct fb_videomode *lcd_cfg; | 1194 | const struct fb_videomode *lcd_cfg, *max_cfg = NULL; |
1107 | cfg = &priv->ch[i].cfg; | 1195 | struct sh_mobile_lcdc_chan *ch = priv->ch + i; |
1196 | struct sh_mobile_lcdc_chan_cfg *cfg = &ch->cfg; | ||
1197 | const struct fb_videomode *mode = cfg->lcd_cfg; | ||
1198 | unsigned long max_size = 0; | ||
1199 | int k; | ||
1108 | 1200 | ||
1109 | priv->ch[i].info = framebuffer_alloc(0, &pdev->dev); | 1201 | ch->info = framebuffer_alloc(0, &pdev->dev); |
1110 | if (!priv->ch[i].info) { | 1202 | if (!ch->info) { |
1111 | dev_err(&pdev->dev, "unable to allocate fb_info\n"); | 1203 | dev_err(&pdev->dev, "unable to allocate fb_info\n"); |
1112 | error = -ENOMEM; | 1204 | error = -ENOMEM; |
1113 | break; | 1205 | break; |
1114 | } | 1206 | } |
1115 | 1207 | ||
1116 | info = priv->ch[i].info; | 1208 | info = ch->info; |
1117 | var = &info->var; | 1209 | var = &info->var; |
1118 | lcd_cfg = &cfg->lcd_cfg; | ||
1119 | info->fbops = &sh_mobile_lcdc_ops; | 1210 | info->fbops = &sh_mobile_lcdc_ops; |
1120 | var->xres = var->xres_virtual = lcd_cfg->xres; | 1211 | info->par = ch; |
1121 | var->yres = lcd_cfg->yres; | 1212 | |
1213 | mutex_init(&ch->open_lock); | ||
1214 | |||
1215 | for (k = 0, lcd_cfg = mode; | ||
1216 | k < cfg->num_cfg && lcd_cfg; | ||
1217 | k++, lcd_cfg++) { | ||
1218 | unsigned long size = lcd_cfg->yres * lcd_cfg->xres; | ||
1219 | |||
1220 | if (size > max_size) { | ||
1221 | max_cfg = lcd_cfg; | ||
1222 | max_size = size; | ||
1223 | } | ||
1224 | } | ||
1225 | |||
1226 | if (!mode) | ||
1227 | max_size = DEFAULT_XRES * DEFAULT_YRES; | ||
1228 | else if (max_cfg) | ||
1229 | dev_dbg(&pdev->dev, "Found largest videomode %ux%u\n", | ||
1230 | max_cfg->xres, max_cfg->yres); | ||
1231 | |||
1232 | info->fix = sh_mobile_lcdc_fix; | ||
1233 | info->fix.smem_len = max_size * (cfg->bpp / 8) * 2; | ||
1234 | |||
1235 | if (!mode) | ||
1236 | mode = &default_720p; | ||
1237 | |||
1238 | fb_videomode_to_var(var, mode); | ||
1122 | /* Default Y virtual resolution is 2x panel size */ | 1239 | /* Default Y virtual resolution is 2x panel size */ |
1123 | var->yres_virtual = var->yres * 2; | 1240 | var->yres_virtual = var->yres * 2; |
1124 | var->width = cfg->lcd_size_cfg.width; | ||
1125 | var->height = cfg->lcd_size_cfg.height; | ||
1126 | var->activate = FB_ACTIVATE_NOW; | 1241 | var->activate = FB_ACTIVATE_NOW; |
1127 | var->left_margin = lcd_cfg->left_margin; | ||
1128 | var->right_margin = lcd_cfg->right_margin; | ||
1129 | var->upper_margin = lcd_cfg->upper_margin; | ||
1130 | var->lower_margin = lcd_cfg->lower_margin; | ||
1131 | var->hsync_len = lcd_cfg->hsync_len; | ||
1132 | var->vsync_len = lcd_cfg->vsync_len; | ||
1133 | var->sync = lcd_cfg->sync; | ||
1134 | var->pixclock = lcd_cfg->pixclock; | ||
1135 | 1242 | ||
1136 | error = sh_mobile_lcdc_set_bpp(var, cfg->bpp); | 1243 | error = sh_mobile_lcdc_set_bpp(var, cfg->bpp); |
1137 | if (error) | 1244 | if (error) |
1138 | break; | 1245 | break; |
1139 | 1246 | ||
1140 | info->fix = sh_mobile_lcdc_fix; | ||
1141 | info->fix.line_length = lcd_cfg->xres * (cfg->bpp / 8); | ||
1142 | info->fix.smem_len = info->fix.line_length * | ||
1143 | var->yres_virtual; | ||
1144 | |||
1145 | buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len, | 1247 | buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len, |
1146 | &priv->ch[i].dma_handle, GFP_KERNEL); | 1248 | &ch->dma_handle, GFP_KERNEL); |
1147 | if (!buf) { | 1249 | if (!buf) { |
1148 | dev_err(&pdev->dev, "unable to allocate buffer\n"); | 1250 | dev_err(&pdev->dev, "unable to allocate buffer\n"); |
1149 | error = -ENOMEM; | 1251 | error = -ENOMEM; |
1150 | break; | 1252 | break; |
1151 | } | 1253 | } |
1152 | 1254 | ||
1153 | info->pseudo_palette = &priv->ch[i].pseudo_palette; | 1255 | info->pseudo_palette = &ch->pseudo_palette; |
1154 | info->flags = FBINFO_FLAG_DEFAULT; | 1256 | info->flags = FBINFO_FLAG_DEFAULT; |
1155 | 1257 | ||
1156 | error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0); | 1258 | error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0); |
1157 | if (error < 0) { | 1259 | if (error < 0) { |
1158 | dev_err(&pdev->dev, "unable to allocate cmap\n"); | 1260 | dev_err(&pdev->dev, "unable to allocate cmap\n"); |
1159 | dma_free_coherent(&pdev->dev, info->fix.smem_len, | 1261 | dma_free_coherent(&pdev->dev, info->fix.smem_len, |
1160 | buf, priv->ch[i].dma_handle); | 1262 | buf, ch->dma_handle); |
1161 | break; | 1263 | break; |
1162 | } | 1264 | } |
1163 | 1265 | ||
1164 | memset(buf, 0, info->fix.smem_len); | 1266 | info->fix.smem_start = ch->dma_handle; |
1165 | info->fix.smem_start = priv->ch[i].dma_handle; | 1267 | info->fix.line_length = var->xres * (cfg->bpp / 8); |
1166 | info->screen_base = buf; | 1268 | info->screen_base = buf; |
1167 | info->device = &pdev->dev; | 1269 | info->device = &pdev->dev; |
1168 | info->par = &priv->ch[i]; | 1270 | ch->display_var = *var; |
1169 | } | 1271 | } |
1170 | 1272 | ||
1171 | if (error) | 1273 | if (error) |
@@ -1179,6 +1281,10 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
1179 | 1281 | ||
1180 | for (i = 0; i < j; i++) { | 1282 | for (i = 0; i < j; i++) { |
1181 | struct sh_mobile_lcdc_chan *ch = priv->ch + i; | 1283 | struct sh_mobile_lcdc_chan *ch = priv->ch + i; |
1284 | const struct fb_videomode *mode = ch->cfg.lcd_cfg; | ||
1285 | |||
1286 | if (!mode) | ||
1287 | mode = &default_720p; | ||
1182 | 1288 | ||
1183 | info = ch->info; | 1289 | info = ch->info; |
1184 | 1290 | ||
@@ -1191,6 +1297,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
1191 | } | 1297 | } |
1192 | } | 1298 | } |
1193 | 1299 | ||
1300 | fb_videomode_to_modelist(mode, ch->cfg.num_cfg, &info->modelist); | ||
1194 | error = register_framebuffer(info); | 1301 | error = register_framebuffer(info); |
1195 | if (error < 0) | 1302 | if (error < 0) |
1196 | goto err1; | 1303 | goto err1; |
@@ -1200,8 +1307,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
1200 | pdev->name, | 1307 | pdev->name, |
1201 | (ch->cfg.chan == LCDC_CHAN_MAINLCD) ? | 1308 | (ch->cfg.chan == LCDC_CHAN_MAINLCD) ? |
1202 | "mainlcd" : "sublcd", | 1309 | "mainlcd" : "sublcd", |
1203 | (int) ch->cfg.lcd_cfg.xres, | 1310 | info->var.xres, info->var.yres, |
1204 | (int) ch->cfg.lcd_cfg.yres, | ||
1205 | ch->cfg.bpp); | 1311 | ch->cfg.bpp); |
1206 | 1312 | ||
1207 | /* deferred io mode: disable clock to save power */ | 1313 | /* deferred io mode: disable clock to save power */ |
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h new file mode 100644 index 000000000000..9ecee2fba1d7 --- /dev/null +++ b/drivers/video/sh_mobile_lcdcfb.h | |||
@@ -0,0 +1,41 @@ | |||
1 | #ifndef SH_MOBILE_LCDCFB_H | ||
2 | #define SH_MOBILE_LCDCFB_H | ||
3 | |||
4 | #include <linux/completion.h> | ||
5 | #include <linux/fb.h> | ||
6 | #include <linux/mutex.h> | ||
7 | #include <linux/wait.h> | ||
8 | |||
9 | /* per-channel registers */ | ||
10 | enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R, | ||
11 | LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR, | ||
12 | LDHAJR, | ||
13 | NR_CH_REGS }; | ||
14 | |||
15 | #define PALETTE_NR 16 | ||
16 | |||
17 | struct sh_mobile_lcdc_priv; | ||
18 | struct fb_info; | ||
19 | |||
20 | struct sh_mobile_lcdc_chan { | ||
21 | struct sh_mobile_lcdc_priv *lcdc; | ||
22 | unsigned long *reg_offs; | ||
23 | unsigned long ldmt1r_value; | ||
24 | unsigned long enabled; /* ME and SE in LDCNT2R */ | ||
25 | struct sh_mobile_lcdc_chan_cfg cfg; | ||
26 | u32 pseudo_palette[PALETTE_NR]; | ||
27 | unsigned long saved_ch_regs[NR_CH_REGS]; | ||
28 | struct fb_info *info; | ||
29 | dma_addr_t dma_handle; | ||
30 | struct fb_deferred_io defio; | ||
31 | struct scatterlist *sglist; | ||
32 | unsigned long frame_end; | ||
33 | unsigned long pan_offset; | ||
34 | wait_queue_head_t frame_end_wait; | ||
35 | struct completion vsync_completion; | ||
36 | struct fb_var_screeninfo display_var; | ||
37 | int use_count; | ||
38 | struct mutex open_lock; /* protects the use counter */ | ||
39 | }; | ||
40 | |||
41 | #endif | ||
diff --git a/fs/compat.c b/fs/compat.c index ff66c0d7583d..c580c322fa6b 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include <linux/eventpoll.h> | 49 | #include <linux/eventpoll.h> |
50 | #include <linux/fs_struct.h> | 50 | #include <linux/fs_struct.h> |
51 | #include <linux/slab.h> | 51 | #include <linux/slab.h> |
52 | #include <linux/pagemap.h> | ||
52 | 53 | ||
53 | #include <asm/uaccess.h> | 54 | #include <asm/uaccess.h> |
54 | #include <asm/mmu_context.h> | 55 | #include <asm/mmu_context.h> |
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index a906f538d11c..85c6be2db02f 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c | |||
@@ -23,7 +23,7 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *, | |||
23 | static inline struct jffs2_inode_cache * | 23 | static inline struct jffs2_inode_cache * |
24 | first_inode_chain(int *i, struct jffs2_sb_info *c) | 24 | first_inode_chain(int *i, struct jffs2_sb_info *c) |
25 | { | 25 | { |
26 | for (; *i < INOCACHE_HASHSIZE; (*i)++) { | 26 | for (; *i < c->inocache_hashsize; (*i)++) { |
27 | if (c->inocache_list[*i]) | 27 | if (c->inocache_list[*i]) |
28 | return c->inocache_list[*i]; | 28 | return c->inocache_list[*i]; |
29 | } | 29 | } |
diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c index 617a1e5694c1..de4247021d25 100644 --- a/fs/jffs2/compr.c +++ b/fs/jffs2/compr.c | |||
@@ -103,7 +103,7 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | |||
103 | spin_unlock(&jffs2_compressor_list_lock); | 103 | spin_unlock(&jffs2_compressor_list_lock); |
104 | *datalen = orig_slen; | 104 | *datalen = orig_slen; |
105 | *cdatalen = orig_dlen; | 105 | *cdatalen = orig_dlen; |
106 | compr_ret = this->compress(data_in, output_buf, datalen, cdatalen, NULL); | 106 | compr_ret = this->compress(data_in, output_buf, datalen, cdatalen); |
107 | spin_lock(&jffs2_compressor_list_lock); | 107 | spin_lock(&jffs2_compressor_list_lock); |
108 | this->usecount--; | 108 | this->usecount--; |
109 | if (!compr_ret) { | 109 | if (!compr_ret) { |
@@ -152,7 +152,7 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | |||
152 | spin_unlock(&jffs2_compressor_list_lock); | 152 | spin_unlock(&jffs2_compressor_list_lock); |
153 | *datalen = orig_slen; | 153 | *datalen = orig_slen; |
154 | *cdatalen = orig_dlen; | 154 | *cdatalen = orig_dlen; |
155 | compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen, NULL); | 155 | compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen); |
156 | spin_lock(&jffs2_compressor_list_lock); | 156 | spin_lock(&jffs2_compressor_list_lock); |
157 | this->usecount--; | 157 | this->usecount--; |
158 | if (!compr_ret) { | 158 | if (!compr_ret) { |
@@ -220,7 +220,7 @@ int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | |||
220 | if (comprtype == this->compr) { | 220 | if (comprtype == this->compr) { |
221 | this->usecount++; | 221 | this->usecount++; |
222 | spin_unlock(&jffs2_compressor_list_lock); | 222 | spin_unlock(&jffs2_compressor_list_lock); |
223 | ret = this->decompress(cdata_in, data_out, cdatalen, datalen, NULL); | 223 | ret = this->decompress(cdata_in, data_out, cdatalen, datalen); |
224 | spin_lock(&jffs2_compressor_list_lock); | 224 | spin_lock(&jffs2_compressor_list_lock); |
225 | if (ret) { | 225 | if (ret) { |
226 | printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret); | 226 | printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret); |
diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h index e471a9106fd9..13bb7597ab39 100644 --- a/fs/jffs2/compr.h +++ b/fs/jffs2/compr.h | |||
@@ -49,9 +49,9 @@ struct jffs2_compressor { | |||
49 | char *name; | 49 | char *name; |
50 | char compr; /* JFFS2_COMPR_XXX */ | 50 | char compr; /* JFFS2_COMPR_XXX */ |
51 | int (*compress)(unsigned char *data_in, unsigned char *cpage_out, | 51 | int (*compress)(unsigned char *data_in, unsigned char *cpage_out, |
52 | uint32_t *srclen, uint32_t *destlen, void *model); | 52 | uint32_t *srclen, uint32_t *destlen); |
53 | int (*decompress)(unsigned char *cdata_in, unsigned char *data_out, | 53 | int (*decompress)(unsigned char *cdata_in, unsigned char *data_out, |
54 | uint32_t cdatalen, uint32_t datalen, void *model); | 54 | uint32_t cdatalen, uint32_t datalen); |
55 | int usecount; | 55 | int usecount; |
56 | int disabled; /* if set the compressor won't compress */ | 56 | int disabled; /* if set the compressor won't compress */ |
57 | unsigned char *compr_buf; /* used by size compr. mode */ | 57 | unsigned char *compr_buf; /* used by size compr. mode */ |
diff --git a/fs/jffs2/compr_lzo.c b/fs/jffs2/compr_lzo.c index ed25ae7c98eb..af186ee674d8 100644 --- a/fs/jffs2/compr_lzo.c +++ b/fs/jffs2/compr_lzo.c | |||
@@ -42,7 +42,7 @@ static int __init alloc_workspace(void) | |||
42 | } | 42 | } |
43 | 43 | ||
44 | static int jffs2_lzo_compress(unsigned char *data_in, unsigned char *cpage_out, | 44 | static int jffs2_lzo_compress(unsigned char *data_in, unsigned char *cpage_out, |
45 | uint32_t *sourcelen, uint32_t *dstlen, void *model) | 45 | uint32_t *sourcelen, uint32_t *dstlen) |
46 | { | 46 | { |
47 | size_t compress_size; | 47 | size_t compress_size; |
48 | int ret; | 48 | int ret; |
@@ -67,7 +67,7 @@ static int jffs2_lzo_compress(unsigned char *data_in, unsigned char *cpage_out, | |||
67 | } | 67 | } |
68 | 68 | ||
69 | static int jffs2_lzo_decompress(unsigned char *data_in, unsigned char *cpage_out, | 69 | static int jffs2_lzo_decompress(unsigned char *data_in, unsigned char *cpage_out, |
70 | uint32_t srclen, uint32_t destlen, void *model) | 70 | uint32_t srclen, uint32_t destlen) |
71 | { | 71 | { |
72 | size_t dl = destlen; | 72 | size_t dl = destlen; |
73 | int ret; | 73 | int ret; |
diff --git a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c index 9696ad9ef5f7..16a5047903a6 100644 --- a/fs/jffs2/compr_rtime.c +++ b/fs/jffs2/compr_rtime.c | |||
@@ -31,8 +31,7 @@ | |||
31 | /* _compress returns the compressed size, -1 if bigger */ | 31 | /* _compress returns the compressed size, -1 if bigger */ |
32 | static int jffs2_rtime_compress(unsigned char *data_in, | 32 | static int jffs2_rtime_compress(unsigned char *data_in, |
33 | unsigned char *cpage_out, | 33 | unsigned char *cpage_out, |
34 | uint32_t *sourcelen, uint32_t *dstlen, | 34 | uint32_t *sourcelen, uint32_t *dstlen) |
35 | void *model) | ||
36 | { | 35 | { |
37 | short positions[256]; | 36 | short positions[256]; |
38 | int outpos = 0; | 37 | int outpos = 0; |
@@ -73,8 +72,7 @@ static int jffs2_rtime_compress(unsigned char *data_in, | |||
73 | 72 | ||
74 | static int jffs2_rtime_decompress(unsigned char *data_in, | 73 | static int jffs2_rtime_decompress(unsigned char *data_in, |
75 | unsigned char *cpage_out, | 74 | unsigned char *cpage_out, |
76 | uint32_t srclen, uint32_t destlen, | 75 | uint32_t srclen, uint32_t destlen) |
77 | void *model) | ||
78 | { | 76 | { |
79 | short positions[256]; | 77 | short positions[256]; |
80 | int outpos = 0; | 78 | int outpos = 0; |
diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c index a12b4f763373..9e7cec808c4c 100644 --- a/fs/jffs2/compr_rubin.c +++ b/fs/jffs2/compr_rubin.c | |||
@@ -298,7 +298,7 @@ static int rubin_do_compress(int bit_divider, int *bits, unsigned char *data_in, | |||
298 | #if 0 | 298 | #if 0 |
299 | /* _compress returns the compressed size, -1 if bigger */ | 299 | /* _compress returns the compressed size, -1 if bigger */ |
300 | int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, | 300 | int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, |
301 | uint32_t *sourcelen, uint32_t *dstlen, void *model) | 301 | uint32_t *sourcelen, uint32_t *dstlen) |
302 | { | 302 | { |
303 | return rubin_do_compress(BIT_DIVIDER_MIPS, bits_mips, data_in, | 303 | return rubin_do_compress(BIT_DIVIDER_MIPS, bits_mips, data_in, |
304 | cpage_out, sourcelen, dstlen); | 304 | cpage_out, sourcelen, dstlen); |
@@ -306,8 +306,7 @@ int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, | |||
306 | #endif | 306 | #endif |
307 | static int jffs2_dynrubin_compress(unsigned char *data_in, | 307 | static int jffs2_dynrubin_compress(unsigned char *data_in, |
308 | unsigned char *cpage_out, | 308 | unsigned char *cpage_out, |
309 | uint32_t *sourcelen, uint32_t *dstlen, | 309 | uint32_t *sourcelen, uint32_t *dstlen) |
310 | void *model) | ||
311 | { | 310 | { |
312 | int bits[8]; | 311 | int bits[8]; |
313 | unsigned char histo[256]; | 312 | unsigned char histo[256]; |
@@ -387,8 +386,7 @@ static void rubin_do_decompress(int bit_divider, int *bits, | |||
387 | 386 | ||
388 | static int jffs2_rubinmips_decompress(unsigned char *data_in, | 387 | static int jffs2_rubinmips_decompress(unsigned char *data_in, |
389 | unsigned char *cpage_out, | 388 | unsigned char *cpage_out, |
390 | uint32_t sourcelen, uint32_t dstlen, | 389 | uint32_t sourcelen, uint32_t dstlen) |
391 | void *model) | ||
392 | { | 390 | { |
393 | rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in, | 391 | rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in, |
394 | cpage_out, sourcelen, dstlen); | 392 | cpage_out, sourcelen, dstlen); |
@@ -397,8 +395,7 @@ static int jffs2_rubinmips_decompress(unsigned char *data_in, | |||
397 | 395 | ||
398 | static int jffs2_dynrubin_decompress(unsigned char *data_in, | 396 | static int jffs2_dynrubin_decompress(unsigned char *data_in, |
399 | unsigned char *cpage_out, | 397 | unsigned char *cpage_out, |
400 | uint32_t sourcelen, uint32_t dstlen, | 398 | uint32_t sourcelen, uint32_t dstlen) |
401 | void *model) | ||
402 | { | 399 | { |
403 | int bits[8]; | 400 | int bits[8]; |
404 | int c; | 401 | int c; |
diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c index 97fc45de6f81..fd05a0b9431d 100644 --- a/fs/jffs2/compr_zlib.c +++ b/fs/jffs2/compr_zlib.c | |||
@@ -68,8 +68,7 @@ static void free_workspaces(void) | |||
68 | 68 | ||
69 | static int jffs2_zlib_compress(unsigned char *data_in, | 69 | static int jffs2_zlib_compress(unsigned char *data_in, |
70 | unsigned char *cpage_out, | 70 | unsigned char *cpage_out, |
71 | uint32_t *sourcelen, uint32_t *dstlen, | 71 | uint32_t *sourcelen, uint32_t *dstlen) |
72 | void *model) | ||
73 | { | 72 | { |
74 | int ret; | 73 | int ret; |
75 | 74 | ||
@@ -136,8 +135,7 @@ static int jffs2_zlib_compress(unsigned char *data_in, | |||
136 | 135 | ||
137 | static int jffs2_zlib_decompress(unsigned char *data_in, | 136 | static int jffs2_zlib_decompress(unsigned char *data_in, |
138 | unsigned char *cpage_out, | 137 | unsigned char *cpage_out, |
139 | uint32_t srclen, uint32_t destlen, | 138 | uint32_t srclen, uint32_t destlen) |
140 | void *model) | ||
141 | { | 139 | { |
142 | int ret; | 140 | int ret; |
143 | int wbits = MAX_WBITS; | 141 | int wbits = MAX_WBITS; |
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 79121aa5858b..92978658ed18 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c | |||
@@ -367,7 +367,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
367 | } | 367 | } |
368 | 368 | ||
369 | /* We use f->target field to store the target path. */ | 369 | /* We use f->target field to store the target path. */ |
370 | f->target = kmalloc(targetlen + 1, GFP_KERNEL); | 370 | f->target = kmemdup(target, targetlen + 1, GFP_KERNEL); |
371 | if (!f->target) { | 371 | if (!f->target) { |
372 | printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1); | 372 | printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1); |
373 | mutex_unlock(&f->sem); | 373 | mutex_unlock(&f->sem); |
@@ -376,7 +376,6 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
376 | goto fail; | 376 | goto fail; |
377 | } | 377 | } |
378 | 378 | ||
379 | memcpy(f->target, target, targetlen + 1); | ||
380 | D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached\n", (char *)f->target)); | 379 | D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached\n", (char *)f->target)); |
381 | 380 | ||
382 | /* No data here. Only a metadata node, which will be | 381 | /* No data here. Only a metadata node, which will be |
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index abac961f617b..e513f1913c15 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c | |||
@@ -151,7 +151,7 @@ int jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count) | |||
151 | } | 151 | } |
152 | 152 | ||
153 | /* Be nice */ | 153 | /* Be nice */ |
154 | yield(); | 154 | cond_resched(); |
155 | mutex_lock(&c->erase_free_sem); | 155 | mutex_lock(&c->erase_free_sem); |
156 | spin_lock(&c->erase_completion_lock); | 156 | spin_lock(&c->erase_completion_lock); |
157 | } | 157 | } |
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index d9beb06e6fca..e896e67767eb 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c | |||
@@ -474,6 +474,25 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i | |||
474 | return inode; | 474 | return inode; |
475 | } | 475 | } |
476 | 476 | ||
477 | static int calculate_inocache_hashsize(uint32_t flash_size) | ||
478 | { | ||
479 | /* | ||
480 | * Pick a inocache hash size based on the size of the medium. | ||
481 | * Count how many megabytes we're dealing with, apply a hashsize twice | ||
482 | * that size, but rounding down to the usual big powers of 2. And keep | ||
483 | * to sensible bounds. | ||
484 | */ | ||
485 | |||
486 | int size_mb = flash_size / 1024 / 1024; | ||
487 | int hashsize = (size_mb * 2) & ~0x3f; | ||
488 | |||
489 | if (hashsize < INOCACHE_HASHSIZE_MIN) | ||
490 | return INOCACHE_HASHSIZE_MIN; | ||
491 | if (hashsize > INOCACHE_HASHSIZE_MAX) | ||
492 | return INOCACHE_HASHSIZE_MAX; | ||
493 | |||
494 | return hashsize; | ||
495 | } | ||
477 | 496 | ||
478 | int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) | 497 | int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) |
479 | { | 498 | { |
@@ -520,7 +539,8 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) | |||
520 | if (ret) | 539 | if (ret) |
521 | return ret; | 540 | return ret; |
522 | 541 | ||
523 | c->inocache_list = kcalloc(INOCACHE_HASHSIZE, sizeof(struct jffs2_inode_cache *), GFP_KERNEL); | 542 | c->inocache_hashsize = calculate_inocache_hashsize(c->flash_size); |
543 | c->inocache_list = kcalloc(c->inocache_hashsize, sizeof(struct jffs2_inode_cache *), GFP_KERNEL); | ||
524 | if (!c->inocache_list) { | 544 | if (!c->inocache_list) { |
525 | ret = -ENOMEM; | 545 | ret = -ENOMEM; |
526 | goto out_wbuf; | 546 | goto out_wbuf; |
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 846a79452497..31dce611337c 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c | |||
@@ -219,13 +219,14 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
219 | if (!list_empty(&c->erase_complete_list) || | 219 | if (!list_empty(&c->erase_complete_list) || |
220 | !list_empty(&c->erase_pending_list)) { | 220 | !list_empty(&c->erase_pending_list)) { |
221 | spin_unlock(&c->erase_completion_lock); | 221 | spin_unlock(&c->erase_completion_lock); |
222 | mutex_unlock(&c->alloc_sem); | ||
222 | D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() erasing pending blocks\n")); | 223 | D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() erasing pending blocks\n")); |
223 | if (jffs2_erase_pending_blocks(c, 1)) { | 224 | if (jffs2_erase_pending_blocks(c, 1)) |
224 | mutex_unlock(&c->alloc_sem); | ||
225 | return 0; | 225 | return 0; |
226 | } | 226 | |
227 | D1(printk(KERN_DEBUG "No progress from erasing blocks; doing GC anyway\n")); | 227 | D1(printk(KERN_DEBUG "No progress from erasing blocks; doing GC anyway\n")); |
228 | spin_lock(&c->erase_completion_lock); | 228 | spin_lock(&c->erase_completion_lock); |
229 | mutex_lock(&c->alloc_sem); | ||
229 | } | 230 | } |
230 | 231 | ||
231 | /* First, work out which block we're garbage-collecting */ | 232 | /* First, work out which block we're garbage-collecting */ |
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h index 6784bc89add1..f864005de64c 100644 --- a/fs/jffs2/jffs2_fs_sb.h +++ b/fs/jffs2/jffs2_fs_sb.h | |||
@@ -100,6 +100,7 @@ struct jffs2_sb_info { | |||
100 | wait_queue_head_t erase_wait; /* For waiting for erases to complete */ | 100 | wait_queue_head_t erase_wait; /* For waiting for erases to complete */ |
101 | 101 | ||
102 | wait_queue_head_t inocache_wq; | 102 | wait_queue_head_t inocache_wq; |
103 | int inocache_hashsize; | ||
103 | struct jffs2_inode_cache **inocache_list; | 104 | struct jffs2_inode_cache **inocache_list; |
104 | spinlock_t inocache_lock; | 105 | spinlock_t inocache_lock; |
105 | 106 | ||
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index af02bd138469..5e03233c2363 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c | |||
@@ -420,7 +420,7 @@ struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t | |||
420 | { | 420 | { |
421 | struct jffs2_inode_cache *ret; | 421 | struct jffs2_inode_cache *ret; |
422 | 422 | ||
423 | ret = c->inocache_list[ino % INOCACHE_HASHSIZE]; | 423 | ret = c->inocache_list[ino % c->inocache_hashsize]; |
424 | while (ret && ret->ino < ino) { | 424 | while (ret && ret->ino < ino) { |
425 | ret = ret->next; | 425 | ret = ret->next; |
426 | } | 426 | } |
@@ -441,7 +441,7 @@ void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new | |||
441 | 441 | ||
442 | dbg_inocache("add %p (ino #%u)\n", new, new->ino); | 442 | dbg_inocache("add %p (ino #%u)\n", new, new->ino); |
443 | 443 | ||
444 | prev = &c->inocache_list[new->ino % INOCACHE_HASHSIZE]; | 444 | prev = &c->inocache_list[new->ino % c->inocache_hashsize]; |
445 | 445 | ||
446 | while ((*prev) && (*prev)->ino < new->ino) { | 446 | while ((*prev) && (*prev)->ino < new->ino) { |
447 | prev = &(*prev)->next; | 447 | prev = &(*prev)->next; |
@@ -462,7 +462,7 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old) | |||
462 | dbg_inocache("del %p (ino #%u)\n", old, old->ino); | 462 | dbg_inocache("del %p (ino #%u)\n", old, old->ino); |
463 | spin_lock(&c->inocache_lock); | 463 | spin_lock(&c->inocache_lock); |
464 | 464 | ||
465 | prev = &c->inocache_list[old->ino % INOCACHE_HASHSIZE]; | 465 | prev = &c->inocache_list[old->ino % c->inocache_hashsize]; |
466 | 466 | ||
467 | while ((*prev) && (*prev)->ino < old->ino) { | 467 | while ((*prev) && (*prev)->ino < old->ino) { |
468 | prev = &(*prev)->next; | 468 | prev = &(*prev)->next; |
@@ -487,7 +487,7 @@ void jffs2_free_ino_caches(struct jffs2_sb_info *c) | |||
487 | int i; | 487 | int i; |
488 | struct jffs2_inode_cache *this, *next; | 488 | struct jffs2_inode_cache *this, *next; |
489 | 489 | ||
490 | for (i=0; i<INOCACHE_HASHSIZE; i++) { | 490 | for (i=0; i < c->inocache_hashsize; i++) { |
491 | this = c->inocache_list[i]; | 491 | this = c->inocache_list[i]; |
492 | while (this) { | 492 | while (this) { |
493 | next = this->next; | 493 | next = this->next; |
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 523a91691052..5a53d9bdb2b5 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h | |||
@@ -199,7 +199,8 @@ struct jffs2_inode_cache { | |||
199 | #define RAWNODE_CLASS_XATTR_DATUM 1 | 199 | #define RAWNODE_CLASS_XATTR_DATUM 1 |
200 | #define RAWNODE_CLASS_XATTR_REF 2 | 200 | #define RAWNODE_CLASS_XATTR_REF 2 |
201 | 201 | ||
202 | #define INOCACHE_HASHSIZE 128 | 202 | #define INOCACHE_HASHSIZE_MIN 128 |
203 | #define INOCACHE_HASHSIZE_MAX 1024 | ||
203 | 204 | ||
204 | #define write_ofs(c) ((c)->nextblock->offset + (c)->sector_size - (c)->nextblock->free_size) | 205 | #define write_ofs(c) ((c)->nextblock->offset + (c)->sector_size - (c)->nextblock->free_size) |
205 | 206 | ||
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 46f870d1cc36..b632dddcb482 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include "summary.h" | 20 | #include "summary.h" |
21 | #include "debug.h" | 21 | #include "debug.h" |
22 | 22 | ||
23 | #define DEFAULT_EMPTY_SCAN_SIZE 1024 | 23 | #define DEFAULT_EMPTY_SCAN_SIZE 256 |
24 | 24 | ||
25 | #define noisy_printk(noise, args...) do { \ | 25 | #define noisy_printk(noise, args...) do { \ |
26 | if (*(noise)) { \ | 26 | if (*(noise)) { \ |
@@ -435,7 +435,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo | |||
435 | unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) { | 435 | unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) { |
436 | struct jffs2_unknown_node *node; | 436 | struct jffs2_unknown_node *node; |
437 | struct jffs2_unknown_node crcnode; | 437 | struct jffs2_unknown_node crcnode; |
438 | uint32_t ofs, prevofs; | 438 | uint32_t ofs, prevofs, max_ofs; |
439 | uint32_t hdr_crc, buf_ofs, buf_len; | 439 | uint32_t hdr_crc, buf_ofs, buf_len; |
440 | int err; | 440 | int err; |
441 | int noise = 0; | 441 | int noise = 0; |
@@ -550,12 +550,12 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo | |||
550 | 550 | ||
551 | /* We temporarily use 'ofs' as a pointer into the buffer/jeb */ | 551 | /* We temporarily use 'ofs' as a pointer into the buffer/jeb */ |
552 | ofs = 0; | 552 | ofs = 0; |
553 | 553 | max_ofs = EMPTY_SCAN_SIZE(c->sector_size); | |
554 | /* Scan only 4KiB of 0xFF before declaring it's empty */ | 554 | /* Scan only EMPTY_SCAN_SIZE of 0xFF before declaring it's empty */ |
555 | while(ofs < EMPTY_SCAN_SIZE(c->sector_size) && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF) | 555 | while(ofs < max_ofs && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF) |
556 | ofs += 4; | 556 | ofs += 4; |
557 | 557 | ||
558 | if (ofs == EMPTY_SCAN_SIZE(c->sector_size)) { | 558 | if (ofs == max_ofs) { |
559 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER | 559 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER |
560 | if (jffs2_cleanmarker_oob(c)) { | 560 | if (jffs2_cleanmarker_oob(c)) { |
561 | /* scan oob, take care of cleanmarker */ | 561 | /* scan oob, take care of cleanmarker */ |
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h index 7fa20beb2ab9..57cc0e63714f 100644 --- a/include/linux/mtd/bbm.h +++ b/include/linux/mtd/bbm.h | |||
@@ -84,7 +84,7 @@ struct nand_bbt_descr { | |||
84 | #define NAND_BBT_PERCHIP 0x00000080 | 84 | #define NAND_BBT_PERCHIP 0x00000080 |
85 | /* bbt has a version counter at offset veroffs */ | 85 | /* bbt has a version counter at offset veroffs */ |
86 | #define NAND_BBT_VERSION 0x00000100 | 86 | #define NAND_BBT_VERSION 0x00000100 |
87 | /* Create a bbt if none axists */ | 87 | /* Create a bbt if none exists */ |
88 | #define NAND_BBT_CREATE 0x00000200 | 88 | #define NAND_BBT_CREATE 0x00000200 |
89 | /* Search good / bad pattern through all pages of a block */ | 89 | /* Search good / bad pattern through all pages of a block */ |
90 | #define NAND_BBT_SCANALLPAGES 0x00000400 | 90 | #define NAND_BBT_SCANALLPAGES 0x00000400 |
@@ -102,6 +102,8 @@ struct nand_bbt_descr { | |||
102 | #define NAND_BBT_SCANBYTE1AND6 0x00100000 | 102 | #define NAND_BBT_SCANBYTE1AND6 0x00100000 |
103 | /* The nand_bbt_descr was created dynamicaly and must be freed */ | 103 | /* The nand_bbt_descr was created dynamicaly and must be freed */ |
104 | #define NAND_BBT_DYNAMICSTRUCT 0x00200000 | 104 | #define NAND_BBT_DYNAMICSTRUCT 0x00200000 |
105 | /* The bad block table does not OOB for marker */ | ||
106 | #define NAND_BBT_NO_OOB 0x00400000 | ||
105 | 107 | ||
106 | /* The maximum number of blocks to scan for a bbt */ | 108 | /* The maximum number of blocks to scan for a bbt */ |
107 | #define NAND_BBT_SCAN_MAXBLOCKS 4 | 109 | #define NAND_BBT_SCAN_MAXBLOCKS 4 |
diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index d2118b0eac9a..4dd0c2cd7659 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h | |||
@@ -289,6 +289,7 @@ struct cfi_private { | |||
289 | must be of the same type. */ | 289 | must be of the same type. */ |
290 | int mfr, id; | 290 | int mfr, id; |
291 | int numchips; | 291 | int numchips; |
292 | map_word sector_erase_cmd; | ||
292 | unsigned long chipshift; /* Because they're of the same type */ | 293 | unsigned long chipshift; /* Because they're of the same type */ |
293 | const char *im_name; /* inter_module name for cmdset_setup */ | 294 | const char *im_name; /* inter_module name for cmdset_setup */ |
294 | struct flchip chips[0]; /* per-chip data structure for each chip */ | 295 | struct flchip chips[0]; /* per-chip data structure for each chip */ |
diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h new file mode 100644 index 000000000000..5d2556700ec2 --- /dev/null +++ b/include/linux/mtd/fsmc.h | |||
@@ -0,0 +1,181 @@ | |||
1 | /* | ||
2 | * incude/mtd/fsmc.h | ||
3 | * | ||
4 | * ST Microelectronics | ||
5 | * Flexible Static Memory Controller (FSMC) | ||
6 | * platform data interface and header file | ||
7 | * | ||
8 | * Copyright © 2010 ST Microelectronics | ||
9 | * Vipin Kumar <vipin.kumar@st.com> | ||
10 | * | ||
11 | * This file is licensed under the terms of the GNU General Public | ||
12 | * License version 2. This program is licensed "as is" without any | ||
13 | * warranty of any kind, whether express or implied. | ||
14 | */ | ||
15 | |||
16 | #ifndef __MTD_FSMC_H | ||
17 | #define __MTD_FSMC_H | ||
18 | |||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/mtd/physmap.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/mtd/partitions.h> | ||
23 | #include <asm/param.h> | ||
24 | |||
25 | #define FSMC_NAND_BW8 1 | ||
26 | #define FSMC_NAND_BW16 2 | ||
27 | |||
28 | /* | ||
29 | * The placement of the Command Latch Enable (CLE) and | ||
30 | * Address Latch Enable (ALE) is twised around in the | ||
31 | * SPEAR310 implementation. | ||
32 | */ | ||
33 | #if defined(CONFIG_MACH_SPEAR310) | ||
34 | #define PLAT_NAND_CLE (1 << 17) | ||
35 | #define PLAT_NAND_ALE (1 << 16) | ||
36 | #else | ||
37 | #define PLAT_NAND_CLE (1 << 16) | ||
38 | #define PLAT_NAND_ALE (1 << 17) | ||
39 | #endif | ||
40 | |||
41 | #define FSMC_MAX_NOR_BANKS 4 | ||
42 | #define FSMC_MAX_NAND_BANKS 4 | ||
43 | |||
44 | #define FSMC_FLASH_WIDTH8 1 | ||
45 | #define FSMC_FLASH_WIDTH16 2 | ||
46 | |||
47 | struct fsmc_nor_bank_regs { | ||
48 | uint32_t ctrl; | ||
49 | uint32_t ctrl_tim; | ||
50 | }; | ||
51 | |||
52 | /* ctrl register definitions */ | ||
53 | #define BANK_ENABLE (1 << 0) | ||
54 | #define MUXED (1 << 1) | ||
55 | #define NOR_DEV (2 << 2) | ||
56 | #define WIDTH_8 (0 << 4) | ||
57 | #define WIDTH_16 (1 << 4) | ||
58 | #define RSTPWRDWN (1 << 6) | ||
59 | #define WPROT (1 << 7) | ||
60 | #define WRT_ENABLE (1 << 12) | ||
61 | #define WAIT_ENB (1 << 13) | ||
62 | |||
63 | /* ctrl_tim register definitions */ | ||
64 | |||
65 | struct fsms_nand_bank_regs { | ||
66 | uint32_t pc; | ||
67 | uint32_t sts; | ||
68 | uint32_t comm; | ||
69 | uint32_t attrib; | ||
70 | uint32_t ioata; | ||
71 | uint32_t ecc1; | ||
72 | uint32_t ecc2; | ||
73 | uint32_t ecc3; | ||
74 | }; | ||
75 | |||
76 | #define FSMC_NOR_REG_SIZE 0x40 | ||
77 | |||
78 | struct fsmc_regs { | ||
79 | struct fsmc_nor_bank_regs nor_bank_regs[FSMC_MAX_NOR_BANKS]; | ||
80 | uint8_t reserved_1[0x40 - 0x20]; | ||
81 | struct fsms_nand_bank_regs bank_regs[FSMC_MAX_NAND_BANKS]; | ||
82 | uint8_t reserved_2[0xfe0 - 0xc0]; | ||
83 | uint32_t peripid0; /* 0xfe0 */ | ||
84 | uint32_t peripid1; /* 0xfe4 */ | ||
85 | uint32_t peripid2; /* 0xfe8 */ | ||
86 | uint32_t peripid3; /* 0xfec */ | ||
87 | uint32_t pcellid0; /* 0xff0 */ | ||
88 | uint32_t pcellid1; /* 0xff4 */ | ||
89 | uint32_t pcellid2; /* 0xff8 */ | ||
90 | uint32_t pcellid3; /* 0xffc */ | ||
91 | }; | ||
92 | |||
93 | #define FSMC_BUSY_WAIT_TIMEOUT (1 * HZ) | ||
94 | |||
95 | /* pc register definitions */ | ||
96 | #define FSMC_RESET (1 << 0) | ||
97 | #define FSMC_WAITON (1 << 1) | ||
98 | #define FSMC_ENABLE (1 << 2) | ||
99 | #define FSMC_DEVTYPE_NAND (1 << 3) | ||
100 | #define FSMC_DEVWID_8 (0 << 4) | ||
101 | #define FSMC_DEVWID_16 (1 << 4) | ||
102 | #define FSMC_ECCEN (1 << 6) | ||
103 | #define FSMC_ECCPLEN_512 (0 << 7) | ||
104 | #define FSMC_ECCPLEN_256 (1 << 7) | ||
105 | #define FSMC_TCLR_1 (1 << 9) | ||
106 | #define FSMC_TAR_1 (1 << 13) | ||
107 | |||
108 | /* sts register definitions */ | ||
109 | #define FSMC_CODE_RDY (1 << 15) | ||
110 | |||
111 | /* comm register definitions */ | ||
112 | #define FSMC_TSET_0 (0 << 0) | ||
113 | #define FSMC_TWAIT_6 (6 << 8) | ||
114 | #define FSMC_THOLD_4 (4 << 16) | ||
115 | #define FSMC_THIZ_1 (1 << 24) | ||
116 | |||
117 | /* peripid2 register definitions */ | ||
118 | #define FSMC_REVISION_MSK (0xf) | ||
119 | #define FSMC_REVISION_SHFT (0x4) | ||
120 | |||
121 | #define FSMC_VER1 1 | ||
122 | #define FSMC_VER2 2 | ||
123 | #define FSMC_VER3 3 | ||
124 | #define FSMC_VER4 4 | ||
125 | #define FSMC_VER5 5 | ||
126 | #define FSMC_VER6 6 | ||
127 | #define FSMC_VER7 7 | ||
128 | #define FSMC_VER8 8 | ||
129 | |||
130 | static inline uint32_t get_fsmc_version(struct fsmc_regs *regs) | ||
131 | { | ||
132 | return (readl(®s->peripid2) >> FSMC_REVISION_SHFT) & | ||
133 | FSMC_REVISION_MSK; | ||
134 | } | ||
135 | |||
136 | /* | ||
137 | * There are 13 bytes of ecc for every 512 byte block in FSMC version 8 | ||
138 | * and it has to be read consecutively and immediately after the 512 | ||
139 | * byte data block for hardware to generate the error bit offsets | ||
140 | * Managing the ecc bytes in the following way is easier. This way is | ||
141 | * similar to oobfree structure maintained already in u-boot nand driver | ||
142 | */ | ||
143 | #define MAX_ECCPLACE_ENTRIES 32 | ||
144 | |||
145 | struct fsmc_nand_eccplace { | ||
146 | uint8_t offset; | ||
147 | uint8_t length; | ||
148 | }; | ||
149 | |||
150 | struct fsmc_eccplace { | ||
151 | struct fsmc_nand_eccplace eccplace[MAX_ECCPLACE_ENTRIES]; | ||
152 | }; | ||
153 | |||
154 | /** | ||
155 | * fsmc_nand_platform_data - platform specific NAND controller config | ||
156 | * @partitions: partition table for the platform, use a default fallback | ||
157 | * if this is NULL | ||
158 | * @nr_partitions: the number of partitions in the previous entry | ||
159 | * @options: different options for the driver | ||
160 | * @width: bus width | ||
161 | * @bank: default bank | ||
162 | * @select_bank: callback to select a certain bank, this is | ||
163 | * platform-specific. If the controller only supports one bank | ||
164 | * this may be set to NULL | ||
165 | */ | ||
166 | struct fsmc_nand_platform_data { | ||
167 | struct mtd_partition *partitions; | ||
168 | unsigned int nr_partitions; | ||
169 | unsigned int options; | ||
170 | unsigned int width; | ||
171 | unsigned int bank; | ||
172 | void (*select_bank)(uint32_t bank, uint32_t busw); | ||
173 | }; | ||
174 | |||
175 | extern int __init fsmc_nor_init(struct platform_device *pdev, | ||
176 | unsigned long base, uint32_t bank, uint32_t width); | ||
177 | extern void __init fsmc_init_board_info(struct platform_device *pdev, | ||
178 | struct mtd_partition *partitions, unsigned int nr_partitions, | ||
179 | unsigned int width); | ||
180 | |||
181 | #endif /* __MTD_FSMC_H */ | ||
diff --git a/include/linux/mtd/inftl.h b/include/linux/mtd/inftl.h index 64ee53ce95a9..02cd5f9b79b8 100644 --- a/include/linux/mtd/inftl.h +++ b/include/linux/mtd/inftl.h | |||
@@ -37,14 +37,14 @@ struct INFTLrecord { | |||
37 | __u16 firstEUN; | 37 | __u16 firstEUN; |
38 | __u16 lastEUN; | 38 | __u16 lastEUN; |
39 | __u16 numfreeEUNs; | 39 | __u16 numfreeEUNs; |
40 | __u16 LastFreeEUN; /* To speed up finding a free EUN */ | 40 | __u16 LastFreeEUN; /* To speed up finding a free EUN */ |
41 | int head,sect,cyl; | 41 | int head,sect,cyl; |
42 | __u16 *PUtable; /* Physical Unit Table */ | 42 | __u16 *PUtable; /* Physical Unit Table */ |
43 | __u16 *VUtable; /* Virtual Unit Table */ | 43 | __u16 *VUtable; /* Virtual Unit Table */ |
44 | unsigned int nb_blocks; /* number of physical blocks */ | 44 | unsigned int nb_blocks; /* number of physical blocks */ |
45 | unsigned int nb_boot_blocks; /* number of blocks used by the bios */ | 45 | unsigned int nb_boot_blocks; /* number of blocks used by the bios */ |
46 | struct erase_info instr; | 46 | struct erase_info instr; |
47 | struct nand_ecclayout oobinfo; | 47 | struct nand_ecclayout oobinfo; |
48 | }; | 48 | }; |
49 | 49 | ||
50 | int INFTL_mount(struct INFTLrecord *s); | 50 | int INFTL_mount(struct INFTLrecord *s); |
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 8485e42a9b09..fe8d77ebec13 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h | |||
@@ -110,6 +110,21 @@ struct mtd_oob_ops { | |||
110 | uint8_t *oobbuf; | 110 | uint8_t *oobbuf; |
111 | }; | 111 | }; |
112 | 112 | ||
113 | #define MTD_MAX_OOBFREE_ENTRIES_LARGE 32 | ||
114 | #define MTD_MAX_ECCPOS_ENTRIES_LARGE 448 | ||
115 | /* | ||
116 | * Internal ECC layout control structure. For historical reasons, there is a | ||
117 | * similar, smaller struct nand_ecclayout_user (in mtd-abi.h) that is retained | ||
118 | * for export to user-space via the ECCGETLAYOUT ioctl. | ||
119 | * nand_ecclayout should be expandable in the future simply by the above macros. | ||
120 | */ | ||
121 | struct nand_ecclayout { | ||
122 | __u32 eccbytes; | ||
123 | __u32 eccpos[MTD_MAX_ECCPOS_ENTRIES_LARGE]; | ||
124 | __u32 oobavail; | ||
125 | struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES_LARGE]; | ||
126 | }; | ||
127 | |||
113 | struct mtd_info { | 128 | struct mtd_info { |
114 | u_char type; | 129 | u_char type; |
115 | uint32_t flags; | 130 | uint32_t flags; |
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 102e12c58cb3..63e17d01fde9 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h | |||
@@ -27,15 +27,17 @@ | |||
27 | struct mtd_info; | 27 | struct mtd_info; |
28 | struct nand_flash_dev; | 28 | struct nand_flash_dev; |
29 | /* Scan and identify a NAND device */ | 29 | /* Scan and identify a NAND device */ |
30 | extern int nand_scan (struct mtd_info *mtd, int max_chips); | 30 | extern int nand_scan(struct mtd_info *mtd, int max_chips); |
31 | /* Separate phases of nand_scan(), allowing board driver to intervene | 31 | /* |
32 | * and override command or ECC setup according to flash type */ | 32 | * Separate phases of nand_scan(), allowing board driver to intervene |
33 | * and override command or ECC setup according to flash type. | ||
34 | */ | ||
33 | extern int nand_scan_ident(struct mtd_info *mtd, int max_chips, | 35 | extern int nand_scan_ident(struct mtd_info *mtd, int max_chips, |
34 | struct nand_flash_dev *table); | 36 | struct nand_flash_dev *table); |
35 | extern int nand_scan_tail(struct mtd_info *mtd); | 37 | extern int nand_scan_tail(struct mtd_info *mtd); |
36 | 38 | ||
37 | /* Free resources held by the NAND device */ | 39 | /* Free resources held by the NAND device */ |
38 | extern void nand_release (struct mtd_info *mtd); | 40 | extern void nand_release(struct mtd_info *mtd); |
39 | 41 | ||
40 | /* Internal helper for board drivers which need to override command function */ | 42 | /* Internal helper for board drivers which need to override command function */ |
41 | extern void nand_wait_ready(struct mtd_info *mtd); | 43 | extern void nand_wait_ready(struct mtd_info *mtd); |
@@ -49,12 +51,13 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); | |||
49 | /* The maximum number of NAND chips in an array */ | 51 | /* The maximum number of NAND chips in an array */ |
50 | #define NAND_MAX_CHIPS 8 | 52 | #define NAND_MAX_CHIPS 8 |
51 | 53 | ||
52 | /* This constant declares the max. oobsize / page, which | 54 | /* |
55 | * This constant declares the max. oobsize / page, which | ||
53 | * is supported now. If you add a chip with bigger oobsize/page | 56 | * is supported now. If you add a chip with bigger oobsize/page |
54 | * adjust this accordingly. | 57 | * adjust this accordingly. |
55 | */ | 58 | */ |
56 | #define NAND_MAX_OOBSIZE 256 | 59 | #define NAND_MAX_OOBSIZE 576 |
57 | #define NAND_MAX_PAGESIZE 4096 | 60 | #define NAND_MAX_PAGESIZE 8192 |
58 | 61 | ||
59 | /* | 62 | /* |
60 | * Constants for hardware specific CLE/ALE/NCE function | 63 | * Constants for hardware specific CLE/ALE/NCE function |
@@ -88,6 +91,7 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); | |||
88 | #define NAND_CMD_RNDIN 0x85 | 91 | #define NAND_CMD_RNDIN 0x85 |
89 | #define NAND_CMD_READID 0x90 | 92 | #define NAND_CMD_READID 0x90 |
90 | #define NAND_CMD_ERASE2 0xd0 | 93 | #define NAND_CMD_ERASE2 0xd0 |
94 | #define NAND_CMD_PARAM 0xec | ||
91 | #define NAND_CMD_RESET 0xff | 95 | #define NAND_CMD_RESET 0xff |
92 | 96 | ||
93 | #define NAND_CMD_LOCK 0x2a | 97 | #define NAND_CMD_LOCK 0x2a |
@@ -152,9 +156,10 @@ typedef enum { | |||
152 | #define NAND_GET_DEVICE 0x80 | 156 | #define NAND_GET_DEVICE 0x80 |
153 | 157 | ||
154 | 158 | ||
155 | /* Option constants for bizarre disfunctionality and real | 159 | /* |
156 | * features | 160 | * Option constants for bizarre disfunctionality and real |
157 | */ | 161 | * features. |
162 | */ | ||
158 | /* Chip can not auto increment pages */ | 163 | /* Chip can not auto increment pages */ |
159 | #define NAND_NO_AUTOINCR 0x00000001 | 164 | #define NAND_NO_AUTOINCR 0x00000001 |
160 | /* Buswitdh is 16 bit */ | 165 | /* Buswitdh is 16 bit */ |
@@ -165,19 +170,27 @@ typedef enum { | |||
165 | #define NAND_CACHEPRG 0x00000008 | 170 | #define NAND_CACHEPRG 0x00000008 |
166 | /* Chip has copy back function */ | 171 | /* Chip has copy back function */ |
167 | #define NAND_COPYBACK 0x00000010 | 172 | #define NAND_COPYBACK 0x00000010 |
168 | /* AND Chip which has 4 banks and a confusing page / block | 173 | /* |
169 | * assignment. See Renesas datasheet for further information */ | 174 | * AND Chip which has 4 banks and a confusing page / block |
175 | * assignment. See Renesas datasheet for further information. | ||
176 | */ | ||
170 | #define NAND_IS_AND 0x00000020 | 177 | #define NAND_IS_AND 0x00000020 |
171 | /* Chip has a array of 4 pages which can be read without | 178 | /* |
172 | * additional ready /busy waits */ | 179 | * Chip has a array of 4 pages which can be read without |
180 | * additional ready /busy waits. | ||
181 | */ | ||
173 | #define NAND_4PAGE_ARRAY 0x00000040 | 182 | #define NAND_4PAGE_ARRAY 0x00000040 |
174 | /* Chip requires that BBT is periodically rewritten to prevent | 183 | /* |
184 | * Chip requires that BBT is periodically rewritten to prevent | ||
175 | * bits from adjacent blocks from 'leaking' in altering data. | 185 | * bits from adjacent blocks from 'leaking' in altering data. |
176 | * This happens with the Renesas AG-AND chips, possibly others. */ | 186 | * This happens with the Renesas AG-AND chips, possibly others. |
187 | */ | ||
177 | #define BBT_AUTO_REFRESH 0x00000080 | 188 | #define BBT_AUTO_REFRESH 0x00000080 |
178 | /* Chip does not require ready check on read. True | 189 | /* |
190 | * Chip does not require ready check on read. True | ||
179 | * for all large page devices, as they do not support | 191 | * for all large page devices, as they do not support |
180 | * autoincrement.*/ | 192 | * autoincrement. |
193 | */ | ||
181 | #define NAND_NO_READRDY 0x00000100 | 194 | #define NAND_NO_READRDY 0x00000100 |
182 | /* Chip does not allow subpage writes */ | 195 | /* Chip does not allow subpage writes */ |
183 | #define NAND_NO_SUBPAGE_WRITE 0x00000200 | 196 | #define NAND_NO_SUBPAGE_WRITE 0x00000200 |
@@ -205,16 +218,27 @@ typedef enum { | |||
205 | #define NAND_CHIPOPTIONS_MSK (0x0000ffff & ~NAND_NO_AUTOINCR) | 218 | #define NAND_CHIPOPTIONS_MSK (0x0000ffff & ~NAND_NO_AUTOINCR) |
206 | 219 | ||
207 | /* Non chip related options */ | 220 | /* Non chip related options */ |
208 | /* Use a flash based bad block table. This option is passed to the | 221 | /* |
209 | * default bad block table function. */ | 222 | * Use a flash based bad block table. OOB identifier is saved in OOB area. |
223 | * This option is passed to the default bad block table function. | ||
224 | */ | ||
210 | #define NAND_USE_FLASH_BBT 0x00010000 | 225 | #define NAND_USE_FLASH_BBT 0x00010000 |
211 | /* This option skips the bbt scan during initialization. */ | 226 | /* This option skips the bbt scan during initialization. */ |
212 | #define NAND_SKIP_BBTSCAN 0x00020000 | 227 | #define NAND_SKIP_BBTSCAN 0x00020000 |
213 | /* This option is defined if the board driver allocates its own buffers | 228 | /* |
214 | (e.g. because it needs them DMA-coherent */ | 229 | * This option is defined if the board driver allocates its own buffers |
230 | * (e.g. because it needs them DMA-coherent). | ||
231 | */ | ||
215 | #define NAND_OWN_BUFFERS 0x00040000 | 232 | #define NAND_OWN_BUFFERS 0x00040000 |
216 | /* Chip may not exist, so silence any errors in scan */ | 233 | /* Chip may not exist, so silence any errors in scan */ |
217 | #define NAND_SCAN_SILENT_NODEV 0x00080000 | 234 | #define NAND_SCAN_SILENT_NODEV 0x00080000 |
235 | /* | ||
236 | * If passed additionally to NAND_USE_FLASH_BBT then BBT code will not touch | ||
237 | * the OOB area. | ||
238 | */ | ||
239 | #define NAND_USE_FLASH_BBT_NO_OOB 0x00100000 | ||
240 | /* Create an empty BBT with no vendor information if the BBT is available */ | ||
241 | #define NAND_CREATE_EMPTY_BBT 0x00200000 | ||
218 | 242 | ||
219 | /* Options set by nand scan */ | 243 | /* Options set by nand scan */ |
220 | /* Nand scan has allocated controller struct */ | 244 | /* Nand scan has allocated controller struct */ |
@@ -227,15 +251,80 @@ typedef enum { | |||
227 | /* Keep gcc happy */ | 251 | /* Keep gcc happy */ |
228 | struct nand_chip; | 252 | struct nand_chip; |
229 | 253 | ||
254 | struct nand_onfi_params { | ||
255 | /* rev info and features block */ | ||
256 | /* 'O' 'N' 'F' 'I' */ | ||
257 | u8 sig[4]; | ||
258 | __le16 revision; | ||
259 | __le16 features; | ||
260 | __le16 opt_cmd; | ||
261 | u8 reserved[22]; | ||
262 | |||
263 | /* manufacturer information block */ | ||
264 | char manufacturer[12]; | ||
265 | char model[20]; | ||
266 | u8 jedec_id; | ||
267 | __le16 date_code; | ||
268 | u8 reserved2[13]; | ||
269 | |||
270 | /* memory organization block */ | ||
271 | __le32 byte_per_page; | ||
272 | __le16 spare_bytes_per_page; | ||
273 | __le32 data_bytes_per_ppage; | ||
274 | __le16 spare_bytes_per_ppage; | ||
275 | __le32 pages_per_block; | ||
276 | __le32 blocks_per_lun; | ||
277 | u8 lun_count; | ||
278 | u8 addr_cycles; | ||
279 | u8 bits_per_cell; | ||
280 | __le16 bb_per_lun; | ||
281 | __le16 block_endurance; | ||
282 | u8 guaranteed_good_blocks; | ||
283 | __le16 guaranteed_block_endurance; | ||
284 | u8 programs_per_page; | ||
285 | u8 ppage_attr; | ||
286 | u8 ecc_bits; | ||
287 | u8 interleaved_bits; | ||
288 | u8 interleaved_ops; | ||
289 | u8 reserved3[13]; | ||
290 | |||
291 | /* electrical parameter block */ | ||
292 | u8 io_pin_capacitance_max; | ||
293 | __le16 async_timing_mode; | ||
294 | __le16 program_cache_timing_mode; | ||
295 | __le16 t_prog; | ||
296 | __le16 t_bers; | ||
297 | __le16 t_r; | ||
298 | __le16 t_ccs; | ||
299 | __le16 src_sync_timing_mode; | ||
300 | __le16 src_ssync_features; | ||
301 | __le16 clk_pin_capacitance_typ; | ||
302 | __le16 io_pin_capacitance_typ; | ||
303 | __le16 input_pin_capacitance_typ; | ||
304 | u8 input_pin_capacitance_max; | ||
305 | u8 driver_strenght_support; | ||
306 | __le16 t_int_r; | ||
307 | __le16 t_ald; | ||
308 | u8 reserved4[7]; | ||
309 | |||
310 | /* vendor */ | ||
311 | u8 reserved5[90]; | ||
312 | |||
313 | __le16 crc; | ||
314 | } __attribute__((packed)); | ||
315 | |||
316 | #define ONFI_CRC_BASE 0x4F4E | ||
317 | |||
230 | /** | 318 | /** |
231 | * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices | 319 | * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices |
232 | * @lock: protection lock | 320 | * @lock: protection lock |
233 | * @active: the mtd device which holds the controller currently | 321 | * @active: the mtd device which holds the controller currently |
234 | * @wq: wait queue to sleep on if a NAND operation is in progress | 322 | * @wq: wait queue to sleep on if a NAND operation is in |
235 | * used instead of the per chip wait queue when a hw controller is available | 323 | * progress used instead of the per chip wait queue |
324 | * when a hw controller is available. | ||
236 | */ | 325 | */ |
237 | struct nand_hw_control { | 326 | struct nand_hw_control { |
238 | spinlock_t lock; | 327 | spinlock_t lock; |
239 | struct nand_chip *active; | 328 | struct nand_chip *active; |
240 | wait_queue_head_t wq; | 329 | wait_queue_head_t wq; |
241 | }; | 330 | }; |
@@ -256,51 +345,42 @@ struct nand_hw_control { | |||
256 | * @correct: function for ecc correction, matching to ecc generator (sw/hw) | 345 | * @correct: function for ecc correction, matching to ecc generator (sw/hw) |
257 | * @read_page_raw: function to read a raw page without ECC | 346 | * @read_page_raw: function to read a raw page without ECC |
258 | * @write_page_raw: function to write a raw page without ECC | 347 | * @write_page_raw: function to write a raw page without ECC |
259 | * @read_page: function to read a page according to the ecc generator requirements | 348 | * @read_page: function to read a page according to the ecc generator |
349 | * requirements. | ||
260 | * @read_subpage: function to read parts of the page covered by ECC. | 350 | * @read_subpage: function to read parts of the page covered by ECC. |
261 | * @write_page: function to write a page according to the ecc generator requirements | 351 | * @write_page: function to write a page according to the ecc generator |
352 | * requirements. | ||
262 | * @read_oob: function to read chip OOB data | 353 | * @read_oob: function to read chip OOB data |
263 | * @write_oob: function to write chip OOB data | 354 | * @write_oob: function to write chip OOB data |
264 | */ | 355 | */ |
265 | struct nand_ecc_ctrl { | 356 | struct nand_ecc_ctrl { |
266 | nand_ecc_modes_t mode; | 357 | nand_ecc_modes_t mode; |
267 | int steps; | 358 | int steps; |
268 | int size; | 359 | int size; |
269 | int bytes; | 360 | int bytes; |
270 | int total; | 361 | int total; |
271 | int prepad; | 362 | int prepad; |
272 | int postpad; | 363 | int postpad; |
273 | struct nand_ecclayout *layout; | 364 | struct nand_ecclayout *layout; |
274 | void (*hwctl)(struct mtd_info *mtd, int mode); | 365 | void (*hwctl)(struct mtd_info *mtd, int mode); |
275 | int (*calculate)(struct mtd_info *mtd, | 366 | int (*calculate)(struct mtd_info *mtd, const uint8_t *dat, |
276 | const uint8_t *dat, | 367 | uint8_t *ecc_code); |
277 | uint8_t *ecc_code); | 368 | int (*correct)(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc, |
278 | int (*correct)(struct mtd_info *mtd, uint8_t *dat, | 369 | uint8_t *calc_ecc); |
279 | uint8_t *read_ecc, | 370 | int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, |
280 | uint8_t *calc_ecc); | 371 | uint8_t *buf, int page); |
281 | int (*read_page_raw)(struct mtd_info *mtd, | 372 | void (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, |
282 | struct nand_chip *chip, | 373 | const uint8_t *buf); |
283 | uint8_t *buf, int page); | 374 | int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip, |
284 | void (*write_page_raw)(struct mtd_info *mtd, | 375 | uint8_t *buf, int page); |
285 | struct nand_chip *chip, | 376 | int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip, |
286 | const uint8_t *buf); | 377 | uint32_t offs, uint32_t len, uint8_t *buf); |
287 | int (*read_page)(struct mtd_info *mtd, | 378 | void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, |
288 | struct nand_chip *chip, | 379 | const uint8_t *buf); |
289 | uint8_t *buf, int page); | 380 | int (*read_oob)(struct mtd_info *mtd, struct nand_chip *chip, int page, |
290 | int (*read_subpage)(struct mtd_info *mtd, | 381 | int sndcmd); |
291 | struct nand_chip *chip, | 382 | int (*write_oob)(struct mtd_info *mtd, struct nand_chip *chip, |
292 | uint32_t offs, uint32_t len, | 383 | int page); |
293 | uint8_t *buf); | ||
294 | void (*write_page)(struct mtd_info *mtd, | ||
295 | struct nand_chip *chip, | ||
296 | const uint8_t *buf); | ||
297 | int (*read_oob)(struct mtd_info *mtd, | ||
298 | struct nand_chip *chip, | ||
299 | int page, | ||
300 | int sndcmd); | ||
301 | int (*write_oob)(struct mtd_info *mtd, | ||
302 | struct nand_chip *chip, | ||
303 | int page); | ||
304 | }; | 384 | }; |
305 | 385 | ||
306 | /** | 386 | /** |
@@ -320,102 +400,132 @@ struct nand_buffers { | |||
320 | 400 | ||
321 | /** | 401 | /** |
322 | * struct nand_chip - NAND Private Flash Chip Data | 402 | * struct nand_chip - NAND Private Flash Chip Data |
323 | * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device | 403 | * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the |
324 | * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device | 404 | * flash device |
405 | * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the | ||
406 | * flash device. | ||
325 | * @read_byte: [REPLACEABLE] read one byte from the chip | 407 | * @read_byte: [REPLACEABLE] read one byte from the chip |
326 | * @read_word: [REPLACEABLE] read one word from the chip | 408 | * @read_word: [REPLACEABLE] read one word from the chip |
327 | * @write_buf: [REPLACEABLE] write data from the buffer to the chip | 409 | * @write_buf: [REPLACEABLE] write data from the buffer to the chip |
328 | * @read_buf: [REPLACEABLE] read data from the chip into the buffer | 410 | * @read_buf: [REPLACEABLE] read data from the chip into the buffer |
329 | * @verify_buf: [REPLACEABLE] verify buffer contents against the chip data | 411 | * @verify_buf: [REPLACEABLE] verify buffer contents against the chip |
412 | * data. | ||
330 | * @select_chip: [REPLACEABLE] select chip nr | 413 | * @select_chip: [REPLACEABLE] select chip nr |
331 | * @block_bad: [REPLACEABLE] check, if the block is bad | 414 | * @block_bad: [REPLACEABLE] check, if the block is bad |
332 | * @block_markbad: [REPLACEABLE] mark the block bad | 415 | * @block_markbad: [REPLACEABLE] mark the block bad |
333 | * @cmd_ctrl: [BOARDSPECIFIC] hardwarespecific funtion for controlling | 416 | * @cmd_ctrl: [BOARDSPECIFIC] hardwarespecific funtion for controlling |
334 | * ALE/CLE/nCE. Also used to write command and address | 417 | * ALE/CLE/nCE. Also used to write command and address |
335 | * @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line | 418 | * @init_size: [BOARDSPECIFIC] hardwarespecific funtion for setting |
336 | * If set to NULL no access to ready/busy is available and the ready/busy information | 419 | * mtd->oobsize, mtd->writesize and so on. |
337 | * is read from the chip status register | 420 | * @id_data contains the 8 bytes values of NAND_CMD_READID. |
338 | * @cmdfunc: [REPLACEABLE] hardwarespecific function for writing commands to the chip | 421 | * Return with the bus width. |
339 | * @waitfunc: [REPLACEABLE] hardwarespecific function for wait on ready | 422 | * @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accesing |
423 | * device ready/busy line. If set to NULL no access to | ||
424 | * ready/busy is available and the ready/busy information | ||
425 | * is read from the chip status register. | ||
426 | * @cmdfunc: [REPLACEABLE] hardwarespecific function for writing | ||
427 | * commands to the chip. | ||
428 | * @waitfunc: [REPLACEABLE] hardwarespecific function for wait on | ||
429 | * ready. | ||
340 | * @ecc: [BOARDSPECIFIC] ecc control ctructure | 430 | * @ecc: [BOARDSPECIFIC] ecc control ctructure |
341 | * @buffers: buffer structure for read/write | 431 | * @buffers: buffer structure for read/write |
342 | * @hwcontrol: platform-specific hardware control structure | 432 | * @hwcontrol: platform-specific hardware control structure |
343 | * @ops: oob operation operands | 433 | * @ops: oob operation operands |
344 | * @erase_cmd: [INTERN] erase command write function, selectable due to AND support | 434 | * @erase_cmd: [INTERN] erase command write function, selectable due |
435 | * to AND support. | ||
345 | * @scan_bbt: [REPLACEABLE] function to scan bad block table | 436 | * @scan_bbt: [REPLACEABLE] function to scan bad block table |
346 | * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR) | 437 | * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transfering |
438 | * data from array to read regs (tR). | ||
347 | * @state: [INTERN] the current state of the NAND device | 439 | * @state: [INTERN] the current state of the NAND device |
348 | * @oob_poi: poison value buffer | 440 | * @oob_poi: poison value buffer |
349 | * @page_shift: [INTERN] number of address bits in a page (column address bits) | 441 | * @page_shift: [INTERN] number of address bits in a page (column |
442 | * address bits). | ||
350 | * @phys_erase_shift: [INTERN] number of address bits in a physical eraseblock | 443 | * @phys_erase_shift: [INTERN] number of address bits in a physical eraseblock |
351 | * @bbt_erase_shift: [INTERN] number of address bits in a bbt entry | 444 | * @bbt_erase_shift: [INTERN] number of address bits in a bbt entry |
352 | * @chip_shift: [INTERN] number of address bits in one chip | 445 | * @chip_shift: [INTERN] number of address bits in one chip |
353 | * @options: [BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about | 446 | * @options: [BOARDSPECIFIC] various chip options. They can partly |
354 | * special functionality. See the defines for further explanation | 447 | * be set to inform nand_scan about special functionality. |
355 | * @badblockpos: [INTERN] position of the bad block marker in the oob area | 448 | * See the defines for further explanation. |
449 | * @badblockpos: [INTERN] position of the bad block marker in the oob | ||
450 | * area. | ||
356 | * @cellinfo: [INTERN] MLC/multichip data from chip ident | 451 | * @cellinfo: [INTERN] MLC/multichip data from chip ident |
357 | * @numchips: [INTERN] number of physical chips | 452 | * @numchips: [INTERN] number of physical chips |
358 | * @chipsize: [INTERN] the size of one chip for multichip arrays | 453 | * @chipsize: [INTERN] the size of one chip for multichip arrays |
359 | * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1 | 454 | * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1 |
360 | * @pagebuf: [INTERN] holds the pagenumber which is currently in data_buf | 455 | * @pagebuf: [INTERN] holds the pagenumber which is currently in |
456 | * data_buf. | ||
361 | * @subpagesize: [INTERN] holds the subpagesize | 457 | * @subpagesize: [INTERN] holds the subpagesize |
458 | * @onfi_version: [INTERN] holds the chip ONFI version (BCD encoded), | ||
459 | * non 0 if ONFI supported. | ||
460 | * @onfi_params: [INTERN] holds the ONFI page parameter when ONFI is | ||
461 | * supported, 0 otherwise. | ||
362 | * @ecclayout: [REPLACEABLE] the default ecc placement scheme | 462 | * @ecclayout: [REPLACEABLE] the default ecc placement scheme |
363 | * @bbt: [INTERN] bad block table pointer | 463 | * @bbt: [INTERN] bad block table pointer |
364 | * @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup | 464 | * @bbt_td: [REPLACEABLE] bad block table descriptor for flash |
465 | * lookup. | ||
365 | * @bbt_md: [REPLACEABLE] bad block table mirror descriptor | 466 | * @bbt_md: [REPLACEABLE] bad block table mirror descriptor |
366 | * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial bad block scan | 467 | * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial |
367 | * @controller: [REPLACEABLE] a pointer to a hardware controller structure | 468 | * bad block scan. |
368 | * which is shared among multiple independend devices | 469 | * @controller: [REPLACEABLE] a pointer to a hardware controller |
470 | * structure which is shared among multiple independend | ||
471 | * devices. | ||
369 | * @priv: [OPTIONAL] pointer to private chip date | 472 | * @priv: [OPTIONAL] pointer to private chip date |
370 | * @errstat: [OPTIONAL] hardware specific function to perform additional error status checks | 473 | * @errstat: [OPTIONAL] hardware specific function to perform |
371 | * (determine if errors are correctable) | 474 | * additional error status checks (determine if errors are |
475 | * correctable). | ||
372 | * @write_page: [REPLACEABLE] High-level page write function | 476 | * @write_page: [REPLACEABLE] High-level page write function |
373 | */ | 477 | */ |
374 | 478 | ||
375 | struct nand_chip { | 479 | struct nand_chip { |
376 | void __iomem *IO_ADDR_R; | 480 | void __iomem *IO_ADDR_R; |
377 | void __iomem *IO_ADDR_W; | 481 | void __iomem *IO_ADDR_W; |
378 | 482 | ||
379 | uint8_t (*read_byte)(struct mtd_info *mtd); | 483 | uint8_t (*read_byte)(struct mtd_info *mtd); |
380 | u16 (*read_word)(struct mtd_info *mtd); | 484 | u16 (*read_word)(struct mtd_info *mtd); |
381 | void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); | 485 | void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); |
382 | void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len); | 486 | void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len); |
383 | int (*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); | 487 | int (*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); |
384 | void (*select_chip)(struct mtd_info *mtd, int chip); | 488 | void (*select_chip)(struct mtd_info *mtd, int chip); |
385 | int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip); | 489 | int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip); |
386 | int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); | 490 | int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); |
387 | void (*cmd_ctrl)(struct mtd_info *mtd, int dat, | 491 | void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl); |
388 | unsigned int ctrl); | 492 | int (*init_size)(struct mtd_info *mtd, struct nand_chip *this, |
389 | int (*dev_ready)(struct mtd_info *mtd); | 493 | u8 *id_data); |
390 | void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr); | 494 | int (*dev_ready)(struct mtd_info *mtd); |
391 | int (*waitfunc)(struct mtd_info *mtd, struct nand_chip *this); | 495 | void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, |
392 | void (*erase_cmd)(struct mtd_info *mtd, int page); | 496 | int page_addr); |
393 | int (*scan_bbt)(struct mtd_info *mtd); | 497 | int(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this); |
394 | int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page); | 498 | void (*erase_cmd)(struct mtd_info *mtd, int page); |
395 | int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, | 499 | int (*scan_bbt)(struct mtd_info *mtd); |
396 | const uint8_t *buf, int page, int cached, int raw); | 500 | int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, |
397 | 501 | int status, int page); | |
398 | int chip_delay; | 502 | int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, |
399 | unsigned int options; | 503 | const uint8_t *buf, int page, int cached, int raw); |
400 | 504 | ||
401 | int page_shift; | 505 | int chip_delay; |
402 | int phys_erase_shift; | 506 | unsigned int options; |
403 | int bbt_erase_shift; | 507 | |
404 | int chip_shift; | 508 | int page_shift; |
405 | int numchips; | 509 | int phys_erase_shift; |
406 | uint64_t chipsize; | 510 | int bbt_erase_shift; |
407 | int pagemask; | 511 | int chip_shift; |
408 | int pagebuf; | 512 | int numchips; |
409 | int subpagesize; | 513 | uint64_t chipsize; |
410 | uint8_t cellinfo; | 514 | int pagemask; |
411 | int badblockpos; | 515 | int pagebuf; |
412 | int badblockbits; | 516 | int subpagesize; |
413 | 517 | uint8_t cellinfo; | |
414 | flstate_t state; | 518 | int badblockpos; |
415 | 519 | int badblockbits; | |
416 | uint8_t *oob_poi; | 520 | |
417 | struct nand_hw_control *controller; | 521 | int onfi_version; |
418 | struct nand_ecclayout *ecclayout; | 522 | struct nand_onfi_params onfi_params; |
523 | |||
524 | flstate_t state; | ||
525 | |||
526 | uint8_t *oob_poi; | ||
527 | struct nand_hw_control *controller; | ||
528 | struct nand_ecclayout *ecclayout; | ||
419 | 529 | ||
420 | struct nand_ecc_ctrl ecc; | 530 | struct nand_ecc_ctrl ecc; |
421 | struct nand_buffers *buffers; | 531 | struct nand_buffers *buffers; |
@@ -423,13 +533,13 @@ struct nand_chip { | |||
423 | 533 | ||
424 | struct mtd_oob_ops ops; | 534 | struct mtd_oob_ops ops; |
425 | 535 | ||
426 | uint8_t *bbt; | 536 | uint8_t *bbt; |
427 | struct nand_bbt_descr *bbt_td; | 537 | struct nand_bbt_descr *bbt_td; |
428 | struct nand_bbt_descr *bbt_md; | 538 | struct nand_bbt_descr *bbt_md; |
429 | 539 | ||
430 | struct nand_bbt_descr *badblock_pattern; | 540 | struct nand_bbt_descr *badblock_pattern; |
431 | 541 | ||
432 | void *priv; | 542 | void *priv; |
433 | }; | 543 | }; |
434 | 544 | ||
435 | /* | 545 | /* |
@@ -473,7 +583,7 @@ struct nand_flash_dev { | |||
473 | */ | 583 | */ |
474 | struct nand_manufacturers { | 584 | struct nand_manufacturers { |
475 | int id; | 585 | int id; |
476 | char * name; | 586 | char *name; |
477 | }; | 587 | }; |
478 | 588 | ||
479 | extern struct nand_flash_dev nand_flash_ids[]; | 589 | extern struct nand_flash_dev nand_flash_ids[]; |
@@ -486,7 +596,7 @@ extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt); | |||
486 | extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, | 596 | extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, |
487 | int allowbbt); | 597 | int allowbbt); |
488 | extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len, | 598 | extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len, |
489 | size_t * retlen, uint8_t * buf); | 599 | size_t *retlen, uint8_t *buf); |
490 | 600 | ||
491 | /** | 601 | /** |
492 | * struct platform_nand_chip - chip level device structure | 602 | * struct platform_nand_chip - chip level device structure |
@@ -502,17 +612,16 @@ extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
502 | * @priv: hardware controller specific settings | 612 | * @priv: hardware controller specific settings |
503 | */ | 613 | */ |
504 | struct platform_nand_chip { | 614 | struct platform_nand_chip { |
505 | int nr_chips; | 615 | int nr_chips; |
506 | int chip_offset; | 616 | int chip_offset; |
507 | int nr_partitions; | 617 | int nr_partitions; |
508 | struct mtd_partition *partitions; | 618 | struct mtd_partition *partitions; |
509 | struct nand_ecclayout *ecclayout; | 619 | struct nand_ecclayout *ecclayout; |
510 | int chip_delay; | 620 | int chip_delay; |
511 | unsigned int options; | 621 | unsigned int options; |
512 | const char **part_probe_types; | 622 | const char **part_probe_types; |
513 | void (*set_parts)(uint64_t size, | 623 | void (*set_parts)(uint64_t size, struct platform_nand_chip *chip); |
514 | struct platform_nand_chip *chip); | 624 | void *priv; |
515 | void *priv; | ||
516 | }; | 625 | }; |
517 | 626 | ||
518 | /* Keep gcc happy */ | 627 | /* Keep gcc happy */ |
@@ -534,18 +643,15 @@ struct platform_device; | |||
534 | * All fields are optional and depend on the hardware driver requirements | 643 | * All fields are optional and depend on the hardware driver requirements |
535 | */ | 644 | */ |
536 | struct platform_nand_ctrl { | 645 | struct platform_nand_ctrl { |
537 | int (*probe)(struct platform_device *pdev); | 646 | int (*probe)(struct platform_device *pdev); |
538 | void (*remove)(struct platform_device *pdev); | 647 | void (*remove)(struct platform_device *pdev); |
539 | void (*hwcontrol)(struct mtd_info *mtd, int cmd); | 648 | void (*hwcontrol)(struct mtd_info *mtd, int cmd); |
540 | int (*dev_ready)(struct mtd_info *mtd); | 649 | int (*dev_ready)(struct mtd_info *mtd); |
541 | void (*select_chip)(struct mtd_info *mtd, int chip); | 650 | void (*select_chip)(struct mtd_info *mtd, int chip); |
542 | void (*cmd_ctrl)(struct mtd_info *mtd, int dat, | 651 | void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl); |
543 | unsigned int ctrl); | 652 | void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len); |
544 | void (*write_buf)(struct mtd_info *mtd, | 653 | void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len); |
545 | const uint8_t *buf, int len); | 654 | void *priv; |
546 | void (*read_buf)(struct mtd_info *mtd, | ||
547 | uint8_t *buf, int len); | ||
548 | void *priv; | ||
549 | }; | 655 | }; |
550 | 656 | ||
551 | /** | 657 | /** |
@@ -554,8 +660,8 @@ struct platform_nand_ctrl { | |||
554 | * @ctrl: controller level device structure | 660 | * @ctrl: controller level device structure |
555 | */ | 661 | */ |
556 | struct platform_nand_data { | 662 | struct platform_nand_data { |
557 | struct platform_nand_chip chip; | 663 | struct platform_nand_chip chip; |
558 | struct platform_nand_ctrl ctrl; | 664 | struct platform_nand_ctrl ctrl; |
559 | }; | 665 | }; |
560 | 666 | ||
561 | /* Some helpers to access the data structures */ | 667 | /* Some helpers to access the data structures */ |
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h index 274b6196091d..2b54316591d2 100644 --- a/include/linux/mtd/partitions.h +++ b/include/linux/mtd/partitions.h | |||
@@ -39,7 +39,7 @@ struct mtd_partition { | |||
39 | uint64_t size; /* partition size */ | 39 | uint64_t size; /* partition size */ |
40 | uint64_t offset; /* offset within the master MTD space */ | 40 | uint64_t offset; /* offset within the master MTD space */ |
41 | uint32_t mask_flags; /* master MTD flags to mask out for this partition */ | 41 | uint32_t mask_flags; /* master MTD flags to mask out for this partition */ |
42 | struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/ | 42 | struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only) */ |
43 | }; | 43 | }; |
44 | 44 | ||
45 | #define MTDPART_OFS_NXTBLK (-2) | 45 | #define MTDPART_OFS_NXTBLK (-2) |
@@ -89,4 +89,9 @@ static inline int mtd_has_cmdlinepart(void) { return 1; } | |||
89 | static inline int mtd_has_cmdlinepart(void) { return 0; } | 89 | static inline int mtd_has_cmdlinepart(void) { return 0; } |
90 | #endif | 90 | #endif |
91 | 91 | ||
92 | int mtd_is_master(struct mtd_info *mtd); | ||
93 | int mtd_add_partition(struct mtd_info *master, char *name, | ||
94 | long long offset, long long length); | ||
95 | int mtd_del_partition(struct mtd_info *master, int partno); | ||
96 | |||
92 | #endif | 97 | #endif |
diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h index 4debb4514634..2f7d45bcbd24 100644 --- a/include/mtd/mtd-abi.h +++ b/include/mtd/mtd-abi.h | |||
@@ -52,6 +52,7 @@ struct mtd_oob_buf64 { | |||
52 | #define MTD_NANDFLASH 4 | 52 | #define MTD_NANDFLASH 4 |
53 | #define MTD_DATAFLASH 6 | 53 | #define MTD_DATAFLASH 6 |
54 | #define MTD_UBIVOLUME 7 | 54 | #define MTD_UBIVOLUME 7 |
55 | #define MTD_MLCNANDFLASH 8 | ||
55 | 56 | ||
56 | #define MTD_WRITEABLE 0x400 /* Device is writeable */ | 57 | #define MTD_WRITEABLE 0x400 /* Device is writeable */ |
57 | #define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */ | 58 | #define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */ |
@@ -119,7 +120,7 @@ struct otp_info { | |||
119 | #define OTPGETREGIONCOUNT _IOW('M', 14, int) | 120 | #define OTPGETREGIONCOUNT _IOW('M', 14, int) |
120 | #define OTPGETREGIONINFO _IOW('M', 15, struct otp_info) | 121 | #define OTPGETREGIONINFO _IOW('M', 15, struct otp_info) |
121 | #define OTPLOCK _IOR('M', 16, struct otp_info) | 122 | #define OTPLOCK _IOR('M', 16, struct otp_info) |
122 | #define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout) | 123 | #define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout_user) |
123 | #define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats) | 124 | #define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats) |
124 | #define MTDFILEMODE _IO('M', 19) | 125 | #define MTDFILEMODE _IO('M', 19) |
125 | #define MEMERASE64 _IOW('M', 20, struct erase_info_user64) | 126 | #define MEMERASE64 _IOW('M', 20, struct erase_info_user64) |
@@ -144,13 +145,18 @@ struct nand_oobfree { | |||
144 | }; | 145 | }; |
145 | 146 | ||
146 | #define MTD_MAX_OOBFREE_ENTRIES 8 | 147 | #define MTD_MAX_OOBFREE_ENTRIES 8 |
148 | #define MTD_MAX_ECCPOS_ENTRIES 64 | ||
147 | /* | 149 | /* |
148 | * ECC layout control structure. Exported to userspace for | 150 | * OBSOLETE: ECC layout control structure. Exported to user-space via ioctl |
149 | * diagnosis and to allow creation of raw images | 151 | * ECCGETLAYOUT for backwards compatbility and should not be mistaken as a |
152 | * complete set of ECC information. The ioctl truncates the larger internal | ||
153 | * structure to retain binary compatibility with the static declaration of the | ||
154 | * ioctl. Note that the "MTD_MAX_..._ENTRIES" macros represent the max size of | ||
155 | * the user struct, not the MAX size of the internal struct nand_ecclayout. | ||
150 | */ | 156 | */ |
151 | struct nand_ecclayout { | 157 | struct nand_ecclayout_user { |
152 | __u32 eccbytes; | 158 | __u32 eccbytes; |
153 | __u32 eccpos[64]; | 159 | __u32 eccpos[MTD_MAX_ECCPOS_ENTRIES]; |
154 | __u32 oobavail; | 160 | __u32 oobavail; |
155 | struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES]; | 161 | struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES]; |
156 | }; | 162 | }; |
diff --git a/include/mtd/mtd-user.h b/include/mtd/mtd-user.h index aa3c2f86a913..83327c808c86 100644 --- a/include/mtd/mtd-user.h +++ b/include/mtd/mtd-user.h | |||
@@ -29,6 +29,6 @@ typedef struct mtd_info_user mtd_info_t; | |||
29 | typedef struct erase_info_user erase_info_t; | 29 | typedef struct erase_info_user erase_info_t; |
30 | typedef struct region_info_user region_info_t; | 30 | typedef struct region_info_user region_info_t; |
31 | typedef struct nand_oobinfo nand_oobinfo_t; | 31 | typedef struct nand_oobinfo nand_oobinfo_t; |
32 | typedef struct nand_ecclayout nand_ecclayout_t; | 32 | typedef struct nand_ecclayout_user nand_ecclayout_t; |
33 | 33 | ||
34 | #endif /* __MTD_USER_H__ */ | 34 | #endif /* __MTD_USER_H__ */ |
diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h index 55d700e8566e..daabae5817c6 100644 --- a/include/video/sh_mobile_lcdc.h +++ b/include/video/sh_mobile_lcdc.h | |||
@@ -49,7 +49,9 @@ struct sh_mobile_lcdc_sys_bus_ops { | |||
49 | unsigned long (*read_data)(void *handle); | 49 | unsigned long (*read_data)(void *handle); |
50 | }; | 50 | }; |
51 | 51 | ||
52 | struct module; | ||
52 | struct sh_mobile_lcdc_board_cfg { | 53 | struct sh_mobile_lcdc_board_cfg { |
54 | struct module *owner; | ||
53 | void *board_data; | 55 | void *board_data; |
54 | int (*setup_sys)(void *board_data, void *sys_ops_handle, | 56 | int (*setup_sys)(void *board_data, void *sys_ops_handle, |
55 | struct sh_mobile_lcdc_sys_bus_ops *sys_ops); | 57 | struct sh_mobile_lcdc_sys_bus_ops *sys_ops); |
@@ -70,7 +72,8 @@ struct sh_mobile_lcdc_chan_cfg { | |||
70 | int interface_type; /* selects RGBn or SYSn I/F, see above */ | 72 | int interface_type; /* selects RGBn or SYSn I/F, see above */ |
71 | int clock_divider; | 73 | int clock_divider; |
72 | unsigned long flags; /* LCDC_FLAGS_... */ | 74 | unsigned long flags; /* LCDC_FLAGS_... */ |
73 | struct fb_videomode lcd_cfg; | 75 | const struct fb_videomode *lcd_cfg; |
76 | int num_cfg; | ||
74 | struct sh_mobile_lcdc_lcd_size_cfg lcd_size_cfg; | 77 | struct sh_mobile_lcdc_lcd_size_cfg lcd_size_cfg; |
75 | struct sh_mobile_lcdc_board_cfg board_cfg; | 78 | struct sh_mobile_lcdc_board_cfg board_cfg; |
76 | struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */ | 79 | struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */ |
@@ -479,6 +479,7 @@ static inline unsigned long copy_shmid_to_user(void __user *buf, struct shmid64_ | |||
479 | { | 479 | { |
480 | struct shmid_ds out; | 480 | struct shmid_ds out; |
481 | 481 | ||
482 | memset(&out, 0, sizeof(out)); | ||
482 | ipc64_perm_to_ipc_perm(&in->shm_perm, &out.shm_perm); | 483 | ipc64_perm_to_ipc_perm(&in->shm_perm, &out.shm_perm); |
483 | out.shm_segsz = in->shm_segsz; | 484 | out.shm_segsz = in->shm_segsz; |
484 | out.shm_atime = in->shm_atime; | 485 | out.shm_atime = in->shm_atime; |