1 /* prom.c - emulates a sparc v0 PROM for the linux kernel.
3 * Copyright (C) 2003 Konrad Eisele <eiselekd@web.de>
4 * Copyright (C) 2004 Stefan Holst <mail@s-holst.de>
5 * Copyright (C) 2007 Daniel Hellstrom <daniel@gaisler.com>
7 * SPDX-License-Identifier: GPL-2.0+
12 #include <asm/machines.h>
13 #include <asm/srmmu.h>
14 #include <asm/processor.h>
18 #include <grlib/apbuart.h>
19 #include <grlib/irqmp.h>
20 #include <grlib/gptimer.h>
26 extern struct linux_romvec *kernel_arg_promvec;
28 DECLARE_GLOBAL_DATA_PTR;
30 #define PROM_PGT __attribute__ ((__section__ (".prom.pgt")))
31 #define PROM_TEXT __attribute__ ((__section__ (".prom.text")))
32 #define PROM_DATA __attribute__ ((__section__ (".prom.data")))
34 ambapp_dev_gptimer *gptimer;
36 void *__prom_start_reloc; /* relocated prom_start address */
39 extern int __prom_start;
40 #define PAGE_OFFSET 0xf0000000
41 #define phys_base CONFIG_SYS_SDRAM_BASE
42 #define PROM_OFFS 8192
43 #define PROM_SIZE_MASK (PROM_OFFS-1)
45 (void *)( ((unsigned long)(x))-PROM_OFFS+ \
46 (CONFIG_SYS_PROM_OFFSET-phys_base)+PAGE_OFFSET-CONFIG_SYS_TEXT_BASE ) \
48 #define __phy(x) ((void *)(((unsigned long)(x))-PROM_OFFS+CONFIG_SYS_PROM_OFFSET-CONFIG_SYS_TEXT_BASE))
58 struct property *properties;
61 static void leon_reboot(char *bcommand);
62 static void leon_halt(void);
63 static int leon_nbputchar(int c);
64 static int leon_nbgetchar(void);
66 static int no_nextnode(int node);
67 static int no_child(int node);
68 static int no_proplen(int node, char *name);
69 static int no_getprop(int node, char *name, char *value);
70 static int no_setprop(int node, char *name, char *value, int len);
71 static char *no_nextprop(int node, char *name);
73 static struct property PROM_TEXT *find_property(int node, char *name);
74 static int PROM_TEXT leon_strcmp(const char *s1, const char *s2);
75 static void *PROM_TEXT leon_memcpy(void *dest, const void *src, size_t n);
76 static void PROM_TEXT leon_reboot_physical(char *bcommand);
78 void __inline__ leon_flush_cache_all(void)
80 __asm__ __volatile__(" flush ");
81 __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t"::"i"(ASI_DFLUSH):"memory");
84 void __inline__ leon_flush_tlb_all(void)
86 leon_flush_cache_all();
87 __asm__ __volatile__("sta %%g0, [%0] %1\n\t"::"r"(0x400),
88 "i"(ASI_MMUFLUSH):"memory");
92 unsigned int ctx_table[256];
93 unsigned int pgd_table[256];
96 sparc_srmmu_setup srmmu_tables PROM_PGT = {
338 0x400001e /* default */
342 /* a self contained prom info structure */
343 struct leon_reloc_func {
344 struct property *(*find_property) (int node, char *name);
345 int (*strcmp) (char *s1, char *s2);
346 void *(*memcpy) (void *dest, const void *src, size_t n);
347 void (*reboot_physical) (char *cmd);
348 ambapp_dev_apbuart *leon3_apbuart;
351 struct leon_prom_info {
356 struct leon_reloc_func reloc_funcs;
357 struct property root_properties[4];
358 struct property cpu_properties[7];
360 #define CPUENTRY(idx) struct property cpu_properties##idx[4]
392 struct idprom idprom;
393 struct linux_nodeops nodeops;
394 struct linux_mlist_v0 *totphys_p;
395 struct linux_mlist_v0 totphys;
396 struct linux_mlist_v0 *avail_p;
397 struct linux_mlist_v0 avail;
398 struct linux_mlist_v0 *prommap_p;
399 void (*synchook) (void);
400 struct linux_arguments_v0 *bootargs_p;
401 struct linux_arguments_v0 bootargs;
402 struct linux_romvec romvec;
403 struct node nodes[35];
404 char s_device_type[12];
408 char s_compatability[14];
411 char s_frequency[16];
412 char s_uart1_baud[11];
413 char s_uart2_baud[11];
417 /* static prom info */
418 static struct leon_prom_info PROM_DATA spi = {
419 CONFIG_SYS_CLK_FREQ / 1000,
423 #define CPUENTRY(idx) idx
461 __phy(leon_reboot_physical),
464 {__va(spi.s_device_type), __va(spi.s_idprom), 4},
465 {__va(spi.s_idprom), (char *)__va(&spi.idprom), sizeof(struct idprom)},
466 {__va(spi.s_compatability), __va(spi.s_leon2), 5},
470 {__va(spi.s_device_type), __va(spi.s_cpu), 4},
471 {__va(spi.s_mid), __va(&spi.mids[0]), 4},
472 {__va(spi.s_mmu_nctx), (char *)__va(&spi.leon_nctx), 4},
473 {__va(spi.s_frequency), (char *)__va(&spi.freq_khz), 4},
474 {__va(spi.s_uart1_baud), (char *)__va(&spi.baudrates[0]), 4},
475 {__va(spi.s_uart2_baud), (char *)__va(&spi.baudrates[1]), 4},
479 #define CPUENTRY(idx) \
480 { /* cpu_properties */ \
481 {__va(spi.s_device_type), __va(spi.s_cpu), 4}, \
482 {__va(spi.s_mid), __va(&spi.mids[idx]), 4}, \
483 {__va(spi.s_frequency), (char *)__va(&spi.freq_khz), 4}, \
519 M_LEON2 | M_LEON2_SOC, /* machine type */
520 {0, 0, 0, 0, 0, 0}, /* eth */
524 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* reserved */
537 (char *)CONFIG_SYS_SDRAM_BASE,
543 (char *)CONFIG_SYS_SDRAM_BASE,
546 NULL, /* prommap_p */
550 {NULL, __va(spi.arg), NULL /*... */ },
555 0, /* sun4c v0 prom */
557 {__va(&spi.totphys_p), __va(&spi.prommap_p), __va(&spi.avail_p)},
559 NULL, {NULL /* ... */ },
561 NULL, NULL, /* pv_getchar, pv_putchar */
562 __va(leon_nbgetchar), __va(leon_nbputchar),
571 __va(&spi.bootargs_p)
575 {0, __va(spi.root_properties + 3) /* NULL, NULL, -1 */ },
576 {0, __va(spi.root_properties)},
577 /* cpu 0, must be spi.nodes[2] see leon_prom_init() */
578 {1, __va(spi.cpu_properties)},
581 #define CPUENTRY(idx) \
582 {1, __va(spi.cpu_properties##idx) } /* cpu <idx> */
614 {-1, __va(spi.root_properties + 3) /* NULL, NULL, -1 */ }
626 CONFIG_DEFAULT_KERNEL_COMMAND_LINE
629 /* from arch/sparc/kernel/setup.c */
630 #define RAMDISK_LOAD_FLAG 0x4000
631 extern unsigned short root_flags;
632 extern unsigned short root_dev;
633 extern unsigned short ram_flags;
634 extern unsigned int sparc_ramdisk_image;
635 extern unsigned int sparc_ramdisk_size;
636 extern int root_mountflags;
638 extern char initrd_end, initrd_start;
640 /* Reboot the CPU = jump to beginning of flash again.
642 * Make sure that all function are inlined here.
644 static void PROM_TEXT leon_reboot(char *bcommand)
646 register char *arg = bcommand;
647 void __attribute__ ((noreturn)) (*reboot_physical) (char *cmd);
649 /* get physical address */
650 struct leon_prom_info *pspi =
651 (void *)(CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables));
653 unsigned int *srmmu_ctx_table;
655 /* Turn of Interrupts */
658 /* Set kernel's context, context zero */
659 srmmu_set_context(0);
661 /* Get physical address of the MMU shutdown routine */
662 reboot_physical = (void *)
663 SPARC_BYPASS_READ(&pspi->reloc_funcs.reboot_physical);
665 /* Now that we know the physical address of the function
666 * we can make the MMU allow jumping to it.
668 srmmu_ctx_table = (unsigned int *)srmmu_get_ctable_ptr();
670 srmmu_ctx_table = (unsigned int *)SPARC_BYPASS_READ(srmmu_ctx_table);
672 /* get physical address of kernel's context table (assume ptd) */
673 srmmu_ctx_table = (unsigned int *)
674 (((unsigned int)srmmu_ctx_table & 0xfffffffc) << 4);
676 /* enable access to physical address of MMU shutdown function */
677 SPARC_BYPASS_WRITE(&srmmu_ctx_table
678 [((unsigned int)reboot_physical) >> 24],
679 (((unsigned int)reboot_physical & 0xff000000) >> 4) |
682 /* flush TLB cache */
683 leon_flush_tlb_all();
685 /* flash instruction & data cache */
686 sparc_icache_flush_all();
687 sparc_dcache_flush_all();
689 /* jump to physical address function
690 * so that when the MMU is disabled
691 * we can continue to execute
693 reboot_physical(arg);
696 static void PROM_TEXT leon_reboot_physical(char *bcommand)
698 void __attribute__ ((noreturn)) (*reset) (void);
703 /* Hardcoded start address */
704 reset = CONFIG_SYS_MONITOR_BASE;
706 /* flush data cache */
707 sparc_dcache_flush_all();
709 /* flush instruction cache */
710 sparc_icache_flush_all();
712 /* Jump to start in Flash */
716 static void PROM_TEXT leon_halt(void)
721 /* get single char, don't care for blocking*/
722 static int PROM_TEXT leon_nbgetchar(void)
727 /* put single char, don't care for blocking*/
728 static int PROM_TEXT leon_nbputchar(int c)
730 ambapp_dev_apbuart *uart;
732 /* get physical address */
733 struct leon_prom_info *pspi =
734 (void *)(CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables));
736 uart = (ambapp_dev_apbuart *)
737 SPARC_BYPASS_READ(&pspi->reloc_funcs.leon3_apbuart);
743 /***** put char in buffer... ***********
744 * Make sure all functions are inline! *
745 ***************************************/
747 /* Wait for last character to go. */
748 while (!(SPARC_BYPASS_READ(&uart->status)
749 & APBUART_STATUS_THE));
752 SPARC_BYPASS_WRITE(&uart->data, c);
754 /* Wait for data to be sent */
755 while (!(SPARC_BYPASS_READ(&uart->status)
756 & APBUART_STATUS_TSE));
763 /*#define nodes ((struct node *)__va(&pspi->nodes))*/
764 #define nodes ((struct node *)(pspi->nodes))
766 static int PROM_TEXT no_nextnode(int node)
768 /* get physical address */
769 struct leon_prom_info *pspi =
770 (void *)(CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables));
772 /* convert into virtual address */
773 pspi = (struct leon_prom_info *)
774 (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET);
776 if (nodes[node].level == nodes[node + 1].level)
781 static int PROM_TEXT no_child(int node)
783 /* get physical address */
784 struct leon_prom_info *pspi = (struct leon_prom_info *)
785 (CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables));
787 /* convert into virtual address */
788 pspi = (struct leon_prom_info *)
789 (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET);
791 if (nodes[node].level == nodes[node + 1].level - 1)
796 static struct property PROM_TEXT *find_property(int node, char *name)
798 /* get physical address */
799 struct leon_prom_info *pspi = (struct leon_prom_info *)
800 (CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables));
802 /* convert into virtual address */
803 pspi = (struct leon_prom_info *)
804 (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET);
806 struct property *prop = &nodes[node].properties[0];
807 while (prop && prop->name) {
808 if (pspi->reloc_funcs.strcmp(prop->name, name) == 0)
815 static int PROM_TEXT no_proplen(int node, char *name)
817 /* get physical address */
818 struct leon_prom_info *pspi = (struct leon_prom_info *)
819 (CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables));
821 /* convert into virtual address */
822 pspi = (struct leon_prom_info *)
823 (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET);
825 struct property *prop = pspi->reloc_funcs.find_property(node, name);
831 static int PROM_TEXT no_getprop(int node, char *name, char *value)
833 /* get physical address */
834 struct leon_prom_info *pspi = (struct leon_prom_info *)
835 (CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables));
837 /* convert into virtual address */
838 pspi = (struct leon_prom_info *)
839 (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET);
841 struct property *prop = pspi->reloc_funcs.find_property(node, name);
843 pspi->reloc_funcs.memcpy(value, prop->value, prop->length);
849 static int PROM_TEXT no_setprop(int node, char *name, char *value, int len)
854 static char PROM_TEXT *no_nextprop(int node, char *name)
856 /* get physical address */
857 struct leon_prom_info *pspi = (struct leon_prom_info *)
858 (CONFIG_SYS_PROM_OFFSET + sizeof(srmmu_tables));
859 struct property *prop;
861 /* convert into virtual address */
862 pspi = (struct leon_prom_info *)
863 (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET);
865 if (!name || !name[0])
866 return nodes[node].properties[0].name;
868 prop = pspi->reloc_funcs.find_property(node, name);
874 static int PROM_TEXT leon_strcmp(const char *s1, const char *s2)
876 register char result;
889 static void *PROM_TEXT leon_memcpy(void *dest, const void *src, size_t n)
891 char *dst = (char *)dest, *source = (char *)src;
901 #define GETREGSP(sp) __asm__ __volatile__("mov %%sp, %0" : "=r" (sp))
903 void leon_prom_init(struct leon_prom_info *pspi)
906 unsigned char cksum, *ptr;
907 char *addr_str, *end;
911 pspi->freq_khz = CONFIG_SYS_CLK_FREQ / 1000;
913 /* Set Available main memory size */
914 pspi->totphys.num_bytes = CONFIG_SYS_PROM_OFFSET - CONFIG_SYS_SDRAM_BASE;
915 pspi->avail.num_bytes = pspi->totphys.num_bytes;
917 /* Set the pointer to the Console UART in romvec */
918 pspi->reloc_funcs.leon3_apbuart = gd->arch.uart;
924 b = (ambapp_dev_irqmp *) leon3_getapbbase(VENDOR_GAISLER,
927 j = 1 + ((LEON3_BYPASS_LOAD_PA(&(b->mpstatus))
928 >> LEON3_IRQMPSTATUS_CPUNR) & 0xf);
932 pspi->nodes[2 + j].level = -1;
933 pspi->nodes[2 + j].properties = __va(spi.root_properties + 3);
936 /* Set Ethernet MAC address from environment */
937 if ((addr_str = getenv("ethaddr")) != NULL) {
938 for (i = 0; i < 6; i++) {
939 pspi->idprom.id_ethaddr[i] = addr_str ?
940 simple_strtoul(addr_str, &end, 16) : 0;
942 addr_str = (*end) ? end + 1 : end;
946 /* HW Address not found in environment,
947 * Set default HW address
949 pspi->idprom.id_ethaddr[0] = 0;
950 pspi->idprom.id_ethaddr[1] = 0;
951 pspi->idprom.id_ethaddr[2] = 0;
952 pspi->idprom.id_ethaddr[3] = 0;
953 pspi->idprom.id_ethaddr[4] = 0;
954 pspi->idprom.id_ethaddr[5] = 0;
957 ptr = (unsigned char *)&pspi->idprom;
958 for (i = cksum = 0; i <= 0x0E; i++)
960 pspi->idprom.id_cksum = cksum;
963 static inline void set_cache(unsigned long regval)
965 asm volatile ("sta %0, [%%g0] %1\n\t":: "r" (regval), "i"(2):"memory");
968 extern unsigned short bss_start, bss_end;
970 /* mark as section .img.main.text, to be referenced in linker script */
973 struct leon_prom_info *pspi = (void *)
974 ((((unsigned int)&spi) & PROM_SIZE_MASK) + CONFIG_SYS_PROM_OFFSET);
977 srmmu_set_mmureg(0x00000000);
978 __asm__ __volatile__("flush\n\t");
980 /* init prom info struct */
981 leon_prom_init(pspi);
983 kernel_arg_promvec = &pspi->romvec;
985 printf("Kernel rom vec: 0x%lx\n", (unsigned int)(&pspi->romvec));
990 /* Copy current kernel boot argument to ROMvec */
991 void prepare_bootargs(char *bootargs)
993 struct leon_prom_info *pspi;
997 /* if no bootargs set, skip copying ==> default bootline */
998 if (bootargs && (*bootargs != '\0')) {
999 pspi = (void *)((((unsigned int)&spi) & PROM_SIZE_MASK) +
1000 CONFIG_SYS_PROM_OFFSET);
1002 dst = &pspi->arg[0];
1003 left = 255; /* max len */
1004 while (*src && left > 0) {
1008 /* terminate kernel command line string */
1013 void srmmu_init_cpu(unsigned int entry)
1015 sparc_srmmu_setup *psrmmu_tables = (void *)
1016 ((((unsigned int)&srmmu_tables) & PROM_SIZE_MASK) +
1017 CONFIG_SYS_PROM_OFFSET);
1019 /* Make context 0 (kernel's context) point
1020 * to our prepared memory mapping
1023 psrmmu_tables->ctx_table[0] =
1024 ((unsigned int)&psrmmu_tables->pgd_table[0x00]) >> 4 | PTD;
1026 /* Set virtual kernel address 0xf0000000
1027 * to SRAM/SDRAM address.
1028 * Make it READ/WRITE/EXEC to SuperUser
1031 #define ACC_SU_ALL 0x1c
1032 psrmmu_tables->pgd_table[0xf0] =
1033 (CONFIG_SYS_SDRAM_BASE >> 4) | ACC_SU_ALL | PTE;
1034 psrmmu_tables->pgd_table[0xf1] =
1035 ((CONFIG_SYS_SDRAM_BASE + 0x1000000) >> 4) | ACC_SU_ALL | PTE;
1036 psrmmu_tables->pgd_table[0xf2] =
1037 ((CONFIG_SYS_SDRAM_BASE + 0x2000000) >> 4) | ACC_SU_ALL | PTE;
1038 psrmmu_tables->pgd_table[0xf3] =
1039 ((CONFIG_SYS_SDRAM_BASE + 0x3000000) >> 4) | ACC_SU_ALL | PTE;
1040 psrmmu_tables->pgd_table[0xf4] =
1041 ((CONFIG_SYS_SDRAM_BASE + 0x4000000) >> 4) | ACC_SU_ALL | PTE;
1042 psrmmu_tables->pgd_table[0xf5] =
1043 ((CONFIG_SYS_SDRAM_BASE + 0x5000000) >> 4) | ACC_SU_ALL | PTE;
1044 psrmmu_tables->pgd_table[0xf6] =
1045 ((CONFIG_SYS_SDRAM_BASE + 0x6000000) >> 4) | ACC_SU_ALL | PTE;
1046 psrmmu_tables->pgd_table[0xf7] =
1047 ((CONFIG_SYS_SDRAM_BASE + 0x7000000) >> 4) | ACC_SU_ALL | PTE;
1049 /* convert rom vec pointer to virtual address */
1050 kernel_arg_promvec = (struct linux_romvec *)
1051 (((unsigned int)kernel_arg_promvec & 0x0fffffff) | 0xf0000000);
1053 /* Set Context pointer to point to context table
1054 * 256 contexts supported.
1056 srmmu_set_ctable_ptr((unsigned int)&psrmmu_tables->ctx_table[0]);
1058 /* Set kernel's context, context zero */
1059 srmmu_set_context(0);
1061 /* Invalidate all Cache */
1062 __asm__ __volatile__("flush\n\t");
1064 srmmu_set_mmureg(0x00000001);
1065 leon_flush_tlb_all();
1066 leon_flush_cache_all();