189d63fe1SAtsushi Nemoto /* 289d63fe1SAtsushi Nemoto * Based on linux/arch/mips/txx9/rbtx4938/setup.c, 389d63fe1SAtsushi Nemoto * and RBTX49xx patch from CELF patch archive. 489d63fe1SAtsushi Nemoto * 589d63fe1SAtsushi Nemoto * 2003-2005 (c) MontaVista Software, Inc. 689d63fe1SAtsushi Nemoto * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007 789d63fe1SAtsushi Nemoto * 889d63fe1SAtsushi Nemoto * This file is subject to the terms and conditions of the GNU General Public 989d63fe1SAtsushi Nemoto * License. See the file "COPYING" in the main directory of this archive 1089d63fe1SAtsushi Nemoto * for more details. 1189d63fe1SAtsushi Nemoto */ 1289d63fe1SAtsushi Nemoto #include <linux/init.h> 1389d63fe1SAtsushi Nemoto #include <linux/kernel.h> 1489d63fe1SAtsushi Nemoto #include <linux/types.h> 15edcaf1a6SAtsushi Nemoto #include <linux/interrupt.h> 16edcaf1a6SAtsushi Nemoto #include <linux/string.h> 17edcaf1a6SAtsushi Nemoto #include <linux/module.h> 18edcaf1a6SAtsushi Nemoto #include <linux/clk.h> 19edcaf1a6SAtsushi Nemoto #include <linux/err.h> 20e0eb7307SAtsushi Nemoto #include <linux/gpio.h> 2168314725SAtsushi Nemoto #include <linux/platform_device.h> 227779a5e0SAtsushi Nemoto #include <linux/serial_core.h> 2351f607c7SAtsushi Nemoto #include <linux/mtd/physmap.h> 24ae027eadSAtsushi Nemoto #include <linux/leds.h> 25269a3eb1SKay Sievers #include <linux/device.h> 265a0e3ad6STejun Heo #include <linux/slab.h> 27ca4d3e67SDavid Howells #include <linux/irq.h> 28edcaf1a6SAtsushi Nemoto #include <asm/bootinfo.h> 29bdc92d74SRalf Baechle #include <asm/idle.h> 30e0eb7307SAtsushi Nemoto #include <asm/time.h> 31a49297e8SAtsushi Nemoto #include <asm/reboot.h> 32d10e025fSAtsushi Nemoto #include <asm/r4kcache.h> 33b6263ff2SAtsushi Nemoto #include <asm/sections.h> 3489d63fe1SAtsushi Nemoto #include <asm/txx9/generic.h> 3507517529SAtsushi Nemoto #include <asm/txx9/pci.h> 36496a3b5cSAtsushi Nemoto #include <asm/txx9tmr.h> 37a591f5d3SAtsushi Nemoto #include <asm/txx9/ndfmc.h> 38f48c8c95SAtsushi Nemoto #include <asm/txx9/dmac.h> 39edcaf1a6SAtsushi Nemoto #ifdef CONFIG_CPU_TX49XX 40edcaf1a6SAtsushi Nemoto #include <asm/txx9/tx4938.h> 41edcaf1a6SAtsushi Nemoto #endif 4289d63fe1SAtsushi Nemoto 4389d63fe1SAtsushi Nemoto /* EBUSC settings of TX4927, etc. */ 4489d63fe1SAtsushi Nemoto struct resource txx9_ce_res[8]; 4589d63fe1SAtsushi Nemoto static char txx9_ce_res_name[8][4]; /* "CEn" */ 4689d63fe1SAtsushi Nemoto 4789d63fe1SAtsushi Nemoto /* pcode, internal register */ 4894a4c329SAtsushi Nemoto unsigned int txx9_pcode; 4989d63fe1SAtsushi Nemoto char txx9_pcode_str[8]; 5089d63fe1SAtsushi Nemoto static struct resource txx9_reg_res = { 5189d63fe1SAtsushi Nemoto .name = txx9_pcode_str, 5289d63fe1SAtsushi Nemoto .flags = IORESOURCE_MEM, 5389d63fe1SAtsushi Nemoto }; 5489d63fe1SAtsushi Nemoto void __init 5589d63fe1SAtsushi Nemoto txx9_reg_res_init(unsigned int pcode, unsigned long base, unsigned long size) 5689d63fe1SAtsushi Nemoto { 5789d63fe1SAtsushi Nemoto int i; 5889d63fe1SAtsushi Nemoto 5989d63fe1SAtsushi Nemoto for (i = 0; i < ARRAY_SIZE(txx9_ce_res); i++) { 6089d63fe1SAtsushi Nemoto sprintf(txx9_ce_res_name[i], "CE%d", i); 6189d63fe1SAtsushi Nemoto txx9_ce_res[i].flags = IORESOURCE_MEM; 6289d63fe1SAtsushi Nemoto txx9_ce_res[i].name = txx9_ce_res_name[i]; 6389d63fe1SAtsushi Nemoto } 6489d63fe1SAtsushi Nemoto 65073828d0SAtsushi Nemoto txx9_pcode = pcode; 6689d63fe1SAtsushi Nemoto sprintf(txx9_pcode_str, "TX%x", pcode); 6789d63fe1SAtsushi Nemoto if (base) { 6889d63fe1SAtsushi Nemoto txx9_reg_res.start = base & 0xfffffffffULL; 6989d63fe1SAtsushi Nemoto txx9_reg_res.end = (base & 0xfffffffffULL) + (size - 1); 7089d63fe1SAtsushi Nemoto request_resource(&iomem_resource, &txx9_reg_res); 7189d63fe1SAtsushi Nemoto } 7289d63fe1SAtsushi Nemoto } 7389d63fe1SAtsushi Nemoto 7489d63fe1SAtsushi Nemoto /* clocks */ 7589d63fe1SAtsushi Nemoto unsigned int txx9_master_clock; 7689d63fe1SAtsushi Nemoto unsigned int txx9_cpu_clock; 7789d63fe1SAtsushi Nemoto unsigned int txx9_gbus_clock; 78edcaf1a6SAtsushi Nemoto 79c7b95bcbSAtsushi Nemoto #ifdef CONFIG_CPU_TX39XX 80c7b95bcbSAtsushi Nemoto /* don't enable by default - see errata */ 81c7b95bcbSAtsushi Nemoto int txx9_ccfg_toeon __initdata; 82c7b95bcbSAtsushi Nemoto #else 8394a4c329SAtsushi Nemoto int txx9_ccfg_toeon __initdata = 1; 84c7b95bcbSAtsushi Nemoto #endif 85edcaf1a6SAtsushi Nemoto 86edcaf1a6SAtsushi Nemoto /* Minimum CLK support */ 87edcaf1a6SAtsushi Nemoto 88edcaf1a6SAtsushi Nemoto struct clk *clk_get(struct device *dev, const char *id) 89edcaf1a6SAtsushi Nemoto { 90edcaf1a6SAtsushi Nemoto if (!strcmp(id, "spi-baseclk")) 91fcc152f3SAtsushi Nemoto return (struct clk *)((unsigned long)txx9_gbus_clock / 2 / 2); 92edcaf1a6SAtsushi Nemoto if (!strcmp(id, "imbus_clk")) 9394a4c329SAtsushi Nemoto return (struct clk *)((unsigned long)txx9_gbus_clock / 2); 94edcaf1a6SAtsushi Nemoto return ERR_PTR(-ENOENT); 95edcaf1a6SAtsushi Nemoto } 96edcaf1a6SAtsushi Nemoto EXPORT_SYMBOL(clk_get); 97edcaf1a6SAtsushi Nemoto 98edcaf1a6SAtsushi Nemoto int clk_enable(struct clk *clk) 99edcaf1a6SAtsushi Nemoto { 100edcaf1a6SAtsushi Nemoto return 0; 101edcaf1a6SAtsushi Nemoto } 102edcaf1a6SAtsushi Nemoto EXPORT_SYMBOL(clk_enable); 103edcaf1a6SAtsushi Nemoto 104edcaf1a6SAtsushi Nemoto void clk_disable(struct clk *clk) 105edcaf1a6SAtsushi Nemoto { 106edcaf1a6SAtsushi Nemoto } 107edcaf1a6SAtsushi Nemoto EXPORT_SYMBOL(clk_disable); 108edcaf1a6SAtsushi Nemoto 109edcaf1a6SAtsushi Nemoto unsigned long clk_get_rate(struct clk *clk) 110edcaf1a6SAtsushi Nemoto { 111edcaf1a6SAtsushi Nemoto return (unsigned long)clk; 112edcaf1a6SAtsushi Nemoto } 113edcaf1a6SAtsushi Nemoto EXPORT_SYMBOL(clk_get_rate); 114edcaf1a6SAtsushi Nemoto 115edcaf1a6SAtsushi Nemoto void clk_put(struct clk *clk) 116edcaf1a6SAtsushi Nemoto { 117edcaf1a6SAtsushi Nemoto } 118edcaf1a6SAtsushi Nemoto EXPORT_SYMBOL(clk_put); 119edcaf1a6SAtsushi Nemoto 120860e546cSAtsushi Nemoto #define BOARD_VEC(board) extern struct txx9_board_vec board; 121860e546cSAtsushi Nemoto #include <asm/txx9/boards.h> 122860e546cSAtsushi Nemoto #undef BOARD_VEC 123edcaf1a6SAtsushi Nemoto 124edcaf1a6SAtsushi Nemoto struct txx9_board_vec *txx9_board_vec __initdata; 125edcaf1a6SAtsushi Nemoto static char txx9_system_type[32]; 126edcaf1a6SAtsushi Nemoto 127860e546cSAtsushi Nemoto static struct txx9_board_vec *board_vecs[] __initdata = { 128860e546cSAtsushi Nemoto #define BOARD_VEC(board) &board, 129860e546cSAtsushi Nemoto #include <asm/txx9/boards.h> 130860e546cSAtsushi Nemoto #undef BOARD_VEC 131860e546cSAtsushi Nemoto }; 132860e546cSAtsushi Nemoto 133860e546cSAtsushi Nemoto static struct txx9_board_vec *__init find_board_byname(const char *name) 134860e546cSAtsushi Nemoto { 135860e546cSAtsushi Nemoto int i; 136860e546cSAtsushi Nemoto 137860e546cSAtsushi Nemoto /* search board_vecs table */ 138860e546cSAtsushi Nemoto for (i = 0; i < ARRAY_SIZE(board_vecs); i++) { 139860e546cSAtsushi Nemoto if (strstr(board_vecs[i]->system, name)) 140860e546cSAtsushi Nemoto return board_vecs[i]; 141860e546cSAtsushi Nemoto } 142860e546cSAtsushi Nemoto return NULL; 143860e546cSAtsushi Nemoto } 144860e546cSAtsushi Nemoto 145e0dfb20cSAtsushi Nemoto static void __init prom_init_cmdline(void) 146edcaf1a6SAtsushi Nemoto { 14797b0511cSGeert Uytterhoeven int argc; 14897b0511cSGeert Uytterhoeven int *argv32; 149edcaf1a6SAtsushi Nemoto int i; /* Always ignore the "-c" at argv[0] */ 150edcaf1a6SAtsushi Nemoto 15197b0511cSGeert Uytterhoeven if (fw_arg0 >= CKSEG0 || fw_arg1 < CKSEG0) { 15297b0511cSGeert Uytterhoeven /* 15397b0511cSGeert Uytterhoeven * argc is not a valid number, or argv32 is not a valid 15497b0511cSGeert Uytterhoeven * pointer 15597b0511cSGeert Uytterhoeven */ 15697b0511cSGeert Uytterhoeven argc = 0; 15797b0511cSGeert Uytterhoeven argv32 = NULL; 15897b0511cSGeert Uytterhoeven } else { 15997b0511cSGeert Uytterhoeven argc = (int)fw_arg0; 16097b0511cSGeert Uytterhoeven argv32 = (int *)fw_arg1; 16197b0511cSGeert Uytterhoeven } 16297b0511cSGeert Uytterhoeven 163e0dfb20cSAtsushi Nemoto arcs_cmdline[0] = '\0'; 164edcaf1a6SAtsushi Nemoto 165edcaf1a6SAtsushi Nemoto for (i = 1; i < argc; i++) { 166e0dfb20cSAtsushi Nemoto char *str = (char *)(long)argv32[i]; 167edcaf1a6SAtsushi Nemoto if (i != 1) 168edcaf1a6SAtsushi Nemoto strcat(arcs_cmdline, " "); 169e0dfb20cSAtsushi Nemoto if (strchr(str, ' ')) { 170e0dfb20cSAtsushi Nemoto strcat(arcs_cmdline, "\""); 171e0dfb20cSAtsushi Nemoto strcat(arcs_cmdline, str); 172e0dfb20cSAtsushi Nemoto strcat(arcs_cmdline, "\""); 173e0dfb20cSAtsushi Nemoto } else 174e0dfb20cSAtsushi Nemoto strcat(arcs_cmdline, str); 175e0dfb20cSAtsushi Nemoto } 176edcaf1a6SAtsushi Nemoto } 177edcaf1a6SAtsushi Nemoto 178d10e025fSAtsushi Nemoto static int txx9_ic_disable __initdata; 179d10e025fSAtsushi Nemoto static int txx9_dc_disable __initdata; 180d10e025fSAtsushi Nemoto 181d10e025fSAtsushi Nemoto #if defined(CONFIG_CPU_TX49XX) 182d10e025fSAtsushi Nemoto /* flush all cache on very early stage (before 4k_cache_init) */ 183d10e025fSAtsushi Nemoto static void __init early_flush_dcache(void) 184d10e025fSAtsushi Nemoto { 185d10e025fSAtsushi Nemoto unsigned int conf = read_c0_config(); 186d10e025fSAtsushi Nemoto unsigned int dc_size = 1 << (12 + ((conf & CONF_DC) >> 6)); 187d10e025fSAtsushi Nemoto unsigned int linesz = 32; 188d10e025fSAtsushi Nemoto unsigned long addr, end; 189d10e025fSAtsushi Nemoto 190d10e025fSAtsushi Nemoto end = INDEX_BASE + dc_size / 4; 191d10e025fSAtsushi Nemoto /* 4way, waybit=0 */ 192d10e025fSAtsushi Nemoto for (addr = INDEX_BASE; addr < end; addr += linesz) { 193d10e025fSAtsushi Nemoto cache_op(Index_Writeback_Inv_D, addr | 0); 194d10e025fSAtsushi Nemoto cache_op(Index_Writeback_Inv_D, addr | 1); 195d10e025fSAtsushi Nemoto cache_op(Index_Writeback_Inv_D, addr | 2); 196d10e025fSAtsushi Nemoto cache_op(Index_Writeback_Inv_D, addr | 3); 197d10e025fSAtsushi Nemoto } 198d10e025fSAtsushi Nemoto } 199d10e025fSAtsushi Nemoto 200d10e025fSAtsushi Nemoto static void __init txx9_cache_fixup(void) 201d10e025fSAtsushi Nemoto { 202d10e025fSAtsushi Nemoto unsigned int conf; 203d10e025fSAtsushi Nemoto 204d10e025fSAtsushi Nemoto conf = read_c0_config(); 205d10e025fSAtsushi Nemoto /* flush and disable */ 206d10e025fSAtsushi Nemoto if (txx9_ic_disable) { 207d10e025fSAtsushi Nemoto conf |= TX49_CONF_IC; 208d10e025fSAtsushi Nemoto write_c0_config(conf); 209d10e025fSAtsushi Nemoto } 210d10e025fSAtsushi Nemoto if (txx9_dc_disable) { 211d10e025fSAtsushi Nemoto early_flush_dcache(); 212d10e025fSAtsushi Nemoto conf |= TX49_CONF_DC; 213d10e025fSAtsushi Nemoto write_c0_config(conf); 214d10e025fSAtsushi Nemoto } 215d10e025fSAtsushi Nemoto 216d10e025fSAtsushi Nemoto /* enable cache */ 217d10e025fSAtsushi Nemoto conf = read_c0_config(); 218d10e025fSAtsushi Nemoto if (!txx9_ic_disable) 219d10e025fSAtsushi Nemoto conf &= ~TX49_CONF_IC; 220d10e025fSAtsushi Nemoto if (!txx9_dc_disable) 221d10e025fSAtsushi Nemoto conf &= ~TX49_CONF_DC; 222d10e025fSAtsushi Nemoto write_c0_config(conf); 223d10e025fSAtsushi Nemoto 224d10e025fSAtsushi Nemoto if (conf & TX49_CONF_IC) 225d10e025fSAtsushi Nemoto pr_info("TX49XX I-Cache disabled.\n"); 226d10e025fSAtsushi Nemoto if (conf & TX49_CONF_DC) 227d10e025fSAtsushi Nemoto pr_info("TX49XX D-Cache disabled.\n"); 228d10e025fSAtsushi Nemoto } 229d10e025fSAtsushi Nemoto #elif defined(CONFIG_CPU_TX39XX) 230d10e025fSAtsushi Nemoto /* flush all cache on very early stage (before tx39_cache_init) */ 231d10e025fSAtsushi Nemoto static void __init early_flush_dcache(void) 232d10e025fSAtsushi Nemoto { 233d10e025fSAtsushi Nemoto unsigned int conf = read_c0_config(); 234d10e025fSAtsushi Nemoto unsigned int dc_size = 1 << (10 + ((conf & TX39_CONF_DCS_MASK) >> 235d10e025fSAtsushi Nemoto TX39_CONF_DCS_SHIFT)); 236d10e025fSAtsushi Nemoto unsigned int linesz = 16; 237d10e025fSAtsushi Nemoto unsigned long addr, end; 238d10e025fSAtsushi Nemoto 239d10e025fSAtsushi Nemoto end = INDEX_BASE + dc_size / 2; 240d10e025fSAtsushi Nemoto /* 2way, waybit=0 */ 241d10e025fSAtsushi Nemoto for (addr = INDEX_BASE; addr < end; addr += linesz) { 242d10e025fSAtsushi Nemoto cache_op(Index_Writeback_Inv_D, addr | 0); 243d10e025fSAtsushi Nemoto cache_op(Index_Writeback_Inv_D, addr | 1); 244d10e025fSAtsushi Nemoto } 245d10e025fSAtsushi Nemoto } 246d10e025fSAtsushi Nemoto 247d10e025fSAtsushi Nemoto static void __init txx9_cache_fixup(void) 248d10e025fSAtsushi Nemoto { 249d10e025fSAtsushi Nemoto unsigned int conf; 250d10e025fSAtsushi Nemoto 251d10e025fSAtsushi Nemoto conf = read_c0_config(); 252d10e025fSAtsushi Nemoto /* flush and disable */ 253d10e025fSAtsushi Nemoto if (txx9_ic_disable) { 254d10e025fSAtsushi Nemoto conf &= ~TX39_CONF_ICE; 255d10e025fSAtsushi Nemoto write_c0_config(conf); 256d10e025fSAtsushi Nemoto } 257d10e025fSAtsushi Nemoto if (txx9_dc_disable) { 258d10e025fSAtsushi Nemoto early_flush_dcache(); 259d10e025fSAtsushi Nemoto conf &= ~TX39_CONF_DCE; 260d10e025fSAtsushi Nemoto write_c0_config(conf); 261d10e025fSAtsushi Nemoto } 262d10e025fSAtsushi Nemoto 263d10e025fSAtsushi Nemoto /* enable cache */ 264d10e025fSAtsushi Nemoto conf = read_c0_config(); 265d10e025fSAtsushi Nemoto if (!txx9_ic_disable) 266d10e025fSAtsushi Nemoto conf |= TX39_CONF_ICE; 267d10e025fSAtsushi Nemoto if (!txx9_dc_disable) 268d10e025fSAtsushi Nemoto conf |= TX39_CONF_DCE; 269d10e025fSAtsushi Nemoto write_c0_config(conf); 270d10e025fSAtsushi Nemoto 271d10e025fSAtsushi Nemoto if (!(conf & TX39_CONF_ICE)) 272d10e025fSAtsushi Nemoto pr_info("TX39XX I-Cache disabled.\n"); 273d10e025fSAtsushi Nemoto if (!(conf & TX39_CONF_DCE)) 274d10e025fSAtsushi Nemoto pr_info("TX39XX D-Cache disabled.\n"); 275d10e025fSAtsushi Nemoto } 276d10e025fSAtsushi Nemoto #else 277d10e025fSAtsushi Nemoto static inline void txx9_cache_fixup(void) 278d10e025fSAtsushi Nemoto { 279d10e025fSAtsushi Nemoto } 280d10e025fSAtsushi Nemoto #endif 281d10e025fSAtsushi Nemoto 282860e546cSAtsushi Nemoto static void __init preprocess_cmdline(void) 283edcaf1a6SAtsushi Nemoto { 2847580c9c3SDmitri Vorobiev static char cmdline[COMMAND_LINE_SIZE] __initdata; 285860e546cSAtsushi Nemoto char *s; 286860e546cSAtsushi Nemoto 287860e546cSAtsushi Nemoto strcpy(cmdline, arcs_cmdline); 288860e546cSAtsushi Nemoto s = cmdline; 289860e546cSAtsushi Nemoto arcs_cmdline[0] = '\0'; 290860e546cSAtsushi Nemoto while (s && *s) { 291860e546cSAtsushi Nemoto char *str = strsep(&s, " "); 292860e546cSAtsushi Nemoto if (strncmp(str, "board=", 6) == 0) { 293860e546cSAtsushi Nemoto txx9_board_vec = find_board_byname(str + 6); 294860e546cSAtsushi Nemoto continue; 295860e546cSAtsushi Nemoto } else if (strncmp(str, "masterclk=", 10) == 0) { 2968e9ecbc5SDaniel Walter unsigned int val; 2978e9ecbc5SDaniel Walter if (kstrtouint(str + 10, 10, &val) == 0) 298860e546cSAtsushi Nemoto txx9_master_clock = val; 299860e546cSAtsushi Nemoto continue; 300d10e025fSAtsushi Nemoto } else if (strcmp(str, "icdisable") == 0) { 301d10e025fSAtsushi Nemoto txx9_ic_disable = 1; 302d10e025fSAtsushi Nemoto continue; 303d10e025fSAtsushi Nemoto } else if (strcmp(str, "dcdisable") == 0) { 304d10e025fSAtsushi Nemoto txx9_dc_disable = 1; 305d10e025fSAtsushi Nemoto continue; 306c7b95bcbSAtsushi Nemoto } else if (strcmp(str, "toeoff") == 0) { 307c7b95bcbSAtsushi Nemoto txx9_ccfg_toeon = 0; 308c7b95bcbSAtsushi Nemoto continue; 309c7b95bcbSAtsushi Nemoto } else if (strcmp(str, "toeon") == 0) { 310c7b95bcbSAtsushi Nemoto txx9_ccfg_toeon = 1; 311c7b95bcbSAtsushi Nemoto continue; 312860e546cSAtsushi Nemoto } 313860e546cSAtsushi Nemoto if (arcs_cmdline[0]) 314860e546cSAtsushi Nemoto strcat(arcs_cmdline, " "); 315860e546cSAtsushi Nemoto strcat(arcs_cmdline, str); 316860e546cSAtsushi Nemoto } 317d10e025fSAtsushi Nemoto 318d10e025fSAtsushi Nemoto txx9_cache_fixup(); 319860e546cSAtsushi Nemoto } 320860e546cSAtsushi Nemoto 321860e546cSAtsushi Nemoto static void __init select_board(void) 322860e546cSAtsushi Nemoto { 323860e546cSAtsushi Nemoto const char *envstr; 324860e546cSAtsushi Nemoto 325860e546cSAtsushi Nemoto /* first, determine by "board=" argument in preprocess_cmdline() */ 326860e546cSAtsushi Nemoto if (txx9_board_vec) 327860e546cSAtsushi Nemoto return; 328860e546cSAtsushi Nemoto /* next, determine by "board" envvar */ 329860e546cSAtsushi Nemoto envstr = prom_getenv("board"); 330860e546cSAtsushi Nemoto if (envstr) { 331860e546cSAtsushi Nemoto txx9_board_vec = find_board_byname(envstr); 332860e546cSAtsushi Nemoto if (txx9_board_vec) 333860e546cSAtsushi Nemoto return; 334860e546cSAtsushi Nemoto } 335860e546cSAtsushi Nemoto 336860e546cSAtsushi Nemoto /* select "default" board */ 337c8acd40dSMarkos Chandras #ifdef CONFIG_TOSHIBA_JMR3927 3387a1fdf19SYoichi Yuasa txx9_board_vec = &jmr3927_vec; 339edcaf1a6SAtsushi Nemoto #endif 340edcaf1a6SAtsushi Nemoto #ifdef CONFIG_CPU_TX49XX 341edcaf1a6SAtsushi Nemoto switch (TX4938_REV_PCODE()) { 3428d795f2aSAtsushi Nemoto #ifdef CONFIG_TOSHIBA_RBTX4927 343edcaf1a6SAtsushi Nemoto case 0x4927: 3447a1fdf19SYoichi Yuasa txx9_board_vec = &rbtx4927_vec; 345edcaf1a6SAtsushi Nemoto break; 346edcaf1a6SAtsushi Nemoto case 0x4937: 3477a1fdf19SYoichi Yuasa txx9_board_vec = &rbtx4937_vec; 348edcaf1a6SAtsushi Nemoto break; 3498d795f2aSAtsushi Nemoto #endif 3508d795f2aSAtsushi Nemoto #ifdef CONFIG_TOSHIBA_RBTX4938 351edcaf1a6SAtsushi Nemoto case 0x4938: 3527a1fdf19SYoichi Yuasa txx9_board_vec = &rbtx4938_vec; 353edcaf1a6SAtsushi Nemoto break; 3548d795f2aSAtsushi Nemoto #endif 355b27311e1SAtsushi Nemoto #ifdef CONFIG_TOSHIBA_RBTX4939 356b27311e1SAtsushi Nemoto case 0x4939: 357b27311e1SAtsushi Nemoto txx9_board_vec = &rbtx4939_vec; 358b27311e1SAtsushi Nemoto break; 359b27311e1SAtsushi Nemoto #endif 360edcaf1a6SAtsushi Nemoto } 361edcaf1a6SAtsushi Nemoto #endif 362860e546cSAtsushi Nemoto } 363860e546cSAtsushi Nemoto 364860e546cSAtsushi Nemoto void __init prom_init(void) 365860e546cSAtsushi Nemoto { 366860e546cSAtsushi Nemoto prom_init_cmdline(); 367860e546cSAtsushi Nemoto preprocess_cmdline(); 368860e546cSAtsushi Nemoto select_board(); 3697a1fdf19SYoichi Yuasa 370edcaf1a6SAtsushi Nemoto strcpy(txx9_system_type, txx9_board_vec->system); 3717a1fdf19SYoichi Yuasa 3727b226094SAtsushi Nemoto txx9_board_vec->prom_init(); 373edcaf1a6SAtsushi Nemoto } 374edcaf1a6SAtsushi Nemoto 375edcaf1a6SAtsushi Nemoto void __init prom_free_prom_memory(void) 376edcaf1a6SAtsushi Nemoto { 377b6263ff2SAtsushi Nemoto unsigned long saddr = PAGE_SIZE; 378b6263ff2SAtsushi Nemoto unsigned long eaddr = __pa_symbol(&_text); 379b6263ff2SAtsushi Nemoto 380b6263ff2SAtsushi Nemoto if (saddr < eaddr) 381b6263ff2SAtsushi Nemoto free_init_pages("prom memory", saddr, eaddr); 382edcaf1a6SAtsushi Nemoto } 383edcaf1a6SAtsushi Nemoto 384edcaf1a6SAtsushi Nemoto const char *get_system_type(void) 385edcaf1a6SAtsushi Nemoto { 386edcaf1a6SAtsushi Nemoto return txx9_system_type; 387edcaf1a6SAtsushi Nemoto } 388edcaf1a6SAtsushi Nemoto 389265b89dbSAtsushi Nemoto const char *__init prom_getenv(const char *name) 390265b89dbSAtsushi Nemoto { 39197b0511cSGeert Uytterhoeven const s32 *str; 392265b89dbSAtsushi Nemoto 39397b0511cSGeert Uytterhoeven if (fw_arg2 < CKSEG0) 394265b89dbSAtsushi Nemoto return NULL; 39597b0511cSGeert Uytterhoeven 39697b0511cSGeert Uytterhoeven str = (const s32 *)fw_arg2; 397265b89dbSAtsushi Nemoto /* YAMON style ("name", "value" pairs) */ 398265b89dbSAtsushi Nemoto while (str[0] && str[1]) { 399265b89dbSAtsushi Nemoto if (!strcmp((const char *)(unsigned long)str[0], name)) 400265b89dbSAtsushi Nemoto return (const char *)(unsigned long)str[1]; 401265b89dbSAtsushi Nemoto str += 2; 402265b89dbSAtsushi Nemoto } 403265b89dbSAtsushi Nemoto return NULL; 404265b89dbSAtsushi Nemoto } 405265b89dbSAtsushi Nemoto 406a49297e8SAtsushi Nemoto static void __noreturn txx9_machine_halt(void) 407a49297e8SAtsushi Nemoto { 408a49297e8SAtsushi Nemoto local_irq_disable(); 409a49297e8SAtsushi Nemoto clear_c0_status(ST0_IM); 410a49297e8SAtsushi Nemoto while (1) { 411a49297e8SAtsushi Nemoto if (cpu_wait) { 412a49297e8SAtsushi Nemoto (*cpu_wait)(); 413a49297e8SAtsushi Nemoto if (cpu_has_counter) { 414a49297e8SAtsushi Nemoto /* 415a49297e8SAtsushi Nemoto * Clear counter interrupt while it 416a49297e8SAtsushi Nemoto * breaks WAIT instruction even if 417a49297e8SAtsushi Nemoto * masked. 418a49297e8SAtsushi Nemoto */ 419a49297e8SAtsushi Nemoto write_c0_compare(0); 420a49297e8SAtsushi Nemoto } 421a49297e8SAtsushi Nemoto } 422a49297e8SAtsushi Nemoto } 423a49297e8SAtsushi Nemoto } 424a49297e8SAtsushi Nemoto 42568314725SAtsushi Nemoto /* Watchdog support */ 42668314725SAtsushi Nemoto void __init txx9_wdt_init(unsigned long base) 42768314725SAtsushi Nemoto { 42868314725SAtsushi Nemoto struct resource res = { 42968314725SAtsushi Nemoto .start = base, 43068314725SAtsushi Nemoto .end = base + 0x100 - 1, 43168314725SAtsushi Nemoto .flags = IORESOURCE_MEM, 43268314725SAtsushi Nemoto }; 43368314725SAtsushi Nemoto platform_device_register_simple("txx9wdt", -1, &res, 1); 43468314725SAtsushi Nemoto } 43568314725SAtsushi Nemoto 436496a3b5cSAtsushi Nemoto void txx9_wdt_now(unsigned long base) 437496a3b5cSAtsushi Nemoto { 438496a3b5cSAtsushi Nemoto struct txx9_tmr_reg __iomem *tmrptr = 439496a3b5cSAtsushi Nemoto ioremap(base, sizeof(struct txx9_tmr_reg)); 440496a3b5cSAtsushi Nemoto /* disable watch dog timer */ 441496a3b5cSAtsushi Nemoto __raw_writel(TXx9_TMWTMR_WDIS | TXx9_TMWTMR_TWC, &tmrptr->wtmr); 442496a3b5cSAtsushi Nemoto __raw_writel(0, &tmrptr->tcr); 443496a3b5cSAtsushi Nemoto /* kick watchdog */ 444496a3b5cSAtsushi Nemoto __raw_writel(TXx9_TMWTMR_TWIE, &tmrptr->wtmr); 445496a3b5cSAtsushi Nemoto __raw_writel(1, &tmrptr->cpra); /* immediate */ 446496a3b5cSAtsushi Nemoto __raw_writel(TXx9_TMTCR_TCE | TXx9_TMTCR_CCDE | TXx9_TMTCR_TMODE_WDOG, 447496a3b5cSAtsushi Nemoto &tmrptr->tcr); 448496a3b5cSAtsushi Nemoto } 449496a3b5cSAtsushi Nemoto 450c49f91f5SAtsushi Nemoto /* SPI support */ 451c49f91f5SAtsushi Nemoto void __init txx9_spi_init(int busid, unsigned long base, int irq) 452c49f91f5SAtsushi Nemoto { 453c49f91f5SAtsushi Nemoto struct resource res[] = { 454c49f91f5SAtsushi Nemoto { 455c49f91f5SAtsushi Nemoto .start = base, 456c49f91f5SAtsushi Nemoto .end = base + 0x20 - 1, 457c49f91f5SAtsushi Nemoto .flags = IORESOURCE_MEM, 458c49f91f5SAtsushi Nemoto }, { 459c49f91f5SAtsushi Nemoto .start = irq, 460c49f91f5SAtsushi Nemoto .flags = IORESOURCE_IRQ, 461c49f91f5SAtsushi Nemoto }, 462c49f91f5SAtsushi Nemoto }; 463c49f91f5SAtsushi Nemoto platform_device_register_simple("spi_txx9", busid, 464c49f91f5SAtsushi Nemoto res, ARRAY_SIZE(res)); 465c49f91f5SAtsushi Nemoto } 466c49f91f5SAtsushi Nemoto 467c49f91f5SAtsushi Nemoto void __init txx9_ethaddr_init(unsigned int id, unsigned char *ethaddr) 468c49f91f5SAtsushi Nemoto { 469c49f91f5SAtsushi Nemoto struct platform_device *pdev = 470c49f91f5SAtsushi Nemoto platform_device_alloc("tc35815-mac", id); 471c49f91f5SAtsushi Nemoto if (!pdev || 472c49f91f5SAtsushi Nemoto platform_device_add_data(pdev, ethaddr, 6) || 473c49f91f5SAtsushi Nemoto platform_device_add(pdev)) 474c49f91f5SAtsushi Nemoto platform_device_put(pdev); 475c49f91f5SAtsushi Nemoto } 476c49f91f5SAtsushi Nemoto 4777779a5e0SAtsushi Nemoto void __init txx9_sio_init(unsigned long baseaddr, int irq, 4787779a5e0SAtsushi Nemoto unsigned int line, unsigned int sclk, int nocts) 4797779a5e0SAtsushi Nemoto { 4807779a5e0SAtsushi Nemoto #ifdef CONFIG_SERIAL_TXX9 4817779a5e0SAtsushi Nemoto struct uart_port req; 4827779a5e0SAtsushi Nemoto 4837779a5e0SAtsushi Nemoto memset(&req, 0, sizeof(req)); 4847779a5e0SAtsushi Nemoto req.line = line; 4857779a5e0SAtsushi Nemoto req.iotype = UPIO_MEM; 4867779a5e0SAtsushi Nemoto req.membase = ioremap(baseaddr, 0x24); 4877779a5e0SAtsushi Nemoto req.mapbase = baseaddr; 4887779a5e0SAtsushi Nemoto req.irq = irq; 4897779a5e0SAtsushi Nemoto if (!nocts) 4907779a5e0SAtsushi Nemoto req.flags |= UPF_BUGGY_UART /*HAVE_CTS_LINE*/; 4917779a5e0SAtsushi Nemoto if (sclk) { 4927779a5e0SAtsushi Nemoto req.flags |= UPF_MAGIC_MULTIPLIER /*USE_SCLK*/; 4937779a5e0SAtsushi Nemoto req.uartclk = sclk; 4947779a5e0SAtsushi Nemoto } else 4957779a5e0SAtsushi Nemoto req.uartclk = TXX9_IMCLK; 4967779a5e0SAtsushi Nemoto early_serial_txx9_setup(&req); 4977779a5e0SAtsushi Nemoto #endif /* CONFIG_SERIAL_TXX9 */ 4987779a5e0SAtsushi Nemoto } 4997779a5e0SAtsushi Nemoto 500e352953cSAtsushi Nemoto #ifdef CONFIG_EARLY_PRINTK 501f7be4e75SAaro Koskinen static void null_prom_putchar(char c) 502e352953cSAtsushi Nemoto { 503e352953cSAtsushi Nemoto } 504f7be4e75SAaro Koskinen void (*txx9_prom_putchar)(char c) = null_prom_putchar; 505e352953cSAtsushi Nemoto 506f7be4e75SAaro Koskinen void prom_putchar(char c) 507e352953cSAtsushi Nemoto { 508e352953cSAtsushi Nemoto txx9_prom_putchar(c); 509e352953cSAtsushi Nemoto } 510e352953cSAtsushi Nemoto 511e352953cSAtsushi Nemoto static void __iomem *early_txx9_sio_port; 512e352953cSAtsushi Nemoto 513f7be4e75SAaro Koskinen static void early_txx9_sio_putchar(char c) 514e352953cSAtsushi Nemoto { 515e352953cSAtsushi Nemoto #define TXX9_SICISR 0x0c 516e352953cSAtsushi Nemoto #define TXX9_SITFIFO 0x1c 517e352953cSAtsushi Nemoto #define TXX9_SICISR_TXALS 0x00000002 518e352953cSAtsushi Nemoto while (!(__raw_readl(early_txx9_sio_port + TXX9_SICISR) & 519e352953cSAtsushi Nemoto TXX9_SICISR_TXALS)) 520e352953cSAtsushi Nemoto ; 521e352953cSAtsushi Nemoto __raw_writel(c, early_txx9_sio_port + TXX9_SITFIFO); 522e352953cSAtsushi Nemoto } 523e352953cSAtsushi Nemoto 524e352953cSAtsushi Nemoto void __init txx9_sio_putchar_init(unsigned long baseaddr) 525e352953cSAtsushi Nemoto { 526e352953cSAtsushi Nemoto early_txx9_sio_port = ioremap(baseaddr, 0x24); 527e352953cSAtsushi Nemoto txx9_prom_putchar = early_txx9_sio_putchar; 528e352953cSAtsushi Nemoto } 529e352953cSAtsushi Nemoto #endif /* CONFIG_EARLY_PRINTK */ 530e352953cSAtsushi Nemoto 531edcaf1a6SAtsushi Nemoto /* wrappers */ 532edcaf1a6SAtsushi Nemoto void __init plat_mem_setup(void) 533edcaf1a6SAtsushi Nemoto { 53494a4c329SAtsushi Nemoto ioport_resource.start = 0; 53594a4c329SAtsushi Nemoto ioport_resource.end = ~0UL; /* no limit */ 53694a4c329SAtsushi Nemoto iomem_resource.start = 0; 53794a4c329SAtsushi Nemoto iomem_resource.end = ~0UL; /* no limit */ 538a49297e8SAtsushi Nemoto 539a49297e8SAtsushi Nemoto /* fallback restart/halt routines */ 540a49297e8SAtsushi Nemoto _machine_restart = (void (*)(char *))txx9_machine_halt; 541a49297e8SAtsushi Nemoto _machine_halt = txx9_machine_halt; 542a49297e8SAtsushi Nemoto pm_power_off = txx9_machine_halt; 543a49297e8SAtsushi Nemoto 54407517529SAtsushi Nemoto #ifdef CONFIG_PCI 54507517529SAtsushi Nemoto pcibios_plat_setup = txx9_pcibios_setup; 54607517529SAtsushi Nemoto #endif 547edcaf1a6SAtsushi Nemoto txx9_board_vec->mem_setup(); 548edcaf1a6SAtsushi Nemoto } 549edcaf1a6SAtsushi Nemoto 550edcaf1a6SAtsushi Nemoto void __init arch_init_irq(void) 551edcaf1a6SAtsushi Nemoto { 552edcaf1a6SAtsushi Nemoto txx9_board_vec->irq_setup(); 553edcaf1a6SAtsushi Nemoto } 554edcaf1a6SAtsushi Nemoto 555edcaf1a6SAtsushi Nemoto void __init plat_time_init(void) 556edcaf1a6SAtsushi Nemoto { 5571374d084SAtsushi Nemoto #ifdef CONFIG_CPU_TX49XX 5581374d084SAtsushi Nemoto mips_hpt_frequency = txx9_cpu_clock / 2; 5591374d084SAtsushi Nemoto #endif 560edcaf1a6SAtsushi Nemoto txx9_board_vec->time_init(); 561edcaf1a6SAtsushi Nemoto } 562edcaf1a6SAtsushi Nemoto 563edcaf1a6SAtsushi Nemoto static int __init _txx9_arch_init(void) 564edcaf1a6SAtsushi Nemoto { 565edcaf1a6SAtsushi Nemoto if (txx9_board_vec->arch_init) 566edcaf1a6SAtsushi Nemoto txx9_board_vec->arch_init(); 567edcaf1a6SAtsushi Nemoto return 0; 568edcaf1a6SAtsushi Nemoto } 569edcaf1a6SAtsushi Nemoto arch_initcall(_txx9_arch_init); 570edcaf1a6SAtsushi Nemoto 571edcaf1a6SAtsushi Nemoto static int __init _txx9_device_init(void) 572edcaf1a6SAtsushi Nemoto { 573edcaf1a6SAtsushi Nemoto if (txx9_board_vec->device_init) 574edcaf1a6SAtsushi Nemoto txx9_board_vec->device_init(); 575edcaf1a6SAtsushi Nemoto return 0; 576edcaf1a6SAtsushi Nemoto } 577edcaf1a6SAtsushi Nemoto device_initcall(_txx9_device_init); 578edcaf1a6SAtsushi Nemoto 579edcaf1a6SAtsushi Nemoto int (*txx9_irq_dispatch)(int pending); 580edcaf1a6SAtsushi Nemoto asmlinkage void plat_irq_dispatch(void) 581edcaf1a6SAtsushi Nemoto { 582edcaf1a6SAtsushi Nemoto int pending = read_c0_status() & read_c0_cause() & ST0_IM; 583edcaf1a6SAtsushi Nemoto int irq = txx9_irq_dispatch(pending); 584edcaf1a6SAtsushi Nemoto 585edcaf1a6SAtsushi Nemoto if (likely(irq >= 0)) 586edcaf1a6SAtsushi Nemoto do_IRQ(irq); 587edcaf1a6SAtsushi Nemoto else 588edcaf1a6SAtsushi Nemoto spurious_interrupt(); 589edcaf1a6SAtsushi Nemoto } 5904c642f3fSAtsushi Nemoto 5914c642f3fSAtsushi Nemoto /* see include/asm-mips/mach-tx39xx/mangle-port.h, for example. */ 5924c642f3fSAtsushi Nemoto #ifdef NEEDS_TXX9_SWIZZLE_ADDR_B 5934c642f3fSAtsushi Nemoto static unsigned long __swizzle_addr_none(unsigned long port) 5944c642f3fSAtsushi Nemoto { 5954c642f3fSAtsushi Nemoto return port; 5964c642f3fSAtsushi Nemoto } 5974c642f3fSAtsushi Nemoto unsigned long (*__swizzle_addr_b)(unsigned long port) = __swizzle_addr_none; 5984c642f3fSAtsushi Nemoto EXPORT_SYMBOL(__swizzle_addr_b); 5994c642f3fSAtsushi Nemoto #endif 60051f607c7SAtsushi Nemoto 6011ba5a176SAtsushi Nemoto #ifdef NEEDS_TXX9_IOSWABW 6021ba5a176SAtsushi Nemoto static u16 ioswabw_default(volatile u16 *a, u16 x) 6031ba5a176SAtsushi Nemoto { 6041ba5a176SAtsushi Nemoto return le16_to_cpu(x); 6051ba5a176SAtsushi Nemoto } 6061ba5a176SAtsushi Nemoto static u16 __mem_ioswabw_default(volatile u16 *a, u16 x) 6071ba5a176SAtsushi Nemoto { 6081ba5a176SAtsushi Nemoto return x; 6091ba5a176SAtsushi Nemoto } 6101ba5a176SAtsushi Nemoto u16 (*ioswabw)(volatile u16 *a, u16 x) = ioswabw_default; 6111ba5a176SAtsushi Nemoto EXPORT_SYMBOL(ioswabw); 6121ba5a176SAtsushi Nemoto u16 (*__mem_ioswabw)(volatile u16 *a, u16 x) = __mem_ioswabw_default; 6131ba5a176SAtsushi Nemoto EXPORT_SYMBOL(__mem_ioswabw); 6141ba5a176SAtsushi Nemoto #endif 6151ba5a176SAtsushi Nemoto 61651f607c7SAtsushi Nemoto void __init txx9_physmap_flash_init(int no, unsigned long addr, 61751f607c7SAtsushi Nemoto unsigned long size, 61851f607c7SAtsushi Nemoto const struct physmap_flash_data *pdata) 61951f607c7SAtsushi Nemoto { 620b33b4407SFlorian Fainelli #if IS_ENABLED(CONFIG_MTD_PHYSMAP) 62151f607c7SAtsushi Nemoto struct resource res = { 62251f607c7SAtsushi Nemoto .start = addr, 62351f607c7SAtsushi Nemoto .end = addr + size - 1, 62451f607c7SAtsushi Nemoto .flags = IORESOURCE_MEM, 62551f607c7SAtsushi Nemoto }; 62651f607c7SAtsushi Nemoto struct platform_device *pdev; 62751f607c7SAtsushi Nemoto static struct mtd_partition parts[2]; 62851f607c7SAtsushi Nemoto struct physmap_flash_data pdata_part; 62951f607c7SAtsushi Nemoto 63051f607c7SAtsushi Nemoto /* If this area contained boot area, make separate partition */ 63151f607c7SAtsushi Nemoto if (pdata->nr_parts == 0 && !pdata->parts && 63251f607c7SAtsushi Nemoto addr < 0x1fc00000 && addr + size > 0x1fc00000 && 63351f607c7SAtsushi Nemoto !parts[0].name) { 63451f607c7SAtsushi Nemoto parts[0].name = "boot"; 63551f607c7SAtsushi Nemoto parts[0].offset = 0x1fc00000 - addr; 63651f607c7SAtsushi Nemoto parts[0].size = addr + size - 0x1fc00000; 63751f607c7SAtsushi Nemoto parts[1].name = "user"; 63851f607c7SAtsushi Nemoto parts[1].offset = 0; 63951f607c7SAtsushi Nemoto parts[1].size = 0x1fc00000 - addr; 64051f607c7SAtsushi Nemoto pdata_part = *pdata; 64151f607c7SAtsushi Nemoto pdata_part.nr_parts = ARRAY_SIZE(parts); 64251f607c7SAtsushi Nemoto pdata_part.parts = parts; 64351f607c7SAtsushi Nemoto pdata = &pdata_part; 64451f607c7SAtsushi Nemoto } 64547854888SJamie Iles 64651f607c7SAtsushi Nemoto pdev = platform_device_alloc("physmap-flash", no); 64751f607c7SAtsushi Nemoto if (!pdev || 64851f607c7SAtsushi Nemoto platform_device_add_resources(pdev, &res, 1) || 64951f607c7SAtsushi Nemoto platform_device_add_data(pdev, pdata, sizeof(*pdata)) || 65051f607c7SAtsushi Nemoto platform_device_add(pdev)) 65151f607c7SAtsushi Nemoto platform_device_put(pdev); 65251f607c7SAtsushi Nemoto #endif 65351f607c7SAtsushi Nemoto } 654ae027eadSAtsushi Nemoto 655a591f5d3SAtsushi Nemoto void __init txx9_ndfmc_init(unsigned long baseaddr, 656a591f5d3SAtsushi Nemoto const struct txx9ndfmc_platform_data *pdata) 657a591f5d3SAtsushi Nemoto { 658b33b4407SFlorian Fainelli #if IS_ENABLED(CONFIG_MTD_NAND_TXX9NDFMC) 659a591f5d3SAtsushi Nemoto struct resource res = { 660a591f5d3SAtsushi Nemoto .start = baseaddr, 661a591f5d3SAtsushi Nemoto .end = baseaddr + 0x1000 - 1, 662a591f5d3SAtsushi Nemoto .flags = IORESOURCE_MEM, 663a591f5d3SAtsushi Nemoto }; 664a591f5d3SAtsushi Nemoto struct platform_device *pdev = platform_device_alloc("txx9ndfmc", -1); 665a591f5d3SAtsushi Nemoto 666a591f5d3SAtsushi Nemoto if (!pdev || 667a591f5d3SAtsushi Nemoto platform_device_add_resources(pdev, &res, 1) || 668a591f5d3SAtsushi Nemoto platform_device_add_data(pdev, pdata, sizeof(*pdata)) || 669a591f5d3SAtsushi Nemoto platform_device_add(pdev)) 670a591f5d3SAtsushi Nemoto platform_device_put(pdev); 671a591f5d3SAtsushi Nemoto #endif 672a591f5d3SAtsushi Nemoto } 673a591f5d3SAtsushi Nemoto 674b33b4407SFlorian Fainelli #if IS_ENABLED(CONFIG_LEDS_GPIO) 675ae027eadSAtsushi Nemoto static DEFINE_SPINLOCK(txx9_iocled_lock); 676ae027eadSAtsushi Nemoto 677ae027eadSAtsushi Nemoto #define TXX9_IOCLED_MAXLEDS 8 678ae027eadSAtsushi Nemoto 679ae027eadSAtsushi Nemoto struct txx9_iocled_data { 680ae027eadSAtsushi Nemoto struct gpio_chip chip; 681ae027eadSAtsushi Nemoto u8 cur_val; 682ae027eadSAtsushi Nemoto void __iomem *mmioaddr; 683ae027eadSAtsushi Nemoto struct gpio_led_platform_data pdata; 684ae027eadSAtsushi Nemoto struct gpio_led leds[TXX9_IOCLED_MAXLEDS]; 685ae027eadSAtsushi Nemoto char names[TXX9_IOCLED_MAXLEDS][32]; 686ae027eadSAtsushi Nemoto }; 687ae027eadSAtsushi Nemoto 688ae027eadSAtsushi Nemoto static int txx9_iocled_get(struct gpio_chip *chip, unsigned int offset) 689ae027eadSAtsushi Nemoto { 690ae027eadSAtsushi Nemoto struct txx9_iocled_data *data = 691ae027eadSAtsushi Nemoto container_of(chip, struct txx9_iocled_data, chip); 692*8cbe4b5cSLinus Walleij return !!(data->cur_val & (1 << offset)); 693ae027eadSAtsushi Nemoto } 694ae027eadSAtsushi Nemoto 695ae027eadSAtsushi Nemoto static void txx9_iocled_set(struct gpio_chip *chip, unsigned int offset, 696ae027eadSAtsushi Nemoto int value) 697ae027eadSAtsushi Nemoto { 698ae027eadSAtsushi Nemoto struct txx9_iocled_data *data = 699ae027eadSAtsushi Nemoto container_of(chip, struct txx9_iocled_data, chip); 700ae027eadSAtsushi Nemoto unsigned long flags; 701ae027eadSAtsushi Nemoto spin_lock_irqsave(&txx9_iocled_lock, flags); 702ae027eadSAtsushi Nemoto if (value) 703ae027eadSAtsushi Nemoto data->cur_val |= 1 << offset; 704ae027eadSAtsushi Nemoto else 705ae027eadSAtsushi Nemoto data->cur_val &= ~(1 << offset); 706ae027eadSAtsushi Nemoto writeb(data->cur_val, data->mmioaddr); 707ae027eadSAtsushi Nemoto mmiowb(); 708ae027eadSAtsushi Nemoto spin_unlock_irqrestore(&txx9_iocled_lock, flags); 709ae027eadSAtsushi Nemoto } 710ae027eadSAtsushi Nemoto 711ae027eadSAtsushi Nemoto static int txx9_iocled_dir_in(struct gpio_chip *chip, unsigned int offset) 712ae027eadSAtsushi Nemoto { 713ae027eadSAtsushi Nemoto return 0; 714ae027eadSAtsushi Nemoto } 715ae027eadSAtsushi Nemoto 716ae027eadSAtsushi Nemoto static int txx9_iocled_dir_out(struct gpio_chip *chip, unsigned int offset, 717ae027eadSAtsushi Nemoto int value) 718ae027eadSAtsushi Nemoto { 719ae027eadSAtsushi Nemoto txx9_iocled_set(chip, offset, value); 720ae027eadSAtsushi Nemoto return 0; 721ae027eadSAtsushi Nemoto } 722ae027eadSAtsushi Nemoto 723ae027eadSAtsushi Nemoto void __init txx9_iocled_init(unsigned long baseaddr, 724ae027eadSAtsushi Nemoto int basenum, unsigned int num, int lowactive, 725ae027eadSAtsushi Nemoto const char *color, char **deftriggers) 726ae027eadSAtsushi Nemoto { 727ae027eadSAtsushi Nemoto struct txx9_iocled_data *iocled; 728ae027eadSAtsushi Nemoto struct platform_device *pdev; 729ae027eadSAtsushi Nemoto int i; 730ae027eadSAtsushi Nemoto static char *default_triggers[] __initdata = { 731ae027eadSAtsushi Nemoto "heartbeat", 732ae027eadSAtsushi Nemoto "ide-disk", 733ae027eadSAtsushi Nemoto "nand-disk", 734ae027eadSAtsushi Nemoto NULL, 735ae027eadSAtsushi Nemoto }; 736ae027eadSAtsushi Nemoto 737ae027eadSAtsushi Nemoto if (!deftriggers) 738ae027eadSAtsushi Nemoto deftriggers = default_triggers; 739ae027eadSAtsushi Nemoto iocled = kzalloc(sizeof(*iocled), GFP_KERNEL); 740ae027eadSAtsushi Nemoto if (!iocled) 741ae027eadSAtsushi Nemoto return; 742ae027eadSAtsushi Nemoto iocled->mmioaddr = ioremap(baseaddr, 1); 743ae027eadSAtsushi Nemoto if (!iocled->mmioaddr) 74470ebadc8SJulia Lawall goto out_free; 745ae027eadSAtsushi Nemoto iocled->chip.get = txx9_iocled_get; 746ae027eadSAtsushi Nemoto iocled->chip.set = txx9_iocled_set; 747ae027eadSAtsushi Nemoto iocled->chip.direction_input = txx9_iocled_dir_in; 748ae027eadSAtsushi Nemoto iocled->chip.direction_output = txx9_iocled_dir_out; 749ae027eadSAtsushi Nemoto iocled->chip.label = "iocled"; 750ae027eadSAtsushi Nemoto iocled->chip.base = basenum; 751ae027eadSAtsushi Nemoto iocled->chip.ngpio = num; 752ae027eadSAtsushi Nemoto if (gpiochip_add(&iocled->chip)) 75370ebadc8SJulia Lawall goto out_unmap; 754ae027eadSAtsushi Nemoto if (basenum < 0) 755ae027eadSAtsushi Nemoto basenum = iocled->chip.base; 756ae027eadSAtsushi Nemoto 757ae027eadSAtsushi Nemoto pdev = platform_device_alloc("leds-gpio", basenum); 758ae027eadSAtsushi Nemoto if (!pdev) 75970ebadc8SJulia Lawall goto out_gpio; 760ae027eadSAtsushi Nemoto iocled->pdata.num_leds = num; 761ae027eadSAtsushi Nemoto iocled->pdata.leds = iocled->leds; 762ae027eadSAtsushi Nemoto for (i = 0; i < num; i++) { 763ae027eadSAtsushi Nemoto struct gpio_led *led = &iocled->leds[i]; 764ae027eadSAtsushi Nemoto snprintf(iocled->names[i], sizeof(iocled->names[i]), 765ae027eadSAtsushi Nemoto "iocled:%s:%u", color, i); 766ae027eadSAtsushi Nemoto led->name = iocled->names[i]; 767ae027eadSAtsushi Nemoto led->gpio = basenum + i; 768ae027eadSAtsushi Nemoto led->active_low = lowactive; 769ae027eadSAtsushi Nemoto if (deftriggers && *deftriggers) 770ae027eadSAtsushi Nemoto led->default_trigger = *deftriggers++; 771ae027eadSAtsushi Nemoto } 772ae027eadSAtsushi Nemoto pdev->dev.platform_data = &iocled->pdata; 773ae027eadSAtsushi Nemoto if (platform_device_add(pdev)) 77470ebadc8SJulia Lawall goto out_pdev; 77570ebadc8SJulia Lawall return; 77688d5e520Sabdoulaye berthe 77770ebadc8SJulia Lawall out_pdev: 778ae027eadSAtsushi Nemoto platform_device_put(pdev); 77970ebadc8SJulia Lawall out_gpio: 78088d5e520Sabdoulaye berthe gpiochip_remove(&iocled->chip); 78170ebadc8SJulia Lawall out_unmap: 78270ebadc8SJulia Lawall iounmap(iocled->mmioaddr); 78370ebadc8SJulia Lawall out_free: 78470ebadc8SJulia Lawall kfree(iocled); 785ae027eadSAtsushi Nemoto } 786ae027eadSAtsushi Nemoto #else /* CONFIG_LEDS_GPIO */ 787ae027eadSAtsushi Nemoto void __init txx9_iocled_init(unsigned long baseaddr, 788ae027eadSAtsushi Nemoto int basenum, unsigned int num, int lowactive, 789ae027eadSAtsushi Nemoto const char *color, char **deftriggers) 790ae027eadSAtsushi Nemoto { 791ae027eadSAtsushi Nemoto } 792ae027eadSAtsushi Nemoto #endif /* CONFIG_LEDS_GPIO */ 793f48c8c95SAtsushi Nemoto 794f48c8c95SAtsushi Nemoto void __init txx9_dmac_init(int id, unsigned long baseaddr, int irq, 795f48c8c95SAtsushi Nemoto const struct txx9dmac_platform_data *pdata) 796f48c8c95SAtsushi Nemoto { 797b33b4407SFlorian Fainelli #if IS_ENABLED(CONFIG_TXX9_DMAC) 798f48c8c95SAtsushi Nemoto struct resource res[] = { 799f48c8c95SAtsushi Nemoto { 800f48c8c95SAtsushi Nemoto .start = baseaddr, 801f48c8c95SAtsushi Nemoto .end = baseaddr + 0x800 - 1, 802f48c8c95SAtsushi Nemoto .flags = IORESOURCE_MEM, 803f48c8c95SAtsushi Nemoto #ifndef CONFIG_MACH_TX49XX 804f48c8c95SAtsushi Nemoto }, { 805f48c8c95SAtsushi Nemoto .start = irq, 806f48c8c95SAtsushi Nemoto .flags = IORESOURCE_IRQ, 807f48c8c95SAtsushi Nemoto #endif 808f48c8c95SAtsushi Nemoto } 809f48c8c95SAtsushi Nemoto }; 810f48c8c95SAtsushi Nemoto #ifdef CONFIG_MACH_TX49XX 811f48c8c95SAtsushi Nemoto struct resource chan_res[] = { 812f48c8c95SAtsushi Nemoto { 813f48c8c95SAtsushi Nemoto .flags = IORESOURCE_IRQ, 814f48c8c95SAtsushi Nemoto } 815f48c8c95SAtsushi Nemoto }; 816f48c8c95SAtsushi Nemoto #endif 817f48c8c95SAtsushi Nemoto struct platform_device *pdev = platform_device_alloc("txx9dmac", id); 818f48c8c95SAtsushi Nemoto struct txx9dmac_chan_platform_data cpdata; 819f48c8c95SAtsushi Nemoto int i; 820f48c8c95SAtsushi Nemoto 821f48c8c95SAtsushi Nemoto if (!pdev || 822f48c8c95SAtsushi Nemoto platform_device_add_resources(pdev, res, ARRAY_SIZE(res)) || 823f48c8c95SAtsushi Nemoto platform_device_add_data(pdev, pdata, sizeof(*pdata)) || 824f48c8c95SAtsushi Nemoto platform_device_add(pdev)) { 825f48c8c95SAtsushi Nemoto platform_device_put(pdev); 826f48c8c95SAtsushi Nemoto return; 827f48c8c95SAtsushi Nemoto } 828f48c8c95SAtsushi Nemoto memset(&cpdata, 0, sizeof(cpdata)); 829f48c8c95SAtsushi Nemoto cpdata.dmac_dev = pdev; 830f48c8c95SAtsushi Nemoto for (i = 0; i < TXX9_DMA_MAX_NR_CHANNELS; i++) { 831f48c8c95SAtsushi Nemoto #ifdef CONFIG_MACH_TX49XX 832f48c8c95SAtsushi Nemoto chan_res[0].start = irq + i; 833f48c8c95SAtsushi Nemoto #endif 834f48c8c95SAtsushi Nemoto pdev = platform_device_alloc("txx9dmac-chan", 835f48c8c95SAtsushi Nemoto id * TXX9_DMA_MAX_NR_CHANNELS + i); 836f48c8c95SAtsushi Nemoto if (!pdev || 837f48c8c95SAtsushi Nemoto #ifdef CONFIG_MACH_TX49XX 838f48c8c95SAtsushi Nemoto platform_device_add_resources(pdev, chan_res, 839f48c8c95SAtsushi Nemoto ARRAY_SIZE(chan_res)) || 840f48c8c95SAtsushi Nemoto #endif 841f48c8c95SAtsushi Nemoto platform_device_add_data(pdev, &cpdata, sizeof(cpdata)) || 842f48c8c95SAtsushi Nemoto platform_device_add(pdev)) 843f48c8c95SAtsushi Nemoto platform_device_put(pdev); 844f48c8c95SAtsushi Nemoto } 845f48c8c95SAtsushi Nemoto #endif 846f48c8c95SAtsushi Nemoto } 847742cd586SAtsushi Nemoto 848742cd586SAtsushi Nemoto void __init txx9_aclc_init(unsigned long baseaddr, int irq, 849742cd586SAtsushi Nemoto unsigned int dmac_id, 850742cd586SAtsushi Nemoto unsigned int dma_chan_out, 851742cd586SAtsushi Nemoto unsigned int dma_chan_in) 852742cd586SAtsushi Nemoto { 853b33b4407SFlorian Fainelli #if IS_ENABLED(CONFIG_SND_SOC_TXX9ACLC) 854742cd586SAtsushi Nemoto unsigned int dma_base = dmac_id * TXX9_DMA_MAX_NR_CHANNELS; 855742cd586SAtsushi Nemoto struct resource res[] = { 856742cd586SAtsushi Nemoto { 857742cd586SAtsushi Nemoto .start = baseaddr, 858742cd586SAtsushi Nemoto .end = baseaddr + 0x100 - 1, 859742cd586SAtsushi Nemoto .flags = IORESOURCE_MEM, 860742cd586SAtsushi Nemoto }, { 861742cd586SAtsushi Nemoto .start = irq, 862742cd586SAtsushi Nemoto .flags = IORESOURCE_IRQ, 863742cd586SAtsushi Nemoto }, { 864742cd586SAtsushi Nemoto .name = "txx9dmac-chan", 865742cd586SAtsushi Nemoto .start = dma_base + dma_chan_out, 866742cd586SAtsushi Nemoto .flags = IORESOURCE_DMA, 867742cd586SAtsushi Nemoto }, { 868742cd586SAtsushi Nemoto .name = "txx9dmac-chan", 869742cd586SAtsushi Nemoto .start = dma_base + dma_chan_in, 870742cd586SAtsushi Nemoto .flags = IORESOURCE_DMA, 871742cd586SAtsushi Nemoto } 872742cd586SAtsushi Nemoto }; 873742cd586SAtsushi Nemoto struct platform_device *pdev = 874742cd586SAtsushi Nemoto platform_device_alloc("txx9aclc-ac97", -1); 875742cd586SAtsushi Nemoto 876742cd586SAtsushi Nemoto if (!pdev || 877742cd586SAtsushi Nemoto platform_device_add_resources(pdev, res, ARRAY_SIZE(res)) || 878742cd586SAtsushi Nemoto platform_device_add(pdev)) 879742cd586SAtsushi Nemoto platform_device_put(pdev); 880742cd586SAtsushi Nemoto #endif 881742cd586SAtsushi Nemoto } 882c3b28ae2SAtsushi Nemoto 883269a3eb1SKay Sievers static struct bus_type txx9_sramc_subsys = { 884269a3eb1SKay Sievers .name = "txx9_sram", 885269a3eb1SKay Sievers .dev_name = "txx9_sram", 886269a3eb1SKay Sievers }; 887c3b28ae2SAtsushi Nemoto 888269a3eb1SKay Sievers struct txx9_sramc_dev { 889269a3eb1SKay Sievers struct device dev; 890c3b28ae2SAtsushi Nemoto struct bin_attribute bindata_attr; 891c3b28ae2SAtsushi Nemoto void __iomem *base; 892c3b28ae2SAtsushi Nemoto }; 893c3b28ae2SAtsushi Nemoto 8942c3c8beaSChris Wright static ssize_t txx9_sram_read(struct file *filp, struct kobject *kobj, 895c3b28ae2SAtsushi Nemoto struct bin_attribute *bin_attr, 896c3b28ae2SAtsushi Nemoto char *buf, loff_t pos, size_t size) 897c3b28ae2SAtsushi Nemoto { 898269a3eb1SKay Sievers struct txx9_sramc_dev *dev = bin_attr->private; 899c3b28ae2SAtsushi Nemoto size_t ramsize = bin_attr->size; 900c3b28ae2SAtsushi Nemoto 901c3b28ae2SAtsushi Nemoto if (pos >= ramsize) 902c3b28ae2SAtsushi Nemoto return 0; 903c3b28ae2SAtsushi Nemoto if (pos + size > ramsize) 904c3b28ae2SAtsushi Nemoto size = ramsize - pos; 905c3b28ae2SAtsushi Nemoto memcpy_fromio(buf, dev->base + pos, size); 906c3b28ae2SAtsushi Nemoto return size; 907c3b28ae2SAtsushi Nemoto } 908c3b28ae2SAtsushi Nemoto 9092c3c8beaSChris Wright static ssize_t txx9_sram_write(struct file *filp, struct kobject *kobj, 910c3b28ae2SAtsushi Nemoto struct bin_attribute *bin_attr, 911c3b28ae2SAtsushi Nemoto char *buf, loff_t pos, size_t size) 912c3b28ae2SAtsushi Nemoto { 913269a3eb1SKay Sievers struct txx9_sramc_dev *dev = bin_attr->private; 914c3b28ae2SAtsushi Nemoto size_t ramsize = bin_attr->size; 915c3b28ae2SAtsushi Nemoto 916c3b28ae2SAtsushi Nemoto if (pos >= ramsize) 917c3b28ae2SAtsushi Nemoto return 0; 918c3b28ae2SAtsushi Nemoto if (pos + size > ramsize) 919c3b28ae2SAtsushi Nemoto size = ramsize - pos; 920c3b28ae2SAtsushi Nemoto memcpy_toio(dev->base + pos, buf, size); 921c3b28ae2SAtsushi Nemoto return size; 922c3b28ae2SAtsushi Nemoto } 923c3b28ae2SAtsushi Nemoto 9241610c8a8SLevente Kurusa static void txx9_device_release(struct device *dev) 9251610c8a8SLevente Kurusa { 9261610c8a8SLevente Kurusa struct txx9_sramc_dev *tdev; 9271610c8a8SLevente Kurusa 9281610c8a8SLevente Kurusa tdev = container_of(dev, struct txx9_sramc_dev, dev); 9291610c8a8SLevente Kurusa kfree(tdev); 9301610c8a8SLevente Kurusa } 9311610c8a8SLevente Kurusa 932c3b28ae2SAtsushi Nemoto void __init txx9_sramc_init(struct resource *r) 933c3b28ae2SAtsushi Nemoto { 934269a3eb1SKay Sievers struct txx9_sramc_dev *dev; 935c3b28ae2SAtsushi Nemoto size_t size; 936c3b28ae2SAtsushi Nemoto int err; 937c3b28ae2SAtsushi Nemoto 938269a3eb1SKay Sievers err = subsys_system_register(&txx9_sramc_subsys, NULL); 939269a3eb1SKay Sievers if (err) 940c3b28ae2SAtsushi Nemoto return; 941c3b28ae2SAtsushi Nemoto dev = kzalloc(sizeof(*dev), GFP_KERNEL); 942c3b28ae2SAtsushi Nemoto if (!dev) 943c3b28ae2SAtsushi Nemoto return; 944c3b28ae2SAtsushi Nemoto size = resource_size(r); 945c3b28ae2SAtsushi Nemoto dev->base = ioremap(r->start, size); 9461610c8a8SLevente Kurusa if (!dev->base) { 9471610c8a8SLevente Kurusa kfree(dev); 9481610c8a8SLevente Kurusa return; 9491610c8a8SLevente Kurusa } 9501610c8a8SLevente Kurusa dev->dev.release = &txx9_device_release; 951269a3eb1SKay Sievers dev->dev.bus = &txx9_sramc_subsys; 952f937331bSWolfram Sang sysfs_bin_attr_init(&dev->bindata_attr); 953c3b28ae2SAtsushi Nemoto dev->bindata_attr.attr.name = "bindata"; 954c3b28ae2SAtsushi Nemoto dev->bindata_attr.attr.mode = S_IRUSR | S_IWUSR; 955c3b28ae2SAtsushi Nemoto dev->bindata_attr.read = txx9_sram_read; 956c3b28ae2SAtsushi Nemoto dev->bindata_attr.write = txx9_sram_write; 957c3b28ae2SAtsushi Nemoto dev->bindata_attr.size = size; 958c3b28ae2SAtsushi Nemoto dev->bindata_attr.private = dev; 959269a3eb1SKay Sievers err = device_register(&dev->dev); 960c3b28ae2SAtsushi Nemoto if (err) 9611610c8a8SLevente Kurusa goto exit_put; 962c3b28ae2SAtsushi Nemoto err = sysfs_create_bin_file(&dev->dev.kobj, &dev->bindata_attr); 963c3b28ae2SAtsushi Nemoto if (err) { 964269a3eb1SKay Sievers device_unregister(&dev->dev); 965c3b28ae2SAtsushi Nemoto iounmap(dev->base); 966c3b28ae2SAtsushi Nemoto kfree(dev); 967c3b28ae2SAtsushi Nemoto } 9681610c8a8SLevente Kurusa return; 9691610c8a8SLevente Kurusa exit_put: 9701610c8a8SLevente Kurusa put_device(&dev->dev); 9711610c8a8SLevente Kurusa return; 972c3b28ae2SAtsushi Nemoto } 973