aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-06 18:30:54 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-06 18:30:54 -0500
commitf70f5b9dc74ca7d0a64c4ead3fb28da09dc1b234 (patch)
tree01f79ae109966d2ec515358481c151cda549d9ab /arch/sparc/kernel
parentb69fc2efc9205d58c820eb2eb1caa6bf873b4b0d (diff)
parent09798eb9479da3413bdf96e7d22a84d8b21e05e1 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6: (25 commits) atyfb: Fix bootup hangs on sparc64. sparc: update copyright in piggyback.c sparc: unify strip command in boot/Makefile sparc: rename piggyback_32 to piggyback sparc: fix tftpboot.img for sparc64 on little-endian host sparc: add $BITS to piggyback arguments sparc: remove obsolete ELF support in piggyback_32.c sparc: additional comments to piggyback_32.c sparc: use _start for the start entry (like 64 bit does) sparc: use trapbase in setup_arch sparc: refactor piggy_32.c Added support for ampopts in APBUART driver. Used in AMP systems. APBUART: added raw AMBA vendor/device number to match against. SPARC/LEON: avoid AMBAPP name duplicates in openprom fs when REG is missing SPARC/LEON: added support for selecting Timer Core and Timer within core LEON: added raw AMBA vendor/device number to find TIMER, IRQCTRL SPARC/LEON: added support for IRQAMP IRQ Controller SPARC/LEON: find IRQCTRL and Timer via OF-Tree, instead of hardcoded. sparc: fix sparse warnings in arch/sparc/prom for 32 bit build sparc: remove unused prom tree functions ...
Diffstat (limited to 'arch/sparc/kernel')
-rw-r--r--arch/sparc/kernel/head_32.S3
-rw-r--r--arch/sparc/kernel/leon_kernel.c114
-rw-r--r--arch/sparc/kernel/prom_32.c27
-rw-r--r--arch/sparc/kernel/setup_32.c3
4 files changed, 118 insertions, 29 deletions
diff --git a/arch/sparc/kernel/head_32.S b/arch/sparc/kernel/head_32.S
index 21bb2590d4ae..59423491cef8 100644
--- a/arch/sparc/kernel/head_32.S
+++ b/arch/sparc/kernel/head_32.S
@@ -73,12 +73,11 @@ sun4e_notsup:
73 73
74 /* The Sparc trap table, bootloader gives us control at _start. */ 74 /* The Sparc trap table, bootloader gives us control at _start. */
75 __HEAD 75 __HEAD
76 .globl start, _stext, _start, __stext 76 .globl _stext, _start, __stext
77 .globl trapbase 77 .globl trapbase
78_start: /* danger danger */ 78_start: /* danger danger */
79__stext: 79__stext:
80_stext: 80_stext:
81start:
82trapbase: 81trapbase:
83#ifdef CONFIG_SMP 82#ifdef CONFIG_SMP
84trapbase_cpu0: 83trapbase_cpu0:
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
index f01c42661ee5..fdab7f854f80 100644
--- a/arch/sparc/kernel/leon_kernel.c
+++ b/arch/sparc/kernel/leon_kernel.c
@@ -23,15 +23,16 @@
23#include "prom.h" 23#include "prom.h"
24#include "irq.h" 24#include "irq.h"
25 25
26struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address, initialized by amba_init() */ 26struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address */
27struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address, initialized by amba_init() */ 27struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address */
28struct amba_apb_device leon_percpu_timer_dev[16]; 28struct amba_apb_device leon_percpu_timer_dev[16];
29 29
30int leondebug_irq_disable; 30int leondebug_irq_disable;
31int leon_debug_irqout; 31int leon_debug_irqout;
32static int dummy_master_l10_counter; 32static int dummy_master_l10_counter;
33 33
34unsigned long leon3_gptimer_irq; /* interrupt controller irq number, initialized by amba_init() */ 34unsigned long leon3_gptimer_irq; /* interrupt controller irq number */
35unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */
35unsigned int sparc_leon_eirq; 36unsigned int sparc_leon_eirq;
36#define LEON_IMASK ((&leon3_irqctrl_regs->mask[0])) 37#define LEON_IMASK ((&leon3_irqctrl_regs->mask[0]))
37 38
@@ -105,21 +106,79 @@ static void leon_disable_irq(unsigned int irq_nr)
105void __init leon_init_timers(irq_handler_t counter_fn) 106void __init leon_init_timers(irq_handler_t counter_fn)
106{ 107{
107 int irq; 108 int irq;
109 struct device_node *rootnp, *np, *nnp;
110 struct property *pp;
111 int len;
112 int cpu, icsel;
113 int ampopts;
108 114
109 leondebug_irq_disable = 0; 115 leondebug_irq_disable = 0;
110 leon_debug_irqout = 0; 116 leon_debug_irqout = 0;
111 master_l10_counter = (unsigned int *)&dummy_master_l10_counter; 117 master_l10_counter = (unsigned int *)&dummy_master_l10_counter;
112 dummy_master_l10_counter = 0; 118 dummy_master_l10_counter = 0;
113 119
114 if (leon3_gptimer_regs && leon3_irqctrl_regs) { 120 /*Find IRQMP IRQ Controller Registers base address otherwise bail out.*/
115 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0); 121 rootnp = of_find_node_by_path("/ambapp0");
116 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld, 122 if (!rootnp)
117 (((1000000 / HZ) - 1))); 123 goto bad;
118 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 0); 124 np = of_find_node_by_name(rootnp, "GAISLER_IRQMP");
125 if (!np) {
126 np = of_find_node_by_name(rootnp, "01_00d");
127 if (!np)
128 goto bad;
129 }
130 pp = of_find_property(np, "reg", &len);
131 if (!pp)
132 goto bad;
133 leon3_irqctrl_regs = *(struct leon3_irqctrl_regs_map **)pp->value;
134
135 /* Find GPTIMER Timer Registers base address otherwise bail out. */
136 nnp = rootnp;
137 do {
138 np = of_find_node_by_name(nnp, "GAISLER_GPTIMER");
139 if (!np) {
140 np = of_find_node_by_name(nnp, "01_011");
141 if (!np)
142 goto bad;
143 }
144
145 ampopts = 0;
146 pp = of_find_property(np, "ampopts", &len);
147 if (pp) {
148 ampopts = *(int *)pp->value;
149 if (ampopts == 0) {
150 /* Skip this instance, resource already
151 * allocated by other OS */
152 nnp = np;
153 continue;
154 }
155 }
156
157 /* Select Timer-Instance on Timer Core. Default is zero */
158 leon3_gptimer_idx = ampopts & 0x7;
159
160 pp = of_find_property(np, "reg", &len);
161 if (pp)
162 leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)
163 pp->value;
164 pp = of_find_property(np, "interrupts", &len);
165 if (pp)
166 leon3_gptimer_irq = *(unsigned int *)pp->value;
167 } while (0);
168
169 if (leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq) {
170 LEON3_BYPASS_STORE_PA(
171 &leon3_gptimer_regs->e[leon3_gptimer_idx].val, 0);
172 LEON3_BYPASS_STORE_PA(
173 &leon3_gptimer_regs->e[leon3_gptimer_idx].rld,
174 (((1000000 / HZ) - 1)));
175 LEON3_BYPASS_STORE_PA(
176 &leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0);
119 177
120#ifdef CONFIG_SMP 178#ifdef CONFIG_SMP
121 leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs; 179 leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs;
122 leon_percpu_timer_dev[0].irq = leon3_gptimer_irq+1; 180 leon_percpu_timer_dev[0].irq = leon3_gptimer_irq + 1 +
181 leon3_gptimer_idx;
123 182
124 if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) & 183 if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) &
125 (1<<LEON3_GPTIMER_SEPIRQ))) { 184 (1<<LEON3_GPTIMER_SEPIRQ))) {
@@ -127,17 +186,33 @@ void __init leon_init_timers(irq_handler_t counter_fn)
127 BUG(); 186 BUG();
128 } 187 }
129 188
130 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].val, 0); 189 LEON3_BYPASS_STORE_PA(
131 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].rld, (((1000000/HZ) - 1))); 190 &leon3_gptimer_regs->e[leon3_gptimer_idx+1].val, 0);
132 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0); 191 LEON3_BYPASS_STORE_PA(
192 &leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld,
193 (((1000000/HZ) - 1)));
194 LEON3_BYPASS_STORE_PA(
195 &leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, 0);
133# endif 196# endif
134 197
198 /*
199 * The IRQ controller may (if implemented) consist of multiple
200 * IRQ controllers, each mapped on a 4Kb boundary.
201 * Each CPU may be routed to different IRQCTRLs, however
202 * we assume that all CPUs (in SMP system) is routed to the
203 * same IRQ Controller, and for non-SMP only one IRQCTRL is
204 * accessed anyway.
205 * In AMP systems, Linux must run on CPU0 for the time being.
206 */
207 cpu = sparc_leon3_cpuid();
208 icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[cpu/8]);
209 icsel = (icsel >> ((7 - (cpu&0x7)) * 4)) & 0xf;
210 leon3_irqctrl_regs += icsel;
135 } else { 211 } else {
136 printk(KERN_ERR "No Timer/irqctrl found\n"); 212 goto bad;
137 BUG();
138 } 213 }
139 214
140 irq = request_irq(leon3_gptimer_irq, 215 irq = request_irq(leon3_gptimer_irq+leon3_gptimer_idx,
141 counter_fn, 216 counter_fn,
142 (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); 217 (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL);
143 218
@@ -169,13 +244,13 @@ void __init leon_init_timers(irq_handler_t counter_fn)
169# endif 244# endif
170 245
171 if (leon3_gptimer_regs) { 246 if (leon3_gptimer_regs) {
172 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 247 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl,
173 LEON3_GPTIMER_EN | 248 LEON3_GPTIMER_EN |
174 LEON3_GPTIMER_RL | 249 LEON3_GPTIMER_RL |
175 LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); 250 LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN);
176 251
177#ifdef CONFIG_SMP 252#ifdef CONFIG_SMP
178 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 253 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl,
179 LEON3_GPTIMER_EN | 254 LEON3_GPTIMER_EN |
180 LEON3_GPTIMER_RL | 255 LEON3_GPTIMER_RL |
181 LEON3_GPTIMER_LD | 256 LEON3_GPTIMER_LD |
@@ -183,6 +258,11 @@ void __init leon_init_timers(irq_handler_t counter_fn)
183#endif 258#endif
184 259
185 } 260 }
261 return;
262bad:
263 printk(KERN_ERR "No Timer/irqctrl found\n");
264 BUG();
265 return;
186} 266}
187 267
188void leon_clear_clock_irq(void) 268void leon_clear_clock_irq(void)
diff --git a/arch/sparc/kernel/prom_32.c b/arch/sparc/kernel/prom_32.c
index 0a37e8cfd160..05fb25330583 100644
--- a/arch/sparc/kernel/prom_32.c
+++ b/arch/sparc/kernel/prom_32.c
@@ -136,18 +136,29 @@ static void __init ebus_path_component(struct device_node *dp, char *tmp_buf)
136/* "name:vendor:device@irq,addrlo" */ 136/* "name:vendor:device@irq,addrlo" */
137static void __init ambapp_path_component(struct device_node *dp, char *tmp_buf) 137static void __init ambapp_path_component(struct device_node *dp, char *tmp_buf)
138{ 138{
139 struct amba_prom_registers *regs; unsigned int *intr; 139 struct amba_prom_registers *regs;
140 unsigned int *device, *vendor; 140 unsigned int *intr, *device, *vendor, reg0;
141 struct property *prop; 141 struct property *prop;
142 int interrupt = 0;
142 143
144 /* In order to get a unique ID in the device tree (multiple AMBA devices
145 * may have the same name) the node number is printed
146 */
143 prop = of_find_property(dp, "reg", NULL); 147 prop = of_find_property(dp, "reg", NULL);
144 if (!prop) 148 if (!prop) {
145 return; 149 reg0 = (unsigned int)dp->phandle;
146 regs = prop->value; 150 } else {
151 regs = prop->value;
152 reg0 = regs->phys_addr;
153 }
154
155 /* Not all cores have Interrupt */
147 prop = of_find_property(dp, "interrupts", NULL); 156 prop = of_find_property(dp, "interrupts", NULL);
148 if (!prop) 157 if (!prop)
149 return; 158 intr = &interrupt; /* IRQ0 does not exist */
150 intr = prop->value; 159 else
160 intr = prop->value;
161
151 prop = of_find_property(dp, "vendor", NULL); 162 prop = of_find_property(dp, "vendor", NULL);
152 if (!prop) 163 if (!prop)
153 return; 164 return;
@@ -159,7 +170,7 @@ static void __init ambapp_path_component(struct device_node *dp, char *tmp_buf)
159 170
160 sprintf(tmp_buf, "%s:%d:%d@%x,%x", 171 sprintf(tmp_buf, "%s:%d:%d@%x,%x",
161 dp->name, *vendor, *device, 172 dp->name, *vendor, *device,
162 *intr, regs->phys_addr); 173 *intr, reg0);
163} 174}
164 175
165static void __init __build_path_component(struct device_node *dp, char *tmp_buf) 176static void __init __build_path_component(struct device_node *dp, char *tmp_buf)
diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c
index b22ce6100403..648f2161b851 100644
--- a/arch/sparc/kernel/setup_32.c
+++ b/arch/sparc/kernel/setup_32.c
@@ -185,7 +185,6 @@ static void __init boot_flags_init(char *commands)
185 185
186extern void sun4c_probe_vac(void); 186extern void sun4c_probe_vac(void);
187extern char cputypval; 187extern char cputypval;
188extern unsigned long start, end;
189 188
190extern unsigned short root_flags; 189extern unsigned short root_flags;
191extern unsigned short root_dev; 190extern unsigned short root_dev;
@@ -210,7 +209,7 @@ void __init setup_arch(char **cmdline_p)
210 int i; 209 int i;
211 unsigned long highest_paddr; 210 unsigned long highest_paddr;
212 211
213 sparc_ttable = (struct tt_entry *) &start; 212 sparc_ttable = (struct tt_entry *) &trapbase;
214 213
215 /* Initialize PROM console and command line. */ 214 /* Initialize PROM console and command line. */
216 *cmdline_p = prom_getbootargs(); 215 *cmdline_p = prom_getbootargs();