diff options
Diffstat (limited to 'arch/arm/mach-s3c64xx/common.c')
| -rw-r--r-- | arch/arm/mach-s3c64xx/common.c | 81 |
1 files changed, 69 insertions, 12 deletions
diff --git a/arch/arm/mach-s3c64xx/common.c b/arch/arm/mach-s3c64xx/common.c index aef303b8997..5c45aae675b 100644 --- a/arch/arm/mach-s3c64xx/common.c +++ b/arch/arm/mach-s3c64xx/common.c @@ -14,40 +14,60 @@ * published by the Free Software Foundation. */ +/* + * NOTE: Code in this file is not used when booting with Device Tree support. + */ + #include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> +#include <linux/clk-provider.h> #include <linux/interrupt.h> #include <linux/ioport.h> #include <linux/serial_core.h> +#include <linux/serial_s3c.h> #include <linux/platform_device.h> +#include <linux/reboot.h> #include <linux/io.h> #include <linux/dma-mapping.h> #include <linux/irq.h> #include <linux/gpio.h> +#include <linux/irqchip/arm-vic.h> +#include <clocksource/samsung_pwm.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> -#include <asm/hardware/vic.h> #include <asm/system_misc.h> #include <mach/map.h> #include <mach/hardware.h> #include <mach/regs-gpio.h> +#include <mach/gpio-samsung.h> #include <plat/cpu.h> -#include <plat/clock.h> #include <plat/devs.h> #include <plat/pm.h> #include <plat/gpio-cfg.h> #include <plat/irq-uart.h> -#include <plat/irq-vic-timer.h> +#include <plat/pwm-core.h> #include <plat/regs-irqtype.h> -#include <plat/regs-serial.h> #include <plat/watchdog-reset.h> #include "common.h" +/* External clock frequency */ +static unsigned long xtal_f = 12000000, xusbxti_f = 48000000; + +void __init s3c64xx_set_xtal_freq(unsigned long freq) +{ + xtal_f = freq; +} + +void __init s3c64xx_set_xusbxti_freq(unsigned long freq) +{ + xusbxti_f = freq; +} + /* uart registration process */ static void __init s3c64xx_init_uarts(struct s3c2410_uartcfg *cfg, int no) @@ -65,7 +85,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = S3C6400_CPU_ID, .idmask = S3C64XX_CPU_MASK, .map_io = s3c6400_map_io, - .init_clocks = s3c6400_init_clocks, .init_uarts = s3c64xx_init_uarts, .init = s3c6400_init, .name = name_s3c6400, @@ -73,7 +92,6 @@ static struct cpu_table cpu_ids[] __initdata = { .idcode = S3C6410_CPU_ID, .idmask = S3C64XX_CPU_MASK, .map_io = s3c6410_map_io, - .init_clocks = s3c6410_init_clocks, .init_uarts = s3c64xx_init_uarts, .init = s3c6410_init, .name = name_s3c6410, @@ -148,6 +166,30 @@ static struct device s3c64xx_dev = { .bus = &s3c64xx_subsys, }; +static struct samsung_pwm_variant s3c64xx_pwm_variant = { + .bits = 32, + .div_base = 0, + .has_tint_cstat = true, + .tclk_mask = (1 << 7) | (1 << 6) | (1 << 5), +}; + +void __init samsung_set_timer_source(unsigned int event, unsigned int source) +{ + s3c64xx_pwm_variant.output_mask = BIT(SAMSUNG_PWM_NUM) - 1; + s3c64xx_pwm_variant.output_mask &= ~(BIT(event) | BIT(source)); +} + +void __init samsung_timer_init(void) +{ + unsigned int timer_irqs[SAMSUNG_PWM_NUM] = { + IRQ_TIMER0_VIC, IRQ_TIMER1_VIC, IRQ_TIMER2_VIC, + IRQ_TIMER3_VIC, IRQ_TIMER4_VIC, + }; + + samsung_pwm_clocksource_init(S3C_VA_TIMER, + timer_irqs, &s3c64xx_pwm_variant); +} + /* read cpu identification code */ void __init s3c64xx_init_io(struct map_desc *mach_desc, int size) @@ -160,10 +202,16 @@ void __init s3c64xx_init_io(struct map_desc *mach_desc, int size) s3c64xx_init_cpu(); s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids)); + + samsung_pwm_set_platdata(&s3c64xx_pwm_variant); } static __init int s3c64xx_dev_init(void) { + /* Not applicable when using DT. */ + if (of_have_populated_dt()) + return 0; + subsys_system_register(&s3c64xx_subsys, NULL); return device_register(&s3c64xx_dev); } @@ -183,14 +231,19 @@ core_initcall(s3c64xx_dev_init); void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid) { + /* + * FIXME: there is no better place to put this at the moment + * (s3c64xx_clk_init needs ioremap and must happen before init_time + * samsung_wdt_reset_init needs clocks) + */ + s3c64xx_clk_init(NULL, xtal_f, xusbxti_f, soc_is_s3c6400(), S3C_VA_SYS); + samsung_wdt_reset_init(S3C_VA_WATCHDOG); + printk(KERN_DEBUG "%s: initialising interrupts\n", __func__); /* initialise the pair of VICs */ vic_init(VA_VIC0, IRQ_VIC0_BASE, vic0_valid, IRQ_VIC0_RESUME); vic_init(VA_VIC1, IRQ_VIC1_BASE, vic1_valid, IRQ_VIC1_RESUME); - - /* add the timer sub-irqs */ - s3c_init_vic_timer_irq(5, IRQ_TIMER0); } #define eint_offset(irq) ((irq) - IRQ_EINT(0)) @@ -360,6 +413,10 @@ static int __init s3c64xx_init_irq_eint(void) { int irq; + /* On DT-enabled systems EINTs are handled by pinctrl-s3c64xx driver. */ + if (of_have_populated_dt()) + return -ENODEV; + for (irq = IRQ_EINT(0); irq <= IRQ_EINT(27); irq++) { irq_set_chip_and_handler(irq, &s3c_irq_eint, handle_level_irq); irq_set_chip_data(irq, (void *)eint_irq_to_bit(irq)); @@ -375,10 +432,10 @@ static int __init s3c64xx_init_irq_eint(void) } arch_initcall(s3c64xx_init_irq_eint); -void s3c64xx_restart(char mode, const char *cmd) +void s3c64xx_restart(enum reboot_mode mode, const char *cmd) { - if (mode != 's') - arch_wdt_reset(); + if (mode != REBOOT_SOFT) + samsung_wdt_reset(); /* if all else fails, or mode was for soft, jump to 0 */ soft_restart(0); |
