From: wdenk Date: Mon, 26 Nov 2001 23:10:26 +0000 (+0000) Subject: Series of patches by Erik Theisen, 25 Nov 2001: X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=77c2195f07e4b18be60a705f9b975988f3a40ba7;p=users%2Frw%2Fppcboot.git Series of patches by Erik Theisen, 25 Nov 2001: Patch 6 of 9: - Fix length check bug in cpu/ppc4xx/i2c.c - Fix special case handling (for all IBM 4xx derivatives) in include/i2c.h - Add new i2c_write_page function. Patch 7 of 9: - Fix and document bug in cpu/ppc4xx/serial.c concerning hardware errata about the serial divisor on all 405s. - Add watchdog support to cpu/ppc4xx/serial.c --- diff --git a/CHANGELOG b/CHANGELOG index f37e6e0..5804a86 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -115,6 +115,17 @@ Modifications for 1.1.2: - New watchdog interface via watchdog.h to support Wave 7 Optics hardware watchdog; cleanup the whole watchdog stuff + Patch 6 of 9: + - Fix length check bug in cpu/ppc4xx/i2c.c + - Fix special case handling (for all IBM 4xx derivatives) in + include/i2c.h + - Add new i2c_write_page function. + + Patch 7 of 9: + - Fix and document bug in cpu/ppc4xx/serial.c concerning hardware + errata about the serial divisor on all 405s. + - Add watchdog support to cpu/ppc4xx/serial.c + * Add I2C support for Xicor X40430 EEPROM (ICU862 board) * Fix comment and change overly conservative value in diff --git a/cpu/ppc4xx/i2c.c b/cpu/ppc4xx/i2c.c index 420fa67..4cb5246 100644 --- a/cpu/ppc4xx/i2c.c +++ b/cpu/ppc4xx/i2c.c @@ -8,6 +8,7 @@ #include #include #include <405gp_i2c.h> +#include #define IIC_OK 0 @@ -272,7 +273,7 @@ int i2c_read (uchar *addr, int alen, uchar *buffer, int len) { int rcode = 0; - if ((alen != 2) && (alen != 3)) { + if ((alen < 1) || (alen > 3)) { printf ("I2C read: addr len %d not supported\n", alen); return 1; } @@ -362,3 +363,41 @@ int i2c_write (uchar *addr, int alen, uchar *buffer, int len) } #endif /* CFG_EEPROM_PAGE_WRITE_ENABLE */ + +int i2c_write_page (uchar *addr, int alen, uchar *data, int dlen, int dsize) +{ + uchar xbuf[7]; + int idx, i; + + /* Validate parameters. */ + if (alen > 3) { + printf("I2C write: addr len %d not supported\n", alen); + return 1; + } + if (dsize > 4) { + printf ("I2C write: data size %d not supported\n", dsize); + return 1; + } + + /* write with ack polling */ + while (dlen > 0) { + /* build up an output buffer */ + idx = 0; + + /* move the extra address bytes to buffer */ + for (i = 1; i < alen; i++) + xbuf[idx++] = addr[i]; + + /* move the data to output buffer */ + for (i = 0; ((i < dsize) && (dlen-- > 0)); i++) + xbuf[idx++] = *data++; + + /* single write + ack polling */ + while ((i2c_send(addr[0] << 1, idx, xbuf)) != 0) { + udelay(100); + } + } + + return 0; +} + diff --git a/cpu/ppc4xx/serial.c b/cpu/ppc4xx/serial.c index 6ef73fd..8847472 100644 --- a/cpu/ppc4xx/serial.c +++ b/cpu/ppc4xx/serial.c @@ -44,6 +44,7 @@ #include #include #include +#include #if CONFIG_SERIAL_SOFTWARE_FIFO #include @@ -337,16 +338,19 @@ serial_init(ulong cpu_clock, int baudrate) /* * Use internal cpu clock to generate serial clock */ +#if 0 + /* + * The divisor bits are STUCK on ALL IBM 405GP/CR Rev. D silicon. + * RTF Errata! + */ cntrl0Reg = mfdcr(cntrl0) & 0xffffe000; cntrl0Reg |= 0x00001022; mtdcr(cntrl0, cntrl0Reg); /* serial clock = cpu clock / 18 */ -#if 0 br_reg = (((((cpu_clock/16)/18) * 10) / baudrate) + 5) / 10 ; #else - /* - * The divisor bits are STUCK on some Walnut boards. - * Dave Updegraff Thu, 12 Jul 2001 10:52:32 -0500 - */ + cntrl0Reg = mfdcr(cntrl0) & 0xffffe000; + cntrl0Reg |= 0x0000103c; + mtdcr(cntrl0, cntrl0Reg); /* Divisor stuck at 31 */ br_reg = ( ( (cpu_clock / (16 * (((mfdcr(cntrl0) & 0x3e) >> 1) + 1)) * 10) / baudrate ) + 5 ) / 10; #endif /* 0 */ @@ -377,7 +381,18 @@ serial_setbrg (ulong cpu_clock, int baudrate) #ifdef CFG_EXT_SERIAL_CLOCK br_reg = (((CFG_EXT_SERIAL_CLOCK*10)/16) / baudrate + 5) / 10; #else + +#if 0 + /* + * The divisor bits are STUCK on ALL IBM 405GP/CR Rev. D silicon. + * RTF Errata! + */ br_reg = (((((cpu_clock/16)/18) * 10) / baudrate) + 5) / 10 ; +#else + br_reg = ( ( (cpu_clock / (16 * (((mfdcr(cntrl0) & 0x3e) >> 1) + 1)) * 10) + / baudrate ) + 5 ) / 10; +#endif /* 0 */ + #endif out8(UART0_BASE + UART_LCR, 0x80); /* set DLAB bit */ @@ -390,14 +405,20 @@ serial_setbrg (ulong cpu_clock, int baudrate) void serial_putc(const char c) { - if (c == '\n') - serial_putc ('\r'); - - out8(UART0_BASE + UART_THR, c); /* put character out */ - - /* check THRE bit, wait for transfer done */ - while ((in8(UART0_BASE + UART_LSR) & 0x20) != 0x20) - ; + int i; + if (c == '\n') + serial_putc ('\r'); + + /* check THRE bit, wait for transmiter available */ + for(i = 1; i < 3500 ; i++) { + if ((in8(UART0_BASE + UART_LSR) & 0x20) == 0x20) + break; +#if defined(CONFIG_HW_WATCHDOG) + WATCHDOG_RESET(); /* Reset HW Watchdog, if needed */ +#endif /* CONFIG_HW_WATCHDOG */ + udelay(100); + } + out8(UART0_BASE + UART_THR, c); /* put character out */ } @@ -415,8 +436,10 @@ int serial_getc() { unsigned char status=0; - while(1) - { + while(1) { +#if defined(CONFIG_HW_WATCHDOG) + WATCHDOG_RESET(); /* Reset HW Watchdog, if needed */ +#endif /* CONFIG_HW_WATCHDOG*/ status = in8(UART0_BASE + UART_LSR); if ((status&asyncLSRDataReady1)!=0x0) { @@ -513,8 +536,13 @@ void serial_buffered_putc (const char c) { /* Wait for CTS */ +#if defined(CONFIG_HW_WATCHDOG) + while (!(in8(UART0_BASE + UART_MSR) & 0x10)) + WATCHDOG_RESET(); +#else while (!(in8(UART0_BASE + UART_MSR) & 0x10)) ; +#endif serial_putc(c); } @@ -531,7 +559,12 @@ serial_buffered_getc (void) int c; int rx_get = buf_info.rx_get; int rx_put; +#if defined(CONFIG_HW_WATCHDOG) + while (rx_get == buf_info.rx_put) + WATCHDOG_RESET(); +#else while (rx_get == buf_info.rx_put) ; +#endif c = buf_info.rx_buffer[rx_get++]; if (rx_get==CONFIG_SERIAL_SOFTWARE_FIFO) rx_get = 0; buf_info.rx_get = rx_get; diff --git a/include/i2c.h b/include/i2c.h index e4e6ddd..45b8caf 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -12,17 +12,16 @@ int i2c_read (uchar *addr, int alen, uchar *buffer, int len); int i2c_write (uchar *addr, int alen, uchar *buffer, int len); -#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \ - defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC) || \ - defined (CONFIG_PIP405) || defined (CONFIG_W7O) +#if defined(CONFIG_4xx) || defined(CONFIG_IOP480) void i2c_init(void); int i2c_receive(unsigned char address, unsigned short size_to_expect, unsigned char datain[] ); int i2c_send(unsigned char address, unsigned short size_to_send, unsigned char dataout[] ); +int i2c_write_page(uchar *addr, int alen, uchar *data, int dlen, int dsize); -#else /* !CPCI405, !AR405, !WALNUT405, !ERIC */ +#else /* !( CONFIG_4xx || CONFIG_IOP480) */ uchar i2c_reg_read (uchar i2c_addr, uchar reg); void i2c_reg_write (uchar i2c_addr, uchar reg, uchar val);