init.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Nintendo 64 init.
  4. *
  5. * Copyright (C) 2021 Lauri Kasanen
  6. */
  7. #include <linux/init.h>
  8. #include <linux/ioport.h>
  9. #include <linux/irq.h>
  10. #include <linux/memblock.h>
  11. #include <linux/platform_device.h>
  12. #include <linux/platform_data/simplefb.h>
  13. #include <linux/string.h>
  14. #include <asm/bootinfo.h>
  15. #include <asm/fw/fw.h>
  16. #include <asm/time.h>
  17. #define IO_MEM_RESOURCE_START 0UL
  18. #define IO_MEM_RESOURCE_END 0x1fffffffUL
  19. /*
  20. * System-specifc irq names for clarity
  21. */
  22. #define MIPS_CPU_IRQ(x) (MIPS_CPU_IRQ_BASE + (x))
  23. #define MIPS_SOFTINT0_IRQ MIPS_CPU_IRQ(0)
  24. #define MIPS_SOFTINT1_IRQ MIPS_CPU_IRQ(1)
  25. #define RCP_IRQ MIPS_CPU_IRQ(2)
  26. #define CART_IRQ MIPS_CPU_IRQ(3)
  27. #define PRENMI_IRQ MIPS_CPU_IRQ(4)
  28. #define RDBR_IRQ MIPS_CPU_IRQ(5)
  29. #define RDBW_IRQ MIPS_CPU_IRQ(6)
  30. #define TIMER_IRQ MIPS_CPU_IRQ(7)
  31. static void __init iomem_resource_init(void)
  32. {
  33. iomem_resource.start = IO_MEM_RESOURCE_START;
  34. iomem_resource.end = IO_MEM_RESOURCE_END;
  35. }
  36. const char *get_system_type(void)
  37. {
  38. return "Nintendo 64";
  39. }
  40. void __init prom_init(void)
  41. {
  42. fw_init_cmdline();
  43. }
  44. #define W 320
  45. #define H 240
  46. #define REG_BASE ((u32 *) CKSEG1ADDR(0x4400000))
  47. static void __init n64rdp_write_reg(const u8 reg, const u32 value)
  48. {
  49. __raw_writel(value, REG_BASE + reg);
  50. }
  51. #undef REG_BASE
  52. static const u32 ntsc_320[] __initconst = {
  53. 0x00013212, 0x00000000, 0x00000140, 0x00000200,
  54. 0x00000000, 0x03e52239, 0x0000020d, 0x00000c15,
  55. 0x0c150c15, 0x006c02ec, 0x002501ff, 0x000e0204,
  56. 0x00000200, 0x00000400
  57. };
  58. #define MI_REG_BASE 0x4300000
  59. #define NUM_MI_REGS 4
  60. #define AI_REG_BASE 0x4500000
  61. #define NUM_AI_REGS 6
  62. #define PI_REG_BASE 0x4600000
  63. #define NUM_PI_REGS 5
  64. #define SI_REG_BASE 0x4800000
  65. #define NUM_SI_REGS 7
  66. static int __init n64_platform_init(void)
  67. {
  68. static const char simplefb_resname[] = "FB";
  69. static const struct simplefb_platform_data mode = {
  70. .width = W,
  71. .height = H,
  72. .stride = W * 2,
  73. .format = "r5g5b5a1"
  74. };
  75. struct resource res[3];
  76. void *orig;
  77. unsigned long phys;
  78. unsigned i;
  79. memset(res, 0, sizeof(struct resource) * 3);
  80. res[0].flags = IORESOURCE_MEM;
  81. res[0].start = MI_REG_BASE;
  82. res[0].end = MI_REG_BASE + NUM_MI_REGS * 4 - 1;
  83. res[1].flags = IORESOURCE_MEM;
  84. res[1].start = AI_REG_BASE;
  85. res[1].end = AI_REG_BASE + NUM_AI_REGS * 4 - 1;
  86. res[2].flags = IORESOURCE_IRQ;
  87. res[2].start = RCP_IRQ;
  88. res[2].end = RCP_IRQ;
  89. platform_device_register_simple("n64audio", -1, res, 3);
  90. memset(&res[0], 0, sizeof(res[0]));
  91. res[0].flags = IORESOURCE_MEM;
  92. res[0].start = PI_REG_BASE;
  93. res[0].end = PI_REG_BASE + NUM_PI_REGS * 4 - 1;
  94. platform_device_register_simple("n64cart", -1, res, 1);
  95. memset(&res[0], 0, sizeof(res[0]));
  96. res[0].flags = IORESOURCE_MEM;
  97. res[0].start = SI_REG_BASE;
  98. res[0].end = SI_REG_BASE + NUM_SI_REGS * 4 - 1;
  99. platform_device_register_simple("n64joy", -1, res, 1);
  100. /* The framebuffer needs 64-byte alignment */
  101. orig = kzalloc(W * H * 2 + 63, GFP_DMA | GFP_KERNEL);
  102. if (!orig)
  103. return -ENOMEM;
  104. phys = virt_to_phys(orig);
  105. phys += 63;
  106. phys &= ~63;
  107. for (i = 0; i < ARRAY_SIZE(ntsc_320); i++) {
  108. if (i == 1)
  109. n64rdp_write_reg(i, phys);
  110. else
  111. n64rdp_write_reg(i, ntsc_320[i]);
  112. }
  113. /* setup IORESOURCE_MEM as framebuffer memory */
  114. memset(&res[0], 0, sizeof(res[0]));
  115. res[0].flags = IORESOURCE_MEM;
  116. res[0].name = simplefb_resname;
  117. res[0].start = phys;
  118. res[0].end = phys + W * H * 2 - 1;
  119. platform_device_register_resndata(NULL, "simple-framebuffer", 0,
  120. &res[0], 1, &mode, sizeof(mode));
  121. return 0;
  122. }
  123. #undef W
  124. #undef H
  125. arch_initcall(n64_platform_init);
  126. void __init plat_mem_setup(void)
  127. {
  128. iomem_resource_init();
  129. memblock_add(0x0, 8 * 1024 * 1024); /* Bootloader blocks the 4mb config */
  130. }
  131. void __init plat_time_init(void)
  132. {
  133. /* 93.75 MHz cpu, count register runs at half rate */
  134. mips_hpt_frequency = 93750000 / 2;
  135. }