| // SPDX-License-Identifier: GPL-2.0-only |
| /* |
| * prom.c |
| * Early intialization code for the Realtek RTL838X SoC |
| * |
| * based on the original BSP by |
| * Copyright (C) 2006-2012 Tony Wu (tonywu@realtek.com) |
| * Copyright (C) 2020 B. Koblitz |
| * |
| */ |
| |
| #include <linux/init.h> |
| #include <linux/kernel.h> |
| #include <linux/string.h> |
| #include <linux/of_fdt.h> |
| #include <linux/libfdt.h> |
| #include <asm/bootinfo.h> |
| #include <asm/addrspace.h> |
| #include <asm/page.h> |
| #include <asm/cpu.h> |
| |
| #include <mach-rtl83xx.h> |
| |
| extern char arcs_cmdline[]; |
| extern const char __appended_dtb; |
| |
| struct rtl83xx_soc_info soc_info; |
| const void *fdt; |
| |
| const char *get_system_type(void) |
| { |
| return soc_info.name; |
| } |
| |
| void __init prom_free_prom_memory(void) |
| { |
| |
| } |
| |
| void __init device_tree_init(void) |
| { |
| if (!fdt_check_header(&__appended_dtb)) { |
| fdt = &__appended_dtb; |
| pr_info("Using appended Device Tree.\n"); |
| } |
| initial_boot_params = (void *)fdt; |
| unflatten_and_copy_device_tree(); |
| } |
| |
| static void __init prom_init_cmdline(void) |
| { |
| int argc = fw_arg0; |
| char **argv = (char **) KSEG1ADDR(fw_arg1); |
| int i; |
| |
| arcs_cmdline[0] = '\0'; |
| |
| for (i = 0; i < argc; i++) { |
| char *p = (char *) KSEG1ADDR(argv[i]); |
| |
| if (CPHYSADDR(p) && *p) { |
| strlcat(arcs_cmdline, p, sizeof(arcs_cmdline)); |
| strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline)); |
| } |
| } |
| pr_info("Kernel command line: %s\n", arcs_cmdline); |
| } |
| |
| void __init identify_rtl9302(void) |
| { |
| switch (sw_r32(RTL93XX_MODEL_NAME_INFO) & 0xfffffff0) { |
| case 0x93020810: |
| soc_info.name = "RTL9302A 12x2.5G"; |
| break; |
| case 0x93021010: |
| soc_info.name = "RTL9302B 8x2.5G"; |
| break; |
| case 0x93021810: |
| soc_info.name = "RTL9302C 16x2.5G"; |
| break; |
| case 0x93022010: |
| soc_info.name = "RTL9302D 24x2.5G"; |
| break; |
| case 0x93020800: |
| soc_info.name = "RTL9302A"; |
| break; |
| case 0x93021000: |
| soc_info.name = "RTL9302B"; |
| break; |
| case 0x93021800: |
| soc_info.name = "RTL9302C"; |
| break; |
| case 0x93022000: |
| soc_info.name = "RTL9302D"; |
| break; |
| case 0x93023001: |
| soc_info.name = "RTL9302F"; |
| break; |
| default: |
| soc_info.name = "RTL9302"; |
| } |
| } |
| |
| void __init prom_init(void) |
| { |
| uint32_t model; |
| |
| /* uart0 */ |
| setup_8250_early_printk_port(0xb8002000, 2, 0); |
| |
| model = sw_r32(RTL838X_MODEL_NAME_INFO); |
| pr_info("RTL838X model is %x\n", model); |
| model = model >> 16 & 0xFFFF; |
| |
| if ((model != 0x8328) && (model != 0x8330) && (model != 0x8332) |
| && (model != 0x8380) && (model != 0x8382)) { |
| model = sw_r32(RTL839X_MODEL_NAME_INFO); |
| pr_info("RTL839X model is %x\n", model); |
| model = model >> 16 & 0xFFFF; |
| } |
| |
| if ((model & 0x8390) != 0x8380 && (model & 0x8390) != 0x8390) { |
| model = sw_r32(RTL93XX_MODEL_NAME_INFO); |
| pr_info("RTL93XX model is %x\n", model); |
| model = model >> 16 & 0xFFFF; |
| } |
| |
| soc_info.id = model; |
| |
| switch (model) { |
| case 0x8328: |
| soc_info.name = "RTL8328"; |
| soc_info.family = RTL8328_FAMILY_ID; |
| break; |
| case 0x8332: |
| soc_info.name = "RTL8332"; |
| soc_info.family = RTL8380_FAMILY_ID; |
| break; |
| case 0x8380: |
| soc_info.name = "RTL8380"; |
| soc_info.family = RTL8380_FAMILY_ID; |
| break; |
| case 0x8382: |
| soc_info.name = "RTL8382"; |
| soc_info.family = RTL8380_FAMILY_ID; |
| break; |
| case 0x8390: |
| soc_info.name = "RTL8390"; |
| soc_info.family = RTL8390_FAMILY_ID; |
| break; |
| case 0x8391: |
| soc_info.name = "RTL8391"; |
| soc_info.family = RTL8390_FAMILY_ID; |
| break; |
| case 0x8392: |
| soc_info.name = "RTL8392"; |
| soc_info.family = RTL8390_FAMILY_ID; |
| break; |
| case 0x8393: |
| soc_info.name = "RTL8393"; |
| soc_info.family = RTL8390_FAMILY_ID; |
| break; |
| case 0x9301: |
| soc_info.name = "RTL9301"; |
| soc_info.family = RTL9300_FAMILY_ID; |
| break; |
| case 0x9302: |
| identify_rtl9302(); |
| soc_info.family = RTL9300_FAMILY_ID; |
| break; |
| case 0x9313: |
| soc_info.name = "RTL9313"; |
| soc_info.family = RTL9310_FAMILY_ID; |
| break; |
| default: |
| soc_info.name = "DEFAULT"; |
| soc_info.family = 0; |
| } |
| |
| pr_info("SoC Type: %s\n", get_system_type()); |
| |
| prom_init_cmdline(); |
| } |