1/* 2 * Ralink SoC specific prom routines 3 * 4 * Copyright (C) 2010 Joonas Lahtinen <joonas.lahtinen@gmail.com> 5 * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 as published 9 * by the Free Software Foundation. 10 */ 11 12#include <linux/kernel.h> 13#include <linux/init.h> 14#include <linux/string.h> 15 16#include <asm/bootinfo.h> 17#include <asm/addrspace.h> 18 19#include <asm/mach-ralink/common.h> 20#include <asm/mach-ralink/machine.h> 21 22unsigned long ramips_mem_base; 23unsigned long ramips_mem_size_min; 24unsigned long ramips_mem_size_max; 25 26static inline void *to_ram_addr(void *addr) 27{ 28 u32 base; 29 30 base = KSEG0ADDR(ramips_mem_base); 31 if (((u32) addr > base) && 32 ((u32) addr < (base + ramips_mem_size_max))) 33 return addr; 34 35 base = KSEG1ADDR(ramips_mem_base); 36 if (((u32) addr > base) && 37 ((u32) addr < (base + ramips_mem_size_max))) 38 return addr; 39 40 /* some U-Boot variants uses physical addresses */ 41 base = ramips_mem_base; 42 if (((u32) addr > base) && 43 ((u32) addr < (base + ramips_mem_size_max))) 44 return (void *)KSEG0ADDR(addr); 45 46 return NULL; 47} 48 49static char ramips_cmdline_buf[COMMAND_LINE_SIZE] __initdata; 50static void __init prom_append_cmdline(const char *name, 51 const char *value) 52{ 53 snprintf(ramips_cmdline_buf, sizeof(ramips_cmdline_buf), 54 " %s=%s", name, value); 55 strlcat(arcs_cmdline, ramips_cmdline_buf, sizeof(arcs_cmdline)); 56} 57 58#ifdef CONFIG_IMAGE_CMDLINE_HACK 59extern char __image_cmdline[]; 60 61static int __init use_image_cmdline(void) 62{ 63 char *p = __image_cmdline; 64 int replace = 0; 65 66 if (*p == '-') { 67 replace = 1; 68 p++; 69 } 70 71 if (*p == '\0') 72 return 0; 73 74 if (replace) { 75 strlcpy(arcs_cmdline, p, sizeof(arcs_cmdline)); 76 } else { 77 strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline)); 78 strlcat(arcs_cmdline, p, sizeof(arcs_cmdline)); 79 } 80 81 return 1; 82} 83#else 84static int inline use_image_cmdline(void) { return 0; } 85#endif 86 87static __init void prom_init_cmdline(int argc, char **argv) 88{ 89 int i; 90 91 if (use_image_cmdline()) 92 return; 93 94 if (!argv) { 95 printk(KERN_DEBUG "argv=%p is invalid, skipping\n", 96 argv); 97 return; 98 } 99 100 for (i = 0; i < argc; i++) { 101 char *p = to_ram_addr(argv[i]); 102 103 if (!p) { 104 printk(KERN_DEBUG 105 "argv[%d]=%p is invalid, skipping\n", 106 i, argv[i]); 107 continue; 108 } 109 110 printk(KERN_DEBUG "argv[%d]: %s\n", i, p); 111 strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline)); 112 strlcat(arcs_cmdline, p, sizeof(arcs_cmdline)); 113 } 114} 115 116static __init char *prom_append_env(char **env, const char *envname) 117{ 118#define PROM_MAX_ENVS 256 119 int len = strlen(envname); 120 int i; 121 122 if (!env) { 123 printk(KERN_DEBUG "env=%p is not in RAM, skipping\n", 124 env); 125 return NULL; 126 } 127 128 for (i = 0; i < PROM_MAX_ENVS; i++) { 129 char *p = to_ram_addr(env[i]); 130 131 if (!p) 132 break; 133 134 printk(KERN_DEBUG "env[%d]: %s\n", i, p); 135 if (strncmp(envname, p, len) == 0 && p[len] == '=') 136 prom_append_cmdline(envname, p + len + 1); 137 } 138 139 return NULL; 140#undef PROM_MAX_ENVS 141} 142 143void __init prom_init(void) 144{ 145 int argc; 146 char **envp; 147 char **argv; 148 149 ramips_soc_prom_init(); 150 151 printk(KERN_DEBUG 152 "prom: fw_arg0=%08x, fw_arg1=%08x, fw_arg2=%08x, fw_arg3=%08x\n", 153 (unsigned int)fw_arg0, (unsigned int)fw_arg1, 154 (unsigned int)fw_arg2, (unsigned int)fw_arg3); 155 156 argc = fw_arg0; 157 argv = to_ram_addr((void *)fw_arg1); 158 prom_init_cmdline(argc, argv); 159 160 envp = to_ram_addr((void *)fw_arg2); 161 prom_append_env(envp, "board"); 162 prom_append_env(envp, "ethaddr"); 163} 164 165void __init prom_free_prom_memory(void) 166{ 167 /* We do not have to prom memory to free */ 168} 169