1/* linux/arch/arm/mach-s3c2410/s3c2410.c 2 * 3 * Copyright (c) 2003-2005 Simtec Electronics 4 * Ben Dooks <ben@simtec.co.uk> 5 * 6 * http://www.simtec.co.uk/products/EB2410ITX/ 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/list.h> 17#include <linux/timer.h> 18#include <linux/init.h> 19#include <linux/gpio.h> 20#include <linux/clk.h> 21#include <linux/sysdev.h> 22#include <linux/serial_core.h> 23#include <linux/platform_device.h> 24#include <linux/io.h> 25 26#include <asm/mach/arch.h> 27#include <asm/mach/map.h> 28#include <asm/mach/irq.h> 29 30#include <mach/hardware.h> 31#include <asm/irq.h> 32 33#include <plat/cpu-freq.h> 34 35#include <mach/regs-clock.h> 36#include <plat/regs-serial.h> 37 38#include <plat/s3c2410.h> 39#include <plat/cpu.h> 40#include <plat/devs.h> 41#include <plat/clock.h> 42#include <plat/pll.h> 43 44#include <plat/gpio-core.h> 45#include <plat/gpio-cfg.h> 46#include <plat/gpio-cfg-helpers.h> 47 48/* Initial IO mappings */ 49 50static struct map_desc s3c2410_iodesc[] __initdata = { 51 IODESC_ENT(CLKPWR), 52 IODESC_ENT(TIMER), 53 IODESC_ENT(WATCHDOG), 54}; 55 56/* our uart devices */ 57 58/* uart registration process */ 59 60void __init s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no) 61{ 62 s3c24xx_init_uartdevs("s3c2410-uart", s3c2410_uart_resources, cfg, no); 63} 64 65/* s3c2410_map_io 66 * 67 * register the standard cpu IO areas, and any passed in from the 68 * machine specific initialisation. 69*/ 70 71void __init s3c2410_map_io(void) 72{ 73 s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1up; 74 s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1up; 75 76 iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc)); 77} 78 79void __init_or_cpufreq s3c2410_setup_clocks(void) 80{ 81 struct clk *xtal_clk; 82 unsigned long tmp; 83 unsigned long xtal; 84 unsigned long fclk; 85 unsigned long hclk; 86 unsigned long pclk; 87 88 xtal_clk = clk_get(NULL, "xtal"); 89 xtal = clk_get_rate(xtal_clk); 90 clk_put(xtal_clk); 91 92 /* now we've got our machine bits initialised, work out what 93 * clocks we've got */ 94 95 fclk = s3c24xx_get_pll(__raw_readl(S3C2410_MPLLCON), xtal); 96 97 tmp = __raw_readl(S3C2410_CLKDIVN); 98 99 /* work out clock scalings */ 100 101 hclk = fclk / ((tmp & S3C2410_CLKDIVN_HDIVN) ? 2 : 1); 102 pclk = hclk / ((tmp & S3C2410_CLKDIVN_PDIVN) ? 2 : 1); 103 104 /* print brieft summary of clocks, etc */ 105 106 printk("S3C2410: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n", 107 print_mhz(fclk), print_mhz(hclk), print_mhz(pclk)); 108 109 /* initialise the clocks here, to allow other things like the 110 * console to use them 111 */ 112 113 s3c24xx_setup_clocks(fclk, hclk, pclk); 114} 115 116/* fake ARMCLK for use with cpufreq, etc. */ 117 118static struct clk s3c2410_armclk = { 119 .name = "armclk", 120 .parent = &clk_f, 121 .id = -1, 122}; 123 124void __init s3c2410_init_clocks(int xtal) 125{ 126 s3c24xx_register_baseclocks(xtal); 127 s3c2410_setup_clocks(); 128 s3c2410_baseclk_add(); 129 s3c24xx_register_clock(&s3c2410_armclk); 130} 131 132struct sysdev_class s3c2410_sysclass = { 133 .name = "s3c2410-core", 134}; 135 136/* Note, we would have liked to name this s3c2410-core, but we cannot 137 * register two sysdev_class with the same name. 138 */ 139struct sysdev_class s3c2410a_sysclass = { 140 .name = "s3c2410a-core", 141}; 142 143static struct sys_device s3c2410_sysdev = { 144 .cls = &s3c2410_sysclass, 145}; 146 147/* need to register class before we actually register the device, and 148 * we also need to ensure that it has been initialised before any of the 149 * drivers even try to use it (even if not on an s3c2410 based system) 150 * as a driver which may support both 2410 and 2440 may try and use it. 151*/ 152 153static int __init s3c2410_core_init(void) 154{ 155 return sysdev_class_register(&s3c2410_sysclass); 156} 157 158core_initcall(s3c2410_core_init); 159 160static int __init s3c2410a_core_init(void) 161{ 162 return sysdev_class_register(&s3c2410a_sysclass); 163} 164 165core_initcall(s3c2410a_core_init); 166 167int __init s3c2410_init(void) 168{ 169 printk("S3C2410: Initialising architecture\n"); 170 171 return sysdev_register(&s3c2410_sysdev); 172} 173 174int __init s3c2410a_init(void) 175{ 176 s3c2410_sysdev.cls = &s3c2410a_sysclass; 177 return s3c2410_init(); 178} 179