189d63fe1SAtsushi Nemoto /* 289d63fe1SAtsushi Nemoto * linux/arch/mips/txx9/generic/setup.c 389d63fe1SAtsushi Nemoto * 489d63fe1SAtsushi Nemoto * Based on linux/arch/mips/txx9/rbtx4938/setup.c, 589d63fe1SAtsushi Nemoto * and RBTX49xx patch from CELF patch archive. 689d63fe1SAtsushi Nemoto * 789d63fe1SAtsushi Nemoto * 2003-2005 (c) MontaVista Software, Inc. 889d63fe1SAtsushi Nemoto * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007 989d63fe1SAtsushi Nemoto * 1089d63fe1SAtsushi Nemoto * This file is subject to the terms and conditions of the GNU General Public 1189d63fe1SAtsushi Nemoto * License. See the file "COPYING" in the main directory of this archive 1289d63fe1SAtsushi Nemoto * for more details. 1389d63fe1SAtsushi Nemoto */ 1489d63fe1SAtsushi Nemoto #include <linux/init.h> 1589d63fe1SAtsushi Nemoto #include <linux/kernel.h> 1689d63fe1SAtsushi Nemoto #include <linux/types.h> 17edcaf1a6SAtsushi Nemoto #include <linux/interrupt.h> 18edcaf1a6SAtsushi Nemoto #include <linux/string.h> 19edcaf1a6SAtsushi Nemoto #include <linux/module.h> 20edcaf1a6SAtsushi Nemoto #include <linux/clk.h> 21edcaf1a6SAtsushi Nemoto #include <linux/err.h> 22e0eb7307SAtsushi Nemoto #include <linux/gpio.h> 2368314725SAtsushi Nemoto #include <linux/platform_device.h> 247779a5e0SAtsushi Nemoto #include <linux/serial_core.h> 25edcaf1a6SAtsushi Nemoto #include <asm/bootinfo.h> 26e0eb7307SAtsushi Nemoto #include <asm/time.h> 27a49297e8SAtsushi Nemoto #include <asm/reboot.h> 28d10e025fSAtsushi Nemoto #include <asm/r4kcache.h> 2989d63fe1SAtsushi Nemoto #include <asm/txx9/generic.h> 3007517529SAtsushi Nemoto #include <asm/txx9/pci.h> 31edcaf1a6SAtsushi Nemoto #ifdef CONFIG_CPU_TX49XX 32edcaf1a6SAtsushi Nemoto #include <asm/txx9/tx4938.h> 33edcaf1a6SAtsushi Nemoto #endif 3489d63fe1SAtsushi Nemoto 3589d63fe1SAtsushi Nemoto /* EBUSC settings of TX4927, etc. */ 3689d63fe1SAtsushi Nemoto struct resource txx9_ce_res[8]; 3789d63fe1SAtsushi Nemoto static char txx9_ce_res_name[8][4]; /* "CEn" */ 3889d63fe1SAtsushi Nemoto 3989d63fe1SAtsushi Nemoto /* pcode, internal register */ 4094a4c329SAtsushi Nemoto unsigned int txx9_pcode; 4189d63fe1SAtsushi Nemoto char txx9_pcode_str[8]; 4289d63fe1SAtsushi Nemoto static struct resource txx9_reg_res = { 4389d63fe1SAtsushi Nemoto .name = txx9_pcode_str, 4489d63fe1SAtsushi Nemoto .flags = IORESOURCE_MEM, 4589d63fe1SAtsushi Nemoto }; 4689d63fe1SAtsushi Nemoto void __init 4789d63fe1SAtsushi Nemoto txx9_reg_res_init(unsigned int pcode, unsigned long base, unsigned long size) 4889d63fe1SAtsushi Nemoto { 4989d63fe1SAtsushi Nemoto int i; 5089d63fe1SAtsushi Nemoto 5189d63fe1SAtsushi Nemoto for (i = 0; i < ARRAY_SIZE(txx9_ce_res); i++) { 5289d63fe1SAtsushi Nemoto sprintf(txx9_ce_res_name[i], "CE%d", i); 5389d63fe1SAtsushi Nemoto txx9_ce_res[i].flags = IORESOURCE_MEM; 5489d63fe1SAtsushi Nemoto txx9_ce_res[i].name = txx9_ce_res_name[i]; 5589d63fe1SAtsushi Nemoto } 5689d63fe1SAtsushi Nemoto 57073828d0SAtsushi Nemoto txx9_pcode = pcode; 5889d63fe1SAtsushi Nemoto sprintf(txx9_pcode_str, "TX%x", pcode); 5989d63fe1SAtsushi Nemoto if (base) { 6089d63fe1SAtsushi Nemoto txx9_reg_res.start = base & 0xfffffffffULL; 6189d63fe1SAtsushi Nemoto txx9_reg_res.end = (base & 0xfffffffffULL) + (size - 1); 6289d63fe1SAtsushi Nemoto request_resource(&iomem_resource, &txx9_reg_res); 6389d63fe1SAtsushi Nemoto } 6489d63fe1SAtsushi Nemoto } 6589d63fe1SAtsushi Nemoto 6689d63fe1SAtsushi Nemoto /* clocks */ 6789d63fe1SAtsushi Nemoto unsigned int txx9_master_clock; 6889d63fe1SAtsushi Nemoto unsigned int txx9_cpu_clock; 6989d63fe1SAtsushi Nemoto unsigned int txx9_gbus_clock; 70edcaf1a6SAtsushi Nemoto 71*c7b95bcbSAtsushi Nemoto #ifdef CONFIG_CPU_TX39XX 72*c7b95bcbSAtsushi Nemoto /* don't enable by default - see errata */ 73*c7b95bcbSAtsushi Nemoto int txx9_ccfg_toeon __initdata; 74*c7b95bcbSAtsushi Nemoto #else 7594a4c329SAtsushi Nemoto int txx9_ccfg_toeon __initdata = 1; 76*c7b95bcbSAtsushi Nemoto #endif 77edcaf1a6SAtsushi Nemoto 78edcaf1a6SAtsushi Nemoto /* Minimum CLK support */ 79edcaf1a6SAtsushi Nemoto 80edcaf1a6SAtsushi Nemoto struct clk *clk_get(struct device *dev, const char *id) 81edcaf1a6SAtsushi Nemoto { 82edcaf1a6SAtsushi Nemoto if (!strcmp(id, "spi-baseclk")) 8394a4c329SAtsushi Nemoto return (struct clk *)((unsigned long)txx9_gbus_clock / 2 / 4); 84edcaf1a6SAtsushi Nemoto if (!strcmp(id, "imbus_clk")) 8594a4c329SAtsushi Nemoto return (struct clk *)((unsigned long)txx9_gbus_clock / 2); 86edcaf1a6SAtsushi Nemoto return ERR_PTR(-ENOENT); 87edcaf1a6SAtsushi Nemoto } 88edcaf1a6SAtsushi Nemoto EXPORT_SYMBOL(clk_get); 89edcaf1a6SAtsushi Nemoto 90edcaf1a6SAtsushi Nemoto int clk_enable(struct clk *clk) 91edcaf1a6SAtsushi Nemoto { 92edcaf1a6SAtsushi Nemoto return 0; 93edcaf1a6SAtsushi Nemoto } 94edcaf1a6SAtsushi Nemoto EXPORT_SYMBOL(clk_enable); 95edcaf1a6SAtsushi Nemoto 96edcaf1a6SAtsushi Nemoto void clk_disable(struct clk *clk) 97edcaf1a6SAtsushi Nemoto { 98edcaf1a6SAtsushi Nemoto } 99edcaf1a6SAtsushi Nemoto EXPORT_SYMBOL(clk_disable); 100edcaf1a6SAtsushi Nemoto 101edcaf1a6SAtsushi Nemoto unsigned long clk_get_rate(struct clk *clk) 102edcaf1a6SAtsushi Nemoto { 103edcaf1a6SAtsushi Nemoto return (unsigned long)clk; 104edcaf1a6SAtsushi Nemoto } 105edcaf1a6SAtsushi Nemoto EXPORT_SYMBOL(clk_get_rate); 106edcaf1a6SAtsushi Nemoto 107edcaf1a6SAtsushi Nemoto void clk_put(struct clk *clk) 108edcaf1a6SAtsushi Nemoto { 109edcaf1a6SAtsushi Nemoto } 110edcaf1a6SAtsushi Nemoto EXPORT_SYMBOL(clk_put); 111edcaf1a6SAtsushi Nemoto 1128d795f2aSAtsushi Nemoto /* GPIO support */ 1138d795f2aSAtsushi Nemoto 1148d795f2aSAtsushi Nemoto #ifdef CONFIG_GENERIC_GPIO 1158d795f2aSAtsushi Nemoto int gpio_to_irq(unsigned gpio) 1168d795f2aSAtsushi Nemoto { 1178d795f2aSAtsushi Nemoto return -EINVAL; 1188d795f2aSAtsushi Nemoto } 1198d795f2aSAtsushi Nemoto EXPORT_SYMBOL(gpio_to_irq); 1208d795f2aSAtsushi Nemoto 1218d795f2aSAtsushi Nemoto int irq_to_gpio(unsigned irq) 1228d795f2aSAtsushi Nemoto { 1238d795f2aSAtsushi Nemoto return -EINVAL; 1248d795f2aSAtsushi Nemoto } 1258d795f2aSAtsushi Nemoto EXPORT_SYMBOL(irq_to_gpio); 1268d795f2aSAtsushi Nemoto #endif 1278d795f2aSAtsushi Nemoto 128860e546cSAtsushi Nemoto #define BOARD_VEC(board) extern struct txx9_board_vec board; 129860e546cSAtsushi Nemoto #include <asm/txx9/boards.h> 130860e546cSAtsushi Nemoto #undef BOARD_VEC 131edcaf1a6SAtsushi Nemoto 132edcaf1a6SAtsushi Nemoto struct txx9_board_vec *txx9_board_vec __initdata; 133edcaf1a6SAtsushi Nemoto static char txx9_system_type[32]; 134edcaf1a6SAtsushi Nemoto 135860e546cSAtsushi Nemoto static struct txx9_board_vec *board_vecs[] __initdata = { 136860e546cSAtsushi Nemoto #define BOARD_VEC(board) &board, 137860e546cSAtsushi Nemoto #include <asm/txx9/boards.h> 138860e546cSAtsushi Nemoto #undef BOARD_VEC 139860e546cSAtsushi Nemoto }; 140860e546cSAtsushi Nemoto 141860e546cSAtsushi Nemoto static struct txx9_board_vec *__init find_board_byname(const char *name) 142860e546cSAtsushi Nemoto { 143860e546cSAtsushi Nemoto int i; 144860e546cSAtsushi Nemoto 145860e546cSAtsushi Nemoto /* search board_vecs table */ 146860e546cSAtsushi Nemoto for (i = 0; i < ARRAY_SIZE(board_vecs); i++) { 147860e546cSAtsushi Nemoto if (strstr(board_vecs[i]->system, name)) 148860e546cSAtsushi Nemoto return board_vecs[i]; 149860e546cSAtsushi Nemoto } 150860e546cSAtsushi Nemoto return NULL; 151860e546cSAtsushi Nemoto } 152860e546cSAtsushi Nemoto 153e0dfb20cSAtsushi Nemoto static void __init prom_init_cmdline(void) 154edcaf1a6SAtsushi Nemoto { 155edcaf1a6SAtsushi Nemoto int argc = (int)fw_arg0; 156e0dfb20cSAtsushi Nemoto int *argv32 = (int *)fw_arg1; 157edcaf1a6SAtsushi Nemoto int i; /* Always ignore the "-c" at argv[0] */ 158e0dfb20cSAtsushi Nemoto char builtin[CL_SIZE]; 159edcaf1a6SAtsushi Nemoto 160edcaf1a6SAtsushi Nemoto /* ignore all built-in args if any f/w args given */ 161e0dfb20cSAtsushi Nemoto /* 162e0dfb20cSAtsushi Nemoto * But if built-in strings was started with '+', append them 163e0dfb20cSAtsushi Nemoto * to command line args. If built-in was started with '-', 164e0dfb20cSAtsushi Nemoto * ignore all f/w args. 165e0dfb20cSAtsushi Nemoto */ 166e0dfb20cSAtsushi Nemoto builtin[0] = '\0'; 167e0dfb20cSAtsushi Nemoto if (arcs_cmdline[0] == '+') 168e0dfb20cSAtsushi Nemoto strcpy(builtin, arcs_cmdline + 1); 169e0dfb20cSAtsushi Nemoto else if (arcs_cmdline[0] == '-') { 170e0dfb20cSAtsushi Nemoto strcpy(builtin, arcs_cmdline + 1); 171e0dfb20cSAtsushi Nemoto argc = 0; 172e0dfb20cSAtsushi Nemoto } else if (argc <= 1) 173e0dfb20cSAtsushi Nemoto strcpy(builtin, arcs_cmdline); 174e0dfb20cSAtsushi Nemoto arcs_cmdline[0] = '\0'; 175edcaf1a6SAtsushi Nemoto 176edcaf1a6SAtsushi Nemoto for (i = 1; i < argc; i++) { 177e0dfb20cSAtsushi Nemoto char *str = (char *)(long)argv32[i]; 178edcaf1a6SAtsushi Nemoto if (i != 1) 179edcaf1a6SAtsushi Nemoto strcat(arcs_cmdline, " "); 180e0dfb20cSAtsushi Nemoto if (strchr(str, ' ')) { 181e0dfb20cSAtsushi Nemoto strcat(arcs_cmdline, "\""); 182e0dfb20cSAtsushi Nemoto strcat(arcs_cmdline, str); 183e0dfb20cSAtsushi Nemoto strcat(arcs_cmdline, "\""); 184e0dfb20cSAtsushi Nemoto } else 185e0dfb20cSAtsushi Nemoto strcat(arcs_cmdline, str); 186e0dfb20cSAtsushi Nemoto } 187e0dfb20cSAtsushi Nemoto /* append saved builtin args */ 188e0dfb20cSAtsushi Nemoto if (builtin[0]) { 189e0dfb20cSAtsushi Nemoto if (arcs_cmdline[0]) 190e0dfb20cSAtsushi Nemoto strcat(arcs_cmdline, " "); 191e0dfb20cSAtsushi Nemoto strcat(arcs_cmdline, builtin); 192edcaf1a6SAtsushi Nemoto } 193edcaf1a6SAtsushi Nemoto } 194edcaf1a6SAtsushi Nemoto 195d10e025fSAtsushi Nemoto static int txx9_ic_disable __initdata; 196d10e025fSAtsushi Nemoto static int txx9_dc_disable __initdata; 197d10e025fSAtsushi Nemoto 198d10e025fSAtsushi Nemoto #if defined(CONFIG_CPU_TX49XX) 199d10e025fSAtsushi Nemoto /* flush all cache on very early stage (before 4k_cache_init) */ 200d10e025fSAtsushi Nemoto static void __init early_flush_dcache(void) 201d10e025fSAtsushi Nemoto { 202d10e025fSAtsushi Nemoto unsigned int conf = read_c0_config(); 203d10e025fSAtsushi Nemoto unsigned int dc_size = 1 << (12 + ((conf & CONF_DC) >> 6)); 204d10e025fSAtsushi Nemoto unsigned int linesz = 32; 205d10e025fSAtsushi Nemoto unsigned long addr, end; 206d10e025fSAtsushi Nemoto 207d10e025fSAtsushi Nemoto end = INDEX_BASE + dc_size / 4; 208d10e025fSAtsushi Nemoto /* 4way, waybit=0 */ 209d10e025fSAtsushi Nemoto for (addr = INDEX_BASE; addr < end; addr += linesz) { 210d10e025fSAtsushi Nemoto cache_op(Index_Writeback_Inv_D, addr | 0); 211d10e025fSAtsushi Nemoto cache_op(Index_Writeback_Inv_D, addr | 1); 212d10e025fSAtsushi Nemoto cache_op(Index_Writeback_Inv_D, addr | 2); 213d10e025fSAtsushi Nemoto cache_op(Index_Writeback_Inv_D, addr | 3); 214d10e025fSAtsushi Nemoto } 215d10e025fSAtsushi Nemoto } 216d10e025fSAtsushi Nemoto 217d10e025fSAtsushi Nemoto static void __init txx9_cache_fixup(void) 218d10e025fSAtsushi Nemoto { 219d10e025fSAtsushi Nemoto unsigned int conf; 220d10e025fSAtsushi Nemoto 221d10e025fSAtsushi Nemoto conf = read_c0_config(); 222d10e025fSAtsushi Nemoto /* flush and disable */ 223d10e025fSAtsushi Nemoto if (txx9_ic_disable) { 224d10e025fSAtsushi Nemoto conf |= TX49_CONF_IC; 225d10e025fSAtsushi Nemoto write_c0_config(conf); 226d10e025fSAtsushi Nemoto } 227d10e025fSAtsushi Nemoto if (txx9_dc_disable) { 228d10e025fSAtsushi Nemoto early_flush_dcache(); 229d10e025fSAtsushi Nemoto conf |= TX49_CONF_DC; 230d10e025fSAtsushi Nemoto write_c0_config(conf); 231d10e025fSAtsushi Nemoto } 232d10e025fSAtsushi Nemoto 233d10e025fSAtsushi Nemoto /* enable cache */ 234d10e025fSAtsushi Nemoto conf = read_c0_config(); 235d10e025fSAtsushi Nemoto if (!txx9_ic_disable) 236d10e025fSAtsushi Nemoto conf &= ~TX49_CONF_IC; 237d10e025fSAtsushi Nemoto if (!txx9_dc_disable) 238d10e025fSAtsushi Nemoto conf &= ~TX49_CONF_DC; 239d10e025fSAtsushi Nemoto write_c0_config(conf); 240d10e025fSAtsushi Nemoto 241d10e025fSAtsushi Nemoto if (conf & TX49_CONF_IC) 242d10e025fSAtsushi Nemoto pr_info("TX49XX I-Cache disabled.\n"); 243d10e025fSAtsushi Nemoto if (conf & TX49_CONF_DC) 244d10e025fSAtsushi Nemoto pr_info("TX49XX D-Cache disabled.\n"); 245d10e025fSAtsushi Nemoto } 246d10e025fSAtsushi Nemoto #elif defined(CONFIG_CPU_TX39XX) 247d10e025fSAtsushi Nemoto /* flush all cache on very early stage (before tx39_cache_init) */ 248d10e025fSAtsushi Nemoto static void __init early_flush_dcache(void) 249d10e025fSAtsushi Nemoto { 250d10e025fSAtsushi Nemoto unsigned int conf = read_c0_config(); 251d10e025fSAtsushi Nemoto unsigned int dc_size = 1 << (10 + ((conf & TX39_CONF_DCS_MASK) >> 252d10e025fSAtsushi Nemoto TX39_CONF_DCS_SHIFT)); 253d10e025fSAtsushi Nemoto unsigned int linesz = 16; 254d10e025fSAtsushi Nemoto unsigned long addr, end; 255d10e025fSAtsushi Nemoto 256d10e025fSAtsushi Nemoto end = INDEX_BASE + dc_size / 2; 257d10e025fSAtsushi Nemoto /* 2way, waybit=0 */ 258d10e025fSAtsushi Nemoto for (addr = INDEX_BASE; addr < end; addr += linesz) { 259d10e025fSAtsushi Nemoto cache_op(Index_Writeback_Inv_D, addr | 0); 260d10e025fSAtsushi Nemoto cache_op(Index_Writeback_Inv_D, addr | 1); 261d10e025fSAtsushi Nemoto } 262d10e025fSAtsushi Nemoto } 263d10e025fSAtsushi Nemoto 264d10e025fSAtsushi Nemoto static void __init txx9_cache_fixup(void) 265d10e025fSAtsushi Nemoto { 266d10e025fSAtsushi Nemoto unsigned int conf; 267d10e025fSAtsushi Nemoto 268d10e025fSAtsushi Nemoto conf = read_c0_config(); 269d10e025fSAtsushi Nemoto /* flush and disable */ 270d10e025fSAtsushi Nemoto if (txx9_ic_disable) { 271d10e025fSAtsushi Nemoto conf &= ~TX39_CONF_ICE; 272d10e025fSAtsushi Nemoto write_c0_config(conf); 273d10e025fSAtsushi Nemoto } 274d10e025fSAtsushi Nemoto if (txx9_dc_disable) { 275d10e025fSAtsushi Nemoto early_flush_dcache(); 276d10e025fSAtsushi Nemoto conf &= ~TX39_CONF_DCE; 277d10e025fSAtsushi Nemoto write_c0_config(conf); 278d10e025fSAtsushi Nemoto } 279d10e025fSAtsushi Nemoto 280d10e025fSAtsushi Nemoto /* enable cache */ 281d10e025fSAtsushi Nemoto conf = read_c0_config(); 282d10e025fSAtsushi Nemoto if (!txx9_ic_disable) 283d10e025fSAtsushi Nemoto conf |= TX39_CONF_ICE; 284d10e025fSAtsushi Nemoto if (!txx9_dc_disable) 285d10e025fSAtsushi Nemoto conf |= TX39_CONF_DCE; 286d10e025fSAtsushi Nemoto write_c0_config(conf); 287d10e025fSAtsushi Nemoto 288d10e025fSAtsushi Nemoto if (!(conf & TX39_CONF_ICE)) 289d10e025fSAtsushi Nemoto pr_info("TX39XX I-Cache disabled.\n"); 290d10e025fSAtsushi Nemoto if (!(conf & TX39_CONF_DCE)) 291d10e025fSAtsushi Nemoto pr_info("TX39XX D-Cache disabled.\n"); 292d10e025fSAtsushi Nemoto } 293d10e025fSAtsushi Nemoto #else 294d10e025fSAtsushi Nemoto static inline void txx9_cache_fixup(void) 295d10e025fSAtsushi Nemoto { 296d10e025fSAtsushi Nemoto } 297d10e025fSAtsushi Nemoto #endif 298d10e025fSAtsushi Nemoto 299860e546cSAtsushi Nemoto static void __init preprocess_cmdline(void) 300edcaf1a6SAtsushi Nemoto { 301860e546cSAtsushi Nemoto char cmdline[CL_SIZE]; 302860e546cSAtsushi Nemoto char *s; 303860e546cSAtsushi Nemoto 304860e546cSAtsushi Nemoto strcpy(cmdline, arcs_cmdline); 305860e546cSAtsushi Nemoto s = cmdline; 306860e546cSAtsushi Nemoto arcs_cmdline[0] = '\0'; 307860e546cSAtsushi Nemoto while (s && *s) { 308860e546cSAtsushi Nemoto char *str = strsep(&s, " "); 309860e546cSAtsushi Nemoto if (strncmp(str, "board=", 6) == 0) { 310860e546cSAtsushi Nemoto txx9_board_vec = find_board_byname(str + 6); 311860e546cSAtsushi Nemoto continue; 312860e546cSAtsushi Nemoto } else if (strncmp(str, "masterclk=", 10) == 0) { 313860e546cSAtsushi Nemoto unsigned long val; 314860e546cSAtsushi Nemoto if (strict_strtoul(str + 10, 10, &val) == 0) 315860e546cSAtsushi Nemoto txx9_master_clock = val; 316860e546cSAtsushi Nemoto continue; 317d10e025fSAtsushi Nemoto } else if (strcmp(str, "icdisable") == 0) { 318d10e025fSAtsushi Nemoto txx9_ic_disable = 1; 319d10e025fSAtsushi Nemoto continue; 320d10e025fSAtsushi Nemoto } else if (strcmp(str, "dcdisable") == 0) { 321d10e025fSAtsushi Nemoto txx9_dc_disable = 1; 322d10e025fSAtsushi Nemoto continue; 323*c7b95bcbSAtsushi Nemoto } else if (strcmp(str, "toeoff") == 0) { 324*c7b95bcbSAtsushi Nemoto txx9_ccfg_toeon = 0; 325*c7b95bcbSAtsushi Nemoto continue; 326*c7b95bcbSAtsushi Nemoto } else if (strcmp(str, "toeon") == 0) { 327*c7b95bcbSAtsushi Nemoto txx9_ccfg_toeon = 1; 328*c7b95bcbSAtsushi Nemoto continue; 329860e546cSAtsushi Nemoto } 330860e546cSAtsushi Nemoto if (arcs_cmdline[0]) 331860e546cSAtsushi Nemoto strcat(arcs_cmdline, " "); 332860e546cSAtsushi Nemoto strcat(arcs_cmdline, str); 333860e546cSAtsushi Nemoto } 334d10e025fSAtsushi Nemoto 335d10e025fSAtsushi Nemoto txx9_cache_fixup(); 336860e546cSAtsushi Nemoto } 337860e546cSAtsushi Nemoto 338860e546cSAtsushi Nemoto static void __init select_board(void) 339860e546cSAtsushi Nemoto { 340860e546cSAtsushi Nemoto const char *envstr; 341860e546cSAtsushi Nemoto 342860e546cSAtsushi Nemoto /* first, determine by "board=" argument in preprocess_cmdline() */ 343860e546cSAtsushi Nemoto if (txx9_board_vec) 344860e546cSAtsushi Nemoto return; 345860e546cSAtsushi Nemoto /* next, determine by "board" envvar */ 346860e546cSAtsushi Nemoto envstr = prom_getenv("board"); 347860e546cSAtsushi Nemoto if (envstr) { 348860e546cSAtsushi Nemoto txx9_board_vec = find_board_byname(envstr); 349860e546cSAtsushi Nemoto if (txx9_board_vec) 350860e546cSAtsushi Nemoto return; 351860e546cSAtsushi Nemoto } 352860e546cSAtsushi Nemoto 353860e546cSAtsushi Nemoto /* select "default" board */ 354edcaf1a6SAtsushi Nemoto #ifdef CONFIG_CPU_TX39XX 3557a1fdf19SYoichi Yuasa txx9_board_vec = &jmr3927_vec; 356edcaf1a6SAtsushi Nemoto #endif 357edcaf1a6SAtsushi Nemoto #ifdef CONFIG_CPU_TX49XX 358edcaf1a6SAtsushi Nemoto switch (TX4938_REV_PCODE()) { 3598d795f2aSAtsushi Nemoto #ifdef CONFIG_TOSHIBA_RBTX4927 360edcaf1a6SAtsushi Nemoto case 0x4927: 3617a1fdf19SYoichi Yuasa txx9_board_vec = &rbtx4927_vec; 362edcaf1a6SAtsushi Nemoto break; 363edcaf1a6SAtsushi Nemoto case 0x4937: 3647a1fdf19SYoichi Yuasa txx9_board_vec = &rbtx4937_vec; 365edcaf1a6SAtsushi Nemoto break; 3668d795f2aSAtsushi Nemoto #endif 3678d795f2aSAtsushi Nemoto #ifdef CONFIG_TOSHIBA_RBTX4938 368edcaf1a6SAtsushi Nemoto case 0x4938: 3697a1fdf19SYoichi Yuasa txx9_board_vec = &rbtx4938_vec; 370edcaf1a6SAtsushi Nemoto break; 3718d795f2aSAtsushi Nemoto #endif 372edcaf1a6SAtsushi Nemoto } 373edcaf1a6SAtsushi Nemoto #endif 374860e546cSAtsushi Nemoto } 375860e546cSAtsushi Nemoto 376860e546cSAtsushi Nemoto void __init prom_init(void) 377860e546cSAtsushi Nemoto { 378860e546cSAtsushi Nemoto prom_init_cmdline(); 379860e546cSAtsushi Nemoto preprocess_cmdline(); 380860e546cSAtsushi Nemoto select_board(); 3817a1fdf19SYoichi Yuasa 382edcaf1a6SAtsushi Nemoto strcpy(txx9_system_type, txx9_board_vec->system); 3837a1fdf19SYoichi Yuasa 3847b226094SAtsushi Nemoto txx9_board_vec->prom_init(); 385edcaf1a6SAtsushi Nemoto } 386edcaf1a6SAtsushi Nemoto 387edcaf1a6SAtsushi Nemoto void __init prom_free_prom_memory(void) 388edcaf1a6SAtsushi Nemoto { 389edcaf1a6SAtsushi Nemoto } 390edcaf1a6SAtsushi Nemoto 391edcaf1a6SAtsushi Nemoto const char *get_system_type(void) 392edcaf1a6SAtsushi Nemoto { 393edcaf1a6SAtsushi Nemoto return txx9_system_type; 394edcaf1a6SAtsushi Nemoto } 395edcaf1a6SAtsushi Nemoto 396edcaf1a6SAtsushi Nemoto char * __init prom_getcmdline(void) 397edcaf1a6SAtsushi Nemoto { 398edcaf1a6SAtsushi Nemoto return &(arcs_cmdline[0]); 399edcaf1a6SAtsushi Nemoto } 400edcaf1a6SAtsushi Nemoto 401265b89dbSAtsushi Nemoto const char *__init prom_getenv(const char *name) 402265b89dbSAtsushi Nemoto { 403265b89dbSAtsushi Nemoto const s32 *str = (const s32 *)fw_arg2; 404265b89dbSAtsushi Nemoto 405265b89dbSAtsushi Nemoto if (!str) 406265b89dbSAtsushi Nemoto return NULL; 407265b89dbSAtsushi Nemoto /* YAMON style ("name", "value" pairs) */ 408265b89dbSAtsushi Nemoto while (str[0] && str[1]) { 409265b89dbSAtsushi Nemoto if (!strcmp((const char *)(unsigned long)str[0], name)) 410265b89dbSAtsushi Nemoto return (const char *)(unsigned long)str[1]; 411265b89dbSAtsushi Nemoto str += 2; 412265b89dbSAtsushi Nemoto } 413265b89dbSAtsushi Nemoto return NULL; 414265b89dbSAtsushi Nemoto } 415265b89dbSAtsushi Nemoto 416a49297e8SAtsushi Nemoto static void __noreturn txx9_machine_halt(void) 417a49297e8SAtsushi Nemoto { 418a49297e8SAtsushi Nemoto local_irq_disable(); 419a49297e8SAtsushi Nemoto clear_c0_status(ST0_IM); 420a49297e8SAtsushi Nemoto while (1) { 421a49297e8SAtsushi Nemoto if (cpu_wait) { 422a49297e8SAtsushi Nemoto (*cpu_wait)(); 423a49297e8SAtsushi Nemoto if (cpu_has_counter) { 424a49297e8SAtsushi Nemoto /* 425a49297e8SAtsushi Nemoto * Clear counter interrupt while it 426a49297e8SAtsushi Nemoto * breaks WAIT instruction even if 427a49297e8SAtsushi Nemoto * masked. 428a49297e8SAtsushi Nemoto */ 429a49297e8SAtsushi Nemoto write_c0_compare(0); 430a49297e8SAtsushi Nemoto } 431a49297e8SAtsushi Nemoto } 432a49297e8SAtsushi Nemoto } 433a49297e8SAtsushi Nemoto } 434a49297e8SAtsushi Nemoto 43568314725SAtsushi Nemoto /* Watchdog support */ 43668314725SAtsushi Nemoto void __init txx9_wdt_init(unsigned long base) 43768314725SAtsushi Nemoto { 43868314725SAtsushi Nemoto struct resource res = { 43968314725SAtsushi Nemoto .start = base, 44068314725SAtsushi Nemoto .end = base + 0x100 - 1, 44168314725SAtsushi Nemoto .flags = IORESOURCE_MEM, 44268314725SAtsushi Nemoto }; 44368314725SAtsushi Nemoto platform_device_register_simple("txx9wdt", -1, &res, 1); 44468314725SAtsushi Nemoto } 44568314725SAtsushi Nemoto 446c49f91f5SAtsushi Nemoto /* SPI support */ 447c49f91f5SAtsushi Nemoto void __init txx9_spi_init(int busid, unsigned long base, int irq) 448c49f91f5SAtsushi Nemoto { 449c49f91f5SAtsushi Nemoto struct resource res[] = { 450c49f91f5SAtsushi Nemoto { 451c49f91f5SAtsushi Nemoto .start = base, 452c49f91f5SAtsushi Nemoto .end = base + 0x20 - 1, 453c49f91f5SAtsushi Nemoto .flags = IORESOURCE_MEM, 454c49f91f5SAtsushi Nemoto }, { 455c49f91f5SAtsushi Nemoto .start = irq, 456c49f91f5SAtsushi Nemoto .flags = IORESOURCE_IRQ, 457c49f91f5SAtsushi Nemoto }, 458c49f91f5SAtsushi Nemoto }; 459c49f91f5SAtsushi Nemoto platform_device_register_simple("spi_txx9", busid, 460c49f91f5SAtsushi Nemoto res, ARRAY_SIZE(res)); 461c49f91f5SAtsushi Nemoto } 462c49f91f5SAtsushi Nemoto 463c49f91f5SAtsushi Nemoto void __init txx9_ethaddr_init(unsigned int id, unsigned char *ethaddr) 464c49f91f5SAtsushi Nemoto { 465c49f91f5SAtsushi Nemoto struct platform_device *pdev = 466c49f91f5SAtsushi Nemoto platform_device_alloc("tc35815-mac", id); 467c49f91f5SAtsushi Nemoto if (!pdev || 468c49f91f5SAtsushi Nemoto platform_device_add_data(pdev, ethaddr, 6) || 469c49f91f5SAtsushi Nemoto platform_device_add(pdev)) 470c49f91f5SAtsushi Nemoto platform_device_put(pdev); 471c49f91f5SAtsushi Nemoto } 472c49f91f5SAtsushi Nemoto 4737779a5e0SAtsushi Nemoto void __init txx9_sio_init(unsigned long baseaddr, int irq, 4747779a5e0SAtsushi Nemoto unsigned int line, unsigned int sclk, int nocts) 4757779a5e0SAtsushi Nemoto { 4767779a5e0SAtsushi Nemoto #ifdef CONFIG_SERIAL_TXX9 4777779a5e0SAtsushi Nemoto struct uart_port req; 4787779a5e0SAtsushi Nemoto 4797779a5e0SAtsushi Nemoto memset(&req, 0, sizeof(req)); 4807779a5e0SAtsushi Nemoto req.line = line; 4817779a5e0SAtsushi Nemoto req.iotype = UPIO_MEM; 4827779a5e0SAtsushi Nemoto req.membase = ioremap(baseaddr, 0x24); 4837779a5e0SAtsushi Nemoto req.mapbase = baseaddr; 4847779a5e0SAtsushi Nemoto req.irq = irq; 4857779a5e0SAtsushi Nemoto if (!nocts) 4867779a5e0SAtsushi Nemoto req.flags |= UPF_BUGGY_UART /*HAVE_CTS_LINE*/; 4877779a5e0SAtsushi Nemoto if (sclk) { 4887779a5e0SAtsushi Nemoto req.flags |= UPF_MAGIC_MULTIPLIER /*USE_SCLK*/; 4897779a5e0SAtsushi Nemoto req.uartclk = sclk; 4907779a5e0SAtsushi Nemoto } else 4917779a5e0SAtsushi Nemoto req.uartclk = TXX9_IMCLK; 4927779a5e0SAtsushi Nemoto early_serial_txx9_setup(&req); 4937779a5e0SAtsushi Nemoto #endif /* CONFIG_SERIAL_TXX9 */ 4947779a5e0SAtsushi Nemoto } 4957779a5e0SAtsushi Nemoto 496e352953cSAtsushi Nemoto #ifdef CONFIG_EARLY_PRINTK 497e352953cSAtsushi Nemoto static void __init null_prom_putchar(char c) 498e352953cSAtsushi Nemoto { 499e352953cSAtsushi Nemoto } 500e352953cSAtsushi Nemoto void (*txx9_prom_putchar)(char c) __initdata = null_prom_putchar; 501e352953cSAtsushi Nemoto 502e352953cSAtsushi Nemoto void __init prom_putchar(char c) 503e352953cSAtsushi Nemoto { 504e352953cSAtsushi Nemoto txx9_prom_putchar(c); 505e352953cSAtsushi Nemoto } 506e352953cSAtsushi Nemoto 507e352953cSAtsushi Nemoto static void __iomem *early_txx9_sio_port; 508e352953cSAtsushi Nemoto 509e352953cSAtsushi Nemoto static void __init early_txx9_sio_putchar(char c) 510e352953cSAtsushi Nemoto { 511e352953cSAtsushi Nemoto #define TXX9_SICISR 0x0c 512e352953cSAtsushi Nemoto #define TXX9_SITFIFO 0x1c 513e352953cSAtsushi Nemoto #define TXX9_SICISR_TXALS 0x00000002 514e352953cSAtsushi Nemoto while (!(__raw_readl(early_txx9_sio_port + TXX9_SICISR) & 515e352953cSAtsushi Nemoto TXX9_SICISR_TXALS)) 516e352953cSAtsushi Nemoto ; 517e352953cSAtsushi Nemoto __raw_writel(c, early_txx9_sio_port + TXX9_SITFIFO); 518e352953cSAtsushi Nemoto } 519e352953cSAtsushi Nemoto 520e352953cSAtsushi Nemoto void __init txx9_sio_putchar_init(unsigned long baseaddr) 521e352953cSAtsushi Nemoto { 522e352953cSAtsushi Nemoto early_txx9_sio_port = ioremap(baseaddr, 0x24); 523e352953cSAtsushi Nemoto txx9_prom_putchar = early_txx9_sio_putchar; 524e352953cSAtsushi Nemoto } 525e352953cSAtsushi Nemoto #endif /* CONFIG_EARLY_PRINTK */ 526e352953cSAtsushi Nemoto 527edcaf1a6SAtsushi Nemoto /* wrappers */ 528edcaf1a6SAtsushi Nemoto void __init plat_mem_setup(void) 529edcaf1a6SAtsushi Nemoto { 53094a4c329SAtsushi Nemoto ioport_resource.start = 0; 53194a4c329SAtsushi Nemoto ioport_resource.end = ~0UL; /* no limit */ 53294a4c329SAtsushi Nemoto iomem_resource.start = 0; 53394a4c329SAtsushi Nemoto iomem_resource.end = ~0UL; /* no limit */ 534a49297e8SAtsushi Nemoto 535a49297e8SAtsushi Nemoto /* fallback restart/halt routines */ 536a49297e8SAtsushi Nemoto _machine_restart = (void (*)(char *))txx9_machine_halt; 537a49297e8SAtsushi Nemoto _machine_halt = txx9_machine_halt; 538a49297e8SAtsushi Nemoto pm_power_off = txx9_machine_halt; 539a49297e8SAtsushi Nemoto 54007517529SAtsushi Nemoto #ifdef CONFIG_PCI 54107517529SAtsushi Nemoto pcibios_plat_setup = txx9_pcibios_setup; 54207517529SAtsushi Nemoto #endif 543edcaf1a6SAtsushi Nemoto txx9_board_vec->mem_setup(); 544edcaf1a6SAtsushi Nemoto } 545edcaf1a6SAtsushi Nemoto 546edcaf1a6SAtsushi Nemoto void __init arch_init_irq(void) 547edcaf1a6SAtsushi Nemoto { 548edcaf1a6SAtsushi Nemoto txx9_board_vec->irq_setup(); 549edcaf1a6SAtsushi Nemoto } 550edcaf1a6SAtsushi Nemoto 551edcaf1a6SAtsushi Nemoto void __init plat_time_init(void) 552edcaf1a6SAtsushi Nemoto { 5531374d084SAtsushi Nemoto #ifdef CONFIG_CPU_TX49XX 5541374d084SAtsushi Nemoto mips_hpt_frequency = txx9_cpu_clock / 2; 5551374d084SAtsushi Nemoto #endif 556edcaf1a6SAtsushi Nemoto txx9_board_vec->time_init(); 557edcaf1a6SAtsushi Nemoto } 558edcaf1a6SAtsushi Nemoto 559edcaf1a6SAtsushi Nemoto static int __init _txx9_arch_init(void) 560edcaf1a6SAtsushi Nemoto { 561edcaf1a6SAtsushi Nemoto if (txx9_board_vec->arch_init) 562edcaf1a6SAtsushi Nemoto txx9_board_vec->arch_init(); 563edcaf1a6SAtsushi Nemoto return 0; 564edcaf1a6SAtsushi Nemoto } 565edcaf1a6SAtsushi Nemoto arch_initcall(_txx9_arch_init); 566edcaf1a6SAtsushi Nemoto 567edcaf1a6SAtsushi Nemoto static int __init _txx9_device_init(void) 568edcaf1a6SAtsushi Nemoto { 569edcaf1a6SAtsushi Nemoto if (txx9_board_vec->device_init) 570edcaf1a6SAtsushi Nemoto txx9_board_vec->device_init(); 571edcaf1a6SAtsushi Nemoto return 0; 572edcaf1a6SAtsushi Nemoto } 573edcaf1a6SAtsushi Nemoto device_initcall(_txx9_device_init); 574edcaf1a6SAtsushi Nemoto 575edcaf1a6SAtsushi Nemoto int (*txx9_irq_dispatch)(int pending); 576edcaf1a6SAtsushi Nemoto asmlinkage void plat_irq_dispatch(void) 577edcaf1a6SAtsushi Nemoto { 578edcaf1a6SAtsushi Nemoto int pending = read_c0_status() & read_c0_cause() & ST0_IM; 579edcaf1a6SAtsushi Nemoto int irq = txx9_irq_dispatch(pending); 580edcaf1a6SAtsushi Nemoto 581edcaf1a6SAtsushi Nemoto if (likely(irq >= 0)) 582edcaf1a6SAtsushi Nemoto do_IRQ(irq); 583edcaf1a6SAtsushi Nemoto else 584edcaf1a6SAtsushi Nemoto spurious_interrupt(); 585edcaf1a6SAtsushi Nemoto } 5864c642f3fSAtsushi Nemoto 5874c642f3fSAtsushi Nemoto /* see include/asm-mips/mach-tx39xx/mangle-port.h, for example. */ 5884c642f3fSAtsushi Nemoto #ifdef NEEDS_TXX9_SWIZZLE_ADDR_B 5894c642f3fSAtsushi Nemoto static unsigned long __swizzle_addr_none(unsigned long port) 5904c642f3fSAtsushi Nemoto { 5914c642f3fSAtsushi Nemoto return port; 5924c642f3fSAtsushi Nemoto } 5934c642f3fSAtsushi Nemoto unsigned long (*__swizzle_addr_b)(unsigned long port) = __swizzle_addr_none; 5944c642f3fSAtsushi Nemoto EXPORT_SYMBOL(__swizzle_addr_b); 5954c642f3fSAtsushi Nemoto #endif 596