setup.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. /*
  2. * linux/arch/mips/txx9/generic/setup.c
  3. *
  4. * Based on linux/arch/mips/txx9/rbtx4938/setup.c,
  5. * and RBTX49xx patch from CELF patch archive.
  6. *
  7. * 2003-2005 (c) MontaVista Software, Inc.
  8. * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007
  9. *
  10. * This file is subject to the terms and conditions of the GNU General Public
  11. * License. See the file "COPYING" in the main directory of this archive
  12. * for more details.
  13. */
  14. #include <linux/init.h>
  15. #include <linux/kernel.h>
  16. #include <linux/types.h>
  17. #include <linux/interrupt.h>
  18. #include <linux/string.h>
  19. #include <linux/module.h>
  20. #include <linux/clk.h>
  21. #include <linux/err.h>
  22. #include <linux/gpio.h>
  23. #include <linux/platform_device.h>
  24. #include <linux/serial_core.h>
  25. #include <linux/mtd/physmap.h>
  26. #include <asm/bootinfo.h>
  27. #include <asm/time.h>
  28. #include <asm/reboot.h>
  29. #include <asm/r4kcache.h>
  30. #include <asm/txx9/generic.h>
  31. #include <asm/txx9/pci.h>
  32. #ifdef CONFIG_CPU_TX49XX
  33. #include <asm/txx9/tx4938.h>
  34. #endif
  35. /* EBUSC settings of TX4927, etc. */
  36. struct resource txx9_ce_res[8];
  37. static char txx9_ce_res_name[8][4]; /* "CEn" */
  38. /* pcode, internal register */
  39. unsigned int txx9_pcode;
  40. char txx9_pcode_str[8];
  41. static struct resource txx9_reg_res = {
  42. .name = txx9_pcode_str,
  43. .flags = IORESOURCE_MEM,
  44. };
  45. void __init
  46. txx9_reg_res_init(unsigned int pcode, unsigned long base, unsigned long size)
  47. {
  48. int i;
  49. for (i = 0; i < ARRAY_SIZE(txx9_ce_res); i++) {
  50. sprintf(txx9_ce_res_name[i], "CE%d", i);
  51. txx9_ce_res[i].flags = IORESOURCE_MEM;
  52. txx9_ce_res[i].name = txx9_ce_res_name[i];
  53. }
  54. txx9_pcode = pcode;
  55. sprintf(txx9_pcode_str, "TX%x", pcode);
  56. if (base) {
  57. txx9_reg_res.start = base & 0xfffffffffULL;
  58. txx9_reg_res.end = (base & 0xfffffffffULL) + (size - 1);
  59. request_resource(&iomem_resource, &txx9_reg_res);
  60. }
  61. }
  62. /* clocks */
  63. unsigned int txx9_master_clock;
  64. unsigned int txx9_cpu_clock;
  65. unsigned int txx9_gbus_clock;
  66. #ifdef CONFIG_CPU_TX39XX
  67. /* don't enable by default - see errata */
  68. int txx9_ccfg_toeon __initdata;
  69. #else
  70. int txx9_ccfg_toeon __initdata = 1;
  71. #endif
  72. /* Minimum CLK support */
  73. struct clk *clk_get(struct device *dev, const char *id)
  74. {
  75. if (!strcmp(id, "spi-baseclk"))
  76. return (struct clk *)((unsigned long)txx9_gbus_clock / 2 / 4);
  77. if (!strcmp(id, "imbus_clk"))
  78. return (struct clk *)((unsigned long)txx9_gbus_clock / 2);
  79. return ERR_PTR(-ENOENT);
  80. }
  81. EXPORT_SYMBOL(clk_get);
  82. int clk_enable(struct clk *clk)
  83. {
  84. return 0;
  85. }
  86. EXPORT_SYMBOL(clk_enable);
  87. void clk_disable(struct clk *clk)
  88. {
  89. }
  90. EXPORT_SYMBOL(clk_disable);
  91. unsigned long clk_get_rate(struct clk *clk)
  92. {
  93. return (unsigned long)clk;
  94. }
  95. EXPORT_SYMBOL(clk_get_rate);
  96. void clk_put(struct clk *clk)
  97. {
  98. }
  99. EXPORT_SYMBOL(clk_put);
  100. /* GPIO support */
  101. #ifdef CONFIG_GENERIC_GPIO
  102. int gpio_to_irq(unsigned gpio)
  103. {
  104. return -EINVAL;
  105. }
  106. EXPORT_SYMBOL(gpio_to_irq);
  107. int irq_to_gpio(unsigned irq)
  108. {
  109. return -EINVAL;
  110. }
  111. EXPORT_SYMBOL(irq_to_gpio);
  112. #endif
  113. #define BOARD_VEC(board) extern struct txx9_board_vec board;
  114. #include <asm/txx9/boards.h>
  115. #undef BOARD_VEC
  116. struct txx9_board_vec *txx9_board_vec __initdata;
  117. static char txx9_system_type[32];
  118. static struct txx9_board_vec *board_vecs[] __initdata = {
  119. #define BOARD_VEC(board) &board,
  120. #include <asm/txx9/boards.h>
  121. #undef BOARD_VEC
  122. };
  123. static struct txx9_board_vec *__init find_board_byname(const char *name)
  124. {
  125. int i;
  126. /* search board_vecs table */
  127. for (i = 0; i < ARRAY_SIZE(board_vecs); i++) {
  128. if (strstr(board_vecs[i]->system, name))
  129. return board_vecs[i];
  130. }
  131. return NULL;
  132. }
  133. static void __init prom_init_cmdline(void)
  134. {
  135. int argc = (int)fw_arg0;
  136. int *argv32 = (int *)fw_arg1;
  137. int i; /* Always ignore the "-c" at argv[0] */
  138. char builtin[CL_SIZE];
  139. /* ignore all built-in args if any f/w args given */
  140. /*
  141. * But if built-in strings was started with '+', append them
  142. * to command line args. If built-in was started with '-',
  143. * ignore all f/w args.
  144. */
  145. builtin[0] = '\0';
  146. if (arcs_cmdline[0] == '+')
  147. strcpy(builtin, arcs_cmdline + 1);
  148. else if (arcs_cmdline[0] == '-') {
  149. strcpy(builtin, arcs_cmdline + 1);
  150. argc = 0;
  151. } else if (argc <= 1)
  152. strcpy(builtin, arcs_cmdline);
  153. arcs_cmdline[0] = '\0';
  154. for (i = 1; i < argc; i++) {
  155. char *str = (char *)(long)argv32[i];
  156. if (i != 1)
  157. strcat(arcs_cmdline, " ");
  158. if (strchr(str, ' ')) {
  159. strcat(arcs_cmdline, "\"");
  160. strcat(arcs_cmdline, str);
  161. strcat(arcs_cmdline, "\"");
  162. } else
  163. strcat(arcs_cmdline, str);
  164. }
  165. /* append saved builtin args */
  166. if (builtin[0]) {
  167. if (arcs_cmdline[0])
  168. strcat(arcs_cmdline, " ");
  169. strcat(arcs_cmdline, builtin);
  170. }
  171. }
  172. static int txx9_ic_disable __initdata;
  173. static int txx9_dc_disable __initdata;
  174. #if defined(CONFIG_CPU_TX49XX)
  175. /* flush all cache on very early stage (before 4k_cache_init) */
  176. static void __init early_flush_dcache(void)
  177. {
  178. unsigned int conf = read_c0_config();
  179. unsigned int dc_size = 1 << (12 + ((conf & CONF_DC) >> 6));
  180. unsigned int linesz = 32;
  181. unsigned long addr, end;
  182. end = INDEX_BASE + dc_size / 4;
  183. /* 4way, waybit=0 */
  184. for (addr = INDEX_BASE; addr < end; addr += linesz) {
  185. cache_op(Index_Writeback_Inv_D, addr | 0);
  186. cache_op(Index_Writeback_Inv_D, addr | 1);
  187. cache_op(Index_Writeback_Inv_D, addr | 2);
  188. cache_op(Index_Writeback_Inv_D, addr | 3);
  189. }
  190. }
  191. static void __init txx9_cache_fixup(void)
  192. {
  193. unsigned int conf;
  194. conf = read_c0_config();
  195. /* flush and disable */
  196. if (txx9_ic_disable) {
  197. conf |= TX49_CONF_IC;
  198. write_c0_config(conf);
  199. }
  200. if (txx9_dc_disable) {
  201. early_flush_dcache();
  202. conf |= TX49_CONF_DC;
  203. write_c0_config(conf);
  204. }
  205. /* enable cache */
  206. conf = read_c0_config();
  207. if (!txx9_ic_disable)
  208. conf &= ~TX49_CONF_IC;
  209. if (!txx9_dc_disable)
  210. conf &= ~TX49_CONF_DC;
  211. write_c0_config(conf);
  212. if (conf & TX49_CONF_IC)
  213. pr_info("TX49XX I-Cache disabled.\n");
  214. if (conf & TX49_CONF_DC)
  215. pr_info("TX49XX D-Cache disabled.\n");
  216. }
  217. #elif defined(CONFIG_CPU_TX39XX)
  218. /* flush all cache on very early stage (before tx39_cache_init) */
  219. static void __init early_flush_dcache(void)
  220. {
  221. unsigned int conf = read_c0_config();
  222. unsigned int dc_size = 1 << (10 + ((conf & TX39_CONF_DCS_MASK) >>
  223. TX39_CONF_DCS_SHIFT));
  224. unsigned int linesz = 16;
  225. unsigned long addr, end;
  226. end = INDEX_BASE + dc_size / 2;
  227. /* 2way, waybit=0 */
  228. for (addr = INDEX_BASE; addr < end; addr += linesz) {
  229. cache_op(Index_Writeback_Inv_D, addr | 0);
  230. cache_op(Index_Writeback_Inv_D, addr | 1);
  231. }
  232. }
  233. static void __init txx9_cache_fixup(void)
  234. {
  235. unsigned int conf;
  236. conf = read_c0_config();
  237. /* flush and disable */
  238. if (txx9_ic_disable) {
  239. conf &= ~TX39_CONF_ICE;
  240. write_c0_config(conf);
  241. }
  242. if (txx9_dc_disable) {
  243. early_flush_dcache();
  244. conf &= ~TX39_CONF_DCE;
  245. write_c0_config(conf);
  246. }
  247. /* enable cache */
  248. conf = read_c0_config();
  249. if (!txx9_ic_disable)
  250. conf |= TX39_CONF_ICE;
  251. if (!txx9_dc_disable)
  252. conf |= TX39_CONF_DCE;
  253. write_c0_config(conf);
  254. if (!(conf & TX39_CONF_ICE))
  255. pr_info("TX39XX I-Cache disabled.\n");
  256. if (!(conf & TX39_CONF_DCE))
  257. pr_info("TX39XX D-Cache disabled.\n");
  258. }
  259. #else
  260. static inline void txx9_cache_fixup(void)
  261. {
  262. }
  263. #endif
  264. static void __init preprocess_cmdline(void)
  265. {
  266. char cmdline[CL_SIZE];
  267. char *s;
  268. strcpy(cmdline, arcs_cmdline);
  269. s = cmdline;
  270. arcs_cmdline[0] = '\0';
  271. while (s && *s) {
  272. char *str = strsep(&s, " ");
  273. if (strncmp(str, "board=", 6) == 0) {
  274. txx9_board_vec = find_board_byname(str + 6);
  275. continue;
  276. } else if (strncmp(str, "masterclk=", 10) == 0) {
  277. unsigned long val;
  278. if (strict_strtoul(str + 10, 10, &val) == 0)
  279. txx9_master_clock = val;
  280. continue;
  281. } else if (strcmp(str, "icdisable") == 0) {
  282. txx9_ic_disable = 1;
  283. continue;
  284. } else if (strcmp(str, "dcdisable") == 0) {
  285. txx9_dc_disable = 1;
  286. continue;
  287. } else if (strcmp(str, "toeoff") == 0) {
  288. txx9_ccfg_toeon = 0;
  289. continue;
  290. } else if (strcmp(str, "toeon") == 0) {
  291. txx9_ccfg_toeon = 1;
  292. continue;
  293. }
  294. if (arcs_cmdline[0])
  295. strcat(arcs_cmdline, " ");
  296. strcat(arcs_cmdline, str);
  297. }
  298. txx9_cache_fixup();
  299. }
  300. static void __init select_board(void)
  301. {
  302. const char *envstr;
  303. /* first, determine by "board=" argument in preprocess_cmdline() */
  304. if (txx9_board_vec)
  305. return;
  306. /* next, determine by "board" envvar */
  307. envstr = prom_getenv("board");
  308. if (envstr) {
  309. txx9_board_vec = find_board_byname(envstr);
  310. if (txx9_board_vec)
  311. return;
  312. }
  313. /* select "default" board */
  314. #ifdef CONFIG_CPU_TX39XX
  315. txx9_board_vec = &jmr3927_vec;
  316. #endif
  317. #ifdef CONFIG_CPU_TX49XX
  318. switch (TX4938_REV_PCODE()) {
  319. #ifdef CONFIG_TOSHIBA_RBTX4927
  320. case 0x4927:
  321. txx9_board_vec = &rbtx4927_vec;
  322. break;
  323. case 0x4937:
  324. txx9_board_vec = &rbtx4937_vec;
  325. break;
  326. #endif
  327. #ifdef CONFIG_TOSHIBA_RBTX4938
  328. case 0x4938:
  329. txx9_board_vec = &rbtx4938_vec;
  330. break;
  331. #endif
  332. }
  333. #endif
  334. }
  335. void __init prom_init(void)
  336. {
  337. prom_init_cmdline();
  338. preprocess_cmdline();
  339. select_board();
  340. strcpy(txx9_system_type, txx9_board_vec->system);
  341. txx9_board_vec->prom_init();
  342. }
  343. void __init prom_free_prom_memory(void)
  344. {
  345. }
  346. const char *get_system_type(void)
  347. {
  348. return txx9_system_type;
  349. }
  350. char * __init prom_getcmdline(void)
  351. {
  352. return &(arcs_cmdline[0]);
  353. }
  354. const char *__init prom_getenv(const char *name)
  355. {
  356. const s32 *str = (const s32 *)fw_arg2;
  357. if (!str)
  358. return NULL;
  359. /* YAMON style ("name", "value" pairs) */
  360. while (str[0] && str[1]) {
  361. if (!strcmp((const char *)(unsigned long)str[0], name))
  362. return (const char *)(unsigned long)str[1];
  363. str += 2;
  364. }
  365. return NULL;
  366. }
  367. static void __noreturn txx9_machine_halt(void)
  368. {
  369. local_irq_disable();
  370. clear_c0_status(ST0_IM);
  371. while (1) {
  372. if (cpu_wait) {
  373. (*cpu_wait)();
  374. if (cpu_has_counter) {
  375. /*
  376. * Clear counter interrupt while it
  377. * breaks WAIT instruction even if
  378. * masked.
  379. */
  380. write_c0_compare(0);
  381. }
  382. }
  383. }
  384. }
  385. /* Watchdog support */
  386. void __init txx9_wdt_init(unsigned long base)
  387. {
  388. struct resource res = {
  389. .start = base,
  390. .end = base + 0x100 - 1,
  391. .flags = IORESOURCE_MEM,
  392. };
  393. platform_device_register_simple("txx9wdt", -1, &res, 1);
  394. }
  395. /* SPI support */
  396. void __init txx9_spi_init(int busid, unsigned long base, int irq)
  397. {
  398. struct resource res[] = {
  399. {
  400. .start = base,
  401. .end = base + 0x20 - 1,
  402. .flags = IORESOURCE_MEM,
  403. }, {
  404. .start = irq,
  405. .flags = IORESOURCE_IRQ,
  406. },
  407. };
  408. platform_device_register_simple("spi_txx9", busid,
  409. res, ARRAY_SIZE(res));
  410. }
  411. void __init txx9_ethaddr_init(unsigned int id, unsigned char *ethaddr)
  412. {
  413. struct platform_device *pdev =
  414. platform_device_alloc("tc35815-mac", id);
  415. if (!pdev ||
  416. platform_device_add_data(pdev, ethaddr, 6) ||
  417. platform_device_add(pdev))
  418. platform_device_put(pdev);
  419. }
  420. void __init txx9_sio_init(unsigned long baseaddr, int irq,
  421. unsigned int line, unsigned int sclk, int nocts)
  422. {
  423. #ifdef CONFIG_SERIAL_TXX9
  424. struct uart_port req;
  425. memset(&req, 0, sizeof(req));
  426. req.line = line;
  427. req.iotype = UPIO_MEM;
  428. req.membase = ioremap(baseaddr, 0x24);
  429. req.mapbase = baseaddr;
  430. req.irq = irq;
  431. if (!nocts)
  432. req.flags |= UPF_BUGGY_UART /*HAVE_CTS_LINE*/;
  433. if (sclk) {
  434. req.flags |= UPF_MAGIC_MULTIPLIER /*USE_SCLK*/;
  435. req.uartclk = sclk;
  436. } else
  437. req.uartclk = TXX9_IMCLK;
  438. early_serial_txx9_setup(&req);
  439. #endif /* CONFIG_SERIAL_TXX9 */
  440. }
  441. #ifdef CONFIG_EARLY_PRINTK
  442. static void __init null_prom_putchar(char c)
  443. {
  444. }
  445. void (*txx9_prom_putchar)(char c) __initdata = null_prom_putchar;
  446. void __init prom_putchar(char c)
  447. {
  448. txx9_prom_putchar(c);
  449. }
  450. static void __iomem *early_txx9_sio_port;
  451. static void __init early_txx9_sio_putchar(char c)
  452. {
  453. #define TXX9_SICISR 0x0c
  454. #define TXX9_SITFIFO 0x1c
  455. #define TXX9_SICISR_TXALS 0x00000002
  456. while (!(__raw_readl(early_txx9_sio_port + TXX9_SICISR) &
  457. TXX9_SICISR_TXALS))
  458. ;
  459. __raw_writel(c, early_txx9_sio_port + TXX9_SITFIFO);
  460. }
  461. void __init txx9_sio_putchar_init(unsigned long baseaddr)
  462. {
  463. early_txx9_sio_port = ioremap(baseaddr, 0x24);
  464. txx9_prom_putchar = early_txx9_sio_putchar;
  465. }
  466. #endif /* CONFIG_EARLY_PRINTK */
  467. /* wrappers */
  468. void __init plat_mem_setup(void)
  469. {
  470. ioport_resource.start = 0;
  471. ioport_resource.end = ~0UL; /* no limit */
  472. iomem_resource.start = 0;
  473. iomem_resource.end = ~0UL; /* no limit */
  474. /* fallback restart/halt routines */
  475. _machine_restart = (void (*)(char *))txx9_machine_halt;
  476. _machine_halt = txx9_machine_halt;
  477. pm_power_off = txx9_machine_halt;
  478. #ifdef CONFIG_PCI
  479. pcibios_plat_setup = txx9_pcibios_setup;
  480. #endif
  481. txx9_board_vec->mem_setup();
  482. }
  483. void __init arch_init_irq(void)
  484. {
  485. txx9_board_vec->irq_setup();
  486. }
  487. void __init plat_time_init(void)
  488. {
  489. #ifdef CONFIG_CPU_TX49XX
  490. mips_hpt_frequency = txx9_cpu_clock / 2;
  491. #endif
  492. txx9_board_vec->time_init();
  493. }
  494. static int __init _txx9_arch_init(void)
  495. {
  496. if (txx9_board_vec->arch_init)
  497. txx9_board_vec->arch_init();
  498. return 0;
  499. }
  500. arch_initcall(_txx9_arch_init);
  501. static int __init _txx9_device_init(void)
  502. {
  503. if (txx9_board_vec->device_init)
  504. txx9_board_vec->device_init();
  505. return 0;
  506. }
  507. device_initcall(_txx9_device_init);
  508. int (*txx9_irq_dispatch)(int pending);
  509. asmlinkage void plat_irq_dispatch(void)
  510. {
  511. int pending = read_c0_status() & read_c0_cause() & ST0_IM;
  512. int irq = txx9_irq_dispatch(pending);
  513. if (likely(irq >= 0))
  514. do_IRQ(irq);
  515. else
  516. spurious_interrupt();
  517. }
  518. /* see include/asm-mips/mach-tx39xx/mangle-port.h, for example. */
  519. #ifdef NEEDS_TXX9_SWIZZLE_ADDR_B
  520. static unsigned long __swizzle_addr_none(unsigned long port)
  521. {
  522. return port;
  523. }
  524. unsigned long (*__swizzle_addr_b)(unsigned long port) = __swizzle_addr_none;
  525. EXPORT_SYMBOL(__swizzle_addr_b);
  526. #endif
  527. void __init txx9_physmap_flash_init(int no, unsigned long addr,
  528. unsigned long size,
  529. const struct physmap_flash_data *pdata)
  530. {
  531. #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
  532. struct resource res = {
  533. .start = addr,
  534. .end = addr + size - 1,
  535. .flags = IORESOURCE_MEM,
  536. };
  537. struct platform_device *pdev;
  538. #ifdef CONFIG_MTD_PARTITIONS
  539. static struct mtd_partition parts[2];
  540. struct physmap_flash_data pdata_part;
  541. /* If this area contained boot area, make separate partition */
  542. if (pdata->nr_parts == 0 && !pdata->parts &&
  543. addr < 0x1fc00000 && addr + size > 0x1fc00000 &&
  544. !parts[0].name) {
  545. parts[0].name = "boot";
  546. parts[0].offset = 0x1fc00000 - addr;
  547. parts[0].size = addr + size - 0x1fc00000;
  548. parts[1].name = "user";
  549. parts[1].offset = 0;
  550. parts[1].size = 0x1fc00000 - addr;
  551. pdata_part = *pdata;
  552. pdata_part.nr_parts = ARRAY_SIZE(parts);
  553. pdata_part.parts = parts;
  554. pdata = &pdata_part;
  555. }
  556. #endif
  557. pdev = platform_device_alloc("physmap-flash", no);
  558. if (!pdev ||
  559. platform_device_add_resources(pdev, &res, 1) ||
  560. platform_device_add_data(pdev, pdata, sizeof(*pdata)) ||
  561. platform_device_add(pdev))
  562. platform_device_put(pdev);
  563. #endif
  564. }