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