1/* 2 * linux/arch/arm/mach-w90x900/cpu.c 3 * 4 * Copyright (c) 2009 Nuvoton corporation. 5 * 6 * Wan ZongShun <mcuos.com@gmail.com> 7 * 8 * NUC900 series cpu common support 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 as published by 12 * the Free Software Foundation;version 2 of the License. 13 * 14 */ 15 16#include <linux/kernel.h> 17#include <linux/types.h> 18#include <linux/interrupt.h> 19#include <linux/list.h> 20#include <linux/timer.h> 21#include <linux/init.h> 22#include <linux/platform_device.h> 23#include <linux/io.h> 24#include <linux/serial_8250.h> 25#include <linux/delay.h> 26 27#include <asm/mach/arch.h> 28#include <asm/mach/map.h> 29#include <asm/mach/irq.h> 30#include <asm/irq.h> 31#include <asm/system_misc.h> 32 33#include <mach/hardware.h> 34#include <mach/regs-serial.h> 35#include <mach/regs-clock.h> 36#include <mach/regs-ebi.h> 37#include <mach/regs-timer.h> 38 39#include "cpu.h" 40#include "clock.h" 41#include "nuc9xx.h" 42 43/* Initial IO mappings */ 44 45static struct map_desc nuc900_iodesc[] __initdata = { 46 IODESC_ENT(IRQ), 47 IODESC_ENT(GCR), 48 IODESC_ENT(UART), 49 IODESC_ENT(TIMER), 50 IODESC_ENT(EBI), 51 IODESC_ENT(GPIO), 52}; 53 54/* Initial clock declarations. */ 55static DEFINE_CLK(lcd, 0); 56static DEFINE_CLK(audio, 1); 57static DEFINE_CLK(fmi, 4); 58static DEFINE_SUBCLK(ms, 0); 59static DEFINE_SUBCLK(sd, 1); 60static DEFINE_CLK(dmac, 5); 61static DEFINE_CLK(atapi, 6); 62static DEFINE_CLK(emc, 7); 63static DEFINE_SUBCLK(rmii, 2); 64static DEFINE_CLK(usbd, 8); 65static DEFINE_CLK(usbh, 9); 66static DEFINE_CLK(g2d, 10); 67static DEFINE_CLK(pwm, 18); 68static DEFINE_CLK(ps2, 24); 69static DEFINE_CLK(kpi, 25); 70static DEFINE_CLK(wdt, 26); 71static DEFINE_CLK(gdma, 27); 72static DEFINE_CLK(adc, 28); 73static DEFINE_CLK(usi, 29); 74static DEFINE_CLK(ext, 0); 75static DEFINE_CLK(timer0, 19); 76static DEFINE_CLK(timer1, 20); 77static DEFINE_CLK(timer2, 21); 78static DEFINE_CLK(timer3, 22); 79static DEFINE_CLK(timer4, 23); 80 81static struct clk_lookup nuc900_clkregs[] = { 82 DEF_CLKLOOK(&clk_lcd, "nuc900-lcd", NULL), 83 DEF_CLKLOOK(&clk_audio, "nuc900-ac97", NULL), 84 DEF_CLKLOOK(&clk_fmi, "nuc900-fmi", NULL), 85 DEF_CLKLOOK(&clk_ms, "nuc900-fmi", "MS"), 86 DEF_CLKLOOK(&clk_sd, "nuc900-fmi", "SD"), 87 DEF_CLKLOOK(&clk_dmac, "nuc900-dmac", NULL), 88 DEF_CLKLOOK(&clk_atapi, "nuc900-atapi", NULL), 89 DEF_CLKLOOK(&clk_emc, "nuc900-emc", NULL), 90 DEF_CLKLOOK(&clk_rmii, "nuc900-emc", "RMII"), 91 DEF_CLKLOOK(&clk_usbd, "nuc900-usbd", NULL), 92 DEF_CLKLOOK(&clk_usbh, "nuc900-usbh", NULL), 93 DEF_CLKLOOK(&clk_g2d, "nuc900-g2d", NULL), 94 DEF_CLKLOOK(&clk_pwm, "nuc900-pwm", NULL), 95 DEF_CLKLOOK(&clk_ps2, "nuc900-ps2", NULL), 96 DEF_CLKLOOK(&clk_kpi, "nuc900-kpi", NULL), 97 DEF_CLKLOOK(&clk_wdt, "nuc900-wdt", NULL), 98 DEF_CLKLOOK(&clk_gdma, "nuc900-gdma", NULL), 99 DEF_CLKLOOK(&clk_adc, "nuc900-ts", NULL), 100 DEF_CLKLOOK(&clk_usi, "nuc900-spi", NULL), 101 DEF_CLKLOOK(&clk_ext, NULL, "ext"), 102 DEF_CLKLOOK(&clk_timer0, NULL, "timer0"), 103 DEF_CLKLOOK(&clk_timer1, NULL, "timer1"), 104 DEF_CLKLOOK(&clk_timer2, NULL, "timer2"), 105 DEF_CLKLOOK(&clk_timer3, NULL, "timer3"), 106 DEF_CLKLOOK(&clk_timer4, NULL, "timer4"), 107}; 108 109/* Initial serial platform data */ 110 111struct plat_serial8250_port nuc900_uart_data[] = { 112 NUC900_8250PORT(UART0), 113 {}, 114}; 115 116struct platform_device nuc900_serial_device = { 117 .name = "serial8250", 118 .id = PLAT8250_DEV_PLATFORM, 119 .dev = { 120 .platform_data = nuc900_uart_data, 121 }, 122}; 123 124/*Set NUC900 series cpu frequence*/ 125static int __init nuc900_set_clkval(unsigned int cpufreq) 126{ 127 unsigned int pllclk, ahbclk, apbclk, val; 128 129 pllclk = 0; 130 ahbclk = 0; 131 apbclk = 0; 132 133 switch (cpufreq) { 134 case 66: 135 pllclk = PLL_66MHZ; 136 ahbclk = AHB_CPUCLK_1_1; 137 apbclk = APB_AHB_1_2; 138 break; 139 140 case 100: 141 pllclk = PLL_100MHZ; 142 ahbclk = AHB_CPUCLK_1_1; 143 apbclk = APB_AHB_1_2; 144 break; 145 146 case 120: 147 pllclk = PLL_120MHZ; 148 ahbclk = AHB_CPUCLK_1_2; 149 apbclk = APB_AHB_1_2; 150 break; 151 152 case 166: 153 pllclk = PLL_166MHZ; 154 ahbclk = AHB_CPUCLK_1_2; 155 apbclk = APB_AHB_1_2; 156 break; 157 158 case 200: 159 pllclk = PLL_200MHZ; 160 ahbclk = AHB_CPUCLK_1_2; 161 apbclk = APB_AHB_1_2; 162 break; 163 } 164 165 __raw_writel(pllclk, REG_PLLCON0); 166 167 val = __raw_readl(REG_CLKDIV); 168 val &= ~(0x03 << 24 | 0x03 << 26); 169 val |= (ahbclk << 24 | apbclk << 26); 170 __raw_writel(val, REG_CLKDIV); 171 172 return 0; 173} 174static int __init nuc900_set_cpufreq(char *str) 175{ 176 unsigned long cpufreq, val; 177 178 if (!*str) 179 return 0; 180 181 if (kstrtoul(str, 0, &cpufreq)) 182 return 0; 183 184 nuc900_clock_source(NULL, "ext"); 185 186 nuc900_set_clkval(cpufreq); 187 188 mdelay(1); 189 190 val = __raw_readl(REG_CKSKEW); 191 val &= ~0xff; 192 val |= DEFAULTSKEW; 193 __raw_writel(val, REG_CKSKEW); 194 195 nuc900_clock_source(NULL, "pll0"); 196 197 return 1; 198} 199 200__setup("cpufreq=", nuc900_set_cpufreq); 201 202/*Init NUC900 evb io*/ 203 204void __init nuc900_map_io(struct map_desc *mach_desc, int mach_size) 205{ 206 unsigned long idcode = 0x0; 207 208 iotable_init(mach_desc, mach_size); 209 iotable_init(nuc900_iodesc, ARRAY_SIZE(nuc900_iodesc)); 210 211 idcode = __raw_readl(NUC900PDID); 212 if (idcode == NUC910_CPUID) 213 printk(KERN_INFO "CPU type 0x%08lx is NUC910\n", idcode); 214 else if (idcode == NUC920_CPUID) 215 printk(KERN_INFO "CPU type 0x%08lx is NUC920\n", idcode); 216 else if (idcode == NUC950_CPUID) 217 printk(KERN_INFO "CPU type 0x%08lx is NUC950\n", idcode); 218 else if (idcode == NUC960_CPUID) 219 printk(KERN_INFO "CPU type 0x%08lx is NUC960\n", idcode); 220} 221 222/*Init NUC900 clock*/ 223 224void __init nuc900_init_clocks(void) 225{ 226 clkdev_add_table(nuc900_clkregs, ARRAY_SIZE(nuc900_clkregs)); 227} 228 229#define WTCR (TMR_BA + 0x1C) 230#define WTCLK (1 << 10) 231#define WTE (1 << 7) 232#define WTRE (1 << 1) 233 234void nuc9xx_restart(enum reboot_mode mode, const char *cmd) 235{ 236 if (mode == REBOOT_SOFT) { 237 /* Jump into ROM at address 0 */ 238 soft_restart(0); 239 } else { 240 __raw_writel(WTE | WTRE | WTCLK, WTCR); 241 } 242} 243