^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2000, 2001, 2002, 2003, 2004 Broadcom Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Setup code for the SWARM board
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/memblock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/blkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/screen_info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/initrd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/bootinfo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/mipsregs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/reboot.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <asm/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <asm/traps.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <asm/sibyte/sb1250.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <asm/sibyte/bcm1480_regs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <asm/sibyte/sb1250_regs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #error invalid SiByte board configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <asm/sibyte/sb1250_genbus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <asm/sibyte/board.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) extern void bcm1480_setup(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) extern void sb1250_setup(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #error invalid SiByte board configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) extern int xicor_probe(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) extern int xicor_set_time(time64_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) extern time64_t xicor_get_time(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) extern int m41t81_probe(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) extern int m41t81_set_time(time64_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) extern time64_t m41t81_get_time(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) const char *get_system_type(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return "SiByte " SIBYTE_BOARD_NAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) int swarm_be_handler(struct pt_regs *regs, int is_fixup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (!is_fixup && (regs->cp0_cause & 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* Data bus error - print PA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) printk("DBE physical address: %010Lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) __read_64bit_c0_register($26, 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) enum swarm_rtc_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) RTC_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) RTC_XICOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) RTC_M41T81,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) enum swarm_rtc_type swarm_rtc_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) void read_persistent_clock64(struct timespec64 *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) time64_t sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) switch (swarm_rtc_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) case RTC_XICOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) sec = xicor_get_time();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) case RTC_M41T81:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) sec = m41t81_get_time();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) case RTC_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) sec = mktime64(2000, 1, 1, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) ts->tv_sec = sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) ts->tv_nsec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int update_persistent_clock64(struct timespec64 now)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) time64_t sec = now.tv_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) switch (swarm_rtc_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) case RTC_XICOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return xicor_set_time(sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) case RTC_M41T81:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return m41t81_set_time(sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) case RTC_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) void __init plat_mem_setup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) bcm1480_setup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) sb1250_setup();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #error invalid SiByte board configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) board_be_handler = swarm_be_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (xicor_probe())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) swarm_rtc_type = RTC_XICOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (m41t81_probe())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) swarm_rtc_type = RTC_M41T81;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #ifdef CONFIG_VT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) screen_info = (struct screen_info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .orig_video_page = 52,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .orig_video_mode = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .orig_video_cols = 80,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .flags = 12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .orig_video_ega_bx = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .orig_video_lines = 25,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .orig_video_isVGA = 0x22,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .orig_video_points = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /* XXXKW for CFE, get lines/cols from environment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #ifdef LEDS_PHYS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #ifdef CONFIG_SIBYTE_CARMEL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* XXXKW need to detect Monterey/LittleSur/etc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #undef LEDS_PHYS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #define LEDS_PHYS MLEDS_PHYS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) void setleds(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) void *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) reg = IOADDR(LEDS_PHYS) + 0x20 + ((3 - i) << 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (!str[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) writeb(' ', reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) writeb(str[i], reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #endif /* LEDS_PHYS */