123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504 |
- /*
- * BRIEF MODULE DESCRIPTION
- * PROM library initialisation code, assuming a version of
- * pmon is the boot code.
- *
- * Copyright 2000,2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * ppopov@mvista.com or source@mvista.com
- *
- * This file was derived from Carsten Langgaard's
- * arch/mips/mips-boards/xx files.
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/string.h>
- #include <linux/interrupt.h>
- #include <linux/mm.h>
- #include <linux/slab.h>
- #include <asm/addrspace.h>
- #include <asm/bootinfo.h>
- #include <asm-generic/sections.h>
- #include <asm/page.h>
- #include <msp_prom.h>
- #include <msp_regs.h>
- /* global PROM environment variables and pointers */
- int prom_argc;
- char **prom_argv, **prom_envp;
- int *prom_vec;
- /* debug flag */
- int init_debug = 1;
- /* memory blocks */
- struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
- /* default feature sets */
- static char msp_default_features[] =
- #if defined(CONFIG_PMC_MSP4200_EVAL) \
- || defined(CONFIG_PMC_MSP4200_GW)
- "ERER";
- #elif defined(CONFIG_PMC_MSP7120_EVAL) \
- || defined(CONFIG_PMC_MSP7120_GW)
- "EMEMSP";
- #elif defined(CONFIG_PMC_MSP7120_FPGA)
- "EMEM";
- #endif
- /* conversion functions */
- static inline unsigned char str2hexnum(unsigned char c)
- {
- if (c >= '0' && c <= '9')
- return c - '0';
- if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
- return 0; /* foo */
- }
- int str2eaddr(unsigned char *ea, unsigned char *str)
- {
- int index = 0;
- unsigned char num = 0;
- while (*str != '\0') {
- if ((*str == '.') || (*str == ':')) {
- ea[index++] = num;
- num = 0;
- str++;
- } else {
- num = num << 4;
- num |= str2hexnum(*str++);
- }
- }
- if (index == 5) {
- ea[index++] = num;
- return 0;
- } else
- return -1;
- }
- EXPORT_SYMBOL(str2eaddr);
- static inline unsigned long str2hex(unsigned char *str)
- {
- int value = 0;
- while (*str) {
- value = value << 4;
- value |= str2hexnum(*str++);
- }
- return value;
- }
- /* function to query the system information */
- const char *get_system_type(void)
- {
- #if defined(CONFIG_PMC_MSP4200_EVAL)
- return "PMC-Sierra MSP4200 Eval Board";
- #elif defined(CONFIG_PMC_MSP4200_GW)
- return "PMC-Sierra MSP4200 VoIP Gateway";
- #elif defined(CONFIG_PMC_MSP7120_EVAL)
- return "PMC-Sierra MSP7120 Eval Board";
- #elif defined(CONFIG_PMC_MSP7120_GW)
- return "PMC-Sierra MSP7120 Residential Gateway";
- #elif defined(CONFIG_PMC_MSP7120_FPGA)
- return "PMC-Sierra MSP7120 FPGA";
- #else
- #error "What is the type of *your* MSP?"
- #endif
- }
- int get_ethernet_addr(char *ethaddr_name, char *ethernet_addr)
- {
- char *ethaddr_str;
- ethaddr_str = prom_getenv(ethaddr_name);
- if (!ethaddr_str) {
- printk(KERN_WARNING "%s not set in boot prom\n", ethaddr_name);
- return -1;
- }
- if (str2eaddr(ethernet_addr, ethaddr_str) == -1) {
- printk(KERN_WARNING "%s badly formatted-<%s>\n",
- ethaddr_name, ethaddr_str);
- return -1;
- }
- if (init_debug > 1) {
- int i;
- printk(KERN_DEBUG "get_ethernet_addr: for %s ", ethaddr_name);
- for (i = 0; i < 5; i++)
- printk(KERN_DEBUG "%02x:",
- (unsigned char)*(ethernet_addr+i));
- printk(KERN_DEBUG "%02x\n", *(ethernet_addr+i));
- }
- return 0;
- }
- EXPORT_SYMBOL(get_ethernet_addr);
- static char *get_features(void)
- {
- char *feature = prom_getenv(FEATURES);
- if (feature == NULL) {
- /* default features based on MACHINE_TYPE */
- feature = msp_default_features;
- }
- return feature;
- }
- static char test_feature(char c)
- {
- char *feature = get_features();
- while (*feature) {
- if (*feature++ == c)
- return *feature;
- feature++;
- }
- return FEATURE_NOEXIST;
- }
- unsigned long get_deviceid(void)
- {
- char *deviceid = prom_getenv(DEVICEID);
- if (deviceid == NULL)
- return *DEV_ID_REG;
- else
- return str2hex(deviceid);
- }
- char identify_pci(void)
- {
- return test_feature(PCI_KEY);
- }
- EXPORT_SYMBOL(identify_pci);
- char identify_pcimux(void)
- {
- return test_feature(PCIMUX_KEY);
- }
- char identify_sec(void)
- {
- return test_feature(SEC_KEY);
- }
- EXPORT_SYMBOL(identify_sec);
- char identify_spad(void)
- {
- return test_feature(SPAD_KEY);
- }
- EXPORT_SYMBOL(identify_spad);
- char identify_tdm(void)
- {
- return test_feature(TDM_KEY);
- }
- EXPORT_SYMBOL(identify_tdm);
- char identify_zsp(void)
- {
- return test_feature(ZSP_KEY);
- }
- EXPORT_SYMBOL(identify_zsp);
- static char identify_enetfeature(char key, unsigned long interface_num)
- {
- char *feature = get_features();
- while (*feature) {
- if (*feature++ == key && interface_num-- == 0)
- return *feature;
- feature++;
- }
- return FEATURE_NOEXIST;
- }
- char identify_enet(unsigned long interface_num)
- {
- return identify_enetfeature(ENET_KEY, interface_num);
- }
- EXPORT_SYMBOL(identify_enet);
- char identify_enetTxD(unsigned long interface_num)
- {
- return identify_enetfeature(ENETTXD_KEY, interface_num);
- }
- EXPORT_SYMBOL(identify_enetTxD);
- unsigned long identify_family(void)
- {
- unsigned long deviceid;
- deviceid = get_deviceid();
- return deviceid & CPU_DEVID_FAMILY;
- }
- EXPORT_SYMBOL(identify_family);
- unsigned long identify_revision(void)
- {
- unsigned long deviceid;
- deviceid = get_deviceid();
- return deviceid & CPU_DEVID_REVISION;
- }
- EXPORT_SYMBOL(identify_revision);
- /* PROM environment functions */
- char *prom_getenv(char *env_name)
- {
- /*
- * Return a pointer to the given environment variable. prom_envp
- * points to a null terminated array of pointers to variables.
- * Environment variables are stored in the form of "memsize=64"
- */
- char **var = prom_envp;
- int i = strlen(env_name);
- while (*var) {
- if (strncmp(env_name, *var, i) == 0) {
- return *var + strlen(env_name) + 1;
- }
- var++;
- }
- return NULL;
- }
- /* PROM commandline functions */
- void __init prom_init_cmdline(void)
- {
- char *cp;
- int actr;
- actr = 1; /* Always ignore argv[0] */
- cp = &(arcs_cmdline[0]);
- while (actr < prom_argc) {
- strcpy(cp, prom_argv[actr]);
- cp += strlen(prom_argv[actr]);
- *cp++ = ' ';
- actr++;
- }
- if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
- --cp;
- *cp = '\0';
- }
- /* memory allocation functions */
- static int __init prom_memtype_classify(unsigned int type)
- {
- switch (type) {
- case yamon_free:
- return BOOT_MEM_RAM;
- case yamon_prom:
- return BOOT_MEM_ROM_DATA;
- default:
- return BOOT_MEM_RESERVED;
- }
- }
- void __init prom_meminit(void)
- {
- struct prom_pmemblock *p;
- p = prom_getmdesc();
- while (p->size) {
- long type;
- unsigned long base, size;
- type = prom_memtype_classify(p->type);
- base = p->base;
- size = p->size;
- add_memory_region(base, size, type);
- p++;
- }
- }
- void __init prom_free_prom_memory(void)
- {
- int argc;
- char **argv;
- char **envp;
- char *ptr;
- int len = 0;
- int i;
- unsigned long addr;
- /*
- * preserve environment variables and command line from pmon/bbload
- * first preserve the command line
- */
- for (argc = 0; argc < prom_argc; argc++) {
- len += sizeof(char *); /* length of pointer */
- len += strlen(prom_argv[argc]) + 1; /* length of string */
- }
- len += sizeof(char *); /* plus length of null pointer */
- argv = kmalloc(len, GFP_KERNEL);
- ptr = (char *) &argv[prom_argc + 1]; /* strings follow array */
- for (argc = 0; argc < prom_argc; argc++) {
- argv[argc] = ptr;
- strcpy(ptr, prom_argv[argc]);
- ptr += strlen(prom_argv[argc]) + 1;
- }
- argv[prom_argc] = NULL; /* end array with null pointer */
- prom_argv = argv;
- /* next preserve the environment variables */
- len = 0;
- i = 0;
- for (envp = prom_envp; *envp != NULL; envp++) {
- i++; /* count number of environment variables */
- len += sizeof(char *); /* length of pointer */
- len += strlen(*envp) + 1; /* length of string */
- }
- len += sizeof(char *); /* plus length of null pointer */
- envp = kmalloc(len, GFP_KERNEL);
- ptr = (char *) &envp[i+1];
- for (argc = 0; argc < i; argc++) {
- envp[argc] = ptr;
- strcpy(ptr, prom_envp[argc]);
- ptr += strlen(prom_envp[argc]) + 1;
- }
- envp[i] = NULL; /* end array with null pointer */
- prom_envp = envp;
- for (i = 0; i < boot_mem_map.nr_map; i++) {
- if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
- continue;
- addr = boot_mem_map.map[i].addr;
- free_init_pages("prom memory",
- addr, addr + boot_mem_map.map[i].size);
- }
- }
- struct prom_pmemblock *__init prom_getmdesc(void)
- {
- static char memsz_env[] __initdata = "memsize";
- static char heaptop_env[] __initdata = "heaptop";
- char *str;
- unsigned int memsize;
- unsigned int heaptop;
- int i;
- str = prom_getenv(memsz_env);
- if (!str) {
- ppfinit("memsize not set in boot prom, "
- "set to default (32Mb)\n");
- memsize = 0x02000000;
- } else {
- memsize = simple_strtol(str, NULL, 0);
- if (memsize == 0) {
- /* if memsize is a bad size, use reasonable default */
- memsize = 0x02000000;
- }
- /* convert to physical address (removing caching bits, etc) */
- memsize = CPHYSADDR(memsize);
- }
- str = prom_getenv(heaptop_env);
- if (!str) {
- heaptop = CPHYSADDR((u32)&_text);
- ppfinit("heaptop not set in boot prom, "
- "set to default 0x%08x\n", heaptop);
- } else {
- heaptop = simple_strtol(str, NULL, 16);
- if (heaptop == 0) {
- /* heaptop conversion bad, might have 0xValue */
- heaptop = simple_strtol(str, NULL, 0);
- if (heaptop == 0) {
- /* heaptop still bad, use reasonable default */
- heaptop = CPHYSADDR((u32)&_text);
- }
- }
- /* convert to physical address (removing caching bits, etc) */
- heaptop = CPHYSADDR((u32)heaptop);
- }
- /* the base region */
- i = 0;
- mdesc[i].type = BOOT_MEM_RESERVED;
- mdesc[i].base = 0x00000000;
- mdesc[i].size = PAGE_ALIGN(0x300 + 0x80);
- /* jtag interrupt vector + sizeof vector */
- /* PMON data */
- if (heaptop > mdesc[i].base + mdesc[i].size) {
- i++; /* 1 */
- mdesc[i].type = BOOT_MEM_ROM_DATA;
- mdesc[i].base = mdesc[i-1].base + mdesc[i-1].size;
- mdesc[i].size = heaptop - mdesc[i].base;
- }
- /* end of PMON data to start of kernel -- probably zero .. */
- if (heaptop != CPHYSADDR((u32)_text)) {
- i++; /* 2 */
- mdesc[i].type = BOOT_MEM_RAM;
- mdesc[i].base = heaptop;
- mdesc[i].size = CPHYSADDR((u32)_text) - mdesc[i].base;
- }
- /* kernel proper */
- i++; /* 3 */
- mdesc[i].type = BOOT_MEM_RESERVED;
- mdesc[i].base = CPHYSADDR((u32)_text);
- mdesc[i].size = CPHYSADDR(PAGE_ALIGN((u32)_end)) - mdesc[i].base;
- /* Remainder of RAM -- under memsize */
- i++; /* 5 */
- mdesc[i].type = yamon_free;
- mdesc[i].base = mdesc[i-1].base + mdesc[i-1].size;
- mdesc[i].size = memsize - mdesc[i].base;
- return &mdesc[0];
- }
|