From 16a6ad032f7cd197c90f54193a561b51e0e993c2 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Tue, 29 Jul 2025 12:16:38 -0400 Subject: [PATCH] pp502x: Restructure UART code * Move to a structure instead of pointers to registers * Autobaud operates per-uart * When explitily setting uart speed, it applies to all uarts This allows both UARTs to be enabled and serviced simultaneously, allowing either accessory port to be used. Note that the last port to receive something is where subsequent transmits are directed, and only one set of IAP state is maintained. To change this, we will need to revamp IAP to support more than one state machine, and then extend the serial API to allow for both UARTs to be used independently. Probably not worth the effort. Change-Id: I0142f0906706fc0c4ee6d6d7aa6b0515e1a749dd --- firmware/target/arm/pp/system-pp502x.c | 2 + firmware/target/arm/pp/uart-pp.c | 139 +++++++++++-------------- 2 files changed, 65 insertions(+), 76 deletions(-) diff --git a/firmware/target/arm/pp/system-pp502x.c b/firmware/target/arm/pp/system-pp502x.c index 860e17957c..8b9c2b15a1 100644 --- a/firmware/target/arm/pp/system-pp502x.c +++ b/firmware/target/arm/pp/system-pp502x.c @@ -190,9 +190,11 @@ void __attribute__((interrupt("IRQ"))) irq_handler(void) else if (CPU_HI_INT_STAT & SER0_MASK) { SERIAL_ISR(0); } +#if defined(IPOD_COLOR) || defined(IPOD_4G) || defined(IPOD_MINI) || defined(IPOD_MINI2G) else if (CPU_HI_INT_STAT & SER1_MASK) { SERIAL_ISR(1); } +#endif #endif } else { if (COP_INT_STAT & TIMER2_MASK) diff --git a/firmware/target/arm/pp/uart-pp.c b/firmware/target/arm/pp/uart-pp.c index f7d5aacb11..e51c680053 100644 --- a/firmware/target/arm/pp/uart-pp.c +++ b/firmware/target/arm/pp/uart-pp.c @@ -31,17 +31,29 @@ #include "iap.h" #if defined(IPOD_ACCESSORY_PROTOCOL) -static int autobaud = 0; -volatile unsigned long * base_RBR, * base_THR, * base_LCR, * base_LSR, * base_DLL; +struct ppuart { + volatile unsigned long *RBR_THR_DLL; + volatile unsigned long *LCR; + volatile unsigned long *LSR; + int autobaud; +}; -static void set_bitrate(unsigned int rate) +static struct ppuart SER0 = { &SER0_RBR, &SER0_LCR, &SER0_LSR, 0 }; +#if defined(IPOD_COLOR) || defined(IPOD_4G) || defined(IPOD_MINI) || defined(IPOD_MINI2G) +static struct ppuart SER1 = { &SER1_RBR, &SER1_LCR, &SER1_LSR, 0 }; +static volatile struct ppuart *SERn = &SER1; // ie dock connector +#else +static volatile struct ppuart *SERn = &SER0; +#endif + +static void set_bitrate(volatile struct ppuart *port, unsigned int rate) { unsigned int divisor; divisor = 24000000L / rate / 16; - *base_LCR = 0x80; /* Divisor latch enable */ - *base_DLL = (divisor >> 0) & 0xFF; - *base_LCR = 0x03; /* Divisor latch disable, 8-N-1 */ + *port->LCR = 0x80; /* Divisor latch enable */ + *port->RBR_THR_DLL = (divisor >> 0) & 0xFF; + *port->LCR = 0x03; /* Divisor latch disable, 8-N-1 */ } void serial_setup (void) @@ -53,12 +65,6 @@ void serial_setup (void) (*(volatile unsigned long *)(0x7000008C)) &= ~0x0C; GPO32_ENABLE &= ~0x0C; - base_RBR = &SER0_RBR; - base_THR = &SER0_THR; - base_LCR = &SER0_LCR; - base_LSR = &SER0_LSR; - base_DLL = &SER0_DLL; - DEV_EN = DEV_EN | DEV_SER0; CPU_HI_INT_DIS = SER0_MASK; @@ -77,22 +83,18 @@ void serial_setup (void) CPU_HI_INT_EN = SER0_MASK; tmp = SER0_RBR; - serial_bitrate(0); + SER0.autobaud = 2; + set_bitrate(&SER0, 115200); #elif defined(IPOD_COLOR) || defined(IPOD_4G) || defined(IPOD_MINI) || defined(IPOD_MINI2G) /* Route the Tx/Rx pins. 4G Ipods, MINI & MINI2G. ser1, dock connector */ GPIO_CLEAR_BITWISE(GPIOD_ENABLE, 0x6); GPIO_CLEAR_BITWISE(GPIOD_OUTPUT_EN, 0x6); + GPIOD_INT_CLR = 0x6; outl(0x70000018, inl(0x70000018) & ~0xc00); - base_RBR = &SER1_RBR; - base_THR = &SER1_THR; - base_LCR = &SER1_LCR; - base_LSR = &SER1_LSR; - base_DLL = &SER1_DLL; - DEV_EN |= DEV_SER1; CPU_HI_INT_DIS = SER1_MASK; @@ -111,19 +113,11 @@ void serial_setup (void) CPU_HI_INT_EN = SER1_MASK; tmp = SER1_RBR; - serial_bitrate(0); - /* Route the Tx/Rx pins. 4G Ipod, ser0, top connector */ GPIO_CLEAR_BITWISE(GPIOC_INT_EN, 0x8); GPIO_CLEAR_BITWISE(GPIOC_INT_LEV, 0x8); GPIOC_INT_CLR = 0x8; - base_RBR = &SER0_RBR; - base_THR = &SER0_THR; - base_LCR = &SER0_LCR; - base_LSR = &SER0_LSR; - base_DLL = &SER0_DLL; - DEV_EN |= DEV_SER0; CPU_HI_INT_DIS = SER0_MASK; @@ -142,7 +136,10 @@ void serial_setup (void) CPU_HI_INT_EN = SER0_MASK; tmp = SER0_RBR; - serial_bitrate(0); + SER1.autobaud = 2; + set_bitrate(&SER1, 115200); + SER0.autobaud = 2; + set_bitrate(&SER0, 115200); #endif @@ -154,27 +151,27 @@ void serial_bitrate(int rate) { if(rate == 0) { - autobaud = 2; - set_bitrate(115200); + SER0.autobaud = 2; + set_bitrate(&SER0, 115200); +#if defined(IPOD_COLOR) || defined(IPOD_4G) || defined(IPOD_MINI) || defined(IPOD_MINI2G) + SER1.autobaud = 2; + set_bitrate(&SER1, 115200); +#endif } else { - autobaud = 0; - set_bitrate(rate); + SER0.autobaud = 0; + set_bitrate(&SER0, rate); +#if defined(IPOD_COLOR) || defined(IPOD_4G) || defined(IPOD_MINI) || defined(IPOD_MINI2G) + SER1.autobaud = 0; + set_bitrate(&SER1, rate); +#endif } } int tx_rdy(void) { - if((*base_LSR & 0x20)) - return 1; - else - return 0; -} - -static int rx_rdy(void) -{ - if((*base_LSR & 0x1)) + if((*SERn->LSR & 0x20)) return 1; else return 0; @@ -182,12 +179,7 @@ static int rx_rdy(void) void tx_writec(unsigned char c) { - *base_THR =(int) c; -} - -static unsigned char rx_readc(void) -{ - return (*base_RBR & 0xFF); + *SERn->RBR_THR_DLL = (int)c; } void SERIAL_ISR(int port) @@ -196,26 +188,21 @@ void SERIAL_ISR(int port) static bool newpkt = true; char temp; - if (port && base_RBR != &SER1_RBR) { - base_RBR = &SER1_RBR; - base_THR = &SER1_THR; - base_LCR = &SER1_LCR; - base_LSR = &SER1_LSR; - base_DLL = &SER1_DLL; - } else if (!port && base_RBR != &SER0_RBR) { - base_RBR = &SER0_RBR; - base_THR = &SER0_THR; - base_LCR = &SER0_LCR; - base_LSR = &SER0_LSR; - base_DLL = &SER0_DLL; - } +#if defined(IPOD_COLOR) || defined(IPOD_4G) || defined(IPOD_MINI) || defined(IPOD_MINI2G) + if (port && SERn != &SER1) + SERn = &SER1; + else if (!port && SERn != &SER0) + SERn = &SER0; +#else + (void)port; +#endif - while(rx_rdy()) + while((*SERn->LSR & 0x1)) { - temp = rx_readc(); - if (newpkt && autobaud > 0) + temp = (*SERn->RBR_THR_DLL & 0xFF); + if (newpkt && SERn->autobaud > 0) { - if (autobaud == 1) + if (SERn->autobaud == 1) { switch (temp) { @@ -223,22 +210,22 @@ void SERIAL_ISR(int port) case 0x55: break; case 0xFC: - set_bitrate(19200); + set_bitrate(SERn, 19200); temp = 0xFF; break; case 0xE0: - set_bitrate(9600); + set_bitrate(SERn, 9600); temp = 0xFF; break; default: badbaud++; if (badbaud >= 6) /* Switch baud detection mode */ { - autobaud = 2; - set_bitrate(115200); + SERn->autobaud = 2; + set_bitrate(SERn, 115200); badbaud = 0; } else { - set_bitrate(57600); + set_bitrate(SERn, 57600); } continue; } @@ -249,26 +236,26 @@ void SERIAL_ISR(int port) case 0x55: break; case 0xFE: - set_bitrate(57600); + set_bitrate(SERn, 57600); temp = 0xFF; break; case 0xFC: - set_bitrate(38400); + set_bitrate(SERn, 38400); temp = 0xFF; break; case 0xE0: - set_bitrate(19200); + set_bitrate(SERn, 19200); temp = 0xFF; break; default: badbaud++; if (badbaud >= 6) /* Switch baud detection */ { - autobaud = 1; - set_bitrate(57600); + SERn->autobaud = 1; + set_bitrate(SERn, 57600); badbaud = 0; } else { - set_bitrate(115200); + set_bitrate(SERn, 115200); } continue; } @@ -276,7 +263,7 @@ void SERIAL_ISR(int port) } bool pkt = iap_getc(temp); if(newpkt && !pkt) - autobaud = 0; /* Found good baud */ + SERn->autobaud = 0; /* Found good baud */ newpkt = pkt; } }