msp_prom.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  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 <asm/addrspace.h>
  43. #include <asm/bootinfo.h>
  44. #include <asm-generic/sections.h>
  45. #include <asm/page.h>
  46. #include <msp_prom.h>
  47. #include <msp_regs.h>
  48. /* global PROM environment variables and pointers */
  49. int prom_argc;
  50. char **prom_argv, **prom_envp;
  51. int *prom_vec;
  52. /* debug flag */
  53. int init_debug = 1;
  54. /* memory blocks */
  55. struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
  56. /* default feature sets */
  57. static char msp_default_features[] =
  58. #if defined(CONFIG_PMC_MSP4200_EVAL) \
  59. || defined(CONFIG_PMC_MSP4200_GW)
  60. "ERER";
  61. #elif defined(CONFIG_PMC_MSP7120_EVAL) \
  62. || defined(CONFIG_PMC_MSP7120_GW)
  63. "EMEMSP";
  64. #elif defined(CONFIG_PMC_MSP7120_FPGA)
  65. "EMEM";
  66. #endif
  67. /* conversion functions */
  68. static inline unsigned char str2hexnum(unsigned char c)
  69. {
  70. if (c >= '0' && c <= '9')
  71. return c - '0';
  72. if (c >= 'a' && c <= 'f')
  73. return c - 'a' + 10;
  74. return 0; /* foo */
  75. }
  76. static inline int str2eaddr(unsigned char *ea, unsigned char *str)
  77. {
  78. int index = 0;
  79. unsigned char num = 0;
  80. while (*str != '\0') {
  81. if ((*str == '.') || (*str == ':')) {
  82. ea[index++] = num;
  83. num = 0;
  84. str++;
  85. } else {
  86. num = num << 4;
  87. num |= str2hexnum(*str++);
  88. }
  89. }
  90. if (index == 5) {
  91. ea[index++] = num;
  92. return 0;
  93. } else
  94. return -1;
  95. }
  96. EXPORT_SYMBOL(str2eaddr);
  97. static inline unsigned long str2hex(unsigned char *str)
  98. {
  99. int value = 0;
  100. while (*str) {
  101. value = value << 4;
  102. value |= str2hexnum(*str++);
  103. }
  104. return value;
  105. }
  106. /* function to query the system information */
  107. const char *get_system_type(void)
  108. {
  109. #if defined(CONFIG_PMC_MSP4200_EVAL)
  110. return "PMC-Sierra MSP4200 Eval Board";
  111. #elif defined(CONFIG_PMC_MSP4200_GW)
  112. return "PMC-Sierra MSP4200 VoIP Gateway";
  113. #elif defined(CONFIG_PMC_MSP7120_EVAL)
  114. return "PMC-Sierra MSP7120 Eval Board";
  115. #elif defined(CONFIG_PMC_MSP7120_GW)
  116. return "PMC-Sierra MSP7120 Residential Gateway";
  117. #elif defined(CONFIG_PMC_MSP7120_FPGA)
  118. return "PMC-Sierra MSP7120 FPGA";
  119. #else
  120. #error "What is the type of *your* MSP?"
  121. #endif
  122. }
  123. int get_ethernet_addr(char *ethaddr_name, char *ethernet_addr)
  124. {
  125. char *ethaddr_str;
  126. ethaddr_str = prom_getenv(ethaddr_name);
  127. if (!ethaddr_str) {
  128. printk(KERN_WARNING "%s not set in boot prom\n", ethaddr_name);
  129. return -1;
  130. }
  131. if (str2eaddr(ethernet_addr, ethaddr_str) == -1) {
  132. printk(KERN_WARNING "%s badly formatted-<%s>\n",
  133. ethaddr_name, ethaddr_str);
  134. return -1;
  135. }
  136. if (init_debug > 1) {
  137. int i;
  138. printk(KERN_DEBUG "get_ethernet_addr: for %s ", ethaddr_name);
  139. for (i = 0; i < 5; i++)
  140. printk(KERN_DEBUG "%02x:",
  141. (unsigned char)*(ethernet_addr+i));
  142. printk(KERN_DEBUG "%02x\n", *(ethernet_addr+i));
  143. }
  144. return 0;
  145. }
  146. EXPORT_SYMBOL(get_ethernet_addr);
  147. static char *get_features(void)
  148. {
  149. char *feature = prom_getenv(FEATURES);
  150. if (feature == NULL) {
  151. /* default features based on MACHINE_TYPE */
  152. feature = msp_default_features;
  153. }
  154. return feature;
  155. }
  156. static char test_feature(char c)
  157. {
  158. char *feature = get_features();
  159. while (*feature) {
  160. if (*feature++ == c)
  161. return *feature;
  162. feature++;
  163. }
  164. return FEATURE_NOEXIST;
  165. }
  166. unsigned long get_deviceid(void)
  167. {
  168. char *deviceid = prom_getenv(DEVICEID);
  169. if (deviceid == NULL)
  170. return *DEV_ID_REG;
  171. else
  172. return str2hex(deviceid);
  173. }
  174. char identify_pci(void)
  175. {
  176. return test_feature(PCI_KEY);
  177. }
  178. EXPORT_SYMBOL(identify_pci);
  179. char identify_pcimux(void)
  180. {
  181. return test_feature(PCIMUX_KEY);
  182. }
  183. char identify_sec(void)
  184. {
  185. return test_feature(SEC_KEY);
  186. }
  187. EXPORT_SYMBOL(identify_sec);
  188. char identify_spad(void)
  189. {
  190. return test_feature(SPAD_KEY);
  191. }
  192. EXPORT_SYMBOL(identify_spad);
  193. char identify_tdm(void)
  194. {
  195. return test_feature(TDM_KEY);
  196. }
  197. EXPORT_SYMBOL(identify_tdm);
  198. char identify_zsp(void)
  199. {
  200. return test_feature(ZSP_KEY);
  201. }
  202. EXPORT_SYMBOL(identify_zsp);
  203. static char identify_enetfeature(char key, unsigned long interface_num)
  204. {
  205. char *feature = get_features();
  206. while (*feature) {
  207. if (*feature++ == key && interface_num-- == 0)
  208. return *feature;
  209. feature++;
  210. }
  211. return FEATURE_NOEXIST;
  212. }
  213. char identify_enet(unsigned long interface_num)
  214. {
  215. return identify_enetfeature(ENET_KEY, interface_num);
  216. }
  217. EXPORT_SYMBOL(identify_enet);
  218. char identify_enetTxD(unsigned long interface_num)
  219. {
  220. return identify_enetfeature(ENETTXD_KEY, interface_num);
  221. }
  222. EXPORT_SYMBOL(identify_enetTxD);
  223. unsigned long identify_family(void)
  224. {
  225. unsigned long deviceid;
  226. deviceid = get_deviceid();
  227. return deviceid & CPU_DEVID_FAMILY;
  228. }
  229. EXPORT_SYMBOL(identify_family);
  230. unsigned long identify_revision(void)
  231. {
  232. unsigned long deviceid;
  233. deviceid = get_deviceid();
  234. return deviceid & CPU_DEVID_REVISION;
  235. }
  236. EXPORT_SYMBOL(identify_revision);
  237. /* PROM environment functions */
  238. char *prom_getenv(char *env_name)
  239. {
  240. /*
  241. * Return a pointer to the given environment variable. prom_envp
  242. * points to a null terminated array of pointers to variables.
  243. * Environment variables are stored in the form of "memsize=64"
  244. */
  245. char **var = prom_envp;
  246. int i = strlen(env_name);
  247. while (*var) {
  248. if (strncmp(env_name, *var, i) == 0) {
  249. return (*var + strlen(env_name) + 1);
  250. }
  251. var++;
  252. }
  253. return NULL;
  254. }
  255. /* PROM commandline functions */
  256. char *prom_getcmdline(void)
  257. {
  258. return &(arcs_cmdline[0]);
  259. }
  260. EXPORT_SYMBOL(prom_getcmdline);
  261. void __init prom_init_cmdline(void)
  262. {
  263. char *cp;
  264. int actr;
  265. actr = 1; /* Always ignore argv[0] */
  266. cp = &(arcs_cmdline[0]);
  267. while (actr < prom_argc) {
  268. strcpy(cp, prom_argv[actr]);
  269. cp += strlen(prom_argv[actr]);
  270. *cp++ = ' ';
  271. actr++;
  272. }
  273. if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
  274. --cp;
  275. *cp = '\0';
  276. }
  277. /* memory allocation functions */
  278. static int __init prom_memtype_classify(unsigned int type)
  279. {
  280. switch (type) {
  281. case yamon_free:
  282. return BOOT_MEM_RAM;
  283. case yamon_prom:
  284. return BOOT_MEM_ROM_DATA;
  285. default:
  286. return BOOT_MEM_RESERVED;
  287. }
  288. }
  289. void __init prom_meminit(void)
  290. {
  291. struct prom_pmemblock *p;
  292. p = prom_getmdesc();
  293. while (p->size) {
  294. long type;
  295. unsigned long base, size;
  296. type = prom_memtype_classify(p->type);
  297. base = p->base;
  298. size = p->size;
  299. add_memory_region(base, size, type);
  300. p++;
  301. }
  302. }
  303. void __init prom_free_prom_memory(void)
  304. {
  305. int argc;
  306. char **argv;
  307. char **envp;
  308. char *ptr;
  309. int len = 0;
  310. int i;
  311. unsigned long addr;
  312. /*
  313. * preserve environment variables and command line from pmon/bbload
  314. * first preserve the command line
  315. */
  316. for (argc = 0; argc < prom_argc; argc++) {
  317. len += sizeof(char *); /* length of pointer */
  318. len += strlen(prom_argv[argc]) + 1; /* length of string */
  319. }
  320. len += sizeof(char *); /* plus length of null pointer */
  321. argv = kmalloc(len, GFP_KERNEL);
  322. ptr = (char *) &argv[prom_argc + 1]; /* strings follow array */
  323. for (argc = 0; argc < prom_argc; argc++) {
  324. argv[argc] = ptr;
  325. strcpy(ptr, prom_argv[argc]);
  326. ptr += strlen(prom_argv[argc]) + 1;
  327. }
  328. argv[prom_argc] = NULL; /* end array with null pointer */
  329. prom_argv = argv;
  330. /* next preserve the environment variables */
  331. len = 0;
  332. i = 0;
  333. for (envp = prom_envp; *envp != NULL; envp++) {
  334. i++; /* count number of environment variables */
  335. len += sizeof(char *); /* length of pointer */
  336. len += strlen(*envp) + 1; /* length of string */
  337. }
  338. len += sizeof(char *); /* plus length of null pointer */
  339. envp = kmalloc(len, GFP_KERNEL);
  340. ptr = (char *) &envp[i+1];
  341. for (argc = 0; argc < i; argc++) {
  342. envp[argc] = ptr;
  343. strcpy(ptr, prom_envp[argc]);
  344. ptr += strlen(prom_envp[argc]) + 1;
  345. }
  346. envp[i] = NULL; /* end array with null pointer */
  347. prom_envp = envp;
  348. for (i = 0; i < boot_mem_map.nr_map; i++) {
  349. if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
  350. continue;
  351. addr = boot_mem_map.map[i].addr;
  352. free_init_pages("prom memory",
  353. addr, addr + boot_mem_map.map[i].size);
  354. }
  355. }
  356. struct prom_pmemblock *__init prom_getmdesc(void)
  357. {
  358. static char memsz_env[] __initdata = "memsize";
  359. static char heaptop_env[] __initdata = "heaptop";
  360. char *str;
  361. unsigned int memsize;
  362. unsigned int heaptop;
  363. int i;
  364. str = prom_getenv(memsz_env);
  365. if (!str) {
  366. ppfinit("memsize not set in boot prom, "
  367. "set to default (32Mb)\n");
  368. memsize = 0x02000000;
  369. } else {
  370. memsize = simple_strtol(str, NULL, 0);
  371. if (memsize == 0) {
  372. /* if memsize is a bad size, use reasonable default */
  373. memsize = 0x02000000;
  374. }
  375. /* convert to physical address (removing caching bits, etc) */
  376. memsize = CPHYSADDR(memsize);
  377. }
  378. str = prom_getenv(heaptop_env);
  379. if (!str) {
  380. heaptop = CPHYSADDR((u32)&_text);
  381. ppfinit("heaptop not set in boot prom, "
  382. "set to default 0x%08x\n", heaptop);
  383. } else {
  384. heaptop = simple_strtol(str, NULL, 16);
  385. if (heaptop == 0) {
  386. /* heaptop conversion bad, might have 0xValue */
  387. heaptop = simple_strtol(str, NULL, 0);
  388. if (heaptop == 0) {
  389. /* heaptop still bad, use reasonable default */
  390. heaptop = CPHYSADDR((u32)&_text);
  391. }
  392. }
  393. /* convert to physical address (removing caching bits, etc) */
  394. heaptop = CPHYSADDR((u32)heaptop);
  395. }
  396. /* the base region */
  397. i = 0;
  398. mdesc[i].type = BOOT_MEM_RESERVED;
  399. mdesc[i].base = 0x00000000;
  400. mdesc[i].size = PAGE_ALIGN(0x300 + 0x80);
  401. /* jtag interrupt vector + sizeof vector */
  402. /* PMON data */
  403. if (heaptop > mdesc[i].base + mdesc[i].size) {
  404. i++; /* 1 */
  405. mdesc[i].type = BOOT_MEM_ROM_DATA;
  406. mdesc[i].base = mdesc[i-1].base + mdesc[i-1].size;
  407. mdesc[i].size = heaptop - mdesc[i].base;
  408. }
  409. /* end of PMON data to start of kernel -- probably zero .. */
  410. if (heaptop != CPHYSADDR((u32)_text)) {
  411. i++; /* 2 */
  412. mdesc[i].type = BOOT_MEM_RAM;
  413. mdesc[i].base = heaptop;
  414. mdesc[i].size = CPHYSADDR((u32)_text) - mdesc[i].base;
  415. }
  416. /* kernel proper */
  417. i++; /* 3 */
  418. mdesc[i].type = BOOT_MEM_RESERVED;
  419. mdesc[i].base = CPHYSADDR((u32)_text);
  420. mdesc[i].size = CPHYSADDR(PAGE_ALIGN((u32)_end)) - mdesc[i].base;
  421. /* Remainder of RAM -- under memsize */
  422. i++; /* 5 */
  423. mdesc[i].type = yamon_free;
  424. mdesc[i].base = mdesc[i-1].base + mdesc[i-1].size;
  425. mdesc[i].size = memsize - mdesc[i].base;
  426. return &mdesc[0];
  427. }