msp_prom.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. /*
  2. * BRIEF MODULE DESCRIPTION
  3. * PROM library initialisation code, assuming a version of
  4. * pmon is the boot code.
  5. *
  6. * Copyright 2000,2001 MontaVista Software Inc.
  7. * Author: MontaVista Software, Inc.
  8. * ppopov@mvista.com or source@mvista.com
  9. *
  10. * This file was derived from Carsten Langgaard's
  11. * arch/mips/mips-boards/xx files.
  12. *
  13. * Carsten Langgaard, carstenl@mips.com
  14. * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
  15. *
  16. * This program is free software; you can redistribute it and/or modify it
  17. * under the terms of the GNU General Public License as published by the
  18. * Free Software Foundation; either version 2 of the License, or (at your
  19. * option) any later version.
  20. *
  21. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  22. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  23. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
  24. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  25. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  26. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  27. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  28. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  30. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. * You should have received a copy of the GNU General Public License along
  33. * with this program; if not, write to the Free Software Foundation, Inc.,
  34. * 675 Mass Ave, Cambridge, MA 02139, USA.
  35. */
  36. #include <linux/module.h>
  37. #include <linux/kernel.h>
  38. #include <linux/init.h>
  39. #include <linux/string.h>
  40. #include <linux/interrupt.h>
  41. #include <linux/mm.h>
  42. #include <linux/slab.h>
  43. #include <asm/addrspace.h>
  44. #include <asm/bootinfo.h>
  45. #include <asm-generic/sections.h>
  46. #include <asm/page.h>
  47. #include <msp_prom.h>
  48. #include <msp_regs.h>
  49. /* global PROM environment variables and pointers */
  50. int prom_argc;
  51. char **prom_argv, **prom_envp;
  52. int *prom_vec;
  53. /* debug flag */
  54. int init_debug = 1;
  55. /* memory blocks */
  56. struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
  57. /* default feature sets */
  58. static char msp_default_features[] =
  59. #if defined(CONFIG_PMC_MSP4200_EVAL) \
  60. || defined(CONFIG_PMC_MSP4200_GW)
  61. "ERER";
  62. #elif defined(CONFIG_PMC_MSP7120_EVAL) \
  63. || defined(CONFIG_PMC_MSP7120_GW)
  64. "EMEMSP";
  65. #elif defined(CONFIG_PMC_MSP7120_FPGA)
  66. "EMEM";
  67. #endif
  68. /* conversion functions */
  69. static inline unsigned char str2hexnum(unsigned char c)
  70. {
  71. if (c >= '0' && c <= '9')
  72. return c - '0';
  73. if (c >= 'a' && c <= 'f')
  74. return c - 'a' + 10;
  75. return 0; /* foo */
  76. }
  77. int str2eaddr(unsigned char *ea, unsigned char *str)
  78. {
  79. int index = 0;
  80. unsigned char num = 0;
  81. while (*str != '\0') {
  82. if ((*str == '.') || (*str == ':')) {
  83. ea[index++] = num;
  84. num = 0;
  85. str++;
  86. } else {
  87. num = num << 4;
  88. num |= str2hexnum(*str++);
  89. }
  90. }
  91. if (index == 5) {
  92. ea[index++] = num;
  93. return 0;
  94. } else
  95. return -1;
  96. }
  97. EXPORT_SYMBOL(str2eaddr);
  98. static inline unsigned long str2hex(unsigned char *str)
  99. {
  100. int value = 0;
  101. while (*str) {
  102. value = value << 4;
  103. value |= str2hexnum(*str++);
  104. }
  105. return value;
  106. }
  107. /* function to query the system information */
  108. const char *get_system_type(void)
  109. {
  110. #if defined(CONFIG_PMC_MSP4200_EVAL)
  111. return "PMC-Sierra MSP4200 Eval Board";
  112. #elif defined(CONFIG_PMC_MSP4200_GW)
  113. return "PMC-Sierra MSP4200 VoIP Gateway";
  114. #elif defined(CONFIG_PMC_MSP7120_EVAL)
  115. return "PMC-Sierra MSP7120 Eval Board";
  116. #elif defined(CONFIG_PMC_MSP7120_GW)
  117. return "PMC-Sierra MSP7120 Residential Gateway";
  118. #elif defined(CONFIG_PMC_MSP7120_FPGA)
  119. return "PMC-Sierra MSP7120 FPGA";
  120. #else
  121. #error "What is the type of *your* MSP?"
  122. #endif
  123. }
  124. int get_ethernet_addr(char *ethaddr_name, char *ethernet_addr)
  125. {
  126. char *ethaddr_str;
  127. ethaddr_str = prom_getenv(ethaddr_name);
  128. if (!ethaddr_str) {
  129. printk(KERN_WARNING "%s not set in boot prom\n", ethaddr_name);
  130. return -1;
  131. }
  132. if (str2eaddr(ethernet_addr, ethaddr_str) == -1) {
  133. printk(KERN_WARNING "%s badly formatted-<%s>\n",
  134. ethaddr_name, ethaddr_str);
  135. return -1;
  136. }
  137. if (init_debug > 1) {
  138. int i;
  139. printk(KERN_DEBUG "get_ethernet_addr: for %s ", ethaddr_name);
  140. for (i = 0; i < 5; i++)
  141. printk(KERN_DEBUG "%02x:",
  142. (unsigned char)*(ethernet_addr+i));
  143. printk(KERN_DEBUG "%02x\n", *(ethernet_addr+i));
  144. }
  145. return 0;
  146. }
  147. EXPORT_SYMBOL(get_ethernet_addr);
  148. static char *get_features(void)
  149. {
  150. char *feature = prom_getenv(FEATURES);
  151. if (feature == NULL) {
  152. /* default features based on MACHINE_TYPE */
  153. feature = msp_default_features;
  154. }
  155. return feature;
  156. }
  157. static char test_feature(char c)
  158. {
  159. char *feature = get_features();
  160. while (*feature) {
  161. if (*feature++ == c)
  162. return *feature;
  163. feature++;
  164. }
  165. return FEATURE_NOEXIST;
  166. }
  167. unsigned long get_deviceid(void)
  168. {
  169. char *deviceid = prom_getenv(DEVICEID);
  170. if (deviceid == NULL)
  171. return *DEV_ID_REG;
  172. else
  173. return str2hex(deviceid);
  174. }
  175. char identify_pci(void)
  176. {
  177. return test_feature(PCI_KEY);
  178. }
  179. EXPORT_SYMBOL(identify_pci);
  180. char identify_pcimux(void)
  181. {
  182. return test_feature(PCIMUX_KEY);
  183. }
  184. char identify_sec(void)
  185. {
  186. return test_feature(SEC_KEY);
  187. }
  188. EXPORT_SYMBOL(identify_sec);
  189. char identify_spad(void)
  190. {
  191. return test_feature(SPAD_KEY);
  192. }
  193. EXPORT_SYMBOL(identify_spad);
  194. char identify_tdm(void)
  195. {
  196. return test_feature(TDM_KEY);
  197. }
  198. EXPORT_SYMBOL(identify_tdm);
  199. char identify_zsp(void)
  200. {
  201. return test_feature(ZSP_KEY);
  202. }
  203. EXPORT_SYMBOL(identify_zsp);
  204. static char identify_enetfeature(char key, unsigned long interface_num)
  205. {
  206. char *feature = get_features();
  207. while (*feature) {
  208. if (*feature++ == key && interface_num-- == 0)
  209. return *feature;
  210. feature++;
  211. }
  212. return FEATURE_NOEXIST;
  213. }
  214. char identify_enet(unsigned long interface_num)
  215. {
  216. return identify_enetfeature(ENET_KEY, interface_num);
  217. }
  218. EXPORT_SYMBOL(identify_enet);
  219. char identify_enetTxD(unsigned long interface_num)
  220. {
  221. return identify_enetfeature(ENETTXD_KEY, interface_num);
  222. }
  223. EXPORT_SYMBOL(identify_enetTxD);
  224. unsigned long identify_family(void)
  225. {
  226. unsigned long deviceid;
  227. deviceid = get_deviceid();
  228. return deviceid & CPU_DEVID_FAMILY;
  229. }
  230. EXPORT_SYMBOL(identify_family);
  231. unsigned long identify_revision(void)
  232. {
  233. unsigned long deviceid;
  234. deviceid = get_deviceid();
  235. return deviceid & CPU_DEVID_REVISION;
  236. }
  237. EXPORT_SYMBOL(identify_revision);
  238. /* PROM environment functions */
  239. char *prom_getenv(char *env_name)
  240. {
  241. /*
  242. * Return a pointer to the given environment variable. prom_envp
  243. * points to a null terminated array of pointers to variables.
  244. * Environment variables are stored in the form of "memsize=64"
  245. */
  246. char **var = prom_envp;
  247. int i = strlen(env_name);
  248. while (*var) {
  249. if (strncmp(env_name, *var, i) == 0) {
  250. return *var + strlen(env_name) + 1;
  251. }
  252. var++;
  253. }
  254. return NULL;
  255. }
  256. /* PROM commandline functions */
  257. void __init prom_init_cmdline(void)
  258. {
  259. char *cp;
  260. int actr;
  261. actr = 1; /* Always ignore argv[0] */
  262. cp = &(arcs_cmdline[0]);
  263. while (actr < prom_argc) {
  264. strcpy(cp, prom_argv[actr]);
  265. cp += strlen(prom_argv[actr]);
  266. *cp++ = ' ';
  267. actr++;
  268. }
  269. if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
  270. --cp;
  271. *cp = '\0';
  272. }
  273. /* memory allocation functions */
  274. static int __init prom_memtype_classify(unsigned int type)
  275. {
  276. switch (type) {
  277. case yamon_free:
  278. return BOOT_MEM_RAM;
  279. case yamon_prom:
  280. return BOOT_MEM_ROM_DATA;
  281. default:
  282. return BOOT_MEM_RESERVED;
  283. }
  284. }
  285. void __init prom_meminit(void)
  286. {
  287. struct prom_pmemblock *p;
  288. p = prom_getmdesc();
  289. while (p->size) {
  290. long type;
  291. unsigned long base, size;
  292. type = prom_memtype_classify(p->type);
  293. base = p->base;
  294. size = p->size;
  295. add_memory_region(base, size, type);
  296. p++;
  297. }
  298. }
  299. void __init prom_free_prom_memory(void)
  300. {
  301. int argc;
  302. char **argv;
  303. char **envp;
  304. char *ptr;
  305. int len = 0;
  306. int i;
  307. unsigned long addr;
  308. /*
  309. * preserve environment variables and command line from pmon/bbload
  310. * first preserve the command line
  311. */
  312. for (argc = 0; argc < prom_argc; argc++) {
  313. len += sizeof(char *); /* length of pointer */
  314. len += strlen(prom_argv[argc]) + 1; /* length of string */
  315. }
  316. len += sizeof(char *); /* plus length of null pointer */
  317. argv = kmalloc(len, GFP_KERNEL);
  318. ptr = (char *) &argv[prom_argc + 1]; /* strings follow array */
  319. for (argc = 0; argc < prom_argc; argc++) {
  320. argv[argc] = ptr;
  321. strcpy(ptr, prom_argv[argc]);
  322. ptr += strlen(prom_argv[argc]) + 1;
  323. }
  324. argv[prom_argc] = NULL; /* end array with null pointer */
  325. prom_argv = argv;
  326. /* next preserve the environment variables */
  327. len = 0;
  328. i = 0;
  329. for (envp = prom_envp; *envp != NULL; envp++) {
  330. i++; /* count number of environment variables */
  331. len += sizeof(char *); /* length of pointer */
  332. len += strlen(*envp) + 1; /* length of string */
  333. }
  334. len += sizeof(char *); /* plus length of null pointer */
  335. envp = kmalloc(len, GFP_KERNEL);
  336. ptr = (char *) &envp[i+1];
  337. for (argc = 0; argc < i; argc++) {
  338. envp[argc] = ptr;
  339. strcpy(ptr, prom_envp[argc]);
  340. ptr += strlen(prom_envp[argc]) + 1;
  341. }
  342. envp[i] = NULL; /* end array with null pointer */
  343. prom_envp = envp;
  344. for (i = 0; i < boot_mem_map.nr_map; i++) {
  345. if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
  346. continue;
  347. addr = boot_mem_map.map[i].addr;
  348. free_init_pages("prom memory",
  349. addr, addr + boot_mem_map.map[i].size);
  350. }
  351. }
  352. struct prom_pmemblock *__init prom_getmdesc(void)
  353. {
  354. static char memsz_env[] __initdata = "memsize";
  355. static char heaptop_env[] __initdata = "heaptop";
  356. char *str;
  357. unsigned int memsize;
  358. unsigned int heaptop;
  359. int i;
  360. str = prom_getenv(memsz_env);
  361. if (!str) {
  362. ppfinit("memsize not set in boot prom, "
  363. "set to default (32Mb)\n");
  364. memsize = 0x02000000;
  365. } else {
  366. memsize = simple_strtol(str, NULL, 0);
  367. if (memsize == 0) {
  368. /* if memsize is a bad size, use reasonable default */
  369. memsize = 0x02000000;
  370. }
  371. /* convert to physical address (removing caching bits, etc) */
  372. memsize = CPHYSADDR(memsize);
  373. }
  374. str = prom_getenv(heaptop_env);
  375. if (!str) {
  376. heaptop = CPHYSADDR((u32)&_text);
  377. ppfinit("heaptop not set in boot prom, "
  378. "set to default 0x%08x\n", heaptop);
  379. } else {
  380. heaptop = simple_strtol(str, NULL, 16);
  381. if (heaptop == 0) {
  382. /* heaptop conversion bad, might have 0xValue */
  383. heaptop = simple_strtol(str, NULL, 0);
  384. if (heaptop == 0) {
  385. /* heaptop still bad, use reasonable default */
  386. heaptop = CPHYSADDR((u32)&_text);
  387. }
  388. }
  389. /* convert to physical address (removing caching bits, etc) */
  390. heaptop = CPHYSADDR((u32)heaptop);
  391. }
  392. /* the base region */
  393. i = 0;
  394. mdesc[i].type = BOOT_MEM_RESERVED;
  395. mdesc[i].base = 0x00000000;
  396. mdesc[i].size = PAGE_ALIGN(0x300 + 0x80);
  397. /* jtag interrupt vector + sizeof vector */
  398. /* PMON data */
  399. if (heaptop > mdesc[i].base + mdesc[i].size) {
  400. i++; /* 1 */
  401. mdesc[i].type = BOOT_MEM_ROM_DATA;
  402. mdesc[i].base = mdesc[i-1].base + mdesc[i-1].size;
  403. mdesc[i].size = heaptop - mdesc[i].base;
  404. }
  405. /* end of PMON data to start of kernel -- probably zero .. */
  406. if (heaptop != CPHYSADDR((u32)_text)) {
  407. i++; /* 2 */
  408. mdesc[i].type = BOOT_MEM_RAM;
  409. mdesc[i].base = heaptop;
  410. mdesc[i].size = CPHYSADDR((u32)_text) - mdesc[i].base;
  411. }
  412. /* kernel proper */
  413. i++; /* 3 */
  414. mdesc[i].type = BOOT_MEM_RESERVED;
  415. mdesc[i].base = CPHYSADDR((u32)_text);
  416. mdesc[i].size = CPHYSADDR(PAGE_ALIGN((u32)_end)) - mdesc[i].base;
  417. /* Remainder of RAM -- under memsize */
  418. i++; /* 5 */
  419. mdesc[i].type = yamon_free;
  420. mdesc[i].base = mdesc[i-1].base + mdesc[i-1].size;
  421. mdesc[i].size = memsize - mdesc[i].base;
  422. return &mdesc[0];
  423. }