Update serial API
[qemu/ar7.git] / hw / mips / ar7.c
blob0a7cef5e14cf9cdd883bb46af51e297b715f29d1
1 /*
2 * QEMU AR7 support
4 * Copyright (C) 2006-2011 Stefan Weil
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 /* This code emulates specific parts of Texas Instruments AR7 SoC family.
21 * AR7 contains a MIPS 4KEc core and on-chip peripherals (avalanche).
23 * These members of the AR7 family are partially supported:
24 * - TNETD7100 (not supported)
25 * - TNETD7200 (just started, very incomplete)
26 * - TNETD7300 (best emulation)
27 * Maybe support for Titan can be added, too.
29 * TODO:
30 * - Fix save, load support.
31 * - ldl_phys, stl_phys wrong for big endian AR7
32 * - TNETD7100 emulation is missing
33 * - TNETD7200 emulation is very incomplete
34 * - Support Titan.
35 * - reboot loops endless reading device config latch (AVALANCHE_DCL_BASE)
36 * - uart0, uart1 wrong type (is 16450, should be 16550). Fixed in latest QEMU?
37 * - vlynq emulation only very rudimentary
38 * - Ethernet not stable. Linux kernel problem? Fixed by latest OpenWrt?
39 * - much more
40 * - Sinus 154 DSL Basic SE raises assertion in pflash_cfi01.c
42 * Interrupts:
43 * CPU0
44 * 2: 64 MIPS AR7 on hw0
45 * 7: 1686 MIPS timer
46 * 15: 64 AR7 serial
47 * 16: 0 AR7 serial
48 * 27: 0 AR7 Cpmac Driver
49 * 41: 0 AR7 Cpmac Driver
51 * ERR: 0
55 #include "qemu/osdep.h"
56 #include "cpu.h"
58 #include <zlib.h> /* crc32 */
60 #include "hw/hw.h"
61 #include "hw/boards.h"
62 #include "hw/mips/mips.h"
63 #include "net/net.h"
64 #include "hw/pci/pci.h"
66 #include "chardev/char.h" /* qemu_chr_fe_printf */
67 #include "sysemu/sysemu.h" /* serial_hd */
68 #include "qemu/timer.h" /* QEMU_CLOCK_VIRTUAL */
70 #include "sysemu/block-backend.h" /* blk_getlength */
71 #include "sysemu/blockdev.h" /* drive_get */
72 #include "ui/console.h" /* console_select */
73 #include "disas/disas.h" /* lookup_symbol */
74 #include "elf.h" /* EM_MIPS (needed by loader.h) */
75 #include "exec/address-spaces.h" /* get_system_memory */
76 #include "hw/loader.h" /* load_elf, load_image_targphys */
77 #include "hw/mips/cpudevs.h" /* cpu_mips_kseg0_to_phys, ... */
79 #include "hw/char/serial.h" /* serial_16550_init, ... */
80 #include "hw/block/pflash.h" /* pflash_device_register, ... */
81 #include "hw/sysbus.h" /* SysBusDevice */
82 #include "hw/vlynq.h" /* vlynq_create_bus */
84 #include "qapi/error.h" /* error_abort */
85 #include "target/mips/internal.h" /* mips_cpu_do_interrupt */
87 #if 0 /* Support Titan SoC. */
88 #define CONFIG_TITAN
89 #endif
91 #define MIPS_EXCEPTION_OFFSET 8
92 #define NUM_PRIMARY_IRQS 40
93 #define NUM_SECONDARY_IRQS 32
95 #define AR7_PRIMARY_IRQ(num) ar7->primary_irq[(num) - MIPS_EXCEPTION_OFFSET]
97 /* physical address of flash memory */
98 #define FLASH_ADDR 0x10000000
100 /* physical address of kernel */
101 #define KERNEL_LOAD_ADDR 0x14000000
103 /* physical address of kernel parameters */
104 #define INITRD_LOAD_ADDR 0x14800000
106 /* physical address of 4 KiB internal ROM */
107 #define PROM_ADDR 0x1fc00000
109 #define K1(physaddr) ((physaddr) + 0x80000000)
111 #define MAX_ETH_FRAME_SIZE 1514
113 #define DEBUG_AR7
115 #if defined(DEBUG_AR7)
116 /* Set flags to >0 to enable debug output. */
117 static struct {
118 unsigned CLOCK:1; /* 0x0001 */
119 unsigned CPMAC:1;
120 unsigned DCL:1;
121 unsigned EMIF:1;
122 unsigned GPIO:1; /* 0x0010 */
123 unsigned INTC:1;
124 unsigned MDIO:1;
125 unsigned RESET:1;
126 unsigned TIMER:1; /* 0x0100 */
127 unsigned UART:1;
128 unsigned VLYNQ:1;
129 unsigned WDOG:1;
130 unsigned OTHER:1; /* 0x1000 */
131 unsigned RXTX:1;
132 } traceflags;
134 #define CLOCK traceflags.CLOCK
135 #define DCL traceflags.DCL
136 #define CPMAC traceflags.CPMAC
137 #define EMIF traceflags.EMIF
138 #define GPIO traceflags.GPIO
139 #define INTC traceflags.INTC
140 #define MDIO traceflags.MDIO
141 #define RESET traceflags.RESET
142 #define TIMER traceflags.TIMER
143 #define UART traceflags.UART
144 #define VLYNQ traceflags.VLYNQ
145 #define WDOG traceflags.WDOG
146 #define OTHER traceflags.OTHER
147 #define RXTX traceflags.RXTX
149 #define TRACE(flag, command) ((flag) ? (command) : (void)0)
151 #define logout(fmt, ...) warn_report("AR7\t%-24s" fmt, __func__, ##__VA_ARGS__)
152 //~ #define logout(fmt, ...) warn_report("AR7\t%-24s%-40.40s " fmt, __func__, backtrace(), ##__VA_ARGS__)
154 #else /* DEBUG_AR7 */
156 #define TRACE(flag, command) ((void)0)
157 #define logout(fmt, ...) ((void)0)
159 #endif /* DEBUG_AR7 */
161 #define MISSING() logout("%s:%u missing, %s!!!", __FILE__, __LINE__, backtrace())
162 #define UNEXPECTED() logout("%s:%u unexpected, %s!!!", __FILE__, __LINE__, backtrace())
163 #define backtrace() mips_backtrace()
165 #if !defined(BIT)
166 #define BIT(n) (1 << (n))
167 #endif
168 #define BITS(n, m) (((UINT32_MAX << (31 - n)) >> (31 - n + m)) << m)
169 //~ #define MASK(hi, lo) (((~(~0 << (hi))) & (~0 << (lo))) | (1 << (hi)))
171 static struct _loaderparams {
172 ram_addr_t ram_size;
173 uint64_t kernel_addr;
174 const char *kernel_filename;
175 const char *kernel_cmdline;
176 const char *initrd_filename;
177 } loaderparams;
179 #if 0
180 #define BBIF_SPACE1 (KSEG1ADDR(0x01800000))
181 #endif
183 /* Chip variants. */
185 #define AR7_CHIP_7100 0x18
186 #define AR7_CHIP_7200 0x2b
187 #define AR7_CHIP_7300 0x05
188 #define AR7_CHIP_TITAN 0x07
190 #define TITAN_CHIP_1050 0x0f
191 #define TITAN_CHIP_1055 0x0e
192 #define TITAN_CHIP_1056 0x0d
193 #define TITAN_CHIP_1060 0x07
195 #if defined(CONFIG_TITAN)
196 #define AR7_CHIP_DEFAULT 0 /* TODO: check value */
197 #define TITAN_CHIP_DEFAULT TITAN_CHIP_1060
198 #else
199 #define AR7_CHIP_DEFAULT AR7_CHIP_7300
200 #define TITAN_CHIP_DEFAULT 0xffffffff
201 #endif /* CONFIG_TITAN */
203 #if 0
204 #define OHIO_ADSLSS_BASE0 KERNEL_ADDR(0x01000000)
205 #define OHIO_ADSLSS_BASE1 KERNEL_ADDR(0x01800000)
206 #define OHIO_ADSLSS_BASE2 KERNEL_ADDR(0x01C00000)
207 #endif
210 Physical memory map
211 0x00000000 RAM start
212 0x00000fff RAM end
213 0x08610000 I/O start
214 0x08613000 I/O end
215 0x10000000 Flash start
216 0x101fffff Flash end (2 MiB)
217 0x103fffff Flash end (4 MiB)
218 0x107fffff Flash end (8 MiB)
219 0x14000000 RAM start
220 0x14ffffff RAM end (16 MiB)
221 0x15ffffff RAM end (32 MiB)
222 0x1e000000 ???
223 0x1fc00000 internal ROM start
224 0x1fc00fff internal ROM end
227 #define AVALANCHE_ADSLSSYS_MEM_BASE 0x01000000 /* ADSL subsystem mem base */
228 #define AVALANCHE_BBIF_BASE 0x02000000 /* broadband interface */
229 #define AVALANCHE_ATM_SAR_BASE 0x03000000 /* ATM SAR */
230 #define AVALANCHE_USB_MEM_BASE 0x03400000 /* USB slave mem map */
231 #define AVALANCHE_VLYNQ0_REGION0_BASE 0x04000000 /* VLYNQ 0 memory mapped region 0 */
232 #define AVALANCHE_VLYNQ0_REGION1_BASE 0x04022000 /* VLYNQ 0 memory mapped region 1 */
233 #define AVALANCHE_VLYNQ1_REGION0_BASE 0x0c000000 /* VLYNQ 1 memory mapped region 0 */
234 #define AVALANCHE_VLYNQ1_REGION1_BASE 0x0c022000 /* VLYNQ 1 memory mapped region 1 */
235 #define AVALANCHE_DES_BASE 0x08600000 /* ??? */
236 #define AVALANCHE_CPMAC0_BASE 0x08610000
237 #define AVALANCHE_EMIF_BASE 0x08610800
238 #define AVALANCHE_GPIO_BASE 0x08610900
239 #define AVALANCHE_CLOCK_BASE 0x08610a00 /* Clock Control */
240 //~ #define AVALANCHE_POWER_CTRL_PDCR (KSEG1ADDR(0x08610A00))
241 #define AVALANCHE_WAKEUP_CTRL_WKCR (KSEG1ADDR(0x08610A0C))
242 #define AVALANCHE_WATCHDOG_BASE 0x08610b00 /* Watchdog */
243 #define AVALANCHE_TIMER0_BASE 0x08610c00 /* Timer 1 */
244 #define AVALANCHE_TIMER1_BASE 0x08610d00 /* Timer 2 */
245 #define AVALANCHE_UART0_BASE 0x08610e00 /* UART 0 */
246 #define AVALANCHE_UART1_BASE 0x08610f00 /* UART 1 */
247 #define OHIO_I2C_BASE 0x08610f00
248 #define AVALANCHE_I2C_BASE 0x08611000 /* I2C */
249 #define DEV_ID_BASE 0x08611100
250 #define AVALANCHE_USB_SLAVE_BASE 0x08611200 /* USB DMA */
251 #define PCI_CONFIG_BASE 0x08611300
252 #define AVALANCHE_MCDMA_BASE 0x08611400 /* MC DMA channels 0-3 */
253 #define TNETD73xx_VDMAVT_BASE 0x08611500 /* VDMAVT Control */
254 #define AVALANCHE_RESET_BASE 0x08611600
255 #define AVALANCHE_BIST_CONTROL_BASE 0x08611700 /* BIST Control */
256 #define AVALANCHE_VLYNQ0_BASE 0x08611800 /* VLYNQ0 port controller */
257 #define AVALANCHE_DCL_BASE 0x08611a00 /* Device Config Latch */
258 #define OHIO_MII_SEL_REG 0x08611a08
259 #define DSL_IF_BASE 0x08611b00
260 #define AVALANCHE_VLYNQ1_BASE 0x08611c00 /* VLYNQ1 port controller */
261 #define AVALANCHE_MDIO_BASE 0x08611e00
262 #define OHIO_WDT_BASE 0x08611f00
263 #define AVALANCHE_FSER_BASE 0x08612000 /* FSER base */
264 #define AVALANCHE_INTC_BASE 0x08612400
265 #define AVALANCHE_CPMAC1_BASE 0x08612800
266 #define AVALANCHE_END 0x08613000
267 #define AVALANCHE_PHY_BASE 0x1e000000 /* ??? */
268 #define AVALANCHE_PHY1_BASE 0x1e100000 /* ??? */
269 #define AVALANCHE_PHY2_BASE 0x1e200000 /* ??? */
270 #define AVALANCHE_DISPLAY_BASE 0x1f000000 /* ??? */
272 #define TYPE_AR7_STATE "ar7"
273 #define TYPE_CPMAC_STATE "ar7-cpmac"
275 #define AR7_STATE(obj) \
276 OBJECT_CHECK(AR7State, (obj), TYPE_AR7_STATE)
277 #define CPMAC_STATE(obj) \
278 OBJECT_CHECK(CpmacState, (obj), TYPE_CPMAC_STATE)
280 typedef struct {
281 uint32_t next;
282 uint32_t buff;
283 uint32_t length;
284 uint32_t mode;
285 } cpphy_rcb_t;
287 typedef enum {
288 RCB_SOP = BIT(31),
289 RCB_EOP = BIT(30),
290 RCB_OWNER = BIT(29),
291 RCB_EOQ = BIT(28),
292 RCB_TDOWNCMPLT = BIT(27),
293 RCB_PASSCRC = BIT(26),
294 RCB_JABBER = BIT(25),
295 RCB_OVERSIZE = BIT(24),
296 RCB_FRAGMENT = BIT(23),
297 RCB_UNDERSIZED = BIT(22),
298 RCB_CONTROL = BIT(21),
299 RCB_OVERRUN = BIT(20),
300 RCB_CODEERROR = BIT(19),
301 RCB_ALIGNERROR = BIT(18),
302 RCB_CRCERROR = BIT(17),
303 RCB_NOMATCH = BIT(16),
304 } rcb_bit_t;
306 typedef struct {
307 uint32_t next;
308 uint32_t buff;
309 uint32_t length;
310 uint32_t mode;
311 } cpphy_tcb_t;
313 typedef enum {
314 TCB_SOP = BIT(31),
315 TCB_EOP = BIT(30),
316 TCB_OWNER = BIT(29),
317 TCB_EOQ = BIT(28),
318 TCB_TDOWNCMPLT = BIT(27),
319 TCB_PASSCRC = BIT(26),
320 } tcb_bit_t;
322 typedef struct {
323 uint8_t *base; /* base address */
324 qemu_irq interrupt; /* interrupt number */
325 int cyclic; /* 1 = cyclic timer */
326 int64_t time; /* preload value */
327 uint16_t prescale; /* prescale divisor */
328 QEMUTimer *qemu_timer;
329 } ar7_timer_t;
331 /* Hardware registers of the AR7. Some data is not kept here,
332 but in other devices (for example both serial devices). */
333 typedef struct {
334 uint32_t adsl[0x8000]; // 0x01000000
335 uint32_t bbif[3]; // 0x02000000
336 uint32_t atmsar[0x2400]; // 0x03000000
337 uint32_t usbslave[0x800]; // 0x03400000
338 /* VLYNQ0 memory regions are emulated in tnetw1130.c. */
339 //~ uint32_t vlynq0region0[8 * KiB / 4]; // 0x04000000
340 //~ uint32_t vlynq0region1[128 * KiB / 4]; // 0x04022000
341 uint32_t vlynq1region0[8 * KiB / 4]; // 0x0c000000
342 uint32_t vlynq1region1[128 * KiB / 4]; // 0x0c022000
344 uint8_t cpmac0[0x800]; // 0x08610000
345 uint8_t emif[0x100]; // 0x08610800
346 uint8_t gpio[40]; /* 0x08610900 */
347 //~ uint8_t gpio_dummy[4 * 0x38];
348 uint8_t clock_control[0x100]; // 0x08610a00
349 // 0x08610a80 struct _ohio_clock_pll
350 //~ uint32_t clock_dummy[0x18];
351 uint32_t watchdog[0x20]; // 0x08610b00 struct _ohio_clock_pll
352 uint8_t timer0[16]; // 0x08610c00
353 uint8_t timer1[16]; // 0x08610d00
354 /* TODO: UART0, UART1 memory is emulated in serial_16450.c, remove here. */
355 uint32_t uart0[8]; // 0x08610e00
356 uint32_t uart1[8]; // 0x08610f00
357 uint32_t usb[20]; // 0x08611200
358 uint32_t mc_dma[0x10][4]; // 0x08611400
359 uint32_t reset_control[3]; // 0x08611600
360 uint32_t reset_dummy[0x80 - 3];
361 uint8_t vlynq0[0x100]; // 0x08611800
362 // + 0xe0 interrupt enable bits
363 uint8_t dcl[20]; // 0x08611a00
364 uint8_t vlynq1[0x100]; // 0x08611c00
365 uint8_t mdio[0x90]; // 0x08611e00
366 uint32_t wdt[8]; // 0x08611f00
367 uint8_t intc[0x300]; // 0x08612400
368 //~ uint32_t exception_control[7]; // +0x80
369 //~ uint32_t pacing[3]; // +0xa0
370 //~ uint32_t channel_control[40]; // +0x200
371 uint8_t cpmac1[0x800]; // 0x08612800
372 //~ uint32_t unknown[0x40] // 0x08613000
373 } ar7_register_t;
375 typedef struct {
376 SysBusDevice busdev;
378 unsigned index;
379 qemu_irq irq;
381 uint8_t *addr;
382 NICState *nic;
383 NICConf conf;
384 } CpmacState;
386 /* Emulation registers of the AR7. */
387 typedef struct {
388 SysBusDevice busdev;
389 MemoryRegion mmio;
390 MemoryRegion ram;
391 MemoryRegion internal_ram;
392 MemoryRegion rom;
393 QEMUTimer *wd_timer;
394 qemu_irq *primary_irq;
395 qemu_irq *secondary_irq;
396 /* Address of phy device (0...31). Only one phy device is supported.
397 The internal phy has address 31. */
398 uint8_t phyaddr;
399 /* VLYNQ index for TNETW1130. Set to >1 to disable WLAN. */
400 uint8_t vlynq_tnetw1130;
401 CharBackend gpio_display;
402 bool gpio_display_inited;
403 SerialState *serial[2];
404 CpmacState *cpmac[2];
405 ar7_timer_t timer[2];
406 uint8_t *vlynq[2];
407 } AR7State;
409 static ar7_register_t av;
410 static AR7State *ar7;
412 int ar7_afe_clock = 35328000;
413 int ar7_ref_clock = 25000000;
414 int ar7_xtal_clock = 24000000;
416 #if 0
417 static const unsigned ar7_cpu_clock = 150000000;
418 static const unsigned ar7_bus_clock = 125000000;
419 static const unsigned ar7_dsp_clock = 0;
420 #endif
421 static const unsigned io_frequency = 125000000 / 2;
423 /* Global variable avalanche can be used in debugger. */
424 //~ ar7_register_t *avalanche = &av;
426 static const char *mips_backtrace(void)
428 static char buffer[256];
429 char *p = buffer;
430 if (first_cpu != 0) {
431 CPUArchState *env = first_cpu->env_ptr;
432 p += sprintf(p, "[%s]", lookup_symbol(env->active_tc.PC));
433 p += sprintf(p, "[%s]", lookup_symbol(env->active_tc.gpr[31]));
434 } else {
435 /* Called from remote gdb. */
436 p += sprintf(p, "[gdb?]");
438 assert((p - buffer) < sizeof(buffer));
439 return buffer;
442 static const char *dump(const uint8_t * buf, unsigned size)
444 static char buffer[3 * 25 + 1];
445 char *p = &buffer[0];
446 if (size > 25)
447 size = 25;
448 while (size-- > 0) {
449 p += sprintf(p, " %02x", *buf++);
451 return buffer;
454 /*****************************************************************************
456 * Helper functions.
458 ****************************************************************************/
460 typedef struct {
461 unsigned offset;
462 const char *name;
463 } offset_name_t;
465 static const char *offset2name(const offset_name_t *o2n, unsigned offset)
467 static char buffer[12];
468 const char *name = buffer;
469 snprintf(buffer, sizeof(buffer), "0x%08x", offset);
470 for (; o2n->name != 0; o2n++) {
471 if (offset == o2n->offset) {
472 name = o2n->name;
473 break;
476 return name;
479 #if defined(DEBUG_AR7)
481 #define SET_TRACEFLAG(name) \
482 do { \
483 char *substring = strstr(env, #name); \
484 if (substring) { \
485 name = ((substring > env && substring[-1] == '-') ? 0 : 1); \
487 TRACE(name, logout("Logging enabled for " #name)); \
488 } while(0)
490 static void set_traceflags(void)
492 const char *env = getenv("DEBUG_AR7");
493 if (env != 0) {
494 unsigned long ul = strtoul(env, 0, 0);
495 if ((ul == 0) && strstr(env, "ALL")) ul = 0xffffffff;
496 memcpy(&traceflags, &ul, sizeof(traceflags));
497 SET_TRACEFLAG(CLOCK);
498 SET_TRACEFLAG(CPMAC);
499 SET_TRACEFLAG(DCL);
500 SET_TRACEFLAG(EMIF);
501 SET_TRACEFLAG(GPIO);
502 SET_TRACEFLAG(INTC);
503 SET_TRACEFLAG(MDIO);
504 SET_TRACEFLAG(RESET);
505 SET_TRACEFLAG(TIMER);
506 SET_TRACEFLAG(UART);
507 SET_TRACEFLAG(VLYNQ);
508 SET_TRACEFLAG(WDOG);
509 SET_TRACEFLAG(OTHER);
510 SET_TRACEFLAG(RXTX);
513 #endif /* DEBUG_AR7 */
515 static uint32_t reg_read(const uint8_t * reg, uint32_t addr)
517 if (addr & 3) {
518 logout("0x%08x", addr);
519 UNEXPECTED();
521 return le32_to_cpu(*(uint32_t *) (&reg[addr]));
524 static void reg_write(uint8_t * reg, uint32_t addr, uint32_t value)
526 assert(!(addr & 3));
527 *(uint32_t *) (&reg[addr]) = cpu_to_le32(value);
530 #if 0
531 static void reg_inc(uint8_t * reg, uint32_t addr)
533 assert(!(addr & 3));
534 reg_write(reg, addr, reg_read(reg, addr) + 1);
536 #endif
538 static void reg_clear(uint8_t * reg, uint32_t addr, uint32_t value)
540 assert(!(addr & 3));
541 *(uint32_t *) (&reg[addr]) &= cpu_to_le32(~value);
544 static void reg_set(uint8_t * reg, uint32_t addr, uint32_t value)
546 assert(!(addr & 3));
547 *(uint32_t *) (&reg[addr]) |= cpu_to_le32(value);
550 /*****************************************************************************
552 * Malta display emulation.
553 * AR7 based routers don't include an ASCII display, but AVM code
554 * thinks there is a Malta like display. So we emulate it here.
556 ****************************************************************************/
558 typedef struct {
559 uint32_t leds;
560 CharBackend display;
561 bool display_inited;
562 char display_text[9];
563 } MaltaFPGAState;
565 static MaltaFPGAState malta_display;
567 /* Malta FPGA */
568 static void malta_fpga_update_display(void *opaque)
570 char leds_text[9];
571 int i;
572 MaltaFPGAState *s = opaque;
574 for (i = 7 ; i >= 0 ; i--) {
575 if (s->leds & (1 << i))
576 leds_text[i] = '#';
577 else
578 leds_text[i] = ' ';
580 leds_text[8] = '\0';
582 qemu_chr_fe_printf(&s->display, "\e[3;2H\e[0;32m%-8.8s", leds_text);
583 qemu_chr_fe_printf(&s->display, "\e[8;2H\e[0;31m%-8.8s\r\n\n\e[0;37m", s->display_text);
586 /*****************************************************************************
588 * Interrupt emulation.
589 * Interrupt controller emulation.
591 ****************************************************************************/
593 typedef enum {
594 /* primary interrupts 8 ... 47 */
595 INTERRUPT_EXT0 = 9, /* ext0 ??? */
596 INTERRUPT_EXT1 = 10, /* ext1 ??? */
597 INTERRUPT_TIMER0 = 13, /* timer0 ??? */
598 INTERRUPT_TIMER1 = 14, /* timer1 ??? */
599 INTERRUPT_SERIAL0 = 15,
600 INTERRUPT_SERIAL1 = 16,
601 INTERRUPT_DMA0 = 17, /* ??? */
602 INTERRUPT_DMA1 = 18, /* ??? */
603 INTERRUPT_ATMSAR = 23, /* ??? */
604 INTERRUPT_CPMAC0 = 27,
605 INTERRUPT_VLYNQ0 = 29, /* ??? */
606 INTERRUPT_CODEC = 30, /* ??? */
607 INTERRUPT_USBSLAVE = 32, /* ??? */
608 INTERRUPT_VLYNQ1 = 33, /* ??? */
609 INTERRUPT_PHY = 36, /* ??? */
610 INTERRUPT_I2C = 37, /* ??? */
611 INTERRUPT_DMA2 = 38, /* ??? */
612 INTERRUPT_DMA3 = 39, /* ??? */
613 INTERRUPT_CPMAC1 = 41,
614 INTERRUPT_VDMA_RX = 45, /* ??? */
615 INTERRUPT_VDMA_TX = 46, /* ??? */
616 INTERRUPT_ADSLSS = 47, /* ??? */
617 /* secondary interrupts 40 ... 71 */
618 INTERRUPT_EMIF = 55, /* emif ??? */
619 } ar7_interrupt;
621 typedef enum {
622 INTC_SR1 = 0x00, /* Interrupt Status/Set 1 */
623 INTC_SR2 = 0x04, /* Interrupt Status/Set 2 */
624 INTC_CR1 = 0x10, /* Interrupt Clear 1 */
625 INTC_CR2 = 0x14, /* Interrupt Clear 2 */
626 INTC_ESR1 = 0x20, /* Interrupt Enable (Set) 1 */
627 INTC_ESR2 = 0x24, /* Interrupt Enable (Set) 2 */
628 INTC_ECR1 = 0x30, /* Interrupt Enable Clear 1 */
629 INTC_ECR2 = 0x34, /* Interrupt Enable Clear 2 */
630 INTC_PIIR = 0x40, /* Priority Interrupt Index */
631 INTC_PIMR = 0x44, /* Priority Interrupt Mask Index */
632 INTC_IPMR1 = 0x50, /* Interrupt Polarity Mask 1 */
633 INTC_IPMR2 = 0x54, /* Interrupt Polarity Mask 2 */
634 INTC_TMR1 = 0x60, /* Interrupt Type Mask 1 */
635 INTC_TMR2 = 0x64, /* Interrupt Type Mask 2 */
636 /* Avalanche Exception control registers */
637 INTC_EXSR = 0x80, /* Exceptions Status/Set */
638 INTC_EXCR = 0x88, /* Exceptions Clear */
639 INTC_EXIESR = 0x90, /* Exceptions Interrupt Enable Status/Set */
640 INTC_EXIECR = 0x98, /* Exceptions Interrupt Enable Clear */
641 /* Interrupt Pacing */
642 INTC_IPACEP = 0xa0, /* Interrupt pacing */
643 INTC_IPACEMAP = 0xa4,
644 /* Interrupt Pacing Map */
645 INTC_IPACEMAX = 0xa8,
646 /* Interrupt Pacing Max Register */
647 /* Interrupt Channel Control */
648 INTC_CINTNR = 0x200, /* 40 entries */
649 /* Channel Interrupt Number Reg */
650 } intc_register_t;
652 static void ar7_update_interrupt(void)
654 static int intset;
656 CPUMIPSState *env = first_cpu->env_ptr;
657 uint32_t masked_int1;
658 uint32_t masked_int2;
660 masked_int1 = (reg_read(av.intc, INTC_ESR1) & reg_read(av.intc, INTC_SR1));
661 masked_int2 = (reg_read(av.intc, INTC_ESR2) & reg_read(av.intc, INTC_SR2));
662 if (masked_int1 || masked_int2) {
663 if (!intset) {
664 intset = 1;
665 //~ reg_set(av.intc, INTC_EXSR, BIT(2));
666 //~ reg_set(av.intc, INTC_EXCR, BIT(2));
667 qemu_irq_raise(env->irq[2]);
668 //~ /* use hardware interrupt 0 */
669 //~ env->CP0_Cause |= 0x00000400;
670 //~ cpu_interrupt(env, CPU_INTERRUPT_HARD);
671 TRACE(INTC, logout("raise hardware interrupt, mask 0x%08x%08x",
672 masked_int2, masked_int1));
673 } else {
674 int channel;
675 TRACE(INTC, logout("interrupt still set"));
676 for (channel = 0; channel < 40; channel++) {
677 unsigned cindex = channel / 32;
678 unsigned offset = channel % 32;
679 uint32_t cr = reg_read(av.intc, INTC_CR1 + 4 * cindex);
680 if (cr & BIT(offset)) {
681 reg_write(av.intc, INTC_PIIR, (channel << 16) | channel);
682 break;
685 if (channel == 40) {
686 reg_write(av.intc, INTC_PIIR, 0);
689 } else {
690 if (intset) {
691 intset = 0;
692 qemu_irq_lower(env->irq[2]);
693 //~ env->CP0_Cause &= ~0x00000400;
694 //~ cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
695 TRACE(INTC, logout("clear hardware interrupt"));
696 } else {
697 TRACE(INTC, logout("interrupt still cleared"));
702 static void ar7_primary_irq(void *opaque, int channel, int level)
704 /* AR7 primary interrupt. */
705 CPUMIPSState *env = opaque;
706 unsigned irq_num = channel + MIPS_EXCEPTION_OFFSET;
707 unsigned cindex = channel / 32;
708 unsigned offset = channel % 32;
709 TRACE(INTC && (irq_num != INTERRUPT_SERIAL0 || UART),
710 logout("(%p,%d,%d)", opaque, irq_num, level));
711 if (level) {
712 assert(env == first_cpu->env_ptr);
713 uint32_t intmask = reg_read(av.intc, INTC_ESR1 + 4 * cindex);
714 if (intmask & BIT(offset)) {
715 TRACE(INTC && (irq_num != 15 || UART),
716 logout("(%p,%d,%d)", opaque, irq_num, level));
717 reg_write(av.intc, INTC_PIIR, (channel << 16) | channel);
718 /* use hardware interrupt 0 */
719 qemu_irq_raise(env->irq[2]);
720 //~ env->CP0_Cause |= 0x00000400;
721 //~ cpu_interrupt(env, CPU_INTERRUPT_HARD);
722 } else {
723 TRACE(INTC && (irq_num != 15 || UART),
724 logout("(%p,%d,%d) is disabled", opaque, irq_num, level));
726 reg_set(av.intc, INTC_SR1 + 4 * cindex, BIT(offset));
727 reg_set(av.intc, INTC_CR1 + 4 * cindex, BIT(offset));
728 /* TODO: write correct value to INTC_PIIR? */
729 //~ reg_write(av.intc, INTC_PIIR, (channel << 16) | channel);
730 } else {
731 /* TODO: write correct value to INTC_PIIR? */
732 reg_clear(av.intc, INTC_SR1 + 4 * cindex, BIT(offset));
734 ar7_update_interrupt();
737 static void ar7_secondary_irq(void *opaque, int channel, int level)
739 /* AR7 secondary interrupt. */
740 unsigned irq_num = channel + MIPS_EXCEPTION_OFFSET + NUM_PRIMARY_IRQS;
741 TRACE(INTC, logout("(%p,%d,%d)", opaque, irq_num, level));
742 reg_set(av.intc, INTC_EXSR, BIT(channel));
743 reg_set(av.intc, INTC_EXCR, BIT(channel));
744 MISSING();
745 ar7_update_interrupt();
748 static const char *const intc_names[] = {
749 "Interrupt Status/Set 1",
750 "Interrupt Status/Set 2",
751 "0x08",
752 "0x0c",
753 "Interrupt Clear 1",
754 "Interrupt Clear 2",
755 "0x18",
756 "0x1c",
757 "Interrupt Enable Set 1",
758 "Interrupt Enable Set 2",
759 "0x28",
760 "0x2c",
761 "Interrupt Enable Clear 1",
762 "Interrupt Enable Clear 2",
763 "0x38",
764 "0x3c",
765 "Priority Interrupt Index",
766 "Priority Interrupt Mask Index",
767 "0x48",
768 "0x4c",
769 "Interrupt Polarity Mask 1",
770 "Interrupt Polarity Mask 2",
771 "0x58",
772 "0x5c",
773 "Interrupt Type Mask 1",
774 "Interrupt Type Mask 2",
775 "0x68",
776 "0x6c",
777 "0x70",
778 "0x74",
779 "0x78",
780 "0x7c",
781 "Exceptions Status/Set",
782 "0x84",
783 "Exceptions Clear",
784 "0x8c",
785 "Exceptions Interrupt Enable (set)",
786 "0x94",
787 "Exceptions Interrupt Enable (clear)",
788 "0x9c",
789 "Interrupt Pacing",
790 "Interrupt Pacing Map",
791 "Interrupt Pacing Max",
794 static const char *i2intc(unsigned name_index)
796 static char buffer[32];
797 const char *text = buffer;
798 if (name_index < ARRAY_SIZE(intc_names)) {
799 text = intc_names[name_index];
800 } else if (name_index >= 128 && name_index < 168) {
801 snprintf(buffer, sizeof(buffer),
802 "Channel Interrupt Number 0x%02x", name_index - 128);
803 } else {
804 snprintf(buffer, sizeof(buffer), "0x%02x", name_index);
806 return text;
809 static uint32_t ar7_intc_read(unsigned offset)
811 unsigned name_index = offset / 4;
812 uint32_t val = reg_read(av.intc, offset);
813 if (0) {
814 } else if (offset == INTC_ECR1 || offset == INTC_ECR2) {
815 TRACE(INTC, logout("intc[%s] = 0x%08x", i2intc(name_index), val));
816 MISSING();
817 } else {
818 TRACE(INTC, logout("intc[%s] = 0x%08x", i2intc(name_index), val));
820 return val;
823 static void ar7_intc_write(unsigned offset, uint32_t val)
825 unsigned name_index = offset / 4;
826 if (0) {
827 //~ } else if (name_index == 4) {
828 } else if (offset == INTC_SR1 || offset == INTC_SR2) {
829 /* Interrupt set. */
830 TRACE(INTC, logout("intc[%s] val 0x%08x", i2intc(name_index), val));
831 reg_set(av.intc, offset, val);
832 MISSING();
833 ar7_update_interrupt();
834 } else if (offset == INTC_CR1 || offset == INTC_CR2) {
835 /* Interrupt clear. */
836 TRACE(INTC, logout("intc[%s] val 0x%08x", i2intc(name_index), val));
837 offset -= INTC_CR1;
838 reg_clear(av.intc, INTC_SR1 + offset, val);
839 reg_clear(av.intc, INTC_CR1 + offset, val);
840 /* TODO: check old value? */
841 //~ reg_write(av.intc, INTC_PIIR, 0);
842 //~ logout("??? clear interrupt\a");
843 ar7_update_interrupt();
844 } else if (offset == INTC_ESR1 || offset == INTC_ESR2) {
845 /* Interrupt enable. */
846 reg_set(av.intc, offset, val);
847 TRACE(INTC, logout("intc[%s] val 0x%08x, mask 0x%08x",
848 i2intc(name_index), val, reg_read(av.intc, offset)));
849 //~ logout("??? check interrupt\a");
850 ar7_update_interrupt();
851 } else if (offset == INTC_ECR1 || offset == INTC_ECR2) {
852 offset += INTC_ESR1 - INTC_ECR1;
853 reg_clear(av.intc, offset, val);
854 TRACE(INTC, logout("intc[%s] val 0x%08x, mask 0x%08x",
855 i2intc(name_index), val, reg_read(av.intc, offset)));
856 //~ logout("??? check interrupt\a");
857 ar7_update_interrupt();
858 } else if (offset == INTC_EXSR) {
859 /* Exceptions Status/Set. */
860 TRACE(INTC, logout("intc[%s] val 0x%08x", i2intc(name_index), val));
861 reg_set(av.intc, INTC_EXSR, val);
862 MISSING();
863 } else if (offset == INTC_EXCR) {
864 /* Exceptions Clear. */
865 TRACE(INTC, logout("intc[%s] val 0x%08x", i2intc(name_index), val));
866 reg_clear(av.intc, INTC_EXSR, val);
867 ar7_update_interrupt();
868 } else if (offset == INTC_EXIESR) {
869 /* Exceptions Interrupt Enable Status/Set. */
870 TRACE(INTC, logout("intc[%s] val 0x%08x", i2intc(name_index), val));
871 reg_set(av.intc, INTC_EXIESR, val);
872 ar7_update_interrupt();
873 } else if (offset == INTC_EXIECR) {
874 /* Exceptions Interrupt Enable Clear. */
875 TRACE(INTC, logout("intc[%s] val 0x%08x", i2intc(name_index), val));
876 reg_clear(av.intc, INTC_EXIESR, val);
877 ar7_update_interrupt();
878 } else {
879 TRACE(INTC, logout("intc[%s] val 0x%08x", i2intc(name_index), val));
880 reg_write(av.intc, offset, val);
884 /*****************************************************************************
886 * Clock / power controller emulation.
888 ****************************************************************************/
890 #if 0
891 /* Power Control */
892 #define TNETD73XX_POWER_CTRL_PDCR (TNETD73XX_CLOCK_CTRL_BASE + 0x0)
893 #define TNETD73XX_POWER_CTRL_PCLKCR (TNETD73XX_CLOCK_CTRL_BASE + 0x4)
894 #define TNETD73XX_POWER_CTRL_PDUCR (TNETD73XX_CLOCK_CTRL_BASE + 0x8)
895 #define TNETD73XX_POWER_CTRL_WKCR (TNETD73XX_CLOCK_CTRL_BASE + 0xC)
897 /* Clock Control */
898 #define TNETD73XX_CLK_CTRL_ACLKCR1 (TNETD73XX_CLOCK_CTRL_BASE + 0xA0)
899 #define TNETD73XX_CLK_CTRL_ACLKPLLCR1 (TNETD73XX_CLOCK_CTRL_BASE + 0xB0)
901 #define CLKC_CLKCR(x) (TNETD73XX_CLOCK_CTRL_BASE + 0x20 + (0x20 * (x)))
902 #define CLKC_CLKPLLCR(x) (TNETD73XX_CLOCK_CTRL_BASE + 0x30 + (0x20 * (x)))
904 static void ar7_machine_power_off(void)
906 volatile uint32_t *power_reg = (void *)(KSEG1ADDR(0x08610A00));
907 uint32_t power_state = *power_reg;
909 power_state &= ~(3 << 30);
910 power_state |= (3 << 30); /* power down */
911 *power_reg = power_state;
913 printk("after power down?\n");
915 #endif
917 typedef enum {
918 CLOCK_PDC = 0x00,
919 CLOCK_BUS_CTL = 0x20,
920 CLOCK_BUS_PLL = 0x30,
921 CLOCK_CPU_CTL = 0x40,
922 CLOCK_CPU_PLL = 0x50,
923 CLOCK_USB_CTL = 0x60,
924 CLOCK_USB_PLL = 0x70,
925 CLOCK_DSP_CTL = 0x80,
926 CLOCK_DSP_PLL = 0x90,
927 //~ CLOCK_DSP1_CTL = 0xa0,
928 //~ CLOCK_DSP1_PLL = 0xb0,
929 } clock_register_t;
931 #undef ENTRY
932 #define ENTRY(entry) { CLOCK_##entry, #entry }
933 static const offset_name_t clock_addr2reg[] = {
934 ENTRY(PDC),
935 ENTRY(BUS_CTL),
936 ENTRY(BUS_PLL),
937 ENTRY(CPU_CTL),
938 ENTRY(CPU_PLL),
939 ENTRY(USB_CTL),
940 ENTRY(USB_PLL),
941 ENTRY(DSP_CTL),
942 ENTRY(DSP_PLL),
943 { 0 }
946 static const char *clock_regname(unsigned offset)
948 return offset2name(clock_addr2reg, offset);
951 #if 0
952 struct tnetd7300_clock {
953 u32 ctrl;
954 #define PREDIV_MASK 0x001f0000
955 #define PREDIV_SHIFT 16
956 #define POSTDIV_MASK 0x0000001f
957 u32 unused1[3];
958 u32 pll;
959 #define MUL_MASK 0x0000f000
960 #define MUL_SHIFT 12
961 #define PLL_MODE_MASK 0x00000001
962 #define PLL_NDIV 0x00000800
963 #define PLL_DIV 0x00000002
964 #define PLL_STATUS 0x00000001
965 u32 unused2[3];
966 } __attribute__ ((packed));
968 struct tnetd7300_clocks {
969 struct tnetd7300_clock bus;
970 struct tnetd7300_clock cpu;
971 struct tnetd7300_clock usb;
972 struct tnetd7300_clock dsp;
973 } __attribute__ ((packed));
974 #endif
976 static void power_write(uint32_t val)
978 uint32_t oldpowerstate = reg_read(av.clock_control, 0);
979 uint32_t newpowerstate = val;
980 if (oldpowerstate != newpowerstate) {
981 #if defined(DEBUG_AR7)
982 static const char *powerbits[] = {
983 /* 00 */ "usb", "wdt", "uart0", "uart1",
984 /* 04 */ "iic", "vdma", "gpio", "vlynq1",
985 /* 08 */ "sar", "adsl", "emif", "reserved11",
986 /* 12 */ "adsp", "ram", "rom", "dma",
987 /* 16 */ "bist", "reserved17", "timer0", "timer1",
988 /* 20 */ "emac0", "reserved21", "emac1", "reserved23",
989 /* 24 */ "ephy", "reserved25", "reserved26", "vlynq0",
990 /* 28 */ "reserved28", "reserved29", "reserved30", "reserved31" // 30?, 31?
992 // bit coded device(s). 0 = disabled (reset), 1 = enabled.
993 uint32_t changed = (oldpowerstate ^ newpowerstate);
994 uint32_t enabled = (changed & newpowerstate);
995 unsigned i;
996 for (i = 0; i < 32; i++) {
997 if (changed & BIT(i)) {
998 TRACE(CLOCK,
999 logout("power %sabled %s (0x%08x)",
1000 (enabled & BIT(i)) ? "en" : "dis",
1001 powerbits[i], val));
1004 #endif
1005 oldpowerstate >>= 30;
1006 TRACE(CLOCK, logout("change power state from %u to %u",
1007 oldpowerstate, newpowerstate));
1011 static uint32_t clock_read(unsigned offset)
1013 static uint32_t last;
1014 static unsigned count;
1015 uint32_t val = reg_read(av.clock_control, offset);
1016 unsigned clock_index = offset / 4;
1017 if (clock_index == 0x0c || clock_index == 0x14 || clock_index == 0x1c || clock_index == 0x24) {
1018 /* Reset PLL status bit after a short delay. */
1019 if (val == 0x00000005 || val == 0x00007005 || val == 0x000047fd || val == 0x000057fd) {
1020 /* Workaround for AVM Linux 2.6.13.1. */
1021 val &= ~1;
1022 } else if (val == last) {
1023 if (count > 0) {
1024 count--;
1025 } else {
1026 val ^= 1;
1027 reg_write(av.clock_control, offset, val);
1029 } else {
1030 count = 2;
1031 last = val;
1032 val |= 1;
1033 reg_write(av.clock_control, offset, val);
1036 TRACE(CLOCK, logout("clock[%s] = 0x%08x %s", clock_regname(offset), val, backtrace()));
1037 return val;
1040 static void clock_write(unsigned offset, uint32_t val)
1042 TRACE(CLOCK, logout("clock[%s] = 0x%08x %s", clock_regname(offset), val, backtrace()));
1043 if (offset == CLOCK_PDC) {
1044 power_write(val);
1045 } else if (offset / 4 == 0x0c) {
1046 uint32_t oldval = reg_read(av.clock_control, offset);
1047 TRACE(CLOCK, logout("clock[%s] was 0x%08x %s", clock_regname(offset), oldval, backtrace()));
1048 if ((oldval & ~1) == val) {
1049 val = oldval;
1052 reg_write(av.clock_control, offset, val);
1055 /*****************************************************************************
1057 * Configuration (device config latch) emulation.
1059 ****************************************************************************/
1061 static const char *i2dcl[] = {
1062 "config",
1063 "test mux1",
1064 "test mux2",
1065 "test mux3",
1066 "adsl pll select",
1067 "speed control",
1068 "speed control password",
1069 "speed control capture",
1072 typedef enum {
1073 DCL_BOOT_CONFIG = 0x00,
1074 DCL_BOOT_TEST_MUX1 = 0x04,
1075 DCL_BOOT_TEST_MUX2 = 0x08,
1076 DCL_BOOT_TEST_MUX3 = 0x0c,
1077 DCL_BOOT_ADSL_PLL_SELECT = 0x10,
1078 DCL_BOOT_SPEED_CONTROL = 0x14,
1079 DCL_BOOT_SPEED_CONTROL_PW = 0x18,
1080 DCL_BOOT_SPEED_CONTROL_CAPTURE = 0x1c,
1081 } dcl_register_t;
1083 typedef enum {
1084 CONFIG_BOOTS = BITS(2, 0), /* 001 */
1085 CONFIG_WSDP = BIT(3), /* 0 */
1086 CONFIG_WDHE = BIT(4), /* 0 */
1087 CONFIG_PLL_BYP = BIT(5), /* 0 */
1088 CONFIG_ENDIAN = BIT(6), /* 0 = little endian */
1089 CONFIG_FLASHW = BITS(8, 7), /* 01 = 16 bit flash */
1090 CONFIG_EMIFRATE = BIT(9), /* 1 */
1091 CONFIG_EMIFTEST = BIT(10), /* 0 */
1092 CONFIG_BOOTS_INT = BITS(13, 11), /* 000 */
1093 CONFIG_SYS_PLL_SEL = BITS(15, 14), /* 01, BUS */
1094 CONFIG_CPU_PLL_SEL = BITS(17, 16), /* 01 */
1095 CONFIG_USB_PLL_SEL = BITS(19, 18), /* 11 */
1096 CONFIG_EPHY_PLL_SEL = BITS(21, 20), /* 01 */
1097 CONFIG_DSP_PLL_SEL = BITS(23, 22), /* 01, ADSL */
1098 CONFIG_ADSL_RST = BIT(24), /* 0 */
1099 CONFIG_MIPS_ASYNC = BIT(25), /* 1 */
1100 CONFIG_DEF = BIT(26), /* 0 */
1101 CONFIG_RESERVED = BITS(31, 27), /* 0 */
1102 } dcl_config_bit_t;
1104 #if 0
1105 /* clock selection */
1106 case 0: /*--- AFE_CLKl input (DSP, 35328000) ---*/
1107 case 1: /*--- REFCLCKl input (LAN, 25000000) ---*/
1108 case 2: /*--- XTAL3IN input ---*/
1109 case 3: /*--- MIPS-Pll output ---*/
1110 #endif
1112 static uint32_t ar7_dcl_read(unsigned offset)
1114 uint32_t val = reg_read(av.dcl, offset);
1115 const char *text = i2dcl[offset / 4];
1116 int logflag = DCL;
1117 if (0) {
1118 } else if (offset == DCL_BOOT_CONFIG) {
1119 } else {
1121 TRACE(logflag, logout("dcl[%s] (0x%08x) = 0x%08x %s",
1122 text, (AVALANCHE_DCL_BASE + offset),
1123 val, backtrace()));
1124 return val;
1127 static uint32_t ar7_dcl_write(unsigned offset, uint32_t val)
1129 reg_write(av.dcl, offset, val);
1130 const char *text = i2dcl[offset / 4];
1131 int logflag = DCL;
1132 if (0) {
1133 } else if (offset == DCL_BOOT_CONFIG) {
1134 assert(0);
1135 } else {
1137 TRACE(logflag, logout("dcl[%s] (0x%08x) = 0x%08x %s",
1138 text, (AVALANCHE_DCL_BASE + offset),
1139 val, backtrace()));
1140 return val;
1143 typedef enum {
1144 TEST_MUX_MBSPL_SEL = BIT(0),
1145 TEST_MUX_CODEC_CHAR_EN = BIT(1),
1146 } dcl_test_mux1_bit_t;
1148 #if 0
1149 union _hw_boot_test_mux_2 {
1150 struct __hw_boot_test_mux_2 {
1151 unsigned int mii0_sel : 1;
1152 } Bits;
1153 volatile unsigned int Register;
1154 } hw_boot_test_mux_2 ;
1156 union _hw_boot_test_mux_3 {
1157 struct __hw_boot_test_mux_3 {
1158 unsigned int pll_pin_output_enable : 1;
1159 unsigned int pll_pin_out_id : 2; /* 0: System, 1: MIPS, 2: USB, 3: adsl */
1160 unsigned int pll_pin_out_div_enable : 1;
1161 } Bits;
1162 volatile unsigned int Register;
1163 } hw_boot_test_mux_3 ;
1165 union _hw_boot_adsl_pll_select {
1166 struct __hw_boot_adsl_pll_select {
1167 unsigned int pll_0_select : 1;
1168 } Bits;
1169 volatile unsigned int Register;
1170 } hw_boot_adsl_pll_select ;
1172 union _hw_boot_speed_control {
1173 struct __hw_boot_speed_control {
1174 unsigned int gated_ring_oscillator_enable : 1;
1175 unsigned int input_counter_enable : 1;
1176 unsigned int gated_oscillator_select : 3;
1177 } Bits;
1178 volatile unsigned int Register;
1179 } hw_boot_speed_control ;
1181 union _hw_boot_speed_control_password {
1182 struct __hw_boot_speed_control_password {
1183 unsigned int passwd_enable : 1;
1184 } Bits;
1185 volatile unsigned int Register;
1186 } hw_boot_speed_control_password ;
1188 union _hw_boot_speed_control_capture {
1189 struct __hw_boot_speed_control_capture {
1190 unsigned int out : 16;
1191 } Bits;
1192 volatile unsigned int Register;
1193 } hw_boot_speed_control_capture ;
1194 #endif
1196 /*****************************************************************************
1198 * Ethernet Media Access Controller (EMAC, CPMAC) emulation.
1200 ****************************************************************************/
1202 /* Large parts of the emac code can be used for TMS320DM644x emac, too.
1203 * Parts which are specific for AR7 and must be changed for other SoCs
1204 * are marked with CONFIG_AR7_EMAC.
1205 * See also linux drivers/net/cpmac.c, drivers/net/davinci_emac.c.
1208 #define CONFIG_AR7_EMAC 1
1210 #if 0
1213 08611600 43 00 72 04 00 00 00 00 00 00 00 00 00 00 00 00 |C.r.............|
1214 08611610 43 00 72 04 00 00 00 00 00 00 00 00 00 00 00 00 |C.r.............|
1215 08611a00 91 42 5d 02 00 00 00 00 00 00 00 00 00 00 00 00 |.B].............|
1216 08611a10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
1217 08611b00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
1220 cpmac_reg.h:
1221 #define BOFFTEST(base) ((MEM_PTR)(base+0x1E0))
1222 #define PACTEST(base) ((MEM_PTR)(base+0x1E4))
1223 #define RXPAUSE(base) ((MEM_PTR)(base+0x1E8))
1224 #define TXPAUSE(base) ((MEM_PTR)(base+0x1EC))
1226 #endif
1228 typedef enum {
1229 CPMAC_TXIDVER = 0x0000,
1230 CPMAC_TXCONTROL = 0x0004,
1231 CPMAC_TXTEARDOWN = 0x0008,
1232 CPMAC_RXIDVER = 0x0010,
1233 CPMAC_RXCONTROL = 0x0014,
1234 CPMAC_RXTEARDOWN = 0x0018,
1235 CPMAC_RXMBPENABLE = 0x0100,
1236 CPMAC_RXUNICASTSET = 0x0104,
1237 CPMAC_RXUNICASTCLEAR = 0x0108,
1238 CPMAC_RXMAXLEN = 0x010c,
1239 CPMAC_RXBUFFEROFFSET = 0x0110,
1240 CPMAC_RXFILTERLOWTHRESH = 0x0114,
1241 CPMAC_RX0FLOWTHRESH = 0x0120,
1242 CPMAC_RX1FLOWTHRESH = 0x0124,
1243 CPMAC_RX2FLOWTHRESH = 0x0128,
1244 CPMAC_RX3FLOWTHRESH = 0x012c,
1245 CPMAC_RX4FLOWTHRESH = 0x0130,
1246 CPMAC_RX5FLOWTHRESH = 0x0134,
1247 CPMAC_RX6FLOWTHRESH = 0x0138,
1248 CPMAC_RX7FLOWTHRESH = 0x013c,
1249 CPMAC_RX0FREEBUFFER = 0x0140,
1250 CPMAC_RX1FREEBUFFER = 0x0144,
1251 CPMAC_RX2FREEBUFFER = 0x0148,
1252 CPMAC_RX3FREEBUFFER = 0x014c,
1253 CPMAC_RX4FREEBUFFER = 0x0150,
1254 CPMAC_RX5FREEBUFFER = 0x0154,
1255 CPMAC_RX6FREEBUFFER = 0x0158,
1256 CPMAC_RX7FREEBUFFER = 0x015c,
1257 CPMAC_MACCONTROL = 0x0160,
1258 CPMAC_MACSTATUS = 0x0164,
1259 CPMAC_EMCONTROL = 0x0168,
1260 CPMAC_TXINTSTATRAW = 0x0170,
1261 CPMAC_TXINTSTATMASKED = 0x0174,
1262 CPMAC_TXINTMASKSET = 0x0178,
1263 CPMAC_TXINTMASKCLEAR = 0x017c,
1264 CPMAC_MACINVECTOR = 0x0180,
1265 CPMAC_MACEOIVECTOR = 0x0184,
1266 CPMAC_RXINTSTATRAW = 0x0190,
1267 CPMAC_RXINTSTATMASKED = 0x0194,
1268 CPMAC_RXINTMASKSET = 0x0198,
1269 CPMAC_RXINTMASKCLEAR = 0x019c,
1270 CPMAC_MACINTSTATRAW = 0x01a0,
1271 CPMAC_MACINTSTATMASKED = 0x01a4,
1272 CPMAC_MACINTMASKSET = 0x01a8,
1273 CPMAC_MACINTMASKCLEAR = 0x01ac,
1274 CPMAC_MACADDRLO_0 = 0x01b0,
1275 CPMAC_MACADDRLO_1 = 0x01b4,
1276 CPMAC_MACADDRLO_2 = 0x01b8,
1277 CPMAC_MACADDRLO_3 = 0x01bc,
1278 CPMAC_MACADDRLO_4 = 0x01c0,
1279 CPMAC_MACADDRLO_5 = 0x01c4,
1280 CPMAC_MACADDRLO_6 = 0x01c8,
1281 CPMAC_MACADDRLO_7 = 0x01cc,
1282 CPMAC_MACADDRMID = 0x01d0,
1283 CPMAC_MACADDRHI = 0x01d4,
1284 CPMAC_MACHASH1 = 0x01d8,
1285 CPMAC_MACHASH2 = 0x01dc,
1286 /* Statistics. */
1287 CPMAC_RXGOODFRAMES = 0x0200,
1288 CPMAC_RXBROADCASTFRAMES = 0x0204,
1289 CPMAC_RXMULTICASTFRAMES = 0x0208,
1290 CPMAC_RXPAUSEFRAMES = 0x020c,
1291 CPMAC_RXCRCERRORS = 0x0210,
1292 CPMAC_RXALIGNCODEERRORS = 0x0214,
1293 CPMAC_RXOVERSIZEDFRAMES = 0x0218,
1294 CPMAC_RXJABBERFRAMES = 0x021c,
1295 CPMAC_RXUNDERSIZEDFRAMES = 0x0220,
1296 CPMAC_RXFRAGMENTS = 0x0224,
1297 CPMAC_RXFILTEREDFRAMES = 0x0228,
1298 CPMAC_RXQOSFILTEREDFRAMES = 0x022c,
1299 CPMAC_RXOCTETS = 0x0230,
1300 CPMAC_TXGOODFRAMES = 0x234,
1301 CPMAC_TXBROADCASTFRAMES = 0x238,
1302 CPMAC_TXMULTICASTFRAMES = 0x23c,
1303 CPMAC_TXPAUSEFRAMES = 0x0240,
1304 CPMAC_TXDEFERREDFRAMES = 0x0244,
1305 CPMAC_TXCOLLISIONFRAMES = 0x0248,
1306 CPMAC_TXSINGLECOLLFRAMES = 0x024c,
1307 CPMAC_TXMULTCOLLFRAMES = 0x0250,
1308 CPMAC_TXEXCESSIVECOLLISIONS = 0x0254,
1309 CPMAC_TXLATECOLLISIONS = 0x0258,
1310 CPMAC_TXUNDERRUN = 0x025c,
1311 CPMAC_TXCARRIERSENSEERRORS = 0x0260,
1312 CPMAC_TXOCTETS = 0x0264,
1313 CPMAC_64OCTETFRAMES = 0x0268,
1314 CPMAC_65T127OCTETFRAMES = 0x026c,
1315 CPMAC_128T255OCTETFRAMES = 0x0270,
1316 CPMAC_256T511OCTETFRAMES = 0x0274,
1317 CPMAC_512T1023OCTETFRAMES = 0x0278,
1318 CPMAC_1024TUPOCTETFRAMES = 0x027c,
1319 CPMAC_NETOCTETS = 0x0280,
1320 CPMAC_RXSOFOVERRUNS = 0x0284,
1321 CPMAC_RXMOFOVERRUNS = 0x0288,
1322 CPMAC_RXDMAOVERRUNS = 0x028c,
1323 CPMAC_TX0HDP = 0x0600,
1324 CPMAC_TX1HDP = 0x0604,
1325 CPMAC_TX2HDP = 0x0608,
1326 CPMAC_TX3HDP = 0x060c,
1327 CPMAC_TX4HDP = 0x0610,
1328 CPMAC_TX5HDP = 0x0614,
1329 CPMAC_TX6HDP = 0x0618,
1330 CPMAC_TX7HDP = 0x061c,
1331 CPMAC_RX0HDP = 0x0620,
1332 CPMAC_RX1HDP = 0x0624,
1333 CPMAC_RX2HDP = 0x0628,
1334 CPMAC_RX3HDP = 0x062c,
1335 CPMAC_RX4HDP = 0x0630,
1336 CPMAC_RX5HDP = 0x0634,
1337 CPMAC_RX6HDP = 0x0638,
1338 CPMAC_RX7HDP = 0x063c,
1339 CPMAC_TX0CP = 0x0640,
1340 CPMAC_TX1CP = 0x0644,
1341 CPMAC_TX2CP = 0x0648,
1342 CPMAC_TX3CP = 0x064c,
1343 CPMAC_TX4CP = 0x0650,
1344 CPMAC_TX5CP = 0x0654,
1345 CPMAC_TX6CP = 0x0658,
1346 CPMAC_TX7CP = 0x065c,
1347 CPMAC_RX0CP = 0x0660,
1348 CPMAC_RX1CP = 0x0664,
1349 CPMAC_RX2CP = 0x0668,
1350 CPMAC_RX3CP = 0x066c,
1351 CPMAC_RX4CP = 0x0670,
1352 CPMAC_RX5CP = 0x0674,
1353 CPMAC_RX6CP = 0x0678,
1354 CPMAC_RX7CP = 0x067c,
1355 } cpmac_register_t;
1357 typedef enum {
1358 TXCONTROL_TXEN = BIT(0),
1359 } txcontrol_bit_t;
1361 typedef enum {
1362 RXCONTROL_RXEN = BIT(0),
1363 } rxcontrol_bit_t;
1365 #if defined(CONFIG_AR7_EMAC)
1366 typedef enum {
1367 MACINVECTOR_STATUS_INT = BIT(19),
1368 MACINVECTOR_HOST_INT = BIT(18),
1369 MACINVECTOR_RX_INT_OR = BIT(17),
1370 MACINVECTOR_TX_INT_OR = BIT(16),
1371 MACINVECTOR_RX_INT_VEC = BITS(10, 8),
1372 MACINVECTOR_TX_INT_VEC = BITS(2, 0),
1373 } mac_in_vec_bit_t;
1374 #else
1375 # error Implementation missing
1376 #endif
1378 typedef enum {
1379 MACINTSTAT_HOSTPEND = BIT(1),
1380 MACINTSTAT_STATPEND = BIT(0),
1381 } macintstat_bit_t;
1383 typedef enum {
1384 RXMBPENABLE_RXPASSCRC = BIT(30),
1385 RXMBPENABLE_RXQOSEN = BIT(29),
1386 RXMBPENABLE_RXNOCHAIN = BIT(28),
1387 RXMBPENABLE_RXCMEMFEN = BIT(24),
1388 RXMBPENABLE_RXCSFEN = BIT(23),
1389 RXMBPENABLE_RXCEFEN = BIT(22),
1390 RXMBPENABLE_RXCAFEN = BIT(21),
1391 RXMBPENABLE_RXPROMCH = BITS(18, 16),
1392 RXMBPENABLE_RXBROADEN = BIT(13),
1393 RXMBPENABLE_RXBROADCH = BITS(10, 8),
1394 RXMBPENABLE_RXMULTEN = BIT(5),
1395 RXMBPENABLE_RXMULTCH = BITS(2, 0),
1396 } rxmbpenable_bit_t;
1398 typedef enum {
1399 MACCONTROL_RXOFFLENBLOCK = BIT(14),
1400 MACCONTROL_RXOWNERSHIP = BIT(13),
1401 MACCONTROL_CMDIDLE = BIT(11),
1402 MACCONTROL_TXPTYPE = BIT(9),
1403 MACCONTROL_TXPACE = BIT(6),
1404 MACCONTROL_GMIIEN = BIT(5),
1405 MACCONTROL_TXFLOWEN = BIT(4),
1406 MACCONTROL_RXBUFFERFLOWEN = BIT(3),
1407 MACCONTROL_LOOPBACK = BIT(1),
1408 MACCONTROL_FULLDUPLEX = BIT(0),
1409 } maccontrol_bit_t;
1411 #undef ENTRY
1412 #define ENTRY(entry) { CPMAC_##entry, #entry }
1413 static const offset_name_t cpmac_addr2reg[] = {
1414 ENTRY(TXIDVER),
1415 ENTRY(TXCONTROL),
1416 ENTRY(TXTEARDOWN),
1417 ENTRY(RXIDVER),
1418 ENTRY(RXCONTROL),
1419 ENTRY(RXTEARDOWN),
1420 ENTRY(RXMBPENABLE),
1421 ENTRY(RXUNICASTSET),
1422 ENTRY(RXUNICASTCLEAR),
1423 ENTRY(RXMAXLEN),
1424 ENTRY(RXBUFFEROFFSET),
1425 ENTRY(RXFILTERLOWTHRESH),
1426 ENTRY(MACCONTROL),
1427 ENTRY(MACSTATUS),
1428 ENTRY(EMCONTROL),
1429 ENTRY(TXINTSTATRAW),
1430 ENTRY(TXINTSTATMASKED),
1431 ENTRY(TXINTMASKSET),
1432 ENTRY(TXINTMASKCLEAR),
1433 ENTRY(MACINVECTOR),
1434 ENTRY(MACEOIVECTOR),
1435 ENTRY(RXINTSTATRAW),
1436 ENTRY(RXINTSTATMASKED),
1437 ENTRY(RXINTMASKSET),
1438 ENTRY(RXINTMASKCLEAR),
1439 ENTRY(MACINTSTATRAW),
1440 ENTRY(MACINTSTATMASKED),
1441 ENTRY(MACINTMASKSET),
1442 ENTRY(MACINTMASKCLEAR),
1443 ENTRY(MACADDRLO_0),
1444 ENTRY(MACADDRLO_1),
1445 ENTRY(MACADDRLO_2),
1446 ENTRY(MACADDRLO_3),
1447 ENTRY(MACADDRLO_4),
1448 ENTRY(MACADDRLO_5),
1449 ENTRY(MACADDRLO_6),
1450 ENTRY(MACADDRLO_7),
1451 ENTRY(MACADDRMID),
1452 ENTRY(MACADDRHI),
1453 ENTRY(MACHASH1),
1454 ENTRY(MACHASH2),
1455 ENTRY(RXGOODFRAMES),
1456 ENTRY(RXBROADCASTFRAMES),
1457 ENTRY(RXMULTICASTFRAMES),
1458 ENTRY(RXPAUSEFRAMES),
1459 ENTRY(RXCRCERRORS),
1460 ENTRY(RXALIGNCODEERRORS),
1461 ENTRY(RXOVERSIZEDFRAMES),
1462 ENTRY(RXJABBERFRAMES),
1463 ENTRY(RXUNDERSIZEDFRAMES),
1464 ENTRY(RXFRAGMENTS),
1465 ENTRY(RXFILTEREDFRAMES),
1466 ENTRY(RXQOSFILTEREDFRAMES),
1467 ENTRY(RXOCTETS),
1468 ENTRY(TXGOODFRAMES),
1469 ENTRY(TXBROADCASTFRAMES),
1470 ENTRY(TXMULTICASTFRAMES),
1471 ENTRY(TXPAUSEFRAMES),
1472 ENTRY(TXDEFERREDFRAMES),
1473 ENTRY(TXCOLLISIONFRAMES),
1474 ENTRY(TXSINGLECOLLFRAMES),
1475 ENTRY(TXMULTCOLLFRAMES),
1476 ENTRY(TXEXCESSIVECOLLISIONS),
1477 ENTRY(TXLATECOLLISIONS),
1478 ENTRY(TXUNDERRUN),
1479 ENTRY(TXCARRIERSENSEERRORS),
1480 ENTRY(TXOCTETS),
1481 ENTRY(64OCTETFRAMES),
1482 ENTRY(65T127OCTETFRAMES),
1483 ENTRY(128T255OCTETFRAMES),
1484 ENTRY(256T511OCTETFRAMES),
1485 ENTRY(512T1023OCTETFRAMES),
1486 ENTRY(1024TUPOCTETFRAMES),
1487 ENTRY(NETOCTETS),
1488 ENTRY(RXSOFOVERRUNS),
1489 ENTRY(RXMOFOVERRUNS),
1490 ENTRY(RXDMAOVERRUNS),
1491 ENTRY(TX0HDP),
1492 ENTRY(TX1HDP),
1493 ENTRY(TX2HDP),
1494 ENTRY(TX3HDP),
1495 ENTRY(TX4HDP),
1496 ENTRY(TX5HDP),
1497 ENTRY(TX6HDP),
1498 ENTRY(TX7HDP),
1499 ENTRY(RX0HDP),
1500 ENTRY(RX1HDP),
1501 ENTRY(RX2HDP),
1502 ENTRY(RX3HDP),
1503 ENTRY(RX4HDP),
1504 ENTRY(RX5HDP),
1505 ENTRY(RX6HDP),
1506 ENTRY(RX7HDP),
1507 ENTRY(TX0CP),
1508 ENTRY(TX1CP),
1509 ENTRY(TX2CP),
1510 ENTRY(TX3CP),
1511 ENTRY(TX4CP),
1512 ENTRY(TX5CP),
1513 ENTRY(TX6CP),
1514 ENTRY(TX7CP),
1515 ENTRY(RX0CP),
1516 ENTRY(RX1CP),
1517 ENTRY(RX2CP),
1518 ENTRY(RX3CP),
1519 ENTRY(RX4CP),
1520 ENTRY(RX5CP),
1521 ENTRY(RX6CP),
1522 ENTRY(RX7CP),
1523 { 0 }
1526 static const char *cpmac_regname(unsigned offset)
1528 return offset2name(cpmac_addr2reg, offset);
1531 //~ static const int cpmac_address[] = { av.cpmac0, av.cpmac1 };
1532 static const int cpmac_interrupt[] = { INTERRUPT_CPMAC0, INTERRUPT_CPMAC1 };
1534 static void emac_update_interrupt(CpmacState *s)
1536 uint8_t *cpmac = s->addr;
1537 uint32_t txintmask = reg_read(cpmac, CPMAC_TXINTMASKSET);
1538 uint32_t txintstat = (reg_read(cpmac, CPMAC_TXINTSTATRAW) & txintmask);
1539 uint32_t rxintmask = reg_read(cpmac, CPMAC_RXINTMASKSET);
1540 uint32_t rxintstat = (reg_read(cpmac, CPMAC_RXINTSTATRAW) & rxintmask);
1541 uint32_t macintmask = reg_read(cpmac, CPMAC_MACINTMASKSET);
1542 uint32_t macintstat = (reg_read(cpmac, CPMAC_MACINTSTATRAW) & macintmask);
1543 #if defined(CONFIG_AR7_EMAC)
1544 uint32_t macintvector = (reg_read(cpmac, CPMAC_MACINVECTOR) & 0xffff);
1545 #else
1546 uint32_t macintvector = (((rxintstat & 0xff) << 8) | (txintstat & 0xff));
1547 #endif
1548 int enabled;
1549 reg_write(cpmac, CPMAC_TXINTSTATMASKED, txintstat);
1550 reg_write(cpmac, CPMAC_RXINTSTATMASKED, rxintstat);
1551 reg_write(cpmac, CPMAC_MACINTSTATMASKED, macintstat);
1552 // !!!
1553 if (txintstat) {
1554 macintvector |= MACINVECTOR_TX_INT_OR;
1555 #if defined(CONFIG_AR7_EMAC)
1556 } else {
1557 macintvector &= ~MACINVECTOR_TX_INT_VEC;
1558 #endif
1560 if (rxintstat) {
1561 macintvector |= MACINVECTOR_RX_INT_OR;
1562 #if defined(CONFIG_AR7_EMAC)
1563 } else {
1564 macintvector &= ~MACINVECTOR_RX_INT_VEC;
1565 #endif
1567 if (macintstat & MACINTSTAT_HOSTPEND) {
1568 macintvector |= MACINVECTOR_HOST_INT;
1570 if (macintstat & MACINTSTAT_STATPEND) {
1571 macintvector |= MACINVECTOR_STATUS_INT;
1573 reg_write(cpmac, CPMAC_MACINVECTOR, macintvector);
1574 enabled = (txintstat || rxintstat || macintstat);
1575 qemu_set_irq(AR7_PRIMARY_IRQ(cpmac_interrupt[s->index]), enabled);
1578 static void cpmac_reset(DeviceState *d)
1580 CpmacState *cpmac = CPMAC_STATE(d);
1581 uint8_t *address = cpmac->addr;
1582 logout("%s:%u", __FILE__, __LINE__);
1583 memset(address, 0, sizeof(av.cpmac0));
1584 reg_write(address, CPMAC_TXIDVER, 0x000c0a07);
1585 reg_write(address, CPMAC_RXIDVER, 0x000c0a07);
1586 reg_write(address, CPMAC_RXMAXLEN, 1518);
1587 //~ reg_write(address, CPMAC_MACCONFIG, 0x03030101);
1590 #define BD_SOP MASK(31, 31)
1591 #define BD_EOP MASK(30, 30)
1592 #define BD_OWNS MASK(29, 29)
1594 static uint32_t ar7_cpmac_read(CpmacState *s, unsigned offset)
1596 uint8_t * cpmac;
1597 if (!s) {
1598 return UINT32_MAX;
1600 cpmac = s->addr;
1601 uint32_t val = reg_read(cpmac, offset);
1602 const char *text = cpmac_regname(offset);
1603 int logflag = CPMAC;
1604 //~ do_raise_exception(EXCP_DEBUG)
1605 if (0) {
1606 } else if (offset == CPMAC_MACINVECTOR) {
1607 if (val == 0) {
1608 /* Disable logging of polled default value. */
1609 /* Linux 2.6.13.1: [scpphy_if_isr_tasklet][tasklet_action] */
1610 logflag = 0;
1612 } else {
1614 TRACE(logflag, logout("cpmac%u[%s] (0x%08x) = 0x%08x %s",
1615 s->index, text,
1616 AVALANCHE_CPMAC0_BASE + (AVALANCHE_CPMAC1_BASE -
1617 AVALANCHE_CPMAC0_BASE) *
1618 s->index + offset,
1619 val, backtrace()));
1620 return val;
1623 #if 0
1624 /* Table of CRCs of all 8-bit messages. */
1625 static uint32_t crc_table[256];
1627 /* Flag: has the table been computed? Initially false. */
1628 static int crc_table_computed = 0;
1630 /* Make the table for a fast CRC. */
1631 static void make_crc_table(void)
1633 int n, k;
1635 for (n = 0; n < 256; n++) {
1636 uint32_t c = (uint32_t) n;
1637 for (k = 0; k < 8; k++) {
1638 if (c & 1)
1639 c = 0xedb88320L ^ (c >> 1);
1640 else
1641 c = c >> 1;
1643 crc_table[n] = c;
1645 crc_table_computed = 1;
1648 /* Update a running CRC with the bytes buf[0..len-1]--the CRC
1649 should be initialized to all 1's, and the transmitted value
1650 is the 1's complement of the final running CRC (see the
1651 crc() routine below). */
1653 static uint32_t update_crc(uint32_t crc, const uint8_t * buf, int len)
1655 uint32_t c = crc;
1656 int n;
1658 if (!crc_table_computed)
1659 make_crc_table();
1660 for (n = 0; n < len; n++) {
1661 c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
1663 return c;
1666 /* Return the CRC of the bytes buf[0..len-1]. */
1667 static uint32_t fcs(const uint8_t * buf, int len)
1669 return update_crc(UINT32_MAX, buf, len) ^ UINT32_MAX;
1671 #endif
1673 static void statusreg_inc(CpmacState *s, unsigned offset)
1675 uint8_t *cpmac = s->addr;
1676 uint32_t value = reg_read(cpmac, offset);
1677 value++;
1678 reg_write(cpmac, offset, value);
1679 if (value >= 0x80000000) {
1680 reg_set(cpmac, CPMAC_MACINTSTATRAW, MACINTSTAT_STATPEND);
1681 emac_update_interrupt(s);
1682 MISSING();
1686 static void emac_transmit(CpmacState *s, unsigned offset, uint32_t address)
1688 uint8_t *cpmac = s->addr;
1689 uint8_t channel = (offset - CPMAC_TX0HDP) / 4;
1690 reg_write(cpmac, offset, address);
1691 if (address == 0) {
1692 } else if (!(reg_read(cpmac, CPMAC_MACCONTROL) & MACCONTROL_GMIIEN)) {
1693 TRACE(CPMAC, logout("cpmac%u MII is disabled, frame ignored",
1694 s->index));
1695 } else if (!(reg_read(cpmac, CPMAC_TXCONTROL) & TXCONTROL_TXEN)) {
1696 TRACE(CPMAC, logout("cpmac%u transmitter is disabled, frame ignored",
1697 s->index));
1698 } else {
1699 uint32_t length = 0;
1700 uint8_t buffer[MAX_ETH_FRAME_SIZE + 4];
1701 cpphy_tcb_t tcb;
1703 loop:
1705 length = 0;
1706 cpu_physical_memory_read(address, (uint8_t *) & tcb, sizeof(tcb));
1707 uint32_t next = le32_to_cpu(tcb.next);
1708 uint32_t addr = le32_to_cpu(tcb.buff);
1709 uint32_t bufferlength = le32_to_cpu(tcb.length);
1710 uint32_t packetlength = le32_to_cpu(tcb.mode);
1711 uint32_t bufferoffset = bufferlength >> 16;
1712 uint32_t flags = packetlength & BITS(31, 16);
1713 bufferlength &= BITS(15, 0);
1714 packetlength &= BITS(15, 0);
1716 TRACE(RXTX,
1717 logout
1718 ("buffer 0x%08x, next 0x%08x, buff 0x%08x, flags 0x%08x, len 0x%08x, total 0x%08x",
1719 address, next, addr, flags, bufferlength, packetlength));
1720 assert(length + packetlength <= MAX_ETH_FRAME_SIZE);
1721 cpu_physical_memory_read(addr, buffer + length, bufferlength);
1722 length += bufferlength;
1723 assert(packetlength == bufferlength);
1724 /* Next assertions normally raise host interrupt. */
1725 assert(flags & TCB_SOP);
1726 assert(flags & TCB_EOP);
1727 //~ assert(flags & TCB_OWNER); // !!!
1728 if (!(flags & TCB_OWNER)) {
1729 logout("%s: OWNER flag is not set", __func__);
1730 UNEXPECTED();
1732 assert(!(flags & TCB_PASSCRC));
1733 assert(bufferoffset == 0);
1734 /* Real hardware sets flag when finished, we set it here. */
1735 flags &= ~(TCB_OWNER);
1736 flags |= TCB_EOQ;
1737 stl_phys(&address_space_memory,
1738 address + offsetof(cpphy_tcb_t, mode), flags | packetlength);
1740 if (s->nic != 0) {
1741 #if 0
1742 uint32_t crc = fcs(buffer, length);
1743 TRACE(CPMAC,
1744 logout("FCS 0x%04x 0x%04x",
1745 (uint32_t) crc32(~0, buffer, length - 4), crc));
1746 crc = htonl(crc);
1747 memcpy(&buffer[length], &crc, 4);
1748 length += 4;
1749 #endif
1750 TRACE(RXTX,
1751 logout("cpmac%u sent %u byte: %s", s->index, length,
1752 dump(buffer, length)));
1753 qemu_send_packet(qemu_get_queue(s->nic), buffer, length);
1755 statusreg_inc(s, CPMAC_TXGOODFRAMES);
1756 reg_write(cpmac, offset, next);
1757 reg_write(cpmac, CPMAC_TX0CP + 4 * channel, address);
1758 reg_set(cpmac, CPMAC_TXINTSTATRAW, BIT(channel));
1759 #if defined(CONFIG_AR7_EMAC)
1760 reg_set(cpmac, CPMAC_MACINVECTOR, channel);
1761 #endif
1762 emac_update_interrupt(s);
1763 //~ break;
1764 //~ statusreg_inc(s, CPMAC_TXBROADCASTFRAMES);
1765 //~ statusreg_inc(s, CPMAC_TXMULTICASTFRAMES);
1767 if (next != 0) {
1768 TRACE(RXTX, logout("more data to send..."));
1769 address = next;
1770 goto loop;
1775 static void ar7_cpmac_write(CpmacState *s, unsigned offset, uint32_t val)
1777 uint8_t * cpmac;
1778 if (!s) {
1779 return;
1781 cpmac = s->addr;
1782 assert((offset & 3) == 0);
1783 TRACE(CPMAC, logout("cpmac%u[%s] (0x%08x) = 0x%08lx",
1784 s->index, cpmac_regname(offset),
1785 (AVALANCHE_CPMAC0_BASE +
1786 (AVALANCHE_CPMAC1_BASE -
1787 AVALANCHE_CPMAC0_BASE) * s->index +
1788 offset), (unsigned long)val));
1789 if (0) {
1790 } else if (offset == CPMAC_TXTEARDOWN) {
1791 uint32_t channel = val;
1792 uint32_t txhdp = reg_read(cpmac, CPMAC_TX0HDP + 4 * channel);
1793 assert(channel < 8);
1794 channel &= BITS(2, 0);
1795 if (txhdp != 0) {
1796 uint32_t flags = ldl_phys(&address_space_memory,
1797 txhdp + offsetof(cpphy_tcb_t, mode));
1798 flags |= TCB_TDOWNCMPLT;
1799 stl_phys(&address_space_memory,
1800 txhdp + offsetof(cpphy_tcb_t, mode), flags);
1802 reg_write(cpmac, CPMAC_TX0HDP + 4 * channel, 0);
1803 reg_write(cpmac, CPMAC_TX0CP + 4 * channel, 0xfffffffc);
1804 reg_set(cpmac, CPMAC_TXINTSTATRAW, BIT(channel));
1805 emac_update_interrupt(s);
1806 } else if (offset == CPMAC_RXTEARDOWN) {
1807 uint32_t channel = val;
1808 uint32_t rxhdp = reg_read(cpmac, CPMAC_RX0HDP + 4 * channel);
1809 assert(channel < 8);
1810 channel &= BITS(2, 0);
1811 if (rxhdp != 0) {
1812 uint32_t flags = ldl_phys(&address_space_memory,
1813 rxhdp + offsetof(cpphy_rcb_t, mode));
1814 flags |= RCB_TDOWNCMPLT;
1815 stl_phys(&address_space_memory,
1816 rxhdp + offsetof(cpphy_rcb_t, mode), flags);
1818 reg_write(cpmac, CPMAC_RX0HDP + 4 * channel, 0);
1819 reg_write(cpmac, CPMAC_RX0CP + 4 * channel, 0xfffffffc);
1820 reg_set(cpmac, CPMAC_RXINTSTATRAW, BIT(channel));
1821 emac_update_interrupt(s);
1822 } else if (offset == CPMAC_RXMBPENABLE) {
1823 /* 13 ... 8 = 0x20 enable broadcast */
1824 reg_write(cpmac, offset, val);
1825 } else if (offset == CPMAC_RXUNICASTSET) {
1826 val &= BITS(7, 0);
1827 val = (reg_read(cpmac, offset) | val);
1828 //~ assert(val < 2);
1829 reg_write(cpmac, offset, val);
1830 } else if (offset == CPMAC_RXUNICASTCLEAR) {
1831 val = (reg_read(cpmac, CPMAC_RXUNICASTSET) & ~val);
1832 reg_write(cpmac, CPMAC_RXUNICASTSET, val);
1833 } else if (offset == CPMAC_RXMAXLEN) {
1834 TRACE(CPMAC, logout("setting max packet length %u", val));
1835 val &= 0xffff;
1836 reg_write(cpmac, offset, val);
1837 } else if (offset == CPMAC_TXINTMASKSET) {
1838 val &= BITS(7, 0);
1839 val = (reg_read(cpmac, offset) | val);
1840 reg_write(cpmac, offset, val);
1841 emac_update_interrupt(s);
1842 } else if (offset == CPMAC_TXINTMASKCLEAR) {
1843 val = (reg_read(cpmac, CPMAC_TXINTMASKSET) & ~val);
1844 reg_write(cpmac, CPMAC_TXINTMASKSET, val);
1845 emac_update_interrupt(s);
1846 } else if (offset == CPMAC_RXINTMASKSET) {
1847 val &= BITS(7, 0);
1848 val = (reg_read(cpmac, offset) | val);
1849 reg_write(cpmac, offset, val);
1850 emac_update_interrupt(s);
1851 } else if (offset == CPMAC_RXINTMASKCLEAR) {
1852 val = (reg_read(cpmac, CPMAC_RXINTMASKSET) & ~val);
1853 reg_write(cpmac, CPMAC_RXINTMASKSET, val);
1854 emac_update_interrupt(s);
1855 } else if (offset == CPMAC_MACINTMASKSET) {
1856 val &= BITS(1, 0);
1857 val = (reg_read(cpmac, offset) | val);
1858 reg_write(cpmac, offset, val);
1859 emac_update_interrupt(s);
1860 } else if (offset == CPMAC_MACINTMASKCLEAR) {
1861 val = (reg_read(cpmac, CPMAC_MACINTMASKSET) & ~val);
1862 reg_write(cpmac, CPMAC_MACINTMASKSET, val);
1863 emac_update_interrupt(s);
1864 } else if (offset == CPMAC_MACADDRHI) {
1865 /* set MAC address (4 high bytes) */
1866 uint8_t *phys = s->conf.macaddr.a;
1867 reg_write(cpmac, offset, val);
1868 phys[5] = cpmac[CPMAC_MACADDRLO_0];
1869 phys[4] = cpmac[CPMAC_MACADDRMID];
1870 phys[3] = cpmac[CPMAC_MACADDRHI + 3];
1871 phys[2] = cpmac[CPMAC_MACADDRHI + 2];
1872 phys[1] = cpmac[CPMAC_MACADDRHI + 1];
1873 phys[0] = cpmac[CPMAC_MACADDRHI + 0];
1874 // TODO: set address for qemu?
1875 if (s->nic) {
1876 qemu_format_nic_info_str(qemu_get_queue(s->nic), phys);
1877 TRACE(CPMAC, logout("setting mac address %s",
1878 qemu_get_queue(s->nic)->info_str));
1880 } else if (offset >= CPMAC_RXGOODFRAMES && offset <= CPMAC_RXDMAOVERRUNS) {
1881 /* Write access to statistics register. */
1882 if (reg_read(cpmac, CPMAC_MACCONTROL) & MACCONTROL_GMIIEN) {
1883 /* Write-to-decrement mode. */
1884 uint32_t oldval = reg_read(cpmac, offset);
1885 if (oldval < val) {
1886 val = 0;
1887 } else {
1888 oldval -= val;
1890 reg_write(cpmac, offset, val);
1891 } else {
1892 /* Normal write direct mode. */
1893 reg_write(cpmac, offset, val);
1895 } else if (offset >= CPMAC_TX0HDP && offset <= CPMAC_TX7HDP) {
1896 /* Transmit buffer. */
1897 emac_transmit(s, offset, val);
1898 } else if (offset >= CPMAC_RX0HDP && offset <= CPMAC_RX7HDP) {
1899 reg_write(cpmac, offset, val);
1900 } else if (offset >= CPMAC_TX0CP && offset <= CPMAC_TX7CP) {
1901 uint8_t channel = (offset - CPMAC_TX0CP) / 4;
1902 uint32_t oldval = reg_read(cpmac, offset);
1903 if (oldval == val) {
1904 reg_clear(cpmac, CPMAC_TXINTSTATRAW, BIT(channel));
1905 emac_update_interrupt(s);
1907 } else if (offset >= CPMAC_RX0CP && offset <= CPMAC_RX7CP) {
1908 uint8_t channel = (offset - CPMAC_RX0CP) / 4;
1909 uint32_t oldval = reg_read(cpmac, offset);
1910 if (oldval == val) {
1911 reg_clear(cpmac, CPMAC_RXINTSTATRAW, BIT(channel));
1912 emac_update_interrupt(s);
1914 } else {
1915 //~ logout("???");
1916 reg_write(cpmac, offset, val);
1920 /*****************************************************************************
1922 * EMIF emulation.
1924 ****************************************************************************/
1926 typedef enum {
1927 EMIF_REV = 0x00,
1928 EMIF_GASYNC = 0x04,
1929 EMIF_DRAMCTL = 0x08,
1930 EMIF_REFRESH = 0x0c,
1931 EMIF_ASYNC_CS0 = 0x10,
1932 EMIF_ASYNC_CS3 = 0x14,
1933 EMIF_ASYNC_CS4 = 0x18,
1934 EMIF_ASYNC_CS5 = 0x1c,
1935 } emif_register_t;
1937 static uint32_t ar7_emif_read(unsigned offset)
1939 uint32_t value = reg_read(av.emif, offset);
1940 TRACE(EMIF, logout("emif[0x%02x] = 0x%08x", offset, value));
1941 return value;
1944 static void ar7_emif_write(unsigned offset, uint32_t value)
1946 TRACE(EMIF, logout("emif[0x%02x] = 0x%08x", offset, value));
1947 if (offset == EMIF_REV) {
1948 /* Revision is readonly. */
1949 UNEXPECTED();
1950 } else {
1951 reg_write(av.emif, offset, value);
1955 /*****************************************************************************
1957 * GPIO emulation.
1959 ****************************************************************************/
1961 typedef enum {
1962 GPIO_IN = 0x00,
1963 GPIO_OUT = 0x04,
1964 GPIO_DIR = 0x08,
1965 GPIO_ENABLE = 0x0c,
1966 GPIO_CVR = 0x14, /* chip version */
1967 GPIO_DIDR1 = 0x18,
1968 GPIO_DIDR2 = 0x1c,
1969 GPIO_TITAN = 0x24, /* titan chip */
1970 } GpioOffset;
1972 static void ar7_led_display(unsigned led_index, int on)
1974 static const uint8_t x[] = { 1, 7, 14, 23, 29 };
1975 qemu_chr_fe_printf(&ar7->gpio_display, "\e[10;%uH\e[%dm \e[m", x[led_index], (on) ? 42 : 40);
1978 static void ar7_gpio_display(void)
1980 unsigned bit_index;
1981 uint32_t in = reg_read(av.gpio, GPIO_IN);
1982 uint32_t out = reg_read(av.gpio, GPIO_OUT);
1983 uint32_t dir = reg_read(av.gpio, GPIO_DIR);
1984 uint32_t enable = reg_read(av.gpio, GPIO_ENABLE);
1985 char text[32];
1986 for (bit_index = 0; bit_index < 32; bit_index++) {
1987 text[bit_index] = (in & BIT(bit_index)) ? '*' : '.';
1989 qemu_chr_fe_printf(&ar7->gpio_display, "\e[5;1H%32.32s (in 0x%08x)",
1990 text, in);
1991 for (bit_index = 0; bit_index < 32; bit_index++) {
1992 text[bit_index] = (out & BIT(bit_index)) ? '*' : '.';
1994 qemu_chr_fe_printf(&ar7->gpio_display, "\e[6;1H%32.32s (out 0x%08x)",
1995 text, out);
1996 for (bit_index = 0; bit_index < 32; bit_index++) {
1997 text[bit_index] = (dir & BIT(bit_index)) ? '*' : '.';
1999 qemu_chr_fe_printf(&ar7->gpio_display, "\e[7;1H%32.32s (dir 0x%08x)",
2000 text, dir);
2001 for (bit_index = 0; bit_index < 32; bit_index++) {
2002 text[bit_index] = (enable & BIT(bit_index)) ? '*' : '.';
2004 qemu_chr_fe_printf(&ar7->gpio_display, "\e[8;1H%32.32s (ena 0x%08x)",
2005 text, enable);
2007 /* LAN LED. */
2008 ar7_led_display(0, 1);
2010 /* WLAN LED. */
2011 ar7_led_display(1, !(out & BIT(6)));
2013 /* ONLINE LED. */
2014 ar7_led_display(2, !(out & BIT(13)));
2016 /* DSL LED. */
2017 ar7_led_display(3, 0);
2019 /* POWER LED. */
2020 ar7_led_display(4, 1);
2022 /* Hide cursor. */
2023 qemu_chr_fe_printf(&ar7->gpio_display, "\e[20;1H");
2026 #undef ENTRY
2027 #define ENTRY(entry) { GPIO_##entry, #entry }
2028 static const offset_name_t gpio_addr2reg[] = {
2029 ENTRY(IN),
2030 ENTRY(OUT),
2031 ENTRY(DIR),
2032 ENTRY(ENABLE),
2033 ENTRY(CVR),
2034 ENTRY(DIDR1),
2035 ENTRY(DIDR2),
2036 { 0 }
2039 static const char *gpio_regname(unsigned offset)
2041 return offset2name(gpio_addr2reg, offset);
2044 static uint32_t ar7_gpio_read(unsigned offset)
2046 uint32_t value = reg_read(av.gpio, offset);
2047 if (offset == GPIO_IN && value == 0x00000800) {
2048 /* Do not log polling of reset button. */
2049 TRACE(GPIO, logout("gpio[%s] = 0x%08x", gpio_regname(offset), value));
2050 } else {
2051 TRACE(GPIO, logout("gpio[%s] = 0x%08x", gpio_regname(offset), value));
2053 return value;
2056 static void ar7_gpio_write(unsigned offset, uint32_t value)
2058 TRACE(GPIO, logout("gpio[%s] = 0x%08x", gpio_regname(offset), value));
2059 reg_write(av.gpio, offset, value);
2060 if (offset <= GPIO_DIR) {
2061 ar7_gpio_display();
2065 /*****************************************************************************
2067 * Management Data Input/Output (MDIO) emulation.
2069 ****************************************************************************/
2071 typedef enum {
2072 MDIO_VERSION = 0,
2073 MDIO_CONTROL = 4,
2074 MDIO_ALIVE = 8,
2075 MDIO_LINK = 0x0c,
2076 MDIO_LINKINTRAW = 0x10,
2077 MDIO_LINKINTMASKED = 0x14,
2078 MDIO_USERINTRAW = 0x20,
2079 MDIO_USERINTMASKED = 0x24,
2080 MDIO_USERINTMASKSET = 0x28,
2081 MDIO_USERINTMASKCLEAR = 0x2c,
2082 MDIO_USERACCESS0 = 0x80,
2083 MDIO_USERPHYSEL0 = 0x84,
2084 MDIO_USERACCESS1 = 0x88,
2085 MDIO_USERPHYSEL1 = 0x8c,
2086 } mdio_t;
2088 typedef enum {
2089 MDIO_VERSION_MODID = BITS(31, 16),
2090 MDIO_VERSION_REVMAJ = BITS(15, 8),
2091 MDIO_VERSION_REVMIN = BITS(7, 0),
2092 } mdio_version_bit_t;
2094 typedef enum {
2095 MDIO_CONTROL_IDLE = BIT(31),
2096 MDIO_CONTROL_ENABLE = BIT(30),
2097 MDIO_CONTROL_HIGHEST_USER_CHANNEL = BITS(28, 24),
2098 MDIO_CONTROL_PREAMBLE = BIT(20),
2099 MDIO_CONTROL_FAULT = BIT(19),
2100 MDIO_CONTROL_FAULTENB = BIT(18),
2101 MDIO_CONTROL_INT_TEST_ENABLE = BIT(17),
2102 MDIO_CONTROL_CLKDIV = BITS(15, 0),
2103 } mdio_control_bit_t;
2105 typedef enum {
2106 MDIO_USERACCESS_GO = BIT(31),
2107 MDIO_USERACCESS_WRITE = BIT(30),
2108 MDIO_USERACCESS_ACK = BIT(29),
2109 MDIO_USERACCESS_REGADR = BITS(25, 21),
2110 MDIO_USERACCESS_PHYADR = BITS(20, 16),
2111 MDIO_USERACCESS_DATA = BITS(15, 0),
2112 } mdio_useraccess_bit_t;
2114 typedef enum {
2115 MDIO_USERPHYSEL_LINKSEL = BIT(7),
2116 MDIO_USERPHYSEL_LINKINTENB = BIT(6),
2117 MDIO_USERPHYSEL_PHYADRMON = BITS(4, 0),
2118 } mdio_userphysel_bit_t;
2120 #include "hw/phy.c"
2122 static uint32_t mdio_phy_read(unsigned phy_index)
2124 uint32_t val = reg_read(av.mdio, (phy_index == 0) ? MDIO_USERACCESS0 : MDIO_USERACCESS1);
2125 TRACE(MDIO, logout("mdio[USERACCESS%u] = 0x%08x", phy_index, val));
2126 return val;
2129 static void mdio_phy_write(unsigned phy_index, uint32_t val)
2131 unsigned writeflag = (val & MDIO_USERACCESS_WRITE) >> 30;
2132 unsigned regaddr = (val & MDIO_USERACCESS_REGADR) >> 21;
2133 unsigned phyaddr = (val & MDIO_USERACCESS_PHYADR) >> 16;
2134 uint32_t mdio_control = reg_read(av.mdio, MDIO_CONTROL);
2135 assert(regaddr < 32);
2136 assert(phyaddr < 32);
2137 TRACE(MDIO,
2138 logout
2139 ("mdio[USERACCESS%u] = 0x%08x, writeflag = %u, reg = %u, phy = %u",
2140 phy_index, val, writeflag, regaddr, phyaddr));
2141 if (val & MDIO_USERACCESS_GO) {
2142 val &= (MDIO_USERACCESS_WRITE | MDIO_USERACCESS_REGADR |
2143 MDIO_USERACCESS_PHYADR | MDIO_USERACCESS_DATA);
2144 if (!(mdio_control & MDIO_CONTROL_ENABLE)) {
2145 /* MDIO state machine is not enabled. */
2146 val = 0;
2147 } else if (phyaddr == ar7->phyaddr) {
2148 if (writeflag) {
2149 phy_write(regaddr, val & MDIO_USERACCESS_DATA);
2150 } else {
2151 val = phy_read(regaddr);
2152 val |= MDIO_USERACCESS_ACK;
2153 val |= (regaddr << 21);
2154 val |= (phyaddr << 16);
2156 reg_set(av.mdio, MDIO_ALIVE, BIT(phyaddr));
2157 } else {
2158 val = 0;
2159 reg_clear(av.mdio, MDIO_ALIVE, BIT(phyaddr));
2163 reg_write(av.mdio,
2164 (phy_index == 0) ? MDIO_USERACCESS0 : MDIO_USERACCESS1,
2165 val);
2168 static uint32_t ar7_mdio_read(uint8_t *mdio, unsigned offset)
2170 const char *text = 0;
2171 uint32_t val = reg_read(mdio, offset);
2172 if (offset == MDIO_VERSION) {
2173 text = "VERSION";
2174 //~ cpMacMdioInit(): MDIO_CONTROL = 0x40000138
2175 //~ cpMacMdioInit(): MDIO_CONTROL < 0x40000037
2176 } else if (offset == MDIO_CONTROL) {
2177 text = "CONTROL";
2178 } else if (offset == MDIO_ALIVE) {
2179 text = "ALIVE";
2180 } else if (offset == MDIO_LINK) {
2181 /* Suppress noise logging output from polling of link. */
2182 //~ if (val != 0x80000000) {
2183 text = "LINK";
2184 //~ }
2185 } else if (offset == MDIO_USERACCESS0) {
2186 val = mdio_phy_read(0);
2187 } else if (offset == MDIO_USERACCESS1) {
2188 val = mdio_phy_read(1);
2189 } else {
2190 TRACE(MDIO, logout("mdio[0x%02x] = 0x%08x", offset, val));
2192 if (text) {
2193 TRACE(MDIO, logout("mdio[%s] = 0x%08x", text, val));
2195 return val;
2198 static void ar7_mdio_write(uint8_t *mdio, unsigned offset, uint32_t val)
2200 const char *text = 0;
2201 if (offset == MDIO_VERSION) {
2202 text = "VERSION";
2203 UNEXPECTED();
2204 } else if (offset == MDIO_CONTROL) {
2205 uint32_t oldval = reg_read(mdio, offset);
2206 text = "CONTROL";
2207 if ((val ^ oldval) & MDIO_CONTROL_ENABLE) {
2208 if (val & MDIO_CONTROL_ENABLE) {
2209 TRACE(MDIO, logout("enable MDIO state machine"));
2210 phy_enable();
2211 reg_write(av.mdio, MDIO_ALIVE, BIT(ar7->phyaddr));
2212 } else {
2213 TRACE(MDIO, logout("disable MDIO state machine"));
2214 phy_disable();
2217 reg_write(mdio, offset, val);
2218 } else if (offset == MDIO_USERACCESS0) {
2219 mdio_phy_write(0, val);
2220 } else if (offset == MDIO_USERACCESS1) {
2221 mdio_phy_write(1, val);
2222 } else {
2223 TRACE(MDIO, logout("mdio[0x%02x] = 0x%08x", offset, val));
2224 reg_write(mdio, offset, val);
2226 if (text) {
2227 TRACE(MDIO, logout("mdio[%s] = 0x%08x", text, val));
2231 /*****************************************************************************
2233 * Reset emulation.
2235 ****************************************************************************/
2237 static void ar7_reset_write(uint32_t offset, uint32_t val)
2239 if (offset == 0) {
2240 #if defined(DEBUG_AR7)
2241 static const char *resetdevice[] = {
2242 /* 00 */ "uart0", "uart1", "i2c", "timer0",
2243 /* 04 */ "timer1", "reserved05", "gpio", "adsl",
2244 /* 08 */ "usb", "atm", "reserved10", "vdma",
2245 /* 12 */ "fser", "reserved13", "reserved14", "reserved15",
2246 /* 16 */ "vlynq1", "cpmac0", "mcdma", "bist",
2247 /* 20 */ "vlynq0", "cpmac1", "mdio", "dsp",
2248 /* 24 */ "reserved24", "reserved25", "ephy", "reserved27",
2249 /* 28 */ "reserved28", "reserved29", "reserved30", "reserved31"
2251 // Reset bit coded device(s). 0 = disabled (reset), 1 = enabled.
2252 static uint32_t oldval;
2253 uint32_t changed = (val ^ oldval);
2254 uint32_t enabled = (changed & val);
2255 //~ uint32_t disabled = (changed & oldval);
2256 unsigned i;
2257 oldval = val;
2258 for (i = 0; i < 32; i++) {
2259 if (changed & BIT(i)) {
2260 TRACE(RESET,
2261 logout("reset %sabled %s (0x%08x)",
2262 (enabled & BIT(i)) ? "en" : "dis",
2263 resetdevice[i], val));
2266 #endif
2267 } else if (offset == 4) {
2268 TRACE(RESET, logout("reset"));
2269 qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
2270 //~ CPUMIPSState *env = first_cpu;
2271 //~ env->active_tc.PC = 0xbfc00000;
2272 } else {
2273 TRACE(RESET, logout("reset[%u]=0x%08x", offset, val));
2277 /*****************************************************************************
2279 * Timer emulation.
2281 ****************************************************************************/
2283 // CTL0 /* control register */
2284 // PRD0 /* period register */
2285 // CNT0 /* counter register */
2287 typedef enum {
2288 TIMER_CONTROL = 0,
2289 TIMER_LOAD = 4,
2290 TIMER_VALUE = 8,
2291 TIMER_INTERRUPT = 12,
2292 } timer_register_t;
2294 typedef enum {
2295 TIMER_CONTROL_GO = BIT(0),
2296 TIMER_CONTROL_MODE = BIT(1),
2297 TIMER_CONTROL_PRESCALE = BITS(5, 2),
2298 TIMER_CONTROL_PRESCALE_ENABLE = BIT(15),
2299 } timer_control_bit_t;
2301 static void timer_cb(void *opaque)
2303 ar7_timer_t *timer = (ar7_timer_t *)opaque;
2305 TRACE(TIMER, logout("timer%d expired", timer == &ar7->timer[1]));
2306 qemu_irq_raise(timer->interrupt);
2307 if (timer->cyclic) {
2308 int64_t t = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
2309 timer_mod(timer->qemu_timer, t + timer->prescale * timer->time);
2313 static uint32_t ar7_timer_read(unsigned timer_index, uint32_t addr)
2315 ar7_timer_t *timer = &ar7->timer[timer_index];
2316 uint32_t val;
2317 val = reg_read(timer->base, addr);
2318 TRACE(TIMER, logout("timer%u[%d]=0x%08x", timer_index, addr, val));
2319 return val;
2322 static void ar7_timer_write(unsigned timer_index, uint32_t addr, uint32_t val)
2324 ar7_timer_t *timer = &ar7->timer[timer_index];
2325 TRACE(TIMER, logout("timer%u[%d]=0x%08x", timer_index, addr, val));
2326 reg_write(timer->base, addr, val);
2327 if (addr == TIMER_CONTROL) {
2328 timer->cyclic = ((val & TIMER_CONTROL_MODE) != 0);
2329 if (val & TIMER_CONTROL_PRESCALE_ENABLE) {
2330 timer->prescale = ((val & TIMER_CONTROL_PRESCALE) >> 2);
2331 logout("prescale %u", timer->prescale);
2332 } else {
2333 timer->prescale = 1;
2335 if (val & TIMER_CONTROL_GO) {
2336 int64_t t = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
2337 timer_mod(timer->qemu_timer, t + timer->prescale * timer->time);
2338 } else {
2339 timer_del(timer->qemu_timer);
2341 } else if (addr == TIMER_LOAD) {
2342 timer->time = val * (NANOSECONDS_PER_SECOND / io_frequency);
2346 /*****************************************************************************
2348 * UART emulation.
2350 ****************************************************************************/
2352 static const char *const uart_read_names[] = {
2353 "RBR",
2354 "IER",
2355 "IIR",
2356 "LCR",
2357 "MCR",
2358 "LSR",
2359 "MSR",
2360 "SCR",
2361 "DLL",
2362 "DLM",
2365 static const char *const uart_write_names[] = {
2366 "TBR",
2367 "IER",
2368 "FCR",
2369 "LCR",
2370 "MCR",
2371 "LSR",
2372 "MSR",
2373 "SCR",
2374 "DLL",
2375 "DLM",
2378 #define UART_MEM_TO_IO(addr) (((addr) - AVALANCHE_UART0_BASE) / 4)
2380 static const hwaddr uart_base[] = {
2381 AVALANCHE_UART0_BASE, AVALANCHE_UART1_BASE
2384 static const int uart_interrupt[] = {
2385 INTERRUPT_SERIAL0, INTERRUPT_SERIAL1
2388 /* Status of DLAB bit. */
2389 static uint32_t dlab[2];
2391 static inline unsigned uart_name_index(unsigned uart_index, unsigned reg)
2393 if (reg < 2 && dlab[uart_index]) {
2394 reg += 8;
2396 return reg;
2399 static uint32_t uart_read(unsigned uart_index, uint32_t addr)
2401 uint32_t val;
2402 int port = UART_MEM_TO_IO(addr);
2403 unsigned reg = port;
2404 if (uart_index == 1) {
2405 reg -= UART_MEM_TO_IO(AVALANCHE_UART1_BASE);
2407 assert(reg < 8);
2408 val = serial_mm_read(ar7->serial[uart_index], addr, 1);
2409 //~ if (reg != 5) {
2410 TRACE(UART, logout("uart%u[%s]=0x%08x", uart_index,
2411 uart_read_names[uart_name_index(uart_index, reg)], val));
2412 //~ }
2413 return val;
2416 static void uart_write(unsigned uart_index, uint32_t addr, uint32_t val)
2418 int port = UART_MEM_TO_IO(addr);
2419 unsigned reg = port;
2420 if (uart_index == 1) {
2421 reg -= UART_MEM_TO_IO(AVALANCHE_UART1_BASE);
2423 assert(reg < 8);
2424 //~ if (reg != 0 || dlab[uart_index]) {
2425 TRACE(UART, logout("uart%u[%s]=0x%08x", uart_index,
2426 uart_write_names[uart_name_index(uart_index, reg)], val));
2427 //~ }
2428 if (reg == 3) {
2429 dlab[uart_index] = (val & 0x80);
2431 serial_mm_write(ar7->serial[uart_index], addr, val, 1);
2434 /*****************************************************************************
2436 * VLYNQ emulation.
2438 ****************************************************************************/
2440 static const char *const vlynq_names[] = {
2441 /* 0x00 */
2442 "Revision",
2443 "Control",
2444 "Status",
2445 "Interrupt Priority Vector Status/Clear",
2446 /* 0x10 */
2447 "Interrupt Status/Clear",
2448 "Interrupt Pending/Set",
2449 "Interrupt Pointer",
2450 "Tx Address Map",
2451 /* 0x20 */
2452 "Rx Address Map Size 1",
2453 "Rx Address Map Offset 1",
2454 "Rx Address Map Size 2",
2455 "Rx Address Map Offset 2",
2456 /* 0x30 */
2457 "Rx Address Map Size 3",
2458 "Rx Address Map Offset 3",
2459 "Rx Address Map Size 4",
2460 "Rx Address Map Offset 4",
2461 /* 0x40 */
2462 "Chip Version",
2463 "Auto Negotiation",
2464 "Manual Negotiation",
2465 "Negotiation Status",
2466 /* 0x50 */
2467 "Reserved",
2468 "Reserved",
2469 "Reserved",
2470 "Reserved",
2471 /* 0x60 */
2472 "Reserved",
2473 "Reserved",
2474 "Reserved",
2475 "Reserved",
2476 /* 0x70 */
2477 "Reserved",
2478 "Reserved",
2479 "Reserved",
2480 "Reserved",
2481 /* 0x80 */
2482 "Remote Revision",
2483 "Remote Control",
2484 "Remote Status",
2485 "Remote Interrupt Priority Vector Status/Clear",
2486 /* 0x90 */
2487 "Remote Interrupt Status/Clear",
2488 "Remote Interrupt Pending/Set",
2489 "Remote Interrupt Pointer",
2490 "Remote Tx Address Map",
2491 /* 0xa0 */
2492 "Remote Rx Address Map Size 1",
2493 "Remote Rx Address Map Offset 1",
2494 "Remote Rx Address Map Size 2",
2495 "Remote Rx Address Map Offset 2",
2496 /* 0xb0 */
2497 "Remote Rx Address Map Size 3",
2498 "Remote Rx Address Map Offset 3",
2499 "Remote Rx Address Map Size 4",
2500 "Remote Rx Address Map Offset 4",
2501 /* 0xc0 */
2502 "Remote Chip Version",
2503 "Remote Auto Negotiation",
2504 "Remote Manual Negotiation",
2505 "Remote Negotiation Status",
2506 /* 0xd0 */
2507 "Reserved",
2508 "Reserved",
2509 "Reserved",
2510 "Reserved",
2511 /* 0xe0 */
2512 "Remote Interrupt Vector 03-00",
2513 "Remote Interrupt Vector 07-04",
2514 "Remote Interrupt Vector 11-08",
2515 "Remote Interrupt Vector 15-12",
2516 "Remote Interrupt Vector 19-16",
2517 "Remote Interrupt Vector 23-20",
2518 "Remote Interrupt Vector 27-24",
2519 "Remote Interrupt Vector 31-28",
2522 typedef enum {
2523 VLYNQ_REVID = 0x00,
2524 VLYNQ_CTRL = 0x04,
2525 VLYNQ_STAT = 0x08,
2526 VLYNQ_INTPRI = 0x0c,
2527 VLYNQ_INTSTATCLR = 0x10,
2528 VLYNQ_INTPENDSET = 0x14,
2529 VLYNQ_INTPTR = 0x18,
2530 VLYNQ_XAM = 0x1c,
2531 VLYNQ_RAMS1 = 0x20,
2532 VLYNQ_RAMO1 = 0x24,
2533 VLYNQ_RAMS2 = 0x28,
2534 VLYNQ_RAMO2 = 0x2c,
2535 VLYNQ_RAMS3 = 0x30,
2536 VLYNQ_RAMO3 = 0x34,
2537 VLYNQ_RAMS4 = 0x38,
2538 VLYNQ_RAMO4 = 0x3c,
2539 VLYNQ_CHIPVER = 0x40,
2540 VLYNQ_AUTNGO = 0x44,
2541 VLYNQ_RREVID = 0x80,
2542 VLYNQ_RCTRL = 0x84,
2543 VLYNQ_RSTAT = 0x88,
2544 VLYNQ_RINTPRI = 0x8c,
2545 VLYNQ_RINTSTATCLR = 0x90,
2546 VLYNQ_RINTPENDSET = 0x94,
2547 VLYNQ_RINTPTR = 0x98,
2548 VLYNQ_RXAM = 0x9c,
2549 VLYNQ_RRAMS1 = 0xa0,
2550 VLYNQ_RRAMO1 = 0xa4,
2551 VLYNQ_RRAMS2 = 0xa8,
2552 VLYNQ_RRAMO2 = 0xac,
2553 VLYNQ_RRAMS3 = 0xb0,
2554 VLYNQ_RRAMO3 = 0xb4,
2555 VLYNQ_RRAMS4 = 0xb8,
2556 VLYNQ_RRAMO4 = 0xbc,
2557 VLYNQ_RCHIPVER = 0xc0,
2558 VLYNQ_RAUTNGO = 0xc4,
2559 VLYNQ_RMANNGO = 0xc8,
2560 VLYNQ_RNGOSTAT = 0xcc,
2561 VLYNQ_RINTVEC0 = 0xe0,
2562 VLYNQ_RINTVEC1 = 0xe4,
2563 VLYNQ_RINTVEC2 = 0xe8,
2564 VLYNQ_RINTVEC3 = 0xec,
2565 VLYNQ_RINTVEC4 = 0xf0,
2566 VLYNQ_RINTVEC5 = 0xf4,
2567 VLYNQ_RINTVEC6 = 0xf8,
2568 VLYNQ_RINTVEC7 = 0xfc,
2569 } vlynq_register_t;
2571 #if 0
2572 struct _vlynq_registers_half {
2574 /*--- 0x00 Revision/ID Register ---*/
2575 unsigned int Revision_ID;
2577 /*--- 0x04 Control Register ---*/
2578 union __vlynq_Control {
2579 struct _vlynq_Control {
2580 #define VLYNQ_CTL_CTRL_SHIFT 0
2581 unsigned int reset:1;
2582 #define VLYNQ_CTL_ILOOP_SHIFT 1
2583 unsigned int iloop:1;
2584 #define VLYNQ_CTL_AOPT_DISABLE_SHIFT 2
2585 unsigned int aopt_disable:1;
2586 unsigned int reserved1:4;
2587 #define VLYNQ_CTL_INT2CFG_SHIFT 7
2588 unsigned int int2cfg:1;
2589 #define VLYNQ_CTL_INTVEC_SHIFT 8
2590 unsigned int intvec:5;
2591 #define VLYNQ_CTL_INTEN_SHIFT 13
2592 unsigned int intenable:1;
2593 #define VLYNQ_CTL_INTLOCAL_SHIFT 14
2594 unsigned int intlocal:1;
2595 #define VLYNQ_CTL_CLKDIR_SHIFT 15
2596 unsigned int clkdir:1;
2597 #define VLYNQ_CTL_CLKDIV_SHIFT 16
2598 unsigned int clkdiv:3;
2599 unsigned int reserved2:2;
2600 #define VLYNQ_CTL_TXFAST_SHIFT 21
2601 unsigned int txfastpath:1;
2602 #define VLYNQ_CTL_RTMEN_SHIFT 22
2603 unsigned int rtmenable:1;
2604 #define VLYNQ_CTL_RTMVALID_SHIFT 23
2605 unsigned int rtmvalidwr:1;
2606 #define VLYNQ_CTL_RTMSAMPLE_SHIFT 24
2607 unsigned int rxsampleval:3;
2608 unsigned int reserved3:3;
2609 #define VLYNQ_CTL_SCLKUDIS_SHIFT 30
2610 unsigned int sclkpudis:1;
2611 #define VLYNQ_CTL_PMEM_SHIFT 31
2612 unsigned int pmen:1;
2613 } Bits;
2614 volatile unsigned int Register;
2615 } Control;
2617 /*--- 0x08 Status Register ---*/
2618 union __vlynq_Status {
2619 struct _vlynq_Status {
2620 unsigned int link:1;
2621 unsigned int mpend:1;
2622 unsigned int spend:1;
2623 unsigned int nfempty0:1;
2624 unsigned int nfempty1:1;
2625 unsigned int nfempty2:1;
2626 unsigned int nfempty3:1;
2627 unsigned int lerror:1;
2628 unsigned int rerror:1;
2629 unsigned int oflow:1;
2630 unsigned int iflow:1;
2631 unsigned int rtm:1;
2632 unsigned int rxcurrent_sample:3;
2633 unsigned int reserved1:5;
2634 unsigned int swidthout:4;
2635 unsigned int swidthin:4;
2636 unsigned int reserved2:4;
2637 } Bits;
2638 volatile unsigned int Register;
2639 } Status;
2641 /*--- 0x0C Interrupt Priority Vector Status/Clear Register ---*/
2642 union __vlynq_Interrupt_Priority {
2643 struct _vlynq_Interrupt_Priority {
2644 unsigned int intstat:5;
2645 unsigned int reserved:(32 - 5 - 1);
2646 unsigned int nointpend:1;
2647 } Bits;
2648 volatile unsigned int Register;
2649 } Interrupt_Priority;
2651 /*--- 0x10 Interrupt Status/Clear Register ---*/
2652 volatile unsigned int Interrupt_Status;
2654 /*--- 0x14 Interrupt Pending/Set Register ---*/
2655 volatile unsigned int Interrupt_Pending_Set;
2657 /*--- 0x18 Interrupt Pointer Register ---*/
2658 volatile unsigned int Interrupt_Pointer;
2660 /*--- 0x1C Tx Address Map ---*/
2661 volatile unsigned int Tx_Address;
2663 /*--- 0x20 Rx Address Map Size 1 ---*/
2664 /*--- 0x24 Rx Address Map Offset 1 ---*/
2665 /*--- 0x28 Rx Address Map Size 2 ---*/
2666 /*--- 0x2c Rx Address Map Offset 2 ---*/
2667 /*--- 0x30 Rx Address Map Size 3 ---*/
2668 /*--- 0x34 Rx Address Map Offset 3 ---*/
2669 /*--- 0x38 Rx Address Map Size 4 ---*/
2670 /*--- 0x3c Rx Address Map Offset 4 ---*/
2671 struct ___vlynq_Rx_Address Rx_Address[4];
2673 /*--- 0x40 Chip Version Register ---*/
2674 struct ___vlynq_Chip_Version Chip_Version;
2676 /*--- 0x44 Auto Negotiation Register ---*/
2677 union __Auto_Negotiation {
2678 struct _Auto_Negotiation {
2679 unsigned int reserved1:16;
2680 unsigned int _2_x:1;
2681 unsigned int reserved2:15;
2682 } Bits;
2683 volatile unsigned int Register;
2684 } Auto_Negotiation;
2686 /*--- 0x48 Manual Negotiation Register ---*/
2687 volatile unsigned int Manual_Negotiation;
2689 /*--- 0x4C Negotiation Status Register ---*/
2690 union __Negotiation_Status {
2691 struct _Negotiation_Status {
2692 unsigned int status:1;
2693 unsigned int reserved:31;
2694 } Bits;
2695 volatile unsigned int Register;
2696 } Negotiation_Status;
2698 /*--- 0x50-0x5C Reserved ---*/
2699 unsigned char reserved1[0x5C - 0x4C];
2701 /*--- 0x60 Interrupt Vector 3-0 ---*/
2702 union __vlynq_Interrupt_Vector Interrupt_Vector_1;
2704 /*--- 0x64 Interrupt Vector 7-4 ---*/
2705 union __vlynq_Interrupt_Vector Interrupt_Vector_2;
2707 /*--- 0x68-0x7C Reserved for Interrupt Vectors 8-31 ---*/
2708 unsigned char reserved2[0x7C - 0x64];
2710 #endif
2712 static uint32_t ar7_vlynq_read(unsigned vlynq_index, unsigned offset)
2714 uint8_t *vlynq = ar7->vlynq[vlynq_index];
2715 uint32_t val = reg_read(vlynq, offset);
2716 TRACE(VLYNQ, logout("vlynq%u[0x%02x (%s)] = 0x%08lx",
2717 vlynq_index, offset,
2718 vlynq_names[offset / 4],
2719 (unsigned long)val));
2720 if (offset == VLYNQ_REVID) {
2721 val = cpu_to_le32(0x00010206);
2722 } else if (offset == VLYNQ_INTSTATCLR) {
2723 reg_write(vlynq, offset, 0);
2724 } else if (offset == VLYNQ_RCHIPVER &&
2725 vlynq_index == ar7->vlynq_tnetw1130) {
2726 val = cpu_to_le32(0x00000009);
2727 } else {
2729 return val;
2732 static void ar7_vlynq_write(unsigned vlynq_index, unsigned offset, uint32_t val)
2734 uint8_t *vlynq = ar7->vlynq[vlynq_index];
2735 TRACE(VLYNQ, logout("vlynq%u[0x%02x (%s)] = 0x%08lx",
2736 vlynq_index, offset,
2737 vlynq_names[offset / 4],
2738 (unsigned long)val));
2739 if (offset == VLYNQ_REVID) {
2740 } else if (offset == VLYNQ_CTRL && vlynq_index == ar7->vlynq_tnetw1130) {
2741 /* Control and first vlynq emulates an established link. */
2742 if (!(val & BIT(0))) {
2743 /* Normal operation. Emulation sets link bit in status register. */
2744 reg_set(vlynq, VLYNQ_STAT, BIT(0));
2745 reg_set(vlynq, VLYNQ_RSTAT, BIT(0));
2746 } else {
2747 /* Reset. */
2748 reg_clear(vlynq, VLYNQ_STAT, BIT(0));
2749 reg_clear(vlynq, VLYNQ_RSTAT, BIT(0));
2751 } else {
2753 reg_write(vlynq, offset, val);
2756 /*****************************************************************************
2758 * Watchdog timer emulation.
2760 * This watchdog timer module has prescalar and counter which divide the input
2761 * reference frequency and upon expiration, the system is reset.
2763 * ref_freq
2764 * Reset freq = ---------------------
2765 * (prescalar * counter)
2767 * This watchdog timer supports timer values in mSecs. Thus
2769 * prescalar * counter * 1 KHZ
2770 * mSecs = --------------------------
2771 * ref_freq
2773 ****************************************************************************/
2775 #define KHZ 1000
2776 #define KICK_VALUE 1
2778 #define KICK_LOCK_1ST_STAGE 0x5555
2779 #define KICK_LOCK_2ND_STAGE 0xAAAA
2780 #define PRESCALE_LOCK_1ST_STAGE 0x5A5A
2781 #define PRESCALE_LOCK_2ND_STAGE 0xA5A5
2782 #define CHANGE_LOCK_1ST_STAGE 0x6666
2783 #define CHANGE_LOCK_2ND_STAGE 0xBBBB
2784 #define DISABLE_LOCK_1ST_STAGE 0x7777
2785 #define DISABLE_LOCK_2ND_STAGE 0xCCCC
2786 #define DISABLE_LOCK_3RD_STAGE 0xDDDD
2788 typedef struct {
2789 uint32_t kick_lock; /* 0x00 */
2790 uint32_t kick; /* 0x04 */
2791 uint32_t change_lock; /* 0x08 */
2792 uint32_t change; /* 0x0c */
2793 uint32_t disable_lock; /* 0x10 */
2794 uint32_t disable; /* 0x14 */
2795 uint32_t prescale_lock; /* 0x18 */
2796 uint32_t prescale; /* 0x1c */
2797 } wdtimer_t;
2799 static void watchdog_trigger(void)
2801 wdtimer_t *wdt = (wdtimer_t *) & av.watchdog;
2802 if (wdt->disable == 0) {
2803 TRACE(WDOG, logout("disabled watchdog"));
2804 timer_del(ar7->wd_timer);
2805 } else {
2806 int64_t t = ((uint64_t)wdt->change * (uint64_t)wdt->prescale) *
2807 (NANOSECONDS_PER_SECOND / io_frequency);
2808 //~ logout("change = 0x%x", wdt->change);
2809 //~ logout("prescale = 0x%x", wdt->prescale);
2810 TRACE(WDOG, logout("trigger value = %u ms",
2811 (unsigned)(t * 1000 / NANOSECONDS_PER_SECOND)));
2812 //~ logout("trigger value = %u", (unsigned)(NANOSECONDS_PER_SECOND / 1000000));
2813 timer_mod(ar7->wd_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + t);
2817 static inline uint16_t wd_val(uint16_t val, uint16_t bits)
2819 return ((val & ~0x3) | bits);
2822 static void ar7_wdt_write(unsigned offset, uint32_t val)
2824 wdtimer_t *wdt = (wdtimer_t *) & av.watchdog;
2825 if (offset == offsetof(wdtimer_t, kick_lock)) {
2826 if (val == KICK_LOCK_1ST_STAGE) {
2827 TRACE(WDOG, logout("kick lock 1st stage"));
2828 wdt->kick_lock = wd_val(val, 1);
2829 } else if (val == KICK_LOCK_2ND_STAGE) {
2830 TRACE(WDOG, logout("kick lock 2nd stage"));
2831 wdt->kick_lock = wd_val(val, 3);
2832 } else {
2833 TRACE(WDOG,
2834 logout("kick lock unexpected value 0x%08x, %s", val,
2835 backtrace()));
2837 } else if (offset == offsetof(wdtimer_t, kick)) {
2838 if (wdt->kick_lock != wd_val(KICK_LOCK_2ND_STAGE, 3)) {
2839 TRACE(WDOG, logout("kick still locked!"));
2840 UNEXPECTED();
2841 } else if (val == KICK_VALUE) {
2842 TRACE(WDOG, logout("kick (restart) watchdog"));
2843 watchdog_trigger();
2844 } else {
2845 UNEXPECTED();
2847 } else if (offset == offsetof(wdtimer_t, change_lock)) {
2848 if (val == CHANGE_LOCK_1ST_STAGE) {
2849 TRACE(WDOG, logout("change lock 1st stage"));
2850 wdt->change_lock = wd_val(val, 1);
2851 } else if (val == CHANGE_LOCK_2ND_STAGE) {
2852 TRACE(WDOG, logout("change lock 2nd stage"));
2853 wdt->change_lock = wd_val(val, 3);
2854 } else {
2855 TRACE(WDOG,
2856 logout("change lock unexpected value 0x%08x, %s", val,
2857 backtrace()));
2859 } else if (offset == offsetof(wdtimer_t, change)) {
2860 if (wdt->change_lock != wd_val(CHANGE_LOCK_2ND_STAGE, 3)) {
2861 TRACE(WDOG, logout("change still locked!"));
2862 UNEXPECTED();
2863 } else {
2864 TRACE(WDOG, logout("change watchdog, val=0x%08x", val));
2865 wdt->change = val;
2867 } else if (offset == offsetof(wdtimer_t, disable_lock)) {
2868 if (val == DISABLE_LOCK_1ST_STAGE) {
2869 TRACE(WDOG, logout("disable lock 1st stage"));
2870 wdt->disable_lock = wd_val(val, 1);
2871 } else if (val == DISABLE_LOCK_2ND_STAGE) {
2872 TRACE(WDOG, logout("disable lock 2nd stage"));
2873 wdt->disable_lock = wd_val(val, 2);
2874 } else if (val == DISABLE_LOCK_3RD_STAGE) {
2875 TRACE(WDOG, logout("disable lock 3rd stage"));
2876 wdt->disable_lock = wd_val(val, 3);
2877 } else {
2878 TRACE(WDOG,
2879 logout("disable lock unexpected value 0x%08x, %s", val,
2880 backtrace()));
2882 } else if (offset == offsetof(wdtimer_t, disable)) {
2883 if (wdt->disable_lock != wd_val(DISABLE_LOCK_3RD_STAGE, 3)) {
2884 TRACE(WDOG, logout("disable still locked, val=0x%08x!", val));
2885 UNEXPECTED();
2886 } else {
2887 TRACE(WDOG,
2888 logout("%sable watchdog, val=0x%08x", val ? "en" : "dis", val));
2889 wdt->disable = val;
2890 watchdog_trigger();
2892 } else if (offset == offsetof(wdtimer_t, prescale_lock)) {
2893 if (val == PRESCALE_LOCK_1ST_STAGE) {
2894 TRACE(WDOG, logout("prescale lock 1st stage"));
2895 wdt->prescale_lock = wd_val(val, 1);
2896 } else if (val == PRESCALE_LOCK_2ND_STAGE) {
2897 TRACE(WDOG, logout("prescale lock 2nd stage"));
2898 wdt->prescale_lock = wd_val(val, 3);
2899 } else {
2900 TRACE(WDOG,
2901 logout("prescale lock unexpected value 0x%08x, %s", val,
2902 backtrace()));
2904 } else if (offset == offsetof(wdtimer_t, prescale)) {
2905 if (wdt->prescale_lock != wd_val(PRESCALE_LOCK_2ND_STAGE, 3)) {
2906 TRACE(WDOG, logout("prescale still locked, val=0x%08x!", val));
2907 UNEXPECTED();
2908 } else {
2909 TRACE(WDOG, logout("set watchdog prescale, val=0x%08x", val)); // val = 0xffff
2910 wdt->prescale = val;
2912 } else {
2913 TRACE(WDOG,
2914 logout("??? offset 0x%02x = 0x%08x, %s", offset, val,
2915 backtrace()));
2919 static void watchdog_cb(void *opaque)
2921 CPUMIPSState *env = opaque;
2923 logout("watchdog expired");
2924 first_cpu->exception_index = EXCP_NMI;
2925 env->error_code = 0;
2926 mips_cpu_do_interrupt(ENV_GET_CPU(env));
2929 /*****************************************************************************
2931 * Generic AR7 hardware emulation.
2933 ****************************************************************************/
2935 #define INRANGE(base, var) \
2936 (((addr) >= (base)) && ((addr) < ((base) + (sizeof(var)) - 1)))
2938 #define VALUE(base, var) var[(addr - (base)) / 4]
2940 static uint32_t ar7_io_memread(void *opaque, uint32_t addr)
2942 uint32_t val = UINT32_MAX;
2943 const char *name = 0;
2944 int logflag = OTHER;
2946 assert(!(addr & 3));
2948 if (INRANGE(AVALANCHE_ADSLSSYS_MEM_BASE, av.adsl)) {
2949 name = "adsl";
2950 val = VALUE(AVALANCHE_ADSLSSYS_MEM_BASE, av.adsl);
2951 } else if (INRANGE(AVALANCHE_BBIF_BASE, av.bbif)) {
2952 name = "bbif";
2953 val = VALUE(AVALANCHE_BBIF_BASE, av.bbif);
2954 } else if (INRANGE(AVALANCHE_ATM_SAR_BASE, av.atmsar)) {
2955 unsigned offset = (addr - AVALANCHE_ATM_SAR_BASE);
2956 name = "atm sar";
2957 val = VALUE(AVALANCHE_ATM_SAR_BASE, av.atmsar);
2958 if (val == 0 && offset == 0x90) {
2959 val = 0x80000000;
2961 } else if (INRANGE(AVALANCHE_USB_MEM_BASE, av.usbslave)) {
2962 name = "usb memory";
2963 val = VALUE(AVALANCHE_USB_MEM_BASE, av.usbslave);
2964 } else if (INRANGE(AVALANCHE_VLYNQ1_REGION0_BASE, av.vlynq1region0)) {
2965 name = "vlynq1 region 0";
2966 logflag = VLYNQ;
2967 val = VALUE(AVALANCHE_VLYNQ1_REGION0_BASE, av.vlynq1region0);
2968 } else if (INRANGE(AVALANCHE_VLYNQ1_REGION1_BASE, av.vlynq1region1)) {
2969 name = "vlynq1 region 1";
2970 logflag = VLYNQ;
2971 val = VALUE(AVALANCHE_VLYNQ1_REGION1_BASE, av.vlynq1region1);
2972 } else if (INRANGE(AVALANCHE_CPMAC0_BASE, av.cpmac0)) {
2973 logflag = 0;
2974 val = ar7_cpmac_read(ar7->cpmac[0], addr - AVALANCHE_CPMAC0_BASE);
2975 } else if (INRANGE(AVALANCHE_EMIF_BASE, av.emif)) {
2976 logflag = 0;
2977 val = ar7_emif_read(addr - AVALANCHE_EMIF_BASE);
2978 } else if (INRANGE(AVALANCHE_GPIO_BASE, av.gpio)) {
2979 logflag = 0;
2980 val = ar7_gpio_read(addr - AVALANCHE_GPIO_BASE);
2981 } else if (INRANGE(AVALANCHE_CLOCK_BASE, av.clock_control)) {
2982 logflag = 0;
2983 val = clock_read(addr - AVALANCHE_CLOCK_BASE);
2984 } else if (INRANGE(AVALANCHE_WATCHDOG_BASE, av.watchdog)) {
2985 name = "watchdog";
2986 logflag = WDOG;
2987 val = VALUE(AVALANCHE_WATCHDOG_BASE, av.watchdog);
2988 } else if (INRANGE(AVALANCHE_TIMER0_BASE, av.timer0)) {
2989 logflag = 0;
2990 val = ar7_timer_read(0, addr - AVALANCHE_TIMER0_BASE);
2991 } else if (INRANGE(AVALANCHE_TIMER1_BASE, av.timer1)) {
2992 logflag = 0;
2993 val = ar7_timer_read(1, addr - AVALANCHE_TIMER1_BASE);
2994 } else if (INRANGE(AVALANCHE_UART0_BASE, av.uart0)) {
2995 logflag = 0;
2996 val = uart_read(0, addr);
2997 } else if (INRANGE(AVALANCHE_UART1_BASE, av.uart1)) {
2998 logflag = 0;
2999 val = uart_read(1, addr);
3000 } else if (INRANGE(AVALANCHE_USB_SLAVE_BASE, av.usb)) {
3001 name = "usb slave";
3002 val = VALUE(AVALANCHE_USB_SLAVE_BASE, av.usb);
3003 } else if (INRANGE(AVALANCHE_RESET_BASE, av.reset_control)) {
3004 name = "reset control";
3005 logflag = RESET;
3006 val = VALUE(AVALANCHE_RESET_BASE, av.reset_control);
3007 } else if (INRANGE(AVALANCHE_DCL_BASE, av.dcl)) {
3008 logflag = 0;
3009 val = ar7_dcl_read(addr - AVALANCHE_DCL_BASE);
3010 } else if (INRANGE(AVALANCHE_VLYNQ0_BASE, av.vlynq0)) {
3011 logflag = 0;
3012 val = ar7_vlynq_read(0, addr - AVALANCHE_VLYNQ0_BASE);
3013 } else if (INRANGE(AVALANCHE_VLYNQ1_BASE, av.vlynq1)) {
3014 logflag = 0;
3015 val = ar7_vlynq_read(1, addr - AVALANCHE_VLYNQ1_BASE);
3016 } else if (INRANGE(AVALANCHE_MDIO_BASE, av.mdio)) {
3017 logflag = 0;
3018 val = ar7_mdio_read(av.mdio, addr - AVALANCHE_MDIO_BASE);
3019 } else if (INRANGE(OHIO_WDT_BASE, av.wdt)) {
3020 name = "ohio wdt";
3021 val = VALUE(OHIO_WDT_BASE, av.wdt);
3022 } else if (INRANGE(AVALANCHE_INTC_BASE, av.intc)) {
3023 logflag = 0;
3024 val = ar7_intc_read(addr - AVALANCHE_INTC_BASE);
3025 } else if (INRANGE(AVALANCHE_CPMAC1_BASE, av.cpmac1)) {
3026 logflag = 0;
3027 val = ar7_cpmac_read(ar7->cpmac[1], addr - AVALANCHE_CPMAC1_BASE);
3028 } else {
3029 //~ name = "???";
3030 logflag = 0;
3032 logout("addr 0x%08x (???" ") = 0x%08x", addr, val);
3033 MISSING();
3036 if (name != 0) {
3037 TRACE(logflag, logout("addr 0x%08lx (%s) = 0x%08x",
3038 (unsigned long)addr, name, val));
3040 return val;
3043 static void ar7_io_memwrite(void *opaque, uint32_t addr, uint32_t val)
3045 const char *name = 0;
3046 int logflag = OTHER;
3048 if (addr & 3) {
3049 logout("??? addr 0x%08x", addr);
3050 assert(!(addr & 3));
3053 if (INRANGE(AVALANCHE_ADSLSSYS_MEM_BASE, av.adsl)) {
3054 name = "adsl";
3055 VALUE(AVALANCHE_ADSLSSYS_MEM_BASE, av.adsl) = val;
3056 } else if (INRANGE(AVALANCHE_BBIF_BASE, av.bbif)) {
3057 name = "bbif";
3058 VALUE(AVALANCHE_BBIF_BASE, av.bbif) = val;
3059 } else if (INRANGE(AVALANCHE_ATM_SAR_BASE, av.atmsar)) {
3060 name = "atm sar";
3061 VALUE(AVALANCHE_ATM_SAR_BASE, av.atmsar) = val;
3062 } else if (INRANGE(AVALANCHE_USB_MEM_BASE, av.usbslave)) {
3063 name = "usb memory";
3064 //~ VALUE(AVALANCHE_USB_MEM_BASE, av.usbslave) = val;
3065 VALUE(AVALANCHE_USB_MEM_BASE, av.usbslave) = UINT32_MAX;
3066 } else if (INRANGE(AVALANCHE_VLYNQ1_REGION0_BASE, av.vlynq1region0)) {
3067 name = "vlynq1 region 0";
3068 logflag = VLYNQ;
3069 VALUE(AVALANCHE_VLYNQ1_REGION0_BASE, av.vlynq1region0) = val;
3070 } else if (INRANGE(AVALANCHE_VLYNQ1_REGION1_BASE, av.vlynq1region1)) {
3071 name = "vlynq1 region 1";
3072 logflag = VLYNQ;
3073 VALUE(AVALANCHE_VLYNQ1_REGION1_BASE, av.vlynq1region1) = val;
3074 } else if (INRANGE(AVALANCHE_CPMAC0_BASE, av.cpmac0)) {
3075 logflag = 0;
3076 ar7_cpmac_write(ar7->cpmac[0], addr - AVALANCHE_CPMAC0_BASE, val);
3077 } else if (INRANGE(AVALANCHE_EMIF_BASE, av.emif)) {
3078 logflag = 0;
3079 ar7_emif_write(addr - AVALANCHE_EMIF_BASE, val);
3080 } else if (INRANGE(AVALANCHE_GPIO_BASE, av.gpio)) {
3081 logflag = 0;
3082 ar7_gpio_write(addr - AVALANCHE_GPIO_BASE, val);
3083 } else if (INRANGE(AVALANCHE_CLOCK_BASE, av.clock_control)) {
3084 logflag = 0;
3085 clock_write(addr - AVALANCHE_CLOCK_BASE, val);
3086 } else if (INRANGE(AVALANCHE_WATCHDOG_BASE, av.watchdog)) {
3087 logflag = 0;
3088 ar7_wdt_write(addr - AVALANCHE_WATCHDOG_BASE, val);
3089 } else if (INRANGE(AVALANCHE_TIMER0_BASE, av.timer0)) {
3090 logflag = 0;
3091 ar7_timer_write(0, addr - AVALANCHE_TIMER0_BASE, val);
3092 } else if (INRANGE(AVALANCHE_TIMER1_BASE, av.timer1)) {
3093 logflag = 0;
3094 ar7_timer_write(1, addr - AVALANCHE_TIMER1_BASE, val);
3095 } else if (INRANGE(AVALANCHE_UART0_BASE, av.uart0)) {
3096 logflag = 0;
3097 uart_write(0, addr, val);
3098 } else if (INRANGE(AVALANCHE_UART1_BASE, av.uart1)) {
3099 logflag = 0;
3100 uart_write(1, addr, val);
3101 } else if (INRANGE(AVALANCHE_USB_SLAVE_BASE, av.usb)) {
3102 name = "usb slave";
3103 VALUE(AVALANCHE_USB_SLAVE_BASE, av.usb) = val;
3104 } else if (INRANGE(AVALANCHE_RESET_BASE, av.reset_control)) {
3105 logflag = 0;
3106 VALUE(AVALANCHE_RESET_BASE, av.reset_control) = val;
3107 ar7_reset_write(addr - AVALANCHE_RESET_BASE, val);
3108 } else if (INRANGE(AVALANCHE_DCL_BASE, av.dcl)) {
3109 logflag = 0;
3110 ar7_dcl_write(addr - AVALANCHE_DCL_BASE, val);
3111 } else if (INRANGE(AVALANCHE_VLYNQ0_BASE, av.vlynq0)) {
3112 logflag = 0;
3113 ar7_vlynq_write(0, addr - AVALANCHE_VLYNQ0_BASE, val);
3114 } else if (INRANGE(AVALANCHE_VLYNQ1_BASE, av.vlynq1)) {
3115 logflag = 0;
3116 ar7_vlynq_write(1, addr - AVALANCHE_VLYNQ1_BASE, val);
3117 } else if (INRANGE(AVALANCHE_MDIO_BASE, av.mdio)) {
3118 logflag = 0;
3119 ar7_mdio_write(av.mdio, addr - AVALANCHE_MDIO_BASE, val);
3120 } else if (INRANGE(OHIO_WDT_BASE, av.wdt)) {
3121 name = "ohio wdt";
3122 VALUE(OHIO_WDT_BASE, av.wdt) = val;
3123 } else if (INRANGE(AVALANCHE_INTC_BASE, av.intc)) {
3124 logflag = 0;
3125 ar7_intc_write(addr - AVALANCHE_INTC_BASE, val);
3126 } else if (INRANGE(AVALANCHE_CPMAC1_BASE, av.cpmac1)) {
3127 logflag = 0;
3128 ar7_cpmac_write(ar7->cpmac[1], addr - AVALANCHE_CPMAC1_BASE, val);
3129 } else if (addr >= AVALANCHE_DISPLAY_BASE + 0x408 && addr < AVALANCHE_DISPLAY_BASE + 0x453) {
3130 uint32_t display_address = addr - AVALANCHE_DISPLAY_BASE;
3131 switch (display_address) {
3132 /* LEDBAR Register */
3133 case 0x00408:
3134 malta_display.leds = val & 0xff;
3135 break;
3136 /* ASCIIWORD Register */
3137 case 0x00410:
3138 snprintf(malta_display.display_text, 9, "%08X", val);
3139 malta_fpga_update_display(&malta_display);
3140 break;
3141 /* ASCIIPOS0 to ASCIIPOS7 Registers */
3142 case 0x00418:
3143 case 0x00420:
3144 case 0x00428:
3145 case 0x00430:
3146 case 0x00438:
3147 case 0x00440:
3148 case 0x00448:
3149 case 0x00450:
3150 malta_display.display_text[(display_address - 0x00418) >> 3] = (char) val;
3151 malta_fpga_update_display(&malta_display);
3152 break;
3153 default:
3154 MISSING();
3156 } else {
3157 //~ name = "???";
3158 logflag = 0;
3160 logout("addr 0x%08x (???" ") = 0x%08x", addr, val);
3161 MISSING();
3164 if (name != 0) {
3165 TRACE(logflag, logout("addr 0x%08lx (%s) = 0x%08x",
3166 (unsigned long)addr, name, val));
3170 static void io_writeb(void *opaque, hwaddr addr, uint32_t value)
3172 if (0) {
3173 #if !defined(TARGET_WORDS_BIGENDIAN)
3174 } else if (INRANGE(AVALANCHE_VLYNQ0_BASE + VLYNQ_CTRL, 4) ||
3175 INRANGE(AVALANCHE_GPIO_BASE, av.gpio)) {
3176 uint32_t oldvalue = ar7_io_memread(opaque, addr & ~3);
3177 //~ logout("??? addr=0x" TARGET_FMT_plx ", val=0x%02x", addr, value);
3178 oldvalue &= ~(0xff << (8 * (addr & 3)));
3179 value = oldvalue + ((value & 0xff) << (8 * (addr & 3)));
3180 ar7_io_memwrite(opaque, addr & ~3, value);
3181 } else if (addr & 3) {
3182 ar7_io_memwrite(opaque, addr & ~3, value);
3183 logout("addr=0x" TARGET_FMT_plx ", val=0x%02x", addr, value);
3184 UNEXPECTED();
3185 } else if (INRANGE(AVALANCHE_UART0_BASE, av.uart0)) {
3186 ar7_io_memwrite(opaque, addr, value);
3187 } else if (INRANGE(AVALANCHE_UART1_BASE, av.uart1)) {
3188 ar7_io_memwrite(opaque, addr, value);
3189 } else {
3190 ar7_io_memwrite(opaque, addr, value);
3191 logout("??? addr=0x" TARGET_FMT_plx ", val=0x%02x", addr, value);
3192 //~ UNEXPECTED();
3194 #else
3195 } else {
3196 ar7_io_memwrite(opaque, addr, value);
3197 logout("??? addr=0x" TARGET_FMT_plx ", val=0x%02x", addr, value);
3198 MISSING();
3200 #endif
3201 //~ cpu_outb(NULL, addr & 0xffff, value);
3204 static uint32_t io_readb(void *opaque, hwaddr addr)
3206 uint32_t value = ar7_io_memread(opaque, addr & ~3);
3207 if (0) {
3208 #if !defined(TARGET_WORDS_BIGENDIAN)
3209 } else if (INRANGE(AVALANCHE_BBIF_BASE, av.bbif)) {
3210 value >>= (addr & 3) * 8;
3211 value &= 0xff;
3212 logout("??? addr=0x" TARGET_FMT_plx ", val=0x%02x", addr, value);
3213 } else if (INRANGE(AVALANCHE_GPIO_BASE, av.gpio)) {
3214 value >>= ((addr & 3) * 8);
3215 value &= 0xff;
3216 //~ logout("??? addr=0x%08x, val=0x%02x", addr, value);
3217 } else if (INRANGE(AVALANCHE_CLOCK_BASE, av.clock_control)) {
3218 value = clock_read((addr & ~3) - AVALANCHE_CLOCK_BASE);
3219 value >>= ((addr & 3) * 8);
3220 value &= 0xff;
3221 } else if (addr & 3) {
3222 logout("addr=0x" TARGET_FMT_plx ", val=0x%02x", addr, value);
3223 UNEXPECTED();
3224 } else if (INRANGE(AVALANCHE_UART0_BASE, av.uart0)) {
3225 } else if (INRANGE(AVALANCHE_UART1_BASE, av.uart1)) {
3226 } else if (INRANGE(AVALANCHE_UART1_BASE, av.uart1)) {
3227 } else {
3228 logout("addr=0x" TARGET_FMT_plx ", val=0x%02x", addr, value & 0xff);
3229 UNEXPECTED();
3231 #else
3232 } else {
3233 logout("addr=0x" TARGET_FMT_plx ", val=0x%02x", addr, value & 0xff);
3234 MISSING();
3236 #endif
3237 value &= 0xff;
3238 return value;
3241 static void io_writew(void *opaque, hwaddr addr, uint32_t value)
3243 if (0) {
3244 } else {
3245 logout("??? addr=0x" TARGET_FMT_plx ", val=0x%04x", addr, value);
3246 switch (addr & 3) {
3247 #if !defined(TARGET_WORDS_BIGENDIAN)
3248 case 0:
3249 ar7_io_memwrite(opaque, addr, value);
3250 break;
3251 case 2:
3252 value <<= 16;
3253 //~ UNEXPECTED();
3254 ar7_io_memwrite(opaque, addr - 2, value);
3255 break;
3256 #else
3257 case 0:
3258 MISSING();
3259 break;
3260 #endif
3261 default:
3262 assert(0);
3267 static uint32_t io_readw(void *opaque, hwaddr addr)
3269 uint32_t value = ar7_io_memread(opaque, addr & ~3);
3270 if (0) {
3271 } else {
3272 switch (addr & 3) {
3273 #if !defined(TARGET_WORDS_BIGENDIAN)
3274 case 0:
3275 value &= 0xffff;
3276 break;
3277 case 2:
3278 value >>= 16;
3279 break;
3280 #else
3281 case 0:
3282 MISSING();
3283 break;
3284 #endif
3285 default:
3286 assert(0);
3288 TRACE(OTHER, logout("addr=0x" TARGET_FMT_plx ", val=0x%04x", addr, value));
3290 return value;
3293 static uint64_t ar7_read(void *opaque, hwaddr addr, unsigned size)
3295 AR7State *s = opaque;
3296 uint64_t value = 0;
3297 addr += 0x1000;
3298 switch (size) {
3299 case 1:
3300 value = io_readb(s, addr);
3301 break;
3302 case 2:
3303 value = io_readw(s, addr);
3304 break;
3305 case 4:
3306 value = ar7_io_memread(s, addr);
3307 break;
3308 default:
3309 assert(!"unexpected");
3311 return value;
3314 static void ar7_write(void *opaque, hwaddr addr, uint64_t value,
3315 unsigned size)
3317 AR7State *s = opaque;
3318 addr += 0x1000;
3319 switch (size) {
3320 case 1:
3321 io_writeb(s, addr, value);
3322 break;
3323 case 2:
3324 io_writew(s, addr, value);
3325 break;
3326 case 4:
3327 ar7_io_memwrite(s, addr, value);
3328 break;
3329 default:
3330 assert(!"unexpected");
3334 static const MemoryRegionOps ar7_io_ops = {
3335 .read = ar7_read,
3336 .write = ar7_write,
3337 .endianness = DEVICE_NATIVE_ENDIAN,
3338 .valid = {
3339 .min_access_size = 1,
3340 .max_access_size = 4
3344 static void ar7_serial_init(CPUMIPSState * env)
3346 /* By default, QEMU only opens one serial console.
3347 * In this case we open a second console here because
3348 * we need it for full hardware emulation.
3350 unsigned uart_index;
3351 #if 1
3352 assert(serial_hd(1));
3353 #else
3354 if (serial_hd(1) == NULL) {
3355 /* TODO: This code no longer works. Remove or replace. */
3356 serial_hd(1) = qemu_chr_new("serial1", "vc:80Cx24C");
3358 #endif
3359 for (uart_index = 0; uart_index < 2; uart_index++) {
3360 ar7->serial[uart_index] = serial_mm_init(get_system_memory(),
3361 uart_base[uart_index], 2,
3362 AR7_PRIMARY_IRQ(uart_interrupt[uart_index]), io_frequency,
3363 serial_hd(uart_index), DEVICE_NATIVE_ENDIAN);
3364 serial_set_frequency(ar7->serial[uart_index], io_frequency / 16);
3367 /* Set special init values. */
3368 serial_mm_write(ar7->serial[0], AVALANCHE_UART0_BASE + (5 << 2), 0x20, 1);
3371 static int ar7_nic_can_receive(NetClientState *ncs)
3373 CpmacState *s = qemu_get_nic_opaque(ncs);
3374 int enabled = (reg_read(s->addr, CPMAC_RXCONTROL) & RXCONTROL_RXEN) != 0;
3376 TRACE(CPMAC, logout("cpmac%u, enabled %d", s->index, enabled));
3378 return enabled;
3381 static ssize_t ar7_nic_receive(NetClientState *ncs,
3382 const uint8_t *buf, size_t size)
3384 CpmacState *s = qemu_get_nic_opaque(ncs);
3385 uint8_t *cpmac = s->addr;
3386 uint32_t rxmbpenable = reg_read(cpmac, CPMAC_RXMBPENABLE);
3387 uint32_t rxmaxlen = reg_read(cpmac, CPMAC_RXMAXLEN);
3388 unsigned channel = 0xff;
3389 uint32_t flags = 0;
3391 if (!(reg_read(cpmac, CPMAC_MACCONTROL) & MACCONTROL_GMIIEN)) {
3392 TRACE(CPMAC, logout("cpmac%u MII is disabled, frame ignored",
3393 s->index));
3394 return -1;
3395 } else if (!(reg_read(cpmac, CPMAC_RXCONTROL) & RXCONTROL_RXEN)) {
3396 TRACE(CPMAC, logout("cpmac%u receiver is disabled, frame ignored",
3397 s->index));
3398 return -1;
3401 TRACE(RXTX,
3402 logout("cpmac%u received %u byte: %s", s->index, (unsigned)size,
3403 dump(buf, size)));
3405 assert(!(rxmbpenable & RXMBPENABLE_RXPASSCRC));
3406 assert(!(rxmbpenable & RXMBPENABLE_RXQOSEN));
3407 //~ assert(!(rxmbpenable & RXMBPENABLE_RXNOCHAIN));
3408 assert(!(rxmbpenable & RXMBPENABLE_RXCMEMFEN));
3409 assert(!(rxmbpenable & RXMBPENABLE_RXCEFEN));
3410 assert(reg_read(cpmac, CPMAC_RXBUFFEROFFSET) == 0);
3412 /* Received a packet. */
3413 static const uint8_t broadcast_macaddr[6] =
3414 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
3416 if ((rxmbpenable & RXMBPENABLE_RXBROADEN) && !memcmp(buf, broadcast_macaddr, 6)) {
3417 channel = ((rxmbpenable & RXMBPENABLE_RXBROADCH) >> 8);
3418 statusreg_inc(s, CPMAC_RXBROADCASTFRAMES);
3419 TRACE(CPMAC, logout("broadcast to channel %d", channel));
3420 } else if ((rxmbpenable & RXMBPENABLE_RXMULTEN) && (buf[0] & 0x01)) {
3421 // !!! must check MACHASH1, MACHASH2
3422 channel = ((rxmbpenable & RXMBPENABLE_RXMULTCH) >> 0);
3423 statusreg_inc(s, CPMAC_RXMULTICASTFRAMES);
3424 TRACE(CPMAC, logout("multicast to channel %d", channel));
3425 } else if (!memcmp(buf, s->conf.macaddr.a, 6)) {
3426 channel = 0;
3427 TRACE(CPMAC, logout("my address to channel %d", channel));
3428 } else if (rxmbpenable & RXMBPENABLE_RXCAFEN) {
3429 channel = ((rxmbpenable & RXMBPENABLE_RXPROMCH) >> 16);
3430 //~ statusreg_inc(s, CPMAC_RXMULTICASTFRAMES);
3431 TRACE(CPMAC, logout("promiscuous to channel %d", channel));
3432 flags |= RCB_NOMATCH;
3433 } else {
3434 TRACE(CPMAC, logout("unknown address, frame ignored"));
3435 return -1;
3438 /* !!! check handling of short and long frames */
3439 if (size < 64) {
3440 TRACE(CPMAC, logout("short frame, flag = 0x%x",
3441 rxmbpenable & RXMBPENABLE_RXCSFEN));
3442 statusreg_inc(s, CPMAC_RXUNDERSIZEDFRAMES);
3443 flags |= RCB_UNDERSIZED;
3444 } else if (size > rxmaxlen) {
3445 statusreg_inc(s, CPMAC_RXOVERSIZEDFRAMES);
3446 flags |= RCB_OVERSIZE;
3449 statusreg_inc(s, CPMAC_RXGOODFRAMES);
3451 assert(channel < 8);
3453 /* Get descriptor pointer and process the received frame. */
3454 uint32_t dp = reg_read(cpmac, CPMAC_RX0HDP + 4 * channel);
3455 if (dp == 0) {
3456 TRACE(RXTX, logout("no buffer available, frame ignored"));
3457 } else {
3458 cpphy_rcb_t rcb;
3459 cpu_physical_memory_read(dp, (uint8_t *) & rcb, sizeof(rcb));
3460 uint32_t addr = le32_to_cpu(rcb.buff);
3461 uint32_t length = le32_to_cpu(rcb.length);
3462 uint32_t mode = le32_to_cpu(rcb.mode);
3463 TRACE(CPMAC,
3464 logout
3465 ("buffer 0x%08x, next 0x%08x, buff 0x%08x, params 0x%08x, len 0x%08x",
3466 dp, (unsigned)rcb.next, addr, mode, length));
3467 if (mode & RCB_OWNER) {
3468 assert(length >= size);
3469 mode &= ~(RCB_OWNER);
3470 mode &= ~(BITS(15, 0));
3471 mode |= (size & BITS(15, 0));
3472 mode |= RCB_SOP | RCB_EOP;
3473 if (rcb.next == 0) {
3474 TRACE(CPMAC, logout("last buffer"));
3475 mode |= RCB_EOQ;
3477 mode |= RCB_PASSCRC;
3478 mode |= flags;
3479 rcb.length = cpu_to_le32(size);
3480 rcb.mode = cpu_to_le32(mode);
3481 cpu_physical_memory_write(addr, buf, size);
3482 cpu_physical_memory_write(dp, (uint8_t *) & rcb, sizeof(rcb));
3483 reg_write(cpmac, CPMAC_RX0HDP + 4 * channel, rcb.next);
3484 reg_write(cpmac, CPMAC_RX0CP + 4 * channel, dp);
3485 reg_set(cpmac, CPMAC_RXINTSTATRAW, BIT(channel));
3486 #if defined(CONFIG_AR7_EMAC)
3487 reg_set(cpmac, CPMAC_MACINVECTOR, channel << 8);
3488 #endif
3489 emac_update_interrupt(s);
3490 } else {
3491 logout("buffer not free, frame ignored");
3494 return size;
3497 static void ar7_nic_set_link_status(NetClientState *ncs)
3499 //~ CpmacState *s = qemu_get_nic_opaque(ncs);
3500 logout("%s:%u", __FILE__, __LINE__);
3501 MISSING();
3503 #if 0
3504 uint32_t old_status = s->mac_reg[STATUS];
3506 if (nc->link_down) {
3507 s->mac_reg[STATUS] &= ~E1000_STATUS_LU;
3508 } else {
3509 s->mac_reg[STATUS] |= E1000_STATUS_LU;
3512 if (s->mac_reg[STATUS] != old_status) {
3513 set_ics(s, 0, E1000_ICR_LSC);
3515 #endif
3518 static void ar7_nic_cleanup(NetClientState *ncs)
3520 /* TODO: check this code. */
3521 //~ void *d = ncs->opaque;
3522 MISSING();
3524 #if 0
3525 timer_del(d->poll_timer);
3526 timer_free(d->poll_timer);
3527 #endif
3530 static NetClientInfo ar7_net_info = {
3531 .type = NET_CLIENT_DRIVER_NIC,
3532 .size = sizeof(NICState),
3533 .can_receive = ar7_nic_can_receive,
3534 .receive = ar7_nic_receive,
3535 .link_status_changed = ar7_nic_set_link_status,
3536 .cleanup = ar7_nic_cleanup,
3539 static void ar7_nic_init(void)
3541 unsigned i;
3542 unsigned n = 0;
3543 TRACE(CPMAC, logout(""));
3544 for (i = 0; i < nb_nics; i++) {
3545 NICInfo *nd = &nd_table[i];
3546 if (nd->used) {
3547 TRACE(CPMAC, logout("starting AR7 nic CPMAC%u", n));
3548 qemu_check_nic_model(nd, "ar7");
3549 if (n < 2) {
3550 DeviceState *dev = qdev_create(NULL, TYPE_CPMAC_STATE);
3551 CpmacState *s = CPMAC_STATE(dev);
3552 qdev_set_nic_properties(dev, nd);
3553 qdev_init_nofail(dev);
3554 sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
3555 ar7->primary_irq[cpmac_interrupt[n]]);
3556 s->addr = (n == 0) ? av.cpmac0 : av.cpmac1;
3557 s->index = n;
3558 ar7->cpmac[n] = s;
3559 n++;
3563 phy_init();
3566 static int ar7_display_can_receive(void *opaque)
3568 //~ logout("%p", opaque);
3569 return 1;
3572 static void ar7_display_receive(void *opaque, const uint8_t *buf, int size)
3574 //~ logout("%p, %d bytes (0x%02x)", opaque, size, buf[0]);
3575 if (buf[0] == 'r') {
3576 uint32_t in = reg_read(av.gpio, GPIO_IN);
3577 reg_write(av.gpio, GPIO_IN, in ^ 0x00000800);
3578 ar7_gpio_display();
3579 } else if (buf[0] == 'R') {
3580 uint32_t in = reg_read(av.gpio, GPIO_IN);
3581 reg_write(av.gpio, GPIO_IN, in & ~0x00000800);
3582 ar7_gpio_display();
3586 static void ar7_display_event(void *opaque, int event)
3588 /* TODO: what should we do here? */
3589 /* Wird gleich am Anfang mit (NULL, 2) aufgerufen. */
3590 TRACE(OTHER, logout("%p, %d", opaque, event));
3591 //~ if (event == CHR_EVENT_BREAK)
3592 AR7State *s = opaque;
3594 if (event == CHR_EVENT_OPENED && !s->gpio_display_inited) {
3595 CharBackend *chr = &s->gpio_display;
3596 qemu_chr_fe_printf(chr,
3597 "\e[1;1HGPIO Status"
3598 "\e[2;1H0 1 2 3"
3599 "\e[3;1H01234567890123456789012345678901"
3600 "\e[10;1H* lan * wlan * online * dsl * power"
3601 "\e[12;1HPress 'r' to toggle the reset button");
3602 ar7_gpio_display();
3603 s->gpio_display_inited = true;
3607 static void malta_fpga_display_event(void *opaque, int event)
3609 MaltaFPGAState *s = opaque;
3610 CharBackend *chr = &s->display;
3611 if (event == CHR_EVENT_OPENED && !s->display_inited) {
3612 qemu_chr_fe_printf(chr, "\e[HMalta LEDBAR\r\n");
3613 qemu_chr_fe_printf(chr, "+--------+\r\n");
3614 qemu_chr_fe_printf(chr, "+ +\r\n");
3615 qemu_chr_fe_printf(chr, "+--------+\r\n");
3616 qemu_chr_fe_printf(chr, "\n");
3617 qemu_chr_fe_printf(chr, "Malta ASCII\r\n");
3618 qemu_chr_fe_printf(chr, "+--------+\r\n");
3619 qemu_chr_fe_printf(chr, "+ +\r\n");
3620 qemu_chr_fe_printf(chr, "+--------+\r\n");
3622 s->display_inited = true;
3624 /* Select 1st serial console as default (because we don't have VGA). */
3625 console_select(1);
3629 static void ar7_display_init(CPUMIPSState *env)
3631 Chardev *chr;
3633 chr = qemu_chr_new("gpio", "vc:400x300");
3634 qemu_chr_fe_init(&ar7->gpio_display, chr, NULL);
3635 qemu_chr_fe_set_handlers(&ar7->gpio_display, ar7_display_can_receive,
3636 ar7_display_receive, ar7_display_event, NULL, ar7,
3637 NULL, true);
3639 chr = qemu_chr_new("led-display", "vc:320x200");
3640 qemu_chr_fe_init(&malta_display.display , chr, NULL);
3641 qemu_chr_fe_set_handlers(&malta_display.display, NULL, NULL,
3642 malta_fpga_display_event, NULL, &malta_display,
3643 NULL, true);
3646 static void ar7_reset(DeviceState *d)
3648 /* TODO: fix code. */
3649 //~ AR7State *s = AR7_STATE(d);
3650 //~ CPUMIPSState *env = opaque;
3651 logout("%s:%u", __FILE__, __LINE__);
3652 //~ env->exception_index = EXCP_RESET;
3653 //~ env->exception_index = EXCP_SRESET;
3654 //~ mips_cpu_do_interrupt(env);
3655 //~ env->CP0_Cause |= 0x00000400;
3656 //~ cpu_interrupt(env, CPU_INTERRUPT_RESET);
3659 static void ar7_init(AR7State *s, CPUMIPSState *env)
3661 MemoryRegion *system_memory = get_system_memory();
3662 //~ hwaddr addr = (0x08610000 & 0xffff);
3663 //~ unsigned offset;
3664 memory_region_init_io(&s->mmio, OBJECT(s), &ar7_io_ops, s,
3665 "ar7.io", 0x0ffff000);
3666 memory_region_add_subregion(system_memory, 0x00001000, &s->mmio);
3667 // TODO: i/o starting at 0x1e000000, 0x01c00000 bytes.
3669 //~ reg_write(av.gpio, GPIO_IN, 0x0cbea075);
3670 reg_write(av.gpio, GPIO_IN, 0x0cbea875);
3671 //~ reg_write(av.gpio, GPIO_OUT, 0x00000000);
3672 reg_write(av.gpio, GPIO_DIR, UINT32_MAX);
3673 reg_write(av.gpio, GPIO_ENABLE, UINT32_MAX);
3674 reg_write(av.gpio, GPIO_CVR, 0x00020000 + AR7_CHIP_DEFAULT);
3675 reg_write(av.gpio, GPIO_DIDR1, 0x7106150d);
3676 reg_write(av.gpio, GPIO_DIDR2, 0xf52ccccf);
3677 reg_write(av.gpio, GPIO_TITAN, TITAN_CHIP_DEFAULT);
3679 //~ .mdio = {0x00, 0x07, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff}
3680 #if defined(CONFIG_AR7_EMAC)
3681 reg_write(av.mdio, MDIO_VERSION, 0x00070101);
3682 #else
3683 reg_write(av.mdio, MDIO_VERSION, 0x00070103);
3684 #endif
3685 reg_write(av.mdio, MDIO_CONTROL, MDIO_CONTROL_IDLE | BIT(24) | BITS(7, 0));
3687 //~ .reset_control = { 0x04720043 }
3689 //~ .dcl = 0x025d4297
3690 reg_write(av.dcl, DCL_BOOT_CONFIG, 0x025d4291);
3691 if (first_cpu->bigendian) {
3692 reg_set(av.dcl, DCL_BOOT_CONFIG, CONFIG_ENDIAN);
3694 ar7->vlynq[0] = av.vlynq0;
3695 ar7->vlynq[1] = av.vlynq1;
3697 ar7_serial_init(env);
3698 ar7_display_init(env);
3699 ar7_nic_init();
3701 //~ for (offset = 0; offset < 0x2800; offset += 0x100) {
3702 //~ if (offset == 0xe00) continue;
3703 //~ if (offset == 0xf00) continue;
3704 //~ register_ioport_read(addr + offset, 0x100, 1, ar7_io_memread, 0);
3705 //~ register_ioport_read(addr + offset, 0x100, 2, ar7_io_memread, 0);
3706 //~ register_ioport_read(addr + offset, 0x100, 4, ar7_io_memread, 0);
3707 //~ register_ioport_write(addr + offset, 0x100, 1, ar7_io_memwrite, 0);
3708 //~ register_ioport_write(addr + offset, 0x100, 2, ar7_io_memwrite, 0);
3709 //~ register_ioport_write(addr + offset, 0x100, 4, ar7_io_memwrite, 0);
3710 //~ }
3711 // TODO: i/o starting at 0x08610000, 0x2000 bytes.
3714 /* Kernel */
3715 static void kernel_load(CPUMIPSState *env)
3717 uint64_t kernel_addr = 0;
3718 uint64_t kernel_low, kernel_high;
3719 int kernel_size;
3720 kernel_size = load_elf(loaderparams.kernel_filename,
3721 cpu_mips_kseg0_to_phys, NULL,
3722 &kernel_addr, &kernel_low, &kernel_high,
3723 first_cpu->bigendian, EM_MIPS, 1, 0);
3724 if (kernel_size < 0) {
3725 kernel_size = load_image_targphys(loaderparams.kernel_filename,
3726 KERNEL_LOAD_ADDR,
3727 loaderparams.ram_size);
3728 kernel_addr = K1(KERNEL_LOAD_ADDR);
3730 if (kernel_size > 0 && kernel_size < loaderparams.ram_size) {
3731 warn_report("elf kernel '%s' with start address 0x%08" PRIx64
3732 " and size %d bytes",
3733 loaderparams.kernel_filename, kernel_addr, kernel_size);
3734 warn_report("kernel low 0x%08" PRIx64 ", high 0x%08" PRIx64,
3735 kernel_low, kernel_high);
3736 loaderparams.kernel_addr = kernel_addr;
3737 } else {
3738 warn_report("could not load kernel '%s'",
3739 loaderparams.kernel_filename);
3740 exit(1);
3744 static void kernel_init(CPUMIPSState *env)
3746 env->active_tc.PC = loaderparams.kernel_addr;
3748 /* a0 = argc, a1 = argv, a2 = envp */
3749 env->active_tc.gpr[4] = 0;
3750 env->active_tc.gpr[5] = K1(INITRD_LOAD_ADDR);
3751 env->active_tc.gpr[6] = K1(INITRD_LOAD_ADDR);
3753 /* Set SP (needed for some kernels) - normally set by bootloader. */
3754 env->active_tc.gpr[29] = env->active_tc.PC + loaderparams.ram_size - 0x1000;
3756 /* TODO: use code from Malta for command line setup. */
3757 if (loaderparams.kernel_cmdline && *loaderparams.kernel_cmdline) {
3758 /* Load kernel parameters (argv, envp) from file. */
3759 #if 0 // TBD
3760 // TODO: use cpu_physical_memory_write(bdloc, (void *)kernel_cmdline, len + 1)
3761 uint8_t *address = qemu_get_ram_ptr(INITRD_LOAD_ADDR - KERNEL_LOAD_ADDR);
3762 int argc;
3763 uint32_t *argv;
3764 uint32_t *arg0;
3765 target_ulong size = load_image_targphys(loaderparams.kernel_cmdline,
3766 KERNEL_LOAD_ADDR, loaderparams.ram_size);
3767 target_ulong i;
3768 if (size == (target_ulong) -1) {
3769 error_report("could not load kernel parameters '%s'",
3770 loaderparams.kernel_cmdline);
3771 exit(1);
3773 /* Replace all linefeeds by null bytes. */
3774 for (i = 0; i < size; i++) {
3775 uint8_t c = address[i];
3776 if (c == '\n') {
3777 address[i] = '\0';
3780 /* Terminate data with a null byte. */
3781 address[size] = '\0';
3782 /* Build argv and envp vectors (behind data). */
3783 argc = 0;
3784 i = ((i + 3) & ~3);
3785 argv = (uint32_t *)(address + i);
3786 env->active_tc.gpr[5] = K1(INITRD_LOAD_ADDR + i);
3787 arg0 = argv;
3788 *argv = (uint32_t)K1(INITRD_LOAD_ADDR);
3789 for (i = 0; i < size;) {
3790 uint8_t c = address[i++];
3791 if (c == '\0') {
3792 *++argv = (uint32_t)K1(INITRD_LOAD_ADDR + i);
3793 if (address[i] == '\0' && argc == 0) {
3794 argc = argv - arg0;
3795 *argv = 0;
3796 env->active_tc.gpr[4] = argc;
3797 env->active_tc.gpr[6] = env->active_tc.gpr[5] + 4 * (argc + 1);
3801 #else
3802 error_report("missing code for command line parameters '%s'",
3803 loaderparams.kernel_cmdline);
3804 exit(1);
3805 #endif
3809 static void ar7_mips_init(CPUMIPSState *env)
3811 #if !defined(UR8)
3812 /* AR7 cpu revision is 2.2. */
3813 env->CP0_PRid |= 0x48;
3814 #else
3815 /* UR8 cpu revision is 6.8. */
3816 env->CP0_PRid |= 0x68;
3817 #endif
3819 /* Special configuration bits set by external hw inputs. */
3820 env->CP0_Config0 |= (0x2 << CP0C0_MM);
3821 env->CP0_Config0 |= (1 << CP0C0_SB);
3822 /* 256 instruction cache sets. */
3823 env->CP0_Config1 |= (0x2 << CP0C1_IS);
3824 /* 4-way instruction cache associativity. */
3825 env->CP0_Config1 |= (0x3 << CP0C1_IA);
3826 /* 256 data cache sets. */
3827 env->CP0_Config1 |= (0x2 << CP0C1_DS);
3828 /* 4-way data cache associativity. */
3829 env->CP0_Config1 |= (0x3 << CP0C1_DA);
3831 /* Compare selected emulation values to original hardware registers. */
3832 if ((env->CP0_PRid & ~0x68) != 0x00018400) {
3833 printf("CP0_PRid = 0x%08x\n", env->CP0_PRid);
3835 if (env->CP0_Config0 != 0x80240082 + (first_cpu->bigendian ? (1 << CP0C0_BE) : 0)) {
3836 printf("CP0_Config0 = 0x%08x\n", env->CP0_Config0);
3838 if (env->CP0_Config1 != 0x9e9b4d8a) {
3839 printf("CP0_Config1 = 0x%08x\n", env->CP0_Config1);
3841 if (env->CP0_Config2 != 0x80000000) {
3842 printf("CP0_Config2 = 0x%08x\n", env->CP0_Config2);
3844 assert(env->CP0_Config1 == 0x9e9b4d8a);
3845 assert(env->CP0_Config2 == 0x80000000);
3846 assert(env->CP0_Config3 == 0x00000000);
3849 static void main_cpu_reset(void *opaque)
3851 CPUMIPSState *env = opaque;
3852 ar7_mips_init(env);
3853 /* AR7 is MIPS32 release 1. */
3854 assert(!(env->CP0_Config0 & (7 << CP0C0_AR)));
3855 /* AR7 has no FPU. */
3856 assert(!(env->CP0_Config1 & (1 << CP0C1_FP)));
3858 if (loaderparams.kernel_filename) {
3859 kernel_init(env);
3863 static void ar7_common_init(MachineState *machine,
3864 uint16_t flash_manufacturer, uint16_t flash_type,
3865 int flash_size)
3867 char *filename;
3868 MIPSCPU *cpu;
3869 CPUMIPSState *env;
3870 AR7State *s;
3871 DeviceState *dev;
3872 DriveInfo *dinfo;
3873 BlockBackend *flash_driver = NULL;
3874 MemoryRegion *system_memory = get_system_memory();
3875 int rom_size;
3876 #if defined(CONFIG_VLYNQ) // TODO
3877 VLYNQBus *vlynq_bus0;
3878 VLYNQBus *vlynq_bus1;
3879 #endif
3881 #if defined(DEBUG_AR7)
3882 set_traceflags();
3883 #endif
3885 if (machine->ram_size > 192 * MiB) {
3886 /* The external RAM start at 0x14000000 and ends before 0x20000000. */
3887 machine->ram_size = 192 * MiB;
3890 /* Initialize CPU. */
3891 if (machine->cpu_type == NULL) {
3892 #ifdef MIPS_HAS_MIPS64
3893 # error AR7 has a 32 bit CPU
3894 #endif
3895 machine->cpu_type = MIPS_CPU_TYPE_NAME("4KEcR1");
3897 cpu = MIPS_CPU(cpu_create(machine->cpu_type));
3898 env = &cpu->env;
3900 qemu_register_reset(main_cpu_reset, env);
3902 dev = qdev_create(NULL, TYPE_AR7_STATE);
3903 //~ qdev_prop_set_uint32(dev, "memsz", machine->ram_size / MiB);
3904 qdev_prop_set_uint8(dev, "phy addr", 31);
3905 qdev_prop_set_uint8(dev, "vlynq tnetw1130", 0);
3906 qdev_init_nofail(dev);
3907 ar7 = s = AR7_STATE(dev);
3909 #if defined(CONFIG_VLYNQ) // TODO
3910 vlynq_bus0 = vlynq_create_bus(dev, "vlynq0");
3911 vlynq_bus1 = vlynq_create_bus(dev, "vlynq1");
3912 vlynq_create_slave(vlynq_bus0, "tnetw1130-vlynq");
3913 (void)vlynq_bus1;
3914 #endif
3916 loaderparams.ram_size = machine->ram_size;
3917 loaderparams.kernel_filename = machine->kernel_filename;
3918 loaderparams.kernel_cmdline = machine->kernel_cmdline;
3919 loaderparams.initrd_filename = machine->initrd_filename;
3921 memory_region_init_ram(&s->ram, OBJECT(s), "ar7.ram",
3922 machine->ram_size, &error_abort);
3923 memory_region_add_subregion(system_memory, KERNEL_LOAD_ADDR, &s->ram);
3924 warn_report("%s: ram_size = 0x" RAM_ADDR_FMT,
3925 __func__, machine->ram_size);
3927 /* The AR7 processor has 4 KiB internal RAM at physical address 0x00000000. */
3928 memory_region_init_ram(&s->internal_ram, OBJECT(s), "ar7.internal",
3929 4 * KiB, &error_abort);
3930 memory_region_add_subregion(system_memory, 0, &s->internal_ram);
3932 /* Try to load a BIOS image. If this fails, we continue regardless,
3933 but initialize the hardware ourselves. When a kernel gets
3934 preloaded we also initialize the hardware, since the BIOS wasn't
3935 run. */
3936 dinfo = drive_get(IF_PFLASH, 0, 0);
3937 if (dinfo) {
3938 int64_t image_size = blk_getlength(blk_by_legacy_dinfo(dinfo));
3939 if (image_size > 0) {
3940 flash_driver = blk_by_legacy_dinfo(dinfo);
3941 flash_size = image_size;
3944 pflash_device_register(FLASH_ADDR, NULL, "ar7.flash",
3945 flash_size, flash_driver, 2,
3946 flash_manufacturer, flash_type,
3947 first_cpu->bigendian);
3948 if (!dinfo) {
3949 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "flashimage.bin");
3950 if (filename) {
3951 flash_size = load_image_targphys(filename, FLASH_ADDR, flash_size);
3952 g_free(filename);
3955 warn_report("%s: load BIOS '%s', size %d",
3956 __func__, "flashimage.bin", flash_size);
3958 /* The AR7 processor has 4 KiB internal ROM at physical address 0x1fc00000. */
3959 memory_region_init_ram(&s->rom, OBJECT(s), "ar7.rom",
3960 4 * KiB, &error_abort);
3961 memory_region_set_readonly(&s->rom, true);
3962 memory_region_add_subregion(system_memory, PROM_ADDR, &s->rom);
3963 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "mips_bios.bin");
3964 rom_size = load_image_targphys(filename, PROM_ADDR, 4 * KiB);
3965 g_free(filename);
3966 if ((rom_size > 0) && (rom_size <= 4 * KiB)) {
3967 warn_report("%s: load BIOS '%s', size %d", __func__, "mips_bios.bin", rom_size);
3968 } else {
3969 /* Not fatal, write a jump to address 0xb0000000 into memory. */
3970 static const uint8_t jump[] = {
3971 /* lui t9,0xb000; jr t9 */
3972 0x00, 0xb0, 0x19, 0x3c, 0x08, 0x00, 0x20, 0x03
3974 warn_report("could not load MIPS bios 'mips_bios.bin'");
3975 warn_report("QEMU added a jump instruction to flash start");
3976 cpu_physical_memory_write_rom(&address_space_memory, PROM_ADDR, jump, sizeof(jump));
3977 rom_size = 4 * KiB;
3980 if (machine->kernel_filename) {
3981 kernel_load(env);
3982 kernel_init(env);
3985 /* Init internal devices */
3986 cpu_mips_irq_init_cpu(cpu);
3987 cpu_mips_clock_init(cpu);
3989 /* Interrupt controller */
3990 /* The 8259 is attached to the MIPS CPU INT0 pin, ie interrupt 2 */
3991 //~ i8259 = i8259_init(env->irq[2]);
3993 ar7->primary_irq =
3994 qemu_allocate_irqs(ar7_primary_irq, env, NUM_PRIMARY_IRQS);
3995 ar7->secondary_irq =
3996 qemu_allocate_irqs(ar7_secondary_irq, env, NUM_SECONDARY_IRQS);
3998 ar7->wd_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &watchdog_cb, env);
3999 ar7->timer[0].qemu_timer =
4000 timer_new_ns(QEMU_CLOCK_VIRTUAL, &timer_cb, &ar7->timer[0]);
4001 ar7->timer[0].base = av.timer0;
4002 ar7->timer[0].interrupt = AR7_PRIMARY_IRQ(INTERRUPT_TIMER0);
4003 ar7->timer[1].qemu_timer =
4004 timer_new_ns(QEMU_CLOCK_VIRTUAL, &timer_cb, &ar7->timer[1]);
4005 ar7->timer[1].base = av.timer1;
4006 ar7->timer[1].interrupt = AR7_PRIMARY_IRQ(INTERRUPT_TIMER1);
4008 /* Address 31 is the AR7 internal phy. */
4009 ar7->phyaddr = 31;
4011 /* TNETW1130 is connected to VLYNQ0. */
4012 ar7->vlynq_tnetw1130 = 0;
4013 //~ ar7->vlynq_tnetw1130 = 99;
4015 ar7_init(s, env);
4018 static int ar7_sysbus_device_init(SysBusDevice *sysbusdev)
4020 /* TODO */
4021 //~ AR7State *s = AR7_STATE(sysbusdev);
4022 return 0;
4025 static void mips_ar7_init(MachineState *machine)
4027 ar7_common_init(machine, MANUFACTURER_ST, 0x2249, 2 * MiB);
4030 static void ar7_amd_init(MachineState *machine)
4032 ar7_common_init(machine, MANUFACTURER_AMD, AM29LV160DB, 2 * MiB);
4035 static void mips_tnetd7200_init(MachineState *machine)
4037 ar7_common_init(machine, MANUFACTURER_ST, 0x2249, 2 * MiB);
4038 reg_write(av.gpio, GPIO_CVR, 0x0002002b);
4041 static void mips_tnetd7300_init(MachineState *machine)
4043 ar7_common_init(machine, MANUFACTURER_ST, 0x2249, 2 * MiB);
4046 #if defined(TARGET_WORDS_BIGENDIAN)
4048 static void zyxel_init(MachineState *machine)
4050 /* Change the default RAM size from 128 MiB to 8 MiB.
4051 This is the external RAM at physical address KERNEL_LOAD_ADDR.
4052 Any other size can be selected with command line option -m. */
4053 if (machine->ram_size == 128 * MiB) {
4054 machine->ram_size = 8 * MiB;
4056 ar7_common_init(machine, MANUFACTURER_INTEL, I28F160C3B, 2 * MiB);
4059 #else
4061 static void fbox4_init(MachineState *machine)
4063 /* Change the default RAM size from 128 MiB to 32 MiB.
4064 This is the external RAM at physical address KERNEL_LOAD_ADDR.
4065 Any other size can be selected with command line option -m. */
4066 if (machine->ram_size == 128 * MiB) {
4067 machine->ram_size = 32 * MiB;
4069 ar7_common_init(machine, MANUFACTURER_MACRONIX, MX29LV320CT, 4 * MiB);
4072 static void fbox8_init(MachineState *machine)
4074 /* Change the default RAM size from 128 MiB to 32 MiB.
4075 This is the external RAM at physical address KERNEL_LOAD_ADDR.
4076 Any other size can be selected with command line option -m. */
4077 if (machine->ram_size == 128 * MiB) {
4078 machine->ram_size = 32 * MiB;
4080 ar7_common_init(machine, MANUFACTURER_MACRONIX, MX29LV640BT, 8 * MiB);
4083 static void sinus_basic_3_init(MachineState *machine)
4085 /* Change the default RAM size from 128 MiB to 16 MiB.
4086 This is the external RAM at physical address KERNEL_LOAD_ADDR.
4087 Any other size can be selected with command line option -m. */
4088 if (machine->ram_size == 128 * MiB) {
4089 machine->ram_size = 16 * MiB;
4091 ar7_common_init(machine, MANUFACTURER_004A, ES29LV160DB, 2 * MiB);
4094 static void sinus_basic_se_init(MachineState *machine)
4096 /* Change the default RAM size from 128 MiB to 16 MiB.
4097 This is the external RAM at physical address KERNEL_LOAD_ADDR.
4098 Any other size can be selected with command line option -m. */
4099 if (machine->ram_size == 128 * MiB) {
4100 machine->ram_size = 16 * MiB;
4102 ar7_common_init(machine, MANUFACTURER_INTEL, I28F160C3B, 2 * MiB);
4105 static void sinus_se_init(MachineState *machine)
4107 /* Change the default RAM size from 128 MiB to 16 MiB.
4108 This is the external RAM at physical address KERNEL_LOAD_ADDR.
4109 Any other size can be selected with command line option -m. */
4110 if (machine->ram_size == 128 * MiB) {
4111 machine->ram_size = 16 * MiB;
4113 ar7_common_init(machine, MANUFACTURER_INTEL, I28F160C3B, 2 * MiB);
4114 /* Emulate external phy 0. */
4115 ar7->phyaddr = 0;
4118 static void speedport_init(MachineState *machine)
4120 /* Change the default RAM size from 128 MiB to 32 MiB.
4121 This is the external RAM at physical address KERNEL_LOAD_ADDR.
4122 Any other size can be selected with command line option -m. */
4123 if (machine->ram_size == 128 * MiB) {
4124 machine->ram_size = 32 * MiB;
4126 ar7_common_init(machine, MANUFACTURER_MACRONIX, MX29LV320CT, 4 * MiB);
4127 reg_write(av.gpio, GPIO_CVR, 0x0002002b);
4130 #endif
4132 #define RAMSIZE (0 * MiB)
4134 static void ar7_machine_init(MachineClass *mc)
4136 mc->desc = "MIPS 4KEc / AR7 platform";
4137 mc->init = mips_ar7_init;
4138 mc->max_cpus = 1;
4141 DEFINE_MACHINE("ar7", ar7_machine_init)
4143 static void ar7_amd_machine_init(MachineClass *mc)
4145 mc->desc = "MIPS AR7 with AMD flash";
4146 mc->init = ar7_amd_init;
4147 mc->max_cpus = 1;
4150 DEFINE_MACHINE("ar7-amd", ar7_amd_machine_init)
4152 static void tnetd7200_machine_init(MachineClass *mc)
4154 mc->desc = "MIPS 4KEc / TNETD7200 platform";
4155 mc->init = mips_tnetd7200_init;
4156 mc->max_cpus = 1;
4159 DEFINE_MACHINE("tnetd7200", tnetd7200_machine_init)
4161 static void tnetd7300_machine_init(MachineClass *mc)
4163 mc->desc = "MIPS 4KEc / TNETD7300 platform";
4164 mc->init = mips_tnetd7300_init;
4165 mc->max_cpus = 1;
4168 DEFINE_MACHINE("tnetd7300", tnetd7300_machine_init)
4170 #if defined(TARGET_WORDS_BIGENDIAN)
4172 static void zyxel_machine_init(MachineClass *mc)
4174 mc->desc = "Zyxel 2 MiB flash (AR7 platform)";
4175 mc->init = zyxel_init;
4176 mc->max_cpus = 1;
4179 DEFINE_MACHINE("zyxel", zyxel_machine_init)
4181 #else
4183 static void fbox_4mb_machine_init(MachineClass *mc)
4185 mc->desc = "FBox 4 MiB flash (AR7 platform)";
4186 mc->init = fbox4_init;
4187 mc->max_cpus = 1;
4190 DEFINE_MACHINE("fbox-4mb", fbox_4mb_machine_init)
4192 static void fbox_8mb_machine_init(MachineClass *mc)
4194 mc->desc = "FBox 8 MiB flash (AR7 platform)";
4195 mc->init = fbox8_init;
4196 mc->max_cpus = 1;
4199 DEFINE_MACHINE("fbox-8mb", fbox_8mb_machine_init)
4201 static void sinus_basic_se_machine_init(MachineClass *mc)
4203 mc->desc = "Sinus DSL Basic SE (AR7 platform)";
4204 mc->init = sinus_basic_se_init;
4205 mc->max_cpus = 1;
4208 DEFINE_MACHINE("sinus-basic-se", sinus_basic_se_machine_init)
4210 static void sinus_se_machine_init(MachineClass *mc)
4212 mc->desc = "Sinus DSL SE (AR7 platform)";
4213 mc->init = sinus_se_init;
4214 mc->max_cpus = 1;
4217 DEFINE_MACHINE("sinus-se", sinus_se_machine_init)
4219 static void sinus_basic_3_machine_init(MachineClass *mc)
4221 mc->desc = "Sinus DSL Basic 3 (AR7 platform)";
4222 mc->init = sinus_basic_3_init;
4223 mc->max_cpus = 1;
4226 DEFINE_MACHINE("sinus-basic-3", sinus_basic_3_machine_init)
4228 static void speedport_machine_init(MachineClass *mc)
4230 mc->desc = "Speedport (AR7 platform)";
4231 mc->init = speedport_init;
4232 mc->max_cpus = 1;
4235 DEFINE_MACHINE("speedport", speedport_machine_init)
4237 #endif
4239 static const VMStateDescription vmstate_ar7 = {
4240 .name ="ar7",
4241 .version_id = 1,
4242 .minimum_version_id = 1,
4243 .minimum_version_id_old = 1,
4244 .fields = (VMStateField []) {
4245 VMSTATE_UINT32_ARRAY(adsl, ar7_register_t, ARRAY_SIZE(av.adsl)),
4246 VMSTATE_UINT32_ARRAY(bbif, ar7_register_t, ARRAY_SIZE(av.bbif)),
4247 VMSTATE_UINT32_ARRAY(atmsar, ar7_register_t, ARRAY_SIZE(av.atmsar)),
4248 VMSTATE_UINT32_ARRAY(usbslave, ar7_register_t, ARRAY_SIZE(av.usbslave)),
4249 VMSTATE_UINT32_ARRAY(vlynq1region0, ar7_register_t, ARRAY_SIZE(av.vlynq1region0)),
4250 VMSTATE_UINT32_ARRAY(vlynq1region1, ar7_register_t, ARRAY_SIZE(av.vlynq1region1)),
4251 VMSTATE_UINT8_ARRAY(cpmac0, ar7_register_t, ARRAY_SIZE(av.cpmac0)),
4252 VMSTATE_UINT8_ARRAY(cpmac1, ar7_register_t, ARRAY_SIZE(av.cpmac1)),
4253 VMSTATE_UINT8_ARRAY(emif, ar7_register_t, ARRAY_SIZE(av.emif)),
4254 VMSTATE_UINT8_ARRAY(gpio, ar7_register_t, ARRAY_SIZE(av.gpio)),
4255 VMSTATE_UINT8_ARRAY(clock_control, ar7_register_t, ARRAY_SIZE(av.clock_control)),
4256 VMSTATE_UINT32_ARRAY(watchdog, ar7_register_t, ARRAY_SIZE(av.watchdog)),
4257 VMSTATE_UINT8_ARRAY(timer0, ar7_register_t, ARRAY_SIZE(av.timer0)),
4258 VMSTATE_UINT8_ARRAY(timer1, ar7_register_t, ARRAY_SIZE(av.timer1)),
4259 VMSTATE_UINT32_ARRAY(uart0, ar7_register_t, ARRAY_SIZE(av.uart0)),
4260 VMSTATE_UINT32_ARRAY(uart1, ar7_register_t, ARRAY_SIZE(av.uart1)),
4261 VMSTATE_UINT32_ARRAY(usb, ar7_register_t, ARRAY_SIZE(av.usb)),
4262 //~ VMSTATE_UINT32_ARRAY(mc_dma[0], ar7_register_t, ARRAY_SIZE(av.mc_dma) * ARRAY_SIZE(av.mc_dma[0])),
4263 VMSTATE_UINT32_ARRAY(reset_control, ar7_register_t, ARRAY_SIZE(av.reset_control)),
4264 VMSTATE_UINT8_ARRAY(vlynq0, ar7_register_t, ARRAY_SIZE(av.vlynq0)),
4265 VMSTATE_UINT8_ARRAY(vlynq1, ar7_register_t, ARRAY_SIZE(av.vlynq1)),
4266 VMSTATE_UINT8_ARRAY(dcl, ar7_register_t, ARRAY_SIZE(av.dcl)),
4267 VMSTATE_UINT8_ARRAY(mdio, ar7_register_t, ARRAY_SIZE(av.mdio)),
4268 VMSTATE_UINT32_ARRAY(wdt, ar7_register_t, ARRAY_SIZE(av.wdt)),
4269 VMSTATE_UINT8_ARRAY(intc, ar7_register_t, ARRAY_SIZE(av.intc)),
4270 VMSTATE_END_OF_LIST()
4274 static Property ar7_properties[] = {
4275 DEFINE_PROP_UINT8("phy addr", AR7State, phyaddr, 31),
4276 DEFINE_PROP_UINT8("vlynq tnetw1130", AR7State, vlynq_tnetw1130, 0),
4277 DEFINE_PROP_END_OF_LIST()
4280 static void ar7_class_init(ObjectClass *klass, void *data)
4282 DeviceClass *dc = DEVICE_CLASS(klass);
4283 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
4284 dc->desc = "TI TNETD7xxx (AR7)";
4285 dc->props = ar7_properties;
4286 dc->reset = ar7_reset;
4287 dc->vmsd = &vmstate_ar7;
4288 k->init = ar7_sysbus_device_init;
4291 static const TypeInfo ar7_info = {
4292 .name = "ar7",
4293 //~ .alias = "tnetd7xxx",
4294 .parent = TYPE_SYS_BUS_DEVICE,
4295 .instance_size = sizeof(AR7State),
4296 .class_init = ar7_class_init,
4299 static int cpmac_init(SysBusDevice *sbd)
4301 DeviceState *dev = DEVICE(sbd);
4302 CpmacState *s = CPMAC_STATE(dev);
4304 logout("%s:%u", __FILE__, __LINE__);
4306 sysbus_init_irq(sbd, &s->irq);
4307 s->nic = qemu_new_nic(&ar7_net_info, &s->conf,
4308 object_get_typename(OBJECT(dev)), dev->id, s);
4309 return 0;
4312 static const VMStateDescription cpmac_vmsd = {
4313 .name = "ar7-cpmac",
4314 .version_id = 1,
4315 .minimum_version_id = 1,
4316 .minimum_version_id_old = 1,
4317 .fields = (VMStateField[]) {
4318 /* TODO: fill list. */
4319 VMSTATE_END_OF_LIST()
4323 static Property ar7_cpmac_properties[] = {
4324 DEFINE_NIC_PROPERTIES(CpmacState, conf),
4325 DEFINE_PROP_END_OF_LIST()
4328 static void ar7_cpmac_class_init(ObjectClass *klass, void *data)
4330 DeviceClass *dc = DEVICE_CLASS(klass);
4331 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
4332 dc->desc = "TI AR7 CPMAC";
4333 dc->props = ar7_cpmac_properties;
4334 dc->reset = cpmac_reset;
4335 //~ dc->unplug = cpmac_unplug;
4336 dc->vmsd = &cpmac_vmsd;
4337 k->init = cpmac_init;
4338 //~ k->exit = cpmac_exit;
4341 static const TypeInfo ar7_cpmac_info = {
4342 .name = "ar7-cpmac",
4343 .parent = TYPE_SYS_BUS_DEVICE,
4344 //~ .alias = "cpmac",
4345 .instance_size = sizeof(CpmacState),
4346 .class_init = ar7_cpmac_class_init
4349 static void ar7_register_types(void)
4351 type_register_static(&ar7_info);
4352 type_register_static(&ar7_cpmac_info);
4355 type_init(ar7_register_types);
4357 /* eof */