diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-07-15 03:32:22 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-07-15 03:32:22 +0000 |
commit | f1da2c3860e301527d56a1ef0b56c649ee7c4b1b (patch) | |
tree | 562b5d2e8b9cb62eb983d78ff6bcf9789e08fcf6 /arch/ppc | |
parent | 00f11569ac8ca73cbcdef8822de1583e79aee571 (diff) |
Merge with Linux 2.4.0-test5-pre1. This works again on Origin UP.
The IP22 cache bugs which are plaguing some machines are still unfixed.
Diffstat (limited to 'arch/ppc')
44 files changed, 1691 insertions, 716 deletions
diff --git a/arch/ppc/8xx_io/Config.in b/arch/ppc/8xx_io/Config.in index 412b50338..090c09cb4 100644 --- a/arch/ppc/8xx_io/Config.in +++ b/arch/ppc/8xx_io/Config.in @@ -13,8 +13,16 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then fi fi bool '860T FEC Ethernet' CONFIG_FEC_ENET - bool 'Use SMC2 for UART' CONFIG_8xxSMC2 - bool 'Enable SCC2 and SCC3 for UART' CONFIG_8xxSCC + bool 'Use Big CPM Ethernet Buffers' CONFIG_ENET_BIG_BUFFERS +fi +bool 'Use SMC2 for UART' CONFIG_8xxSMC2 +if [ "$CONFIG_8xxSMC2" = "y" ]; then + bool 'Use Alternate SMC2 I/O (823/850)' CONFIG_8xx_ALTSMC2 +fi +bool 'Enable SCC2 and SCC3 for UART' CONFIG_8xxSCC + +if [ "$CONFIG_TQM860" = "y" -o "$CONFIG_TQM860L" = "y" -o "$CONFIG_TQM8xxL" = "y" ]; then + bool 'Use SMC2 for Console' TQM_SMC2_CONSOLE fi # This doesn't really belong here, but it is convenient to ask diff --git a/arch/ppc/8xx_io/commproc.h b/arch/ppc/8xx_io/commproc.h index 7e7e9896d..7faae4ca3 100644 --- a/arch/ppc/8xx_io/commproc.h +++ b/arch/ppc/8xx_io/commproc.h @@ -191,7 +191,9 @@ typedef struct smc_centronics { /* SMC Event and Mask register. */ -#define SMCM_TXE ((unsigned char)0x10) +#define SMCM_BRKE ((unsigned char)0x40) /* When in UART Mode */ +#define SMCM_BRK ((unsigned char)0x10) /* When in UART Mode */ +#define SMCM_TXE ((unsigned char)0x10) /* When in Transparent Mode */ #define SMCM_BSY ((unsigned char)0x04) #define SMCM_TX ((unsigned char)0x02) #define SMCM_RX ((unsigned char)0x01) @@ -457,6 +459,81 @@ typedef struct scc_enet { #define SICR_ENET_CLKRT ((uint)0x0000003d) #endif +#if (defined(CONFIG_TQM860) || defined(CONFIG_TQM860L)) +/* + * TQM860 and TQM860L Configuration: + * + * Signal PAR DIR ODR DAT Function + * Port A, 5 1 0 - - TCLK (CLK3) for Ethernet + * Port A, 7 1 0 - - RCLK (CLK1) for Ethernet + * Port A, 14 1 0 - - TXD for Ethernet (SCC1) + * Port A, 15 1 0 - - RXD for Ethernet (SCC1) + * Port C, 7 0 0 0 - -> ETH-LOOP + * Port C, 10 0 0 1 - CD for Ethernet (SCC1) + * Port C, 11 0 0 1 - CTS for Ethernet (SCC1) + * Port C, 15 * * 0 - TENA/RTS for Ethernet + */ + +#define PA_ENET_RXD ((ushort)0x0001) /* PA 15 */ +#define PA_ENET_TXD ((ushort)0x0002) /* PA 14 */ +#define PA_ENET_TCLK ((ushort)0x0400) /* PA 5 */ +#define PA_ENET_RCLK ((ushort)0x0100) /* PA 7 */ + +#define PC_ENET_TENA ((ushort)0x0001) /* PC 15 */ +#define PC_ENET_CLSN ((ushort)0x0010) /* PC 11 */ +#define PC_ENET_RENA ((ushort)0x0020) /* PC 10 */ + +/* Control bits in the SICR to route TCLK (CLK3) and RCLK (CLK1) to + * SCC1. Also, make sure GR1 (bit 24) and SC1 (bit 25) are zero. + */ +#define SICR_ENET_MASK ((uint)0x000000ff) +#define SICR_ENET_CLKRT ((uint)0x00000026) + +#endif /* CONFIG_TQM860, TQM860L */ + +#ifdef CONFIG_TQM8xxL +/* + * TQM8xxL Configuration (except TQM860L): + * + * Signal PAR DIR ODR DAT Function + * Port A, 5 1 0 - - TCLK (CLK3) for Ethernet + * Port A, 7 1 0 - - RCLK (CLK1) for Ethernet + * Port A, 12 1 0 - - TXD for Ethernet (SCC2) + * Port A, 13 1 0 - - RXD for Ethernet (SCC2) + * Port B, 18 1 1 - - TENA/RTS for Ethernet on STK8xx + * Port C, 7 0 0 0 - -> ETH-LOOP + * Port C, 8 0 0 1 - CD for Ethernet (SCC2) + * Port C, 9 0 0 1 - CTS for Ethernet (SCC2) + * Port C, 14 * * 0 - TENA/RTS for Ethernet on FPS850 + * + * Note: Using PC14 as RTS2 (TENA) does not work on the TQM850L when + * used with the starter-kit mainboard; we *must* use PB18 instead. + * For the FPS850 system, we *must* use PC14 :-( + */ + +#define PA_ENET_RXD ((ushort)0x0004) /* PA 13 */ +#define PA_ENET_TXD ((ushort)0x0008) /* PA 12 */ +#define PA_ENET_RCLK ((ushort)0x0100) /* PA 7 */ +#define PA_ENET_TCLK ((ushort)0x0400) /* PA 5 */ + +#ifndef CONFIG_FPS850 /* not valid on FPS board */ +#define PB_ENET_TENA ((uint)0x00002000) +#endif /* !CONFIG_FPS850 */ + +#ifdef CONFIG_FPS850 /* FPS uses default configuration */ +#define PC_ENET_TENA ((ushort)0x0002) /* PC 14 */ +#endif /* CONFIG_FPS850 */ +#define PC_ENET_CLSN ((ushort)0x0040) /* PC 9 */ +#define PC_ENET_RENA ((ushort)0x0080) /* PC 8 */ + +/* Control bits in the SICR to route TCLK (CLK3) and RCLK (CLK1) to + * SCC2. Also, make sure GR2 (bit 16) and SC2 (bit 17) are zero. + */ +#define SICR_ENET_MASK ((uint)0x0000ff00) +#define SICR_ENET_CLKRT ((uint)0x00002600) + +#endif /* CONFIG_TQM8xxL */ + /* SCC Event register as used by Ethernet. */ #define SCCE_ENET_GRA ((ushort)0x0080) /* Graceful stop complete */ diff --git a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c index 4d95bc9eb..730453bbb 100644 --- a/arch/ppc/8xx_io/enet.c +++ b/arch/ppc/8xx_io/enet.c @@ -73,40 +73,14 @@ * finished otherwise it sets the 'lp->tx_full' flag. * * The MBX has a control register external to the MPC8xx that has some - * control of the Ethernet interface. Control Register 1 has the - * following format: - * bit 0 - Set to enable Ethernet transceiver - * bit 1 - Set to enable Ethernet internal loopback - * bit 2 - Set to auto select AUI or TP port - * bit 3 - if bit 2 is 0, set to select TP port - * bit 4 - Set to disable full duplex (loopback) - * bit 5 - Set to disable XCVR collision test - * bit 6, 7 - Used for RS-232 control. + * control of the Ethernet interface. Information is in the manual for + * your board. * - * EPPC-Bug sets this register to 0x98 for normal Ethernet operation, - * so we should not have to touch it. + * The RPX boards have an external control/status register. Consult the + * programming documents for details unique to your board. * - * The following I/O is used by the MBX implementation of the MPC8xx to - * the MC68160 transceiver. It DOES NOT exactly follow the cookbook - * example from the MPC860 manual. - * Port A, 15 - SCC1 Ethernet Rx - * Port A, 14 - SCC1 Ethernet Tx - * Port A, 6 (CLK2) - SCC1 Ethernet Tx Clk - * Port A, 4 (CLK4) - SCC1 Ethernet Rx Clk - * Port C, 15 - SCC1 Ethernet Tx Enable - * Port C, 11 - SCC1 Ethernet Collision - * Port C, 10 - SCC1 Ethernet Rx Enable - * - * The RPX-Lite (that I had :-), was the MPC850SAR. It has a control - * register to enable Ethernet functions in the 68160, and the Ethernet - * was controlled by SCC2. So, the pin I/O was like this: - * Port A, 13 - SCC2 Ethernet Rx - * Port A, 12 - SCC2 Ethernet Tx - * Port A, 6 (CLK2) - Ethernet Tx Clk - * Port A, 4 (CLK4) - Ethernet Rx Clk - * Port B, 18 (RTS2) - Ethernet Tx Enable - * Port C, 8 (CD2) - Ethernet Rx Enable - * Port C, 9 (CTS2) - SCC Ethernet Collision + * For the TQM8xx(L) modules, there is no control register interface. + * All functions are directly controlled using I/O pins. See commproc.h. */ /* The transmitter timeout @@ -119,12 +93,21 @@ * We don't need to allocate pages for the transmitter. We just use * the skbuffer directly. */ +#ifdef CONFIG_ENET_BIG_BUFFERS +#define CPM_ENET_RX_PAGES 32 +#define CPM_ENET_RX_FRSIZE 2048 +#define CPM_ENET_RX_FRPPG (PAGE_SIZE / CPM_ENET_RX_FRSIZE) +#define RX_RING_SIZE (CPM_ENET_RX_FRPPG * CPM_ENET_RX_PAGES) +#define TX_RING_SIZE 64 /* Must be power of two */ +#define TX_RING_MOD_MASK 63 /* for this to work */ +#else #define CPM_ENET_RX_PAGES 4 #define CPM_ENET_RX_FRSIZE 2048 #define CPM_ENET_RX_FRPPG (PAGE_SIZE / CPM_ENET_RX_FRSIZE) #define RX_RING_SIZE (CPM_ENET_RX_FRPPG * CPM_ENET_RX_PAGES) #define TX_RING_SIZE 8 /* Must be power of two */ #define TX_RING_MOD_MASK 7 /* for this to work */ +#endif /* The CPM stores dest/src/type, data, and checksum for receive packets. */ @@ -896,11 +879,16 @@ int __init scc_enet_init(void) /* It is now OK to enable the Ethernet transmitter. * Unfortunately, there are board implementation differences here. */ -#ifdef CONFIG_MBX +#if (defined(CONFIG_MBX) || defined(CONFIG_TQM860) || defined(CONFIG_TQM860L) || defined(CONFIG_FPS850)) immap->im_ioport.iop_pcpar |= PC_ENET_TENA; immap->im_ioport.iop_pcdir &= ~PC_ENET_TENA; #endif +#if (defined(CONFIG_TQM8xxL) && !defined(CONFIG_FPS850)) + cp->cp_pbpar |= PB_ENET_TENA; + cp->cp_pbdir |= PB_ENET_TENA; +#endif + #if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC) cp->cp_pbpar |= PB_ENET_TENA; cp->cp_pbdir |= PB_ENET_TENA; @@ -928,6 +916,7 @@ int __init scc_enet_init(void) immap->im_ioport.iop_pcdat &= ~PC_BSE_LOOPBACK; #endif + dev->base_addr = (unsigned long)ep; dev->priv = cep; #if 0 diff --git a/arch/ppc/8xx_io/uart.c b/arch/ppc/8xx_io/uart.c index 00f4fa86c..b9f791832 100644 --- a/arch/ppc/8xx_io/uart.c +++ b/arch/ppc/8xx_io/uart.c @@ -41,8 +41,10 @@ #include <asm/8xx_immap.h> #include <asm/mpc8xx.h> #include "commproc.h" - + #ifdef CONFIG_KGDB +extern void breakpoint(void); +extern void set_debug_traps(void); extern int kgdb_output_string (const char* s, unsigned int count); #endif @@ -56,10 +58,17 @@ extern int kgdb_output_string (const char* s, unsigned int count); #endif #endif +#if 0 +/* SCC2 for console +*/ +#undef CONFIG_SERIAL_CONSOLE_PORT +#define CONFIG_SERIAL_CONSOLE_PORT 2 +#endif + #define TX_WAKEUP ASYNC_SHARE_IRQ static char *serial_name = "CPM UART driver"; -static char *serial_version = "0.02"; +static char *serial_version = "0.03"; static DECLARE_TASK_QUEUE(tq_serial); @@ -89,54 +98,33 @@ static int serial_console_setup(struct console *co, char *options); * needs. For example, the port address is the CPM parameter ram * offset for the SCC or SMC. The maximum number of ports is 4 SCCs and * 2 SMCs. The "hub6" field is used to indicate the channel number, with - * 0 and 1 indicating the SMCs and 2, 3, 4, and 5 are the SCCs. - * Since these ports are so versatile, I don't yet have a strategy for - * their management. For example, SCC1 is used for Ethernet. Right - * now, just don't put them in the table. Of course, right now I just - * want the SMC to work as a uart :-).. + * a flag indicating SCC or SMC, and the number is used as an index into + * the CPM parameter area for this device. * The "type" field is currently set to 0, for PORT_UNKNOWN. It is * not currently used. I should probably use it to indicate the port - * type of CMS or SCC. + * type of SMC or SCC. * The SMCs do not support any modem control signals. */ #define smc_scc_num hub6 - -#ifdef CONFIG_8xxSMC2 -/* SMC2 is sometimes used for low performance TDM interfaces. Define - * this as 1 if you want SMC2 as a serial port UART managed by this driver. - * Define this as 0 if you wish to use SMC2 for something else. - */ -#define USE_SMC2 1 -#else -#define USE_SMC2 0 -#endif - -/* Define SCC to ttySx mapping. -*/ -#define SCC_NUM_BASE (USE_SMC2 + 1) /* SCC base tty "number" */ - -/* Define which SCC is the first one to use for a serial port. These - * are 0-based numbers, i.e. this assumes the first SCC (SCC1) is used - * for Ethernet, and the first available SCC for serial UART is SCC2. - * NOTE: IF YOU CHANGE THIS, you have to change the PROFF_xxx and - * interrupt vectors in the table below to match. - */ -#define SCC_IDX_BASE 1 /* table index */ +#define NUM_IS_SCC ((int)0x00010000) +#define PORT_NUM(P) ((P) & 0x0000ffff) /* Processors other than the 860 only get SMCs configured by default. * Either they don't have SCCs or they are allocated somewhere else. * Of course, there are now 860s without some SCCs, so we will need to * address that someday. + * The Embedded Planet Multimedia I/O cards use TDM interfaces to the + * stereo codec parts, and we use SMC2 to help support that. */ static struct serial_state rs_table[] = { /* UART CLK PORT IRQ FLAGS NUM */ { 0, 0, PROFF_SMC1, CPMVEC_SMC1, 0, 0 }, /* SMC1 ttyS0 */ -#if USE_SMC2 +#ifdef CONFIG_8xxSMC2 { 0, 0, PROFF_SMC2, CPMVEC_SMC2, 0, 1 }, /* SMC2 ttyS1 */ #endif #ifdef CONFIG_8xxSCC - { 0, 0, PROFF_SCC2, CPMVEC_SCC2, 0, SCC_NUM_BASE}, /* SCC2 ttyS2 */ - { 0, 0, PROFF_SCC3, CPMVEC_SCC3, 0, SCC_NUM_BASE + 1}, /* SCC3 ttyS3 */ + { 0, 0, PROFF_SCC2, CPMVEC_SCC2, 0, (NUM_IS_SCC | 1) }, /* SCC2 ttyS2 */ + { 0, 0, PROFF_SCC3, CPMVEC_SCC3, 0, (NUM_IS_SCC | 2) }, /* SCC3 ttyS3 */ #endif }; @@ -245,13 +233,14 @@ static void rs_8xx_stop(struct tty_struct *tty) return; save_flags(flags); cli(); - if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) { - smcp = &cpmp->cp_smc[idx]; - smcp->smc_smcm &= ~SMCM_TX; + idx = PORT_NUM(info->state->smc_scc_num); + if (info->state->smc_scc_num & NUM_IS_SCC) { + sccp = &cpmp->cp_scc[idx]; + sccp->scc_sccm &= ~UART_SCCM_TX; } else { - sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE]; - sccp->scc_sccm &= ~UART_SCCM_TX; + smcp = &cpmp->cp_smc[idx]; + smcp->smc_smcm &= ~SMCM_TX; } restore_flags(flags); } @@ -267,14 +256,15 @@ static void rs_8xx_start(struct tty_struct *tty) if (serial_paranoia_check(info, tty->device, "rs_stop")) return; + idx = PORT_NUM(info->state->smc_scc_num); save_flags(flags); cli(); - if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) { - smcp = &cpmp->cp_smc[idx]; - smcp->smc_smcm |= SMCM_TX; + if (info->state->smc_scc_num & NUM_IS_SCC) { + sccp = &cpmp->cp_scc[idx]; + sccp->scc_sccm |= UART_SCCM_TX; } else { - sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE]; - sccp->scc_sccm |= UART_SCCM_TX; + smcp = &cpmp->cp_smc[idx]; + smcp->smc_smcm |= SMCM_TX; } restore_flags(flags); } @@ -372,7 +362,7 @@ static _INLINE_ void receive_chars(ser_info_t *info) icount->rx++; #ifdef SERIAL_DEBUG_INTR - printk("DR%02x:%02x...", ch, *status); + printk("DR%02x:%02x...", ch, status); #endif *tty->flip.flag_buf_ptr = 0; if (status & (BD_SC_BR | BD_SC_FR | @@ -452,10 +442,28 @@ static _INLINE_ void receive_chars(ser_info_t *info) queue_task(&tty->flip.tqueue, &tq_timer); } +static _INLINE_ void receive_break(ser_info_t *info) +{ + struct tty_struct *tty = info->tty; + + info->state->icount.brk++; + /* Check to see if there is room in the tty buffer for + * the break. If not, we exit now, losing the break. FIXME + */ + if ((tty->flip.count + 1) >= TTY_FLIPBUF_SIZE) + return; + *(tty->flip.flag_buf_ptr++) = TTY_BREAK; + *(tty->flip.char_buf_ptr++) = 0; + tty->flip.count++; + + queue_task(&tty->flip.tqueue, &tq_timer); +} + static _INLINE_ void transmit_chars(ser_info_t *info) { - if (info->flags & TX_WAKEUP) { + if ((info->flags & TX_WAKEUP) || + (info->tty->flags & (1 << TTY_DO_WRITE_WAKEUP))) { rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); } @@ -549,24 +557,27 @@ static void rs_8xx_interrupt(void *dev_id) info = (ser_info_t *)dev_id; - if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) { + idx = PORT_NUM(info->state->smc_scc_num); + if (info->state->smc_scc_num & NUM_IS_SCC) { + sccp = &cpmp->cp_scc[idx]; + events = sccp->scc_scce; + if (events & SCCM_RX) + receive_chars(info); + if (events & SCCM_TX) + transmit_chars(info); + sccp->scc_scce = events; + } + else { smcp = &cpmp->cp_smc[idx]; events = smcp->smc_smce; + if (events & SMCM_BRKE) + receive_break(info); if (events & SMCM_RX) receive_chars(info); if (events & SMCM_TX) transmit_chars(info); smcp->smc_smce = events; } - else { - sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE]; - events = sccp->scc_scce; - if (events & SCCM_RX) - receive_chars(info); - if (events & SCCM_TX) - transmit_chars(info); - sccp->scc_scce = events; - } #ifdef SERIAL_DEBUG_INTR printk("rs_interrupt_single(%d, %x)...", @@ -691,7 +702,16 @@ static int startup(ser_info_t *info) */ change_speed(info); - if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) { + idx = PORT_NUM(info->state->smc_scc_num); + if (info->state->smc_scc_num & NUM_IS_SCC) { + sccp = &cpmp->cp_scc[idx]; + scup = (scc_uart_t *)&cpmp->cp_dparam[state->port]; + scup->scc_genscc.scc_mrblr = RX_BUF_SIZE; + scup->scc_maxidl = RX_BUF_SIZE; + sccp->scc_sccm |= (UART_SCCM_TX | UART_SCCM_RX); + sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); + } + else { smcp = &cpmp->cp_smc[idx]; /* Enable interrupts and I/O. @@ -708,22 +728,10 @@ static int startup(ser_info_t *info) * are coming. */ up = (smc_uart_t *)&cpmp->cp_dparam[state->port]; - up->smc_mrblr = RX_BUF_SIZE; up->smc_maxidl = RX_BUF_SIZE; - up->smc_brkcr = 1; /* number of break chars */ } - else { - sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE]; - scup = (scc_uart_t *)&cpmp->cp_dparam[state->port]; - - scup->scc_genscc.scc_mrblr = RX_BUF_SIZE; - scup->scc_maxidl = RX_BUF_SIZE; - - sccp->scc_sccm |= (UART_SCCM_TX | UART_SCCM_RX); - sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); - } info->flags |= ASYNC_INITIALIZED; restore_flags(flags); @@ -758,7 +766,19 @@ static void shutdown(ser_info_t * info) save_flags(flags); cli(); /* Disable interrupts */ - if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) { + idx = PORT_NUM(state->smc_scc_num); + if (state->smc_scc_num & NUM_IS_SCC) { + sccp = &cpmp->cp_scc[idx]; + sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); +#ifdef CONFIG_SERIAL_CONSOLE + /* We can't disable the transmitter if this is the + * system console. + */ + if ((state - rs_table) != CONFIG_SERIAL_CONSOLE_PORT) +#endif + sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX); + } + else { smcp = &cpmp->cp_smc[idx]; /* Disable interrupts and I/O. @@ -768,15 +788,10 @@ static void shutdown(ser_info_t * info) /* We can't disable the transmitter if this is the * system console. */ - if (idx != CONFIG_SERIAL_CONSOLE_PORT) + if ((state - rs_table) != CONFIG_SERIAL_CONSOLE_PORT) #endif smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); } - else { - sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE]; - sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX); - sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); - } if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); @@ -795,6 +810,7 @@ static void change_speed(ser_info_t *info) unsigned cflag, cval, scval, prev_mode; int i, bits, sbits, idx; unsigned long flags; + struct serial_state *state; volatile smc_t *smcp; volatile scc_t *sccp; @@ -802,6 +818,8 @@ static void change_speed(ser_info_t *info) return; cflag = info->tty->termios->c_cflag; + state = info->state; + /* Character length programmed into the mode register is the * sum of: 1 start bit, number of data bits, 0 or 1 parity bit, * 1 or 2 stop bits, minus 1. @@ -903,7 +921,12 @@ static void change_speed(ser_info_t *info) * stops bits (there is always at least one). */ bits++; - if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) { + idx = PORT_NUM(state->smc_scc_num); + if (state->smc_scc_num & NUM_IS_SCC) { + sccp = &cpmp->cp_scc[idx]; + sccp->scc_pmsr = (sbits << 12) | scval; + } + else { smcp = &cpmp->cp_smc[idx]; /* Set the mode register. We want to keep a copy of the @@ -914,12 +937,8 @@ static void change_speed(ser_info_t *info) smcp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART; smcp->smc_smcmr |= (prev_mode & (SMCMR_REN | SMCMR_TEN)); } - else { - sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE]; - sccp->scc_pmsr = (sbits << 12) | scval; - } - m8xx_cpm_setbrg(info->state->smc_scc_num, baud_rate); + m8xx_cpm_setbrg((state - rs_table), baud_rate); restore_flags(flags); } @@ -961,9 +980,9 @@ static int rs_8xx_write(struct tty_struct * tty, int from_user, volatile cbd_t *bdp; #ifdef CONFIG_KGDB - /* Try to let stub handle output. Returns true if it did. */ - if (kgdb_output_string(buf, count)) - return ret; + /* Try to let stub handle output. Returns true if it did. */ + if (kgdb_output_string(buf, count)) + return ret; #endif if (serial_paranoia_check(info, tty->device, "rs_write")) @@ -986,8 +1005,7 @@ static int rs_8xx_write(struct tty_struct * tty, int from_user, } if (from_user) { - c -= copy_from_user(__va(bdp->cbd_bufaddr), buf, c); - if (!c) { + if (copy_from_user(__va(bdp->cbd_bufaddr), buf, c)) { if (!ret) ret = -EFAULT; break; @@ -1271,30 +1289,31 @@ static int set_modem_info(ser_info_t *info, unsigned int cmd, * command. We take advantage of the begin/end functions to make this * happen. */ +static ushort smc_chan_map[] = { + CPM_CR_CH_SMC1, + CPM_CR_CH_SMC2 +}; + +static ushort scc_chan_map[] = { + CPM_CR_CH_SCC1, + CPM_CR_CH_SCC2, + CPM_CR_CH_SCC3, + CPM_CR_CH_SCC4 +}; + static void begin_break(ser_info_t *info) { volatile cpm8xx_t *cp; ushort chan; - ushort num; + int idx; cp = cpmp; - if ((num = info->state->smc_scc_num) < SCC_NUM_BASE) { - if (num == 0) - chan = CPM_CR_CH_SMC1; - else - chan = CPM_CR_CH_SMC2; - } - else { - num -= SCC_NUM_BASE; - switch (num) { - case 0: chan = CPM_CR_CH_SCC1; break; - case 1: chan = CPM_CR_CH_SCC2; break; - case 2: chan = CPM_CR_CH_SCC3; break; - case 3: chan = CPM_CR_CH_SCC4; break; - default: return; - } - } + idx = PORT_NUM(info->state->smc_scc_num); + if (info->state->smc_scc_num & NUM_IS_SCC) + chan = scc_chan_map[idx]; + else + chan = smc_chan_map[idx]; cp->cp_cpcr = mk_cr_cmd(chan, CPM_CR_STOP_TX) | CPM_CR_FLG; while (cp->cp_cpcr & CPM_CR_FLG); } @@ -1303,26 +1322,15 @@ static void end_break(ser_info_t *info) { volatile cpm8xx_t *cp; ushort chan; - ushort num; + int idx; cp = cpmp; - if ((num = info->state->smc_scc_num) < SCC_NUM_BASE) { - if (num == 0) - chan = CPM_CR_CH_SMC1; - else - chan = CPM_CR_CH_SMC2; - } - else { - num -= SCC_NUM_BASE; - switch (num) { - case 0: chan = CPM_CR_CH_SCC1; break; - case 1: chan = CPM_CR_CH_SCC2; break; - case 2: chan = CPM_CR_CH_SCC3; break; - case 3: chan = CPM_CR_CH_SCC4; break; - default: return; - } - } + idx = PORT_NUM(info->state->smc_scc_num); + if (info->state->smc_scc_num & NUM_IS_SCC) + chan = scc_chan_map[idx]; + else + chan = smc_chan_map[idx]; cp->cp_cpcr = mk_cr_cmd(chan, CPM_CR_RESTART_TX) | CPM_CR_FLG; while (cp->cp_cpcr & CPM_CR_FLG); } @@ -1623,16 +1631,17 @@ static void rs_8xx_close(struct tty_struct *tty, struct file * filp) */ info->read_status_mask &= ~BD_SC_EMPTY; if (info->flags & ASYNC_INITIALIZED) { - if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) { + idx = PORT_NUM(info->state->smc_scc_num); + if (info->state->smc_scc_num & NUM_IS_SCC) { + sccp = &cpmp->cp_scc[idx]; + sccp->scc_sccm &= ~UART_SCCM_RX; + sccp->scc_gsmrl &= ~SCC_GSMRL_ENR; + } + else { smcp = &cpmp->cp_smc[idx]; smcp->smc_smcm &= ~SMCM_RX; smcp->smc_smcmr &= ~SMCMR_REN; } - else { - sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE]; - sccp->scc_sccm &= ~UART_SCCM_RX; - sccp->scc_gsmrl &= ~SCC_GSMRL_ENR; - } /* * Before we drop DTR, make sure the UART transmitter * has completely drained; this is especially @@ -1713,7 +1722,18 @@ static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout) break; if (timeout && ((orig_jiffies + timeout) < jiffies)) break; + + /* The 'tx_cur' is really the next buffer to send. We + * have to back up to the previous BD and wait for it + * to go. This isn't perfect, because all this indicates + * is the buffer is available. There are still characters + * in the CPM FIFO. + */ bdp = info->tx_cur; + if (bdp == info->tx_bd_base) + bdp += (TX_NUM_FIFO-1); + else + bdp--; } while (bdp->cbd_sc & BD_SC_READY); current->state = TASK_RUNNING; #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT @@ -1803,7 +1823,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, */ if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR)) || - (info->state->smc_scc_num < SCC_NUM_BASE)) { + !(info->state->smc_scc_num & NUM_IS_SCC)) { if (info->flags & ASYNC_CALLOUT_ACTIVE) return -EBUSY; info->flags |= ASYNC_NORMAL_ACTIVE; @@ -1981,8 +2001,8 @@ static int inline line_info(char *buf, struct serial_state *state) ret = sprintf(buf, "%d: uart:%s port:%X irq:%d", state->line, - (state->smc_scc_num < SCC_NUM_BASE) ? "SMC" : "SCC", - state->port, state->irq); + (state->smc_scc_num & NUM_IS_SCC) ? "SCC" : "SMC", + (unsigned int)(state->port), state->irq); if (!state->port || (state->type == PORT_UNKNOWN)) { ret += sprintf(buf+ret, "\n"); @@ -2070,7 +2090,7 @@ int rs_8xx_read_proc(char *page, char **start, off_t off, int count, done: if (off >= len+begin) return 0; - *start = page + (off-begin); + *start = page + (begin-off); return ((count < begin+len-off) ? count : begin+len-off); } @@ -2229,7 +2249,7 @@ putDebugChar(char ch) /* * Receive character from the serial port. This only works well - * before the port is initialize for real use. + * before the port is initialized for real use. */ static int my_console_wait_key(int idx, int xmon, char *obuf) { @@ -2350,7 +2370,7 @@ void kgdb_map_scc(void) /* To avoid data cache CPM DMA coherency problems, allocate a * buffer in the CPM DPRAM. This will work until the CPM and * serial ports are initialized. At that time a memory buffer - * will be allcoated. + * will be allocated. * The port is already initialized from the boot procedure, all * we do here is give it a different buffer and make it a FIFO. */ @@ -2382,7 +2402,7 @@ void kgdb_map_scc(void) static kdev_t serial_console_device(struct console *c) { - return MKDEV(TTYAUX_MAJOR, 64 + c->index); + return MKDEV(TTY_MAJOR, 64 + c->index); } @@ -2411,12 +2431,9 @@ long __init console_8xx_init(long kmem_start, long kmem_end) #endif -/* This will be used for all boards when the MBX board information - * is modified to include a default baud rate. - */ -#ifndef CONFIG_MBX +/* Index in baud rate table of the default console baud rate. +*/ static int baud_idx; -#endif /* * The serial driver boot-time initialization code! @@ -2425,7 +2442,7 @@ int __init rs_8xx_init(void) { struct serial_state * state; ser_info_t *info; - uint mem_addr, dp_addr; + uint mem_addr, dp_addr, iobits; int i, j, idx; ushort chan; volatile cbd_t *bdp; @@ -2442,7 +2459,6 @@ int __init rs_8xx_init(void) /* Initialize the tty_driver structure */ - /*memset(&serial_driver, 0, sizeof(struct tty_driver));*/ __clear_user(&serial_driver,sizeof(struct tty_driver)); serial_driver.magic = TTY_DRIVER_MAGIC; serial_driver.driver_name = "serial"; @@ -2454,11 +2470,7 @@ int __init rs_8xx_init(void) serial_driver.subtype = SERIAL_TYPE_NORMAL; serial_driver.init_termios = tty_std_termios; serial_driver.init_termios.c_cflag = -#ifndef CONFIG_MBX baud_idx | CS8 | CREAD | HUPCL | CLOCAL; -#else - B9600 | CS8 | CREAD | HUPCL | CLOCAL; -#endif serial_driver.flags = TTY_DRIVER_REAL_RAW; serial_driver.refcount = &serial_refcount; serial_driver.table = serial_table; @@ -2502,29 +2514,16 @@ int __init rs_8xx_init(void) cp = cpmp; /* Get pointer to Communication Processor */ immap = (immap_t *)IMAP_ADDR; /* and to internal registers */ - /* Configure SMCs Tx/Rx instead of port B parallel I/O. - */ -#if USE_SMC2 - cp->cp_pbpar |= 0x00000cc0; - cp->cp_pbdir &= ~0x00000cc0; - cp->cp_pbodr &= ~0x00000cc0; -#else - /* This will only enable SMC1 if you want SMC2 for something else. - */ - cp->cp_pbpar |= 0x000000c0; - cp->cp_pbdir &= ~0x000000c0; - cp->cp_pbodr &= ~0x000000c0; -#endif - /* Configure SCC2 and SCC3 instead of port A parallel I/O. + /* Configure SCC2, SCC3, and SCC4 instead of port A parallel I/O. */ -#if defined(CONFIG_MPC860) || defined(CONFIG_MPC860T) +#ifdef CONFIG_8xxSCC #ifndef CONFIG_MBX /* The "standard" configuration through the 860. */ - immap->im_ioport.iop_papar |= 0x003c; - immap->im_ioport.iop_padir &= ~0x003c; - immap->im_ioport.iop_paodr &= ~0x003c; + immap->im_ioport.iop_papar |= 0x00fc; + immap->im_ioport.iop_padir &= ~0x00fc; + immap->im_ioport.iop_paodr &= ~0x00fc; #else /* On the MBX, SCC3 is through Port D. */ @@ -2547,11 +2546,21 @@ int __init rs_8xx_init(void) */ cp->cp_sicr &= ~0x00ffff00; cp->cp_sicr |= 0x001b1200; -#endif - /* Wire BRG1 to SMC1 and BRG2 to SMC2. +#ifdef CONFIG_PP04 + /* Frequentis PP04 forced to RS-232 until we know better. + * Port C 12 and 13 low enables RS-232 on SCC3 and SCC4. + */ + immap->im_ioport.iop_pcdir |= 0x000c; + immap->im_ioport.iop_pcpar &= ~0x000c; + immap->im_ioport.iop_pcdat &= ~0x000c; + + /* This enables the TX driver. */ - cp->cp_simode = 0x10000000; + cp->cp_pbpar &= ~0x6000; + cp->cp_pbdat &= ~0x6000; +#endif +#endif for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { state->magic = SSTATE_MAGIC; @@ -2568,8 +2577,8 @@ int __init rs_8xx_init(void) state->icount.frame = state->icount.parity = 0; state->icount.overrun = state->icount.brk = 0; printk(KERN_INFO "ttyS%02d at 0x%04x is a %s\n", - i, state->port, - (state->smc_scc_num < SCC_NUM_BASE) ? "SMC" : "SCC"); + i, (unsigned int)(state->port), + (state->smc_scc_num & NUM_IS_SCC) ? "SCC" : "SMC"); #ifdef CONFIG_SERIAL_CONSOLE /* If we just printed the message on the console port, and * we are about to initialize it for general use, we have @@ -2581,7 +2590,6 @@ int __init rs_8xx_init(void) #endif info = kmalloc(sizeof(ser_info_t), GFP_KERNEL); if (info) { - /*memset(info, 0, sizeof(ser_info_t));*/ __clear_user(info,sizeof(ser_info_t)); init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); @@ -2621,16 +2629,17 @@ int __init rs_8xx_init(void) bdp->cbd_bufaddr = __pa(mem_addr); bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; - if ((idx = state->smc_scc_num) < SCC_NUM_BASE) { + idx = PORT_NUM(info->state->smc_scc_num); + if (info->state->smc_scc_num & NUM_IS_SCC) { + scp = &cp->cp_scc[idx]; + sup = (scc_uart_t *)&cp->cp_dparam[state->port]; + sup->scc_genscc.scc_rbase = dp_addr; + } + else { sp = &cp->cp_smc[idx]; up = (smc_uart_t *)&cp->cp_dparam[state->port]; up->smc_rbase = dp_addr; } - else { - scp = &cp->cp_scc[idx - SCC_IDX_BASE]; - sup = (scc_uart_t *)&cp->cp_dparam[state->port]; - sup->scc_genscc.scc_rbase = dp_addr; - } dp_addr = m8xx_cpm_dpalloc(sizeof(cbd_t) * TX_NUM_FIFO); @@ -2654,56 +2663,21 @@ int __init rs_8xx_init(void) bdp->cbd_bufaddr = __pa(mem_addr); bdp->cbd_sc = (BD_SC_WRAP | BD_SC_INTRPT); - if (idx < SCC_NUM_BASE) { - up->smc_tbase = dp_addr; + if (info->state->smc_scc_num & NUM_IS_SCC) { + sup->scc_genscc.scc_tbase = dp_addr; /* Set up the uart parameters in the * parameter ram. */ - up->smc_rfcr = SMC_EB; - up->smc_tfcr = SMC_EB; + sup->scc_genscc.scc_rfcr = SMC_EB; + sup->scc_genscc.scc_tfcr = SMC_EB; /* Set this to 1 for now, so we get single * character interrupts. Using idle charater * time requires some additional tuning. */ - up->smc_mrblr = RX_BUF_SIZE; - up->smc_maxidl = RX_BUF_SIZE; - up->smc_brkcr = 1; - - /* Send the CPM an initialize command. - */ - if (state->smc_scc_num == 0) - chan = CPM_CR_CH_SMC1; - else - chan = CPM_CR_CH_SMC2; - - cp->cp_cpcr = mk_cr_cmd(chan, - CPM_CR_INIT_TRX) | CPM_CR_FLG; - while (cp->cp_cpcr & CPM_CR_FLG); - - /* Set UART mode, 8 bit, no parity, one stop. - * Enable receive and transmit. - */ - sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; - - /* Disable all interrupts and clear all pending - * events. - */ - sp->smc_smcm = 0; - sp->smc_smce = 0xff; - } - else { - sup->scc_genscc.scc_tbase = dp_addr; - - /* Set up the uart parameters in the - * parameter ram. - */ - sup->scc_genscc.scc_rfcr = SMC_EB; - sup->scc_genscc.scc_tfcr = SMC_EB; - - sup->scc_genscc.scc_mrblr = RX_BUF_SIZE; - sup->scc_maxidl = RX_BUF_SIZE; + sup->scc_genscc.scc_mrblr = 1; + sup->scc_maxidl = 0; sup->scc_brkcr = 1; sup->scc_parec = 0; sup->scc_frmec = 0; @@ -2724,10 +2698,7 @@ int __init rs_8xx_init(void) /* Send the CPM an initialize command. */ - if (state->smc_scc_num == 2) - chan = CPM_CR_CH_SCC2; - else - chan = CPM_CR_CH_SCC3; + chan = scc_chan_map[idx]; cp->cp_cpcr = mk_cr_cmd(chan, CPM_CR_INIT_TRX) | CPM_CR_FLG; @@ -2747,6 +2718,91 @@ int __init rs_8xx_init(void) scp->scc_scce = 0xffff; scp->scc_dsr = 0x7e7e; scp->scc_pmsr = 0x3000; + + /* If the port is the console, enable Rx and Tx. + */ +#ifdef CONFIG_SERIAL_CONSOLE + if (i == CONFIG_SERIAL_CONSOLE_PORT) + scp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); +#endif + } + else { + /* Configure SMCs Tx/Rx instead of port B + * parallel I/O. On 823/850 these are on + * port A for SMC2. + */ +#ifndef CONFIG_8xx_ALTSMC2 + iobits = 0xc0 << (idx * 4); + cp->cp_pbpar |= iobits; + cp->cp_pbdir &= ~iobits; + cp->cp_pbodr &= ~iobits; +#else + if (idx == 0) { + /* SMC1 on Port B, like all 8xx. + */ + iobits = 0xc0; + cp->cp_pbpar |= iobits; + cp->cp_pbdir &= ~iobits; + cp->cp_pbodr &= ~iobits; + } + else { + /* SMC2 is on Port A. + */ + iobits = 0x300; + immap->im_ioport.iop_papar |= iobits; + immap->im_ioport.iop_padir &= ~iobits; + immap->im_ioport.iop_paodr &= ~iobits; + } +#endif + + /* Connect the baud rate generator to the + * SMC based upon index in rs_table. Also + * make sure it is connected to NMSI. + */ + cp->cp_simode &= ~(0xffff << (idx * 16)); + cp->cp_simode |= (i << ((idx * 16) + 12)); + + up->smc_tbase = dp_addr; + + /* Set up the uart parameters in the + * parameter ram. + */ + up->smc_rfcr = SMC_EB; + up->smc_tfcr = SMC_EB; + + /* Set this to 1 for now, so we get single + * character interrupts. Using idle charater + * time requires some additional tuning. + */ + up->smc_mrblr = 1; + up->smc_maxidl = 0; + up->smc_brkcr = 1; + + /* Send the CPM an initialize command. + */ + chan = smc_chan_map[idx]; + + cp->cp_cpcr = mk_cr_cmd(chan, + CPM_CR_INIT_TRX) | CPM_CR_FLG; + while (cp->cp_cpcr & CPM_CR_FLG); + + /* Set UART mode, 8 bit, no parity, one stop. + * Enable receive and transmit. + */ + sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; + + /* Disable all interrupts and clear all pending + * events. + */ + sp->smc_smcm = 0; + sp->smc_smce = 0xff; + + /* If the port is the console, enable Rx and Tx. + */ +#ifdef CONFIG_SERIAL_CONSOLE + if (i == CONFIG_SERIAL_CONSOLE_PORT) + sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN; +#endif } /* Install interrupt handler. @@ -2755,19 +2811,8 @@ int __init rs_8xx_init(void) /* Set up the baud rate generator. */ -#ifndef CONFIG_MBX - m8xx_cpm_setbrg(state->smc_scc_num, - baud_table[baud_idx]); -#else - m8xx_cpm_setbrg(state->smc_scc_num, 9600); -#endif + m8xx_cpm_setbrg(i, baud_table[baud_idx]); - /* If the port is the console, enable Rx and Tx. - */ -#ifdef CONFIG_SERIAL_CONSOLE - if (i == CONFIG_SERIAL_CONSOLE_PORT) - sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN; -#endif } } @@ -2780,13 +2825,14 @@ int __init rs_8xx_init(void) static int __init serial_console_setup(struct console *co, char *options) { struct serial_state *ser; - uint mem_addr, dp_addr, bidx; + uint mem_addr, dp_addr, bidx, idx; + ushort chan; volatile cbd_t *bdp; volatile cpm8xx_t *cp; volatile smc_t *sp; + volatile scc_t *scp; volatile smc_uart_t *up; - -#ifndef CONFIG_MBX + volatile scc_uart_t *sup; bd_t *bd; bd = (bd_t *)__res; @@ -2797,40 +2843,41 @@ static int __init serial_console_setup(struct console *co, char *options) co->cflag = CREAD|CLOCAL|bidx|CS8; baud_idx = bidx; -#else - co->cflag = CREAD|CLOCAL|B9600|CS8; -#endif ser = rs_table + co->index; cp = cpmp; /* Get pointer to Communication Processor */ - /* Right now, assume we are using SMCs. - */ - sp = &cp->cp_smc[ser->smc_scc_num]; + idx = PORT_NUM(ser->smc_scc_num); + if (ser->smc_scc_num & NUM_IS_SCC) { + scp = &cp->cp_scc[idx]; + sup = (scc_uart_t *)&cp->cp_dparam[ser->port]; + } + else { + sp = &cp->cp_smc[idx]; + up = (smc_uart_t *)&cpmp->cp_dparam[ser->port]; + } + /* When we get here, the CPM has been reset, so we need * to configure the port. * We need to allocate a transmit and receive buffer descriptor * from dual port ram, and a character buffer area from host mem. */ - up = (smc_uart_t *)&cp->cp_dparam[ser->port]; - cp->cp_pbpar = 0x00c0; /* Enable SMC1 instead of Port B I/O */ /* Allocate space for two buffer descriptors in the DP ram. */ dp_addr = m8xx_cpm_dpalloc(sizeof(cbd_t) * 2); - /* Allocate space for an input FIFO, plus a few bytes for output. - * Allocate bytes to maintain word alignment. - */ - mem_addr = m8xx_cpm_hostalloc(RX_BUF_SIZE + 4); + /* Allocate space for two 2 byte FIFOs in the host memory. + */ + mem_addr = m8xx_cpm_hostalloc(8); /* Set the physical address of the host memory buffers in * the buffer descriptors. */ bdp = (cbd_t *)&cp->cp_dpmem[dp_addr]; bdp->cbd_bufaddr = __pa(mem_addr); - (bdp+1)->cbd_bufaddr = __pa(mem_addr+RX_BUF_SIZE); + (bdp+1)->cbd_bufaddr = __pa(mem_addr+4); /* For the receive, set empty and wrap. * For transmit, set wrap. @@ -2840,39 +2887,98 @@ static int __init serial_console_setup(struct console *co, char *options) /* Set up the uart parameters in the parameter ram. */ - up->smc_rbase = dp_addr; /* Base of receive buffer desc. */ - up->smc_tbase = dp_addr+sizeof(cbd_t); /* Base of xmt buffer desc. */ - up->smc_rfcr = SMC_EB; - up->smc_tfcr = SMC_EB; + if (ser->smc_scc_num & NUM_IS_SCC) { - up->smc_mrblr = RX_BUF_SIZE; /* receive buffer length */ - up->smc_maxidl = RX_BUF_SIZE; + sup->scc_genscc.scc_rbase = dp_addr; + sup->scc_genscc.scc_tbase = dp_addr + sizeof(cbd_t); - /* Send the CPM an initialize command. - */ - cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC1, CPM_CR_INIT_TRX) | CPM_CR_FLG; - /* - * delay for a bit - this is necessary on my board! - * -- Cort - */ - printk(""); - while (cp->cp_cpcr & CPM_CR_FLG); - /* Set UART mode, 8 bit, no parity, one stop. - * Enable receive and transmit. - */ - sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; + /* Set up the uart parameters in the + * parameter ram. + */ + sup->scc_genscc.scc_rfcr = SMC_EB; + sup->scc_genscc.scc_tfcr = SMC_EB; - /* Set up the baud rate generator. - */ -#ifndef CONFIG_MBX - m8xx_cpm_setbrg(ser->smc_scc_num, bd->bi_baudrate); -#else - m8xx_cpm_setbrg(ser->smc_scc_num, 9600); -#endif + /* Set this to 1 for now, so we get single + * character interrupts. Using idle charater + * time requires some additional tuning. + */ + sup->scc_genscc.scc_mrblr = 1; + sup->scc_maxidl = 0; + sup->scc_brkcr = 1; + sup->scc_parec = 0; + sup->scc_frmec = 0; + sup->scc_nosec = 0; + sup->scc_brkec = 0; + sup->scc_uaddr1 = 0; + sup->scc_uaddr2 = 0; + sup->scc_toseq = 0; + sup->scc_char1 = 0x8000; + sup->scc_char2 = 0x8000; + sup->scc_char3 = 0x8000; + sup->scc_char4 = 0x8000; + sup->scc_char5 = 0x8000; + sup->scc_char6 = 0x8000; + sup->scc_char7 = 0x8000; + sup->scc_char8 = 0x8000; + sup->scc_rccm = 0xc0ff; + + /* Send the CPM an initialize command. + */ + chan = scc_chan_map[idx]; + + cp->cp_cpcr = mk_cr_cmd(chan, CPM_CR_INIT_TRX) | CPM_CR_FLG; + while (cp->cp_cpcr & CPM_CR_FLG); + + /* Set UART mode, 8 bit, no parity, one stop. + * Enable receive and transmit. + */ + scp->scc_gsmrh = 0; + scp->scc_gsmrl = + (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16); + + /* Disable all interrupts and clear all pending + * events. + */ + scp->scc_sccm = 0; + scp->scc_scce = 0xffff; + scp->scc_dsr = 0x7e7e; + scp->scc_pmsr = 0x3000; + + scp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); + + } + else { + up->smc_rbase = dp_addr; /* Base of receive buffer desc. */ + up->smc_tbase = dp_addr+sizeof(cbd_t); /* Base of xmt buffer desc. */ + up->smc_rfcr = SMC_EB; + up->smc_tfcr = SMC_EB; + + /* Set this to 1 for now, so we get single character interrupts. + */ + up->smc_mrblr = 1; /* receive buffer length */ + up->smc_maxidl = 0; /* wait forever for next char */ - /* And finally, enable Rx and Tx. + /* Send the CPM an initialize command. + */ + chan = smc_chan_map[idx]; + cp->cp_cpcr = mk_cr_cmd(chan, CPM_CR_INIT_TRX) | CPM_CR_FLG; + printk(""); + while (cp->cp_cpcr & CPM_CR_FLG); + + /* Set UART mode, 8 bit, no parity, one stop. + * Enable receive and transmit. + */ + sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; + + /* And finally, enable Rx and Tx. + */ + sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN; + } + + /* Set up the baud rate generator. */ - sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN; + m8xx_cpm_setbrg((ser - rs_table), bd->bi_baudrate); return 0; } + diff --git a/arch/ppc/coffboot/Makefile b/arch/ppc/coffboot/Makefile index c8541965d..23afda4a8 100644 --- a/arch/ppc/coffboot/Makefile +++ b/arch/ppc/coffboot/Makefile @@ -42,7 +42,7 @@ znetboot: vmlinux.coff vmlinux.elf zImage cp vmlinux.coff $(TFTPIMAGE) cp vmlinux.elf $(TFTPIMAGE).elf -znetboot.initrd: vmlinux.coff.initrd +znetboot.initrd: vmlinux.coff.initrd vmlinux.elf.initrd cp vmlinux.coff.initrd $(TFTPIMAGE) cp vmlinux.elf.initrd $(TFTPIMAGE).elf @@ -81,7 +81,7 @@ vmlinux.coff: coffboot hack-coff ln -sf vmlinux.coff zImage vmlinux.coff.initrd: coffboot.initrd hack-coff - $(OBJCOPY) $(OBJCOPY_ARGS) coffboot $@ + $(OBJCOPY) $(OBJCOPY_ARGS) coffboot.initrd $@ ./hack-coff $@ vmlinux.elf: $(CHRPOBJS) no_initrd.o mknote diff --git a/arch/ppc/config.in b/arch/ppc/config.in index 33f6eaa95..3e0721cb4 100644 --- a/arch/ppc/config.in +++ b/arch/ppc/config.in @@ -12,17 +12,28 @@ bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL endmenu mainmenu_option next_comment +comment 'Loadable module support' +bool 'Enable loadable module support' CONFIG_MODULES +if [ "$CONFIG_MODULES" = "y" ]; then + bool ' Set version information on all module symbols' CONFIG_MODVERSIONS + bool ' Kernel module loader' CONFIG_KMOD +fi +endmenu + +mainmenu_option next_comment comment 'Platform support' define_bool CONFIG_PPC y choice 'Processor Type' \ "6xx/7xx/7400 CONFIG_6xx \ 4xx CONFIG_4xx \ - POWER3/POWER4(64-Bit) CONFIG_PPC64BRIDGE \ + POWER3 CONFIG_POWER3 \ + POWER4 CONFIG_POWER4 \ 8260 CONFIG_8260 \ 8xx CONFIG_8xx" 6xx -if [ "$CONFIG_PPC64BRIDGE" = "y" ]; then - bool 'Power 4 support' CONFIG_POWER4 +if [ "$CONFIG_POWER3" = "y" -o "$CONFIG_POWER4" = "y" ]; then + define_bool CONFIG_PPC64BRIDGE y + define_bool CONFIG_ALL_PPC y fi if [ "$CONFIG_8260" = "y" ]; then @@ -43,6 +54,9 @@ if [ "$CONFIG_8xx" = "y" ]; then "RPX-Lite CONFIG_RPXLITE \ RPX-Classic CONFIG_RPXCLASSIC \ BSE-IP CONFIG_BSEIP \ + TQM8xxL CONFIG_TQM8xxL \ + TQM860L CONFIG_TQM860L \ + TQM860 CONFIG_TQM860 \ MBX CONFIG_MBX \ WinCept CONFIG_WINCEPT" RPX-Lite fi @@ -54,14 +68,14 @@ if [ "$CONFIG_6xx" = "y" ]; then APUS CONFIG_APUS" PowerMac/PReP/MTX/CHRP fi -if [ "$CONFIG_PPC64BRIDGE" = "y" ]; then - define_bool CONFIG_ALL_PPC y -fi - if [ "$CONFIG_8xx" = "y" -o "$CONFIG_8260" = "y" ]; then define_bool CONFIG_ALL_PPC n fi +if [ "$CONFIG_TQM8xxL" = "y" ]; then + bool 'FPS850 Mainboard' CONFIG_FPS850 +fi + bool 'Symmetric multi-processing support' CONFIG_SMP if [ "$CONFIG_6xx" = "y" ];then bool 'AltiVec Support' CONFIG_ALTIVEC @@ -77,15 +91,6 @@ fi endmenu mainmenu_option next_comment -comment 'Loadable module support' -bool 'Enable loadable module support' CONFIG_MODULES -if [ "$CONFIG_MODULES" = "y" ]; then - bool ' Set version information on all module symbols' CONFIG_MODVERSIONS - bool ' Kernel module loader' CONFIG_KMOD -fi -endmenu - -mainmenu_option next_comment comment 'General setup' define_bool CONFIG_ISA n @@ -149,6 +154,7 @@ if [ "$CONFIG_4xx" != "y" -a "$CONFIG_8xx" != "y" ]; then bool 'Support for ADB keyboard' CONFIG_ADB_KEYBOARD bool 'Support for ADB mouse' CONFIG_ADBMOUSE fi + tristate 'Support for /dev/rtc' CONFIG_PPC_RTC bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE bool 'Support for early boot text console (BootX only)' CONFIG_BOOTX_TEXT bool 'Support for Motorola Hot Swap' CONFIG_MOTOROLA_HOTSWAP diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index 501ed931a..0369ad800 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -99,7 +99,8 @@ endif ifeq ($(CONFIG_ALL_PPC),y) O_OBJS += pmac_pic.o pmac_setup.o pmac_time.o feature.o pmac_pci.o prom.o \ chrp_setup.o chrp_time.o chrp_pci.o open_pic.o indirect_pci.o \ - prep_pci.o i8259.o prep_nvram.o prep_time.o residual.o + prep_pci.o i8259.o prep_nvram.o prep_time.o residual.o \ + pmac_backlight.o OX_OBJS += prep_setup.o endif ifeq ($(CONFIG_GEMINI),y) diff --git a/arch/ppc/kernel/bitops.c b/arch/ppc/kernel/bitops.c index fb5a19e3a..69e07057a 100644 --- a/arch/ppc/kernel/bitops.c +++ b/arch/ppc/kernel/bitops.c @@ -6,60 +6,58 @@ #include <asm/bitops.h> /* - * I left these here since the problems with "cc" make it difficult to keep - * them in bitops.h -- Cort + * If the bitops are not inlined in bitops.h, they are defined here. + * -- paulus */ -void set_bit(int nr, volatile void *addr) +#if !__INLINE_BITOPS +void set_bit(int nr, volatile void * addr) { - unsigned int t; - unsigned int mask = 1 << (nr & 0x1f); - volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); - - if ((unsigned long)addr & 3) - printk(KERN_ERR "set_bit(%x, %p)\n", nr, addr); - __asm__ __volatile__("\n\ -1: lwarx %0,0,%2 - or %0,%0,%1 - stwcx. %0,0,%2 + unsigned long old; + unsigned long mask = 1 << (nr & 0x1f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 5); + + __asm__ __volatile__(SMP_WMB "\ +1: lwarx %0,0,%3 + or %0,%0,%2 + stwcx. %0,0,%3 bne 1b" - : "=&r" (t) /*, "=m" (*p)*/ - : "r" (mask), "r" (p) - : "cc"); + SMP_MB + : "=&r" (old), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) + : "cc" ); } void clear_bit(int nr, volatile void *addr) { - unsigned int t; - unsigned int mask = 1 << (nr & 0x1f); - volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); + unsigned long old; + unsigned long mask = 1 << (nr & 0x1f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - if ((unsigned long)addr & 3) - printk(KERN_ERR "clear_bit(%x, %p)\n", nr, addr); - __asm__ __volatile__("\n\ -1: lwarx %0,0,%2 - andc %0,%0,%1 - stwcx. %0,0,%2 + __asm__ __volatile__(SMP_WMB "\ +1: lwarx %0,0,%3 + andc %0,%0,%2 + stwcx. %0,0,%3 bne 1b" - : "=&r" (t) /*, "=m" (*p)*/ - : "r" (mask), "r" (p) + SMP_MB + : "=&r" (old), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) : "cc"); } void change_bit(int nr, volatile void *addr) { - unsigned int t; - unsigned int mask = 1 << (nr & 0x1f); - volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); + unsigned long old; + unsigned long mask = 1 << (nr & 0x1f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 5); - if ((unsigned long)addr & 3) - printk(KERN_ERR "change_bit(%x, %p)\n", nr, addr); - __asm__ __volatile__("\n\ -1: lwarx %0,0,%2 - xor %0,%0,%1 - stwcx. %0,0,%2 + __asm__ __volatile__(SMP_WMB "\ +1: lwarx %0,0,%3 + xor %0,%0,%2 + stwcx. %0,0,%3 bne 1b" - : "=&r" (t) /*, "=m" (*p)*/ - : "r" (mask), "r" (p) + SMP_MB + : "=&r" (old), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) : "cc"); } @@ -69,15 +67,14 @@ int test_and_set_bit(int nr, volatile void *addr) unsigned int mask = 1 << (nr & 0x1f); volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); - if ((unsigned long)addr & 3) - printk(KERN_ERR "test_and_set_bit(%x, %p)\n", nr, addr); - __asm__ __volatile__("\n\ -1: lwarx %0,0,%3 - or %1,%0,%2 - stwcx. %1,0,%3 + __asm__ __volatile__(SMP_WMB "\ +1: lwarx %0,0,%4 + or %1,%0,%3 + stwcx. %1,0,%4 bne 1b" - : "=&r" (old), "=&r" (t) /*, "=m" (*p)*/ - : "r" (mask), "r" (p) + SMP_MB + : "=&r" (old), "=&r" (t), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) : "cc"); return (old & mask) != 0; @@ -89,15 +86,14 @@ int test_and_clear_bit(int nr, volatile void *addr) unsigned int mask = 1 << (nr & 0x1f); volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); - if ((unsigned long)addr & 3) - printk(KERN_ERR "test_and_clear_bit(%x, %p)\n", nr, addr); - __asm__ __volatile__("\n\ -1: lwarx %0,0,%3 - andc %1,%0,%2 - stwcx. %1,0,%3 + __asm__ __volatile__(SMP_WMB "\ +1: lwarx %0,0,%4 + andc %1,%0,%3 + stwcx. %1,0,%4 bne 1b" - : "=&r" (old), "=&r" (t) /*, "=m" (*p)*/ - : "r" (mask), "r" (p) + SMP_MB + : "=&r" (old), "=&r" (t), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) : "cc"); return (old & mask) != 0; @@ -109,93 +105,16 @@ int test_and_change_bit(int nr, volatile void *addr) unsigned int mask = 1 << (nr & 0x1f); volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); - if ((unsigned long)addr & 3) - printk(KERN_ERR "test_and_change_bit(%x, %p)\n", nr, addr); - __asm__ __volatile__("\n\ -1: lwarx %0,0,%3 - xor %1,%0,%2 - stwcx. %1,0,%3 + __asm__ __volatile__(SMP_WMB "\ +1: lwarx %0,0,%4 + xor %1,%0,%3 + stwcx. %1,0,%4 bne 1b" - : "=&r" (old), "=&r" (t) /*, "=m" (*p)*/ - : "r" (mask), "r" (p) + SMP_MB + : "=&r" (old), "=&r" (t), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) : "cc"); return (old & mask) != 0; } - -/* I put it in bitops.h -- Cort */ -#if 0 -int ffz(unsigned int x) -{ - int n; - - x = ~x & (x+1); /* set LS zero to 1, other bits to 0 */ - __asm__ ("cntlzw %0,%1" : "=r" (n) : "r" (x)); - return 31 - n; -} - -/* - * This implementation of find_{first,next}_zero_bit was stolen from - * Linus' asm-alpha/bitops.h. - */ - -int find_first_zero_bit(void * addr, int size) -{ - unsigned int * p = ((unsigned int *) addr); - unsigned int result = 0; - unsigned int tmp; - - if (size == 0) - return 0; - while (size & ~31UL) { - if (~(tmp = *(p++))) - goto found_middle; - result += 32; - size -= 32; - } - if (!size) - return result; - tmp = *p; - tmp |= ~0UL << size; -found_middle: - return result + ffz(tmp); -} - -/* - * Find next zero bit in a bitmap reasonably efficiently.. - */ -int find_next_zero_bit(void * addr, int size, int offset) -{ - unsigned int * p = ((unsigned int *) addr) + (offset >> 5); - unsigned int result = offset & ~31UL; - unsigned int tmp; - - if (offset >= size) - return size; - size -= result; - offset &= 31UL; - if (offset) { - tmp = *(p++); - tmp |= ~0UL >> (32-offset); - if (size < 32) - goto found_first; - if (~tmp) - goto found_middle; - size -= 32; - result += 32; - } - while (size & ~31UL) { - if (~(tmp = *(p++))) - goto found_middle; - result += 32; - size -= 32; - } - if (!size) - return result; - tmp = *p; -found_first: - tmp |= ~0UL << size; -found_middle: - return result + ffz(tmp); -} -#endif +#endif /* !__INLINE_BITOPS */ diff --git a/arch/ppc/kernel/chrp_pci.c b/arch/ppc/kernel/chrp_pci.c index 0d614fba1..c43296c42 100644 --- a/arch/ppc/kernel/chrp_pci.c +++ b/arch/ppc/kernel/chrp_pci.c @@ -288,7 +288,9 @@ void __init chrp_pcibios_fixup(void) { struct pci_dev *dev; +#ifdef CONFIG_POWER4 int i; +#endif int *brp; struct device_node *np; extern struct pci_ops generic_pci_ops; diff --git a/arch/ppc/kernel/chrp_setup.c b/arch/ppc/kernel/chrp_setup.c index d75ccaf5c..8d6649231 100644 --- a/arch/ppc/kernel/chrp_setup.c +++ b/arch/ppc/kernel/chrp_setup.c @@ -51,7 +51,7 @@ #include <asm/keyboard.h> #include <asm/init.h> -#include "time.h" +#include <asm/time.h> #include "local_irq.h" #include "i8259.h" #include "open_pic.h" diff --git a/arch/ppc/kernel/chrp_time.c b/arch/ppc/kernel/chrp_time.c index 6d275e517..54b4a76bb 100644 --- a/arch/ppc/kernel/chrp_time.c +++ b/arch/ppc/kernel/chrp_time.c @@ -26,7 +26,7 @@ #include <asm/nvram.h> #include <asm/prom.h> #include <asm/init.h> -#include "time.h" +#include <asm/time.h> static int nvram_as1 = NVRAM_AS1; static int nvram_as0 = NVRAM_AS0; diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index 354686c2d..8ccb0f571 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S @@ -5,8 +5,8 @@ * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) - * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP - * Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu> + * Rewritten by Cort Dougan (cort@fsmlabs.com) for PReP + * Copyright (C) 1996 Cort Dougan <cort@fsmlabs.com> * Adapted for Power Macintosh by Paul Mackerras. * Low-level exception handlers and MMU support * rewritten by Paul Mackerras. @@ -83,7 +83,9 @@ _GLOBAL(DoSyscall) #endif /* SHOW_SYSCALLS */ cmpi 0,r0,0x7777 /* Special case for 'sys_sigreturn' */ beq- 10f - lwz r10,TASK_PTRACE(r2) + cmpi 0,r0,0x6666 /* Special case for 'sys_rt_sigreturn' */ + beq- 16f + lwz r10,TASK_FLAGS(r2) andi. r10,r10,PT_TRACESYS bne- 50f cmpli 0,r0,NR_syscalls @@ -129,6 +131,12 @@ ret_from_syscall_1: /* sys_sigreturn */ 10: addi r3,r1,STACK_FRAME_OVERHEAD bl sys_sigreturn + cmpi 0,r3,0 /* Check for restarted system call */ + bge ret_from_except + b 20b +/* sys_rt_sigreturn */ +16: addi r3,r1,STACK_FRAME_OVERHEAD + bl sys_rt_sigreturn cmpi 0,r3,0 /* Check for restarted system call */ bge ret_from_except b 20b diff --git a/arch/ppc/kernel/feature.c b/arch/ppc/kernel/feature.c index e47befdd3..4b63d5dc0 100644 --- a/arch/ppc/kernel/feature.c +++ b/arch/ppc/kernel/feature.c @@ -2,6 +2,7 @@ * arch/ppc/kernel/feature.c * * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) + * Ben. Herrenschmidt (bh40@calva.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -30,7 +31,7 @@ #undef DEBUG_FEATURE #define MAX_FEATURE_CONTROLLERS 2 -#define MAX_FEATURE_OFFSET 0x50 +#define MAX_FEATURE_OFFSET 0x100 #define FREG(c,r) (&(((c)->reg)[(r)>>2])) typedef struct feature_bit { @@ -70,6 +71,7 @@ static fbit feature_bits_ohare_pbook[] = { {0x38,0,0}, /* FEATURE_IDE2_reset */ {0x38,0,0}, /* FEATURE_Mediabay_IDE_switch */ {0x38,0,0}, /* FEATURE_Mediabay_content */ + {0x38,0,0}, /* FEATURE_Airport_reset */ }; /* Those bits are from a PowerBook. It's possible that desktop machines @@ -102,6 +104,7 @@ static fbit feature_bits_heathrow[] = { {0x38,0,0}, /* FEATURE_IDE2_reset */ {0x38,0,0}, /* FEATURE_Mediabay_IDE_switch */ {0x38,0,0}, /* FEATURE_Mediabay_content */ + {0x38,0,0}, /* FEATURE_Airport_reset */ }; /* @@ -135,6 +138,7 @@ static fbit feature_bits_paddington[] = { {0x38,0,0}, /* FEATURE_IDE2_reset */ {0x38,0,0}, /* FEATURE_Mediabay_IDE_switch */ {0x38,0,0}, /* FEATURE_Mediabay_content */ + {0x38,0,0}, /* FEATURE_Airport_reset */ }; /* Those bits are for Core99 machines (iBook,G4,iMacSL/DV,Pismo,...). @@ -166,6 +170,7 @@ static fbit feature_bits_keylargo[] = { {0x3c,1,0x40000000}, /* FEATURE_IDE2_reset */ {0x34,0,0x00001000}, /* FEATURE_Mediabay_IDE_switch */ {0x34,0,0x00000100}, /* FEATURE_Mediabay_content */ + {0x40,1,0x08000000}, /* FEATURE_Airport_reset */ }; /* definition of a feature controller object */ @@ -177,22 +182,33 @@ struct feature_controller { }; /* static functions */ -static void +static struct feature_controller* feature_add_controller(struct device_node *controller_device, fbit* bits); static struct feature_controller* feature_lookup_controller(struct device_node *device); -/* static varialbles */ +static void heathrow_prepare_for_sleep(struct feature_controller* ctrler); +static void heathrow_wakeup(struct feature_controller* ctrler); +static void core99_prepare_for_sleep(struct feature_controller* ctrler); +static void core99_wake_up(struct feature_controller* ctrler); + +/* static variables */ static struct feature_controller controllers[MAX_FEATURE_CONTROLLERS]; static int controller_count = 0; +/* Core99 stuffs */ +static volatile u32* uninorth_base = NULL; +static volatile u32* keylargo_base = NULL; +static int uninorth_rev; +static int keylargo_rev; void feature_init(void) { struct device_node *np; - + u32 *rev; + if (_machine != _MACH_Pmac) return; @@ -202,7 +218,14 @@ feature_init(void) * plus some gpio's which could eventually be handled here. */ if (device_is_compatible(np, "Keylargo")) { - feature_add_controller(np, feature_bits_keylargo); + struct feature_controller* ctrler = + feature_add_controller(np, feature_bits_keylargo); + if (ctrler) { + keylargo_base = ctrler->reg; + rev = (u32 *)get_property(ctrler->device, "revision-id", NULL); + if (rev) + keylargo_rev = *rev; + } } else if (device_is_compatible(np, "paddington")) { feature_add_controller(np, feature_bits_paddington); } else { @@ -222,6 +245,18 @@ feature_init(void) } } + /* Handle core99 Uni-N */ + np = find_devices("uni-n"); + if (np && np->n_addrs > 0) { + uninorth_base = ioremap(np->addrs[0].address, 0x1000); + rev = (u32 *)get_property(np, "device-rev", NULL); + if (rev) + uninorth_rev = *rev; + } + if (uninorth_base && keylargo_base) + printk("Uni-N revision: %d, KeyLargo revision: %d\n", + uninorth_rev, keylargo_rev); + if (controller_count) printk(KERN_INFO "Registered %d feature controller(s)\n", controller_count); @@ -236,7 +271,7 @@ feature_init(void) #endif } -static void +static struct feature_controller* feature_add_controller(struct device_node *controller_device, fbit* bits) { struct feature_controller* controller; @@ -244,7 +279,7 @@ feature_add_controller(struct device_node *controller_device, fbit* bits) if (controller_count >= MAX_FEATURE_CONTROLLERS) { printk(KERN_INFO "Feature controller %s skipped(MAX:%d)\n", controller_device->full_name, MAX_FEATURE_CONTROLLERS); - return; + return NULL; } controller = &controllers[controller_count]; @@ -253,7 +288,7 @@ feature_add_controller(struct device_node *controller_device, fbit* bits) if (controller_device->n_addrs == 0) { printk(KERN_ERR "No addresses for %s\n", controller_device->full_name); - return; + return NULL; } controller->reg = (volatile u32 *)ioremap( @@ -262,12 +297,14 @@ feature_add_controller(struct device_node *controller_device, fbit* bits) if (bits == NULL) { printk(KERN_INFO "Twiddling the magic ohare bits\n"); out_le32(FREG(controller,OHARE_FEATURE_REG), STARMAX_FEATURES); - return; + return NULL; } spin_lock_init(&controller->lock); controller_count++; + + return controller; } static struct feature_controller* @@ -389,3 +426,118 @@ feature_test(struct device_node* device, enum system_feature f) return bit->polarity ? (value == 0) : (value == bit->mask); } +/* + * Core99 functions + * + * Note: We currently assume there is _one_ UniN chip and _one_ KeyLargo + * chip, which is the case on all Core99 machines so far + */ + +/* Only one GMAC is assumed */ +void +feature_set_gmac_power(struct device_node* device, int power) +{ + if (!uninorth_base) + return; + if (power) + out_le32(uninorth_base + 0x20/4, + in_le32(uninorth_base + 0x20/4) | 0x02000000); + else + out_le32(uninorth_base + 0x20/4, + in_le32(uninorth_base + 0x20/4) & ~0x02000000); + udelay(20); +} + +/* Pass the node of the correct controller, please */ +void +feature_set_usb_power(struct device_node* device, int power) +{ +} + +/* Not yet implemented */ +void +feature_set_firewire_power(struct device_node* device, int power) +{ +} + +void +feature_prepare_for_sleep(void) +{ + /* We assume gatwick is second */ + struct feature_controller* ctrler = &controllers[0]; + + if (!ctrler) + return; + if (controller_count > 1 && + device_is_compatible(ctrler->device, "gatwick")) + ctrler = &controllers[1]; + + if (ctrler->bits == feature_bits_heathrow || + ctrler->bits == feature_bits_paddington) { + heathrow_prepare_for_sleep(ctrler); + return; + } + if (ctrler->bits == feature_bits_keylargo) { + core99_prepare_for_sleep(ctrler); + return; + } +} + + +void +feature_wake_up(void) +{ + struct feature_controller* ctrler = &controllers[0]; + + if (!ctrler) + return; + if (controller_count > 1 && + device_is_compatible(ctrler->device, "gatwick")) + ctrler = &controllers[1]; + + if (ctrler->bits == feature_bits_heathrow || + ctrler->bits == feature_bits_paddington) { + heathrow_wakeup(ctrler); + return; + } + if (ctrler->bits == feature_bits_keylargo) { + core99_wake_up(ctrler); + return; + } +} + +static u32 save_fcr0; +//static u32 save_fcr1; +//static u32 save_fcr2; +static u32 save_mbcr; + +static void +heathrow_prepare_for_sleep(struct feature_controller* ctrler) +{ + save_mbcr = in_le32(FREG(ctrler, 0x34)); + save_fcr0 = in_le32(FREG(ctrler, 0x38)); + + out_le32(FREG(ctrler, 0x38), save_fcr0 & ~HRW_IOBUS_ENABLE); +} + +static void +heathrow_wakeup(struct feature_controller* ctrler) +{ + out_le32(FREG(ctrler, 0x38), save_fcr0); + out_le32(FREG(ctrler, 0x34), save_mbcr); + + out_le32(FREG(ctrler, 0x38), save_fcr0 | HRW_IOBUS_ENABLE); +} + +static void +core99_prepare_for_sleep(struct feature_controller* ctrler) +{ + /* Not yet implemented */ +} + +static void +core99_wake_up(struct feature_controller* ctrler) +{ + /* Not yet implemented */ +} + diff --git a/arch/ppc/kernel/gemini_setup.c b/arch/ppc/kernel/gemini_setup.c index e069baf5b..7be4675c2 100644 --- a/arch/ppc/kernel/gemini_setup.c +++ b/arch/ppc/kernel/gemini_setup.c @@ -30,7 +30,7 @@ #include <asm/m48t35.h> #include <asm/gemini.h> -#include "time.h" +#include <asm/time.h> #include "local_irq.h" #include "open_pic.h" diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S index 8c5911d30..067581f5d 100644 --- a/arch/ppc/kernel/head.S +++ b/arch/ppc/kernel/head.S @@ -171,6 +171,9 @@ __after_prom_start: #ifndef CONFIG_POWER4 /* POWER4 doesn't have BATs */ bl initial_bats +#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) + bl setup_disp_bat +#endif #else /* CONFIG_POWER4 */ /* * Load up the SDR1 and segment register values now @@ -1603,23 +1606,37 @@ initial_bats: mtspr DBAT0U,r11 /* bit in upper BAT register */ mtspr IBAT0L,r8 mtspr IBAT0U,r11 -#if 0 /* Useful debug code, please leave in for now so I don't have to - * look at docs when I need to setup a BAT ... - */ -setup_screen_bat: - li r3,0 - mtspr DBAT1U,r3 - lis r3,0xfa00 - CLR_TOP32(r3) - lis r4,0xfa00 - CLR_TOP32(r4) - ori r4,r4,0x2a - mtspr DBAT1L,r4 - ori r3,r3,(BL_16M<<2)|0x2 /* set up BAT registers for 604 */ - mtspr DBAT1U,r3 -#endif isync blr + +#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) +setup_disp_bat: + /* + * setup the display bat prepared for us in prom.c + */ + mflr r8 + bl reloc_offset + mtlr r8 + lis r8, disp_BATL@h + ori r8, r8, disp_BATL@l + add r8, r3, r8 + lwz r8, 0(r8) + lis r11, disp_BATU@h + ori r11, r11, disp_BATU@l + add r11, r3, r11 + lwz r11, 0(r11) + mtspr IBAT3L,r8 + mtspr IBAT3U,r11 + mfspr r9,PVR + rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */ + cmpi 0,r9,1 + beq 1f + mtspr DBAT3L,r8 + mtspr DBAT3U,r11 +1: + blr + +#endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */ #endif /* CONFIG_POWER4 */ #ifdef CONFIG_8260 diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c index a81156102..d29f7bd20 100644 --- a/arch/ppc/kernel/idle.c +++ b/arch/ppc/kernel/idle.c @@ -304,3 +304,4 @@ void power_save(void) return; } } + diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c index b055f23ec..ee63ca902 100644 --- a/arch/ppc/kernel/irq.c +++ b/arch/ppc/kernel/irq.c @@ -74,8 +74,7 @@ volatile unsigned char *chrp_int_ack_special; irq_desc_t irq_desc[NR_IRQS]; int ppc_spurious_interrupts = 0; -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; +irq_cpustat_t irq_stat [NR_CPUS]; struct irqaction *ppc_irq_action[NR_IRQS]; unsigned int ppc_cached_irq_mask[NR_MASK_WORDS]; unsigned int ppc_lost_interrupts[NR_MASK_WORDS]; @@ -248,6 +247,7 @@ int get_irq_list(char *buf) len += sprintf(buf+len, " %s ", irq_desc[i].handler->typename ); else len += sprintf(buf+len, " None "); + len += sprintf(buf+len, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge "); len += sprintf(buf+len, " %s",action->name); for (action=action->next; action; action = action->next) { len += sprintf(buf+len, ", %s", action->name); @@ -368,12 +368,12 @@ static void show(char * str) printk("\n%s, CPU %d:\n", str, cpu); printk("irq: %d [%d %d]\n", atomic_read(&global_irq_count), - local_irq_count[0], - local_irq_count[1]); + local_irq_count(0), + local_irq_count(1)); printk("bh: %d [%d %d]\n", atomic_read(&global_bh_count), - local_bh_count[0], - local_bh_count[1]); + local_bh_count(0), + local_bh_count(1)); stack = (unsigned long *) &str; for (i = 40; i ; i--) { unsigned long x = *++stack; @@ -408,7 +408,7 @@ static inline void wait_on_irq(int cpu) * already executing in one.. */ if (!atomic_read(&global_irq_count)) { - if (local_bh_count[cpu] + if (local_bh_count(cpu) || !atomic_read(&global_bh_count)) break; } @@ -430,7 +430,7 @@ static inline void wait_on_irq(int cpu) continue; if (global_irq_lock) continue; - if (!local_bh_count[cpu] + if (!local_bh_count(cpu) && atomic_read(&global_bh_count)) continue; if (!test_and_set_bit(0,&global_irq_lock)) @@ -521,7 +521,7 @@ void __global_cli(void) if (flags & (1 << 15)) { int cpu = smp_processor_id(); __cli(); - if (!local_irq_count[cpu]) + if (!local_irq_count(cpu)) get_irqlock(cpu); } } @@ -530,7 +530,7 @@ void __global_sti(void) { int cpu = smp_processor_id(); - if (!local_irq_count[cpu]) + if (!local_irq_count(cpu)) release_irqlock(cpu); __sti(); } @@ -554,7 +554,7 @@ unsigned long __global_save_flags(void) retval = 2 + local_enabled; /* check for global flags if we're not in an interrupt */ - if (!local_irq_count[smp_processor_id()]) { + if (!local_irq_count(smp_processor_id())) { if (local_enabled) retval = 1; if (global_irq_holder == (unsigned char) smp_processor_id()) diff --git a/arch/ppc/kernel/m8260_setup.c b/arch/ppc/kernel/m8260_setup.c index 2ce3790c3..891b0ca44 100644 --- a/arch/ppc/kernel/m8260_setup.c +++ b/arch/ppc/kernel/m8260_setup.c @@ -44,7 +44,7 @@ #include <asm/immap_8260.h> #include <asm/machdep.h> -#include "time.h" +#include <asm/time.h> #include "ppc8260_pic.h" static int m8260_set_rtc_time(unsigned long time); diff --git a/arch/ppc/kernel/m8xx_setup.c b/arch/ppc/kernel/m8xx_setup.c index 9f0a517e3..a00a8c452 100644 --- a/arch/ppc/kernel/m8xx_setup.c +++ b/arch/ppc/kernel/m8xx_setup.c @@ -45,7 +45,7 @@ #include <asm/8xx_immap.h> #include <asm/machdep.h> -#include "time.h" +#include <asm/time.h> #include "ppc8xx_pic.h" static int m8xx_set_rtc_time(unsigned long time); diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index f8d230c7e..19a218bd4 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -1205,6 +1205,17 @@ _GLOBAL(sys_call_table) .long sys_ni_syscall /* streams2 */ .long sys_vfork .long sys_getrlimit /* 190 */ - .rept NR_syscalls-190 + .long sys_ni_syscall /* 191 */ /* Unused */ + .long sys_ni_syscall /* 192 - reserved - mmap2 */ + .long sys_ni_syscall /* 193 - reserved - truncate64 */ + .long sys_ni_syscall /* 194 - reserved - ftruncate64 */ + .long sys_ni_syscall /* 195 - reserved - stat64 */ + .long sys_ni_syscall /* 196 - reserved - lstat64 */ + .long sys_ni_syscall /* 197 - reserved - fstat64 */ + .long sys_pciconfig_read /* 198 */ + .long sys_pciconfig_write /* 199 */ + .long sys_pciconfig_iobase /* 200 */ + .long sys_ni_syscall /* 201 - reserved - MacOnLinux - new */ + .rept NR_syscalls-201 .long sys_ni_syscall .endr diff --git a/arch/ppc/kernel/oak_setup.c b/arch/ppc/kernel/oak_setup.c index f3c142e2b..09e6e6e6f 100644 --- a/arch/ppc/kernel/oak_setup.c +++ b/arch/ppc/kernel/oak_setup.c @@ -28,7 +28,7 @@ #include "local_irq.h" #include "ppc4xx_pic.h" -#include "time.h" +#include <asm/time.h> #include "oak_setup.h" diff --git a/arch/ppc/kernel/open_pic.c b/arch/ppc/kernel/open_pic.c index 21001a7ce..416137934 100644 --- a/arch/ppc/kernel/open_pic.c +++ b/arch/ppc/kernel/open_pic.c @@ -261,12 +261,15 @@ void __init openpic_init(int main_pic) while(np) { int j, pri; pri = strcmp(np->name, "programmer-switch") ? 2 : 7; - for (j=0;j<np->n_intrs;j++) + for (j=0;j<np->n_intrs;j++) { openpic_initirq( np->intrs[j].line, pri, np->intrs[j].line, - np->intrs[j].sense, + 0, np->intrs[j].sense); + if (np->intrs[j].sense) + irq_desc[np->intrs[j].line].status = IRQ_LEVEL; + } np = np->next; } } diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index 773c99b5c..cfa26b67d 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c @@ -4,11 +4,14 @@ */ #include <linux/kernel.h> +#include <linux/config.h> #include <linux/pci.h> #include <linux/delay.h> #include <linux/string.h> #include <linux/init.h> #include <linux/openpic.h> +#include <linux/capability.h> +#include <linux/sched.h> #include <linux/errno.h> #include <asm/processor.h> @@ -19,6 +22,7 @@ #include <asm/byteorder.h> #include <asm/irq.h> #include <asm/gg2.h> +#include <asm/uaccess.h> #include "pci.h" @@ -184,3 +188,146 @@ int pcibios_enable_device(struct pci_dev *dev) } return 0; } + +/* + * Those syscalls are derived from the Alpha versions, they + * allow userland apps to retreive the per-device iobase and + * mem-base. They also provide wrapper for userland to do + * config space accesses. + * The "host_number" returns the number of the Uni-N sub bridge + */ + +asmlinkage int +sys_pciconfig_read(unsigned long bus, unsigned long dfn, + unsigned long off, unsigned long len, + unsigned char *buf) +{ + unsigned char ubyte; + unsigned short ushort; + unsigned int uint; + long err = 0; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!pcibios_present()) + return -ENOSYS; + + switch (len) { + case 1: + err = pcibios_read_config_byte(bus, dfn, off, &ubyte); + put_user(ubyte, buf); + break; + case 2: + err = pcibios_read_config_word(bus, dfn, off, &ushort); + put_user(ushort, (unsigned short *)buf); + break; + case 4: + err = pcibios_read_config_dword(bus, dfn, off, &uint); + put_user(uint, (unsigned int *)buf); + break; + default: + err = -EINVAL; + break; + } + return err; +} + +asmlinkage int +sys_pciconfig_write(unsigned long bus, unsigned long dfn, + unsigned long off, unsigned long len, + unsigned char *buf) +{ + unsigned char ubyte; + unsigned short ushort; + unsigned int uint; + long err = 0; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!pcibios_present()) + return -ENOSYS; + + switch (len) { + case 1: + err = get_user(ubyte, buf); + if (err) + break; + err = pcibios_write_config_byte(bus, dfn, off, ubyte); + if (err != PCIBIOS_SUCCESSFUL) { + err = -EFAULT; + } + break; + case 2: + err = get_user(ushort, (unsigned short *)buf); + if (err) + break; + err = pcibios_write_config_word(bus, dfn, off, ushort); + if (err != PCIBIOS_SUCCESSFUL) { + err = -EFAULT; + } + break; + case 4: + err = get_user(uint, (unsigned int *)buf); + if (err) + break; + err = pcibios_write_config_dword(bus, dfn, off, uint); + if (err != PCIBIOS_SUCCESSFUL) { + err = -EFAULT; + } + break; + default: + err = -EINVAL; + break; + } + return err; +} + +void * +pci_dev_io_base(unsigned char bus, unsigned char devfn) +{ + /* Defaults to old way */ + if (!ppc_md.pci_dev_io_base) + return pci_io_base(bus); + return ppc_md.pci_dev_io_base(bus, devfn); +} + +void * +pci_dev_mem_base(unsigned char bus, unsigned char devfn) +{ + /* Default memory base is 0 (1:1 mapping) */ + if (!ppc_md.pci_dev_mem_base) + return 0; + return ppc_md.pci_dev_mem_base(bus, devfn); +} + +/* Returns the root-bridge number (Uni-N number) of a device */ +int +pci_dev_root_bridge(unsigned char bus, unsigned char devfn) +{ + /* Defaults to 0 */ + if (!ppc_md.pci_dev_root_bridge) + return 0; + return ppc_md.pci_dev_root_bridge(bus, devfn); +} + +/* Provide information on locations of various I/O regions in physical + * memory. Do this on a per-card basis so that we choose the right + * root bridge. + * Note that the returned IO or memory base is a physical address + */ + +asmlinkage long +sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) +{ + switch (which) { + case IOBASE_BRIDGE_NUMBER: + return (long)pci_dev_root_bridge(bus, devfn); + case IOBASE_MEMORY: + return (long)pci_dev_mem_base(bus, devfn); + case IOBASE_IO: + return (long)pci_dev_io_base(bus, devfn); + } + + return -EOPNOTSUPP; +} + diff --git a/arch/ppc/kernel/pmac_backlight.c b/arch/ppc/kernel/pmac_backlight.c new file mode 100644 index 000000000..c4426a0b0 --- /dev/null +++ b/arch/ppc/kernel/pmac_backlight.c @@ -0,0 +1,148 @@ +/* + * Miscellaneous procedures for dealing with the PowerMac hardware. + * Contains support for the backlight. + * + * Copyright (C) 2000 Benjamin Herrenschmidt + * + */ + +#include <linux/kernel.h> +#include <linux/stddef.h> +#include <linux/reboot.h> +#include <linux/nvram.h> +#include <asm/init.h> +#include <asm/ptrace.h> +#include <asm/io.h> +#include <asm/pgtable.h> +#include <asm/system.h> +#include <asm/prom.h> +#include <asm/machdep.h> +#include <asm/nvram.h> +#include <asm/backlight.h> + +#include <linux/adb.h> +#include <linux/pmu.h> + +static struct backlight_controller *backlighter = NULL; +static void* backlighter_data = NULL; +static int backlight_autosave = 0; +static int backlight_level = BACKLIGHT_MAX; +static int backlight_enabled = 1; + +void __pmac +register_backlight_controller(struct backlight_controller *ctrler, void *data, char *type) +{ + struct device_node* bk_node; + char *prop; + int valid = 0; + + bk_node = find_devices("backlight"); + +#ifdef CONFIG_ADB_PMU + /* Special case for the old PowerBook since I can't test on it */ + if ((machine_is_compatible("AAPL,3400/2400") || machine_is_compatible("AAPL,3500") + || machine_is_compatible("AAPL,PowerBook1998") + || machine_is_compatible("AAPL,PowerBook1999")) + && !strcmp(type, "pmu")) + valid = 1; + else +#endif + { + if (bk_node) + prop = get_property(bk_node, "backlight-control", NULL); + if (prop && !strncmp(prop, type, strlen(type))) + valid = 1; + } + if (!valid) + return; + backlighter = ctrler; + backlighter_data = data; + + if (bk_node && !backlight_autosave) + prop = get_property(bk_node, "bklt", NULL); + else + prop = NULL; + if (prop) { + backlight_level = ((*prop)+1) >> 1; + if (backlight_level > BACKLIGHT_MAX) + backlight_level = BACKLIGHT_MAX; + } + +#ifdef CONFIG_ADB_PMU + backlight_autosave = machine_is_compatible("AAPL,3400/2400") + || machine_is_compatible("AAPL,3500"); + if (backlight_autosave) { + struct adb_request req; + pmu_request(&req, NULL, 2, 0xd9, 0); + while (!req.complete) + pmu_poll(); + backlight_level = req.reply[1] >> 4; + } +#endif + if (!backlighter->set_enable(1, backlight_level, data)) + backlight_enabled = 1; + + printk(KERN_INFO "Registered \"%s\" backlight controller, level: %d/15\n", + type, backlight_level); +} + +void __pmac +unregister_backlight_controller(struct backlight_controller *ctrler, void *data) +{ + /* We keep the current backlight level (for now) */ + if (ctrler == backlighter && data == backlighter_data) + backlighter = NULL; +} + +int __pmac +set_backlight_enable(int enable) +{ + int rc; + + if (!backlighter) + return -ENODEV; + rc = backlighter->set_enable(enable, backlight_level, backlighter_data); + if (!rc) + backlight_enabled = enable; + return rc; +} + +int __pmac +get_backlight_enable(void) +{ + if (!backlighter) + return -ENODEV; + return backlight_enabled; +} + +int __pmac +set_backlight_level(int level) +{ + int rc = 0; + + if (!backlighter) + return -ENODEV; + if (level < BACKLIGHT_MIN) + level = BACKLIGHT_OFF; + if (level > BACKLIGHT_MAX) + level = BACKLIGHT_MAX; + if (backlight_enabled) + rc = backlighter->set_level(level, backlighter_data); + if (!rc) + backlight_level = level; + if (!rc && !backlight_autosave) { + level <<=1; + if (level & 0x10) + level |= 0x01; + // -- todo: save to property "bklt" + } + return rc; +} + +int __pmac +get_backlight_level(void) +{ + if (!backlighter) + return -ENODEV; + return backlight_level; +} diff --git a/arch/ppc/kernel/pmac_nvram.c b/arch/ppc/kernel/pmac_nvram.c index db0632238..d8de113ec 100644 --- a/arch/ppc/kernel/pmac_nvram.c +++ b/arch/ppc/kernel/pmac_nvram.c @@ -19,20 +19,8 @@ #undef DEBUG -/* - * Read and write the non-volatile RAM on PowerMacs and CHRP machines. - */ -static int nvram_naddrs; -static volatile unsigned char *nvram_addr; -static volatile unsigned char *nvram_data; -static int nvram_mult, is_core_99; -static char* nvram_image; -static int core99_bank = 0; - -extern int pmac_newworld; - #define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */ - + #define CORE99_SIGNATURE 0x5a #define CORE99_ADLER_START 0x14 @@ -60,8 +48,29 @@ struct core99_header { u32 reserved[2]; }; +/* + * Read and write the non-volatile RAM on PowerMacs and CHRP machines. + */ +static int nvram_naddrs; +static volatile unsigned char *nvram_addr; +static volatile unsigned char *nvram_data; +static int nvram_mult, is_core_99; +static int core99_bank = 0; static int nvram_partitions[3]; +/* FIXME: kmalloc fails to allocate the image now that I had to move it + * before time_init(). For now, I allocate a static buffer here + * but it's a waste of space on all but core99 machines + */ +#if 0 +static char* nvram_image; +#else +__pmac static char nvram_image[NVRAM_SIZE]; +#endif + +extern int pmac_newworld; + + static u8 chrp_checksum(struct chrp_header* hdr) { @@ -189,6 +198,7 @@ lookup_partitions(void) hdr = (struct chrp_header *)buffer; offset = 0; + buffer[16] = 0; do { for (i=0;i<16;i++) buffer[i] = nvram_read_byte(offset+i); @@ -234,11 +244,13 @@ void pmac_nvram_init(void) printk(KERN_ERR "nvram: no address\n"); return; } +#if 0 nvram_image = kmalloc(NVRAM_SIZE, GFP_KERNEL); if (!nvram_image) { printk(KERN_ERR "nvram: can't allocate image\n"); return; } +#endif nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2); #ifdef DEBUG printk("nvram: Checking bank 0...\n"); @@ -267,6 +279,7 @@ void pmac_nvram_init(void) printk(KERN_ERR "Don't know how to access NVRAM with %d addresses\n", nvram_naddrs); } + lookup_partitions(); } void diff --git a/arch/ppc/kernel/pmac_pci.c b/arch/ppc/kernel/pmac_pci.c index ee54ba37d..ced029722 100644 --- a/arch/ppc/kernel/pmac_pci.c +++ b/arch/ppc/kernel/pmac_pci.c @@ -34,6 +34,7 @@ struct uninorth_data { struct device_node* node; volatile unsigned int* cfg_addr; volatile unsigned int* cfg_data; + void* iobase; }; static struct uninorth_data uninorth_bridges[3]; @@ -54,6 +55,7 @@ static void add_bridges(struct device_node *dev); #define BANDIT_MAGIC 0x50 #define BANDIT_COHERENT 0x40 +/* Obsolete, should be replaced by pmac_pci_dev_io_base() (below) */ __pmac void *pci_io_base(unsigned int bus) { @@ -83,6 +85,72 @@ int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr, return 0; } +/* This routines figures out on which root bridge a given PCI device + * is attached. + */ +__pmac +int +pmac_pci_dev_root_bridge(unsigned char bus, unsigned char dev_fn) +{ + struct device_node *node, *bridge_node; + int bridge = uninorth_default; + + if (uninorth_count == 0) + return 0; + if (bus == 0 && PCI_SLOT(dev_fn) < 11) + return 0; + + /* We look for the OF device corresponding to this bus/devfn pair. If we + * don't find it, we default to the external PCI */ + bridge_node = NULL; + node = find_pci_device_OFnode(bus, dev_fn & 0xf8); + if (node) { + /* note: we don't stop on the first occurence since we need to go + * up to the root bridge */ + do { + if (node->type && !strcmp(node->type, "pci") + && device_is_compatible(node, "uni-north")) + bridge_node = node; + node=node->parent; + } while (node); + } + if (bridge_node) { + int i; + for (i=0;i<uninorth_count;i++) + if (uninorth_bridges[i].node == bridge_node) { + bridge = i; + break; + } + } + + if (bridge == -1) { + printk(KERN_WARNING "pmac_pci: no default bridge !\n"); + return 0; + } + + return bridge; +} + +__pmac +void * +pmac_pci_dev_io_base(unsigned char bus, unsigned char devfn) +{ + int bridge; + if (uninorth_count == 0) + return pci_io_base(bus); + bridge = pmac_pci_dev_root_bridge(bus, devfn); + if (bridge == -1) + return pci_io_base(bus); + return uninorth_bridges[bridge].iobase; +} + +__pmac +void * +pmac_pci_dev_mem_base(unsigned char bus, unsigned char devfn) +{ + return 0; +} + /* This function only works for bus 0, uni-N uses a different mecanism for * other busses (see below) */ @@ -98,48 +166,20 @@ int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr, |(((unsigned long)(off)) & 0xFCUL) \ |1UL) -/* We should really use RTAS here, unfortunately, it's not available with BootX. - * (one more reason for writing a beautiful OF booter). I'll do the RTAS stuff - * later, once I have something that works enough with BootX. - */ __pmac static unsigned int uni_north_access_data(unsigned char bus, unsigned char dev_fn, unsigned char offset) { - struct device_node *node, *bridge_node; - int bridge = uninorth_default; + int bridge; unsigned int caddr; - if (bus == 0) { - if (PCI_SLOT(dev_fn) < 11) { - return 0; - } - /* We look for the OF device corresponding to this bus/devfn pair. If we - * don't find it, we default to the external PCI */ - bridge_node = NULL; - node = find_pci_device_OFnode(bus, dev_fn & 0xf8); - if (node) { - /* note: we don't stop on the first occurence since we need to go - * up to the root bridge */ - do { - if (!strcmp(node->type, "pci")) - bridge_node = node; - node=node->parent; - } while (node); - } - if (bridge_node) { - int i; - for (i=0;i<uninorth_count;i++) - if (uninorth_bridges[i].node == bridge_node) { - bridge = i; - break; - } - } + bridge = pmac_pci_dev_root_bridge(bus, dev_fn); + if (bus == 0) caddr = UNI_N_CFA0(dev_fn, offset); - } else + else caddr = UNI_N_CFA1(bus, dev_fn, offset); - + if (bridge == -1) { printk(KERN_WARNING "pmac_pci: no default bridge !\n"); return 0; @@ -609,6 +649,7 @@ static void __init add_bridges(struct device_node *dev) uninorth_bridges[i].cfg_addr = ioremap(addr->address + 0x800000, 0x1000); uninorth_bridges[i].cfg_data = ioremap(addr->address + 0xc00000, 0x1000); uninorth_bridges[i].node = dev; + uninorth_bridges[i].iobase = (void *)addr->address; /* XXX This is the bridge with the PCI expansion bus. This is also the * address of the bus that will receive type 1 config accesses and io * accesses. Appears to be correct for iMac DV and G4 Sawtooth too. diff --git a/arch/ppc/kernel/pmac_pic.c b/arch/ppc/kernel/pmac_pic.c index ab2fdbc15..e0e654305 100644 --- a/arch/ppc/kernel/pmac_pic.c +++ b/arch/ppc/kernel/pmac_pic.c @@ -61,14 +61,32 @@ static void pmac_openpic_unmask_irq(unsigned int irq_nr) openpic_enable_irq(irq_nr); } +static void pmac_openpic_ack_irq(unsigned int irq_nr) +{ + if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0) + openpic_eoi(smp_processor_id()); + openpic_disable_irq(irq_nr); +} + +static void pmac_openpic_end_irq(unsigned int irq_nr) +{ + if ((irq_desc[irq_nr].status & IRQ_LEVEL) != 0) + openpic_eoi(smp_processor_id()); + openpic_enable_irq(irq_nr); +} + struct hw_interrupt_type pmac_open_pic = { " OpenPIC ", NULL, NULL, pmac_openpic_unmask_irq, pmac_openpic_mask_irq, - pmac_openpic_mask_irq, - 0 + /* Theorically, the mask&ack should be NULL for OpenPIC. However, doing + * so shows tons of bogus interrupts coming in. + */ + pmac_openpic_ack_irq, + pmac_openpic_end_irq, + NULL }; static void __pmac pmac_mask_and_ack_irq(unsigned int irq_nr) @@ -141,7 +159,8 @@ struct hw_interrupt_type pmac_pic = { pmac_unmask_irq, pmac_mask_irq, pmac_mask_and_ack_irq, - 0 + pmac_unmask_irq, + NULL }; struct hw_interrupt_type gatwick_pic = { @@ -151,7 +170,8 @@ struct hw_interrupt_type gatwick_pic = { pmac_unmask_irq, pmac_mask_irq, pmac_mask_and_ack_irq, - 0 + pmac_unmask_irq, + NULL }; static void gatwick_action(int cpl, void *dev_id, struct pt_regs *regs) @@ -199,17 +219,13 @@ pmac_get_irq(struct pt_regs *regs) } #endif /* CONFIG_SMP */ - /* Yeah, I know, this could be a separate get_irq function */ - if (has_openpic) - { + if (has_openpic) { irq = openpic_irq(smp_processor_id()); if (irq == OPENPIC_VEC_SPURIOUS) /* We get those when doing polled ADB requests, * using -2 is a temp hack to disable the printk */ irq = -2; /*-1; */ - else - openpic_eoi(smp_processor_id()); } else { diff --git a/arch/ppc/kernel/pmac_setup.c b/arch/ppc/kernel/pmac_setup.c index 35aa7a76d..ec8c6eca4 100644 --- a/arch/ppc/kernel/pmac_setup.c +++ b/arch/ppc/kernel/pmac_setup.c @@ -62,17 +62,18 @@ #include <asm/dma.h> #include <asm/bootx.h> -#include "time.h" +#include <asm/time.h> #include "local_irq.h" #include "pmac_pic.h" #undef SHOW_GATWICK_IRQS -unsigned long pmac_get_rtc_time(void); -int pmac_set_rtc_time(unsigned long nowtime); -void pmac_read_rtc_time(void); -void pmac_calibrate_decr(void); -void pmac_setup_pci_ptrs(void); +extern void pmac_time_init(void); +extern unsigned long pmac_get_rtc_time(void); +extern int pmac_set_rtc_time(unsigned long nowtime); +extern void pmac_read_rtc_time(void); +extern void pmac_calibrate_decr(void); +extern void pmac_setup_pci_ptrs(void); extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode); extern int mackbd_getkeycode(unsigned int scancode); @@ -91,6 +92,11 @@ extern int pckbd_translate(unsigned char scancode, unsigned char *keycode, extern char pckbd_unexpected_up(unsigned char keycode); extern void pckbd_leds(unsigned char leds); extern void pckbd_init_hw(void); +extern void pmac_nvram_update(void); + +extern void *pmac_pci_dev_io_base(unsigned char bus, unsigned char devfn); +extern void *pmac_pci_dev_mem_base(unsigned char bus, unsigned char devfn); +extern int pmac_pci_dev_root_bridge(unsigned char bus, unsigned char devfn); unsigned char drive_info; @@ -98,6 +104,8 @@ int ppc_override_l2cr = 0; int ppc_override_l2cr_value; int has_l2cache = 0; +static int current_root_goodness = -1; + extern char saved_command_line[]; extern int pmac_newworld; @@ -300,7 +308,9 @@ pmac_setup_arch(void) #ifdef CONFIG_ADB_PMU find_via_pmu(); #endif - +#ifdef CONFIG_NVRAM + pmac_nvram_init(); +#endif #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif @@ -364,27 +374,25 @@ static void __init init_uninorth(void) { /* - * Turns on the gmac clock so that it responds to PCI cycles - * later, the driver may want to turn it off again to save - * power when interface is down + * Turns OFF the gmac clock. The gmac driver will turn + * it back ON when the interface is enabled. This save + * power on portables. + * + * Note: We could also try to turn OFF the PHY. Since this + * has to be done by both the gmac driver and this code, + * I'll probably end-up moving some of this out of the + * modular gmac driver into a non-modular stub containing + * some basic PHY management and power management stuffs */ - struct device_node* uni_n = find_devices("uni-n"); struct device_node* gmac = find_devices("ethernet"); - unsigned long* addr; - - if (!uni_n || uni_n->n_addrs < 1) - return; - addr = ioremap(uni_n->addrs[0].address, 0x300); while(gmac) { if (device_is_compatible(gmac, "gmac")) break; gmac = gmac->next; } - if (gmac) { - *(addr + 8) |= 2; - eieio(); - } + if (gmac) + feature_set_gmac_power(gmac, 0); } extern char *bootpath; @@ -402,9 +410,6 @@ pmac_init2(void) #ifdef CONFIG_ADB_PMU via_pmu_start(); #endif -#ifdef CONFIG_NVRAM - pmac_nvram_init(); -#endif #ifdef CONFIG_PMAC_PBOOK media_bay_init(); #endif @@ -476,13 +481,14 @@ void __init find_boot_device(void) /* can't be __init - can be called whenever a disk is first accessed */ __pmac -void note_bootable_part(kdev_t dev, int part) +void note_bootable_part(kdev_t dev, int part, int goodness) { static int found_boot = 0; char *p; /* Do nothing if the root has been set already. */ - if (ROOT_DEV != to_kdev_t(DEFAULT_ROOT_DEVICE)) + if ((goodness < current_root_goodness) && + (ROOT_DEV != to_kdev_t(DEFAULT_ROOT_DEVICE))) return; p = strstr(saved_command_line, "root="); if (p != NULL && (p == saved_command_line || p[-1] == ' ')) @@ -495,7 +501,7 @@ void note_bootable_part(kdev_t dev, int part) if (boot_dev == 0 || dev == boot_dev) { ROOT_DEV = MKDEV(MAJOR(dev), MINOR(dev) + part); boot_dev = NODEV; - printk(" (root on %d)", part); + current_root_goodness = goodness; } } @@ -666,11 +672,15 @@ pmac_init(unsigned long r3, unsigned long r4, unsigned long r5, ppc_md.power_off = pmac_power_off; ppc_md.halt = pmac_halt; - ppc_md.time_init = NULL; + ppc_md.time_init = pmac_time_init; ppc_md.set_rtc_time = pmac_set_rtc_time; ppc_md.get_rtc_time = pmac_get_rtc_time; ppc_md.calibrate_decr = pmac_calibrate_decr; + ppc_md.pci_dev_io_base = pmac_pci_dev_io_base; + ppc_md.pci_dev_mem_base = pmac_pci_dev_mem_base; + ppc_md.pci_dev_root_bridge = pmac_pci_dev_root_bridge; + #if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD) ppc_md.kbd_setkeycode = mackbd_setkeycode; ppc_md.kbd_getkeycode = mackbd_getkeycode; diff --git a/arch/ppc/kernel/pmac_time.c b/arch/ppc/kernel/pmac_time.c index ebd0037de..9eb326bf9 100644 --- a/arch/ppc/kernel/pmac_time.c +++ b/arch/ppc/kernel/pmac_time.c @@ -26,7 +26,8 @@ #include <asm/pgtable.h> #include <asm/machdep.h> -#include "time.h" +#include <asm/time.h> +#include <asm/nvram.h> extern rwlock_t xtime_lock; @@ -54,8 +55,30 @@ extern rwlock_t xtime_lock; /* Bits in IFR and IER */ #define T1_INT 0x40 /* Timer 1 interrupt */ -__pmac +extern struct timezone sys_tz; + +__init +void pmac_time_init(void) +{ +#ifdef CONFIG_NVRAM + s32 delta = 0; + int dst; + + delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16; + delta |= ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xa)) << 8; + delta |= pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xb); + if (delta & 0x00800000UL) + delta |= 0xFF000000UL; + dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0); + printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60, + dst ? "on" : "off"); + sys_tz.tz_minuteswest = -delta/60; + /* I _suppose_ this is 0:off, 1:on */ + sys_tz.tz_dsttime = dst; +#endif +} +__pmac unsigned long pmac_get_rtc_time(void) { #ifdef CONFIG_ADB @@ -95,7 +118,34 @@ unsigned long pmac_get_rtc_time(void) int pmac_set_rtc_time(unsigned long nowtime) { - return 0; + struct adb_request req; + + nowtime += RTC_OFFSET - sys_tz.tz_minuteswest * 60; + + switch (sys_ctrler) { + case SYS_CTRLER_CUDA: + if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, + nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0) + return 0; + while (!req.complete) + cuda_poll(); +// if (req.reply_len != 7) + printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n", + req.reply_len); + return 1; + case SYS_CTRLER_PMU: + if (pmu_request(&req, NULL, 5, PMU_SET_RTC, + nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0) + return 0; + while (!req.complete) + pmu_poll(); + if (req.reply_len != 5) + printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n", + req.reply_len); + return 1; + default: + return 0; + } } /* diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index 76809881b..b140dd25c 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -35,10 +35,11 @@ #include <asm/dma.h> #include <asm/machdep.h> #include <asm/hw_irq.h> +#include <asm/nvram.h> #ifdef CONFIG_SMP #include <asm/smplock.h> #endif /* CONFIG_SMP */ -#include "time.h" +#include <asm/time.h> /* Tell string.h we don't want memcpy etc. as cpp defines */ #define EXPORT_SYMTAB_STROPS @@ -76,8 +77,7 @@ EXPORT_SYMBOL(do_lost_interrupts); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(disable_irq_nosync); -EXPORT_SYMBOL(local_irq_count); -EXPORT_SYMBOL(local_bh_count); +EXPORT_SYMBOL(irq_stat); #ifdef CONFIG_SMP EXPORT_SYMBOL(kernel_flag); #endif /* CONFIG_SMP */ @@ -96,6 +96,10 @@ EXPORT_SYMBOL(_prep_type); EXPORT_SYMBOL(ucSystemType); #endif #endif +#ifdef CONFIG_PCI +EXPORT_SYMBOL(pci_dev_io_base); +EXPORT_SYMBOL(pci_dev_mem_base); +#endif #if !__INLINE_BITOPS EXPORT_SYMBOL(set_bit); @@ -234,6 +238,9 @@ EXPORT_SYMBOL(pci_device_loc); EXPORT_SYMBOL(feature_set); EXPORT_SYMBOL(feature_clear); EXPORT_SYMBOL(feature_test); +EXPORT_SYMBOL(feature_set_gmac_power); +EXPORT_SYMBOL(feature_set_usb_power); +EXPORT_SYMBOL(feature_set_firewire_power); #endif /* defined(CONFIG_ALL_PPC) */ #if defined(CONFIG_SCSI) && defined(CONFIG_ALL_PPC) EXPORT_SYMBOL(note_scsi_host); @@ -242,7 +249,13 @@ EXPORT_SYMBOL(kd_mksound); #ifdef CONFIG_NVRAM EXPORT_SYMBOL(nvram_read_byte); EXPORT_SYMBOL(nvram_write_byte); +EXPORT_SYMBOL(pmac_xpram_read); +EXPORT_SYMBOL(pmac_xpram_write); #endif /* CONFIG_NVRAM */ +#ifdef CONFIG_PPC_RTC +EXPORT_SYMBOL(mktime); +EXPORT_SYMBOL(to_tm); +#endif EXPORT_SYMBOL_NOVERS(__ashrdi3); EXPORT_SYMBOL_NOVERS(__ashldi3); diff --git a/arch/ppc/kernel/prep_setup.c b/arch/ppc/kernel/prep_setup.c index cb1110eca..a09b4cf81 100644 --- a/arch/ppc/kernel/prep_setup.c +++ b/arch/ppc/kernel/prep_setup.c @@ -49,7 +49,7 @@ #include <asm/raven.h> #include <asm/keyboard.h> -#include "time.h" +#include <asm/time.h> #include "local_irq.h" #include "i8259.h" #include "open_pic.h" diff --git a/arch/ppc/kernel/prep_time.c b/arch/ppc/kernel/prep_time.c index f720841be..7274dfd0b 100644 --- a/arch/ppc/kernel/prep_time.c +++ b/arch/ppc/kernel/prep_time.c @@ -27,7 +27,7 @@ #include <asm/prep_nvram.h> #include <asm/mk48t59.h> -#include "time.h" +#include <asm/time.h> /* * The motorola uses the m48t18 rtc (includes DS1643) whose registers diff --git a/arch/ppc/kernel/prom.c b/arch/ppc/kernel/prom.c index 7f51ca13f..1d661fa71 100644 --- a/arch/ppc/kernel/prom.c +++ b/arch/ppc/kernel/prom.c @@ -118,10 +118,16 @@ static struct device_node *allnodes = 0; #ifdef CONFIG_BOOTX_TEXT +#define NO_SCROLL + static void clearscreen(void); static void flushscreen(void); +#ifndef NO_SCROLL static void scrollscreen(void); +#endif + +static void prepare_disp_BAT(void); static void draw_byte(unsigned char c, long locX, long locY); static void draw_byte_32(unsigned char *bits, unsigned long *base, int rb); @@ -134,6 +140,9 @@ static long g_loc_Y = 0; static long g_max_loc_X = 0; static long g_max_loc_Y = 0; +unsigned long disp_BATL = 0; +unsigned long disp_BATU = 0; + #define cmapsz (16*256) static unsigned char vga_font[cmapsz]; @@ -473,9 +482,10 @@ bootx_init(unsigned long r4, unsigned long phys) } #ifdef CONFIG_BOOTX_TEXT + prepare_disp_BAT(); prom_drawstring(RELOC("booting...\n")); flushscreen(); - RELOC(bootx_text_mapped) = 0; + RELOC(bootx_text_mapped) = 1; #endif } @@ -748,11 +758,15 @@ prom_init(int r3, int r4, prom_entry pp) #ifdef CONFIG_BOOTX_TEXT if (!chrp && RELOC(disp_bi)) { + RELOC(prom_stdout) = 0; /* stop OF output */ clearscreen(); + prepare_disp_BAT(); prom_welcome(PTRRELOC(RELOC(disp_bi)), phys); prom_drawstring(RELOC("booting...\n")); + RELOC(bootx_text_mapped) = 1; + } else { + RELOC(bootx_text_mapped) = 0; } - RELOC(bootx_text_mapped) = 0; #endif prom_print(RELOC("returning from prom_init\n")); @@ -820,6 +834,45 @@ prom_welcome(boot_infos_t* bi, unsigned long phys) } prom_drawstring(RELOC("\n\n")); } + +/* Calc BAT values for mapping the display and store them + * in disp_BATH and disp_BATL. Those values are then used + * from head.S to map the display during identify_machine() + * and MMU_Init() + * + * For now, the display is mapped in place (1:1). This should + * be changed if the display physical address overlaps + * KERNELBASE, which is fortunately not the case on any machine + * I know of. This mapping is temporary and will disappear as + * soon as the setup done by MMU_Init() is applied + * + * For now, we align the BAT and then map 8Mb on 601 and 16Mb + * on other PPCs. This may cause trouble if the framebuffer + * is really badly aligned, but I didn't encounter this case + * yet. + */ +__init +static void +prepare_disp_BAT(void) +{ + unsigned long offset = reloc_offset(); + boot_infos_t* bi = PTRRELOC(RELOC(disp_bi)); + unsigned long addr = (unsigned long)bi->dispDeviceBase; + + if ((_get_PVR() >> 16) != 1) { + /* 603, 604, G3, G4, ... */ + addr &= 0xFF000000UL; + RELOC(disp_BATU) = addr | (BL_16M<<2) | 2; + RELOC(disp_BATL) = addr | (_PAGE_NO_CACHE | _PAGE_GUARDED | BPP_RW); + } else { + /* 601 */ + addr &= 0xFF800000UL; + RELOC(disp_BATU) = addr | (_PAGE_NO_CACHE | PP_RWXX) | 4; + RELOC(disp_BATL) = addr | BL_8M | 0x40; + } + bi->logicalDisplayBase = bi->dispDeviceBase; +} + #endif static int prom_set_color(ihandle ih, int i, int r, int g, int b) @@ -1133,14 +1186,14 @@ finish_device_tree(void) /* All newworld machines now use the interrupt tree */ struct device_node *np = allnodes; - while(np) { + while(np && (_machine == _MACH_Pmac)) { if (get_property(np, "interrupt-parent", 0)) { pmac_newworld = 1; break; } np = np->allnext; } - if (boot_infos == 0 && pmac_newworld) + if ((_machine == _MACH_chrp) || (boot_infos == 0 && pmac_newworld)) use_of_interrupt_tree = 1; mem = finish_node(allnodes, mem, NULL, 0, 0); @@ -1746,8 +1799,17 @@ find_pci_device_OFnode(unsigned char bus, unsigned char dev_fn) int l; for (np = allnodes; np != 0; np = np->allnext) { - if (np->parent == NULL || np->parent->type == NULL - || strcmp(np->parent->type, "pci") != 0) + int in_macio = 0; + struct device_node* parent = np->parent; + while(parent) { + char *pname = (char *)get_property(parent, "name", &l); + if (pname && strcmp(pname, "mac-io") == 0) { + in_macio = 1; + break; + } + parent = parent->parent; + } + if (in_macio) continue; reg = (unsigned int *) get_property(np, "reg", &l); if (reg == 0 || l < sizeof(struct reg_property)) @@ -2014,11 +2076,14 @@ __init void map_bootx_text(void) { + unsigned long base, offset, size; if (disp_bi == 0) return; - disp_bi->logicalDisplayBase = - ioremap((unsigned long) disp_bi->dispDeviceBase, - disp_bi->dispDeviceRowBytes * disp_bi->dispDeviceRect[3]); + base = ((unsigned long) disp_bi->dispDeviceBase) & 0xFFFFF000UL; + offset = ((unsigned long) disp_bi->dispDeviceBase) - base; + size = disp_bi->dispDeviceRowBytes * disp_bi->dispDeviceRect[3] + offset + + disp_bi->dispDeviceRect[0]; + disp_bi->logicalDisplayBase = ioremap(base, size) + offset; bootx_text_mapped = 1; } @@ -2084,6 +2149,7 @@ flushscreen(void) } } +#ifndef NO_SCROLL __pmac static void scrollscreen(void) @@ -2113,6 +2179,7 @@ scrollscreen(void) dst += (bi->dispDeviceRowBytes >> 2); } } +#endif /* ndef NO_SCROLL */ __pmac void @@ -2148,7 +2215,7 @@ prom_drawchar(char c) RELOC(g_loc_Y)++; cline = 1; } -#if 0 +#ifndef NO_SCROLL while (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) { scrollscreen(); RELOC(g_loc_Y)--; diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 6c0c38273..67387cca0 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -75,9 +75,6 @@ extern void gemini_init(unsigned long r3, unsigned long r6, unsigned long r7); -#ifdef CONFIG_BOOTX_TEXT -extern void map_bootx_text(void); -#endif #ifdef CONFIG_XMON extern void xmon_map_scc(void); #endif @@ -110,6 +107,14 @@ unsigned long SYSRQ_KEY; struct machdep_calls ppc_md; /* + * These are used in binfmt_elf.c to put aux entries on the stack + * for each elf executable being started. + */ +int dcache_bsize; +int icache_bsize; +int ucache_bsize; + +/* * Perhaps we can put the pmac screen_info[] here * on pmac as well so we don't need the ifdef's. * Until we get multiple-console support in here @@ -131,14 +136,6 @@ struct screen_info screen_info = { }; /* - * These are used in binfmt_elf.c to put aux entries on the stack - * for each elf executable being started. - */ -int dcache_bsize; -int icache_bsize; -int ucache_bsize; - -/* * I really need to add multiple-console support... -- Cort */ int __init pmac_display_supported(char *name) @@ -286,7 +283,7 @@ int get_cpuinfo(char *buffer) case 0x000C: len += sprintf(len+buffer, "7400 (G4"); #ifdef CONFIG_ALTIVEC - len += sprintf(len+buffer, ", altivec enabled"); + len += sprintf(len+buffer, ", altivec supported"); #endif /* CONFIG_ALTIVEC */ len += sprintf(len+buffer, ")\n"); break; @@ -686,14 +683,9 @@ void __init setup_arch(char **cmdline_p) extern char *klimit; extern void do_init_bootmem(void); -#ifdef CONFIG_BOOTX_TEXT - map_bootx_text(); -#endif - #ifdef CONFIG_ALL_PPC feature_init(); #endif - #ifdef CONFIG_XMON xmon_map_scc(); if (strstr(cmd_line, "xmon")) diff --git a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c index ee7ba852c..79847fa0d 100644 --- a/arch/ppc/kernel/signal.c +++ b/arch/ppc/kernel/signal.c @@ -1,8 +1,6 @@ /* * linux/arch/ppc/kernel/signal.c * - * $Id: signal.c,v 1.27 1999/08/03 19:16:38 cort Exp $ - * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * @@ -156,13 +154,6 @@ sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, int p3, int p4, int p6, } -asmlinkage int sys_rt_sigreturn(unsigned long __unused) -{ - printk("sys_rt_sigreturn(): %s/%d not yet implemented.\n", - current->comm,current->pid); - do_exit(SIGSEGV); -} - asmlinkage int sys_sigaltstack(const stack_t *uss, stack_t *uoss) { @@ -206,13 +197,11 @@ sys_sigaction(int sig, const struct old_sigaction *act, * When we have signals to deliver, we set up on the * user stack, going down from the original stack pointer: * a sigregs struct - * one or more sigcontext structs + * one or more sigcontext structs with * a gap of __SIGNAL_FRAMESIZE bytes * * Each of these things must be a multiple of 16 bytes in size. * - * XXX ultimately we will have to stack up a siginfo and ucontext - * for each rt signal. */ struct sigregs { elf_gregset_t gp_regs; @@ -223,6 +212,149 @@ struct sigregs { int abigap[56]; }; +struct rt_sigframe +{ + unsigned long _unused[2]; + struct siginfo *pinfo; + void *puc; + struct siginfo info; + struct ucontext uc; +}; + + +/* + * When we have rt signals to deliver, we set up on the + * user stack, going down from the original stack pointer: + * a sigregs struct + * one rt_sigframe struct (siginfo + ucontext) + * a gap of __SIGNAL_FRAMESIZE bytes + * + * Each of these things must be a multiple of 16 bytes in size. + * + */ +asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) +{ + struct rt_sigframe *rt_sf; + struct sigcontext_struct sigctx; + struct sigregs *sr; + int ret; + elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */ + sigset_t set; + stack_t st; + unsigned long prevsp; + + rt_sf = (struct rt_sigframe *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); + if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx)) + || copy_from_user(&set, &rt_sf->uc.uc_sigmask, sizeof(set)) + || copy_from_user(&st, &rt_sf->uc.uc_stack, sizeof(st))) + goto badframe; + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sigmask_lock); + current->blocked = set; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + rt_sf++; /* Look at next rt_sigframe */ + if (rt_sf == (struct rt_sigframe *)(sigctx.regs)) { + /* Last stacked signal - restore registers - + * sigctx is initialized to point to the + * preamble frame (where registers are stored) + * see handle_signal() + */ + sr = (struct sigregs *) sigctx.regs; + if (regs->msr & MSR_FP ) + giveup_fpu(current); + if (copy_from_user(saved_regs, &sr->gp_regs, + sizeof(sr->gp_regs))) + goto badframe; + saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) + | (saved_regs[PT_MSR] & MSR_USERCHANGE); + memcpy(regs, saved_regs, GP_REGS_SIZE); + if (copy_from_user(current->thread.fpr, &sr->fp_regs, + sizeof(sr->fp_regs))) + goto badframe; + /* This function sets back the stack flags into + the current task structure. */ + sys_sigaltstack(&st, NULL); + + ret = regs->result; + } else { + /* More signals to go */ + /* Set up registers for next signal handler */ + regs->gpr[1] = (unsigned long)rt_sf - __SIGNAL_FRAMESIZE; + if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx))) + goto badframe; + sr = (struct sigregs *) sigctx.regs; + regs->gpr[3] = ret = sigctx.signal; + /* Get the siginfo */ + get_user(regs->gpr[4], (unsigned long *)&rt_sf->pinfo); + /* Get the ucontext */ + get_user(regs->gpr[5], (unsigned long *)&rt_sf->puc); + regs->gpr[6] = (unsigned long) rt_sf; + + regs->link = (unsigned long) &sr->tramp; + regs->nip = sigctx.handler; + if (get_user(prevsp, &sr->gp_regs[PT_R1]) + || put_user(prevsp, (unsigned long *) regs->gpr[1])) + goto badframe; + } + return ret; + +badframe: + lock_kernel(); + do_exit(SIGSEGV); +} + +static void +setup_rt_frame(struct pt_regs *regs, struct sigregs *frame, + signed long newsp) +{ + struct rt_sigframe *rt_sf = (struct rt_sigframe *) newsp; + + /* Set up preamble frame */ + if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) + goto badframe; + if (regs->msr & MSR_FP) + giveup_fpu(current); + if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE) + || __copy_to_user(&frame->fp_regs, current->thread.fpr, + ELF_NFPREG * sizeof(double)) + /* Set up to return from user space. + It calls the sc exception at offset 0x9999 + for sys_rt_sigreturn(). + */ + || __put_user(0x38006666UL, &frame->tramp[0]) /* li r0,0x6666 */ + || __put_user(0x44000002UL, &frame->tramp[1])) /* sc */ + goto badframe; + flush_icache_range((unsigned long) &frame->tramp[0], + (unsigned long) &frame->tramp[2]); + + /* Retrieve rt_sigframe from stack and + set up registers for signal handler + */ + newsp -= __SIGNAL_FRAMESIZE; + if (put_user(regs->gpr[1], (unsigned long *)newsp) + || get_user(regs->nip, &rt_sf->uc.uc_mcontext.handler) + || get_user(regs->gpr[3], &rt_sf->uc.uc_mcontext.signal) + || get_user(regs->gpr[4], (unsigned long *)&rt_sf->pinfo) + || get_user(regs->gpr[5], (unsigned long *)&rt_sf->puc)) + goto badframe; + + regs->gpr[1] = newsp; + regs->gpr[6] = (unsigned long) rt_sf; + regs->link = (unsigned long) frame->tramp; + + return; + +badframe: +#if DEBUG_SIG + printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", + regs, frame, newsp); +#endif + lock_kernel(); + do_exit(SIGSEGV); +} + /* * Do a signal return; undo the signal stack. */ @@ -341,6 +473,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, unsigned long *newspp, unsigned long frame) { struct sigcontext_struct *sc; + struct rt_sigframe *rt_sf; if (regs->trap == 0x0C00 /* System Call! */ && ((int)regs->result == -ERESTARTNOHAND || @@ -348,20 +481,47 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, !(ka->sa.sa_flags & SA_RESTART)))) regs->result = -EINTR; - /* Put another sigcontext on the stack */ - *newspp -= sizeof(*sc); - sc = (struct sigcontext_struct *) *newspp; - if (verify_area(VERIFY_WRITE, sc, sizeof(*sc))) - goto badframe; + /* Set up Signal Frame */ + if (ka->sa.sa_flags & SA_SIGINFO) { + /* Put a Real Time Context onto stack */ + *newspp -= sizeof(*rt_sf); + rt_sf = (struct rt_sigframe *) *newspp; + if (verify_area(VERIFY_WRITE, rt_sf, sizeof(*rt_sf))) + goto badframe; - if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler) - || __put_user(oldset->sig[0], &sc->oldmask) + if (__put_user((unsigned long) ka->sa.sa_handler, &rt_sf->uc.uc_mcontext.handler) + || __put_user(&rt_sf->info, &rt_sf->pinfo) + || __put_user(&rt_sf->uc, &rt_sf->puc) + /* Put the siginfo */ + || __copy_to_user(&rt_sf->info, info, sizeof(*info)) + /* Create the ucontext */ + || __put_user(0, &rt_sf->uc.uc_flags) + || __put_user(0, &rt_sf->uc.uc_link) + || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp) + || __put_user(sas_ss_flags(regs->gpr[1]), + &rt_sf->uc.uc_stack.ss_flags) + || __put_user(current->sas_ss_size, &rt_sf->uc.uc_stack.ss_size) + || __copy_to_user(&rt_sf->uc.uc_sigmask, oldset, sizeof(*oldset)) + /* mcontext.regs points to preamble register frame */ + || __put_user((struct pt_regs *)frame, &rt_sf->uc.uc_mcontext.regs) + || __put_user(sig, &rt_sf->uc.uc_mcontext.signal)) + goto badframe; + } else { + /* Put another sigcontext on the stack */ + *newspp -= sizeof(*sc); + sc = (struct sigcontext_struct *) *newspp; + if (verify_area(VERIFY_WRITE, sc, sizeof(*sc))) + goto badframe; + + if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler) + || __put_user(oldset->sig[0], &sc->oldmask) #if _NSIG_WORDS > 1 - || __put_user(oldset->sig[1], &sc->_unused[3]) + || __put_user(oldset->sig[1], &sc->_unused[3]) #endif - || __put_user((struct pt_regs *)frame, &sc->regs) - || __put_user(sig, &sc->signal)) - goto badframe; + || __put_user((struct pt_regs *)frame, &sc->regs) + || __put_user(sig, &sc->signal)) + goto badframe; + } if (ka->sa.sa_flags & SA_ONESHOT) ka->sa.sa_handler = SIG_DFL; @@ -517,7 +677,10 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) if (newsp == frame) return 0; /* no signals delivered */ - setup_frame(regs, (struct sigregs *) frame, newsp); + if (ka->sa.sa_flags & SA_SIGINFO) + setup_rt_frame(regs, (struct sigregs *) frame, newsp); + else + setup_frame(regs, (struct sigregs *) frame, newsp); return 1; } diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c index 176a47ca5..8cb68c6b2 100644 --- a/arch/ppc/kernel/smp.c +++ b/arch/ppc/kernel/smp.c @@ -39,7 +39,7 @@ #include <asm/smp.h> #include <asm/gemini.h> -#include "time.h" +#include <asm/time.h> #include "open_pic.h" int smp_threads_ready = 0; volatile int smp_commenced = 0; diff --git a/arch/ppc/kernel/syscalls.c b/arch/ppc/kernel/syscalls.c index 11aa42cad..4c1802135 100644 --- a/arch/ppc/kernel/syscalls.c +++ b/arch/ppc/kernel/syscalls.c @@ -274,3 +274,13 @@ asmlinkage int sys_olduname(struct oldold_utsname * name) error = error ? -EFAULT : 0; return error; } + +#ifndef CONFIG_PCI +/* + * Those are normally defined in arch/ppc/kernel/pci.c. But when CONFIG_PCI is + * not defined, this file is not linked at all, so here are the "empty" versions + */ +asmlinkage int sys_pciconfig_read() { return -ENOSYS; } +asmlinkage int sys_pciconfig_write() { return -ENOSYS; } +asmlinkage long sys_pciconfig_iobase() { return -ENOSYS; } +#endif diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c index 3303bf785..aff4838b3 100644 --- a/arch/ppc/kernel/time.c +++ b/arch/ppc/kernel/time.c @@ -44,7 +44,7 @@ #include <asm/8xx_immap.h> #include <asm/machdep.h> -#include "time.h" +#include <asm/time.h> void smp_local_timer_interrupt(struct pt_regs *); @@ -70,7 +70,9 @@ unsigned long last_tb; int timer_interrupt(struct pt_regs * regs) { int dval, d; +#if 0 unsigned long flags; +#endif unsigned long cpu = smp_processor_id(); hardirq_enter(cpu); @@ -120,6 +122,13 @@ int timer_interrupt(struct pt_regs * regs) if ( !smp_processor_id() ) { do_timer(regs); +#if 0 + /* -- BenH -- I'm removing this for now since it can cause various + * troubles with local-time RTCs. Now that we have a + * /dev/rtc that uses ppc_md.set_rtc_time() on mac, it + * should be possible to program the RTC from userland + * in all cases. + */ /* * update the rtc when needed */ @@ -135,6 +144,7 @@ int timer_interrupt(struct pt_regs * regs) last_rtc_update = xtime.tv_sec; } read_unlock_irqrestore(&xtime_lock, flags); +#endif } #ifdef CONFIG_SMP smp_local_timer_interrupt(regs); diff --git a/arch/ppc/kernel/time.h b/arch/ppc/kernel/time.h deleted file mode 100644 index 05d791546..000000000 --- a/arch/ppc/kernel/time.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * $Id: time.h,v 1.12 1999/08/27 04:21:23 cort Exp $ - * Common time prototypes and such for all ppc machines. - * - * Written by Cort Dougan (cort@cs.nmt.edu) to merge - * Paul Mackerras' version and mine for PReP and Pmac. - */ - -#include <linux/config.h> -#include <linux/mc146818rtc.h> - -#include <asm/processor.h> - -/* time.c */ -extern unsigned decrementer_count; -extern unsigned count_period_num; -extern unsigned count_period_den; -extern unsigned long mktime(unsigned int, unsigned int, unsigned int, - unsigned int, unsigned int, unsigned int); -extern void to_tm(int tim, struct rtc_time * tm); -extern time_t last_rtc_update; - -int via_calibrate_decr(void); - -/* Accessor functions for the decrementer register. */ -static __inline__ unsigned int get_dec(void) -{ -#if defined(CONFIG_4xx) - return (mfspr(SPRN_PIT)); -#else - return (mfspr(SPRN_DEC)); -#endif -} - -static __inline__ void set_dec(unsigned int val) -{ -#if defined(CONFIG_4xx) - mtspr(SPRN_PIT, val); -#else - mtspr(SPRN_DEC, val); -#endif -} diff --git a/arch/ppc/kernel/walnut_setup.c b/arch/ppc/kernel/walnut_setup.c index 284c732c1..768c36a94 100644 --- a/arch/ppc/kernel/walnut_setup.c +++ b/arch/ppc/kernel/walnut_setup.c @@ -28,7 +28,7 @@ #include "local_irq.h" #include "ppc4xx_pic.h" -#include "time.h" +#include <asm/time.h> #include "walnut_setup.h" diff --git a/arch/ppc/mbxboot/m8xx_tty.c b/arch/ppc/mbxboot/m8xx_tty.c index a591d824d..811a13796 100644 --- a/arch/ppc/mbxboot/m8xx_tty.c +++ b/arch/ppc/mbxboot/m8xx_tty.c @@ -21,6 +21,17 @@ #define CSR1_COMEN (u_char)0x02 #endif +#ifdef TQM_SMC2_CONSOLE +#define PROFF_CONS PROFF_SMC2 +#define CPM_CR_CH_CONS CPM_CR_CH_SMC2 +#define SMC_INDEX 1 +static volatile iop8xx_t *iopp = (iop8xx_t *)&(((immap_t *)IMAP_ADDR)->im_ioport); +#else +#define PROFF_CONS PROFF_SMC1 +#define CPM_CR_CH_CONS CPM_CR_CH_SMC1 +#define SMC_INDEX 0 +#endif + static cpm8xx_t *cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm); void @@ -33,8 +44,8 @@ serial_init(bd_t *bd) uint dpaddr, memaddr; cp = cpmp; - sp = (smc_t*)&(cp->cp_smc[0]); - up = (smc_uart_t *)&cp->cp_dparam[PROFF_SMC1]; + sp = (smc_t*)&(cp->cp_smc[SMC_INDEX]); + up = (smc_uart_t *)&cp->cp_dparam[PROFF_CONS]; /* Disable transmitter/receiver. */ @@ -42,18 +53,26 @@ serial_init(bd_t *bd) #ifndef CONFIG_MBX { - /* Initialize SMC1 and use it for the console port. + /* Initialize SMCx and use it for the console port. */ /* Enable SDMA. */ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sdcr = 1; +#ifdef TQM_SMC2_CONSOLE + /* Use Port A for SMC2 instead of other functions. + */ + iopp->iop_papar |= 0x00c0; + iopp->iop_padir &= ~0x00c0; + iopp->iop_paodr &= ~0x00c0; +#else /* Use Port B for SMCs instead of other functions. */ cp->cp_pbpar |= 0x00000cc0; cp->cp_pbdir &= ~0x00000cc0; cp->cp_pbodr &= ~0x00000cc0; +#endif /* Allocate space for two buffer descriptors in the DP ram. * For now, this address seems OK, but it may have to @@ -61,8 +80,7 @@ serial_init(bd_t *bd) */ dpaddr = 0x0800; - /* Grab a few bytes from the top of memory. EPPC-Bug isn't - * running any more, so we can do this. + /* Grab a few bytes from the top of memory for SMC FIFOs. */ memaddr = (bd->bi_memsize - 32) & ~15; @@ -95,9 +113,14 @@ serial_init(bd_t *bd) /* Set up the baud rate generator. * See 8xx_io/commproc.c for details. + * This wires BRG1 to SMC1 and BRG2 to SMC2; */ cp->cp_simode = 0x10000000; +#ifdef TQM_SMC2_CONSOLE + cp->cp_brgc2 = +#else cp->cp_brgc1 = +#endif ((((bd->bi_intfreq * 1000000)/16) / bd->bi_baudrate) << 1) | CPM_BRG_EN; #else /* CONFIG_MBX */ @@ -167,14 +190,14 @@ serial_init(bd_t *bd) } else { #endif /* ndef CONFIG_MBX */ - /* SMC1 is used as console port. + /* SMCx is used as console port. */ tbdf = (cbd_t *)&cp->cp_dpmem[up->smc_tbase]; rbdf = (cbd_t *)&cp->cp_dpmem[up->smc_rbase]; /* Issue a stop transmit, and wait for it. */ - cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC1, + cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_CONS, CPM_CR_STOP_TX) | CPM_CR_FLG; while (cp->cp_cpcr & CPM_CR_FLG); } @@ -191,7 +214,7 @@ serial_init(bd_t *bd) /* Initialize Tx/Rx parameters. */ - cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC1, CPM_CR_INIT_TRX) | CPM_CR_FLG; + cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_CONS, CPM_CR_INIT_TRX) | CPM_CR_FLG; while (cp->cp_cpcr & CPM_CR_FLG); /* Enable transmitter/receiver. @@ -206,7 +229,7 @@ serial_putchar(const char c) volatile char *buf; volatile smc_uart_t *up; - up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC1]; + up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS]; tbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase]; /* Wait for last character to go. @@ -227,7 +250,7 @@ serial_getc() volatile smc_uart_t *up; char c; - up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC1]; + up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS]; rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase]; /* Wait for character to show up. @@ -246,7 +269,7 @@ serial_tstc() volatile cbd_t *rbdf; volatile smc_uart_t *up; - up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC1]; + up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS]; rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase]; return(!(rbdf->cbd_sc & BD_SC_EMPTY)); diff --git a/arch/ppc/mbxboot/misc.c b/arch/ppc/mbxboot/misc.c index d5a44df1e..60563122d 100644 --- a/arch/ppc/mbxboot/misc.c +++ b/arch/ppc/mbxboot/misc.c @@ -225,7 +225,9 @@ void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) s.avail_out = dstlen; r = inflate(&s, Z_FINISH); if (r != Z_OK && r != Z_STREAM_END) { - puts("inflate returned %d\n"); + puts("inflate returned "); + puthex(r); + puts("\n"); exit(); } *lenp = s.next_out - (unsigned char *) dst; diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index 0cfb5916c..16c3bc694 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -931,6 +931,9 @@ MMU_init(void) /* How about ppc_md.md_find_end_of_memory instead of these * ifdefs? -- Dan. */ +#ifdef CONFIG_BOOTX_TEXT +extern boot_infos_t *disp_bi; +#endif void __init MMU_init(void) { if ( ppc_md.progress ) ppc_md.progress("MMU:enter", 0x111); @@ -1050,6 +1053,11 @@ void __init MMU_init(void) #endif #endif /* CONFIG_8xx */ if ( ppc_md.progress ) ppc_md.progress("MMU:exit", 0x211); +#ifdef CONFIG_BOOTX_TEXT + /* Must be done last, or ppc_md.progress will die */ + if (_machine == _MACH_Pmac) + map_bootx_text(); +#endif } #endif /* CONFIG_4xx */ diff --git a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c index 4abc138cf..75160d9b8 100644 --- a/arch/ppc/xmon/xmon.c +++ b/arch/ppc/xmon/xmon.c @@ -84,8 +84,10 @@ static void insert_bpts(void); static struct bpt *at_breakpoint(unsigned pc); static void bpt_cmds(void); static void cacheflush(void); +#if 0 /* Makes compile with -Wall */ static char *pretty_print_addr(unsigned long addr); static char *lookup_name(unsigned long addr); +#endif static void csum(void); extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned); @@ -1493,6 +1495,7 @@ char *str; lineptr = str; } +#if 0 /* Makes compile with -Wall */ static char *pretty_print_addr(unsigned long addr) { printf("%08x", addr); @@ -1500,14 +1503,15 @@ static char *pretty_print_addr(unsigned long addr) printf(" %s", lookup_name(addr) ); return NULL; } +#endif +#if 0 /* Makes compile with -Wall */ static char *lookup_name(unsigned long addr) { extern char *sysmap; extern unsigned long sysmap_size; char *c = sysmap; unsigned long cmp; - if ( !sysmap || !sysmap_size ) return NULL; return NULL; @@ -1525,4 +1529,4 @@ return NULL; return last; #endif } - +#endif |