diff options
30 files changed, 793 insertions, 74 deletions
diff --git a/arch/arm/mach-s3c2410/include/mach/gpio.h b/arch/arm/mach-s3c2410/include/mach/gpio.h index 3b52b86498a6..e0349af8a483 100644 --- a/arch/arm/mach-s3c2410/include/mach/gpio.h +++ b/arch/arm/mach-s3c2410/include/mach/gpio.h | |||
@@ -15,4 +15,10 @@ | |||
15 | #define gpio_set_value __gpio_set_value | 15 | #define gpio_set_value __gpio_set_value |
16 | #define gpio_cansleep __gpio_cansleep | 16 | #define gpio_cansleep __gpio_cansleep |
17 | 17 | ||
18 | /* some boards require extra gpio capacity to support external | ||
19 | * devices that need GPIO. | ||
20 | */ | ||
21 | |||
22 | #define ARCH_NR_GPIOS (256 + CONFIG_S3C24XX_GPIO_EXTRA) | ||
23 | |||
18 | #include <asm-generic/gpio.h> | 24 | #include <asm-generic/gpio.h> |
diff --git a/arch/arm/mach-s3c2412/clock.c b/arch/arm/mach-s3c2412/clock.c index 3ce15e082e77..a037df5e1c2d 100644 --- a/arch/arm/mach-s3c2412/clock.c +++ b/arch/arm/mach-s3c2412/clock.c | |||
@@ -767,5 +767,6 @@ int __init s3c2412_baseclk_add(void) | |||
767 | s3c2412_clkcon_enable(clkp, 0); | 767 | s3c2412_clkcon_enable(clkp, 0); |
768 | } | 768 | } |
769 | 769 | ||
770 | s3c_pwmclk_init(); | ||
770 | return 0; | 771 | return 0; |
771 | } | 772 | } |
diff --git a/arch/arm/mach-s3c2412/mach-jive.c b/arch/arm/mach-s3c2412/mach-jive.c index e08a0f06224e..2cd4044797cf 100644 --- a/arch/arm/mach-s3c2412/mach-jive.c +++ b/arch/arm/mach-s3c2412/mach-jive.c | |||
@@ -399,11 +399,12 @@ static struct s3c2410_spigpio_info jive_lcd_spi = { | |||
399 | .bus_num = 1, | 399 | .bus_num = 1, |
400 | .pin_clk = S3C2410_GPG8, | 400 | .pin_clk = S3C2410_GPG8, |
401 | .pin_mosi = S3C2410_GPB8, | 401 | .pin_mosi = S3C2410_GPB8, |
402 | .num_chipselect = 1, | ||
402 | .chip_select = jive_lcd_spi_chipselect, | 403 | .chip_select = jive_lcd_spi_chipselect, |
403 | }; | 404 | }; |
404 | 405 | ||
405 | static struct platform_device jive_device_lcdspi = { | 406 | static struct platform_device jive_device_lcdspi = { |
406 | .name = "s3c24xx-spi-gpio", | 407 | .name = "spi_s3c24xx_gpio", |
407 | .id = 1, | 408 | .id = 1, |
408 | .num_resources = 0, | 409 | .num_resources = 0, |
409 | .dev.platform_data = &jive_lcd_spi, | 410 | .dev.platform_data = &jive_lcd_spi, |
@@ -420,11 +421,12 @@ static struct s3c2410_spigpio_info jive_wm8750_spi = { | |||
420 | .bus_num = 2, | 421 | .bus_num = 2, |
421 | .pin_clk = S3C2410_GPB4, | 422 | .pin_clk = S3C2410_GPB4, |
422 | .pin_mosi = S3C2410_GPB9, | 423 | .pin_mosi = S3C2410_GPB9, |
424 | .num_chipselect = 1, | ||
423 | .chip_select = jive_wm8750_chipselect, | 425 | .chip_select = jive_wm8750_chipselect, |
424 | }; | 426 | }; |
425 | 427 | ||
426 | static struct platform_device jive_device_wm8750 = { | 428 | static struct platform_device jive_device_wm8750 = { |
427 | .name = "s3c24xx-spi-gpio", | 429 | .name = "spi_s3c24xx_gpio", |
428 | .id = 2, | 430 | .id = 2, |
429 | .num_resources = 0, | 431 | .num_resources = 0, |
430 | .dev.platform_data = &jive_wm8750_spi, | 432 | .dev.platform_data = &jive_wm8750_spi, |
diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig index 57b9c57ff2b4..cde5ae9a4340 100644 --- a/arch/arm/mach-s3c2440/Kconfig +++ b/arch/arm/mach-s3c2440/Kconfig | |||
@@ -32,6 +32,7 @@ config MACH_ANUBIS | |||
32 | select S3C24XX_DCLK | 32 | select S3C24XX_DCLK |
33 | select PM_SIMTEC if PM | 33 | select PM_SIMTEC if PM |
34 | select HAVE_PATA_PLATFORM | 34 | select HAVE_PATA_PLATFORM |
35 | select S3C24XX_GPIO_EXTRA64 | ||
35 | help | 36 | help |
36 | Say Y here if you are using the Simtec Electronics ANUBIS | 37 | Say Y here if you are using the Simtec Electronics ANUBIS |
37 | development system | 38 | development system |
@@ -41,6 +42,7 @@ config MACH_OSIRIS | |||
41 | select CPU_S3C2440 | 42 | select CPU_S3C2440 |
42 | select S3C24XX_DCLK | 43 | select S3C24XX_DCLK |
43 | select PM_SIMTEC if PM | 44 | select PM_SIMTEC if PM |
45 | select S3C24XX_GPIO_EXTRA128 | ||
44 | help | 46 | help |
45 | Say Y here if you are using the Simtec IM2440D20 module, also | 47 | Say Y here if you are using the Simtec IM2440D20 module, also |
46 | known as the Osiris. | 48 | known as the Osiris. |
diff --git a/arch/arm/mach-s3c2440/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c index a9bbc41c4568..b05d56e230a1 100644 --- a/arch/arm/mach-s3c2440/mach-anubis.c +++ b/arch/arm/mach-s3c2440/mach-anubis.c | |||
@@ -367,6 +367,8 @@ static struct sm501_initdata anubis_sm501_initdata = { | |||
367 | .mask = 0, | 367 | .mask = 0, |
368 | }, | 368 | }, |
369 | 369 | ||
370 | .devices = SM501_USE_GPIO, | ||
371 | |||
370 | /* set the SDRAM and bus clocks */ | 372 | /* set the SDRAM and bus clocks */ |
371 | .mclk = 72 * MHZ, | 373 | .mclk = 72 * MHZ, |
372 | .m1xclk = 144 * MHZ, | 374 | .m1xclk = 144 * MHZ, |
@@ -374,10 +376,12 @@ static struct sm501_initdata anubis_sm501_initdata = { | |||
374 | 376 | ||
375 | static struct sm501_platdata_gpio_i2c anubis_sm501_gpio_i2c[] = { | 377 | static struct sm501_platdata_gpio_i2c anubis_sm501_gpio_i2c[] = { |
376 | [0] = { | 378 | [0] = { |
379 | .bus_num = 1, | ||
377 | .pin_scl = 44, | 380 | .pin_scl = 44, |
378 | .pin_sda = 45, | 381 | .pin_sda = 45, |
379 | }, | 382 | }, |
380 | [1] = { | 383 | [1] = { |
384 | .bus_num = 2, | ||
381 | .pin_scl = 40, | 385 | .pin_scl = 40, |
382 | .pin_sda = 41, | 386 | .pin_sda = 41, |
383 | }, | 387 | }, |
@@ -385,6 +389,7 @@ static struct sm501_platdata_gpio_i2c anubis_sm501_gpio_i2c[] = { | |||
385 | 389 | ||
386 | static struct sm501_platdata anubis_sm501_platdata = { | 390 | static struct sm501_platdata anubis_sm501_platdata = { |
387 | .init = &anubis_sm501_initdata, | 391 | .init = &anubis_sm501_initdata, |
392 | .gpio_base = -1, | ||
388 | .gpio_i2c = anubis_sm501_gpio_i2c, | 393 | .gpio_i2c = anubis_sm501_gpio_i2c, |
389 | .gpio_i2c_nr = ARRAY_SIZE(anubis_sm501_gpio_i2c), | 394 | .gpio_i2c_nr = ARRAY_SIZE(anubis_sm501_gpio_i2c), |
390 | }; | 395 | }; |
diff --git a/arch/arm/mach-s3c2440/mach-at2440evb.c b/arch/arm/mach-s3c2440/mach-at2440evb.c index 55e07ae5ab8c..0a6d0a5d961b 100644 --- a/arch/arm/mach-s3c2440/mach-at2440evb.c +++ b/arch/arm/mach-s3c2440/mach-at2440evb.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <asm/mach/irq.h> | 28 | #include <asm/mach/irq.h> |
29 | 29 | ||
30 | #include <mach/hardware.h> | 30 | #include <mach/hardware.h> |
31 | #include <mach/fb.h> | ||
31 | #include <asm/irq.h> | 32 | #include <asm/irq.h> |
32 | #include <asm/mach-types.h> | 33 | #include <asm/mach-types.h> |
33 | 34 | ||
@@ -46,6 +47,7 @@ | |||
46 | #include <plat/clock.h> | 47 | #include <plat/clock.h> |
47 | #include <plat/devs.h> | 48 | #include <plat/devs.h> |
48 | #include <plat/cpu.h> | 49 | #include <plat/cpu.h> |
50 | #include <asm/plat-s3c24xx/mci.h> | ||
49 | 51 | ||
50 | static struct map_desc at2440evb_iodesc[] __initdata = { | 52 | static struct map_desc at2440evb_iodesc[] __initdata = { |
51 | /* Nothing here */ | 53 | /* Nothing here */ |
@@ -163,6 +165,43 @@ static struct platform_device at2440evb_device_eth = { | |||
163 | }, | 165 | }, |
164 | }; | 166 | }; |
165 | 167 | ||
168 | static struct s3c24xx_mci_pdata at2440evb_mci_pdata = { | ||
169 | .gpio_detect = S3C2410_GPG10, | ||
170 | }; | ||
171 | |||
172 | /* 7" LCD panel */ | ||
173 | |||
174 | static struct s3c2410fb_display at2440evb_lcd_cfg __initdata = { | ||
175 | |||
176 | .lcdcon5 = S3C2410_LCDCON5_FRM565 | | ||
177 | S3C2410_LCDCON5_INVVLINE | | ||
178 | S3C2410_LCDCON5_INVVFRAME | | ||
179 | S3C2410_LCDCON5_PWREN | | ||
180 | S3C2410_LCDCON5_HWSWP, | ||
181 | |||
182 | .type = S3C2410_LCDCON1_TFT, | ||
183 | |||
184 | .width = 800, | ||
185 | .height = 480, | ||
186 | |||
187 | .pixclock = 33333, /* HCLK 60 MHz, divisor 2 */ | ||
188 | .xres = 800, | ||
189 | .yres = 480, | ||
190 | .bpp = 16, | ||
191 | .left_margin = 88, | ||
192 | .right_margin = 40, | ||
193 | .hsync_len = 128, | ||
194 | .upper_margin = 32, | ||
195 | .lower_margin = 11, | ||
196 | .vsync_len = 2, | ||
197 | }; | ||
198 | |||
199 | static struct s3c2410fb_mach_info at2440evb_fb_info __initdata = { | ||
200 | .displays = &at2440evb_lcd_cfg, | ||
201 | .num_displays = 1, | ||
202 | .default_display = 0, | ||
203 | }; | ||
204 | |||
166 | static struct platform_device *at2440evb_devices[] __initdata = { | 205 | static struct platform_device *at2440evb_devices[] __initdata = { |
167 | &s3c_device_usb, | 206 | &s3c_device_usb, |
168 | &s3c_device_wdt, | 207 | &s3c_device_wdt, |
@@ -170,12 +209,16 @@ static struct platform_device *at2440evb_devices[] __initdata = { | |||
170 | &s3c_device_i2c0, | 209 | &s3c_device_i2c0, |
171 | &s3c_device_rtc, | 210 | &s3c_device_rtc, |
172 | &s3c_device_nand, | 211 | &s3c_device_nand, |
212 | &s3c_device_sdi, | ||
213 | &s3c_device_lcd, | ||
173 | &at2440evb_device_eth, | 214 | &at2440evb_device_eth, |
174 | }; | 215 | }; |
175 | 216 | ||
176 | static void __init at2440evb_map_io(void) | 217 | static void __init at2440evb_map_io(void) |
177 | { | 218 | { |
178 | s3c_device_nand.dev.platform_data = &at2440evb_nand_info; | 219 | s3c_device_nand.dev.platform_data = &at2440evb_nand_info; |
220 | s3c_device_sdi.name = "s3c2440-sdi"; | ||
221 | s3c_device_sdi.dev.platform_data = &at2440evb_mci_pdata; | ||
179 | 222 | ||
180 | s3c24xx_init_io(at2440evb_iodesc, ARRAY_SIZE(at2440evb_iodesc)); | 223 | s3c24xx_init_io(at2440evb_iodesc, ARRAY_SIZE(at2440evb_iodesc)); |
181 | s3c24xx_init_clocks(16934400); | 224 | s3c24xx_init_clocks(16934400); |
@@ -184,7 +227,9 @@ static void __init at2440evb_map_io(void) | |||
184 | 227 | ||
185 | static void __init at2440evb_init(void) | 228 | static void __init at2440evb_init(void) |
186 | { | 229 | { |
230 | s3c24xx_fb_set_platdata(&at2440evb_fb_info); | ||
187 | s3c_i2c0_set_platdata(NULL); | 231 | s3c_i2c0_set_platdata(NULL); |
232 | |||
188 | platform_add_devices(at2440evb_devices, ARRAY_SIZE(at2440evb_devices)); | 233 | platform_add_devices(at2440evb_devices, ARRAY_SIZE(at2440evb_devices)); |
189 | } | 234 | } |
190 | 235 | ||
diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c index 363f39608783..fdd4ec335a77 100644 --- a/arch/arm/mach-s3c2443/clock.c +++ b/arch/arm/mach-s3c2443/clock.c | |||
@@ -1107,4 +1107,6 @@ void __init s3c2443_init_clocks(int xtal) | |||
1107 | 1107 | ||
1108 | (clkp->enable)(clkp, 0); | 1108 | (clkp->enable)(clkp, 0); |
1109 | } | 1109 | } |
1110 | |||
1111 | s3c_pwmclk_init(); | ||
1110 | } | 1112 | } |
diff --git a/arch/arm/mach-s3c6400/include/mach/pwm-clock.h b/arch/arm/mach-s3c6400/include/mach/pwm-clock.h new file mode 100644 index 000000000000..b25bedee0d52 --- /dev/null +++ b/arch/arm/mach-s3c6400/include/mach/pwm-clock.h | |||
@@ -0,0 +1,56 @@ | |||
1 | /* linux/arch/arm/mach-s3c6400/include/mach/pwm-clock.h | ||
2 | * | ||
3 | * Copyright 2008 Openmoko, Inc. | ||
4 | * Copyright 2008 Simtec Electronics | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * http://armlinux.simtec.co.uk/ | ||
7 | * | ||
8 | * S3C64xx - pwm clock and timer support | ||
9 | */ | ||
10 | |||
11 | /** | ||
12 | * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk | ||
13 | * @tcfg: The timer TCFG1 register bits shifted down to 0. | ||
14 | * | ||
15 | * Return true if the given configuration from TCFG1 is a TCLK instead | ||
16 | * any of the TDIV clocks. | ||
17 | */ | ||
18 | static inline int pwm_cfg_src_is_tclk(unsigned long tcfg) | ||
19 | { | ||
20 | return tcfg >= S3C64XX_TCFG1_MUX_TCLK; | ||
21 | } | ||
22 | |||
23 | /** | ||
24 | * tcfg_to_divisor() - convert tcfg1 setting to a divisor | ||
25 | * @tcfg1: The tcfg1 setting, shifted down. | ||
26 | * | ||
27 | * Get the divisor value for the given tcfg1 setting. We assume the | ||
28 | * caller has already checked to see if this is not a TCLK source. | ||
29 | */ | ||
30 | static inline unsigned long tcfg_to_divisor(unsigned long tcfg1) | ||
31 | { | ||
32 | return 1 << tcfg1; | ||
33 | } | ||
34 | |||
35 | /** | ||
36 | * pwm_tdiv_has_div1() - does the tdiv setting have a /1 | ||
37 | * | ||
38 | * Return true if we have a /1 in the tdiv setting. | ||
39 | */ | ||
40 | static inline unsigned int pwm_tdiv_has_div1(void) | ||
41 | { | ||
42 | return 1; | ||
43 | } | ||
44 | |||
45 | /** | ||
46 | * pwm_tdiv_div_bits() - calculate TCFG1 divisor value. | ||
47 | * @div: The divisor to calculate the bit information for. | ||
48 | * | ||
49 | * Turn a divisor into the necessary bit field for TCFG1. | ||
50 | */ | ||
51 | static inline unsigned long pwm_tdiv_div_bits(unsigned int div) | ||
52 | { | ||
53 | return ilog2(div); | ||
54 | } | ||
55 | |||
56 | #define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK | ||
diff --git a/arch/arm/mach-s3c6400/include/mach/uncompress.h b/arch/arm/mach-s3c6400/include/mach/uncompress.h index cc822c57cc1c..c6a82a20bf2a 100644 --- a/arch/arm/mach-s3c6400/include/mach/uncompress.h +++ b/arch/arm/mach-s3c6400/include/mach/uncompress.h | |||
@@ -21,6 +21,8 @@ | |||
21 | static void arch_detect_cpu(void) | 21 | static void arch_detect_cpu(void) |
22 | { | 22 | { |
23 | /* we do not need to do any cpu detection here at the moment. */ | 23 | /* we do not need to do any cpu detection here at the moment. */ |
24 | fifo_mask = S3C2440_UFSTAT_TXMASK; | ||
25 | fifo_max = 63 << S3C2440_UFSTAT_TXSHIFT; | ||
24 | } | 26 | } |
25 | 27 | ||
26 | #endif /* __ASM_ARCH_UNCOMPRESS_H */ | 28 | #endif /* __ASM_ARCH_UNCOMPRESS_H */ |
diff --git a/arch/arm/mach-s3c6410/mach-smdk6410.c b/arch/arm/mach-s3c6410/mach-smdk6410.c index ae3bd5c2b8c6..3c4d47145c83 100644 --- a/arch/arm/mach-s3c6410/mach-smdk6410.c +++ b/arch/arm/mach-s3c6410/mach-smdk6410.c | |||
@@ -153,8 +153,6 @@ static struct i2c_board_info i2c_devs1[] __initdata = { | |||
153 | { I2C_BOARD_INFO("24c128", 0x57), }, /* Samsung S524AD0XD1 */ | 153 | { I2C_BOARD_INFO("24c128", 0x57), }, /* Samsung S524AD0XD1 */ |
154 | }; | 154 | }; |
155 | 155 | ||
156 | extern void s3c64xx_init_io(struct map_desc *, int); | ||
157 | |||
158 | static void __init smdk6410_map_io(void) | 156 | static void __init smdk6410_map_io(void) |
159 | { | 157 | { |
160 | s3c64xx_init_io(smdk6410_iodesc, ARRAY_SIZE(smdk6410_iodesc)); | 158 | s3c64xx_init_io(smdk6410_iodesc, ARRAY_SIZE(smdk6410_iodesc)); |
diff --git a/arch/arm/plat-s3c/Kconfig b/arch/arm/plat-s3c/Kconfig index e80a32822d88..def0bb457ca3 100644 --- a/arch/arm/plat-s3c/Kconfig +++ b/arch/arm/plat-s3c/Kconfig | |||
@@ -57,6 +57,14 @@ config S3C_BOOT_ERROR_RESET | |||
57 | Say y here to use the watchdog to reset the system if the | 57 | Say y here to use the watchdog to reset the system if the |
58 | kernel decompressor detects an error during decompression. | 58 | kernel decompressor detects an error during decompression. |
59 | 59 | ||
60 | config S3C_BOOT_UART_FORCE_FIFO | ||
61 | bool "Force UART FIFO on during boot process" | ||
62 | depends on PLAT_S3C | ||
63 | default y | ||
64 | help | ||
65 | Say Y here to force the UART FIFOs on during the kernel | ||
66 | uncompressor | ||
67 | |||
60 | comment "Power management" | 68 | comment "Power management" |
61 | 69 | ||
62 | config S3C2410_PM_DEBUG | 70 | config S3C2410_PM_DEBUG |
diff --git a/arch/arm/plat-s3c/include/plat/adc.h b/arch/arm/plat-s3c/include/plat/adc.h new file mode 100644 index 000000000000..43df2a404b0b --- /dev/null +++ b/arch/arm/plat-s3c/include/plat/adc.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* arch/arm/plat-s3c/include/plat/adc.h | ||
2 | * | ||
3 | * Copyright (c) 2008 Simtec Electronics | ||
4 | * http://armlinux.simnte.co.uk/ | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * | ||
7 | * S3C24XX ADC driver information | ||
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 | #ifndef __ASM_PLAT_ADC_H | ||
15 | #define __ASM_PLAT_ADC_H __FILE__ | ||
16 | |||
17 | struct s3c_adc_client; | ||
18 | |||
19 | extern int s3c_adc_start(struct s3c_adc_client *client, | ||
20 | unsigned int channel, unsigned int nr_samples); | ||
21 | |||
22 | extern struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev, | ||
23 | void (*select)(unsigned selected), | ||
24 | void (*conv)(unsigned d0, unsigned d1), | ||
25 | unsigned int is_ts); | ||
26 | |||
27 | extern void s3c_adc_release(struct s3c_adc_client *client); | ||
28 | |||
29 | #endif /* __ASM_PLAT_ADC_H */ | ||
diff --git a/arch/arm/plat-s3c/include/plat/clock.h b/arch/arm/plat-s3c/include/plat/clock.h index ea1f3ffa9717..a10622eed43a 100644 --- a/arch/arm/plat-s3c/include/plat/clock.h +++ b/arch/arm/plat-s3c/include/plat/clock.h | |||
@@ -81,3 +81,8 @@ extern void s3c2443_setup_clocks(void); | |||
81 | /* S3C64XX specific functions and clocks */ | 81 | /* S3C64XX specific functions and clocks */ |
82 | 82 | ||
83 | extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable); | 83 | extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable); |
84 | |||
85 | /* Init for pwm clock code */ | ||
86 | |||
87 | extern void s3c_pwmclk_init(void); | ||
88 | |||
diff --git a/arch/arm/plat-s3c/include/plat/cpu.h b/arch/arm/plat-s3c/include/plat/cpu.h index 6d89a4637f30..e62ae0fcfe56 100644 --- a/arch/arm/plat-s3c/include/plat/cpu.h +++ b/arch/arm/plat-s3c/include/plat/cpu.h | |||
@@ -47,6 +47,7 @@ extern void s3c24xx_init_irq(void); | |||
47 | extern void s3c64xx_init_irq(u32 vic0, u32 vic1); | 47 | extern void s3c64xx_init_irq(u32 vic0, u32 vic1); |
48 | 48 | ||
49 | extern void s3c24xx_init_io(struct map_desc *mach_desc, int size); | 49 | extern void s3c24xx_init_io(struct map_desc *mach_desc, int size); |
50 | extern void s3c64xx_init_io(struct map_desc *mach_desc, int size); | ||
50 | 51 | ||
51 | extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no); | 52 | extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no); |
52 | 53 | ||
diff --git a/arch/arm/plat-s3c/include/plat/regs-timer.h b/arch/arm/plat-s3c/include/plat/regs-timer.h index 086ce2685836..d097d92f8cc7 100644 --- a/arch/arm/plat-s3c/include/plat/regs-timer.h +++ b/arch/arm/plat-s3c/include/plat/regs-timer.h | |||
@@ -73,6 +73,14 @@ | |||
73 | #define S3C2410_TCFG1_MUX_TCLK (4<<0) | 73 | #define S3C2410_TCFG1_MUX_TCLK (4<<0) |
74 | #define S3C2410_TCFG1_MUX_MASK (15<<0) | 74 | #define S3C2410_TCFG1_MUX_MASK (15<<0) |
75 | 75 | ||
76 | #define S3C64XX_TCFG1_MUX_DIV1 (0<<0) | ||
77 | #define S3C64XX_TCFG1_MUX_DIV2 (1<<0) | ||
78 | #define S3C64XX_TCFG1_MUX_DIV4 (2<<0) | ||
79 | #define S3C64XX_TCFG1_MUX_DIV8 (3<<0) | ||
80 | #define S3C64XX_TCFG1_MUX_DIV16 (4<<0) | ||
81 | #define S3C64XX_TCFG1_MUX_TCLK (5<<0) /* 3 sets of TCLK */ | ||
82 | #define S3C64XX_TCFG1_MUX_MASK (15<<0) | ||
83 | |||
76 | #define S3C2410_TCFG1_SHIFT(x) ((x) * 4) | 84 | #define S3C2410_TCFG1_SHIFT(x) ((x) * 4) |
77 | 85 | ||
78 | /* for each timer, we have an count buffer, an compare buffer and | 86 | /* for each timer, we have an count buffer, an compare buffer and |
diff --git a/arch/arm/plat-s3c/include/plat/uncompress.h b/arch/arm/plat-s3c/include/plat/uncompress.h index eeef32c4312d..6061de87f225 100644 --- a/arch/arm/plat-s3c/include/plat/uncompress.h +++ b/arch/arm/plat-s3c/include/plat/uncompress.h | |||
@@ -139,6 +139,28 @@ static void arch_decomp_error(const char *x) | |||
139 | 139 | ||
140 | static void error(char *err); | 140 | static void error(char *err); |
141 | 141 | ||
142 | #ifdef CONFIG_S3C_BOOT_UART_FORCE_FIFO | ||
143 | static inline void arch_enable_uart_fifo(void) | ||
144 | { | ||
145 | u32 fifocon = uart_rd(S3C2410_UFCON); | ||
146 | |||
147 | if (!(fifocon & S3C2410_UFCON_FIFOMODE)) { | ||
148 | fifocon |= S3C2410_UFCON_RESETBOTH; | ||
149 | uart_wr(S3C2410_UFCON, fifocon); | ||
150 | |||
151 | /* wait for fifo reset to complete */ | ||
152 | while (1) { | ||
153 | fifocon = uart_rd(S3C2410_UFCON); | ||
154 | if (!(fifocon & S3C2410_UFCON_RESETBOTH)) | ||
155 | break; | ||
156 | } | ||
157 | } | ||
158 | } | ||
159 | #else | ||
160 | #define arch_enable_uart_fifo() do { } while(0) | ||
161 | #endif | ||
162 | |||
163 | |||
142 | static void | 164 | static void |
143 | arch_decomp_setup(void) | 165 | arch_decomp_setup(void) |
144 | { | 166 | { |
@@ -149,6 +171,12 @@ arch_decomp_setup(void) | |||
149 | 171 | ||
150 | arch_detect_cpu(); | 172 | arch_detect_cpu(); |
151 | arch_decomp_wdog_start(); | 173 | arch_decomp_wdog_start(); |
174 | |||
175 | /* Enable the UART FIFOs if they where not enabled and our | ||
176 | * configuration says we should turn them on. | ||
177 | */ | ||
178 | |||
179 | arch_enable_uart_fifo(); | ||
152 | } | 180 | } |
153 | 181 | ||
154 | 182 | ||
diff --git a/arch/arm/plat-s3c/pwm-clock.c b/arch/arm/plat-s3c/pwm-clock.c index 5242fb0afcca..a318215ab535 100644 --- a/arch/arm/plat-s3c/pwm-clock.c +++ b/arch/arm/plat-s3c/pwm-clock.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/list.h> | 15 | #include <linux/list.h> |
16 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
17 | #include <linux/log2.h> | ||
17 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
18 | #include <linux/err.h> | 19 | #include <linux/err.h> |
19 | #include <linux/io.h> | 20 | #include <linux/io.h> |
@@ -26,6 +27,7 @@ | |||
26 | #include <plat/cpu.h> | 27 | #include <plat/cpu.h> |
27 | 28 | ||
28 | #include <plat/regs-timer.h> | 29 | #include <plat/regs-timer.h> |
30 | #include <mach/pwm-clock.h> | ||
29 | 31 | ||
30 | /* Each of the timers 0 through 5 go through the following | 32 | /* Each of the timers 0 through 5 go through the following |
31 | * clock tree, with the inputs depending on the timers. | 33 | * clock tree, with the inputs depending on the timers. |
@@ -166,11 +168,6 @@ static inline struct pwm_tdiv_clk *to_tdiv(struct clk *clk) | |||
166 | return container_of(clk, struct pwm_tdiv_clk, clk); | 168 | return container_of(clk, struct pwm_tdiv_clk, clk); |
167 | } | 169 | } |
168 | 170 | ||
169 | static inline unsigned long tcfg_to_divisor(unsigned long tcfg1) | ||
170 | { | ||
171 | return 1 << (1 + tcfg1); | ||
172 | } | ||
173 | |||
174 | static unsigned long clk_pwm_tdiv_get_rate(struct clk *clk) | 171 | static unsigned long clk_pwm_tdiv_get_rate(struct clk *clk) |
175 | { | 172 | { |
176 | unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1); | 173 | unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1); |
@@ -179,7 +176,7 @@ static unsigned long clk_pwm_tdiv_get_rate(struct clk *clk) | |||
179 | tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id); | 176 | tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id); |
180 | tcfg1 &= S3C2410_TCFG1_MUX_MASK; | 177 | tcfg1 &= S3C2410_TCFG1_MUX_MASK; |
181 | 178 | ||
182 | if (tcfg1 == S3C2410_TCFG1_MUX_TCLK) | 179 | if (pwm_cfg_src_is_tclk(tcfg1)) |
183 | divisor = to_tdiv(clk)->divisor; | 180 | divisor = to_tdiv(clk)->divisor; |
184 | else | 181 | else |
185 | divisor = tcfg_to_divisor(tcfg1); | 182 | divisor = tcfg_to_divisor(tcfg1); |
@@ -196,7 +193,9 @@ static unsigned long clk_pwm_tdiv_round_rate(struct clk *clk, | |||
196 | parent_rate = clk_get_rate(clk->parent); | 193 | parent_rate = clk_get_rate(clk->parent); |
197 | divisor = parent_rate / rate; | 194 | divisor = parent_rate / rate; |
198 | 195 | ||
199 | if (divisor <= 2) | 196 | if (divisor <= 1 && pwm_tdiv_has_div1()) |
197 | divisor = 1; | ||
198 | else if (divisor <= 2) | ||
200 | divisor = 2; | 199 | divisor = 2; |
201 | else if (divisor <= 4) | 200 | else if (divisor <= 4) |
202 | divisor = 4; | 201 | divisor = 4; |
@@ -210,25 +209,7 @@ static unsigned long clk_pwm_tdiv_round_rate(struct clk *clk, | |||
210 | 209 | ||
211 | static unsigned long clk_pwm_tdiv_bits(struct pwm_tdiv_clk *divclk) | 210 | static unsigned long clk_pwm_tdiv_bits(struct pwm_tdiv_clk *divclk) |
212 | { | 211 | { |
213 | unsigned long bits; | 212 | return pwm_tdiv_div_bits(divclk->divisor); |
214 | |||
215 | switch (divclk->divisor) { | ||
216 | case 2: | ||
217 | bits = S3C2410_TCFG1_MUX_DIV2; | ||
218 | break; | ||
219 | case 4: | ||
220 | bits = S3C2410_TCFG1_MUX_DIV4; | ||
221 | break; | ||
222 | case 8: | ||
223 | bits = S3C2410_TCFG1_MUX_DIV8; | ||
224 | break; | ||
225 | case 16: | ||
226 | default: | ||
227 | bits = S3C2410_TCFG1_MUX_DIV16; | ||
228 | break; | ||
229 | } | ||
230 | |||
231 | return bits; | ||
232 | } | 213 | } |
233 | 214 | ||
234 | static void clk_pwm_tdiv_update(struct pwm_tdiv_clk *divclk) | 215 | static void clk_pwm_tdiv_update(struct pwm_tdiv_clk *divclk) |
@@ -269,7 +250,7 @@ static int clk_pwm_tdiv_set_rate(struct clk *clk, unsigned long rate) | |||
269 | /* Update the current MUX settings if we are currently | 250 | /* Update the current MUX settings if we are currently |
270 | * selected as the clock source for this clock. */ | 251 | * selected as the clock source for this clock. */ |
271 | 252 | ||
272 | if (tcfg1 != S3C2410_TCFG1_MUX_TCLK) | 253 | if (!pwm_cfg_src_is_tclk(tcfg1)) |
273 | clk_pwm_tdiv_update(divclk); | 254 | clk_pwm_tdiv_update(divclk); |
274 | 255 | ||
275 | return 0; | 256 | return 0; |
@@ -356,7 +337,7 @@ static int clk_pwm_tin_set_parent(struct clk *clk, struct clk *parent) | |||
356 | unsigned long shift = S3C2410_TCFG1_SHIFT(id); | 337 | unsigned long shift = S3C2410_TCFG1_SHIFT(id); |
357 | 338 | ||
358 | if (parent == s3c24xx_pwmclk_tclk(id)) | 339 | if (parent == s3c24xx_pwmclk_tclk(id)) |
359 | bits = S3C2410_TCFG1_MUX_TCLK << shift; | 340 | bits = S3C_TCFG1_MUX_TCLK << shift; |
360 | else if (parent == s3c24xx_pwmclk_tdiv(id)) | 341 | else if (parent == s3c24xx_pwmclk_tdiv(id)) |
361 | bits = clk_pwm_tdiv_bits(to_tdiv(parent)) << shift; | 342 | bits = clk_pwm_tdiv_bits(to_tdiv(parent)) << shift; |
362 | else | 343 | else |
@@ -418,7 +399,7 @@ static __init int clk_pwm_tin_register(struct clk *pwm) | |||
418 | tcfg1 >>= S3C2410_TCFG1_SHIFT(id); | 399 | tcfg1 >>= S3C2410_TCFG1_SHIFT(id); |
419 | tcfg1 &= S3C2410_TCFG1_MUX_MASK; | 400 | tcfg1 &= S3C2410_TCFG1_MUX_MASK; |
420 | 401 | ||
421 | if (tcfg1 == S3C2410_TCFG1_MUX_TCLK) | 402 | if (pwm_cfg_src_is_tclk(tcfg1)) |
422 | parent = s3c24xx_pwmclk_tclk(id); | 403 | parent = s3c24xx_pwmclk_tclk(id); |
423 | else | 404 | else |
424 | parent = s3c24xx_pwmclk_tdiv(id); | 405 | parent = s3c24xx_pwmclk_tdiv(id); |
@@ -426,7 +407,16 @@ static __init int clk_pwm_tin_register(struct clk *pwm) | |||
426 | return clk_set_parent(pwm, parent); | 407 | return clk_set_parent(pwm, parent); |
427 | } | 408 | } |
428 | 409 | ||
429 | static __init int s3c24xx_pwmclk_init(void) | 410 | /** |
411 | * s3c_pwmclk_init() - initialise pwm clocks | ||
412 | * | ||
413 | * Initialise and register the clocks which provide the inputs for the | ||
414 | * pwm timer blocks. | ||
415 | * | ||
416 | * Note, this call is required by the time core, so must be called after | ||
417 | * the base clocks are added and before any of the initcalls are run. | ||
418 | */ | ||
419 | __init void s3c_pwmclk_init(void) | ||
430 | { | 420 | { |
431 | struct clk *clk_timers; | 421 | struct clk *clk_timers; |
432 | unsigned int clk; | 422 | unsigned int clk; |
@@ -435,7 +425,7 @@ static __init int s3c24xx_pwmclk_init(void) | |||
435 | clk_timers = clk_get(NULL, "timers"); | 425 | clk_timers = clk_get(NULL, "timers"); |
436 | if (IS_ERR(clk_timers)) { | 426 | if (IS_ERR(clk_timers)) { |
437 | printk(KERN_ERR "%s: no parent clock\n", __func__); | 427 | printk(KERN_ERR "%s: no parent clock\n", __func__); |
438 | return -EINVAL; | 428 | return; |
439 | } | 429 | } |
440 | 430 | ||
441 | for (clk = 0; clk < ARRAY_SIZE(clk_timer_scaler); clk++) { | 431 | for (clk = 0; clk < ARRAY_SIZE(clk_timer_scaler); clk++) { |
@@ -443,7 +433,7 @@ static __init int s3c24xx_pwmclk_init(void) | |||
443 | ret = s3c24xx_register_clock(&clk_timer_scaler[clk]); | 433 | ret = s3c24xx_register_clock(&clk_timer_scaler[clk]); |
444 | if (ret < 0) { | 434 | if (ret < 0) { |
445 | printk(KERN_ERR "error adding pwm scaler%d clock\n", clk); | 435 | printk(KERN_ERR "error adding pwm scaler%d clock\n", clk); |
446 | goto err; | 436 | return; |
447 | } | 437 | } |
448 | } | 438 | } |
449 | 439 | ||
@@ -451,7 +441,7 @@ static __init int s3c24xx_pwmclk_init(void) | |||
451 | ret = s3c24xx_register_clock(&clk_timer_tclk[clk]); | 441 | ret = s3c24xx_register_clock(&clk_timer_tclk[clk]); |
452 | if (ret < 0) { | 442 | if (ret < 0) { |
453 | printk(KERN_ERR "error adding pww tclk%d\n", clk); | 443 | printk(KERN_ERR "error adding pww tclk%d\n", clk); |
454 | goto err; | 444 | return; |
455 | } | 445 | } |
456 | } | 446 | } |
457 | 447 | ||
@@ -459,7 +449,7 @@ static __init int s3c24xx_pwmclk_init(void) | |||
459 | ret = clk_pwm_tdiv_register(clk); | 449 | ret = clk_pwm_tdiv_register(clk); |
460 | if (ret < 0) { | 450 | if (ret < 0) { |
461 | printk(KERN_ERR "error adding pwm%d tdiv clock\n", clk); | 451 | printk(KERN_ERR "error adding pwm%d tdiv clock\n", clk); |
462 | goto err; | 452 | return; |
463 | } | 453 | } |
464 | } | 454 | } |
465 | 455 | ||
@@ -467,14 +457,7 @@ static __init int s3c24xx_pwmclk_init(void) | |||
467 | ret = clk_pwm_tin_register(&clk_tin[clk]); | 457 | ret = clk_pwm_tin_register(&clk_tin[clk]); |
468 | if (ret < 0) { | 458 | if (ret < 0) { |
469 | printk(KERN_ERR "error adding pwm%d tin clock\n", clk); | 459 | printk(KERN_ERR "error adding pwm%d tin clock\n", clk); |
470 | goto err; | 460 | return; |
471 | } | 461 | } |
472 | } | 462 | } |
473 | |||
474 | return 0; | ||
475 | |||
476 | err: | ||
477 | return ret; | ||
478 | } | 463 | } |
479 | |||
480 | arch_initcall(s3c24xx_pwmclk_init); | ||
diff --git a/arch/arm/plat-s3c/time.c b/arch/arm/plat-s3c/time.c index a581ff7ba664..3b27b29da478 100644 --- a/arch/arm/plat-s3c/time.c +++ b/arch/arm/plat-s3c/time.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/err.h> | 26 | #include <linux/err.h> |
27 | #include <linux/clk.h> | 27 | #include <linux/clk.h> |
28 | #include <linux/io.h> | 28 | #include <linux/io.h> |
29 | #include <linux/platform_device.h> | ||
29 | 30 | ||
30 | #include <asm/system.h> | 31 | #include <asm/system.h> |
31 | #include <asm/leds.h> | 32 | #include <asm/leds.h> |
@@ -147,6 +148,10 @@ static struct irqaction s3c2410_timer_irq = { | |||
147 | machine_is_anubis() || \ | 148 | machine_is_anubis() || \ |
148 | machine_is_osiris()) | 149 | machine_is_osiris()) |
149 | 150 | ||
151 | static struct clk *tin; | ||
152 | static struct clk *tdiv; | ||
153 | static struct clk *timerclk; | ||
154 | |||
150 | /* | 155 | /* |
151 | * Set up timer interrupt, and return the current time in seconds. | 156 | * Set up timer interrupt, and return the current time in seconds. |
152 | * | 157 | * |
@@ -162,12 +167,6 @@ static void s3c2410_timer_setup (void) | |||
162 | 167 | ||
163 | tcnt = TICK_MAX; /* default value for tcnt */ | 168 | tcnt = TICK_MAX; /* default value for tcnt */ |
164 | 169 | ||
165 | /* read the current timer configuration bits */ | ||
166 | |||
167 | tcon = __raw_readl(S3C2410_TCON); | ||
168 | tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
169 | tcfg0 = __raw_readl(S3C2410_TCFG0); | ||
170 | |||
171 | /* configure the system for whichever machine is in use */ | 170 | /* configure the system for whichever machine is in use */ |
172 | 171 | ||
173 | if (use_tclk1_12()) { | 172 | if (use_tclk1_12()) { |
@@ -175,11 +174,13 @@ static void s3c2410_timer_setup (void) | |||
175 | timer_usec_ticks = timer_mask_usec_ticks(1, 12000000); | 174 | timer_usec_ticks = timer_mask_usec_ticks(1, 12000000); |
176 | tcnt = 12000000 / HZ; | 175 | tcnt = 12000000 / HZ; |
177 | 176 | ||
177 | tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
178 | tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK; | 178 | tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK; |
179 | tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1; | 179 | tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1; |
180 | __raw_writel(tcfg1, S3C2410_TCFG1); | ||
180 | } else { | 181 | } else { |
181 | unsigned long pclk; | 182 | unsigned long pclk; |
182 | struct clk *clk; | 183 | struct clk *tscaler; |
183 | 184 | ||
184 | /* for the h1940 (and others), we use the pclk from the core | 185 | /* for the h1940 (and others), we use the pclk from the core |
185 | * to generate the timer values. since values around 50 to | 186 | * to generate the timer values. since values around 50 to |
@@ -190,29 +191,25 @@ static void s3c2410_timer_setup (void) | |||
190 | * (8.45 ticks per usec) | 191 | * (8.45 ticks per usec) |
191 | */ | 192 | */ |
192 | 193 | ||
193 | /* this is used as default if no other timer can be found */ | 194 | pclk = clk_get_rate(timerclk); |
194 | |||
195 | clk = clk_get(NULL, "timers"); | ||
196 | if (IS_ERR(clk)) | ||
197 | panic("failed to get clock for system timer"); | ||
198 | |||
199 | clk_enable(clk); | ||
200 | |||
201 | pclk = clk_get_rate(clk); | ||
202 | 195 | ||
203 | /* configure clock tick */ | 196 | /* configure clock tick */ |
204 | 197 | ||
205 | timer_usec_ticks = timer_mask_usec_ticks(6, pclk); | 198 | timer_usec_ticks = timer_mask_usec_ticks(6, pclk); |
206 | 199 | ||
207 | tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK; | 200 | tscaler = clk_get_parent(tdiv); |
208 | tcfg1 |= S3C2410_TCFG1_MUX4_DIV2; | ||
209 | 201 | ||
210 | tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK; | 202 | clk_set_rate(tscaler, pclk / 3); |
211 | tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT; | 203 | clk_set_rate(tdiv, pclk / 6); |
204 | clk_set_parent(tin, tdiv); | ||
212 | 205 | ||
213 | tcnt = (pclk / 6) / HZ; | 206 | tcnt = clk_get_rate(tin) / HZ; |
214 | } | 207 | } |
215 | 208 | ||
209 | tcon = __raw_readl(S3C2410_TCON); | ||
210 | tcfg0 = __raw_readl(S3C2410_TCFG0); | ||
211 | tcfg1 = __raw_readl(S3C2410_TCFG1); | ||
212 | |||
216 | /* timers reload after counting zero, so reduce the count by 1 */ | 213 | /* timers reload after counting zero, so reduce the count by 1 */ |
217 | 214 | ||
218 | tcnt--; | 215 | tcnt--; |
@@ -248,8 +245,35 @@ static void s3c2410_timer_setup (void) | |||
248 | __raw_writel(tcon, S3C2410_TCON); | 245 | __raw_writel(tcon, S3C2410_TCON); |
249 | } | 246 | } |
250 | 247 | ||
248 | static void __init s3c2410_timer_resources(void) | ||
249 | { | ||
250 | struct platform_device tmpdev; | ||
251 | |||
252 | tmpdev.dev.bus = &platform_bus_type; | ||
253 | tmpdev.id = 4; | ||
254 | |||
255 | timerclk = clk_get(NULL, "timers"); | ||
256 | if (IS_ERR(timerclk)) | ||
257 | panic("failed to get clock for system timer"); | ||
258 | |||
259 | clk_enable(timerclk); | ||
260 | |||
261 | if (!use_tclk1_12()) { | ||
262 | tin = clk_get(&tmpdev.dev, "pwm-tin"); | ||
263 | if (IS_ERR(tin)) | ||
264 | panic("failed to get pwm-tin clock for system timer"); | ||
265 | |||
266 | tdiv = clk_get(&tmpdev.dev, "pwm-tdiv"); | ||
267 | if (IS_ERR(tdiv)) | ||
268 | panic("failed to get pwm-tdiv clock for system timer"); | ||
269 | } | ||
270 | |||
271 | clk_enable(tin); | ||
272 | } | ||
273 | |||
251 | static void __init s3c2410_timer_init(void) | 274 | static void __init s3c2410_timer_init(void) |
252 | { | 275 | { |
276 | s3c2410_timer_resources(); | ||
253 | s3c2410_timer_setup(); | 277 | s3c2410_timer_setup(); |
254 | setup_irq(IRQ_TIMER4, &s3c2410_timer_irq); | 278 | setup_irq(IRQ_TIMER4, &s3c2410_timer_irq); |
255 | } | 279 | } |
diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig index f0d54fdf88d4..2c8a2f5d75ff 100644 --- a/arch/arm/plat-s3c24xx/Kconfig +++ b/arch/arm/plat-s3c24xx/Kconfig | |||
@@ -41,6 +41,27 @@ config S3C24XX_PWM | |||
41 | Support for exporting the PWM timer blocks via the pwm device | 41 | Support for exporting the PWM timer blocks via the pwm device |
42 | system. | 42 | system. |
43 | 43 | ||
44 | |||
45 | # gpio configurations | ||
46 | |||
47 | config S3C24XX_GPIO_EXTRA | ||
48 | int | ||
49 | default 128 if S3C24XX_GPIO_EXTRA128 | ||
50 | default 64 if S3C24XX_GPIO_EXTRA64 | ||
51 | default 0 | ||
52 | |||
53 | config S3C24XX_GPIO_EXTRA64 | ||
54 | bool | ||
55 | help | ||
56 | Add an extra 64 gpio numbers to the available GPIO pool. This is | ||
57 | available for boards that need extra gpios for external devices. | ||
58 | |||
59 | config S3C24XX_GPIO_EXTRA128 | ||
60 | bool | ||
61 | help | ||
62 | Add an extra 128 gpio numbers to the available GPIO pool. This is | ||
63 | available for boards that need extra gpios for external devices. | ||
64 | |||
44 | config PM_SIMTEC | 65 | config PM_SIMTEC |
45 | bool | 66 | bool |
46 | help | 67 | help |
@@ -62,6 +83,13 @@ config S3C2410_DMA_DEBUG | |||
62 | Enable debugging output for the DMA code. This option sends info | 83 | Enable debugging output for the DMA code. This option sends info |
63 | to the kernel log, at priority KERN_DEBUG. | 84 | to the kernel log, at priority KERN_DEBUG. |
64 | 85 | ||
86 | config S3C24XX_ADC | ||
87 | bool "ADC common driver support" | ||
88 | help | ||
89 | Core support for the ADC block found in the S3C24XX SoC systems | ||
90 | for drivers such as the touchscreen and hwmon to use to share | ||
91 | this resource. | ||
92 | |||
65 | # SPI default pin configuration code | 93 | # SPI default pin configuration code |
66 | 94 | ||
67 | config S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13 | 95 | config S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13 |
diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile index 763d3444048b..1e0767b266b8 100644 --- a/arch/arm/plat-s3c24xx/Makefile +++ b/arch/arm/plat-s3c24xx/Makefile | |||
@@ -31,6 +31,7 @@ obj-$(CONFIG_PM) += sleep.o | |||
31 | obj-$(CONFIG_HAVE_PWM) += pwm.o | 31 | obj-$(CONFIG_HAVE_PWM) += pwm.o |
32 | obj-$(CONFIG_S3C2410_CLOCK) += s3c2410-clock.o | 32 | obj-$(CONFIG_S3C2410_CLOCK) += s3c2410-clock.o |
33 | obj-$(CONFIG_S3C2410_DMA) += dma.o | 33 | obj-$(CONFIG_S3C2410_DMA) += dma.o |
34 | obj-$(CONFIG_S3C24XX_ADC) += adc.o | ||
34 | 35 | ||
35 | # device specific setup and/or initialisation | 36 | # device specific setup and/or initialisation |
36 | obj-$(CONFIG_ARCH_S3C2410) += setup-i2c.o | 37 | obj-$(CONFIG_ARCH_S3C2410) += setup-i2c.o |
diff --git a/arch/arm/plat-s3c24xx/adc.c b/arch/arm/plat-s3c24xx/adc.c new file mode 100644 index 000000000000..9a5c767e0a42 --- /dev/null +++ b/arch/arm/plat-s3c24xx/adc.c | |||
@@ -0,0 +1,372 @@ | |||
1 | /* arch/arm/plat-s3c24xx/adc.c | ||
2 | * | ||
3 | * Copyright (c) 2008 Simtec Electronics | ||
4 | * http://armlinux.simtec.co.uk/ | ||
5 | * Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org> | ||
6 | * | ||
7 | * S3C24XX ADC device core | ||
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 as published by | ||
11 | * the Free Software Foundation; either version 2 of the License. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/list.h> | ||
18 | #include <linux/err.h> | ||
19 | #include <linux/clk.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/io.h> | ||
22 | |||
23 | #include <plat/regs-adc.h> | ||
24 | #include <plat/adc.h> | ||
25 | |||
26 | /* This driver is designed to control the usage of the ADC block between | ||
27 | * the touchscreen and any other drivers that may need to use it, such as | ||
28 | * the hwmon driver. | ||
29 | * | ||
30 | * Priority will be given to the touchscreen driver, but as this itself is | ||
31 | * rate limited it should not starve other requests which are processed in | ||
32 | * order that they are received. | ||
33 | * | ||
34 | * Each user registers to get a client block which uniquely identifies it | ||
35 | * and stores information such as the necessary functions to callback when | ||
36 | * action is required. | ||
37 | */ | ||
38 | |||
39 | struct s3c_adc_client { | ||
40 | struct platform_device *pdev; | ||
41 | struct list_head pend; | ||
42 | |||
43 | unsigned int nr_samples; | ||
44 | unsigned char is_ts; | ||
45 | unsigned char channel; | ||
46 | |||
47 | void (*select_cb)(unsigned selected); | ||
48 | void (*convert_cb)(unsigned val1, unsigned val2); | ||
49 | }; | ||
50 | |||
51 | struct adc_device { | ||
52 | struct platform_device *pdev; | ||
53 | struct platform_device *owner; | ||
54 | struct clk *clk; | ||
55 | struct s3c_adc_client *cur; | ||
56 | struct s3c_adc_client *ts_pend; | ||
57 | void __iomem *regs; | ||
58 | |||
59 | unsigned int prescale; | ||
60 | |||
61 | int irq; | ||
62 | }; | ||
63 | |||
64 | static struct adc_device *adc_dev; | ||
65 | |||
66 | static LIST_HEAD(adc_pending); | ||
67 | |||
68 | #define adc_dbg(_adc, msg...) dev_dbg(&(_adc)->pdev->dev, msg) | ||
69 | |||
70 | static inline void s3c_adc_convert(struct adc_device *adc) | ||
71 | { | ||
72 | unsigned con = readl(adc->regs + S3C2410_ADCCON); | ||
73 | |||
74 | con |= S3C2410_ADCCON_ENABLE_START; | ||
75 | writel(con, adc->regs + S3C2410_ADCCON); | ||
76 | } | ||
77 | |||
78 | static inline void s3c_adc_select(struct adc_device *adc, | ||
79 | struct s3c_adc_client *client) | ||
80 | { | ||
81 | unsigned con = readl(adc->regs + S3C2410_ADCCON); | ||
82 | |||
83 | client->select_cb(1); | ||
84 | |||
85 | con &= ~S3C2410_ADCCON_MUXMASK; | ||
86 | con &= ~S3C2410_ADCCON_STDBM; | ||
87 | con &= ~S3C2410_ADCCON_STARTMASK; | ||
88 | |||
89 | if (!client->is_ts) | ||
90 | con |= S3C2410_ADCCON_SELMUX(client->channel); | ||
91 | |||
92 | writel(con, adc->regs + S3C2410_ADCCON); | ||
93 | } | ||
94 | |||
95 | static void s3c_adc_dbgshow(struct adc_device *adc) | ||
96 | { | ||
97 | adc_dbg(adc, "CON=%08x, TSC=%08x, DLY=%08x\n", | ||
98 | readl(adc->regs + S3C2410_ADCCON), | ||
99 | readl(adc->regs + S3C2410_ADCTSC), | ||
100 | readl(adc->regs + S3C2410_ADCDLY)); | ||
101 | } | ||
102 | |||
103 | void s3c_adc_try(struct adc_device *adc) | ||
104 | { | ||
105 | struct s3c_adc_client *next = adc->ts_pend; | ||
106 | |||
107 | if (!next && !list_empty(&adc_pending)) { | ||
108 | next = list_first_entry(&adc_pending, | ||
109 | struct s3c_adc_client, pend); | ||
110 | list_del(&next->pend); | ||
111 | } else | ||
112 | adc->ts_pend = NULL; | ||
113 | |||
114 | if (next) { | ||
115 | adc_dbg(adc, "new client is %p\n", next); | ||
116 | adc->cur = next; | ||
117 | s3c_adc_select(adc, next); | ||
118 | s3c_adc_convert(adc); | ||
119 | s3c_adc_dbgshow(adc); | ||
120 | } | ||
121 | } | ||
122 | |||
123 | int s3c_adc_start(struct s3c_adc_client *client, | ||
124 | unsigned int channel, unsigned int nr_samples) | ||
125 | { | ||
126 | struct adc_device *adc = adc_dev; | ||
127 | unsigned long flags; | ||
128 | |||
129 | if (!adc) { | ||
130 | printk(KERN_ERR "%s: failed to find adc\n", __func__); | ||
131 | return -EINVAL; | ||
132 | } | ||
133 | |||
134 | if (client->is_ts && adc->ts_pend) | ||
135 | return -EAGAIN; | ||
136 | |||
137 | local_irq_save(flags); | ||
138 | |||
139 | client->channel = channel; | ||
140 | client->nr_samples = nr_samples; | ||
141 | |||
142 | if (client->is_ts) | ||
143 | adc->ts_pend = client; | ||
144 | else | ||
145 | list_add_tail(&client->pend, &adc_pending); | ||
146 | |||
147 | if (!adc->cur) | ||
148 | s3c_adc_try(adc); | ||
149 | local_irq_restore(flags); | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | EXPORT_SYMBOL_GPL(s3c_adc_start); | ||
154 | |||
155 | static void s3c_adc_default_select(unsigned select) | ||
156 | { | ||
157 | } | ||
158 | |||
159 | struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev, | ||
160 | void (*select)(unsigned int selected), | ||
161 | void (*conv)(unsigned d0, unsigned d1), | ||
162 | unsigned int is_ts) | ||
163 | { | ||
164 | struct s3c_adc_client *client; | ||
165 | |||
166 | WARN_ON(!pdev); | ||
167 | WARN_ON(!conv); | ||
168 | |||
169 | if (!select) | ||
170 | select = s3c_adc_default_select; | ||
171 | |||
172 | if (!conv || !pdev) | ||
173 | return ERR_PTR(-EINVAL); | ||
174 | |||
175 | client = kzalloc(sizeof(struct s3c_adc_client), GFP_KERNEL); | ||
176 | if (!client) { | ||
177 | dev_err(&pdev->dev, "no memory for adc client\n"); | ||
178 | return ERR_PTR(-ENOMEM); | ||
179 | } | ||
180 | |||
181 | client->pdev = pdev; | ||
182 | client->is_ts = is_ts; | ||
183 | client->select_cb = select; | ||
184 | client->convert_cb = conv; | ||
185 | |||
186 | return client; | ||
187 | } | ||
188 | EXPORT_SYMBOL_GPL(s3c_adc_register); | ||
189 | |||
190 | void s3c_adc_release(struct s3c_adc_client *client) | ||
191 | { | ||
192 | /* We should really check that nothing is in progress. */ | ||
193 | kfree(client); | ||
194 | } | ||
195 | EXPORT_SYMBOL_GPL(s3c_adc_release); | ||
196 | |||
197 | static irqreturn_t s3c_adc_irq(int irq, void *pw) | ||
198 | { | ||
199 | struct adc_device *adc = pw; | ||
200 | struct s3c_adc_client *client = adc->cur; | ||
201 | unsigned long flags; | ||
202 | unsigned data0, data1; | ||
203 | |||
204 | if (!client) { | ||
205 | dev_warn(&adc->pdev->dev, "%s: no adc pending\n", __func__); | ||
206 | return IRQ_HANDLED; | ||
207 | } | ||
208 | |||
209 | data0 = readl(adc->regs + S3C2410_ADCDAT0); | ||
210 | data1 = readl(adc->regs + S3C2410_ADCDAT1); | ||
211 | adc_dbg(adc, "read %d: 0x%04x, 0x%04x\n", client->nr_samples, data0, data1); | ||
212 | |||
213 | (client->convert_cb)(data0 & 0x3ff, data1 & 0x3ff); | ||
214 | |||
215 | if (--client->nr_samples > 0) { | ||
216 | /* fire another conversion for this */ | ||
217 | |||
218 | client->select_cb(1); | ||
219 | s3c_adc_convert(adc); | ||
220 | } else { | ||
221 | local_irq_save(flags); | ||
222 | (client->select_cb)(0); | ||
223 | adc->cur = NULL; | ||
224 | |||
225 | s3c_adc_try(adc); | ||
226 | local_irq_restore(flags); | ||
227 | } | ||
228 | |||
229 | return IRQ_HANDLED; | ||
230 | } | ||
231 | |||
232 | static int s3c_adc_probe(struct platform_device *pdev) | ||
233 | { | ||
234 | struct device *dev = &pdev->dev; | ||
235 | struct adc_device *adc; | ||
236 | struct resource *regs; | ||
237 | int ret; | ||
238 | |||
239 | adc = kzalloc(sizeof(struct adc_device), GFP_KERNEL); | ||
240 | if (adc == NULL) { | ||
241 | dev_err(dev, "failed to allocate adc_device\n"); | ||
242 | return -ENOMEM; | ||
243 | } | ||
244 | |||
245 | adc->pdev = pdev; | ||
246 | adc->prescale = S3C2410_ADCCON_PRSCVL(49); | ||
247 | |||
248 | adc->irq = platform_get_irq(pdev, 1); | ||
249 | if (adc->irq <= 0) { | ||
250 | dev_err(dev, "failed to get adc irq\n"); | ||
251 | ret = -ENOENT; | ||
252 | goto err_alloc; | ||
253 | } | ||
254 | |||
255 | ret = request_irq(adc->irq, s3c_adc_irq, 0, dev_name(dev), adc); | ||
256 | if (ret < 0) { | ||
257 | dev_err(dev, "failed to attach adc irq\n"); | ||
258 | goto err_alloc; | ||
259 | } | ||
260 | |||
261 | adc->clk = clk_get(dev, "adc"); | ||
262 | if (IS_ERR(adc->clk)) { | ||
263 | dev_err(dev, "failed to get adc clock\n"); | ||
264 | ret = PTR_ERR(adc->clk); | ||
265 | goto err_irq; | ||
266 | } | ||
267 | |||
268 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
269 | if (!regs) { | ||
270 | dev_err(dev, "failed to find registers\n"); | ||
271 | ret = -ENXIO; | ||
272 | goto err_clk; | ||
273 | } | ||
274 | |||
275 | adc->regs = ioremap(regs->start, resource_size(regs)); | ||
276 | if (!adc->regs) { | ||
277 | dev_err(dev, "failed to map registers\n"); | ||
278 | ret = -ENXIO; | ||
279 | goto err_clk; | ||
280 | } | ||
281 | |||
282 | clk_enable(adc->clk); | ||
283 | |||
284 | writel(adc->prescale | S3C2410_ADCCON_PRSCEN, | ||
285 | adc->regs + S3C2410_ADCCON); | ||
286 | |||
287 | dev_info(dev, "attached adc driver\n"); | ||
288 | |||
289 | platform_set_drvdata(pdev, adc); | ||
290 | adc_dev = adc; | ||
291 | |||
292 | return 0; | ||
293 | |||
294 | err_clk: | ||
295 | clk_put(adc->clk); | ||
296 | |||
297 | err_irq: | ||
298 | free_irq(adc->irq, adc); | ||
299 | |||
300 | err_alloc: | ||
301 | kfree(adc); | ||
302 | return ret; | ||
303 | } | ||
304 | |||
305 | static int s3c_adc_remove(struct platform_device *pdev) | ||
306 | { | ||
307 | struct adc_device *adc = platform_get_drvdata(pdev); | ||
308 | |||
309 | iounmap(adc->regs); | ||
310 | free_irq(adc->irq, adc); | ||
311 | clk_disable(adc->clk); | ||
312 | clk_put(adc->clk); | ||
313 | kfree(adc); | ||
314 | |||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | #ifdef CONFIG_PM | ||
319 | static int s3c_adc_suspend(struct platform_device *pdev, pm_message_t state) | ||
320 | { | ||
321 | struct adc_device *adc = platform_get_drvdata(pdev); | ||
322 | u32 con; | ||
323 | |||
324 | con = readl(adc->regs + S3C2410_ADCCON); | ||
325 | con |= S3C2410_ADCCON_STDBM; | ||
326 | writel(con, adc->regs + S3C2410_ADCCON); | ||
327 | |||
328 | clk_disable(adc->clk); | ||
329 | |||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | static int s3c_adc_resume(struct platform_device *pdev) | ||
334 | { | ||
335 | struct adc_device *adc = platform_get_drvdata(pdev); | ||
336 | |||
337 | clk_enable(adc->clk); | ||
338 | |||
339 | writel(adc->prescale | S3C2410_ADCCON_PRSCEN, | ||
340 | adc->regs + S3C2410_ADCCON); | ||
341 | |||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | #else | ||
346 | #define s3c_adc_suspend NULL | ||
347 | #define s3c_adc_resume NULL | ||
348 | #endif | ||
349 | |||
350 | static struct platform_driver s3c_adc_driver = { | ||
351 | .driver = { | ||
352 | .name = "s3c24xx-adc", | ||
353 | .owner = THIS_MODULE, | ||
354 | }, | ||
355 | .probe = s3c_adc_probe, | ||
356 | .remove = __devexit_p(s3c_adc_remove), | ||
357 | .suspend = s3c_adc_suspend, | ||
358 | .resume = s3c_adc_resume, | ||
359 | }; | ||
360 | |||
361 | static int __init adc_init(void) | ||
362 | { | ||
363 | int ret; | ||
364 | |||
365 | ret = platform_driver_register(&s3c_adc_driver); | ||
366 | if (ret) | ||
367 | printk(KERN_ERR "%s: failed to add adc driver\n", __func__); | ||
368 | |||
369 | return ret; | ||
370 | } | ||
371 | |||
372 | arch_initcall(adc_init); | ||
diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c index 3cb07b6a0e4c..14d4f0bc1253 100644 --- a/arch/arm/plat-s3c24xx/devs.c +++ b/arch/arm/plat-s3c24xx/devs.c | |||
@@ -347,12 +347,20 @@ static struct resource s3c_adc_resource[] = { | |||
347 | }; | 347 | }; |
348 | 348 | ||
349 | struct platform_device s3c_device_adc = { | 349 | struct platform_device s3c_device_adc = { |
350 | .name = "s3c2410-adc", | 350 | .name = "s3c24xx-adc", |
351 | .id = -1, | 351 | .id = -1, |
352 | .num_resources = ARRAY_SIZE(s3c_adc_resource), | 352 | .num_resources = ARRAY_SIZE(s3c_adc_resource), |
353 | .resource = s3c_adc_resource, | 353 | .resource = s3c_adc_resource, |
354 | }; | 354 | }; |
355 | 355 | ||
356 | /* HWMON */ | ||
357 | |||
358 | struct platform_device s3c_device_hwmon = { | ||
359 | .name = "s3c24xx-hwmon", | ||
360 | .id = -1, | ||
361 | .dev.parent = &s3c_device_adc.dev, | ||
362 | }; | ||
363 | |||
356 | /* SDI */ | 364 | /* SDI */ |
357 | 365 | ||
358 | static struct resource s3c_sdi_resource[] = { | 366 | static struct resource s3c_sdi_resource[] = { |
diff --git a/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h b/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h new file mode 100644 index 000000000000..a087de21bc20 --- /dev/null +++ b/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* linux/arch/arm/plat-s3c24xx/include/mach/pwm-clock.h | ||
2 | * | ||
3 | * Copyright 2008 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * http://armlinux.simtec.co.uk/ | ||
6 | * | ||
7 | * S3C24xx - pwm clock and timer support | ||
8 | */ | ||
9 | |||
10 | /** | ||
11 | * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk | ||
12 | * @cfg: The timer TCFG1 register bits shifted down to 0. | ||
13 | * | ||
14 | * Return true if the given configuration from TCFG1 is a TCLK instead | ||
15 | * any of the TDIV clocks. | ||
16 | */ | ||
17 | static inline int pwm_cfg_src_is_tclk(unsigned long tcfg) | ||
18 | { | ||
19 | return tcfg == S3C2410_TCFG1_MUX_TCLK; | ||
20 | } | ||
21 | |||
22 | /** | ||
23 | * tcfg_to_divisor() - convert tcfg1 setting to a divisor | ||
24 | * @tcfg1: The tcfg1 setting, shifted down. | ||
25 | * | ||
26 | * Get the divisor value for the given tcfg1 setting. We assume the | ||
27 | * caller has already checked to see if this is not a TCLK source. | ||
28 | */ | ||
29 | static inline unsigned long tcfg_to_divisor(unsigned long tcfg1) | ||
30 | { | ||
31 | return 1 << (1 + tcfg1); | ||
32 | } | ||
33 | |||
34 | /** | ||
35 | * pwm_tdiv_has_div1() - does the tdiv setting have a /1 | ||
36 | * | ||
37 | * Return true if we have a /1 in the tdiv setting. | ||
38 | */ | ||
39 | static inline unsigned int pwm_tdiv_has_div1(void) | ||
40 | { | ||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | /** | ||
45 | * pwm_tdiv_div_bits() - calculate TCFG1 divisor value. | ||
46 | * @div: The divisor to calculate the bit information for. | ||
47 | * | ||
48 | * Turn a divisor into the necessary bit field for TCFG1. | ||
49 | */ | ||
50 | static inline unsigned long pwm_tdiv_div_bits(unsigned int div) | ||
51 | { | ||
52 | return ilog2(div) - 1; | ||
53 | } | ||
54 | |||
55 | #define S3C_TCFG1_MUX_TCLK S3C2410_TCFG1_MUX_TCLK | ||
diff --git a/arch/arm/plat-s3c24xx/s3c2410-clock.c b/arch/arm/plat-s3c24xx/s3c2410-clock.c index 4e07943c1e29..b61bdb793734 100644 --- a/arch/arm/plat-s3c24xx/s3c2410-clock.c +++ b/arch/arm/plat-s3c24xx/s3c2410-clock.c | |||
@@ -272,5 +272,6 @@ int __init s3c2410_baseclk_add(void) | |||
272 | (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on", | 272 | (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on", |
273 | (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on"); | 273 | (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on"); |
274 | 274 | ||
275 | s3c_pwmclk_init(); | ||
275 | return 0; | 276 | return 0; |
276 | } | 277 | } |
diff --git a/arch/arm/plat-s3c64xx/clock.c b/arch/arm/plat-s3c64xx/clock.c index 2d2e83a036c4..5a1e97e1f8f6 100644 --- a/arch/arm/plat-s3c64xx/clock.c +++ b/arch/arm/plat-s3c64xx/clock.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <mach/hardware.h> | 22 | #include <mach/hardware.h> |
23 | #include <mach/map.h> | 23 | #include <mach/map.h> |
24 | 24 | ||
25 | #include <plat/regs-sys.h> | ||
25 | #include <plat/regs-clock.h> | 26 | #include <plat/regs-clock.h> |
26 | #include <plat/cpu.h> | 27 | #include <plat/cpu.h> |
27 | #include <plat/devs.h> | 28 | #include <plat/devs.h> |
@@ -33,10 +34,31 @@ struct clk clk_27m = { | |||
33 | .rate = 27000000, | 34 | .rate = 27000000, |
34 | }; | 35 | }; |
35 | 36 | ||
37 | static int clk_48m_ctrl(struct clk *clk, int enable) | ||
38 | { | ||
39 | unsigned long flags; | ||
40 | u32 val; | ||
41 | |||
42 | /* can't rely on clock lock, this register has other usages */ | ||
43 | local_irq_save(flags); | ||
44 | |||
45 | val = __raw_readl(S3C64XX_OTHERS); | ||
46 | if (enable) | ||
47 | val |= S3C64XX_OTHERS_USBMASK; | ||
48 | else | ||
49 | val &= ~S3C64XX_OTHERS_USBMASK; | ||
50 | |||
51 | __raw_writel(val, S3C64XX_OTHERS); | ||
52 | local_irq_restore(flags); | ||
53 | |||
54 | return 0; | ||
55 | } | ||
56 | |||
36 | struct clk clk_48m = { | 57 | struct clk clk_48m = { |
37 | .name = "clk_48m", | 58 | .name = "clk_48m", |
38 | .id = -1, | 59 | .id = -1, |
39 | .rate = 48000000, | 60 | .rate = 48000000, |
61 | .enable = clk_48m_ctrl, | ||
40 | }; | 62 | }; |
41 | 63 | ||
42 | static int inline s3c64xx_gate(void __iomem *reg, | 64 | static int inline s3c64xx_gate(void __iomem *reg, |
@@ -255,4 +277,6 @@ void s3c64xx_register_clocks(void) | |||
255 | 277 | ||
256 | (clkp->enable)(clkp, 0); | 278 | (clkp->enable)(clkp, 0); |
257 | } | 279 | } |
280 | |||
281 | s3c_pwmclk_init(); | ||
258 | } | 282 | } |
diff --git a/arch/arm/plat-s3c64xx/include/plat/pll.h b/arch/arm/plat-s3c64xx/include/plat/pll.h index 1a8576422f17..90bbd72fdc4e 100644 --- a/arch/arm/plat-s3c64xx/include/plat/pll.h +++ b/arch/arm/plat-s3c64xx/include/plat/pll.h | |||
@@ -12,9 +12,9 @@ | |||
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #define S3C6400_PLL_MDIV_MASK ((1 << (25-16)) - 1) | 15 | #define S3C6400_PLL_MDIV_MASK ((1 << (25-16+1)) - 1) |
16 | #define S3C6400_PLL_PDIV_MASK ((1 << (13-8)) - 1) | 16 | #define S3C6400_PLL_PDIV_MASK ((1 << (13-8+1)) - 1) |
17 | #define S3C6400_PLL_SDIV_MASK ((1 << (2-0)) - 1) | 17 | #define S3C6400_PLL_SDIV_MASK ((1 << (2-0+1)) - 1) |
18 | #define S3C6400_PLL_MDIV_SHIFT (16) | 18 | #define S3C6400_PLL_MDIV_SHIFT (16) |
19 | #define S3C6400_PLL_PDIV_SHIFT (8) | 19 | #define S3C6400_PLL_PDIV_SHIFT (8) |
20 | #define S3C6400_PLL_SDIV_SHIFT (0) | 20 | #define S3C6400_PLL_SDIV_SHIFT (0) |
diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-clock.h b/arch/arm/plat-s3c64xx/include/plat/regs-clock.h index 78938a5e1d20..b1082c163247 100644 --- a/arch/arm/plat-s3c64xx/include/plat/regs-clock.h +++ b/arch/arm/plat-s3c64xx/include/plat/regs-clock.h | |||
@@ -205,8 +205,8 @@ | |||
205 | #define S3C6400_CLKSRC_MMC2_SHIFT (22) | 205 | #define S3C6400_CLKSRC_MMC2_SHIFT (22) |
206 | #define S3C6400_CLKSRC_MMC1_MASK (0x3 << 20) | 206 | #define S3C6400_CLKSRC_MMC1_MASK (0x3 << 20) |
207 | #define S3C6400_CLKSRC_MMC1_SHIFT (20) | 207 | #define S3C6400_CLKSRC_MMC1_SHIFT (20) |
208 | #define S3C6400_CLKSRC_MMC0_MASK (0xf << 1) | 208 | #define S3C6400_CLKSRC_MMC0_MASK (0x3 << 18) |
209 | #define S3C6400_CLKSRC_MMC0_SHIFT (1) | 209 | #define S3C6400_CLKSRC_MMC0_SHIFT (18) |
210 | #define S3C6400_CLKSRC_SPI1_MASK (0x3 << 16) | 210 | #define S3C6400_CLKSRC_SPI1_MASK (0x3 << 16) |
211 | #define S3C6400_CLKSRC_SPI1_SHIFT (16) | 211 | #define S3C6400_CLKSRC_SPI1_SHIFT (16) |
212 | #define S3C6400_CLKSRC_SPI0_MASK (0x3 << 14) | 212 | #define S3C6400_CLKSRC_SPI0_MASK (0x3 << 14) |
diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-sys.h b/arch/arm/plat-s3c64xx/include/plat/regs-sys.h new file mode 100644 index 000000000000..d8ed82917096 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/regs-sys.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* arch/arm/plat-s3c64xx/include/plat/regs-sys.h | ||
2 | * | ||
3 | * Copyright 2008 Openmoko, Inc. | ||
4 | * Copyright 2008 Simtec Electronics | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * http://armlinux.simtec.co.uk/ | ||
7 | * | ||
8 | * S3C64XX system register definitions | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #ifndef __PLAT_REGS_SYS_H | ||
16 | #define __PLAT_REGS_SYS_H __FILE__ | ||
17 | |||
18 | #define S3C_SYSREG(x) (S3C_VA_SYS + (x)) | ||
19 | |||
20 | #define S3C64XX_OTHERS S3C_SYSREG(0x900) | ||
21 | |||
22 | #define S3C64XX_OTHERS_USBMASK (1 << 16) | ||
23 | |||
24 | #endif /* _PLAT_REGS_SYS_H */ | ||
diff --git a/arch/arm/plat-s3c64xx/irq-eint.c b/arch/arm/plat-s3c64xx/irq-eint.c index 8c01f9cd94b6..1f7cc0067f5c 100644 --- a/arch/arm/plat-s3c64xx/irq-eint.c +++ b/arch/arm/plat-s3c64xx/irq-eint.c | |||
@@ -82,7 +82,7 @@ static int s3c_irq_eint_set_type(unsigned int irq, unsigned int type) | |||
82 | if (offs > 27) | 82 | if (offs > 27) |
83 | return -EINVAL; | 83 | return -EINVAL; |
84 | 84 | ||
85 | if (offs > 15) | 85 | if (offs <= 15) |
86 | reg = S3C64XX_EINT0CON0; | 86 | reg = S3C64XX_EINT0CON0; |
87 | else | 87 | else |
88 | reg = S3C64XX_EINT0CON1; | 88 | reg = S3C64XX_EINT0CON1; |
diff --git a/arch/arm/plat-s3c64xx/s3c6400-clock.c b/arch/arm/plat-s3c64xx/s3c6400-clock.c index 64a9721cccb0..8d9a0cada668 100644 --- a/arch/arm/plat-s3c64xx/s3c6400-clock.c +++ b/arch/arm/plat-s3c64xx/s3c6400-clock.c | |||
@@ -620,6 +620,7 @@ static struct clk *clks[] __initdata = { | |||
620 | &clk_iis_cd1, | 620 | &clk_iis_cd1, |
621 | &clk_pcm_cd, | 621 | &clk_pcm_cd, |
622 | &clk_mout_epll.clk, | 622 | &clk_mout_epll.clk, |
623 | &clk_fout_epll, | ||
623 | &clk_mout_mpll.clk, | 624 | &clk_mout_mpll.clk, |
624 | &clk_dout_mpll, | 625 | &clk_dout_mpll, |
625 | &clk_mmc0.clk, | 626 | &clk_mmc0.clk, |