Path: blob/master/arch/mips/mti-malta/malta-init.c
10817 views
/*1* Copyright (C) 1999, 2000, 2004, 2005 MIPS Technologies, Inc.2* All rights reserved.3* Authors: Carsten Langgaard <[email protected]>4* Maciej W. Rozycki <[email protected]>5*6* This program is free software; you can distribute it and/or modify it7* under the terms of the GNU General Public License (Version 2) as8* published by the Free Software Foundation.9*10* This program is distributed in the hope it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* for more details.14*15* You should have received a copy of the GNU General Public License along16* with this program; if not, write to the Free Software Foundation, Inc.,17* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.18*19* PROM library initialisation code.20*/21#include <linux/init.h>22#include <linux/string.h>23#include <linux/kernel.h>2425#include <asm/bootinfo.h>26#include <asm/gt64120.h>27#include <asm/io.h>28#include <asm/system.h>29#include <asm/cacheflush.h>30#include <asm/traps.h>3132#include <asm/gcmpregs.h>33#include <asm/mips-boards/prom.h>34#include <asm/mips-boards/generic.h>35#include <asm/mips-boards/bonito64.h>36#include <asm/mips-boards/msc01_pci.h>3738#include <asm/mips-boards/malta.h>3940int prom_argc;41int *_prom_argv, *_prom_envp;4243/*44* YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.45* This macro take care of sign extension, if running in 64-bit mode.46*/47#define prom_envp(index) ((char *)(long)_prom_envp[(index)])4849int init_debug;5051static int mips_revision_corid;52int mips_revision_sconid;5354/* Bonito64 system controller register base. */55unsigned long _pcictrl_bonito;56unsigned long _pcictrl_bonito_pcicfg;5758/* GT64120 system controller register base */59unsigned long _pcictrl_gt64120;6061/* MIPS System controller register base */62unsigned long _pcictrl_msc;6364char *prom_getenv(char *envname)65{66/*67* Return a pointer to the given environment variable.68* In 64-bit mode: we're using 64-bit pointers, but all pointers69* in the PROM structures are only 32-bit, so we need some70* workarounds, if we are running in 64-bit mode.71*/72int i, index=0;7374i = strlen(envname);7576while (prom_envp(index)) {77if(strncmp(envname, prom_envp(index), i) == 0) {78return(prom_envp(index+1));79}80index += 2;81}8283return NULL;84}8586static inline unsigned char str2hexnum(unsigned char c)87{88if (c >= '0' && c <= '9')89return c - '0';90if (c >= 'a' && c <= 'f')91return c - 'a' + 10;92return 0; /* foo */93}9495static inline void str2eaddr(unsigned char *ea, unsigned char *str)96{97int i;9899for (i = 0; i < 6; i++) {100unsigned char num;101102if((*str == '.') || (*str == ':'))103str++;104num = str2hexnum(*str++) << 4;105num |= (str2hexnum(*str++));106ea[i] = num;107}108}109110int get_ethernet_addr(char *ethernet_addr)111{112char *ethaddr_str;113114ethaddr_str = prom_getenv("ethaddr");115if (!ethaddr_str) {116printk("ethaddr not set in boot prom\n");117return -1;118}119str2eaddr(ethernet_addr, ethaddr_str);120121if (init_debug > 1) {122int i;123printk("get_ethernet_addr: ");124for (i=0; i<5; i++)125printk("%02x:", (unsigned char)*(ethernet_addr+i));126printk("%02x\n", *(ethernet_addr+i));127}128129return 0;130}131132#ifdef CONFIG_SERIAL_8250_CONSOLE133static void __init console_config(void)134{135char console_string[40];136int baud = 0;137char parity = '\0', bits = '\0', flow = '\0';138char *s;139140if ((strstr(prom_getcmdline(), "console=")) == NULL) {141s = prom_getenv("modetty0");142if (s) {143while (*s >= '0' && *s <= '9')144baud = baud*10 + *s++ - '0';145if (*s == ',') s++;146if (*s) parity = *s++;147if (*s == ',') s++;148if (*s) bits = *s++;149if (*s == ',') s++;150if (*s == 'h') flow = 'r';151}152if (baud == 0)153baud = 38400;154if (parity != 'n' && parity != 'o' && parity != 'e')155parity = 'n';156if (bits != '7' && bits != '8')157bits = '8';158if (flow == '\0')159flow = 'r';160sprintf(console_string, " console=ttyS0,%d%c%c%c", baud, parity, bits, flow);161strcat(prom_getcmdline(), console_string);162pr_info("Config serial console:%s\n", console_string);163}164}165#endif166167static void __init mips_nmi_setup(void)168{169void *base;170extern char except_vec_nmi;171172base = cpu_has_veic ?173(void *)(CAC_BASE + 0xa80) :174(void *)(CAC_BASE + 0x380);175memcpy(base, &except_vec_nmi, 0x80);176flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);177}178179static void __init mips_ejtag_setup(void)180{181void *base;182extern char except_vec_ejtag_debug;183184base = cpu_has_veic ?185(void *)(CAC_BASE + 0xa00) :186(void *)(CAC_BASE + 0x300);187memcpy(base, &except_vec_ejtag_debug, 0x80);188flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);189}190191extern struct plat_smp_ops msmtc_smp_ops;192193void __init prom_init(void)194{195prom_argc = fw_arg0;196_prom_argv = (int *) fw_arg1;197_prom_envp = (int *) fw_arg2;198199mips_display_message("LINUX");200201/*202* early setup of _pcictrl_bonito so that we can determine203* the system controller on a CORE_EMUL board204*/205_pcictrl_bonito = (unsigned long)ioremap(BONITO_REG_BASE, BONITO_REG_SIZE);206207mips_revision_corid = MIPS_REVISION_CORID;208209if (mips_revision_corid == MIPS_REVISION_CORID_CORE_EMUL) {210if (BONITO_PCIDID == 0x0001df53 ||211BONITO_PCIDID == 0x0003df53)212mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_BON;213else214mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_MSC;215}216217mips_revision_sconid = MIPS_REVISION_SCONID;218if (mips_revision_sconid == MIPS_REVISION_SCON_OTHER) {219switch (mips_revision_corid) {220case MIPS_REVISION_CORID_QED_RM5261:221case MIPS_REVISION_CORID_CORE_LV:222case MIPS_REVISION_CORID_CORE_FPGA:223case MIPS_REVISION_CORID_CORE_FPGAR2:224mips_revision_sconid = MIPS_REVISION_SCON_GT64120;225break;226case MIPS_REVISION_CORID_CORE_EMUL_BON:227case MIPS_REVISION_CORID_BONITO64:228case MIPS_REVISION_CORID_CORE_20K:229mips_revision_sconid = MIPS_REVISION_SCON_BONITO;230break;231case MIPS_REVISION_CORID_CORE_MSC:232case MIPS_REVISION_CORID_CORE_FPGA2:233case MIPS_REVISION_CORID_CORE_24K:234/*235* SOCit/ROCit support is essentially identical236* but make an attempt to distinguish them237*/238mips_revision_sconid = MIPS_REVISION_SCON_SOCIT;239break;240case MIPS_REVISION_CORID_CORE_FPGA3:241case MIPS_REVISION_CORID_CORE_FPGA4:242case MIPS_REVISION_CORID_CORE_FPGA5:243case MIPS_REVISION_CORID_CORE_EMUL_MSC:244default:245/* See above */246mips_revision_sconid = MIPS_REVISION_SCON_ROCIT;247break;248}249}250251switch (mips_revision_sconid) {252u32 start, map, mask, data;253254case MIPS_REVISION_SCON_GT64120:255/*256* Setup the North bridge to do Master byte-lane swapping257* when running in bigendian.258*/259_pcictrl_gt64120 = (unsigned long)ioremap(MIPS_GT_BASE, 0x2000);260261#ifdef CONFIG_CPU_LITTLE_ENDIAN262GT_WRITE(GT_PCI0_CMD_OFS, GT_PCI0_CMD_MBYTESWAP_BIT |263GT_PCI0_CMD_SBYTESWAP_BIT);264#else265GT_WRITE(GT_PCI0_CMD_OFS, 0);266#endif267/* Fix up PCI I/O mapping if necessary (for Atlas). */268start = GT_READ(GT_PCI0IOLD_OFS);269map = GT_READ(GT_PCI0IOREMAP_OFS);270if ((start & map) != 0) {271map &= ~start;272GT_WRITE(GT_PCI0IOREMAP_OFS, map);273}274275set_io_port_base(MALTA_GT_PORT_BASE);276break;277278case MIPS_REVISION_SCON_BONITO:279_pcictrl_bonito_pcicfg = (unsigned long)ioremap(BONITO_PCICFG_BASE, BONITO_PCICFG_SIZE);280281/*282* Disable Bonito IOBC.283*/284BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG &285~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |286BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);287288/*289* Setup the North bridge to do Master byte-lane swapping290* when running in bigendian.291*/292#ifdef CONFIG_CPU_LITTLE_ENDIAN293BONITO_BONGENCFG = BONITO_BONGENCFG &294~(BONITO_BONGENCFG_MSTRBYTESWAP |295BONITO_BONGENCFG_BYTESWAP);296#else297BONITO_BONGENCFG = BONITO_BONGENCFG |298BONITO_BONGENCFG_MSTRBYTESWAP |299BONITO_BONGENCFG_BYTESWAP;300#endif301302set_io_port_base(MALTA_BONITO_PORT_BASE);303break;304305case MIPS_REVISION_SCON_SOCIT:306case MIPS_REVISION_SCON_ROCIT:307_pcictrl_msc = (unsigned long)ioremap(MIPS_MSC01_PCI_REG_BASE, 0x2000);308mips_pci_controller:309mb();310MSC_READ(MSC01_PCI_CFG, data);311MSC_WRITE(MSC01_PCI_CFG, data & ~MSC01_PCI_CFG_EN_BIT);312wmb();313314/* Fix up lane swapping. */315#ifdef CONFIG_CPU_LITTLE_ENDIAN316MSC_WRITE(MSC01_PCI_SWAP, MSC01_PCI_SWAP_NOSWAP);317#else318MSC_WRITE(MSC01_PCI_SWAP,319MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_IO_SHF |320MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_MEM_SHF |321MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_BAR0_SHF);322#endif323/* Fix up target memory mapping. */324MSC_READ(MSC01_PCI_BAR0, mask);325MSC_WRITE(MSC01_PCI_P2SCMSKL, mask & MSC01_PCI_BAR0_SIZE_MSK);326327/* Don't handle target retries indefinitely. */328if ((data & MSC01_PCI_CFG_MAXRTRY_MSK) ==329MSC01_PCI_CFG_MAXRTRY_MSK)330data = (data & ~(MSC01_PCI_CFG_MAXRTRY_MSK <<331MSC01_PCI_CFG_MAXRTRY_SHF)) |332((MSC01_PCI_CFG_MAXRTRY_MSK - 1) <<333MSC01_PCI_CFG_MAXRTRY_SHF);334335wmb();336MSC_WRITE(MSC01_PCI_CFG, data);337mb();338339set_io_port_base(MALTA_MSC_PORT_BASE);340break;341342case MIPS_REVISION_SCON_SOCITSC:343case MIPS_REVISION_SCON_SOCITSCP:344_pcictrl_msc = (unsigned long)ioremap(MIPS_SOCITSC_PCI_REG_BASE, 0x2000);345goto mips_pci_controller;346347default:348/* Unknown system controller */349mips_display_message("SC Error");350while (1); /* We die here... */351}352board_nmi_handler_setup = mips_nmi_setup;353board_ejtag_handler_setup = mips_ejtag_setup;354355prom_init_cmdline();356prom_meminit();357#ifdef CONFIG_SERIAL_8250_CONSOLE358console_config();359#endif360#ifdef CONFIG_MIPS_CMP361/* Early detection of CMP support */362if (gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ))363register_smp_ops(&cmp_smp_ops);364else365#endif366#ifdef CONFIG_MIPS_MT_SMP367register_smp_ops(&vsmp_smp_ops);368#endif369#ifdef CONFIG_MIPS_MT_SMTC370register_smp_ops(&msmtc_smp_ops);371#endif372}373374375