Commit 5439779e84e352f20ee2d3e26daec81292f1b59a

Authored by edgar_igl
1 parent 2ea815ca

ETRAX: Allow boot from flash. Support the watchdog timer and resets through it.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4592 c046a42c-6fe2-441c-8c8c-71466251a162
hw/etraxfs.c
... ... @@ -32,25 +32,29 @@
32 32  
33 33 #include "etraxfs_dma.h"
34 34  
35   -static void main_cpu_reset(void *opaque)
36   -{
37   - CPUState *env = opaque;
38   - cpu_reset(env);
39   -}
40   -
41 35 /* Init functions for different blocks. */
42 36 extern qemu_irq *etraxfs_pic_init(CPUState *env, target_phys_addr_t base);
43 37 void etraxfs_timer_init(CPUState *env, qemu_irq *irqs,
44   - target_phys_addr_t base);
45   -void *etraxfs_eth_init(NICInfo *nd, CPUState *env,
46   - qemu_irq *irq, target_phys_addr_t base);
  38 + target_phys_addr_t base);
  39 +void *etraxfs_eth_init(NICInfo *nd, CPUState *env,
  40 + qemu_irq *irq, target_phys_addr_t base);
47 41 void etraxfs_ser_init(CPUState *env, qemu_irq *irq, CharDriverState *chr,
48   - target_phys_addr_t base);
  42 + target_phys_addr_t base);
49 43  
50 44 #define FLASH_SIZE 0x2000000
51 45 #define INTMEM_SIZE (128 * 1024)
52 46  
53 47 static void *etraxfs_dmac;
  48 +static uint32_t bootstrap_pc;
  49 +
  50 +static void main_cpu_reset(void *opaque)
  51 +{
  52 + CPUState *env = opaque;
  53 + cpu_reset(env);
  54 +
  55 + env->pregs[PR_CCS] &= ~I_FLAG;
  56 + env->pc = bootstrap_pc;
  57 +}
54 58  
55 59 static
56 60 void bareetraxfs_init (ram_addr_t ram_size, int vga_ram_size,
... ... @@ -64,6 +68,7 @@ void bareetraxfs_init (ram_addr_t ram_size, int vga_ram_size,
64 68 int kernel_size;
65 69 int i;
66 70 ram_addr_t phys_ram;
  71 + ram_addr_t phys_flash;
67 72 ram_addr_t phys_intmem;
68 73  
69 74 /* init CPUs */
... ... @@ -83,40 +88,42 @@ void bareetraxfs_init (ram_addr_t ram_size, int vga_ram_size,
83 88 /* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the
84 89 internal memory. Cached and uncached mappings. */
85 90 phys_intmem = qemu_ram_alloc(INTMEM_SIZE);
86   - cpu_register_physical_memory(0xb8000000, INTMEM_SIZE,
87   - phys_intmem | IO_MEM_RAM);
88   - cpu_register_physical_memory(0x38000000, INTMEM_SIZE,
89   - phys_intmem | IO_MEM_RAM);
90   -
91   - cpu_register_physical_memory(0, FLASH_SIZE, IO_MEM_ROM);
92   - cpu_register_physical_memory(0x80000000, FLASH_SIZE, IO_MEM_ROM);
93   - cpu_register_physical_memory(0x04000000, FLASH_SIZE, IO_MEM_ROM);
94   - cpu_register_physical_memory(0x84000000, FLASH_SIZE,
95   - 0x04000000 | IO_MEM_ROM);
96   - i = drive_get_index(IF_PFLASH, 0, 0);
97   - pflash_cfi02_register(0x80000000, qemu_ram_alloc(FLASH_SIZE),
98   - drives_table[i].bdrv, (64 * 1024),
99   - FLASH_SIZE >> 16,
100   - 1, 2, 0x0000, 0x0000, 0x0000, 0x0000, 0x555, 0x2aa);
  91 + cpu_register_physical_memory(0xb8000000, INTMEM_SIZE,
  92 + phys_intmem | IO_MEM_RAM);
  93 + cpu_register_physical_memory(0x38000000, INTMEM_SIZE,
  94 + phys_intmem | IO_MEM_RAM);
  95 +
101 96  
  97 + phys_flash = qemu_ram_alloc(FLASH_SIZE);
  98 + i = drive_get_index(IF_PFLASH, 0, 0);
  99 + pflash_cfi02_register(0x80000000, phys_flash,
  100 + drives_table[i].bdrv, (64 * 1024),
  101 + FLASH_SIZE >> 16,
  102 + 1, 2, 0x0000, 0x0000, 0x0000, 0x0000,
  103 + 0x555, 0x2aa);
  104 + pflash_cfi02_register(0x0, phys_flash,
  105 + drives_table[i].bdrv, (64 * 1024),
  106 + FLASH_SIZE >> 16,
  107 + 1, 2, 0x0000, 0x0000, 0x0000, 0x0000,
  108 + 0x555, 0x2aa);
102 109 pic = etraxfs_pic_init(env, 0xb001c000);
103 110 etraxfs_dmac = etraxfs_dmac_init(env, 0xb0000000, 10);
104 111 for (i = 0; i < 10; i++) {
105   - /* On ETRAX, odd numbered channels are inputs. */
106   - etraxfs_dmac_connect(etraxfs_dmac, i, pic + 7 + i, i & 1);
  112 + /* On ETRAX, odd numbered channels are inputs. */
  113 + etraxfs_dmac_connect(etraxfs_dmac, i, pic + 7 + i, i & 1);
107 114 }
108 115  
109 116 /* Add the two ethernet blocks. */
110 117 eth[0] = etraxfs_eth_init(&nd_table[0], env, pic + 25, 0xb0034000);
111 118 if (nb_nics > 1)
112   - eth[1] = etraxfs_eth_init(&nd_table[1], env, pic + 26, 0xb0036000);
113   -
  119 + eth[1] = etraxfs_eth_init(&nd_table[1], env, pic + 26, 0xb0036000);
  120 +
114 121 /* The DMA Connector block is missing, hardwire things for now. */
115 122 etraxfs_dmac_connect_client(etraxfs_dmac, 0, eth[0]);
116 123 etraxfs_dmac_connect_client(etraxfs_dmac, 1, eth[0] + 1);
117 124 if (eth[1]) {
118   - etraxfs_dmac_connect_client(etraxfs_dmac, 6, eth[1]);
119   - etraxfs_dmac_connect_client(etraxfs_dmac, 7, eth[1] + 1);
  125 + etraxfs_dmac_connect_client(etraxfs_dmac, 6, eth[1]);
  126 + etraxfs_dmac_connect_client(etraxfs_dmac, 7, eth[1] + 1);
120 127 }
121 128  
122 129 /* 2 timers. */
... ... @@ -124,40 +131,31 @@ void bareetraxfs_init (ram_addr_t ram_size, int vga_ram_size,
124 131 etraxfs_timer_init(env, pic + 0x1b, 0xb005e000);
125 132  
126 133 for (i = 0; i < 4; i++) {
127   - if (serial_hds[i]) {
128   - etraxfs_ser_init(env, pic + 0x14 + i,
129   - serial_hds[i], 0xb0026000 + i * 0x2000);
130   - }
  134 + if (serial_hds[i]) {
  135 + etraxfs_ser_init(env, pic + 0x14 + i,
  136 + serial_hds[i], 0xb0026000 + i * 0x2000);
  137 + }
131 138 }
132 139  
  140 + if (kernel_filename) {
133 141 #if 1
134   - /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis devboard
135   - SDK. */
136   - kernel_size = load_elf(kernel_filename, 0, &env->pc, NULL, NULL);
  142 + /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis
  143 + devboard SDK. */
  144 + kernel_size = load_elf(kernel_filename, 0,
  145 + &bootstrap_pc, NULL, NULL);
137 146 #else
138   - /* Takes a kimage from the axis devboard SDK. */
139   - kernel_size = load_image(kernel_filename, phys_ram_base + 0x4000);
140   - env->pc = 0x40004000;
  147 + /* Takes a kimage from the axis devboard SDK. */
  148 + kernel_size = load_image(kernel_filename, phys_ram_base + 0x4000);
  149 + bootstrap_pc = 0x40004000;
  150 + /* magic for boot. */
  151 + env->regs[8] = 0x56902387;
  152 + env->regs[9] = 0x40004000 + kernel_size;
141 153 #endif
142   - /* magic for boot. */
143   - env->regs[8] = 0x56902387;
144   - env->regs[9] = 0x40004000 + kernel_size;
145   -
146   - {
147   - unsigned char *ptr = phys_ram_base + 0x4000;
148   - int i;
149   - for (i = 0; i < 8; i++)
150   - {
151   - printf ("%2.2x ", ptr[i]);
152   - }
153   - printf("\n");
154 154 }
  155 + env->pc = bootstrap_pc;
155 156  
156 157 printf ("pc =%x\n", env->pc);
157 158 printf ("ram size =%ld\n", ram_size);
158   - printf ("kernel name =%s\n", kernel_filename);
159   - printf ("kernel size =%d\n", kernel_size);
160   - printf ("cpu haltd =%d\n", env->halted);
161 159 }
162 160  
163 161 void DMA_run(void)
... ... @@ -169,5 +167,5 @@ QEMUMachine bareetraxfs_machine = {
169 167 "bareetraxfs",
170 168 "Bare ETRAX FS board",
171 169 bareetraxfs_init,
172   - 0x4000000,
  170 + 0x8000000,
173 171 };
... ...
hw/etraxfs_timer.c
... ... @@ -24,6 +24,7 @@
24 24 #include <stdio.h>
25 25 #include <sys/time.h>
26 26 #include "hw.h"
  27 +#include "sysemu.h"
27 28 #include "qemu-timer.h"
28 29  
29 30 #define D(x)
... ... @@ -36,6 +37,7 @@
36 37 #define RW_TMR1_CTRL 0x18
37 38 #define R_TIME 0x38
38 39 #define RW_WD_CTRL 0x40
  40 +#define R_WD_STAT 0x44
39 41 #define RW_INTR_MASK 0x48
40 42 #define RW_ACK_INTR 0x4c
41 43 #define R_INTR 0x50
... ... @@ -46,8 +48,12 @@ struct fs_timer_t {
46 48 qemu_irq *irq;
47 49 target_phys_addr_t base;
48 50  
49   - QEMUBH *bh;
50   - ptimer_state *ptimer;
  51 + QEMUBH *bh_t0;
  52 + QEMUBH *bh_t1;
  53 + QEMUBH *bh_wd;
  54 + ptimer_state *ptimer_t0;
  55 + ptimer_state *ptimer_t1;
  56 + ptimer_state *ptimer_wd;
51 57 struct timeval last;
52 58  
53 59 /* Control registers. */
... ... @@ -59,6 +65,8 @@ struct fs_timer_t {
59 65 uint32_t r_tmr1_data;
60 66 uint32_t rw_tmr1_ctrl;
61 67  
  68 + uint32_t rw_wd_ctrl;
  69 +
62 70 uint32_t rw_intr_mask;
63 71 uint32_t rw_ack_intr;
64 72 uint32_t r_intr;
... ... @@ -114,15 +122,28 @@ timer_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value)
114 122 }
115 123  
116 124 #define TIMER_SLOWDOWN 1
117   -static void update_ctrl(struct fs_timer_t *t)
  125 +static void update_ctrl(struct fs_timer_t *t, int tnum)
118 126 {
119 127 unsigned int op;
120 128 unsigned int freq;
121 129 unsigned int freq_hz;
122 130 unsigned int div;
  131 + uint32_t ctrl;
  132 + ptimer_state *timer;
  133 +
  134 + if (tnum == 0) {
  135 + ctrl = t->rw_tmr0_ctrl;
  136 + div = t->rw_tmr0_div;
  137 + timer = t->ptimer_t0;
  138 + } else {
  139 + ctrl = t->rw_tmr1_ctrl;
  140 + div = t->rw_tmr1_div;
  141 + timer = t->ptimer_t1;
  142 + }
  143 +
123 144  
124   - op = t->rw_tmr0_ctrl & 3;
125   - freq = t->rw_tmr0_ctrl >> 2;
  145 + op = ctrl & 3;
  146 + freq = ctrl >> 2;
126 147 freq_hz = 32000000;
127 148  
128 149 switch (freq)
... ... @@ -134,33 +155,32 @@ static void update_ctrl(struct fs_timer_t *t)
134 155 case 4: freq_hz = 29493000; break;
135 156 case 5: freq_hz = 32000000; break;
136 157 case 6: freq_hz = 32768000; break;
137   - case 7: freq_hz = 100000000; break;
  158 + case 7: freq_hz = 100001000; break;
138 159 default:
139 160 abort();
140 161 break;
141 162 }
142 163  
143   - D(printf ("freq_hz=%d div=%d\n", freq_hz, t->rw_tmr0_div));
144   - div = t->rw_tmr0_div * TIMER_SLOWDOWN;
  164 + D(printf ("freq_hz=%d div=%d\n", freq_hz, div));
  165 + div = div * TIMER_SLOWDOWN;
145 166 div >>= 15;
146 167 freq_hz >>= 15;
147   - ptimer_set_freq(t->ptimer, freq_hz);
148   - ptimer_set_limit(t->ptimer, div, 0);
  168 + ptimer_set_freq(timer, freq_hz);
  169 + ptimer_set_limit(timer, div, 0);
149 170  
150 171 switch (op)
151 172 {
152 173 case 0:
153 174 /* Load. */
154   - ptimer_set_limit(t->ptimer, div, 1);
155   - ptimer_run(t->ptimer, 1);
  175 + ptimer_set_limit(timer, div, 1);
156 176 break;
157 177 case 1:
158 178 /* Hold. */
159   - ptimer_stop(t->ptimer);
  179 + ptimer_stop(timer);
160 180 break;
161 181 case 2:
162 182 /* Run. */
163   - ptimer_run(t->ptimer, 0);
  183 + ptimer_run(timer, 0);
164 184 break;
165 185 default:
166 186 abort();
... ... @@ -180,13 +200,55 @@ static void timer_update_irq(struct fs_timer_t *t)
180 200 qemu_irq_lower(t->irq[0]);
181 201 }
182 202  
183   -static void timer_hit(void *opaque)
  203 +static void timer0_hit(void *opaque)
184 204 {
185 205 struct fs_timer_t *t = opaque;
186 206 t->r_intr |= 1;
187 207 timer_update_irq(t);
188 208 }
189 209  
  210 +static void timer1_hit(void *opaque)
  211 +{
  212 + struct fs_timer_t *t = opaque;
  213 + t->r_intr |= 2;
  214 + timer_update_irq(t);
  215 +}
  216 +
  217 +static void watchdog_hit(void *opaque)
  218 +{
  219 + qemu_system_reset_request();
  220 +}
  221 +
  222 +static inline void timer_watchdog_update(struct fs_timer_t *t, uint32_t value)
  223 +{
  224 + unsigned int wd_en = t->rw_wd_ctrl & (1 << 8);
  225 + unsigned int wd_key = t->rw_wd_ctrl >> 9;
  226 + unsigned int wd_cnt = t->rw_wd_ctrl & 511;
  227 + unsigned int new_key = value >> 9 & ((1 << 7) - 1);
  228 + unsigned int new_cmd = (value >> 8) & 1;
  229 +
  230 + /* If the watchdog is enabled, they written key must match the
  231 + complement of the previous. */
  232 + wd_key = ~wd_key & ((1 << 7) - 1);
  233 +
  234 + if (wd_en && wd_key != new_key)
  235 + return;
  236 +
  237 + D(printf("en=%d new_key=%x oldkey=%x cmd=%d cnt=%d\n",
  238 + wd_en, new_key, wd_key, wd_cmd, wd_cnt));
  239 +
  240 + ptimer_set_freq(t->ptimer_wd, 760);
  241 + if (wd_cnt == 0)
  242 + wd_cnt = 256;
  243 + ptimer_set_count(t->ptimer_wd, wd_cnt);
  244 + if (new_cmd)
  245 + ptimer_run(t->ptimer_wd, 1);
  246 + else
  247 + ptimer_stop(t->ptimer_wd);
  248 +
  249 + t->rw_wd_ctrl = value;
  250 +}
  251 +
190 252 static void
191 253 timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
192 254 {
... ... @@ -203,13 +265,15 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
203 265 case RW_TMR0_CTRL:
204 266 D(printf ("RW_TMR0_CTRL=%x\n", value));
205 267 t->rw_tmr0_ctrl = value;
206   - update_ctrl(t);
  268 + update_ctrl(t, 0);
207 269 break;
208 270 case RW_TMR1_DIV:
209 271 t->rw_tmr1_div = value;
210 272 break;
211 273 case RW_TMR1_CTRL:
212 274 D(printf ("RW_TMR1_CTRL=%x\n", value));
  275 + t->rw_tmr1_ctrl = value;
  276 + update_ctrl(t, 1);
213 277 break;
214 278 case RW_INTR_MASK:
215 279 D(printf ("RW_INTR_MASK=%x\n", value));
... ... @@ -217,7 +281,7 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
217 281 timer_update_irq(t);
218 282 break;
219 283 case RW_WD_CTRL:
220   - D(printf ("RW_WD_CTRL=%x\n", value));
  284 + timer_watchdog_update(t, value);
221 285 break;
222 286 case RW_ACK_INTR:
223 287 t->rw_ack_intr = value;
... ... @@ -232,17 +296,30 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
232 296 }
233 297  
234 298 static CPUReadMemoryFunc *timer_read[] = {
235   - &timer_rinvalid,
236   - &timer_rinvalid,
237   - &timer_readl,
  299 + &timer_rinvalid,
  300 + &timer_rinvalid,
  301 + &timer_readl,
238 302 };
239 303  
240 304 static CPUWriteMemoryFunc *timer_write[] = {
241   - &timer_winvalid,
242   - &timer_winvalid,
243   - &timer_writel,
  305 + &timer_winvalid,
  306 + &timer_winvalid,
  307 + &timer_writel,
244 308 };
245 309  
  310 +static void etraxfs_timer_reset(void *opaque)
  311 +{
  312 + struct fs_timer_t *t = opaque;
  313 +
  314 + ptimer_stop(t->ptimer_t0);
  315 + ptimer_stop(t->ptimer_t1);
  316 + ptimer_stop(t->ptimer_wd);
  317 + t->rw_wd_ctrl = 0;
  318 + t->r_intr = 0;
  319 + t->rw_intr_mask = 0;
  320 + qemu_irq_lower(t->irq[0]);
  321 +}
  322 +
246 323 void etraxfs_timer_init(CPUState *env, qemu_irq *irqs,
247 324 target_phys_addr_t base)
248 325 {
... ... @@ -253,12 +330,18 @@ void etraxfs_timer_init(CPUState *env, qemu_irq *irqs,
253 330 if (!t)
254 331 return;
255 332  
256   - t->bh = qemu_bh_new(timer_hit, t);
257   - t->ptimer = ptimer_init(t->bh);
  333 + t->bh_t0 = qemu_bh_new(timer0_hit, t);
  334 + t->bh_t1 = qemu_bh_new(timer1_hit, t);
  335 + t->bh_wd = qemu_bh_new(watchdog_hit, t);
  336 + t->ptimer_t0 = ptimer_init(t->bh_t0);
  337 + t->ptimer_t1 = ptimer_init(t->bh_t1);
  338 + t->ptimer_wd = ptimer_init(t->bh_wd);
258 339 t->irq = irqs;
259 340 t->env = env;
260 341 t->base = base;
261 342  
262 343 timer_regs = cpu_register_io_memory(0, timer_read, timer_write, t);
263 344 cpu_register_physical_memory (base, 0x5c, timer_regs);
  345 +
  346 + qemu_register_reset(etraxfs_timer_reset, t);
264 347 }
... ...