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> 2551f607c7SAtsushi Nemoto #include <linux/mtd/physmap.h> 26*ae027eadSAtsushi Nemoto #include <linux/leds.h> 27edcaf1a6SAtsushi Nemoto #include <asm/bootinfo.h> 28e0eb7307SAtsushi Nemoto #include <asm/time.h> 29a49297e8SAtsushi Nemoto #include <asm/reboot.h> 30d10e025fSAtsushi Nemoto #include <asm/r4kcache.h> 3189d63fe1SAtsushi Nemoto #include <asm/txx9/generic.h> 3207517529SAtsushi Nemoto #include <asm/txx9/pci.h> 33496a3b5cSAtsushi Nemoto #include <asm/txx9tmr.h> 34edcaf1a6SAtsushi Nemoto #ifdef CONFIG_CPU_TX49XX 35edcaf1a6SAtsushi Nemoto #include <asm/txx9/tx4938.h> 36edcaf1a6SAtsushi Nemoto #endif 3789d63fe1SAtsushi Nemoto 3889d63fe1SAtsushi Nemoto /* EBUSC settings of TX4927, etc. */ 3989d63fe1SAtsushi Nemoto struct resource txx9_ce_res[8]; 4089d63fe1SAtsushi Nemoto static char txx9_ce_res_name[8][4]; /* "CEn" */ 4189d63fe1SAtsushi Nemoto 4289d63fe1SAtsushi Nemoto /* pcode, internal register */ 4394a4c329SAtsushi Nemoto unsigned int txx9_pcode; 4489d63fe1SAtsushi Nemoto char txx9_pcode_str[8]; 4589d63fe1SAtsushi Nemoto static struct resource txx9_reg_res = { 4689d63fe1SAtsushi Nemoto .name = txx9_pcode_str, 4789d63fe1SAtsushi Nemoto .flags = IORESOURCE_MEM, 4889d63fe1SAtsushi Nemoto }; 4989d63fe1SAtsushi Nemoto void __init 5089d63fe1SAtsushi Nemoto txx9_reg_res_init(unsigned int pcode, unsigned long base, unsigned long size) 5189d63fe1SAtsushi Nemoto { 5289d63fe1SAtsushi Nemoto int i; 5389d63fe1SAtsushi Nemoto 5489d63fe1SAtsushi Nemoto for (i = 0; i < ARRAY_SIZE(txx9_ce_res); i++) { 5589d63fe1SAtsushi Nemoto sprintf(txx9_ce_res_name[i], "CE%d", i); 5689d63fe1SAtsushi Nemoto txx9_ce_res[i].flags = IORESOURCE_MEM; 5789d63fe1SAtsushi Nemoto txx9_ce_res[i].name = txx9_ce_res_name[i]; 5889d63fe1SAtsushi Nemoto } 5989d63fe1SAtsushi Nemoto 60073828d0SAtsushi Nemoto txx9_pcode = pcode; 6189d63fe1SAtsushi Nemoto sprintf(txx9_pcode_str, "TX%x", pcode); 6289d63fe1SAtsushi Nemoto if (base) { 6389d63fe1SAtsushi Nemoto txx9_reg_res.start = base & 0xfffffffffULL; 6489d63fe1SAtsushi Nemoto txx9_reg_res.end = (base & 0xfffffffffULL) + (size - 1); 6589d63fe1SAtsushi Nemoto request_resource(&iomem_resource, &txx9_reg_res); 6689d63fe1SAtsushi Nemoto } 6789d63fe1SAtsushi Nemoto } 6889d63fe1SAtsushi Nemoto 6989d63fe1SAtsushi Nemoto /* clocks */ 7089d63fe1SAtsushi Nemoto unsigned int txx9_master_clock; 7189d63fe1SAtsushi Nemoto unsigned int txx9_cpu_clock; 7289d63fe1SAtsushi Nemoto unsigned int txx9_gbus_clock; 73edcaf1a6SAtsushi Nemoto 74c7b95bcbSAtsushi Nemoto #ifdef CONFIG_CPU_TX39XX 75c7b95bcbSAtsushi Nemoto /* don't enable by default - see errata */ 76c7b95bcbSAtsushi Nemoto int txx9_ccfg_toeon __initdata; 77c7b95bcbSAtsushi Nemoto #else 7894a4c329SAtsushi Nemoto int txx9_ccfg_toeon __initdata = 1; 79c7b95bcbSAtsushi Nemoto #endif 80edcaf1a6SAtsushi Nemoto 81edcaf1a6SAtsushi Nemoto /* Minimum CLK support */ 82edcaf1a6SAtsushi Nemoto 83edcaf1a6SAtsushi Nemoto struct clk *clk_get(struct device *dev, const char *id) 84edcaf1a6SAtsushi Nemoto { 85edcaf1a6SAtsushi Nemoto if (!strcmp(id, "spi-baseclk")) 8694a4c329SAtsushi Nemoto return (struct clk *)((unsigned long)txx9_gbus_clock / 2 / 4); 87edcaf1a6SAtsushi Nemoto if (!strcmp(id, "imbus_clk")) 8894a4c329SAtsushi Nemoto return (struct clk *)((unsigned long)txx9_gbus_clock / 2); 89edcaf1a6SAtsushi Nemoto return ERR_PTR(-ENOENT); 90edcaf1a6SAtsushi Nemoto } 91edcaf1a6SAtsushi Nemoto EXPORT_SYMBOL(clk_get); 92edcaf1a6SAtsushi Nemoto 93edcaf1a6SAtsushi Nemoto int clk_enable(struct clk *clk) 94edcaf1a6SAtsushi Nemoto { 95edcaf1a6SAtsushi Nemoto return 0; 96edcaf1a6SAtsushi Nemoto } 97edcaf1a6SAtsushi Nemoto EXPORT_SYMBOL(clk_enable); 98edcaf1a6SAtsushi Nemoto 99edcaf1a6SAtsushi Nemoto void clk_disable(struct clk *clk) 100edcaf1a6SAtsushi Nemoto { 101edcaf1a6SAtsushi Nemoto } 102edcaf1a6SAtsushi Nemoto EXPORT_SYMBOL(clk_disable); 103edcaf1a6SAtsushi Nemoto 104edcaf1a6SAtsushi Nemoto unsigned long clk_get_rate(struct clk *clk) 105edcaf1a6SAtsushi Nemoto { 106edcaf1a6SAtsushi Nemoto return (unsigned long)clk; 107edcaf1a6SAtsushi Nemoto } 108edcaf1a6SAtsushi Nemoto EXPORT_SYMBOL(clk_get_rate); 109edcaf1a6SAtsushi Nemoto 110edcaf1a6SAtsushi Nemoto void clk_put(struct clk *clk) 111edcaf1a6SAtsushi Nemoto { 112edcaf1a6SAtsushi Nemoto } 113edcaf1a6SAtsushi Nemoto EXPORT_SYMBOL(clk_put); 114edcaf1a6SAtsushi Nemoto 1158d795f2aSAtsushi Nemoto /* GPIO support */ 1168d795f2aSAtsushi Nemoto 1178d795f2aSAtsushi Nemoto #ifdef CONFIG_GENERIC_GPIO 1188d795f2aSAtsushi Nemoto int gpio_to_irq(unsigned gpio) 1198d795f2aSAtsushi Nemoto { 1208d795f2aSAtsushi Nemoto return -EINVAL; 1218d795f2aSAtsushi Nemoto } 1228d795f2aSAtsushi Nemoto EXPORT_SYMBOL(gpio_to_irq); 1238d795f2aSAtsushi Nemoto 1248d795f2aSAtsushi Nemoto int irq_to_gpio(unsigned irq) 1258d795f2aSAtsushi Nemoto { 1268d795f2aSAtsushi Nemoto return -EINVAL; 1278d795f2aSAtsushi Nemoto } 1288d795f2aSAtsushi Nemoto EXPORT_SYMBOL(irq_to_gpio); 1298d795f2aSAtsushi Nemoto #endif 1308d795f2aSAtsushi Nemoto 131860e546cSAtsushi Nemoto #define BOARD_VEC(board) extern struct txx9_board_vec board; 132860e546cSAtsushi Nemoto #include <asm/txx9/boards.h> 133860e546cSAtsushi Nemoto #undef BOARD_VEC 134edcaf1a6SAtsushi Nemoto 135edcaf1a6SAtsushi Nemoto struct txx9_board_vec *txx9_board_vec __initdata; 136edcaf1a6SAtsushi Nemoto static char txx9_system_type[32]; 137edcaf1a6SAtsushi Nemoto 138860e546cSAtsushi Nemoto static struct txx9_board_vec *board_vecs[] __initdata = { 139860e546cSAtsushi Nemoto #define BOARD_VEC(board) &board, 140860e546cSAtsushi Nemoto #include <asm/txx9/boards.h> 141860e546cSAtsushi Nemoto #undef BOARD_VEC 142860e546cSAtsushi Nemoto }; 143860e546cSAtsushi Nemoto 144860e546cSAtsushi Nemoto static struct txx9_board_vec *__init find_board_byname(const char *name) 145860e546cSAtsushi Nemoto { 146860e546cSAtsushi Nemoto int i; 147860e546cSAtsushi Nemoto 148860e546cSAtsushi Nemoto /* search board_vecs table */ 149860e546cSAtsushi Nemoto for (i = 0; i < ARRAY_SIZE(board_vecs); i++) { 150860e546cSAtsushi Nemoto if (strstr(board_vecs[i]->system, name)) 151860e546cSAtsushi Nemoto return board_vecs[i]; 152860e546cSAtsushi Nemoto } 153860e546cSAtsushi Nemoto return NULL; 154860e546cSAtsushi Nemoto } 155860e546cSAtsushi Nemoto 156e0dfb20cSAtsushi Nemoto static void __init prom_init_cmdline(void) 157edcaf1a6SAtsushi Nemoto { 158edcaf1a6SAtsushi Nemoto int argc = (int)fw_arg0; 159e0dfb20cSAtsushi Nemoto int *argv32 = (int *)fw_arg1; 160edcaf1a6SAtsushi Nemoto int i; /* Always ignore the "-c" at argv[0] */ 161e0dfb20cSAtsushi Nemoto char builtin[CL_SIZE]; 162edcaf1a6SAtsushi Nemoto 163edcaf1a6SAtsushi Nemoto /* ignore all built-in args if any f/w args given */ 164e0dfb20cSAtsushi Nemoto /* 165e0dfb20cSAtsushi Nemoto * But if built-in strings was started with '+', append them 166e0dfb20cSAtsushi Nemoto * to command line args. If built-in was started with '-', 167e0dfb20cSAtsushi Nemoto * ignore all f/w args. 168e0dfb20cSAtsushi Nemoto */ 169e0dfb20cSAtsushi Nemoto builtin[0] = '\0'; 170e0dfb20cSAtsushi Nemoto if (arcs_cmdline[0] == '+') 171e0dfb20cSAtsushi Nemoto strcpy(builtin, arcs_cmdline + 1); 172e0dfb20cSAtsushi Nemoto else if (arcs_cmdline[0] == '-') { 173e0dfb20cSAtsushi Nemoto strcpy(builtin, arcs_cmdline + 1); 174e0dfb20cSAtsushi Nemoto argc = 0; 175e0dfb20cSAtsushi Nemoto } else if (argc <= 1) 176e0dfb20cSAtsushi Nemoto strcpy(builtin, arcs_cmdline); 177e0dfb20cSAtsushi Nemoto arcs_cmdline[0] = '\0'; 178edcaf1a6SAtsushi Nemoto 179edcaf1a6SAtsushi Nemoto for (i = 1; i < argc; i++) { 180e0dfb20cSAtsushi Nemoto char *str = (char *)(long)argv32[i]; 181edcaf1a6SAtsushi Nemoto if (i != 1) 182edcaf1a6SAtsushi Nemoto strcat(arcs_cmdline, " "); 183e0dfb20cSAtsushi Nemoto if (strchr(str, ' ')) { 184e0dfb20cSAtsushi Nemoto strcat(arcs_cmdline, "\""); 185e0dfb20cSAtsushi Nemoto strcat(arcs_cmdline, str); 186e0dfb20cSAtsushi Nemoto strcat(arcs_cmdline, "\""); 187e0dfb20cSAtsushi Nemoto } else 188e0dfb20cSAtsushi Nemoto strcat(arcs_cmdline, str); 189e0dfb20cSAtsushi Nemoto } 190e0dfb20cSAtsushi Nemoto /* append saved builtin args */ 191e0dfb20cSAtsushi Nemoto if (builtin[0]) { 192e0dfb20cSAtsushi Nemoto if (arcs_cmdline[0]) 193e0dfb20cSAtsushi Nemoto strcat(arcs_cmdline, " "); 194e0dfb20cSAtsushi Nemoto strcat(arcs_cmdline, builtin); 195edcaf1a6SAtsushi Nemoto } 196edcaf1a6SAtsushi Nemoto } 197edcaf1a6SAtsushi Nemoto 198d10e025fSAtsushi Nemoto static int txx9_ic_disable __initdata; 199d10e025fSAtsushi Nemoto static int txx9_dc_disable __initdata; 200d10e025fSAtsushi Nemoto 201d10e025fSAtsushi Nemoto #if defined(CONFIG_CPU_TX49XX) 202d10e025fSAtsushi Nemoto /* flush all cache on very early stage (before 4k_cache_init) */ 203d10e025fSAtsushi Nemoto static void __init early_flush_dcache(void) 204d10e025fSAtsushi Nemoto { 205d10e025fSAtsushi Nemoto unsigned int conf = read_c0_config(); 206d10e025fSAtsushi Nemoto unsigned int dc_size = 1 << (12 + ((conf & CONF_DC) >> 6)); 207d10e025fSAtsushi Nemoto unsigned int linesz = 32; 208d10e025fSAtsushi Nemoto unsigned long addr, end; 209d10e025fSAtsushi Nemoto 210d10e025fSAtsushi Nemoto end = INDEX_BASE + dc_size / 4; 211d10e025fSAtsushi Nemoto /* 4way, waybit=0 */ 212d10e025fSAtsushi Nemoto for (addr = INDEX_BASE; addr < end; addr += linesz) { 213d10e025fSAtsushi Nemoto cache_op(Index_Writeback_Inv_D, addr | 0); 214d10e025fSAtsushi Nemoto cache_op(Index_Writeback_Inv_D, addr | 1); 215d10e025fSAtsushi Nemoto cache_op(Index_Writeback_Inv_D, addr | 2); 216d10e025fSAtsushi Nemoto cache_op(Index_Writeback_Inv_D, addr | 3); 217d10e025fSAtsushi Nemoto } 218d10e025fSAtsushi Nemoto } 219d10e025fSAtsushi Nemoto 220d10e025fSAtsushi Nemoto static void __init txx9_cache_fixup(void) 221d10e025fSAtsushi Nemoto { 222d10e025fSAtsushi Nemoto unsigned int conf; 223d10e025fSAtsushi Nemoto 224d10e025fSAtsushi Nemoto conf = read_c0_config(); 225d10e025fSAtsushi Nemoto /* flush and disable */ 226d10e025fSAtsushi Nemoto if (txx9_ic_disable) { 227d10e025fSAtsushi Nemoto conf |= TX49_CONF_IC; 228d10e025fSAtsushi Nemoto write_c0_config(conf); 229d10e025fSAtsushi Nemoto } 230d10e025fSAtsushi Nemoto if (txx9_dc_disable) { 231d10e025fSAtsushi Nemoto early_flush_dcache(); 232d10e025fSAtsushi Nemoto conf |= TX49_CONF_DC; 233d10e025fSAtsushi Nemoto write_c0_config(conf); 234d10e025fSAtsushi Nemoto } 235d10e025fSAtsushi Nemoto 236d10e025fSAtsushi Nemoto /* enable cache */ 237d10e025fSAtsushi Nemoto conf = read_c0_config(); 238d10e025fSAtsushi Nemoto if (!txx9_ic_disable) 239d10e025fSAtsushi Nemoto conf &= ~TX49_CONF_IC; 240d10e025fSAtsushi Nemoto if (!txx9_dc_disable) 241d10e025fSAtsushi Nemoto conf &= ~TX49_CONF_DC; 242d10e025fSAtsushi Nemoto write_c0_config(conf); 243d10e025fSAtsushi Nemoto 244d10e025fSAtsushi Nemoto if (conf & TX49_CONF_IC) 245d10e025fSAtsushi Nemoto pr_info("TX49XX I-Cache disabled.\n"); 246d10e025fSAtsushi Nemoto if (conf & TX49_CONF_DC) 247d10e025fSAtsushi Nemoto pr_info("TX49XX D-Cache disabled.\n"); 248d10e025fSAtsushi Nemoto } 249d10e025fSAtsushi Nemoto #elif defined(CONFIG_CPU_TX39XX) 250d10e025fSAtsushi Nemoto /* flush all cache on very early stage (before tx39_cache_init) */ 251d10e025fSAtsushi Nemoto static void __init early_flush_dcache(void) 252d10e025fSAtsushi Nemoto { 253d10e025fSAtsushi Nemoto unsigned int conf = read_c0_config(); 254d10e025fSAtsushi Nemoto unsigned int dc_size = 1 << (10 + ((conf & TX39_CONF_DCS_MASK) >> 255d10e025fSAtsushi Nemoto TX39_CONF_DCS_SHIFT)); 256d10e025fSAtsushi Nemoto unsigned int linesz = 16; 257d10e025fSAtsushi Nemoto unsigned long addr, end; 258d10e025fSAtsushi Nemoto 259d10e025fSAtsushi Nemoto end = INDEX_BASE + dc_size / 2; 260d10e025fSAtsushi Nemoto /* 2way, waybit=0 */ 261d10e025fSAtsushi Nemoto for (addr = INDEX_BASE; addr < end; addr += linesz) { 262d10e025fSAtsushi Nemoto cache_op(Index_Writeback_Inv_D, addr | 0); 263d10e025fSAtsushi Nemoto cache_op(Index_Writeback_Inv_D, addr | 1); 264d10e025fSAtsushi Nemoto } 265d10e025fSAtsushi Nemoto } 266d10e025fSAtsushi Nemoto 267d10e025fSAtsushi Nemoto static void __init txx9_cache_fixup(void) 268d10e025fSAtsushi Nemoto { 269d10e025fSAtsushi Nemoto unsigned int conf; 270d10e025fSAtsushi Nemoto 271d10e025fSAtsushi Nemoto conf = read_c0_config(); 272d10e025fSAtsushi Nemoto /* flush and disable */ 273d10e025fSAtsushi Nemoto if (txx9_ic_disable) { 274d10e025fSAtsushi Nemoto conf &= ~TX39_CONF_ICE; 275d10e025fSAtsushi Nemoto write_c0_config(conf); 276d10e025fSAtsushi Nemoto } 277d10e025fSAtsushi Nemoto if (txx9_dc_disable) { 278d10e025fSAtsushi Nemoto early_flush_dcache(); 279d10e025fSAtsushi Nemoto conf &= ~TX39_CONF_DCE; 280d10e025fSAtsushi Nemoto write_c0_config(conf); 281d10e025fSAtsushi Nemoto } 282d10e025fSAtsushi Nemoto 283d10e025fSAtsushi Nemoto /* enable cache */ 284d10e025fSAtsushi Nemoto conf = read_c0_config(); 285d10e025fSAtsushi Nemoto if (!txx9_ic_disable) 286d10e025fSAtsushi Nemoto conf |= TX39_CONF_ICE; 287d10e025fSAtsushi Nemoto if (!txx9_dc_disable) 288d10e025fSAtsushi Nemoto conf |= TX39_CONF_DCE; 289d10e025fSAtsushi Nemoto write_c0_config(conf); 290d10e025fSAtsushi Nemoto 291d10e025fSAtsushi Nemoto if (!(conf & TX39_CONF_ICE)) 292d10e025fSAtsushi Nemoto pr_info("TX39XX I-Cache disabled.\n"); 293d10e025fSAtsushi Nemoto if (!(conf & TX39_CONF_DCE)) 294d10e025fSAtsushi Nemoto pr_info("TX39XX D-Cache disabled.\n"); 295d10e025fSAtsushi Nemoto } 296d10e025fSAtsushi Nemoto #else 297d10e025fSAtsushi Nemoto static inline void txx9_cache_fixup(void) 298d10e025fSAtsushi Nemoto { 299d10e025fSAtsushi Nemoto } 300d10e025fSAtsushi Nemoto #endif 301d10e025fSAtsushi Nemoto 302860e546cSAtsushi Nemoto static void __init preprocess_cmdline(void) 303edcaf1a6SAtsushi Nemoto { 304860e546cSAtsushi Nemoto char cmdline[CL_SIZE]; 305860e546cSAtsushi Nemoto char *s; 306860e546cSAtsushi Nemoto 307860e546cSAtsushi Nemoto strcpy(cmdline, arcs_cmdline); 308860e546cSAtsushi Nemoto s = cmdline; 309860e546cSAtsushi Nemoto arcs_cmdline[0] = '\0'; 310860e546cSAtsushi Nemoto while (s && *s) { 311860e546cSAtsushi Nemoto char *str = strsep(&s, " "); 312860e546cSAtsushi Nemoto if (strncmp(str, "board=", 6) == 0) { 313860e546cSAtsushi Nemoto txx9_board_vec = find_board_byname(str + 6); 314860e546cSAtsushi Nemoto continue; 315860e546cSAtsushi Nemoto } else if (strncmp(str, "masterclk=", 10) == 0) { 316860e546cSAtsushi Nemoto unsigned long val; 317860e546cSAtsushi Nemoto if (strict_strtoul(str + 10, 10, &val) == 0) 318860e546cSAtsushi Nemoto txx9_master_clock = val; 319860e546cSAtsushi Nemoto continue; 320d10e025fSAtsushi Nemoto } else if (strcmp(str, "icdisable") == 0) { 321d10e025fSAtsushi Nemoto txx9_ic_disable = 1; 322d10e025fSAtsushi Nemoto continue; 323d10e025fSAtsushi Nemoto } else if (strcmp(str, "dcdisable") == 0) { 324d10e025fSAtsushi Nemoto txx9_dc_disable = 1; 325d10e025fSAtsushi Nemoto continue; 326c7b95bcbSAtsushi Nemoto } else if (strcmp(str, "toeoff") == 0) { 327c7b95bcbSAtsushi Nemoto txx9_ccfg_toeon = 0; 328c7b95bcbSAtsushi Nemoto continue; 329c7b95bcbSAtsushi Nemoto } else if (strcmp(str, "toeon") == 0) { 330c7b95bcbSAtsushi Nemoto txx9_ccfg_toeon = 1; 331c7b95bcbSAtsushi Nemoto continue; 332860e546cSAtsushi Nemoto } 333860e546cSAtsushi Nemoto if (arcs_cmdline[0]) 334860e546cSAtsushi Nemoto strcat(arcs_cmdline, " "); 335860e546cSAtsushi Nemoto strcat(arcs_cmdline, str); 336860e546cSAtsushi Nemoto } 337d10e025fSAtsushi Nemoto 338d10e025fSAtsushi Nemoto txx9_cache_fixup(); 339860e546cSAtsushi Nemoto } 340860e546cSAtsushi Nemoto 341860e546cSAtsushi Nemoto static void __init select_board(void) 342860e546cSAtsushi Nemoto { 343860e546cSAtsushi Nemoto const char *envstr; 344860e546cSAtsushi Nemoto 345860e546cSAtsushi Nemoto /* first, determine by "board=" argument in preprocess_cmdline() */ 346860e546cSAtsushi Nemoto if (txx9_board_vec) 347860e546cSAtsushi Nemoto return; 348860e546cSAtsushi Nemoto /* next, determine by "board" envvar */ 349860e546cSAtsushi Nemoto envstr = prom_getenv("board"); 350860e546cSAtsushi Nemoto if (envstr) { 351860e546cSAtsushi Nemoto txx9_board_vec = find_board_byname(envstr); 352860e546cSAtsushi Nemoto if (txx9_board_vec) 353860e546cSAtsushi Nemoto return; 354860e546cSAtsushi Nemoto } 355860e546cSAtsushi Nemoto 356860e546cSAtsushi Nemoto /* select "default" board */ 357edcaf1a6SAtsushi Nemoto #ifdef CONFIG_CPU_TX39XX 3587a1fdf19SYoichi Yuasa txx9_board_vec = &jmr3927_vec; 359edcaf1a6SAtsushi Nemoto #endif 360edcaf1a6SAtsushi Nemoto #ifdef CONFIG_CPU_TX49XX 361edcaf1a6SAtsushi Nemoto switch (TX4938_REV_PCODE()) { 3628d795f2aSAtsushi Nemoto #ifdef CONFIG_TOSHIBA_RBTX4927 363edcaf1a6SAtsushi Nemoto case 0x4927: 3647a1fdf19SYoichi Yuasa txx9_board_vec = &rbtx4927_vec; 365edcaf1a6SAtsushi Nemoto break; 366edcaf1a6SAtsushi Nemoto case 0x4937: 3677a1fdf19SYoichi Yuasa txx9_board_vec = &rbtx4937_vec; 368edcaf1a6SAtsushi Nemoto break; 3698d795f2aSAtsushi Nemoto #endif 3708d795f2aSAtsushi Nemoto #ifdef CONFIG_TOSHIBA_RBTX4938 371edcaf1a6SAtsushi Nemoto case 0x4938: 3727a1fdf19SYoichi Yuasa txx9_board_vec = &rbtx4938_vec; 373edcaf1a6SAtsushi Nemoto break; 3748d795f2aSAtsushi Nemoto #endif 375edcaf1a6SAtsushi Nemoto } 376edcaf1a6SAtsushi Nemoto #endif 377860e546cSAtsushi Nemoto } 378860e546cSAtsushi Nemoto 379860e546cSAtsushi Nemoto void __init prom_init(void) 380860e546cSAtsushi Nemoto { 381860e546cSAtsushi Nemoto prom_init_cmdline(); 382860e546cSAtsushi Nemoto preprocess_cmdline(); 383860e546cSAtsushi Nemoto select_board(); 3847a1fdf19SYoichi Yuasa 385edcaf1a6SAtsushi Nemoto strcpy(txx9_system_type, txx9_board_vec->system); 3867a1fdf19SYoichi Yuasa 3877b226094SAtsushi Nemoto txx9_board_vec->prom_init(); 388edcaf1a6SAtsushi Nemoto } 389edcaf1a6SAtsushi Nemoto 390edcaf1a6SAtsushi Nemoto void __init prom_free_prom_memory(void) 391edcaf1a6SAtsushi Nemoto { 392edcaf1a6SAtsushi Nemoto } 393edcaf1a6SAtsushi Nemoto 394edcaf1a6SAtsushi Nemoto const char *get_system_type(void) 395edcaf1a6SAtsushi Nemoto { 396edcaf1a6SAtsushi Nemoto return txx9_system_type; 397edcaf1a6SAtsushi Nemoto } 398edcaf1a6SAtsushi Nemoto 399edcaf1a6SAtsushi Nemoto char * __init prom_getcmdline(void) 400edcaf1a6SAtsushi Nemoto { 401edcaf1a6SAtsushi Nemoto return &(arcs_cmdline[0]); 402edcaf1a6SAtsushi Nemoto } 403edcaf1a6SAtsushi Nemoto 404265b89dbSAtsushi Nemoto const char *__init prom_getenv(const char *name) 405265b89dbSAtsushi Nemoto { 406265b89dbSAtsushi Nemoto const s32 *str = (const s32 *)fw_arg2; 407265b89dbSAtsushi Nemoto 408265b89dbSAtsushi Nemoto if (!str) 409265b89dbSAtsushi Nemoto return NULL; 410265b89dbSAtsushi Nemoto /* YAMON style ("name", "value" pairs) */ 411265b89dbSAtsushi Nemoto while (str[0] && str[1]) { 412265b89dbSAtsushi Nemoto if (!strcmp((const char *)(unsigned long)str[0], name)) 413265b89dbSAtsushi Nemoto return (const char *)(unsigned long)str[1]; 414265b89dbSAtsushi Nemoto str += 2; 415265b89dbSAtsushi Nemoto } 416265b89dbSAtsushi Nemoto return NULL; 417265b89dbSAtsushi Nemoto } 418265b89dbSAtsushi Nemoto 419a49297e8SAtsushi Nemoto static void __noreturn txx9_machine_halt(void) 420a49297e8SAtsushi Nemoto { 421a49297e8SAtsushi Nemoto local_irq_disable(); 422a49297e8SAtsushi Nemoto clear_c0_status(ST0_IM); 423a49297e8SAtsushi Nemoto while (1) { 424a49297e8SAtsushi Nemoto if (cpu_wait) { 425a49297e8SAtsushi Nemoto (*cpu_wait)(); 426a49297e8SAtsushi Nemoto if (cpu_has_counter) { 427a49297e8SAtsushi Nemoto /* 428a49297e8SAtsushi Nemoto * Clear counter interrupt while it 429a49297e8SAtsushi Nemoto * breaks WAIT instruction even if 430a49297e8SAtsushi Nemoto * masked. 431a49297e8SAtsushi Nemoto */ 432a49297e8SAtsushi Nemoto write_c0_compare(0); 433a49297e8SAtsushi Nemoto } 434a49297e8SAtsushi Nemoto } 435a49297e8SAtsushi Nemoto } 436a49297e8SAtsushi Nemoto } 437a49297e8SAtsushi Nemoto 43868314725SAtsushi Nemoto /* Watchdog support */ 43968314725SAtsushi Nemoto void __init txx9_wdt_init(unsigned long base) 44068314725SAtsushi Nemoto { 44168314725SAtsushi Nemoto struct resource res = { 44268314725SAtsushi Nemoto .start = base, 44368314725SAtsushi Nemoto .end = base + 0x100 - 1, 44468314725SAtsushi Nemoto .flags = IORESOURCE_MEM, 44568314725SAtsushi Nemoto }; 44668314725SAtsushi Nemoto platform_device_register_simple("txx9wdt", -1, &res, 1); 44768314725SAtsushi Nemoto } 44868314725SAtsushi Nemoto 449496a3b5cSAtsushi Nemoto void txx9_wdt_now(unsigned long base) 450496a3b5cSAtsushi Nemoto { 451496a3b5cSAtsushi Nemoto struct txx9_tmr_reg __iomem *tmrptr = 452496a3b5cSAtsushi Nemoto ioremap(base, sizeof(struct txx9_tmr_reg)); 453496a3b5cSAtsushi Nemoto /* disable watch dog timer */ 454496a3b5cSAtsushi Nemoto __raw_writel(TXx9_TMWTMR_WDIS | TXx9_TMWTMR_TWC, &tmrptr->wtmr); 455496a3b5cSAtsushi Nemoto __raw_writel(0, &tmrptr->tcr); 456496a3b5cSAtsushi Nemoto /* kick watchdog */ 457496a3b5cSAtsushi Nemoto __raw_writel(TXx9_TMWTMR_TWIE, &tmrptr->wtmr); 458496a3b5cSAtsushi Nemoto __raw_writel(1, &tmrptr->cpra); /* immediate */ 459496a3b5cSAtsushi Nemoto __raw_writel(TXx9_TMTCR_TCE | TXx9_TMTCR_CCDE | TXx9_TMTCR_TMODE_WDOG, 460496a3b5cSAtsushi Nemoto &tmrptr->tcr); 461496a3b5cSAtsushi Nemoto } 462496a3b5cSAtsushi Nemoto 463c49f91f5SAtsushi Nemoto /* SPI support */ 464c49f91f5SAtsushi Nemoto void __init txx9_spi_init(int busid, unsigned long base, int irq) 465c49f91f5SAtsushi Nemoto { 466c49f91f5SAtsushi Nemoto struct resource res[] = { 467c49f91f5SAtsushi Nemoto { 468c49f91f5SAtsushi Nemoto .start = base, 469c49f91f5SAtsushi Nemoto .end = base + 0x20 - 1, 470c49f91f5SAtsushi Nemoto .flags = IORESOURCE_MEM, 471c49f91f5SAtsushi Nemoto }, { 472c49f91f5SAtsushi Nemoto .start = irq, 473c49f91f5SAtsushi Nemoto .flags = IORESOURCE_IRQ, 474c49f91f5SAtsushi Nemoto }, 475c49f91f5SAtsushi Nemoto }; 476c49f91f5SAtsushi Nemoto platform_device_register_simple("spi_txx9", busid, 477c49f91f5SAtsushi Nemoto res, ARRAY_SIZE(res)); 478c49f91f5SAtsushi Nemoto } 479c49f91f5SAtsushi Nemoto 480c49f91f5SAtsushi Nemoto void __init txx9_ethaddr_init(unsigned int id, unsigned char *ethaddr) 481c49f91f5SAtsushi Nemoto { 482c49f91f5SAtsushi Nemoto struct platform_device *pdev = 483c49f91f5SAtsushi Nemoto platform_device_alloc("tc35815-mac", id); 484c49f91f5SAtsushi Nemoto if (!pdev || 485c49f91f5SAtsushi Nemoto platform_device_add_data(pdev, ethaddr, 6) || 486c49f91f5SAtsushi Nemoto platform_device_add(pdev)) 487c49f91f5SAtsushi Nemoto platform_device_put(pdev); 488c49f91f5SAtsushi Nemoto } 489c49f91f5SAtsushi Nemoto 4907779a5e0SAtsushi Nemoto void __init txx9_sio_init(unsigned long baseaddr, int irq, 4917779a5e0SAtsushi Nemoto unsigned int line, unsigned int sclk, int nocts) 4927779a5e0SAtsushi Nemoto { 4937779a5e0SAtsushi Nemoto #ifdef CONFIG_SERIAL_TXX9 4947779a5e0SAtsushi Nemoto struct uart_port req; 4957779a5e0SAtsushi Nemoto 4967779a5e0SAtsushi Nemoto memset(&req, 0, sizeof(req)); 4977779a5e0SAtsushi Nemoto req.line = line; 4987779a5e0SAtsushi Nemoto req.iotype = UPIO_MEM; 4997779a5e0SAtsushi Nemoto req.membase = ioremap(baseaddr, 0x24); 5007779a5e0SAtsushi Nemoto req.mapbase = baseaddr; 5017779a5e0SAtsushi Nemoto req.irq = irq; 5027779a5e0SAtsushi Nemoto if (!nocts) 5037779a5e0SAtsushi Nemoto req.flags |= UPF_BUGGY_UART /*HAVE_CTS_LINE*/; 5047779a5e0SAtsushi Nemoto if (sclk) { 5057779a5e0SAtsushi Nemoto req.flags |= UPF_MAGIC_MULTIPLIER /*USE_SCLK*/; 5067779a5e0SAtsushi Nemoto req.uartclk = sclk; 5077779a5e0SAtsushi Nemoto } else 5087779a5e0SAtsushi Nemoto req.uartclk = TXX9_IMCLK; 5097779a5e0SAtsushi Nemoto early_serial_txx9_setup(&req); 5107779a5e0SAtsushi Nemoto #endif /* CONFIG_SERIAL_TXX9 */ 5117779a5e0SAtsushi Nemoto } 5127779a5e0SAtsushi Nemoto 513e352953cSAtsushi Nemoto #ifdef CONFIG_EARLY_PRINTK 514e352953cSAtsushi Nemoto static void __init null_prom_putchar(char c) 515e352953cSAtsushi Nemoto { 516e352953cSAtsushi Nemoto } 517e352953cSAtsushi Nemoto void (*txx9_prom_putchar)(char c) __initdata = null_prom_putchar; 518e352953cSAtsushi Nemoto 519e352953cSAtsushi Nemoto void __init prom_putchar(char c) 520e352953cSAtsushi Nemoto { 521e352953cSAtsushi Nemoto txx9_prom_putchar(c); 522e352953cSAtsushi Nemoto } 523e352953cSAtsushi Nemoto 524e352953cSAtsushi Nemoto static void __iomem *early_txx9_sio_port; 525e352953cSAtsushi Nemoto 526e352953cSAtsushi Nemoto static void __init early_txx9_sio_putchar(char c) 527e352953cSAtsushi Nemoto { 528e352953cSAtsushi Nemoto #define TXX9_SICISR 0x0c 529e352953cSAtsushi Nemoto #define TXX9_SITFIFO 0x1c 530e352953cSAtsushi Nemoto #define TXX9_SICISR_TXALS 0x00000002 531e352953cSAtsushi Nemoto while (!(__raw_readl(early_txx9_sio_port + TXX9_SICISR) & 532e352953cSAtsushi Nemoto TXX9_SICISR_TXALS)) 533e352953cSAtsushi Nemoto ; 534e352953cSAtsushi Nemoto __raw_writel(c, early_txx9_sio_port + TXX9_SITFIFO); 535e352953cSAtsushi Nemoto } 536e352953cSAtsushi Nemoto 537e352953cSAtsushi Nemoto void __init txx9_sio_putchar_init(unsigned long baseaddr) 538e352953cSAtsushi Nemoto { 539e352953cSAtsushi Nemoto early_txx9_sio_port = ioremap(baseaddr, 0x24); 540e352953cSAtsushi Nemoto txx9_prom_putchar = early_txx9_sio_putchar; 541e352953cSAtsushi Nemoto } 542e352953cSAtsushi Nemoto #endif /* CONFIG_EARLY_PRINTK */ 543e352953cSAtsushi Nemoto 544edcaf1a6SAtsushi Nemoto /* wrappers */ 545edcaf1a6SAtsushi Nemoto void __init plat_mem_setup(void) 546edcaf1a6SAtsushi Nemoto { 54794a4c329SAtsushi Nemoto ioport_resource.start = 0; 54894a4c329SAtsushi Nemoto ioport_resource.end = ~0UL; /* no limit */ 54994a4c329SAtsushi Nemoto iomem_resource.start = 0; 55094a4c329SAtsushi Nemoto iomem_resource.end = ~0UL; /* no limit */ 551a49297e8SAtsushi Nemoto 552a49297e8SAtsushi Nemoto /* fallback restart/halt routines */ 553a49297e8SAtsushi Nemoto _machine_restart = (void (*)(char *))txx9_machine_halt; 554a49297e8SAtsushi Nemoto _machine_halt = txx9_machine_halt; 555a49297e8SAtsushi Nemoto pm_power_off = txx9_machine_halt; 556a49297e8SAtsushi Nemoto 55707517529SAtsushi Nemoto #ifdef CONFIG_PCI 55807517529SAtsushi Nemoto pcibios_plat_setup = txx9_pcibios_setup; 55907517529SAtsushi Nemoto #endif 560edcaf1a6SAtsushi Nemoto txx9_board_vec->mem_setup(); 561edcaf1a6SAtsushi Nemoto } 562edcaf1a6SAtsushi Nemoto 563edcaf1a6SAtsushi Nemoto void __init arch_init_irq(void) 564edcaf1a6SAtsushi Nemoto { 565edcaf1a6SAtsushi Nemoto txx9_board_vec->irq_setup(); 566edcaf1a6SAtsushi Nemoto } 567edcaf1a6SAtsushi Nemoto 568edcaf1a6SAtsushi Nemoto void __init plat_time_init(void) 569edcaf1a6SAtsushi Nemoto { 5701374d084SAtsushi Nemoto #ifdef CONFIG_CPU_TX49XX 5711374d084SAtsushi Nemoto mips_hpt_frequency = txx9_cpu_clock / 2; 5721374d084SAtsushi Nemoto #endif 573edcaf1a6SAtsushi Nemoto txx9_board_vec->time_init(); 574edcaf1a6SAtsushi Nemoto } 575edcaf1a6SAtsushi Nemoto 576edcaf1a6SAtsushi Nemoto static int __init _txx9_arch_init(void) 577edcaf1a6SAtsushi Nemoto { 578edcaf1a6SAtsushi Nemoto if (txx9_board_vec->arch_init) 579edcaf1a6SAtsushi Nemoto txx9_board_vec->arch_init(); 580edcaf1a6SAtsushi Nemoto return 0; 581edcaf1a6SAtsushi Nemoto } 582edcaf1a6SAtsushi Nemoto arch_initcall(_txx9_arch_init); 583edcaf1a6SAtsushi Nemoto 584edcaf1a6SAtsushi Nemoto static int __init _txx9_device_init(void) 585edcaf1a6SAtsushi Nemoto { 586edcaf1a6SAtsushi Nemoto if (txx9_board_vec->device_init) 587edcaf1a6SAtsushi Nemoto txx9_board_vec->device_init(); 588edcaf1a6SAtsushi Nemoto return 0; 589edcaf1a6SAtsushi Nemoto } 590edcaf1a6SAtsushi Nemoto device_initcall(_txx9_device_init); 591edcaf1a6SAtsushi Nemoto 592edcaf1a6SAtsushi Nemoto int (*txx9_irq_dispatch)(int pending); 593edcaf1a6SAtsushi Nemoto asmlinkage void plat_irq_dispatch(void) 594edcaf1a6SAtsushi Nemoto { 595edcaf1a6SAtsushi Nemoto int pending = read_c0_status() & read_c0_cause() & ST0_IM; 596edcaf1a6SAtsushi Nemoto int irq = txx9_irq_dispatch(pending); 597edcaf1a6SAtsushi Nemoto 598edcaf1a6SAtsushi Nemoto if (likely(irq >= 0)) 599edcaf1a6SAtsushi Nemoto do_IRQ(irq); 600edcaf1a6SAtsushi Nemoto else 601edcaf1a6SAtsushi Nemoto spurious_interrupt(); 602edcaf1a6SAtsushi Nemoto } 6034c642f3fSAtsushi Nemoto 6044c642f3fSAtsushi Nemoto /* see include/asm-mips/mach-tx39xx/mangle-port.h, for example. */ 6054c642f3fSAtsushi Nemoto #ifdef NEEDS_TXX9_SWIZZLE_ADDR_B 6064c642f3fSAtsushi Nemoto static unsigned long __swizzle_addr_none(unsigned long port) 6074c642f3fSAtsushi Nemoto { 6084c642f3fSAtsushi Nemoto return port; 6094c642f3fSAtsushi Nemoto } 6104c642f3fSAtsushi Nemoto unsigned long (*__swizzle_addr_b)(unsigned long port) = __swizzle_addr_none; 6114c642f3fSAtsushi Nemoto EXPORT_SYMBOL(__swizzle_addr_b); 6124c642f3fSAtsushi Nemoto #endif 61351f607c7SAtsushi Nemoto 61451f607c7SAtsushi Nemoto void __init txx9_physmap_flash_init(int no, unsigned long addr, 61551f607c7SAtsushi Nemoto unsigned long size, 61651f607c7SAtsushi Nemoto const struct physmap_flash_data *pdata) 61751f607c7SAtsushi Nemoto { 61851f607c7SAtsushi Nemoto #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE) 61951f607c7SAtsushi Nemoto struct resource res = { 62051f607c7SAtsushi Nemoto .start = addr, 62151f607c7SAtsushi Nemoto .end = addr + size - 1, 62251f607c7SAtsushi Nemoto .flags = IORESOURCE_MEM, 62351f607c7SAtsushi Nemoto }; 62451f607c7SAtsushi Nemoto struct platform_device *pdev; 62551f607c7SAtsushi Nemoto #ifdef CONFIG_MTD_PARTITIONS 62651f607c7SAtsushi Nemoto static struct mtd_partition parts[2]; 62751f607c7SAtsushi Nemoto struct physmap_flash_data pdata_part; 62851f607c7SAtsushi Nemoto 62951f607c7SAtsushi Nemoto /* If this area contained boot area, make separate partition */ 63051f607c7SAtsushi Nemoto if (pdata->nr_parts == 0 && !pdata->parts && 63151f607c7SAtsushi Nemoto addr < 0x1fc00000 && addr + size > 0x1fc00000 && 63251f607c7SAtsushi Nemoto !parts[0].name) { 63351f607c7SAtsushi Nemoto parts[0].name = "boot"; 63451f607c7SAtsushi Nemoto parts[0].offset = 0x1fc00000 - addr; 63551f607c7SAtsushi Nemoto parts[0].size = addr + size - 0x1fc00000; 63651f607c7SAtsushi Nemoto parts[1].name = "user"; 63751f607c7SAtsushi Nemoto parts[1].offset = 0; 63851f607c7SAtsushi Nemoto parts[1].size = 0x1fc00000 - addr; 63951f607c7SAtsushi Nemoto pdata_part = *pdata; 64051f607c7SAtsushi Nemoto pdata_part.nr_parts = ARRAY_SIZE(parts); 64151f607c7SAtsushi Nemoto pdata_part.parts = parts; 64251f607c7SAtsushi Nemoto pdata = &pdata_part; 64351f607c7SAtsushi Nemoto } 64451f607c7SAtsushi Nemoto #endif 64551f607c7SAtsushi Nemoto pdev = platform_device_alloc("physmap-flash", no); 64651f607c7SAtsushi Nemoto if (!pdev || 64751f607c7SAtsushi Nemoto platform_device_add_resources(pdev, &res, 1) || 64851f607c7SAtsushi Nemoto platform_device_add_data(pdev, pdata, sizeof(*pdata)) || 64951f607c7SAtsushi Nemoto platform_device_add(pdev)) 65051f607c7SAtsushi Nemoto platform_device_put(pdev); 65151f607c7SAtsushi Nemoto #endif 65251f607c7SAtsushi Nemoto } 653*ae027eadSAtsushi Nemoto 654*ae027eadSAtsushi Nemoto #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) 655*ae027eadSAtsushi Nemoto static DEFINE_SPINLOCK(txx9_iocled_lock); 656*ae027eadSAtsushi Nemoto 657*ae027eadSAtsushi Nemoto #define TXX9_IOCLED_MAXLEDS 8 658*ae027eadSAtsushi Nemoto 659*ae027eadSAtsushi Nemoto struct txx9_iocled_data { 660*ae027eadSAtsushi Nemoto struct gpio_chip chip; 661*ae027eadSAtsushi Nemoto u8 cur_val; 662*ae027eadSAtsushi Nemoto void __iomem *mmioaddr; 663*ae027eadSAtsushi Nemoto struct gpio_led_platform_data pdata; 664*ae027eadSAtsushi Nemoto struct gpio_led leds[TXX9_IOCLED_MAXLEDS]; 665*ae027eadSAtsushi Nemoto char names[TXX9_IOCLED_MAXLEDS][32]; 666*ae027eadSAtsushi Nemoto }; 667*ae027eadSAtsushi Nemoto 668*ae027eadSAtsushi Nemoto static int txx9_iocled_get(struct gpio_chip *chip, unsigned int offset) 669*ae027eadSAtsushi Nemoto { 670*ae027eadSAtsushi Nemoto struct txx9_iocled_data *data = 671*ae027eadSAtsushi Nemoto container_of(chip, struct txx9_iocled_data, chip); 672*ae027eadSAtsushi Nemoto return data->cur_val & (1 << offset); 673*ae027eadSAtsushi Nemoto } 674*ae027eadSAtsushi Nemoto 675*ae027eadSAtsushi Nemoto static void txx9_iocled_set(struct gpio_chip *chip, unsigned int offset, 676*ae027eadSAtsushi Nemoto int value) 677*ae027eadSAtsushi Nemoto { 678*ae027eadSAtsushi Nemoto struct txx9_iocled_data *data = 679*ae027eadSAtsushi Nemoto container_of(chip, struct txx9_iocled_data, chip); 680*ae027eadSAtsushi Nemoto unsigned long flags; 681*ae027eadSAtsushi Nemoto spin_lock_irqsave(&txx9_iocled_lock, flags); 682*ae027eadSAtsushi Nemoto if (value) 683*ae027eadSAtsushi Nemoto data->cur_val |= 1 << offset; 684*ae027eadSAtsushi Nemoto else 685*ae027eadSAtsushi Nemoto data->cur_val &= ~(1 << offset); 686*ae027eadSAtsushi Nemoto writeb(data->cur_val, data->mmioaddr); 687*ae027eadSAtsushi Nemoto mmiowb(); 688*ae027eadSAtsushi Nemoto spin_unlock_irqrestore(&txx9_iocled_lock, flags); 689*ae027eadSAtsushi Nemoto } 690*ae027eadSAtsushi Nemoto 691*ae027eadSAtsushi Nemoto static int txx9_iocled_dir_in(struct gpio_chip *chip, unsigned int offset) 692*ae027eadSAtsushi Nemoto { 693*ae027eadSAtsushi Nemoto return 0; 694*ae027eadSAtsushi Nemoto } 695*ae027eadSAtsushi Nemoto 696*ae027eadSAtsushi Nemoto static int txx9_iocled_dir_out(struct gpio_chip *chip, unsigned int offset, 697*ae027eadSAtsushi Nemoto int value) 698*ae027eadSAtsushi Nemoto { 699*ae027eadSAtsushi Nemoto txx9_iocled_set(chip, offset, value); 700*ae027eadSAtsushi Nemoto return 0; 701*ae027eadSAtsushi Nemoto } 702*ae027eadSAtsushi Nemoto 703*ae027eadSAtsushi Nemoto void __init txx9_iocled_init(unsigned long baseaddr, 704*ae027eadSAtsushi Nemoto int basenum, unsigned int num, int lowactive, 705*ae027eadSAtsushi Nemoto const char *color, char **deftriggers) 706*ae027eadSAtsushi Nemoto { 707*ae027eadSAtsushi Nemoto struct txx9_iocled_data *iocled; 708*ae027eadSAtsushi Nemoto struct platform_device *pdev; 709*ae027eadSAtsushi Nemoto int i; 710*ae027eadSAtsushi Nemoto static char *default_triggers[] __initdata = { 711*ae027eadSAtsushi Nemoto "heartbeat", 712*ae027eadSAtsushi Nemoto "ide-disk", 713*ae027eadSAtsushi Nemoto "nand-disk", 714*ae027eadSAtsushi Nemoto NULL, 715*ae027eadSAtsushi Nemoto }; 716*ae027eadSAtsushi Nemoto 717*ae027eadSAtsushi Nemoto if (!deftriggers) 718*ae027eadSAtsushi Nemoto deftriggers = default_triggers; 719*ae027eadSAtsushi Nemoto iocled = kzalloc(sizeof(*iocled), GFP_KERNEL); 720*ae027eadSAtsushi Nemoto if (!iocled) 721*ae027eadSAtsushi Nemoto return; 722*ae027eadSAtsushi Nemoto iocled->mmioaddr = ioremap(baseaddr, 1); 723*ae027eadSAtsushi Nemoto if (!iocled->mmioaddr) 724*ae027eadSAtsushi Nemoto return; 725*ae027eadSAtsushi Nemoto iocled->chip.get = txx9_iocled_get; 726*ae027eadSAtsushi Nemoto iocled->chip.set = txx9_iocled_set; 727*ae027eadSAtsushi Nemoto iocled->chip.direction_input = txx9_iocled_dir_in; 728*ae027eadSAtsushi Nemoto iocled->chip.direction_output = txx9_iocled_dir_out; 729*ae027eadSAtsushi Nemoto iocled->chip.label = "iocled"; 730*ae027eadSAtsushi Nemoto iocled->chip.base = basenum; 731*ae027eadSAtsushi Nemoto iocled->chip.ngpio = num; 732*ae027eadSAtsushi Nemoto if (gpiochip_add(&iocled->chip)) 733*ae027eadSAtsushi Nemoto return; 734*ae027eadSAtsushi Nemoto if (basenum < 0) 735*ae027eadSAtsushi Nemoto basenum = iocled->chip.base; 736*ae027eadSAtsushi Nemoto 737*ae027eadSAtsushi Nemoto pdev = platform_device_alloc("leds-gpio", basenum); 738*ae027eadSAtsushi Nemoto if (!pdev) 739*ae027eadSAtsushi Nemoto return; 740*ae027eadSAtsushi Nemoto iocled->pdata.num_leds = num; 741*ae027eadSAtsushi Nemoto iocled->pdata.leds = iocled->leds; 742*ae027eadSAtsushi Nemoto for (i = 0; i < num; i++) { 743*ae027eadSAtsushi Nemoto struct gpio_led *led = &iocled->leds[i]; 744*ae027eadSAtsushi Nemoto snprintf(iocled->names[i], sizeof(iocled->names[i]), 745*ae027eadSAtsushi Nemoto "iocled:%s:%u", color, i); 746*ae027eadSAtsushi Nemoto led->name = iocled->names[i]; 747*ae027eadSAtsushi Nemoto led->gpio = basenum + i; 748*ae027eadSAtsushi Nemoto led->active_low = lowactive; 749*ae027eadSAtsushi Nemoto if (deftriggers && *deftriggers) 750*ae027eadSAtsushi Nemoto led->default_trigger = *deftriggers++; 751*ae027eadSAtsushi Nemoto } 752*ae027eadSAtsushi Nemoto pdev->dev.platform_data = &iocled->pdata; 753*ae027eadSAtsushi Nemoto if (platform_device_add(pdev)) 754*ae027eadSAtsushi Nemoto platform_device_put(pdev); 755*ae027eadSAtsushi Nemoto } 756*ae027eadSAtsushi Nemoto #else /* CONFIG_LEDS_GPIO */ 757*ae027eadSAtsushi Nemoto void __init txx9_iocled_init(unsigned long baseaddr, 758*ae027eadSAtsushi Nemoto int basenum, unsigned int num, int lowactive, 759*ae027eadSAtsushi Nemoto const char *color, char **deftriggers) 760*ae027eadSAtsushi Nemoto { 761*ae027eadSAtsushi Nemoto } 762*ae027eadSAtsushi Nemoto #endif /* CONFIG_LEDS_GPIO */ 763