162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Carsten Langgaard, carstenl@mips.com 462306a36Sopenharmony_ci * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. 562306a36Sopenharmony_ci * Copyright (C) 2008 Dmitri Vorobiev 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci#include <linux/cpu.h> 862306a36Sopenharmony_ci#include <linux/init.h> 962306a36Sopenharmony_ci#include <linux/sched.h> 1062306a36Sopenharmony_ci#include <linux/ioport.h> 1162306a36Sopenharmony_ci#include <linux/irq.h> 1262306a36Sopenharmony_ci#include <linux/of_fdt.h> 1362306a36Sopenharmony_ci#include <linux/pci.h> 1462306a36Sopenharmony_ci#include <linux/screen_info.h> 1562306a36Sopenharmony_ci#include <linux/time.h> 1662306a36Sopenharmony_ci#include <linux/dma-map-ops.h> /* for dma_default_coherent */ 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include <asm/fw/fw.h> 1962306a36Sopenharmony_ci#include <asm/mips-cps.h> 2062306a36Sopenharmony_ci#include <asm/mips-boards/generic.h> 2162306a36Sopenharmony_ci#include <asm/mips-boards/malta.h> 2262306a36Sopenharmony_ci#include <asm/mips-boards/maltaint.h> 2362306a36Sopenharmony_ci#include <asm/dma.h> 2462306a36Sopenharmony_ci#include <asm/prom.h> 2562306a36Sopenharmony_ci#include <asm/traps.h> 2662306a36Sopenharmony_ci#ifdef CONFIG_VT 2762306a36Sopenharmony_ci#include <linux/console.h> 2862306a36Sopenharmony_ci#endif 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define ROCIT_CONFIG_GEN0 0x1f403000 3162306a36Sopenharmony_ci#define ROCIT_CONFIG_GEN0_PCI_IOCU BIT(7) 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic struct resource standard_io_resources[] = { 3462306a36Sopenharmony_ci { 3562306a36Sopenharmony_ci .name = "dma1", 3662306a36Sopenharmony_ci .start = 0x00, 3762306a36Sopenharmony_ci .end = 0x1f, 3862306a36Sopenharmony_ci .flags = IORESOURCE_IO | IORESOURCE_BUSY 3962306a36Sopenharmony_ci }, 4062306a36Sopenharmony_ci { 4162306a36Sopenharmony_ci .name = "timer", 4262306a36Sopenharmony_ci .start = 0x40, 4362306a36Sopenharmony_ci .end = 0x5f, 4462306a36Sopenharmony_ci .flags = IORESOURCE_IO | IORESOURCE_BUSY 4562306a36Sopenharmony_ci }, 4662306a36Sopenharmony_ci { 4762306a36Sopenharmony_ci .name = "keyboard", 4862306a36Sopenharmony_ci .start = 0x60, 4962306a36Sopenharmony_ci .end = 0x6f, 5062306a36Sopenharmony_ci .flags = IORESOURCE_IO | IORESOURCE_BUSY 5162306a36Sopenharmony_ci }, 5262306a36Sopenharmony_ci { 5362306a36Sopenharmony_ci .name = "dma page reg", 5462306a36Sopenharmony_ci .start = 0x80, 5562306a36Sopenharmony_ci .end = 0x8f, 5662306a36Sopenharmony_ci .flags = IORESOURCE_IO | IORESOURCE_BUSY 5762306a36Sopenharmony_ci }, 5862306a36Sopenharmony_ci { 5962306a36Sopenharmony_ci .name = "dma2", 6062306a36Sopenharmony_ci .start = 0xc0, 6162306a36Sopenharmony_ci .end = 0xdf, 6262306a36Sopenharmony_ci .flags = IORESOURCE_IO | IORESOURCE_BUSY 6362306a36Sopenharmony_ci }, 6462306a36Sopenharmony_ci}; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ciconst char *get_system_type(void) 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci return "MIPS Malta"; 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci#ifdef CONFIG_BLK_DEV_FD 7262306a36Sopenharmony_cistatic void __init fd_activate(void) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci /* 7562306a36Sopenharmony_ci * Activate Floppy Controller in the SMSC FDC37M817 Super I/O 7662306a36Sopenharmony_ci * Controller. 7762306a36Sopenharmony_ci * Done by YAMON 2.00 onwards 7862306a36Sopenharmony_ci */ 7962306a36Sopenharmony_ci /* Entering config state. */ 8062306a36Sopenharmony_ci SMSC_WRITE(SMSC_CONFIG_ENTER, SMSC_CONFIG_REG); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci /* Activate floppy controller. */ 8362306a36Sopenharmony_ci SMSC_WRITE(SMSC_CONFIG_DEVNUM, SMSC_CONFIG_REG); 8462306a36Sopenharmony_ci SMSC_WRITE(SMSC_CONFIG_DEVNUM_FLOPPY, SMSC_DATA_REG); 8562306a36Sopenharmony_ci SMSC_WRITE(SMSC_CONFIG_ACTIVATE, SMSC_CONFIG_REG); 8662306a36Sopenharmony_ci SMSC_WRITE(SMSC_CONFIG_ACTIVATE_ENABLE, SMSC_DATA_REG); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci /* Exit config state. */ 8962306a36Sopenharmony_ci SMSC_WRITE(SMSC_CONFIG_EXIT, SMSC_CONFIG_REG); 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci#endif 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic void __init plat_setup_iocoherency(void) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci u32 cfg; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO) { 9862306a36Sopenharmony_ci if (BONITO_PCICACHECTRL & BONITO_PCICACHECTRL_CPUCOH_PRES) { 9962306a36Sopenharmony_ci BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_CPUCOH_EN; 10062306a36Sopenharmony_ci pr_info("Enabled Bonito CPU coherency\n"); 10162306a36Sopenharmony_ci dma_default_coherent = true; 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci if (strstr(fw_getcmdline(), "iobcuncached")) { 10462306a36Sopenharmony_ci BONITO_PCICACHECTRL &= ~BONITO_PCICACHECTRL_IOBCCOH_EN; 10562306a36Sopenharmony_ci BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG & 10662306a36Sopenharmony_ci ~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED | 10762306a36Sopenharmony_ci BONITO_PCIMEMBASECFG_MEMBASE1_CACHED); 10862306a36Sopenharmony_ci pr_info("Disabled Bonito IOBC coherency\n"); 10962306a36Sopenharmony_ci } else { 11062306a36Sopenharmony_ci BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_IOBCCOH_EN; 11162306a36Sopenharmony_ci BONITO_PCIMEMBASECFG |= 11262306a36Sopenharmony_ci (BONITO_PCIMEMBASECFG_MEMBASE0_CACHED | 11362306a36Sopenharmony_ci BONITO_PCIMEMBASECFG_MEMBASE1_CACHED); 11462306a36Sopenharmony_ci pr_info("Enabled Bonito IOBC coherency\n"); 11562306a36Sopenharmony_ci } 11662306a36Sopenharmony_ci } else if (mips_cps_numiocu(0) != 0) { 11762306a36Sopenharmony_ci /* Nothing special needs to be done to enable coherency */ 11862306a36Sopenharmony_ci pr_info("CMP IOCU detected\n"); 11962306a36Sopenharmony_ci cfg = __raw_readl((u32 *)CKSEG1ADDR(ROCIT_CONFIG_GEN0)); 12062306a36Sopenharmony_ci if (cfg & ROCIT_CONFIG_GEN0_PCI_IOCU) 12162306a36Sopenharmony_ci dma_default_coherent = true; 12262306a36Sopenharmony_ci else 12362306a36Sopenharmony_ci pr_crit("IOCU OPERATION DISABLED BY SWITCH - DEFAULTING TO SW IO COHERENCY\n"); 12462306a36Sopenharmony_ci } 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci if (dma_default_coherent) 12762306a36Sopenharmony_ci pr_info("Hardware DMA cache coherency enabled\n"); 12862306a36Sopenharmony_ci else 12962306a36Sopenharmony_ci pr_info("Software DMA cache coherency enabled\n"); 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic void __init pci_clock_check(void) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci unsigned int __iomem *jmpr_p = 13562306a36Sopenharmony_ci (unsigned int *) ioremap(MALTA_JMPRS_REG, sizeof(unsigned int)); 13662306a36Sopenharmony_ci int jmpr = (__raw_readl(jmpr_p) >> 2) & 0x07; 13762306a36Sopenharmony_ci static const int pciclocks[] __initconst = { 13862306a36Sopenharmony_ci 33, 20, 25, 30, 12, 16, 37, 10 13962306a36Sopenharmony_ci }; 14062306a36Sopenharmony_ci int pciclock = pciclocks[jmpr]; 14162306a36Sopenharmony_ci char *optptr, *argptr = fw_getcmdline(); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci /* 14462306a36Sopenharmony_ci * If user passed a pci_clock= option, don't tack on another one 14562306a36Sopenharmony_ci */ 14662306a36Sopenharmony_ci optptr = strstr(argptr, "pci_clock="); 14762306a36Sopenharmony_ci if (optptr && (optptr == argptr || optptr[-1] == ' ')) 14862306a36Sopenharmony_ci return; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci if (pciclock != 33) { 15162306a36Sopenharmony_ci pr_warn("WARNING: PCI clock is %dMHz, setting pci_clock\n", 15262306a36Sopenharmony_ci pciclock); 15362306a36Sopenharmony_ci argptr += strlen(argptr); 15462306a36Sopenharmony_ci sprintf(argptr, " pci_clock=%d", pciclock); 15562306a36Sopenharmony_ci if (pciclock < 20 || pciclock > 66) 15662306a36Sopenharmony_ci pr_warn("WARNING: IDE timing calculations will be " 15762306a36Sopenharmony_ci "incorrect\n"); 15862306a36Sopenharmony_ci } 15962306a36Sopenharmony_ci} 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) 16262306a36Sopenharmony_cistatic void __init screen_info_setup(void) 16362306a36Sopenharmony_ci{ 16462306a36Sopenharmony_ci screen_info = (struct screen_info) { 16562306a36Sopenharmony_ci .orig_x = 0, 16662306a36Sopenharmony_ci .orig_y = 25, 16762306a36Sopenharmony_ci .ext_mem_k = 0, 16862306a36Sopenharmony_ci .orig_video_page = 0, 16962306a36Sopenharmony_ci .orig_video_mode = 0, 17062306a36Sopenharmony_ci .orig_video_cols = 80, 17162306a36Sopenharmony_ci .unused2 = 0, 17262306a36Sopenharmony_ci .orig_video_ega_bx = 0, 17362306a36Sopenharmony_ci .unused3 = 0, 17462306a36Sopenharmony_ci .orig_video_lines = 25, 17562306a36Sopenharmony_ci .orig_video_isVGA = VIDEO_TYPE_VGAC, 17662306a36Sopenharmony_ci .orig_video_points = 16 17762306a36Sopenharmony_ci }; 17862306a36Sopenharmony_ci} 17962306a36Sopenharmony_ci#endif 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistatic void __init bonito_quirks_setup(void) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci char *argptr; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci argptr = fw_getcmdline(); 18662306a36Sopenharmony_ci if (strstr(argptr, "debug")) { 18762306a36Sopenharmony_ci BONITO_BONGENCFG |= BONITO_BONGENCFG_DEBUGMODE; 18862306a36Sopenharmony_ci pr_info("Enabled Bonito debug mode\n"); 18962306a36Sopenharmony_ci } else 19062306a36Sopenharmony_ci BONITO_BONGENCFG &= ~BONITO_BONGENCFG_DEBUGMODE; 19162306a36Sopenharmony_ci} 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_civoid __init *plat_get_fdt(void) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci return (void *)__dtb_start; 19662306a36Sopenharmony_ci} 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_civoid __init plat_mem_setup(void) 19962306a36Sopenharmony_ci{ 20062306a36Sopenharmony_ci unsigned int i; 20162306a36Sopenharmony_ci void *fdt = plat_get_fdt(); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci fdt = malta_dt_shim(fdt); 20462306a36Sopenharmony_ci __dt_setup_arch(fdt); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_EVA)) 20762306a36Sopenharmony_ci /* EVA has already been configured in mach-malta/kernel-init.h */ 20862306a36Sopenharmony_ci pr_info("Enhanced Virtual Addressing (EVA) activated\n"); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci mips_pcibios_init(); 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci /* Request I/O space for devices used on the Malta board. */ 21362306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++) 21462306a36Sopenharmony_ci request_resource(&ioport_resource, standard_io_resources+i); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci /* 21762306a36Sopenharmony_ci * Enable DMA channel 4 (cascade channel) in the PIIX4 south bridge. 21862306a36Sopenharmony_ci */ 21962306a36Sopenharmony_ci enable_dma(4); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO) 22262306a36Sopenharmony_ci bonito_quirks_setup(); 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci plat_setup_iocoherency(); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci pci_clock_check(); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci#ifdef CONFIG_BLK_DEV_FD 22962306a36Sopenharmony_ci fd_activate(); 23062306a36Sopenharmony_ci#endif 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) 23362306a36Sopenharmony_ci screen_info_setup(); 23462306a36Sopenharmony_ci#endif 23562306a36Sopenharmony_ci} 236