From 5bfe8f17d918d1c19306c857a6415e44c7d8fb4c Mon Sep 17 00:00:00 2001 From: marcan Date: Wed, 18 Mar 2009 18:05:23 +0100 Subject: [PATCH] Clean up hollywood, IRQ, IPC, match Wiibrew --- hollywood.h | 67 +++++------------------------------------------------ ipc.c | 35 +++++++++++++++++++++------- irq.c | 36 ++++++++++++++-------------- 3 files changed, 51 insertions(+), 87 deletions(-) diff --git a/hollywood.h b/hollywood.h index e38695c..b555cd6 100644 --- a/hollywood.h +++ b/hollywood.h @@ -7,74 +7,19 @@ #define HW_REG_BASE 0xd800000 // The PPC can only see the first three IPC registers -#define HW_IPC_PPCMSG (HW_REG_BASE + 0x000) //PPC to ARM +#define HW_IPC_PPCMSG (HW_REG_BASE + 0x000) #define HW_IPC_PPCCTRL (HW_REG_BASE + 0x004) -#define HW_IPC_ARMMSG (HW_REG_BASE + 0x008) //ARM to PPC +#define HW_IPC_ARMMSG (HW_REG_BASE + 0x008) #define HW_IPC_ARMCTRL (HW_REG_BASE + 0x00c) -// Write one to send a message. Cleared when peer writes one to IPC_CTRL_RECV. -#define IPC_CTRL_SEND 0x01 -// Set by peer to acknowledge a message. Write one to clear. -#define IPC_CTRL_SENT 0x02 -// Set by peer to send a message. Write one to clear. -#define IPC_CTRL_RECV 0x04 -// Write one acknowledge a message. Cleared when peer writes one to IPC_CTRL_SENT. -#define IPC_CTRL_RECVD 0x08 -// Enable interrupt when a message is received -#define IPC_CTRL_INT_RECV 0x10 -// Enable interrupt when a sent message is acknowledged -#define IPC_CTRL_INT_SENT 0x20 - -/* - The IPC registers are connected to each other. - Both registers are identical and this works for - both peers. Flag bits are cleared by writing a one - to them. - - When Peer A sets this Peer B sees this set - IPC_CTRL_SEND IPC_CTRL_RECV - IPC_CTRL_RECVD IPC_CTRL_SENT - - In fact, bit _SEND on Peer A and bit _RECV on peer B are the same bit, - and the same goes for _RECVD and _SENT, except writing one from A _sets_ - the bit, and writing one from B _clears_ the bit. The same, of course, - is true for the other pair of bits in the other direction. - - The flow, therefore, goes as follows, for a message - from A to B. Steps with the same number can be taken - in any order. - - 1. Peer A writes the message address to the register - 2. Peer A sets IPC_CTRL_SEND - 3. Peer B sees IPC_CTRL_RECV - 4. Peer B writes one to IPC_CTRL_RECV to clear it (A's IPC_CTRL_SEND is cleared at this point) - 4. Peer B reads its message address register - 5. Peer B sets IPC_CTRL_RECVD - 6. Peer A sees IPC_CTRL_SENT - 7. Peer A writes one to IPC_CTRL_SENT to clear it (B's IPC_CTRL_RECVD is cleared at this point) - 7. Peer A may now write to the message address register again - - The same is true for a message from Peer B to Peer A. - - In the particular case of IOS IPC, the PPC is always the "master" - (it sends requests as messages) and the ARM is always the "slave" - (it replies to PPC's requests). IOS can handle up to 16(15?) - simultaneously pending transactions (the PPC can send up to 16(15?) - messages without getting any replies - for example, due to - asynchronous requests or multithreaded execution of blocking - requests) - -*/ - #define HW_TIMER (HW_REG_BASE + 0x010) #define HW_ALARM (HW_REG_BASE + 0x014) -// maybe? -#define HW_FIQFLAG (HW_REG_BASE + 0x030) -#define HW_FIQENABLE (HW_REG_BASE + 0x034) +#define HW_PPCIRQFLAG (HW_REG_BASE + 0x030) +#define HW_PPCIRQMASK (HW_REG_BASE + 0x034) -#define HW_IRQFLAG (HW_REG_BASE + 0x038) -#define HW_IRQENABLE (HW_REG_BASE + 0x03c) +#define HW_ARMIRQFLAG (HW_REG_BASE + 0x038) +#define HW_ARMIRQMASK (HW_REG_BASE + 0x03c) #define HW_MEMMIRR (HW_REG_BASE + 0x060) diff --git a/ipc.c b/ipc.c index 254d4a8..5c03ff5 100644 --- a/ipc.c +++ b/ipc.c @@ -18,6 +18,25 @@ static volatile ipc_request slow_queue[IPC_SLOW_SIZE]; extern char __mem2_area_start[]; +// These defines are for the ARMCTRL regs +// See http://wiibrew.org/wiki/Hardware/IPC + +#define IPC_CTRL_Y1 0x01 +#define IPC_CTRL_X2 0x02 +#define IPC_CTRL_X1 0x04 +#define IPC_CTRL_Y2 0x08 + +#define IPC_CTRL_IX1 0x10 +#define IPC_CTRL_IX2 0x20 + +// Our definitions for this IPC interface +#define IPC_CTRL_OUT IPC_CTRL_Y1 +#define IPC_CTRL_IN IPC_CTRL_X1 +#define IPC_CTRL_IRQ_IN IPC_CTRL_IX1 + +// reset both flags (X* for ARM and Y* for PPC) +#define IPC_CTRL_RESET 0x06 + const ipc_infohdr __ipc_info ALIGNED(32) MEM2_RODATA = { .magic = "IPC", .version = 1, @@ -74,7 +93,7 @@ void ipc_post(u32 code, u32 tag, u32 num_args, ...) dc_flushrange((void*)&out_queue[out_tail], 32); out_tail = (out_tail+1)&(IPC_OUT_SIZE-1); poke_outtail(out_tail); - write32(HW_IPC_ARMCTRL, IPC_CTRL_INT_RECV | IPC_CTRL_SEND); + write32(HW_IPC_ARMCTRL, IPC_CTRL_IRQ_IN | IPC_CTRL_OUT); irq_restore(cookie); } @@ -204,8 +223,8 @@ static void process_in(void) void ipc_irq(void) { int donebell = 0; - while(read32(HW_IPC_ARMCTRL) & IPC_CTRL_RECV) { - write32(HW_IPC_ARMCTRL, IPC_CTRL_INT_RECV | IPC_CTRL_RECV); + while(read32(HW_IPC_ARMCTRL) & IPC_CTRL_IN) { + write32(HW_IPC_ARMCTRL, IPC_CTRL_IRQ_IN | IPC_CTRL_IN); while(peek_intail() != in_head) { process_in(); in_head = (in_head+1)&(IPC_IN_SIZE-1); @@ -221,22 +240,22 @@ void ipc_initialize(void) { write32(HW_IPC_ARMMSG, 0); write32(HW_IPC_PPCMSG, 0); - write32(HW_IPC_PPCCTRL, IPC_CTRL_SENT|IPC_CTRL_RECV); - write32(HW_IPC_ARMCTRL, IPC_CTRL_SENT|IPC_CTRL_RECV); + write32(HW_IPC_PPCCTRL, IPC_CTRL_RESET); + write32(HW_IPC_ARMCTRL, IPC_CTRL_RESET); slow_queue_head = 0; slow_queue_tail = 0; in_head = 0; out_tail = 0; irq_enable(IRQ_IPC); - write32(HW_IPC_ARMCTRL, IPC_CTRL_INT_RECV); + write32(HW_IPC_ARMCTRL, IPC_CTRL_IRQ_IN); } void ipc_shutdown(void) { write32(HW_IPC_ARMMSG, 0); write32(HW_IPC_PPCMSG, 0); - write32(HW_IPC_PPCCTRL, IPC_CTRL_SENT|IPC_CTRL_RECV); - write32(HW_IPC_ARMCTRL, IPC_CTRL_SENT|IPC_CTRL_RECV); + write32(HW_IPC_PPCCTRL, IPC_CTRL_RESET); + write32(HW_IPC_ARMCTRL, IPC_CTRL_RESET); irq_disable(IRQ_IPC); } diff --git a/irq.c b/irq.c index 9b62200..33a8c36 100644 --- a/irq.c +++ b/irq.c @@ -11,26 +11,26 @@ void irq_setup_stack(void); void irq_initialize(void) { irq_setup_stack(); - write32(HW_IRQENABLE, 0); - write32(HW_IRQFLAG, 0xffffffff); + write32(HW_ARMIRQMASK, 0); + write32(HW_ARMIRQFLAG, 0xffffffff); irq_restore(CPSR_FIQDIS); //??? - write32(HW_IRQENABLE+0x04, 0); - write32(HW_IRQENABLE+0x20, 0); + write32(HW_ARMIRQMASK+0x04, 0); + write32(HW_ARMIRQMASK+0x20, 0); } void irq_shutdown(void) { - write32(HW_IRQENABLE, 0); - write32(HW_IRQFLAG, 0xffffffff); + write32(HW_ARMIRQMASK, 0); + write32(HW_ARMIRQFLAG, 0xffffffff); irq_kill(); } void irq_handler(void) { - u32 enabled = read32(HW_IRQENABLE); - u32 flags = read32(HW_IRQFLAG); + u32 enabled = read32(HW_ARMIRQMASK); + u32 flags = read32(HW_ARMIRQFLAG); //gecko_printf("In IRQ handler: 0x%08x 0x%08x 0x%08x\n", enabled, flags, flags & enabled); @@ -41,50 +41,50 @@ void irq_handler(void) gecko_printf("Timer: %08x\n", read32(HW_TIMER)); gecko_printf("Alarm: %08x\n", read32(HW_ALARM)); write32(HW_ALARM, 0); // shut it up - write32(HW_IRQFLAG, IRQF_TIMER); + write32(HW_ARMIRQFLAG, IRQF_TIMER); } if(flags & IRQF_NAND) { // gecko_printf("IRQ: NAND\n"); write32(NAND_CMD, 0x7fffffff); // shut it up - write32(HW_IRQFLAG, IRQF_NAND); + write32(HW_ARMIRQFLAG, IRQF_NAND); nand_irq(); } if(flags & IRQF_GPIO1B) { gecko_printf("IRQ: GPIO1B\n"); write32(HW_GPIO1BINTFLAG, 0xFFFFFF); // shut it up - write32(HW_IRQFLAG, IRQF_GPIO1B); + write32(HW_ARMIRQFLAG, IRQF_GPIO1B); } if(flags & IRQF_GPIO1) { gecko_printf("IRQ: GPIO1\n"); write32(HW_GPIO1INTFLAG, 0xFFFFFF); // shut it up - write32(HW_IRQFLAG, IRQF_GPIO1); + write32(HW_ARMIRQFLAG, IRQF_GPIO1); } if(flags & IRQF_RESET) { gecko_printf("IRQ: RESET\n"); - write32(HW_IRQFLAG, IRQF_RESET); + write32(HW_ARMIRQFLAG, IRQF_RESET); } if(flags & IRQF_IPC) { //gecko_printf("IRQ: IPC\n"); ipc_irq(); - write32(HW_IRQFLAG, IRQF_IPC); + write32(HW_ARMIRQFLAG, IRQF_IPC); } if(flags & IRQF_AES) { gecko_printf("IRQ: AES\n"); - write32(HW_IRQFLAG, IRQF_AES); + write32(HW_ARMIRQFLAG, IRQF_AES); } flags &= ~IRQF_ALL; if(flags) { gecko_printf("IRQ: unknown 0x%08x\n", flags); - write32(HW_IRQFLAG, flags); + write32(HW_ARMIRQFLAG, flags); } } void irq_enable(u32 irq) { - set32(HW_IRQENABLE, 1<