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>
22 extern struct linux_romvec
*kernel_arg_promvec
;
24 #define PROM_PGT __attribute__ ((__section__ (".prom.pgt")))
25 #define PROM_TEXT __attribute__ ((__section__ (".prom.text")))
26 #define PROM_DATA __attribute__ ((__section__ (".prom.data")))
29 extern int __prom_start
;
30 #define PAGE_OFFSET 0xf0000000
31 #define phys_base CONFIG_SYS_SDRAM_BASE
32 #define PROM_OFFS 8192
33 #define PROM_SIZE_MASK (PROM_OFFS-1)
35 (void *)( ((unsigned long)(x))-PROM_OFFS+ \
36 (CONFIG_SYS_PROM_OFFSET-phys_base)+PAGE_OFFSET-CONFIG_SYS_TEXT_BASE ) \
38 #define __phy(x) ((void *)(((unsigned long)(x))-PROM_OFFS+CONFIG_SYS_PROM_OFFSET-CONFIG_SYS_TEXT_BASE))
48 struct property
*properties
;
51 static void leon_reboot(char *bcommand
);
52 static void leon_halt(void);
53 static int leon_nbputchar(int c
);
54 static int leon_nbgetchar(void);
56 static int no_nextnode(int node
);
57 static int no_child(int node
);
58 static int no_proplen(int node
, char *name
);
59 static int no_getprop(int node
, char *name
, char *value
);
60 static int no_setprop(int node
, char *name
, char *value
, int len
);
61 static char *no_nextprop(int node
, char *name
);
63 static struct property PROM_TEXT
*find_property(int node
, char *name
);
64 static int PROM_TEXT
leon_strcmp(const char *s1
, const char *s2
);
65 static void *PROM_TEXT
leon_memcpy(void *dest
, const void *src
, size_t n
);
66 static void PROM_TEXT
leon_reboot_physical(char *bcommand
);
68 void __inline__
leon_flush_cache_all(void)
70 __asm__
__volatile__(" flush ");
71 __asm__
__volatile__("sta %%g0, [%%g0] %0\n\t"::"i"(ASI_DFLUSH
):"memory");
74 void __inline__
leon_flush_tlb_all(void)
76 leon_flush_cache_all();
77 __asm__
__volatile__("sta %%g0, [%0] %1\n\t"::"r"(0x400),
78 "i"(ASI_MMUFLUSH
):"memory");
82 unsigned int ctx_table
[256];
83 unsigned int pgd_table
[256];
86 sparc_srmmu_setup srmmu_tables PROM_PGT
= {
328 0x400001e /* default */
332 /* a self contained prom info structure */
333 struct leon_reloc_func
{
334 struct property
*(*find_property
) (int node
, char *name
);
335 int (*strcmp
) (char *s1
, char *s2
);
336 void *(*memcpy
) (void *dest
, const void *src
, size_t n
);
337 void (*reboot_physical
) (char *cmd
);
340 struct leon_prom_info
{
345 struct leon_reloc_func reloc_funcs
;
346 struct property root_properties
[4];
347 struct property cpu_properties
[7];
349 #define CPUENTRY(idx) struct property cpu_properties##idx[4]
381 struct idprom idprom
;
382 struct linux_nodeops nodeops
;
383 struct linux_mlist_v0
*totphys_p
;
384 struct linux_mlist_v0 totphys
;
385 struct linux_mlist_v0
*avail_p
;
386 struct linux_mlist_v0 avail
;
387 struct linux_mlist_v0
*prommap_p
;
388 void (*synchook
) (void);
389 struct linux_arguments_v0
*bootargs_p
;
390 struct linux_arguments_v0 bootargs
;
391 struct linux_romvec romvec
;
392 struct node nodes
[35];
393 char s_device_type
[12];
397 char s_compatability
[14];
400 char s_frequency
[16];
401 char s_uart1_baud
[11];
402 char s_uart2_baud
[11];
406 /* static prom info */
407 static struct leon_prom_info PROM_DATA spi
= {
408 CONFIG_SYS_CLK_FREQ
/ 1000,
412 #define CPUENTRY(idx) idx
450 __phy(leon_reboot_physical
),
453 {__va(spi
.s_device_type
), __va(spi
.s_idprom
), 4},
454 {__va(spi
.s_idprom
), (char *)__va(&spi
.idprom
), sizeof(struct idprom
)},
455 {__va(spi
.s_compatability
), __va(spi
.s_leon2
), 5},
459 {__va(spi
.s_device_type
), __va(spi
.s_cpu
), 4},
460 {__va(spi
.s_mid
), __va(&spi
.mids
[0]), 4},
461 {__va(spi
.s_mmu_nctx
), (char *)__va(&spi
.leon_nctx
), 4},
462 {__va(spi
.s_frequency
), (char *)__va(&spi
.freq_khz
), 4},
463 {__va(spi
.s_uart1_baud
), (char *)__va(&spi
.baudrates
[0]), 4},
464 {__va(spi
.s_uart2_baud
), (char *)__va(&spi
.baudrates
[1]), 4},
468 #define CPUENTRY(idx) \
469 { /* cpu_properties */ \
470 {__va(spi.s_device_type), __va(spi.s_cpu), 4}, \
471 {__va(spi.s_mid), __va(&spi.mids[idx]), 4}, \
472 {__va(spi.s_frequency), (char *)__va(&spi.freq_khz), 4}, \
508 M_LEON2
| M_LEON2_SOC
, /* machine type */
509 {0, 0, 0, 0, 0, 0}, /* eth */
513 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* reserved */
526 (char *)CONFIG_SYS_SDRAM_BASE
,
532 (char *)CONFIG_SYS_SDRAM_BASE
,
535 NULL
, /* prommap_p */
539 {NULL
, __va(spi
.arg
), NULL
/*... */ },
544 0, /* sun4c v0 prom */
546 {__va(&spi
.totphys_p
), __va(&spi
.prommap_p
), __va(&spi
.avail_p
)},
548 NULL
, {NULL
/* ... */ },
550 NULL
, NULL
, /* pv_getchar, pv_putchar */
551 __va(leon_nbgetchar
), __va(leon_nbputchar
),
560 __va(&spi
.bootargs_p
)
564 {0, __va(spi
.root_properties
+ 3) /* NULL, NULL, -1 */ },
565 {0, __va(spi
.root_properties
)},
566 /* cpu 0, must be spi.nodes[2] see leon_prom_init() */
567 {1, __va(spi
.cpu_properties
)},
570 #define CPUENTRY(idx) \
571 {1, __va(spi.cpu_properties##idx) } /* cpu <idx> */
603 {-1, __va(spi
.root_properties
+ 3) /* NULL, NULL, -1 */ }
615 CONFIG_DEFAULT_KERNEL_COMMAND_LINE
618 /* from arch/sparc/kernel/setup.c */
619 #define RAMDISK_LOAD_FLAG 0x4000
620 extern unsigned short root_flags
;
621 extern unsigned short root_dev
;
622 extern unsigned short ram_flags
;
623 extern unsigned int sparc_ramdisk_image
;
624 extern unsigned int sparc_ramdisk_size
;
625 extern int root_mountflags
;
627 extern char initrd_end
, initrd_start
;
629 /* Reboot the CPU = jump to beginning of flash again.
631 * Make sure that all function are inlined here.
633 static void PROM_TEXT
leon_reboot(char *bcommand
)
635 register char *arg
= bcommand
;
636 void __attribute__ ((noreturn
)) (*reboot_physical
) (char *cmd
);
638 /* get physical address */
639 struct leon_prom_info
*pspi
=
640 (void *)(CONFIG_SYS_PROM_OFFSET
+ sizeof(srmmu_tables
));
642 unsigned int *srmmu_ctx_table
;
644 /* Turn of Interrupts */
647 /* Set kernel's context, context zero */
648 srmmu_set_context(0);
650 /* Get physical address of the MMU shutdown routine */
651 reboot_physical
= (void *)
652 SPARC_BYPASS_READ(&pspi
->reloc_funcs
.reboot_physical
);
654 /* Now that we know the physical address of the function
655 * we can make the MMU allow jumping to it.
657 srmmu_ctx_table
= (unsigned int *)srmmu_get_ctable_ptr();
659 srmmu_ctx_table
= (unsigned int *)SPARC_BYPASS_READ(srmmu_ctx_table
);
661 /* get physical address of kernel's context table (assume ptd) */
662 srmmu_ctx_table
= (unsigned int *)
663 (((unsigned int)srmmu_ctx_table
& 0xfffffffc) << 4);
665 /* enable access to physical address of MMU shutdown function */
666 SPARC_BYPASS_WRITE(&srmmu_ctx_table
667 [((unsigned int)reboot_physical
) >> 24],
668 (((unsigned int)reboot_physical
& 0xff000000) >> 4) |
671 /* flush TLB cache */
672 leon_flush_tlb_all();
674 /* flash instruction & data cache */
675 sparc_icache_flush_all();
676 sparc_dcache_flush_all();
678 /* jump to physical address function
679 * so that when the MMU is disabled
680 * we can continue to execute
682 reboot_physical(arg
);
685 static void PROM_TEXT
leon_reboot_physical(char *bcommand
)
687 void __attribute__ ((noreturn
)) (*reset
) (void);
692 /* Hardcoded start address */
693 reset
= CONFIG_SYS_MONITOR_BASE
;
695 /* flush data cache */
696 sparc_dcache_flush_all();
698 /* flush instruction cache */
699 sparc_icache_flush_all();
701 /* Jump to start in Flash */
705 static void PROM_TEXT
leon_halt(void)
710 /* get single char, don't care for blocking*/
711 static int PROM_TEXT
leon_nbgetchar(void)
716 /* put single char, don't care for blocking*/
717 static int PROM_TEXT
leon_nbputchar(int c
)
719 LEON2_regs
*leon2
= (LEON2_regs
*) LEON2_PREGS
;
721 /***** put char in buffer... ***********
722 * Make sure all functions are inline! *
723 ***************************************/
725 /* Wait for last character to go. */
726 while (!(SPARC_BYPASS_READ(&leon2
->UART_Status_1
)
727 & LEON2_UART_STAT_THE
)) ;
730 SPARC_BYPASS_WRITE(&leon2
->UART_Channel_1
, c
);
732 /* Wait for data to be sent */
733 while (!(SPARC_BYPASS_READ(&leon2
->UART_Status_1
)
734 & LEON2_UART_STAT_TSE
)) ;
741 /*#define nodes ((struct node *)__va(&pspi->nodes))*/
742 #define nodes ((struct node *)(pspi->nodes))
744 static int PROM_TEXT
no_nextnode(int node
)
746 /* get physical address */
747 struct leon_prom_info
*pspi
=
748 (void *)(CONFIG_SYS_PROM_OFFSET
+ sizeof(srmmu_tables
));
750 /* convert into virtual address */
751 pspi
= (struct leon_prom_info
*)
752 (((unsigned int)pspi
& 0x0fffffff) | PAGE_OFFSET
);
754 if (nodes
[node
].level
== nodes
[node
+ 1].level
)
759 static int PROM_TEXT
no_child(int node
)
761 /* get physical address */
762 struct leon_prom_info
*pspi
= (struct leon_prom_info
*)
763 (CONFIG_SYS_PROM_OFFSET
+ sizeof(srmmu_tables
));
765 /* convert into virtual address */
766 pspi
= (struct leon_prom_info
*)
767 (((unsigned int)pspi
& 0x0fffffff) | PAGE_OFFSET
);
769 if (nodes
[node
].level
== nodes
[node
+ 1].level
- 1)
774 static struct property PROM_TEXT
*find_property(int node
, char *name
)
776 /* get physical address */
777 struct leon_prom_info
*pspi
= (struct leon_prom_info
*)
778 (CONFIG_SYS_PROM_OFFSET
+ sizeof(srmmu_tables
));
780 /* convert into virtual address */
781 pspi
= (struct leon_prom_info
*)
782 (((unsigned int)pspi
& 0x0fffffff) | PAGE_OFFSET
);
784 struct property
*prop
= &nodes
[node
].properties
[0];
785 while (prop
&& prop
->name
) {
786 if (pspi
->reloc_funcs
.strcmp(prop
->name
, name
) == 0)
793 static int PROM_TEXT
no_proplen(int node
, char *name
)
795 /* get physical address */
796 struct leon_prom_info
*pspi
= (struct leon_prom_info
*)
797 (CONFIG_SYS_PROM_OFFSET
+ sizeof(srmmu_tables
));
799 /* convert into virtual address */
800 pspi
= (struct leon_prom_info
*)
801 (((unsigned int)pspi
& 0x0fffffff) | PAGE_OFFSET
);
803 struct property
*prop
= pspi
->reloc_funcs
.find_property(node
, name
);
809 static int PROM_TEXT
no_getprop(int node
, char *name
, char *value
)
811 /* get physical address */
812 struct leon_prom_info
*pspi
= (struct leon_prom_info
*)
813 (CONFIG_SYS_PROM_OFFSET
+ sizeof(srmmu_tables
));
815 /* convert into virtual address */
816 pspi
= (struct leon_prom_info
*)
817 (((unsigned int)pspi
& 0x0fffffff) | PAGE_OFFSET
);
819 struct property
*prop
= pspi
->reloc_funcs
.find_property(node
, name
);
821 pspi
->reloc_funcs
.memcpy(value
, prop
->value
, prop
->length
);
827 static int PROM_TEXT
no_setprop(int node
, char *name
, char *value
, int len
)
832 static char PROM_TEXT
*no_nextprop(int node
, char *name
)
834 /* get physical address */
835 struct leon_prom_info
*pspi
= (struct leon_prom_info
*)
836 (CONFIG_SYS_PROM_OFFSET
+ sizeof(srmmu_tables
));
837 struct property
*prop
;
839 /* convert into virtual address */
840 pspi
= (struct leon_prom_info
*)
841 (((unsigned int)pspi
& 0x0fffffff) | PAGE_OFFSET
);
843 if (!name
|| !name
[0])
844 return nodes
[node
].properties
[0].name
;
846 prop
= pspi
->reloc_funcs
.find_property(node
, name
);
852 static int PROM_TEXT
leon_strcmp(const char *s1
, const char *s2
)
854 register char result
;
867 static void *PROM_TEXT
leon_memcpy(void *dest
, const void *src
, size_t n
)
869 char *dst
= (char *)dest
, *source
= (char *)src
;
879 #define GETREGSP(sp) __asm__ __volatile__("mov %%sp, %0" : "=r" (sp))
881 void leon_prom_init(struct leon_prom_info
*pspi
)
884 unsigned char cksum
, *ptr
;
885 char *addr_str
, *end
;
889 pspi
->freq_khz
= CONFIG_SYS_CLK_FREQ
/ 1000;
891 /* Set Available main memory size */
892 pspi
->totphys
.num_bytes
= CONFIG_SYS_PROM_OFFSET
- CONFIG_SYS_SDRAM_BASE
;
893 pspi
->avail
.num_bytes
= pspi
->totphys
.num_bytes
;
896 pspi
->nodes
[3].level
= -1;
897 pspi
->nodes
[3].properties
= __va(spi
.root_properties
+ 3);
899 /* Set Ethernet MAC address from environment */
900 if ((addr_str
= getenv("ethaddr")) != NULL
) {
901 for (i
= 0; i
< 6; i
++) {
902 pspi
->idprom
.id_ethaddr
[i
] = addr_str
?
903 simple_strtoul(addr_str
, &end
, 16) : 0;
905 addr_str
= (*end
) ? end
+ 1 : end
;
909 /* HW Address not found in environment,
910 * Set default HW address
912 pspi
->idprom
.id_ethaddr
[0] = 0;
913 pspi
->idprom
.id_ethaddr
[1] = 0;
914 pspi
->idprom
.id_ethaddr
[2] = 0;
915 pspi
->idprom
.id_ethaddr
[3] = 0;
916 pspi
->idprom
.id_ethaddr
[4] = 0;
917 pspi
->idprom
.id_ethaddr
[5] = 0;
920 ptr
= (unsigned char *)&pspi
->idprom
;
921 for (i
= cksum
= 0; i
<= 0x0E; i
++)
923 pspi
->idprom
.id_cksum
= cksum
;
926 static inline void set_cache(unsigned long regval
)
928 asm volatile ("sta %0, [%%g0] %1\n\t":: "r" (regval
), "i"(2):"memory");
931 extern unsigned short bss_start
, bss_end
;
933 /* mark as section .img.main.text, to be referenced in linker script */
936 struct leon_prom_info
*pspi
= (void *)
937 ((((unsigned int)&spi
) & PROM_SIZE_MASK
) + CONFIG_SYS_PROM_OFFSET
);
940 srmmu_set_mmureg(0x00000000);
941 __asm__
__volatile__("flush\n\t");
943 /* init prom info struct */
944 leon_prom_init(pspi
);
946 kernel_arg_promvec
= &pspi
->romvec
;
948 printf("Kernel rom vec: 0x%lx\n", (unsigned int)(&pspi
->romvec
));
953 /* Copy current kernel boot argument to ROMvec */
954 void prepare_bootargs(char *bootargs
)
956 struct leon_prom_info
*pspi
;
960 /* if no bootargs set, skip copying ==> default bootline */
961 if (bootargs
&& (*bootargs
!= '\0')) {
962 pspi
= (void *)((((unsigned int)&spi
) & PROM_SIZE_MASK
) +
963 CONFIG_SYS_PROM_OFFSET
);
966 left
= 255; /* max len */
967 while (*src
&& left
> 0) {
971 /* terminate kernel command line string */
976 void srmmu_init_cpu(unsigned int entry
)
978 sparc_srmmu_setup
*psrmmu_tables
= (void *)
979 ((((unsigned int)&srmmu_tables
) & PROM_SIZE_MASK
) +
980 CONFIG_SYS_PROM_OFFSET
);
982 /* Make context 0 (kernel's context) point
983 * to our prepared memory mapping
986 psrmmu_tables
->ctx_table
[0] =
987 ((unsigned int)&psrmmu_tables
->pgd_table
[0x00]) >> 4 | PTD
;
989 /* Set virtual kernel address 0xf0000000
990 * to SRAM/SDRAM address.
991 * Make it READ/WRITE/EXEC to SuperUser
994 #define ACC_SU_ALL 0x1c
995 psrmmu_tables
->pgd_table
[0xf0] =
996 (CONFIG_SYS_SDRAM_BASE
>> 4) | ACC_SU_ALL
| PTE
;
997 psrmmu_tables
->pgd_table
[0xf1] =
998 ((CONFIG_SYS_SDRAM_BASE
+ 0x1000000) >> 4) | ACC_SU_ALL
| PTE
;
999 psrmmu_tables
->pgd_table
[0xf2] =
1000 ((CONFIG_SYS_SDRAM_BASE
+ 0x2000000) >> 4) | ACC_SU_ALL
| PTE
;
1001 psrmmu_tables
->pgd_table
[0xf3] =
1002 ((CONFIG_SYS_SDRAM_BASE
+ 0x3000000) >> 4) | ACC_SU_ALL
| PTE
;
1003 psrmmu_tables
->pgd_table
[0xf4] =
1004 ((CONFIG_SYS_SDRAM_BASE
+ 0x4000000) >> 4) | ACC_SU_ALL
| PTE
;
1005 psrmmu_tables
->pgd_table
[0xf5] =
1006 ((CONFIG_SYS_SDRAM_BASE
+ 0x5000000) >> 4) | ACC_SU_ALL
| PTE
;
1007 psrmmu_tables
->pgd_table
[0xf6] =
1008 ((CONFIG_SYS_SDRAM_BASE
+ 0x6000000) >> 4) | ACC_SU_ALL
| PTE
;
1009 psrmmu_tables
->pgd_table
[0xf7] =
1010 ((CONFIG_SYS_SDRAM_BASE
+ 0x7000000) >> 4) | ACC_SU_ALL
| PTE
;
1012 /* convert rom vec pointer to virtual address */
1013 kernel_arg_promvec
= (struct linux_romvec
*)
1014 (((unsigned int)kernel_arg_promvec
& 0x0fffffff) | 0xf0000000);
1016 /* Set Context pointer to point to context table
1017 * 256 contexts supported.
1019 srmmu_set_ctable_ptr((unsigned int)&psrmmu_tables
->ctx_table
[0]);
1021 /* Set kernel's context, context zero */
1022 srmmu_set_context(0);
1024 /* Invalidate all Cache */
1025 __asm__
__volatile__("flush\n\t");
1027 srmmu_set_mmureg(0x00000001);
1028 leon_flush_tlb_all();
1029 leon_flush_cache_all();