1/* linux/arch/arm/plat-s3c/init.c 2 * 3 * Copyright (c) 2008 Simtec Electronics 4 * Ben Dooks <ben@simtec.co.uk> 5 * http://armlinux.simtec.co.uk/ 6 * 7 * S3C series CPU initialisation 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 * NOTE: Code in this file is not used on S3C64xx when booting with 16 * Device Tree support. 17 */ 18 19#include <linux/init.h> 20#include <linux/module.h> 21#include <linux/interrupt.h> 22#include <linux/ioport.h> 23#include <linux/serial_core.h> 24#include <linux/serial_s3c.h> 25#include <linux/platform_device.h> 26#include <linux/of.h> 27 28#include <asm/mach/arch.h> 29#include <asm/mach/map.h> 30 31#include <plat/cpu.h> 32#include <plat/devs.h> 33 34static struct cpu_table *cpu; 35 36static struct cpu_table * __init s3c_lookup_cpu(unsigned long idcode, 37 struct cpu_table *tab, 38 unsigned int count) 39{ 40 for (; count != 0; count--, tab++) { 41 if ((idcode & tab->idmask) == (tab->idcode & tab->idmask)) 42 return tab; 43 } 44 45 return NULL; 46} 47 48void __init s3c_init_cpu(unsigned long idcode, 49 struct cpu_table *cputab, unsigned int cputab_size) 50{ 51 cpu = s3c_lookup_cpu(idcode, cputab, cputab_size); 52 53 if (cpu == NULL) { 54 printk(KERN_ERR "Unknown CPU type 0x%08lx\n", idcode); 55 panic("Unknown S3C24XX CPU"); 56 } 57 58 printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode); 59 60 if (cpu->init == NULL) { 61 printk(KERN_ERR "CPU %s support not enabled\n", cpu->name); 62 panic("Unsupported Samsung CPU"); 63 } 64 65 if (cpu->map_io) 66 cpu->map_io(); 67} 68 69/* s3c24xx_init_clocks 70 * 71 * Initialise the clock subsystem and associated information from the 72 * given master crystal value. 73 * 74 * xtal = 0 -> use default PLL crystal value (normally 12MHz) 75 * != 0 -> PLL crystal value in Hz 76*/ 77 78void __init s3c24xx_init_clocks(int xtal) 79{ 80 if (xtal == 0) 81 xtal = 12*1000*1000; 82 83 if (cpu == NULL) 84 panic("s3c24xx_init_clocks: no cpu setup?\n"); 85 86 if (cpu->init_clocks == NULL) 87 panic("s3c24xx_init_clocks: cpu has no clock init\n"); 88 else 89 (cpu->init_clocks)(xtal); 90} 91 92/* uart management */ 93#if IS_ENABLED(CONFIG_SAMSUNG_ATAGS) 94static int nr_uarts __initdata = 0; 95 96#ifdef CONFIG_SERIAL_SAMSUNG_UARTS 97static struct s3c2410_uartcfg uart_cfgs[CONFIG_SERIAL_SAMSUNG_UARTS]; 98#endif 99 100/* s3c24xx_init_uartdevs 101 * 102 * copy the specified platform data and configuration into our central 103 * set of devices, before the data is thrown away after the init process. 104 * 105 * This also fills in the array passed to the serial driver for the 106 * early initialisation of the console. 107*/ 108 109void __init s3c24xx_init_uartdevs(char *name, 110 struct s3c24xx_uart_resources *res, 111 struct s3c2410_uartcfg *cfg, int no) 112{ 113#ifdef CONFIG_SERIAL_SAMSUNG_UARTS 114 struct platform_device *platdev; 115 struct s3c2410_uartcfg *cfgptr = uart_cfgs; 116 struct s3c24xx_uart_resources *resp; 117 int uart; 118 119 memcpy(cfgptr, cfg, sizeof(struct s3c2410_uartcfg) * no); 120 121 for (uart = 0; uart < no; uart++, cfg++, cfgptr++) { 122 platdev = s3c24xx_uart_src[cfgptr->hwport]; 123 124 resp = res + cfgptr->hwport; 125 126 s3c24xx_uart_devs[uart] = platdev; 127 128 platdev->name = name; 129 platdev->resource = resp->resources; 130 platdev->num_resources = resp->nr_resources; 131 132 platdev->dev.platform_data = cfgptr; 133 } 134 135 nr_uarts = no; 136#endif 137} 138 139void __init s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no) 140{ 141 if (cpu == NULL) 142 return; 143 144 if (cpu->init_uarts == NULL && IS_ENABLED(CONFIG_SAMSUNG_ATAGS)) { 145 printk(KERN_ERR "s3c24xx_init_uarts: cpu has no uart init\n"); 146 } else 147 (cpu->init_uarts)(cfg, no); 148} 149#endif 150 151static int __init s3c_arch_init(void) 152{ 153 int ret; 154 155 // do the correct init for cpu 156 157 if (cpu == NULL) { 158 /* Not needed when booting with device tree. */ 159 if (of_have_populated_dt()) 160 return 0; 161 panic("s3c_arch_init: NULL cpu\n"); 162 } 163 164 ret = (cpu->init)(); 165 if (ret != 0) 166 return ret; 167#if IS_ENABLED(CONFIG_SAMSUNG_ATAGS) 168 ret = platform_add_devices(s3c24xx_uart_devs, nr_uarts); 169#endif 170 return ret; 171} 172 173arch_initcall(s3c_arch_init); 174