There are four types of PowerPC chips supported. The more common
types (601, 603, 604, 740, 750), the Motorola embedded versions
(821, 823, 850, 855, 860), the IBM embedded versions (403 and
- 405) and the high end 64 bit Power processors (Power 3, Power 4).
- Unless you are building a kernel for one of the embedded
- processor systems, or a 64 bit IBM RS/6000, choose 6xx.
-
-CONFIG_PPC64BRIDGE
- Currently there is not a 64 bit PowerPC Linux kernel. As a result
- if you choose the CONFIG_POWER3 or CONFIG_POWER4 options you
- must choose this option as well. This enables gcc to emit
- both 32 and 64 bit instructions as well as cause your kernel
- to be built as a 32 bit kernel.
+ 405) and the high end 64 bit Power processors (Power 3, Power 4).
+ Unless you are building a kernel for one of the embedded
+ processor systems, or a 64 bit IBM RS/6000, choose 6xx. Note that
+ the kernel runs in 32-bit mode even on 64-bit chips.
Machine Type
CONFIG_PMAC
@@ -12,6+12,13 @@ CONFIG_UID16=y # CONFIG_EXPERIMENTAL is not set
#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KMOD is not set
+
+#
# Processor type and features
#
# CONFIG_M386 is not set
@@ -48,13+55,6 @@ CONFIG_SMP=y CONFIG_HAVE_DEC_LOCK=y
#
-# Loadable module support
-#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
-
-#
# General setup
#
CONFIG_NET=y
@@ -91,6+91,8 @@ static void disable_cobalt_irq(unsigned int irq); static void startup_cobalt_irq(unsigned int irq);
#define shutdown_cobalt_irq disable_cobalt_irq
+static spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED;
+
static struct hw_interrupt_type cobalt_irq_type = {
"Cobalt-APIC",
startup_cobalt_irq,
/*
* Reset a Cobalt Qube.
*/
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <asm/io.h>
#include <asm/pci/bridge.h>
#include <asm/paccess.h>
#include <asm/sn/sn0/ip27.h>
-#include <asm/sn/sn0/hubio.h>
/* Check against user dumbness. */
#ifdef CONFIG_VT
@@ -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
@@ -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 */
* 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
* 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
#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;
}
+
@@ -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
@@ -26,12+26,14 @@ 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
@@ -52,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
@@ -63,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
@@ -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
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)
-/*
- * Copyright (C) 1996 Paul Mackerras.
- */
-
-#include <linux/kernel.h>
-#include <asm/bitops.h>
-
-/*
- * I left these here since the problems with "cc" make it difficult to keep
- * them in bitops.h -- Cort
- */
-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
- bne 1b"
- : "=&r" (t) /*, "=m" (*p)*/
- : "r" (mask), "r" (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);
-
- 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
- bne 1b"
- : "=&r" (t) /*, "=m" (*p)*/
- : "r" (mask), "r" (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);
-
- 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
- bne 1b"
- : "=&r" (t) /*, "=m" (*p)*/
- : "r" (mask), "r" (p)
- : "cc");
-}
-
-int test_and_set_bit(int nr, volatile void *addr)
-{
- unsigned int old, 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 "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
- bne 1b"
- : "=&r" (old), "=&r" (t) /*, "=m" (*p)*/
- : "r" (mask), "r" (p)
- : "cc");
-
- return (old & mask) != 0;
-}
-
-int test_and_clear_bit(int nr, volatile void *addr)
-{
- unsigned int old, 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 "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
- bne 1b"
- : "=&r" (old), "=&r" (t) /*, "=m" (*p)*/
- : "r" (mask), "r" (p)
- : "cc");
-
- return (old & mask) != 0;
-}
-
-int test_and_change_bit(int nr, volatile void *addr)
-{
- unsigned int old, 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 "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
- bne 1b"
- : "=&r" (old), "=&r" (t) /*, "=m" (*p)*/
- : "r" (mask), "r" (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
+/*
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+
+#include <linux/kernel.h>
+#include <asm/bitops.h>
+
+/*
+ * If the bitops are not inlined in bitops.h, they are defined here.
+ * -- paulus
+ */
+#if !__INLINE_BITOPS
+void set_bit(int nr, volatile void * addr)
+{
+ 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"
+ SMP_MB
+ : "=&r" (old), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc" );
+}
+
+void clear_bit(int nr, volatile void *addr)
+{
+ 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
+ andc %0,%0,%2
+ stwcx. %0,0,%3
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc");
+}
+
+void change_bit(int nr, volatile void *addr)
+{
+ 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
+ xor %0,%0,%2
+ stwcx. %0,0,%3
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc");
+}
+
+int test_and_set_bit(int nr, volatile void *addr)
+{
+ unsigned int old, t;
+ unsigned int mask = 1 << (nr & 0x1f);
+ volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
+
+ __asm__ __volatile__(SMP_WMB "\
+1: lwarx %0,0,%4
+ or %1,%0,%3
+ stwcx. %1,0,%4
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=&r" (t), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc");
+
+ return (old & mask) != 0;
+}
+
+int test_and_clear_bit(int nr, volatile void *addr)
+{
+ unsigned int old, t;
+ unsigned int mask = 1 << (nr & 0x1f);
+ volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
+
+ __asm__ __volatile__(SMP_WMB "\
+1: lwarx %0,0,%4
+ andc %1,%0,%3
+ stwcx. %1,0,%4
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=&r" (t), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc");
+
+ return (old & mask) != 0;
+}
+
+int test_and_change_bit(int nr, volatile void *addr)
+{
+ unsigned int old, t;
+ unsigned int mask = 1 << (nr & 0x1f);
+ volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
+
+ __asm__ __volatile__(SMP_WMB "\
+1: lwarx %0,0,%4
+ xor %1,%0,%3
+ stwcx. %1,0,%4
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=&r" (t), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc");
+
+ return (old & mask) != 0;
+}
+#endif /* !__INLINE_BITOPS */
@@ -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;
#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"
#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;
*
* 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
* 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
#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 */
+}
+
#include <asm/m48t35.h>
#include <asm/gemini.h>
-#include "time.h"
+#include <asm/time.h>
#include "local_irq.h"
#include "open_pic.h"
@@ -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
@@ -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())
#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);
#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);
@@ -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
#include "local_irq.h"
#include "ppc4xx_pic.h"
-#include "time.h"
+#include <asm/time.h>
#include "oak_setup.h"
@@ -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;
}
}
*/
#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>
#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;
+}
+
--- /dev/null
+/*
+ * 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;
+}
#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
@@ -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.
@@ -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
{
#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;
#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;
+ }
}
/*
#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);
#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"
#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
@@ -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))
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)--;
@@ -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"))
/*
* 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;
}
#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;
@@ -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
#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);
#include "local_irq.h"
#include "ppc4xx_pic.h"
-#include "time.h"
+#include <asm/time.h>
#include "walnut_setup.h"
#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));
@@ -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;
@@ -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 */
@@ -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
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/slab.h>
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/slab.h>
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pm.h>
#include <linux/acpi.h>
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
@@ -7,9+7,7 @@ comment 'Joysticks'
tristate 'Joystick support' CONFIG_JOYSTICK
if [ "$CONFIG_JOYSTICK" != "n" ]; then
-
- define_tristate CONFIG_USB $CONFIG_JOYSTICK
- define_tristate CONFIG_INPUT_JOYDEV $CONFIG_JOYSTICK
+ define_tristate CONFIG_INPUT_JOYDEV $CONFIG_JOYSTICK
comment 'Game port support'
dep_tristate ' ns558 gameports' CONFIG_INPUT_NS558 $CONFIG_JOYSTICK
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -507,19+506,24 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, * up things on a close.
*/
+/* We use rtc_lock to protect against concurrent opens. So the BKL is not
+ * needed here. Or anywhere else in this driver. */
static int rtc_open(struct inode *inode, struct file *file)
{
- /* If someday somebody decides to remove the kernel_lock on open and
- * close and ioctl this is gonna get open to races */
+ spin_lock_irq (&rtc_lock);
+
if(rtc_status & RTC_IS_OPEN)
- return -EBUSY;
+ goto out_busy;
rtc_status |= RTC_IS_OPEN;
- spin_lock_irq (&rtc_lock);
rtc_irq_data = 0;
spin_unlock_irq (&rtc_lock);
return 0;
+
+out_busy:
+ spin_unlock_irq (&rtc_lock);
+ return -EBUSY;
}
static int rtc_fasync (int fd, struct file *filp, int on)
@@ -538,7+542,6 @@ static int rtc_release(struct inode *inode, struct file *file)
unsigned char tmp;
- lock_kernel();
spin_lock_irq(&rtc_lock);
tmp = CMOS_READ(RTC_CONTROL);
tmp &= ~RTC_PIE;
@@ -556,16+559,15 @@ static int rtc_release(struct inode *inode, struct file *file) if (file->f_flags & FASYNC) {
rtc_fasync (-1, file, 0);
}
-
-#else
- lock_kernel();
#endif
spin_lock_irq (&rtc_lock);
rtc_irq_data = 0;
spin_unlock_irq (&rtc_lock);
- rtc_status = rtc_status & ~RTC_IS_OPEN;
- unlock_kernel();
+
+ /* No need for locking -- nobody else can do anything until this rmw is
+ * committed, and no timer is running. */
+ rtc_status &= ~RTC_IS_OPEN;
return 0;
}
-# $Id: Config.in,v 1.18 2000/07/12 13:43:24 dwmw2 Exp $
+# $Id: Config.in,v 1.20 2000/07/13 12:40:46 scote1 Exp $
mainmenu_option next_comment
comment 'Memory Technology Devices (MTD)'
@@ -25,10+25,15 @@ if [ "$CONFIG_MTD" != "n" ]; then bool ' PMC551 256M DRAM Bugfix' CONFIG_MTD_PMC551_BUGFIX
fi
dep_tristate ' Debugging RAM test driver' CONFIG_MTD_MTDRAM $CONFIG_MTD
+ if [ "$CONFIG_MTD_MTDRAM" != "n" ]; then
+ int 'Device size in kB' CONFIG_MTDRAM_TOTAL_SIZE 4096
+ int 'Size of the erase sectors in kB' CONFIG_MTDRAM_ERASE_SIZE 128
+ fi
comment 'MTD drivers for mapped chips'
dep_tristate ' Common Flash Interface (CFI) support' CONFIG_MTD_CFI $CONFIG_MTD
dep_tristate ' CFI support for Intel/Sharp Extended Command Set chips' CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_CFI
+ dep_tristate ' CFI support for AMD/Fujitsu Standard Command Set chips' CONFIG_MTD_CFI_AMDSTD $CONFIG_MTD_CFI
# These will later become config-options
define_bool CONFIG_MTD_JEDEC n
@@ -45,6+50,7 @@ comment 'Drivers for chip mappings' dep_tristate ' Flash chip mapping on Mixcom piggyback card' CONFIG_MTD_MIXMEM $CONFIG_MTD_JEDEC
dep_tristate ' Flash chip mapping on Nora' CONFIG_MTD_NORA $CONFIG_MTD_CFI
dep_tristate ' Flash chip mapping on Octagon 5066 SBC' CONFIG_MTD_OCTAGON $CONFIG_MTD_JEDEC
+ dep_tristate ' Flash chip mapping on Photron PNC-2000' CONFIG_MTD_PNC2000 $CONFIG_MTD_CFI
dep_tristate ' Flash chip mapping on RPXLite PPC board' CONFIG_MTD_RPXLITE $CONFIG_MTD_CFI
dep_tristate ' Flash chip mapping on Tempustech VMAX SBC301' CONFIG_MTD_VMAX $CONFIG_MTD_JEDEC
-# $Id: Makefile,v 1.20 2000/07/04 08:58:10 dwmw2 Exp $
+# $Id: Makefile,v 1.21 2000/07/13 10:42:55 dwmw2 Exp $
# Uncomment this to enable the DBG macro (see mtd.h)
#CFLAGS+= -DZDBG
endif
endif
+ifeq ($(CONFIG_MTD_CFI_AMDSTD),y)
+ OX_OBJS += cfi_cmdset_0002.o
+else
+ ifeq ($(CONFIG_MTD_CFI_AMDSTD),m)
+ MX_OBJS += cfi_cmdset_0002.o
+ endif
+endif
+
ifeq ($(CONFIG_MTD_DOC1000),y)
O_OBJS += doc1000.o
else
endif
endif
+ifeq ($(CONFIG_MTD_PNC2000),y)
+ O_OBJS += pnc2000.o
+else
+ ifeq ($(CONFIG_MTD_PNC2000),m)
+ M_OBJS += pnc2000.o
+ endif
+endif
+
ifeq ($(CONFIG_FTL),y)
O_OBJS += ftl.o
else
*
* (C) 2000 Red Hat. GPL'd
*
- * $Id: cfi_cmdset_0001.c,v 1.20 2000/07/04 07:36:43 dwmw2 Exp $
+ * $Id: cfi_cmdset_0001.c,v 1.21 2000/07/13 10:36:14 dwmw2 Exp $
*/
#include <linux/module.h>
@@ -455,13+455,9 @@ static inline int do_write_1_by_16_oneword(struct map_info *map, struct flchip * chip->word_write_time--;
if (!chip->word_write_time)
chip->word_write_time++;
- else
- printk("decreasing word_write_time to %d µs\n", chip->word_write_time);
}
- if (z > 100) {
+ if (z > 1)
chip->word_write_time++;
- printk("increasing word_write_time to %d µs\n", chip->word_write_time);
- }
/* Done and happy. */
chip->state = FL_STATUS;
--- /dev/null
+/*
+ * Common Flash Interface support:
+ * AMD & Fujitsu Extended Vendor Command Set (ID 0x0002)
+ *
+ * Copyright (C) 2000 Crossnet Co. <info@crossnet.co.jp>
+ *
+ * This code is GPL
+ *
+ * $Id: cfi_cmdset_0002.c,v 1.1 2000/07/11 12:32:09 dwmw2 Exp $
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+
+#include <linux/errno.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/cfi.h>
+
+#if LINUX_VERSION_CODE < 0x20300
+#define set_current_state(x) current->state = (x);
+#endif
+
+static int cfi_amdext_read_2_by_16 (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
+static int cfi_amdext_write_2_by_16(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
+static int cfi_amdext_erase_2_by_16 (struct mtd_info *, struct erase_info *);
+static void cfi_amdext_sync (struct mtd_info *);
+static int cfi_amdext_suspend (struct mtd_info *);
+static void cfi_amdext_resume (struct mtd_info *);
+
+static void cfi_amdext_destroy(struct mtd_info *);
+
+void cfi_cmdset_0002(struct map_info *, int, unsigned long);
+EXPORT_SYMBOL(cfi_cmdset_0002);
+
+struct mtd_info *cfi_amdext_setup (struct map_info *);
+
+void cfi_cmdset_0002(struct map_info *map, int primary, unsigned long base)
+{
+ struct cfi_private *cfi = map->fldrv_priv;
+ int i;
+// struct cfi_pri_intelext *extp;
+
+ __u16 adr = primary?cfi->cfiq.P_ADR:cfi->cfiq.A_ADR;
+
+ printk(" Amd/Fujitsu Extended Query Table at 0x%4.4X\n", adr);
+
+
+ /* If there was an old setup function, decrease its use count */
+ if (cfi->cmdset_setup)
+ put_module_symbol((unsigned long)cfi->cmdset_setup);
+ if (cfi->cmdset_priv)
+ kfree(cfi->cmdset_priv);
+
+ for (i=0; i< cfi->numchips; i++) {
+ cfi->chips[i].word_write_time = 128;
+ cfi->chips[i].buffer_write_time = 128;
+ cfi->chips[i].erase_time = 1024;
+ }
+
+
+ cfi->cmdset_setup = cfi_amdext_setup;
+// cfi->cmdset_priv = extp;
+ MOD_INC_USE_COUNT; /* So the setup function is still there
+ * by the time it's called */
+
+ return;
+}
+
+struct mtd_info *cfi_amdext_setup(struct map_info *map)
+{
+ struct cfi_private *cfi = map->fldrv_priv;
+ struct mtd_info *mtd;
+
+ mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
+ printk("number of CFI chips: %d\n", cfi->numchips);
+
+ if (!mtd) {
+ printk("Failed to allocate memory for MTD device\n");
+ kfree(cfi->cmdset_priv);
+ return NULL;
+ }
+
+ memset(mtd, 0, sizeof(*mtd));
+ mtd->priv = map;
+ mtd->type = MTD_NORFLASH;
+ mtd->erasesize = 0x20000; /* FIXME */
+ /* Also select the correct geometry setup too */
+ mtd->size = (1 << cfi->cfiq.DevSize) * cfi->numchips * cfi->interleave;
+ mtd->erase = cfi_amdext_erase_2_by_16;
+ mtd->read = cfi_amdext_read_2_by_16;
+ mtd->write = cfi_amdext_write_2_by_16;
+ mtd->sync = cfi_amdext_sync;
+ mtd->suspend = cfi_amdext_suspend;
+ mtd->resume = cfi_amdext_resume;
+ mtd->flags = MTD_CAP_NORFLASH;
+ map->fldrv_destroy = cfi_amdext_destroy;
+ mtd->name = map->name;
+ return mtd;
+}
+
+static inline int do_read_2_by_16_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ unsigned long timeo = jiffies + HZ;
+
+ retry:
+ spin_lock_bh(chip->mutex);
+
+ if (chip->state != FL_READY){
+printk("Waiting for chip to read, status = %d\n", chip->state);
+ set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(&chip->wq, &wait);
+
+ spin_unlock_bh(chip->mutex);
+
+ schedule();
+ remove_wait_queue(&chip->wq, &wait);
+
+ if(signal_pending(current))
+ return -EINTR;
+
+ timeo = jiffies + HZ;
+
+ goto retry;
+ }
+
+ adr += chip->start;
+
+// map->write32(map, cpu_to_le32(0x00F000F0), adr);
+
+ chip->state = FL_READY;
+
+ map->copy_from(map, buf, adr, len);
+
+ wake_up(&chip->wq);
+ spin_unlock_bh(chip->mutex);
+
+ return 0;
+}
+
+static int cfi_amdext_read_2_by_16 (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
+{
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+ unsigned long ofs;
+ int chipnum;
+ int ret = 0;
+
+ /* ofs: offset within the first chip that the first read should start */
+
+ chipnum = (from >> cfi->chipshift);
+ chipnum /= (cfi->interleave);
+ ofs = from - (chipnum << cfi->chipshift) * (cfi->interleave);
+
+ *retlen = 0;
+
+ while (len) {
+ unsigned long thislen;
+
+ if (chipnum >= cfi->numchips)
+ break;
+
+ if (((len + ofs -1) >> cfi->chipshift) / (cfi->interleave))
+ thislen = (1<<cfi->chipshift) * (cfi->interleave) - ofs;
+ else
+ thislen = len;
+
+ ret = do_read_2_by_16_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf);
+ if (ret)
+ break;
+
+ *retlen += thislen;
+ len -= thislen;
+ buf += thislen;
+
+ ofs = 0;
+ chipnum++;
+ }
+ return ret;
+}
+
+static inline int do_write_2_by_16_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, __u32 datum)
+{
+ unsigned long timeo = jiffies + HZ;
+ unsigned int Last[4];
+ unsigned long Count = 0;
+ DECLARE_WAITQUEUE(wait, current);
+ int ret = 0;
+
+ retry:
+ spin_lock_bh(chip->mutex);
+
+ if (chip->state != FL_READY){
+printk("Waiting for chip to write, status = %d\n", chip->state);
+ set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(&chip->wq, &wait);
+
+ spin_unlock_bh(chip->mutex);
+
+ schedule();
+ remove_wait_queue(&chip->wq, &wait);
+printk("Wake up to write:\n");
+ if(signal_pending(current))
+ return -EINTR;
+
+ timeo = jiffies + HZ;
+
+ goto retry;
+ }
+
+ chip->state = FL_WRITING;
+
+ adr += chip->start;
+
+ map->write32(map, cpu_to_le32(0x00AA00AA), 0x555 *4);
+ map->write32(map, cpu_to_le32(0x00550055), 0x2AA *4);
+ map->write32(map, cpu_to_le32(0x00A000A0), 0x555 *4);
+ map->write32(map, cpu_to_le32(datum), adr);
+
+ spin_unlock_bh(chip->mutex);
+ udelay(chip->word_write_time);
+ spin_lock_bh(chip->mutex);
+
+ Last[0] = map->read32(map, adr);
+ Last[1] = map->read32(map, adr);
+ Last[2] = map->read32(map, adr);
+
+ for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] && Count < 10000; Count++){
+ udelay(10);
+
+ Last[Count % 4] = map->read32(map, adr);
+ }
+
+ if (Last[(Count - 1) % 4] != datum){
+ map->write32(map, cpu_to_le32(0x00F000F0), adr);
+ ret = -EIO;
+ }
+
+ chip->state = FL_READY;
+ wake_up(&chip->wq);
+ spin_unlock_bh(chip->mutex);
+
+ return ret;
+}
+
+
+static int cfi_amdext_write_2_by_16 (struct mtd_info *mtd, loff_t to , size_t len, size_t *retlen, const u_char *buf)
+{
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+ int ret = 0;
+ int chipnum;
+ unsigned long ofs;
+
+ *retlen = 0;
+
+ chipnum = (to >> cfi->chipshift);
+ chipnum /= cfi->interleave;
+ ofs = to - (chipnum << cfi->chipshift) * cfi->interleave;
+
+ while(len > 3) {
+
+ ret = do_write_2_by_16_oneword(map, &cfi->chips[chipnum],
+ ofs, *(__u32 *)buf);
+ if (ret)
+ return ret;
+
+ ofs += 4;
+ buf += 4;
+ (*retlen) += 4;
+ len -= 4;
+
+ if ((ofs >> cfi->chipshift) / cfi->interleave) {
+ chipnum ++;
+ ofs = 0;
+ if (chipnum == cfi->numchips)
+ return 0;
+ }
+ }
+
+ if (len) {
+ unsigned int tmp;
+
+ /* Final byte to write */
+#if defined(__LITTLE_ENDIAN)
+ tmp = map->read32(map, ofs);
+
+ tmp = 0xffffffff >> (len*8);
+ tmp = tmp << (len*8);
+
+ tmp |= *(__u32 *)(buf);
+
+ ret = do_write_2_by_16_oneword(map, &cfi->chips[chipnum],
+ ofs, tmp);
+
+#elif defined(__BIG_ENDIAN)
+#error not support big endian yet
+#else
+#error define a sensible endianness
+#endif
+
+ if (ret)
+ return ret;
+
+ (*retlen)+=len;
+ }
+
+ return 0;
+}
+
+
+static inline int do_erase_2_by_16_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr)
+{
+ unsigned int status;
+ unsigned long timeo = jiffies + HZ;
+ DECLARE_WAITQUEUE(wait, current);
+
+ retry:
+ spin_lock_bh(chip->mutex);
+
+ if (chip->state != FL_READY){
+ set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(&chip->wq, &wait);
+
+ spin_unlock_bh(chip->mutex);
+
+ schedule();
+ remove_wait_queue(&chip->wq, &wait);
+
+ if(signal_pending(current))
+ return -EINTR;
+
+ timeo = jiffies + HZ;
+
+ goto retry;
+ }
+
+ chip->state = FL_ERASING;
+
+ adr += chip->start;
+
+ map->write32(map, cpu_to_le32(0x00AA00AA), 0x555 *4);
+ map->write32(map, cpu_to_le32(0x00550055), 0x2AA *4);
+ map->write32(map, cpu_to_le32(0x00800080), 0x555 *4);
+ map->write32(map, cpu_to_le32(0x00AA00AA), 0x555 *4);
+ map->write32(map, cpu_to_le32(0x00550055), 0x2AA *4);
+ map->write32(map, cpu_to_le32(0x00300030), adr);
+
+
+ timeo = jiffies + (HZ*20);
+
+ spin_unlock_bh(chip->mutex);
+ schedule_timeout(HZ);
+ spin_lock_bh(chip->mutex);
+
+ /* FIXME. Use a timer to check this, and return immediately. */
+ /* Once the state machine's known to be working I'll do that */
+
+ while ( ( (status = le32_to_cpu(map->read32(map, 0x00))) & 0x80808080 ) != 0x80808080 ) {
+ static int z=0;
+
+ if (chip->state != FL_ERASING) {
+ /* Someone's suspended the erase. Sleep */
+ set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(&chip->wq, &wait);
+
+ spin_unlock_bh(chip->mutex);
+ printk("erase suspended. Sleeping\n");
+
+ schedule();
+ remove_wait_queue(&chip->wq, &wait);
+
+ if (signal_pending(current))
+ return -EINTR;
+
+ timeo = jiffies + (HZ*2); /* FIXME */
+ spin_lock_bh(chip->mutex);
+ continue;
+ }
+
+ /* OK Still waiting */
+ if (time_after(jiffies, timeo)) {
+ chip->state = FL_READY;
+ spin_unlock_bh(chip->mutex);
+ printk("waiting for erase to complete timed out.");
+ return -EIO;
+ }
+
+ /* Latency issues. Drop the lock, wait a while and retry */
+ spin_unlock_bh(chip->mutex);
+
+ z++;
+ if ( 0 && !(z % 100 ))
+ printk("chip not ready yet after erase. looping\n");
+
+ udelay(1);
+
+ spin_lock_bh(chip->mutex);
+ continue;
+ }
+
+ /* Done and happy. */
+ chip->state = FL_READY;
+ wake_up(&chip->wq);
+ spin_unlock_bh(chip->mutex);
+ printk("erase ret OK\n");
+ return 0;
+}
+
+static int cfi_amdext_erase_2_by_16 (struct mtd_info *mtd, struct erase_info *instr)
+{
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+ unsigned long adr, len;
+ int chipnum, ret = 0;
+
+//printk("erase : 0x%x 0x%x 0x%x\n", instr->addr, instr->len, mtd->size);
+
+ if (instr->addr & (mtd->erasesize - 1))
+ return -EINVAL;
+
+ if (instr->len & (mtd->erasesize -1))
+ return -EINVAL;
+
+ if ((instr->len + instr->addr) > mtd->size)
+ return -EINVAL;
+
+ chipnum = instr->addr >> cfi->chipshift;
+ chipnum /= cfi->interleave;
+ adr = instr->addr - (chipnum << cfi->chipshift) * (cfi->interleave);
+ len = instr->len;
+
+printk("erase : 0x%x 0x%x 0x%x\n", adr, len, chipnum, mtd->size);
+
+ while(len) {
+//printk("erase : 0x%x 0x%x 0x%x 0x%x\n", chipnum, adr, len, cfi->chipshift);
+ ret = do_erase_2_by_16_oneblock(map, &cfi->chips[chipnum], adr);
+
+ if (ret)
+ return ret;
+
+ adr += mtd->erasesize;
+ len -= mtd->erasesize;
+
+ if ((adr >> cfi->chipshift) / (cfi->interleave)) {
+ adr = 0;
+ chipnum++;
+
+ if (chipnum >= cfi->numchips)
+ break;
+ }
+ }
+
+ if (instr->callback)
+ instr->callback(instr);
+
+ return 0;
+}
+
+
+
+static void cfi_amdext_sync (struct mtd_info *mtd)
+{
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+ int i;
+ struct flchip *chip;
+ int ret = 0;
+ DECLARE_WAITQUEUE(wait, current);
+printk("sync\n");
+
+ for (i=0; !ret && i<cfi->numchips; i++) {
+ chip = &cfi->chips[i];
+
+ retry:
+ spin_lock_bh(chip->mutex);
+
+ switch(chip->state) {
+ case FL_READY:
+ case FL_STATUS:
+ case FL_CFI_QUERY:
+ case FL_JEDEC_QUERY:
+ chip->oldstate = chip->state;
+ chip->state = FL_SYNCING;
+ /* No need to wake_up() on this state change -
+ * as the whole point is that nobody can do anything
+ * with the chip now anyway.
+ */
+ spin_unlock_bh(chip->mutex);
+ break;
+
+ default:
+ /* Not an idle state */
+ add_wait_queue(&chip->wq, &wait);
+
+ spin_unlock_bh(chip->mutex);
+ schedule();
+
+ goto retry;
+ }
+ }
+
+ /* Unlock the chips again */
+
+ for (i--; i >=0; i--) {
+ chip = &cfi->chips[i];
+
+ spin_lock_bh(chip->mutex);
+
+ if (chip->state == FL_SYNCING) {
+ chip->state = chip->oldstate;
+ wake_up(&chip->wq);
+ }
+ spin_unlock_bh(chip->mutex);
+ }
+printk("sync end\n");
+}
+
+
+static int cfi_amdext_suspend(struct mtd_info *mtd)
+{
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+ int i;
+ struct flchip *chip;
+ int ret = 0;
+//printk("suspend\n");
+
+ for (i=0; !ret && i<cfi->numchips; i++) {
+ chip = &cfi->chips[i];
+
+ spin_lock_bh(chip->mutex);
+
+ switch(chip->state) {
+ case FL_READY:
+ case FL_STATUS:
+ case FL_CFI_QUERY:
+ case FL_JEDEC_QUERY:
+ chip->oldstate = chip->state;
+ chip->state = FL_PM_SUSPENDED;
+ /* No need to wake_up() on this state change -
+ * as the whole point is that nobody can do anything
+ * with the chip now anyway.
+ */
+ spin_unlock_bh(chip->mutex);
+ break;
+
+ default:
+ ret = -EAGAIN;
+ break;
+ }
+ }
+
+ /* Unlock the chips again */
+
+ for (i--; i >=0; i--) {
+ chip = &cfi->chips[i];
+
+ spin_lock_bh(chip->mutex);
+
+ if (chip->state == FL_PM_SUSPENDED) {
+ chip->state = chip->oldstate;
+ wake_up(&chip->wq);
+ }
+ spin_unlock_bh(chip->mutex);
+ }
+
+ return ret;
+}
+
+static void cfi_amdext_resume(struct mtd_info *mtd)
+{
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+ int i;
+ struct flchip *chip;
+//printk("resume\n");
+
+ for (i=0; i<cfi->numchips; i++) {
+
+ chip = &cfi->chips[i];
+
+ spin_lock_bh(chip->mutex);
+
+ if (chip->state == FL_PM_SUSPENDED) {
+ chip->state = chip->oldstate;
+ wake_up(&chip->wq);
+ }
+ else
+ printk("Argh. Chip not in PM_SUSPENDED state upon resume()\n");
+
+ spin_unlock_bh(chip->mutex);
+ }
+}
+
+static void cfi_amdext_destroy(struct mtd_info *mtd)
+{
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+ kfree(cfi->cmdset_priv);
+ kfree(cfi);
+}
+
/* Linux driver for Disk-On-Chip 2000 */
/* (c) 1999 Machine Vision Holdings, Inc. */
/* Author: David Woodhouse <dwmw2@mvhi.com> */
-/* $Id: doc2000.c,v 1.23 2000/07/03 10:01:38 dwmw2 Exp $ */
+/* $Id: doc2000.c,v 1.24 2000/07/13 10:03:31 dwmw2 Exp $ */
#include <linux/kernel.h>
#include <linux/module.h>
@@ -36,7+36,7 @@ static struct mtd_info *doc2klist = NULL;
/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
-int _DoC_WaitReady (unsigned long docptr)
+static int _DoC_WaitReady (unsigned long docptr)
{
//long c=-1;
short c=-1;
@@ -148,7+148,7 @@ static inline int DoC_SelectFloor(unsigned long docptr, int floor)
/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */
-int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
+static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
{
int mfr, id, chipshift=0;
char *mfrname=NULL, *idname=NULL;
@@ -302,7+302,7 @@ int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */
-void DoC_ScanChips(struct DiskOnChip *this)
+static void DoC_ScanChips(struct DiskOnChip *this)
{
int floor, chip;
int numchips[MAX_FLOORS];
-
/* Linux driver for Disk-On-Chip Millennium */
/* (c) 1999 Machine Vision Holdings, Inc. */
/* Author: David Woodhouse <dwmw2@mvhi.com> */
-/* $Id: doc2001.c,v 1.4 2000/07/03 10:01:38 dwmw2 Exp $ */
+/* $Id: doc2001.c,v 1.7 2000/07/13 10:41:39 dwmw2 Exp $ */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/doc2000.h>
-
-
-//#define PRERELEASE
-#if 0
-static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
-static int doc_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
-static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eecbuf);
-static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf);
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, u_char *buf);
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, const u_char *buf);
+static struct {
+ char * name;
+ int manufacture_id;
+ int model_id;
+ int chipshift;
+} nand_flash_ids[] = {
+ {"Toshiba TC5816BDC", NAND_MFR_TOSHIBA, 0x64, 21},
+ {"Toshiba TC5832DC", NAND_MFR_TOSHIBA, 0x6b, 22},
+ {"Toshiba TH58V128DC", NAND_MFR_TOSHIBA, 0x73, 24},
+ {"Toshiba TC58256FT/DC", NAND_MFR_TOSHIBA, 0x75, 25},
+ {"Toshiba TC58V32DC", NAND_MFR_TOSHIBA, 0xe5, 22},
+ {"Toshiba TC58V64DC", NAND_MFR_TOSHIBA, 0xe6, 23},
+ {"Toshiba TC58V16BDC", NAND_MFR_TOSHIBA, 0xea, 21},
+ {"Samsung KM29N16000", NAND_MFR_SAMSUNG, 0x64, 21},
+ {"Samsung KM29U128T", NAND_MFR_SAMSUNG, 0x73, 24},
+ {"Samsung KM29U256T", NAND_MFR_SAMSUNG, 0x75, 25},
+ {"Samsung KM29W32000", NAND_MFR_SAMSUNG, 0xe3, 22},
+ {"Samsung KM29U64000", NAND_MFR_SAMSUNG, 0xe6, 23},
+ {"Samsung KM29W16000", NAND_MFR_SAMSUNG, 0xea, 21},
+ {NULL,}
+};
+
+static int doc_read (struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf);
+static int doc_write (struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf);
+static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf, u_char *eecbuf);
+static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf, u_char *eccbuf);
+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
+ size_t *retlen, u_char *buf);
+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
+ size_t *retlen, const u_char *buf);
static int doc_erase (struct mtd_info *mtd, struct erase_info *instr);
-#endif
static struct mtd_info *docmillist = NULL;
-/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
-
-int _DoC_WaitReady (unsigned long docptr)
+static void DoC_Delay(unsigned long docptr, unsigned short cycles)
{
- //long c=-1;
- short c=-1;
+ volatile char dummy;
+ int i;
- DEBUG(2,"_DoC_WaitReady called for out-of-line wait\n");
+ for (i = 0; i < cycles; i++)
+ dummy = ReadDOC(docptr, NOP);
+}
+
+/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
+static int _DoC_WaitReady(unsigned long docptr)
+{
+ unsigned short c = 0xffff;
/* Out-of-line routine to wait for chip response */
while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c)
;
- if (c == 0)
- DEBUG(2, "_DoC_WaitReady timed out.\n");
-
- return (c==0);
+ return (c == 0);
}
-static inline int DoC_WaitReady(unsigned long docptr)
+static __inline__ int DoC_WaitReady(unsigned long docptr)
{
/* This is inline, to optimise the common case, where it's ready instantly */
- volatile char dummy;
int ret = 0;
- /* Out-of-line routine to wait for chip response */
- /* TPW: Add 4 reads - see Software Requirement 2.3.2 */
- dummy = ReadDOC(docptr, CDSNControl);
- dummy = ReadDOC(docptr, CDSNControl);
- dummy = ReadDOC(docptr, CDSNControl);
- dummy = ReadDOC(docptr, CDSNControl);
-
+ /* 4 read form NOP register should be issued in prior to the read from CDSNControl
+ see Software Requirement 11.4 item 2. */
+ DoC_Delay(docptr, 4);
+
if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B))
- ret = _DoC_WaitReady(docptr); /* Call the out-of-line routine to wait */
-
- /* TPW: Add 2 reads - see Software Requirement 2.3.2 */
- dummy = ReadDOC(docptr, CDSNControl);
- dummy = ReadDOC(docptr, CDSNControl);
+ /* Call the out-of-line routine to wait */
+ ret = _DoC_WaitReady(docptr);
+
+ /* issue 2 read from NOP register after reading from CDSNControl register
+ see Software Requirement 11.4 item 2. */
+ DoC_Delay(docptr, 2);
return ret;
}
-
-/* DoC_Command: Send a flash command to the flash chip */
-
-static inline int DoC_Command(unsigned long docptr, unsigned char command, unsigned char xtraflags)
+/* DoC_Command: Send a flash command to the flash chip through the CDSN Slow IO register to bypass
+ the internal pipeline. Each of 4 delay cycles (read from the NOP register) is required after
+ writing to CDSN Control register, see Software Requirement 11.4 item 3. */
+static __inline__ void DoC_Command(unsigned long docptr, unsigned char command,
+ unsigned char xtraflags)
{
/* Assert the CLE (Command Latch Enable) line to the flash chip */
- WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE,
- docptr, CDSNControl);
+ WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl);
+ DoC_Delay(docptr, 4);
/* Send the command */
- WriteDOC(command, docptr, 2k_CDSN_IO);
+ WriteDOC(command, docptr, CDSNSlowIO);
+ WriteDOC(command, docptr, Mil_CDSN_IO);
/* Lower the CLE line */
- WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags | CDSN_CTRL_CE, docptr, CDSNControl);
-
- /* Wait for the chip to respond */
- return DoC_WaitReady(docptr);
+ WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl);
+ DoC_Delay(docptr, 4);
}
-/* DoC_Address: Set the current address for the flash chip */
-
-static inline int DoC_Address (unsigned long docptr, int numbytes, unsigned long ofs,
+/* DoC_Address: Set the current address for the flash chip through the CDSN Slow IO register to bypass
+ the internal pipeline. Each of 4 delay cycles (read from the NOP register) is required after
+ writing to CDSN Control register, see Software Requirement 11.4 item 3. */
+static __inline__ void DoC_Address (unsigned long docptr, int numbytes, unsigned long ofs,
unsigned char xtraflags1, unsigned char xtraflags2)
{
/* Assert the ALE (Address Latch Enable line to the flash chip */
- WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE,
- docptr, CDSNControl);
+ WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl);
+ DoC_Delay(docptr, 4);
/* Send the address */
- /* Three cases:
- numbytes == 1: Send single byte, bits 0-7.
- numbytes == 2: Send bits 9-16 followed by 17-23
- numbytes == 3: Send 0-7, 9-16, then 17-23
- */
- if (numbytes != 2)
- WriteDOC(ofs & 0xff, docptr, 2k_CDSN_IO);
-
- if (numbytes != 1) {
- WriteDOC((ofs >> 9) & 0xff, docptr, 2k_CDSN_IO);
- WriteDOC((ofs >> 17) & 0xff, docptr, 2k_CDSN_IO);
- }
+ switch (numbytes)
+ {
+ case 1:
+ /* Send single byte, bits 0-7. */
+ WriteDOC(ofs & 0xff, docptr, CDSNSlowIO);
+ WriteDOC(ofs & 0xff, docptr, Mil_CDSN_IO);
+ break;
+ case 2:
+ /* Send bits 9-16 followed by 17-23 */
+ WriteDOC((ofs >> 9) & 0xff, docptr, CDSNSlowIO);
+ WriteDOC((ofs >> 9) & 0xff, docptr, Mil_CDSN_IO);
+ WriteDOC((ofs >> 17) & 0xff, docptr, CDSNSlowIO);
+ WriteDOC((ofs >> 17) & 0xff, docptr, Mil_CDSN_IO);
+ break;
+ case 3:
+ /* Send 0-7, 9-16, then 17-23 */
+ WriteDOC(ofs & 0xff, docptr, CDSNSlowIO);
+ WriteDOC(ofs & 0xff, docptr, Mil_CDSN_IO);
+ WriteDOC((ofs >> 9) & 0xff, docptr, CDSNSlowIO);
+ WriteDOC((ofs >> 9) & 0xff, docptr, Mil_CDSN_IO);
+ WriteDOC((ofs >> 17) & 0xff, docptr, CDSNSlowIO);
+ WriteDOC((ofs >> 17) & 0xff, docptr, Mil_CDSN_IO);
+ break;
+ default:
+ return;
+ }
+
/* Lower the ALE line */
- WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr, CDSNControl);
-
- /* Wait for the chip to respond */
- return DoC_WaitReady(docptr);
+ WriteDOC(xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr, CDSNControl);
+ DoC_Delay(docptr, 4);
}
/* DoC_SelectChip: Select a given flash chip within the current floor */
-
-static inline int DoC_SelectChip(unsigned long docptr, int chip)
+static int DoC_SelectChip(unsigned long docptr, int chip)
{
/* Select the individual flash chip requested */
- WriteDOC( chip, docptr, CDSNDeviceSelect);
-
+ WriteDOC(chip, docptr, CDSNDeviceSelect);
+ DoC_Delay(docptr, 4);
+
/* Wait for it to be ready */
return DoC_WaitReady(docptr);
}
/* DoC_SelectFloor: Select a given floor (bank of flash chips) */
-
-static inline int DoC_SelectFloor(unsigned long docptr, int floor)
+static int DoC_SelectFloor(unsigned long docptr, int floor)
{
/* Select the floor (bank) of chips required */
- WriteDOC( floor, docptr, FloorSelect);
+ WriteDOC(floor, docptr, FloorSelect);
/* Wait for the chip to be ready */
return DoC_WaitReady(docptr);
}
-
-/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */
-int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
+/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */
+static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
{
- int mfr, id, chipshift=0;
- char *mfrname=NULL, *idname=NULL;
+ int mfr, id, i;
+ volatile char dummy;
- /* Page in the required floor/chip */
+ /* Page in the required floor/chip
+ FIXME: is this supported by Millennium ?? */
DoC_SelectFloor(doc->virtadr, floor);
DoC_SelectChip(doc->virtadr, chip);
- /* Reset the chip */
- if (DoC_Command(doc->virtadr, NAND_CMD_RESET, CDSN_CTRL_WP)) {
- DEBUG(2, "DoC_Command (reset) for %d,%d returned true\n", floor,chip);
- return 0;
- }
-
+ /* Reset the chip, see Software Requirement 11.4 item 1. */
+ DoC_Command(doc->virtadr, NAND_CMD_RESET, CDSN_CTRL_WP);
+ DoC_WaitReady(doc->virtadr);
+
/* Read the NAND chip ID: 1. Send ReadID command */
- if(DoC_Command(doc->virtadr, NAND_CMD_READID, CDSN_CTRL_WP)) {
- DEBUG(2,"DoC_Command (ReadID) for %d,%d returned true\n", floor,chip);
- return 0;
- }
+ DoC_Command(doc->virtadr, NAND_CMD_READID, CDSN_CTRL_WP);
+
+ /* Read the NAND chip ID: 2. Send address byte zero */
+ DoC_Address(doc->virtadr, 1, 0x00, CDSN_CTRL_WP, 0x00);
+
+ /* Read the manufacturer and device id codes of the flash device through
+ CDSN Slow IO register see Software Requirement 11.4 item 5.*/
+ dummy = ReadDOC(doc->virtadr, CDSNSlowIO);
+ DoC_Delay(doc->virtadr, 2);
+ mfr = ReadDOC(doc->virtadr, Mil_CDSN_IO);
+
+ dummy = ReadDOC(doc->virtadr, CDSNSlowIO);
+ DoC_Delay(doc->virtadr, 2);
+ id = ReadDOC(doc->virtadr, Mil_CDSN_IO);
- /* Read the NAND chip ID: 2. Send address byte zero
- */
- DoC_Address(doc->virtadr, 1, 0, CDSN_CTRL_WP, 0);
-
- /* Read the manufacturer and device id codes from the device */
- mfr = ReadDOC(doc->virtadr, 2k_CDSN_IO);
- id = ReadDOC(doc->virtadr, 2k_CDSN_IO);
-
/* No response - return failure */
if (mfr == 0xff || mfr == 0)
return 0;
-
- /* Check it's the same as the first chip we identified.
- * M-Systems say that any given DiskOnChip device should only
- * contain _one_ type of flash part, although that's not a
- * hardware restriction. */
- if (doc->mfr) {
- if (doc->mfr == mfr && doc->id == id)
- return 1; /* This is another the same the first */
- else
- printk(KERN_WARNING "Flash chip at floor %d, chip %d is different:\n",
- floor, chip);
- }
-
- /* Print (and store if first time) the manufacturer and ID codes. */
-
- switch(mfr) {
- case NAND_MFR_TOSHIBA: /* Toshiba */
- mfrname = "Toshiba";
-
- switch(id) {
- case 0x64:
- idname = "TC5816BDC";
- chipshift = 21;
- break;
-
- case 0x6b:
- idname = "TC5832DC";
- chipshift = 22;
- break;
-
- case 0x73:
- idname = "TH58V128DC";
- chipshift = 24;
- break;
-
- case 0x75:
- idname = "TC58256FT/DC";
- chipshift = 25;
- break;
-
- case 0xe5:
- idname = "TC58V32DC";
- chipshift = 22;
- break;
-
- case 0xe6:
- idname = "TC58V64DC";
- chipshift = 23;
- break;
-
- case 0xea:
- idname = "TC58V16BDC";
- chipshift = 21;
- break;
- }
- break; /* End of Toshiba parts */
-
- case NAND_MFR_SAMSUNG: /* Samsung */
- mfrname = "Samsung";
-
- switch(id) {
- case 0x64:
- idname = "KM29N16000";
- chipshift = 21;
-
- case 0x73:
- idname = "KM29U128T";
- chipshift = 24;
- break;
-
- case 0x75:
- idname = "KM29U256T";
- chipshift = 25;
- break;
- case 0xe3:
- idname = "KM29W32000";
- chipshift = 22;
- break;
-
- case 0xe6:
- idname = "KM29U64000";
- chipshift = 23;
- break;
-
- case 0xea:
- idname = "KM29W16000";
- chipshift = 21;
- break;
- }
- break; /* End of Samsung parts */
- }
-
- /* If we've identified it fully, print the full names */
- if (idname) {
-#ifdef PRERELEASE
- DEBUG(1, "Flash chip found: %2.2X %2.2X (%s %s)\n",
- mfr,id,mfrname,idname);
-#endif
- /* If this is the first chip, store the id codes */
- if (!doc->mfr) {
+ /* FIXME: to deal with mulit-flash on multi-Millennium case more carefully */
+ for (i = 0; nand_flash_ids[i].name != NULL; i++) {
+ if (mfr == nand_flash_ids[i].manufacture_id &&
+ id == nand_flash_ids[i].model_id) {
+ printk(KERN_INFO "Flash chip found: Manufacture ID: %2.2X, "
+ "Chip ID: %2.2X (%s)\n",
+ mfr, id, nand_flash_ids[i].name);
doc->mfr = mfr;
doc->id = id;
- doc->chipshift = chipshift;
- return 1;
+ doc->chipshift = nand_flash_ids[i].chipshift;
+ break;
}
- return 0;
}
- /* We haven't fully identified the chip. Print as much as we know. */
- if (mfrname)
- printk(KERN_WARNING "Unknown %s flash chip found: %2.2X %2.2X\n", mfrname,
- id, mfr);
+ if (nand_flash_ids[i].name == NULL)
+ return 0;
else
- printk(KERN_WARNING "Unknown flash chip found: %2.2X %2.2X\n", id, mfr);
-
- printk(KERN_WARNING "Please report to David.Woodhouse@mvhi.com\n");
- return 0;
+ return 1;
}
/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */
-
-void DoC_ScanChips(struct DiskOnChip *this)
+static void DoC_ScanChips(struct DiskOnChip *this)
{
int floor, chip;
- int numchips[MAX_FLOORS];
- int ret = 1;
+ int numchips[MAX_FLOORS_MIL];
+ int ret;
this->numchips = 0;
this->mfr = 0;
this->id = 0;
/* For each floor, find the number of valid chips it contains */
- for (floor = 0 ; floor < MAX_FLOORS ; floor++) {
- ret = 1;
- numchips[floor]=0;
- for (chip = 0 ; chip < MAX_CHIPS && ret != 0; chip++ ) {
-
+ for (floor = 0,ret = 1; floor < MAX_FLOORS_MIL; floor++) {
+ numchips[floor] = 0;
+ for (chip = 0; chip < MAX_CHIPS_MIL && ret != 0; chip++) {
ret = DoC_IdentChip(this, floor, chip);
if (ret) {
numchips[floor]++;
@@ -327,7+259,6 @@ void DoC_ScanChips(struct DiskOnChip *this) }
}
}
-
/* If there are none at all that we recognise, bail */
if (!this->numchips) {
printk("No flash chips recognised.\n");
@@ -341,11+272,9 @@ void DoC_ScanChips(struct DiskOnChip *this) return;
}
- ret = 0;
-
/* Fill out the chip array with {floor, chipno} for each
* detected chip in the device. */
- for (floor = 0; floor < MAX_FLOORS; floor++) {
+ for (floor = 0, ret = 0; floor < MAX_FLOORS_MIL; floor++) {
for (chip = 0 ; chip < numchips[floor] ; chip++) {
this->chips[ret].floor = floor;
this->chips[ret].chip = chip;
@@ -357,14+286,14 @@ void DoC_ScanChips(struct DiskOnChip *this)
/* Calculate and print the total size of the device */
this->totlen = this->numchips * (1 << this->chipshift);
-
- printk(KERN_INFO "%d flash chips found. Total DiskOnChip size: %ld Mb\n", this->numchips ,
- this->totlen >> 20);
+ printk(KERN_INFO "%d flash chips found. Total DiskOnChip size: %ld Mbytes\n",
+ this->numchips ,this->totlen >> 20);
}
static int DoCMil_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2)
{
int tmp1, tmp2, retval;
+
if (doc1->physadr == doc2->physadr)
return 1;
@@ -392,21+321,19 @@ static int DoCMil_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2) return retval;
}
-
void DoCMil_init(struct mtd_info *mtd)
{
struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
struct DiskOnChip *old = NULL;
/* We must avoid being called twice for the same device. */
-
if (docmillist)
old = (struct DiskOnChip *)docmillist->priv;
while (old) {
if (DoCMil_is_alias(this, old)) {
- printk(KERN_NOTICE "Ignoring DiskOnChip Millennium at 0x%lX - already configured\n",
- this->physadr);
+ printk(KERN_NOTICE "Ignoring DiskOnChip Millennium at "
+ "0x%lX - already configured\n", this->physadr);
iounmap((void *)this->virtadr);
kfree(mtd);
return;
@@ -418,14+345,9 @@ void DoCMil_init(struct mtd_info *mtd) }
mtd->name = "DiskOnChip Millennium";
- printk(KERN_NOTICE "DiskOnChip Millennium found at address 0x%lX\n",this->physadr);
+ printk(KERN_NOTICE "DiskOnChip Millennium found at address 0x%lX\n",
+ this->physadr);
-#if 1
- printk("Unfortunately, we don't have support for the DiskOnChip Millennium yet.\n");
- iounmap((void *)this->virtadr);
- kfree(mtd);
- return;
-#else
mtd->type = MTD_NANDFLASH;
mtd->flags = MTD_CAP_NANDFLASH;
mtd->size = 0;
@@ -445,8+367,7 @@ void DoCMil_init(struct mtd_info *mtd) mtd->sync = NULL;
this->totlen = 0;
- this->numchips = 0;
-
+ this->numchips = 0;
this->curfloor = -1;
this->curchip = -1;
@@ -463,78+384,90 @@ void DoCMil_init(struct mtd_info *mtd) add_mtd_device(mtd);
return;
}
-#endif
}
-
EXPORT_SYMBOL(DoCMil_init);
-#if 0
-static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
+
+static int doc_read (struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf)
{
/* Just a special case of doc_read_ecc */
return doc_read_ecc(mtd, from, len, retlen, buf, NULL);
}
-static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf)
+static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf, u_char *eccbuf)
{
+ int i;
+ volatile char dummy;
struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
- int di=0; /* Yes, DI is a hangover from when I was disassembling the binary driver */
- unsigned long docptr;
- struct Nand *mychip;
-
- docptr = this->virtadr;
+ unsigned long docptr = this->virtadr;
+ struct Nand *mychip = &this->chips[from >> (this->chipshift)];
/* Don't allow read past end of device */
if (from >= this->totlen)
return -EINVAL;
-
+
/* Don't allow a single read to cross a 512-byte block boundary */
- if (from + len > ( (from | 0x1ff) + 1))
+ if (from + len > ((from | 0x1ff) + 1))
len = ((from | 0x1ff) + 1) - from;
/* Find the chip which is to be used and select it */
- mychip = &this->chips[from >> (this->chipshift)];
-
if (this->curfloor != mychip->floor) {
DoC_SelectFloor(docptr, mychip->floor);
DoC_SelectChip(docptr, mychip->chip);
- }
- else if (this->curchip != mychip->chip) {
+ } else if (this->curchip != mychip->chip) {
DoC_SelectChip(docptr, mychip->chip);
}
-
this->curfloor = mychip->floor;
this->curchip = mychip->chip;
-
if (eccbuf) {
- /* Prime the ECC engine */
- WriteDOC ( DOC_ECC_RESET, docptr, ECCConf);
- WriteDOC ( DOC_ECC_EN, docptr, ECCConf);
+ /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
+ WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
+ WriteDOC (DOC_ECC_EN, docptr, ECCConf);
+ } else {
+ /* disable the ECC engine, FIXME: is this correct ?? */
+ WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
+ WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
}
+ /* issue the Read0 or Read1 command depend on which half of the page
+ we are accessing. Polling the Flash Ready bit after issue 3 bytes
+ address in Sequence Read Mode, see Software Requirement 11.4 item 1.*/
DoC_Command(docptr, (from >> 8) & 1, CDSN_CTRL_WP);
- DoC_Address(docptr, 3, from, CDSN_CTRL_WP , CDSN_CTRL_ECC_IO);
+ DoC_Address(docptr, 3, from, CDSN_CTRL_WP, 0x00);
+ DoC_WaitReady(docptr);
- for (di=0; di < len ; di++) {
- buf[di] = ReadDOC(docptr, 2k_CDSN_IO);
+ /* Read the data via the internal pipeline through CDSN IO register,
+ see Pipelined Read Operations 11.3 */
+ dummy = ReadDOC(docptr, ReadPipeInit);
+ for (i = 0; i < len-1; i++) {
+ buf[i] = ReadDOC(docptr, Mil_CDSN_IO);
}
+ buf[i] = ReadDOC(docptr, LastDataRead);
/* Let the caller know we completed it */
*retlen = len;
if (eccbuf) {
- /* Read the ECC data through the DiskOnChip ECC logic */
- for (di=0; di<6; di++) {
- eccbuf[di] = ReadDOC(docptr, 2k_CDSN_IO);
+ /* FIXME: are we reading the ECC from the ECC logic of DOC or
+ the spare data space on the flash chip i.e. How do we
+ control the Spare Area Enable bit of the flash ?? */
+ /* Read the ECC data through the DiskOnChip ECC logic
+ see Reed-Solomon EDC/ECC 11.1 */
+ dummy = ReadDOC(docptr, ReadPipeInit);
+ for (i = 0; i < 5; i++) {
+ eccbuf[i] = ReadDOC(docptr, Mil_CDSN_IO);
}
-
+ eccbuf[i] = ReadDOC(docptr, LastDataRead);
+
/* Flush the pipeline */
- (void) ReadDOC(docptr, 2k_ECCStatus);
- (void) ReadDOC(docptr, 2k_ECCStatus);
-
+ dummy = ReadDOC(docptr, ECCConf);
+ dummy = ReadDOC(docptr, ECCConf);
+
/* Check the ECC Status */
- if (ReadDOC(docptr, 2k_ECCStatus) & 0x80) {
+ if (ReadDOC(docptr, ECCConf) & 0x80) {
/* There was an ECC error */
printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
@@ -548,41+481,40 @@ static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, size_t * #ifdef PSYCHO_DEBUG
else
printk("ECC OK at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
- (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], eccbuf[4],
- eccbuf[5]);
+ (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
+ eccbuf[4], eccbuf[5]);
#endif
-
/* Reset the ECC engine */
WriteDOC(DOC_ECC_RESV, docptr , ECCConf);
-
}
return 0;
}
-static int doc_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
+static int doc_write (struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
{
static char as[6];
return doc_write_ecc(mtd, to, len, retlen, buf, as);
}
-static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf)
+static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf, u_char *eccbuf)
{
+ int i;
+ volatile char dummy;
struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
- int di=0;
- unsigned long docptr;
- struct Nand *mychip;
-
- docptr = this->virtadr;
+ unsigned long docptr = this->virtadr;
+ struct Nand *mychip = &this->chips[to >> (this->chipshift)];
/* Don't allow write past end of device */
if (to >= this->totlen)
return -EINVAL;
-#if 0
+
+#if 0
/* Don't allow a single write to cross a 512-byte block boundary */
if (to + len > ( (to | 0x1ff) + 1))
len = ((to | 0x1ff) + 1) - to;
-
#else
/* Don't allow writes which aren't exactly one block */
if (to & 0x1ff || len != 0x200)
@@ -590,8+522,6 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, size_t *r #endif
/* Find the chip which is to be used and select it */
- mychip = &this->chips[to >> (this->chipshift)];
-
if (this->curfloor != mychip->floor) {
DoC_SelectFloor(docptr, mychip->floor);
DoC_SelectChip(docptr, mychip->chip);
@@ -599,61+529,75 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, size_t *r else if (this->curchip != mychip->chip) {
DoC_SelectChip(docptr, mychip->chip);
}
-
this->curfloor = mychip->floor;
this->curchip = mychip->chip;
-
- /* Set device to main plane of flash */
+
+ /* Reset the chip, see Software Requirement 11.4 item 1. */
DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP);
+ DoC_WaitReady(docptr);
+ /* Set device to main plane of flash */
DoC_Command(docptr, NAND_CMD_READ0, CDSN_CTRL_WP);
if (eccbuf) {
- /* Prime the ECC engine */
- WriteDOC ( DOC_ECC_RESET, docptr, ECCConf);
- WriteDOC ( DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
+ /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/
+ WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
+ WriteDOC (DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf);
+ } else {
+ /* disable the ECC engine, FIXME: is this correct ?? */
+ WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
+ WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
}
- DoC_Command(docptr, NAND_CMD_SEQIN, 0);
- DoC_Address(docptr, 3, to, 0, CDSN_CTRL_ECC_IO);
+ /* issue the Serial Data In command to initial the Page Program process */
+ DoC_Command(docptr, NAND_CMD_SEQIN, 0x00);
+ DoC_Address(docptr, 3, to, 0x00, 0x00);
- for (di=0; di < len ; di++) {
- WriteDOC(buf[di], docptr, 2k_CDSN_IO);
+ /* Write the data via the internal pipeline through CDSN IO register,
+ see Pipelined Write Operations 11.2 */
+ for (i = 0; i < len; i++) {
+ WriteDOC(buf[i], docptr, Mil_CDSN_IO);
}
-
+ WriteDOC(0x00, docptr, WritePipeTerm);
if (eccbuf) {
- WriteDOC( CDSN_CTRL_ECC_IO | CDSN_CTRL_CE , docptr, CDSNControl );
-
-#if 1
- /* eduardp@m-sys.com says this shouldn't be necessary,
- * but it doesn't actually work without it, so I've
- * left it in for now. dwmw2.
- */
-
- WriteDOC( 0, docptr, 2k_CDSN_IO);
- WriteDOC( 0, docptr, 2k_CDSN_IO);
- WriteDOC( 0, docptr, 2k_CDSN_IO);
-#endif
+ /* Write ECC data to flash, the ECC info is generated by the DiskOnChip DECC logic
+ see Reed-Solomon EDC/ECC 11.1 */
+ WriteDOC(0, docptr, NOP);
+ WriteDOC(0, docptr, NOP);
+ WriteDOC(0, docptr, NOP);
+
/* Read the ECC data through the DiskOnChip ECC logic */
- for (di=0; di<6; di++) {
- eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di);
+ for (i = 0; i < 6; i++) {
+ eccbuf[i] = ReadDOC(docptr, ECCSyndrome0 + i);
}
+
+ /* Write the ECC data to flash */
+ for (i = 0; i < 6; i++) {
+ WriteDOC(eccbuf[i], docptr, Mil_CDSN_IO);
+ }
+ WriteDOC(0x00, docptr, WritePipeTerm);
+
#ifdef PSYCHO_DEBUG
printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n",
- (long) to, eccbuf[0], eccbuf[1], eccbuf[2],
- eccbuf[3], eccbuf[4], eccbuf[5] );
+ (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3],
+ eccbuf[4], eccbuf[5]);
#endif
+
/* Reset the ECC engine */
WriteDOC(DOC_ECC_RESV, docptr , ECCConf);
-
}
- DoC_Command(docptr, NAND_CMD_PAGEPROG, 0);
-
- DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP);
- /* There's an implicit DoC_WaitReady() in DoC_Command */
+ /* Commit the Page Program command and wait for ready
+ see Software Requirement 11.4 item 1.*/
+ DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00);
+ DoC_WaitReady(docptr);
- if (ReadDOC(docptr, 2k_CDSN_IO) & 1) {
+ /* Read the status of the flash device through CDSN Slow IO register
+ see Software Requirement 11.4 item 5.*/
+ DoC_Command(docptr, NAND_CMD_STATUS, 0x00);
+ dummy = ReadDOC(docptr, CDSNSlowIO);
+ DoC_Delay(docptr, 2);
+ if (ReadDOC(docptr, Mil_CDSN_IO) & 1) {
printk("Error programming flash\n");
/* Error in programming */
*retlen = 0;
@@ -666,19+610,18 @@ static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, size_t *r return 0;
}
-
-
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, u_char *buf)
+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
+ size_t *retlen, u_char *buf)
{
- struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
+ volatile char dummy;
int i;
- unsigned long docptr;
- struct Nand *mychip;
-
- docptr = this->virtadr;
-
- mychip = &this->chips[ofs >> this->chipshift];
-
+ struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
+ unsigned long docptr = this->virtadr;
+ struct Nand *mychip = &this->chips[ofs >> this->chipshift];
+
+ /* FIXME: should we restrict the access between 512 to 527 ?? */
+
+ /* Find the chip which is to be used and select it */
if (this->curfloor != mychip->floor) {
DoC_SelectFloor(docptr, mychip->floor);
DoC_SelectChip(docptr, mychip->chip);
@@ -688,35+631,43 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *re }
this->curfloor = mychip->floor;
this->curchip = mychip->chip;
-
-
-
+
+ /* FIXME: should we disable ECC engine in this way ?? */
+ /* disable the ECC engine, FIXME: is this correct ?? */
+ WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
+ WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
+
+ /* issue the Read2 command to read the Spare Data Area.
+ Polling the Flash Ready bit after issue 3 bytes address in
+ Sequence Read Mode, see Software Requirement 11.4 item 1.*/
DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP);
- DoC_Address(docptr, 3, ofs, CDSN_CTRL_WP, 0);
-
- for (i=0; i<len; i++)
- buf[i] = ReadDOC(docptr, 2k_CDSN_IO);
-
+ DoC_Address(docptr, 3, ofs, CDSN_CTRL_WP, 0x00);
+ DoC_WaitReady(docptr);
+
+ /* Read the data out via the internal pipeline through CDSN IO register,
+ see Pipelined Read Operations 11.3 */
+ dummy = ReadDOC(docptr, ReadPipeInit);
+ for (i = 0; i < len-1; i++) {
+ buf[i] = ReadDOC(docptr, Mil_CDSN_IO);
+ }
+ buf[i] = ReadDOC(docptr, LastDataRead);
+
*retlen = len;
- return 0;
+ return 0;
}
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, const u_char *buf)
+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
+ size_t *retlen, const u_char *buf)
{
- struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
int i;
- unsigned long docptr;
- struct Nand *mychip;
-
- // printk("doc_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n",(long)ofs, len,
- // buf[0], buf[1], buf[2], buf[3], buf[8], buf[9], buf[14],buf[15]);
+ volatile char dummy;
+ struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
+ unsigned long docptr = this->virtadr;
+ struct Nand *mychip = &this->chips[ofs >> this->chipshift];
- docptr = this->virtadr;
-
- mychip = &this->chips[ofs >> this->chipshift];
-
- if (this->curfloor != mychip->floor) {
+ /* Find the chip which is to be used and select it */
+ if (this->curfloor != mychip->floor) {
DoC_SelectFloor(docptr, mychip->floor);
DoC_SelectChip(docptr, mychip->chip);
}
@@ -725,49+676,63 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *r }
this->curfloor = mychip->floor;
this->curchip = mychip->chip;
-
- DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP);
- DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP);
- DoC_Command(docptr, NAND_CMD_SEQIN, 0);
- DoC_Address(docptr, 3, ofs, 0, 0);
-
- for (i=0; i<len; i++)
- WriteDOC(buf[i], docptr, 2k_CDSN_IO);
+ /* FIXME: should we disable ECC engine in this way ?? */
+ /* disable the ECC engine, FIXME: is this correct ?? */
+ WriteDOC (DOC_ECC_RESET, docptr, ECCConf);
+ WriteDOC (DOC_ECC_DIS, docptr, ECCConf);
- DoC_Command(docptr, NAND_CMD_PAGEPROG, 0);
- DoC_Command(docptr, NAND_CMD_STATUS, 0);
- /* DoC_WaitReady() is implicit in DoC_Command */
+ /* Reset the chip, see Software Requirement 11.4 item 1. */
+ DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP);
+ DoC_WaitReady(docptr);
+ /* issue the Read2 command to read the Spare Data Area. */
+ DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP);
- if (ReadDOC(docptr, 2k_CDSN_IO) & 1) {
+ /* issue the Serial Data In command to initial the Page Program process */
+ DoC_Command(docptr, NAND_CMD_SEQIN, 0x00);
+ DoC_Address(docptr, 3, ofs, 0x00, 0x00);
+
+ /* Write the data via the internal pipeline through CDSN IO register,
+ see Pipelined Write Operations 11.2 */
+ for (i = 0; i < len; i++)
+ WriteDOC(buf[i], docptr, Mil_CDSN_IO);
+ WriteDOC(0x00, docptr, WritePipeTerm);
+
+ /* Commit the Page Program command and wait for ready
+ see Software Requirement 11.4 item 1.*/
+ DoC_Command(docptr, NAND_CMD_PAGEPROG, 0x00);
+ DoC_WaitReady(docptr);
+
+ /* Read the status of the flash device through CDSN Slow IO register
+ see Software Requirement 11.4 item 5.*/
+ DoC_Command(docptr, NAND_CMD_STATUS, 0x00);
+ dummy = ReadDOC(docptr, CDSNSlowIO);
+ DoC_Delay(docptr, 2);
+ if (ReadDOC(docptr, Mil_CDSN_IO) & 1) {
printk("Error programming oob data\n");
- /* There was an error */
*retlen = 0;
return -EIO;
}
*retlen = len;
- return 0;
+ return 0;
}
-
int doc_erase (struct mtd_info *mtd, struct erase_info *instr)
{
+ volatile char dummy;
struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv;
unsigned long ofs = instr->addr;
unsigned long len = instr->len;
- unsigned long docptr;
- struct Nand *mychip;
-
- if(len != mtd->erasesize)
- printk(KERN_WARNING "Erase not right size (%lx != %lx)n", len, mtd->erasesize);
-
+ unsigned long docptr = this->virtadr;
+ struct Nand *mychip = &this->chips[ofs >> this->chipshift];
- docptr = this->virtadr;
-
- mychip = &this->chips[ofs >> this->chipshift];
-
+ if (len != mtd->erasesize)
+ printk(KERN_WARNING "Erase not right size (%lx != %lx)n",
+ len, mtd->erasesize);
+
+ /* Find the chip which is to be used and select it */
if (this->curfloor != mychip->floor) {
DoC_SelectFloor(docptr, mychip->floor);
DoC_SelectChip(docptr, mychip->chip);
@@ -780,32+745,35 @@ int doc_erase (struct mtd_info *mtd, struct erase_info *instr)
instr->state = MTD_ERASE_PENDING;
- DoC_Command(docptr, NAND_CMD_ERASE1, 0);
- DoC_Address(docptr, 2, ofs, 0, 0);
- DoC_Command(docptr, NAND_CMD_ERASE2, 0);
+ /* issue the Erase Setup command */
+ DoC_Command(docptr, NAND_CMD_ERASE1, 0x00);
+ DoC_Address(docptr, 2, ofs, 0x00, 0x00);
+
+ /* Commit the Erase Start command and wait for ready
+ see Software Requirement 11.4 item 1.*/
+ DoC_Command(docptr, NAND_CMD_ERASE2, 0x00);
+ DoC_WaitReady(docptr);
instr->state = MTD_ERASING;
+ /* Read the status of the flash device through CDSN Slow IO register
+ see Software Requirement 11.4 item 5.*/
DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP);
-
- if (ReadDOC(docptr, 2k_CDSN_IO) & 1) {
- printk("Error writing\n");
+ dummy = ReadDOC(docptr, CDSNSlowIO);
+ DoC_Delay(docptr, 2);
+ if (ReadDOC(docptr, Mil_CDSN_IO) & 1) {
+ printk("Error Erasing\n");
/* There was an error */
instr->state = MTD_ERASE_FAILED;
- }
- else
+ } else
instr->state = MTD_ERASE_DONE;
if (instr->callback)
instr->callback(instr);
-
+
return 0;
}
-
-
-#endif
-
/****************************************************************************
*
* Module stuff
/* Probe routines common to all DoC devices */
/* (c) 1999 Machine Vision Holdings, Inc. */
/* Author: David Woodhouse <dwmw2@mvhi.com> */
-/* $Id: docprobe.c,v 1.8 2000/06/26 20:40:53 dwmw2 Exp $ */
+/* $Id: docprobe.c,v 1.10 2000/07/13 14:23:20 dwmw2 Exp $ */
@@ -206,7+206,7 @@ static void DoC_Probe(unsigned long physadr) case DOC_ChipID_DocMil:
name="Millennium";
#ifdef CONFIG_MTD_DOC2001
- initroutine = &DocMil_init;
+ initroutine = &DoCMil_init;
#elif CONFIG_MODULES
initroutinedynamic=1;
initroutine = (void *)get_module_symbol(NULL, "DoCMil_init");
@@ -252,7+252,7 @@ int __init init_doc(void)
printk(KERN_NOTICE "M-Systems DiskOnChip driver. (C) 1999 Machine Vision Holdings, Inc.\n");
#ifdef PRERELEASE
- printk(KERN_INFO "$Id: docprobe.c,v 1.8 2000/06/26 20:40:53 dwmw2 Exp $\n");
+ printk(KERN_INFO "$Id: docprobe.c,v 1.10 2000/07/13 14:23:20 dwmw2 Exp $\n");
#endif
for (i=0; doc_locations[i]; i++) {
/*
* Direct MTD block device access
*
- * $Id: mtdblock.c,v 1.16 2000/06/23 09:34:58 dwmw2 Exp $
+ * $Id: mtdblock.c,v 1.17 2000/07/13 14:25:54 dwmw2 Exp $
*/
#ifdef MTDBLOCK_DEBUG
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/malloc.h>
-#include <linux/smp_lock.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
static loff_t mtd_lseek (struct file *file, loff_t offset, int orig)
@@ -91,12+90,10 @@ static release_t mtd_close(struct inode *inode,
mtd = (struct mtd_info *)file->private_data;
- lock_kernel();
if (mtd->sync)
mtd->sync(mtd);
put_mtd_device(mtd);
- unlock_kernel();
release_return(0);
} /* mtd_close */
/*
- * $Id: mtdcore.c,v 1.8 2000/06/27 13:40:05 dwmw2 Exp $
+ * $Id: mtdcore.c,v 1.13 2000/07/13 14:27:37 dwmw2 Exp $
*
* Core registration and callback routines for MTD
* drivers and users.
@@ -44,9+44,18 @@ extern int init_doc1000(void); #ifdef CONFIG_MTD_DOCPROBE
extern int init_doc(void);
#endif
+#ifdef CONFIG_MTD_PHYSMAP
+extern int init_physmap(void);
+#endif
+#ifdef CONFIG_MTD_RPXLITE
+extern int init_rpxlite(void);
+#endif
#ifdef CONFIG_MTD_OCTAGON
extern int init_octagon5066(void);
#endif
+#ifdef CONFIG_MTD_PNC2000
+extern int init_pnc2000(void);
+#endif
#ifdef CONFIG_MTD_VMAX
extern int init_vmax301(void);
#endif
@@ -76,11+85,18 @@ extern int init_mtdchar(void);
static DECLARE_MUTEX(mtd_table_mutex);
-
static struct mtd_info *mtd_table[MAX_MTD_DEVICES];
-
static struct mtd_notifier *mtd_notifiers = NULL;
+/**
+ * add_mtd_device - register an MTD device
+ * @mtd: pointer to new MTD device info structure
+ *
+ * Add a device to the list of MTD devices present in the system, and
+ * notify each currently active MTD 'user' of its arrival. Returns
+ * zero on success or 1 on failure, which currently will only happen
+ * if the number of present devices exceeds MAX_MTD_DEVICES (i.e. 16)
+ */
int add_mtd_device(struct mtd_info *mtd)
{
@@ -109,6+125,15 @@ int add_mtd_device(struct mtd_info *mtd) return 1;
}
+/**
+ * del_mtd_device - unregister an MTD device
+ * @mtd: pointer to MTD device info structure
+ *
+ * Remove a device from the list of MTD devices present in the system,
+ * and notify each currently active MTD 'user' of its departure.
+ * Returns zero on success or 1 on failure, which currently will happen
+ * if the requested device does not appear to be present in the list.
+ */
int del_mtd_device (struct mtd_info *mtd)
{
@@ -137,7+162,14 @@ int del_mtd_device (struct mtd_info *mtd) return 1;
}
-
+/**
+ * register_mtd_user - register a 'user' of MTD devices.
+ * @new: pointer to notifier info structure
+ *
+ * Registers a pair of callbacks function to be called upon addition
+ * or removal of MTD devices. Causes the 'add' callback to be immediately
+ * invoked for each MTD device currently present in the system.
+ */
void register_mtd_user (struct mtd_notifier *new)
{
@@ -157,7+189,15 @@ void register_mtd_user (struct mtd_notifier *new) up(&mtd_table_mutex);
}
-
+/**
+ * register_mtd_user - unregister a 'user' of MTD devices.
+ * @new: pointer to notifier info structure
+ *
+ * Removes a callback function pair from the list of 'users' to be
+ * notified upon addition or removal of MTD devices. Causes the
+ * 'remove' callback to be immediately invoked for each MTD device
+ * currently present in the system.
+ */
int unregister_mtd_user (struct mtd_notifier *old)
{
@@ -187,13+227,17 @@ int unregister_mtd_user (struct mtd_notifier *old) }
-/* get_mtd_device():
- * Prepare to use an MTD device referenced either by number or address.
+/**
+ * __get_mtd_device - obtain a validated handle for an MTD device
+ * @mtd: last known address of the required MTD device
+ * @num: internal device number of the required MTD device
*
- * If <num> == -1, search the table for an MTD device located at <mtd>.
- * If <mtd> == NULL, return the MTD device with number <num>.
- * If both are set, return the MTD device with number <num> _only_ if it
- * is located at <mtd>.
+ * Given a number and NULL address, return the num'th entry in the device
+ * table, if any. Given an address and num == -1, search the device table
+ * for a device with that address and return if it's still present. Given
+ * both, return the num'th driver only if its address matches. Return NULL
+ * if not. get_mtd_device() increases the use count, but
+ * __get_mtd_device() doesn't - you should generally use get_mtd_device().
*/
struct mtd_info *__get_mtd_device(struct mtd_info *mtd, int num)
@@ -224,12+268,45 @@ EXPORT_SYMBOL(register_mtd_user); EXPORT_SYMBOL(unregister_mtd_user);
/*====================================================================*/
-/* /proc/mtd support */
+/* Power management code */
+
+#ifdef CONFIG_PM
+
+#include <linux/pm.h>
+
+static struct pm_dev *mtd_pm_dev = NULL;
+
+static int mtd_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
+{
+ int ret = 0, i;
+
+ if (down_trylock(&mtd_table_mutex))
+ return -EAGAIN;
+ if (rqst == PM_SUSPEND) {
+ for (i = 0; ret == 0 && i < MAX_MTD_DEVICES; i++) {
+ if (mtd_table[i] && mtd_table[i]->suspend)
+ ret = mtd_table[i]->suspend(mtd_table[i]);
+ }
+ } else i = MAX_MTD_DEVICES-1;
+
+ if (rqst == PM_RESUME || ret) {
+ for ( ; i >= 0; i--) {
+ if (mtd_table[i] && mtd_table[i]->resume)
+ mtd_table[i]->resume(mtd_table[i]);
+ }
+ }
+ up(&mtd_table_mutex);
+ return ret;
+}
+#endif
+
+/*====================================================================*/
+/* Support for /proc/mtd */
#ifdef CONFIG_PROC_FS
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
-struct proc_dir_entry *proc_mtd;
+static struct proc_dir_entry *proc_mtd;
#endif
static inline int mtd_proc_info (char *buf, int i)
@@ -292,10+369,10 @@ struct proc_dir_entry mtd_proc_entry = { };
#endif
-#endif
+#endif /* CONFIG_PROC_FS */
/*====================================================================*/
-
+/* Init code */
#if LINUX_VERSION_CODE < 0x20300
@@ -315,9+392,18 @@ static inline void init_others(void) * Theoretically all other DiskOnChip
* devices too. */
#endif
+#ifdef CONFIG_MTD_PHYSMAP
+ init_physmap();
+#endif
+#ifdef CONFIG_MTD_RPXLITE
+ init_rpxlite();
+#endif
#ifdef CONFIG_MTD_OCTAGON
init_octagon5066();
#endif
+#ifdef CONFIG_MTD_PNC2000
+ init_pnc2000();
+#endif
#ifdef CONFIG_MTD_VMAX
init_vmax301();
#endif
@@ -374,13+460,21 @@ mod_init_t init_mtd(void) #if LINUX_VERSION_CODE < 0x20300
init_others();
#endif
-
+#ifdef CONFIG_PM
+ mtd_pm_dev = pm_register(PM_UNKNOWN_DEV, 0, mtd_pm_callback);
+#endif
return 0;
}
mod_exit_t cleanup_mtd(void)
{
unregister_chrdev(MTD_CHAR_MAJOR, "mtd");
+#ifdef CONFIG_PM
+ if (mtd_pm_dev) {
+ pm_unregister(mtd_pm_dev);
+ mtd_pm_dev = NULL;
+ }
+#endif
#ifdef CONFIG_PROC_FS
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
if (proc_mtd)
/*
* mtdram - a test mtd device
- * $Id: mtdram.c,v 1.13 2000/07/03 10:01:38 dwmw2 Exp $
+ * $Id: mtdram.c,v 1.15 2000/07/13 12:40:46 scote1 Exp $
* Author: Alexander Larsson <alex@cendio.se>
*
* Copyright (c) 1999 Alexander Larsson <alex@cendio.se>
#include <linux/mtd/mtd.h>
-#define MTDRAM_TOTAL_SIZE 1024*1024*8
-#define MTDRAM_ERASE_SIZE 4*1024
+#define MTDRAM_TOTAL_SIZE (CONFIG_MTDRAM_TOTAL_SIZE * 1024)
+#define MTDRAM_ERASE_SIZE (CONFIG_MTDRAM_ERASE_SIZE * 1024)
// We could store these in the mtd structure, but we only support 1 device..
/* Linux driver for NAND Flash Translation Layer */
/* (c) 1999 Machine Vision Holdings, Inc. */
/* Author: David Woodhouse <dwmw2@infradead.org> */
-/* $Id: nftl.c,v 1.35 2000/07/06 14:35:01 dwmw2 Exp $ */
+/* $Id: nftl.c,v 1.36 2000/07/13 14:14:20 dwmw2 Exp $ */
/*
The contents of this file are distributed under the GNU Public
@@ -1293,7+1293,7 @@ int __init init_nftl(void)
printk(KERN_NOTICE "M-Systems NAND Flash Translation Layer driver. (C) 1999 MVHI\n");
#ifdef PRERELEASE
- printk(KERN_INFO"$Id: nftl.c,v 1.35 2000/07/06 14:35:01 dwmw2 Exp $\n");
+ printk(KERN_INFO"$Id: nftl.c,v 1.36 2000/07/13 14:14:20 dwmw2 Exp $\n");
#endif
if (register_blkdev(NFTL_MAJOR, "nftl", &nftl_fops)){
/*
- * $Id: nora.c,v 1.11 2000/07/04 16:42:50 dwmw2 Exp $
+ * $Id: nora.c,v 1.12 2000/07/13 10:32:33 dwmw2 Exp $
*
* This is so simple I love it.
*/
@@ -125,7+125,7 @@ static struct mtd_info nora_mtds[4] = { /* boot, kernel, ramdisk, fs */ {
type: MTD_NORFLASH,
flags: MTD_CAP_NORFLASH,
- size: 0x1a0000,
+ size: 0x0a0000,
erasesize: 0x20000,
name: "NORA kernel",
module: THIS_MODULE,
@@ -140,9+140,9 @@ static struct mtd_info nora_mtds[4] = { /* boot, kernel, ramdisk, fs */ {
type: MTD_NORFLASH,
flags: MTD_CAP_NORFLASH,
- size: 0xe00000,
+ size: 0xf00000,
erasesize: 0x20000,
- name: "NORA ramdisk",
+ name: "NORA root filesystem",
module: THIS_MODULE,
erase: nora_mtd_erase,
read: nora_mtd_read,
@@ -150,14+150,14 @@ static struct mtd_info nora_mtds[4] = { /* boot, kernel, ramdisk, fs */ suspend: nora_mtd_suspend,
resume: nora_mtd_resume,
sync: nora_mtd_sync,
- priv: (void *)0x200000
+ priv: (void *)0x100000
},
{
type: MTD_NORFLASH,
flags: MTD_CAP_NORFLASH,
size: 0x1000000,
erasesize: 0x20000,
- name: "NORA filesystem",
+ name: "NORA main filesystem",
module: THIS_MODULE,
erase: nora_mtd_erase,
read: nora_mtd_read,
-// $Id: octagon-5066.c,v 1.9 2000/07/03 10:01:38 dwmw2 Exp $
+// $Id: octagon-5066.c,v 1.10 2000/07/13 14:04:23 dwmw2 Exp $
/* ######################################################################
Octagon 5066 MTD Driver.
@@ -56,8+56,8 @@ static inline void oct5066_page(struct map_info *map, unsigned long ofs) {
__u8 byte = map->map_priv_1 | (ofs >> WINDOW_SHIFT);
- if (page_n_dev != byte);
- __oct5066_page(map, byte);
+ if (page_n_dev != byte)
+ __oct5066_page(map, byte);
}
--- /dev/null
+/*
+ * pnc2000.c - mapper for Photron PNC-2000 board.
+ *
+ * Copyright (C) 2000 Crossnet Co. <info@crossnet.co.jp>
+ *
+ * This code is GPL
+ *
+ * $Id: pnc2000.c,v 1.1 2000/07/12 09:34:32 dwmw2 Exp $
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+
+
+#define WINDOW_ADDR 0xbf000000
+#define WINDOW_SIZE 0x00400000
+
+/*
+ * MAP DRIVER STUFF
+ */
+
+__u8 pnc_read8(struct map_info *map, unsigned long ofs)
+{
+ return *(__u8 *)(WINDOW_ADDR + ofs);
+}
+
+__u16 pnc_read16(struct map_info *map, unsigned long ofs)
+{
+ return *(__u16 *)(WINDOW_ADDR + ofs);
+}
+
+__u32 pnc_read32(struct map_info *map, unsigned long ofs)
+{
+ return *(volatile unsigned int *)(WINDOW_ADDR + ofs);
+}
+
+void pnc_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
+{
+ memcpy(to, (void *)(WINDOW_ADDR + from), len);
+}
+
+void pnc_write8(struct map_info *map, __u8 d, unsigned long adr)
+{
+ *(__u8 *)(WINDOW_ADDR + adr) = d;
+}
+
+void pnc_write16(struct map_info *map, __u16 d, unsigned long adr)
+{
+ *(__u16 *)(WINDOW_ADDR + adr) = d;
+}
+
+void pnc_write32(struct map_info *map, __u32 d, unsigned long adr)
+{
+ *(__u32 *)(WINDOW_ADDR + adr) = d;
+}
+
+void pnc_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
+{
+ memcpy((void *)(WINDOW_ADDR + to), from, len);
+}
+
+struct map_info pnc_map = {
+ "PNC-2000",
+ WINDOW_SIZE,
+ 4,
+ pnc_read8,
+ pnc_read16,
+ pnc_read32,
+ pnc_copy_from,
+ pnc_write8,
+ pnc_write16,
+ pnc_write32,
+ pnc_copy_to,
+ 0,
+ 0
+};
+
+
+/*
+ * MTD 'PARTITIONING' STUFF
+ */
+
+/*
+ * This is the _real_ MTD device for which all the others are just
+ * auto-relocating aliases.
+ */
+static struct mtd_info *mymtd;
+
+/*
+ * MTD methods which simply translate the effective address and pass through
+ * to the _real_ device.
+ */
+
+static int pnc_mtd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
+{
+ return mymtd->read(mymtd, from + (unsigned long)mtd->priv, len, retlen, buf);
+}
+
+static int pnc_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
+{
+ return mymtd->write(mymtd, to + (unsigned long)mtd->priv, len, retlen, buf);
+}
+
+static int pnc_mtd_erase (struct mtd_info *mtd, struct erase_info *instr)
+{
+ instr->addr += (unsigned long)mtd->priv;
+ return mymtd->erase(mymtd, instr);
+}
+
+static void pnc_mtd_sync (struct mtd_info *mtd)
+{
+ mymtd->sync(mymtd);
+}
+
+static int pnc_mtd_suspend (struct mtd_info *mtd)
+{
+ return mymtd->suspend(mymtd);
+}
+
+static void pnc_mtd_resume (struct mtd_info *mtd)
+{
+ mymtd->resume(mymtd);
+}
+
+
+static struct mtd_info pnc_mtds[3] = { /* boot, kernel, fs */
+ {
+ type: MTD_NORFLASH,
+ flags: MTD_CAP_NORFLASH,
+ size: 0x20000,
+ erasesize: 0x20000,
+ name: "PNC-2000 boot firmware",
+ module: THIS_MODULE,
+ erase: pnc_mtd_erase,
+ read: pnc_mtd_read,
+ write: pnc_mtd_write,
+ suspend: pnc_mtd_suspend,
+ resume: pnc_mtd_resume,
+ sync: pnc_mtd_sync,
+ priv: (void *)0
+ },
+ {
+ type: MTD_NORFLASH,
+ flags: MTD_CAP_NORFLASH,
+ size: 0x1a0000,
+ erasesize: 0x20000,
+ name: "PNC-2000 kernel",
+ module: THIS_MODULE,
+ erase: pnc_mtd_erase,
+ read: pnc_mtd_read,
+ write: pnc_mtd_write,
+ suspend: pnc_mtd_suspend,
+ resume: pnc_mtd_resume,
+ sync: pnc_mtd_sync,
+ priv: (void *)0x20000
+ },
+ {
+ type: MTD_NORFLASH,
+ flags: MTD_CAP_NORFLASH,
+ size: 0x240000,
+ erasesize: 0x20000,
+ name: "PNC-2000 filesystem",
+ module: THIS_MODULE,
+ erase: pnc_mtd_erase,
+ read: pnc_mtd_read,
+ write: pnc_mtd_write,
+ suspend: pnc_mtd_suspend,
+ resume: pnc_mtd_resume,
+ sync: pnc_mtd_sync,
+ priv: (void *)0x1c0000
+ }
+};
+
+#if LINUX_VERSION_CODE < 0x20300
+#ifdef MODULE
+#define init_pnc init_module
+#define cleanup_pnc cleanup_module
+#endif
+#endif
+
+int __init init_pnc(void)
+{
+ printk(KERN_NOTICE "Photron PNC-2000 flash mapping: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR);
+
+ mymtd = do_cfi_probe(&pnc_map);
+ if (mymtd) {
+ mymtd->module = THIS_MODULE;
+
+ add_mtd_device(&pnc_mtds[0]); /* boot */
+ add_mtd_device(&pnc_mtds[1]); /* kernel */
+ add_mtd_device(&pnc_mtds[2]); /* file system */
+ return 0;
+ }
+
+ return -ENXIO;
+}
+
+static void __exit cleanup_pnc(void)
+{
+ if (mymtd) {
+ del_mtd_device(&pnc_mtds[2]);
+ del_mtd_device(&pnc_mtds[1]);
+ del_mtd_device(&pnc_mtds[0]);
+ map_destroy(mymtd);
+ }
+}
@@ -3271,6+3271,7 @@ srom_map_media(struct net_device *dev)
case ANS:
lp->media = ANS;
+ lp->fdx = lp->params.fdx;
break;
default:
@@ -175,6+175,7 @@ ifeq ($(CONFIG_SDLA),y) else
ifeq ($(CONFIG_SDLA),m)
M_OBJS += sdla.o
+ endif
endif
ifeq ($(CONFIG_VENDOR_SANGOMA),y)
@@ -194,8+195,6 @@ ifeq ($(CONFIG_VENDOR_SANGOMA),y) endif
endif
-endif
-
ifeq ($(CONFIG_VENDOR_SANGOMA),m)
MX_OBJS += sdladrv.o
M_OBJS += wanpipe.o
@@ -1587,7+1587,7 @@ static int trident_mmap(struct file *file, struct vm_area_struct *vma) goto out;
dmabuf->mapped = 1;
ret = 0;
-out;
+out:
unlock_kernel();
return ret;
}
@@ -58,8+58,6 @@ static struct usb_driver *usb_minors[16];
int usb_register(struct usb_driver *new_driver)
{
- struct list_head *tmp;
-
if (new_driver->fops != NULL) {
if (usb_minors[new_driver->minor/16]) {
err("error registering %s driver", new_driver->name);
@@ -75,13+73,22 @@ int usb_register(struct usb_driver *new_driver) /* Add it to the list of known drivers */
list_add(&new_driver->driver_list, &usb_driver_list);
- /*
- * We go through all existing devices, and see if any of them would
- * be acceptable to the new driver.. This is done using a depth-first
- * search for devices without a registered driver already, then
- * running 'probe' with each of the drivers registered on every one
- * of these.
- */
+ usb_scan_devices();
+
+ return 0;
+}
+
+/*
+ * We go through all existing devices, and see if any of them would
+ * be acceptable to the new driver.. This is done using a depth-first
+ * search for devices without a registered driver already, then
+ * running 'probe' with each of the drivers registered on every one
+ * of these.
+ */
+void usb_scan_devices(void)
+{
+ struct list_head *tmp;
+
tmp = usb_bus_list.next;
while (tmp != &usb_bus_list) {
struct usb_bus *bus = list_entry(tmp,struct usb_bus, bus_list);
@@ -89,7+96,6 @@ int usb_register(struct usb_driver *new_driver) tmp = tmp->next;
usb_check_support(bus->root_hub);
}
- return 0;
}
/*
@@ -1772,6+1778,7 @@ EXPORT_SYMBOL(usb_ifnum_to_if);
EXPORT_SYMBOL(usb_register);
EXPORT_SYMBOL(usb_deregister);
+EXPORT_SYMBOL(usb_scan_devices);
EXPORT_SYMBOL(usb_alloc_bus);
EXPORT_SYMBOL(usb_free_bus);
EXPORT_SYMBOL(usb_register_bus);
@@ -100,8+100,8 @@ void fbcon_mac_bmove(struct display *p, int sy, int sx, int dy, int dx, err_buf[cnt] = 0x700 | err_str[cnt];
fbcon_mac_putcs(p->conp, p, err_buf, len, 0, 0);
/* pause for the user */
- for(cnt = 0; cnt < 50000; cnt++)
- udelay(100);
+ printk( "ERROR: shift algorithm...\n" );
+ mdelay(5000);
return;
}
}
@@ -318,12+318,25 @@ void fbcon_mac_revc(struct display *p, int xx, int yy) }
}
+static inline void plot_helper(u8 *dest, u8 bit, int bw)
+{
+ switch (bw) {
+ case PIXEL_BLACK_MAC:
+ fb_writeb( fb_readb(dest) | bit, dest );
+ break;
+ case PIXEL_WHITE_MAC:
+ fb_writeb( fb_readb(dest) & (~bit), dest );
+ break;
+ case PIXEL_INVERT_MAC:
+ fb_writeb( fb_readb(dest) ^ bit, dest );
+ break;
+ default:
+ printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
+ }
+}
+
/*
* plot_pixel_mac
- *
- * bw == 0 = black
- * 1 = white
- * 2 = invert
*/
static void plot_pixel_mac(struct display *p, int bw, int pixel_x, int pixel_y)
{
@@ -333,10+346,8 @@ static void plot_pixel_mac(struct display *p, int bw, int pixel_x, int pixel_y)
/* There *are* 68k Macs that support more than 832x624, you know :-) */
if (pixel_x < 0 || pixel_y < 0 || pixel_x >= p->var.xres || pixel_y >= p->var.yres) {
- int cnt;
printk ("ERROR: pixel_x == %d, pixel_y == %d", pixel_x, pixel_y);
- for(cnt = 0; cnt < 100000; cnt++)
- udelay(100);
+ mdelay(1000);
return;
}
@@ -344,90+355,36 @@ static void plot_pixel_mac(struct display *p, int bw, int pixel_x, int pixel_y) case 1:
dest = (u8 *) ((pixel_x >> 3) + p->screen_base + pixel_y * p->next_line);
bit = 0x80 >> (pixel_x & 7);
- switch (bw) {
- case PIXEL_BLACK_MAC:
- *dest |= bit;
- break;
- case PIXEL_WHITE_MAC:
- *dest &= ~bit;
- break;
- case PIXEL_INVERT_MAC:
- *dest ^= bit;
- break;
- default:
- printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
- }
+ plot_helper(dest, bit, bw);
break;
case 2:
dest = (u8 *) ((pixel_x >> 2) + p->screen_base + pixel_y * p->next_line);
bit = 0xC0 >> ((pixel_x & 3) << 1);
- switch (bw) {
- case PIXEL_BLACK_MAC:
- *dest |= bit;
- break;
- case PIXEL_WHITE_MAC:
- *dest &= ~bit;
- break;
- case PIXEL_INVERT_MAC:
- *dest ^= bit;
- break;
- default:
- printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
- }
+ plot_helper(dest, bit, bw);
break;
case 4:
- dest = (u8 *) ((pixel_x / 2) + p->screen_base + pixel_y * p->next_line);
+ dest = (u8 *) ((pixel_x >> 1) + p->screen_base + pixel_y * p->next_line);
bit = 0xF0 >> ((pixel_x & 1) << 2);
- switch (bw) {
- case PIXEL_BLACK_MAC:
- *dest |= bit;
- break;
- case PIXEL_WHITE_MAC:
- *dest &= ~bit;
- break;
- case PIXEL_INVERT_MAC:
- *dest ^= bit;
- break;
- default:
- printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
- }
+ plot_helper(dest, bit, bw);
break;
case 8:
dest = (u8 *) (pixel_x + p->screen_base + pixel_y * p->next_line);
bit = 0xFF;
- switch (bw) {
- case PIXEL_BLACK_MAC:
- *dest |= bit;
- break;
- case PIXEL_WHITE_MAC:
- *dest &= ~bit;
- break;
- case PIXEL_INVERT_MAC:
- *dest ^= bit;
- break;
- default:
- printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
- }
+ plot_helper(dest, bit, bw);
break;
+/* FIXME: You can't access framebuffer directly like this! */
case 16:
dest16 = (u16 *) ((pixel_x *2) + p->screen_base + pixel_y * p->next_line);
pix16 = 0xFFFF;
switch (bw) {
- case PIXEL_BLACK_MAC:
- *dest16 = ~pix16;
- break;
- case PIXEL_WHITE_MAC:
- *dest16 = pix16;
- break;
- case PIXEL_INVERT_MAC:
- *dest16 ^= pix16;
- break;
- default:
- printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
+ case PIXEL_BLACK_MAC: *dest16 = ~pix16; break;
+ case PIXEL_WHITE_MAC: *dest16 = pix16; break;
+ case PIXEL_INVERT_MAC: *dest16 ^= pix16; break;
+ default: printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
}
break;
@@ -435,17+392,10 @@ static void plot_pixel_mac(struct display *p, int bw, int pixel_x, int pixel_y) dest32 = (u32 *) ((pixel_x *4) + p->screen_base + pixel_y * p->next_line);
pix32 = 0xFFFFFFFF;
switch (bw) {
- case PIXEL_BLACK_MAC:
- *dest32 = ~pix32;
- break;
- case PIXEL_WHITE_MAC:
- *dest32 = pix32;
- break;
- case PIXEL_INVERT_MAC:
- *dest32 ^= pix32;
- break;
- default:
- printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
+ case PIXEL_BLACK_MAC: *dest32 = ~pix32; break;
+ case PIXEL_WHITE_MAC: *dest32 = pix32; break;
+ case PIXEL_INVERT_MAC: *dest32 ^= pix32; break;
+ default: printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
}
break;
}
@@ -497,7+447,7 @@ static int get_pixel_mac(struct display *p, int pixel_x, int pixel_y) */
struct display_switch fbcon_mac = {
- fbcon_mac_setup, fbcon_mac_bmove, fbcon_mac_clear, fbcon_mac_putc,
+ fbcon_mac_setup, fbcon_redraw_bmove, fbcon_redraw_clear, fbcon_mac_putc,
fbcon_mac_putcs, fbcon_mac_revc, NULL, NULL, NULL, FONTWIDTHRANGE(1,8)
};
@@ -1124,6+1124,15 @@ static void fbcon_redraw(struct vc_data *conp, struct display *p, }
}
+void fbcon_redraw_clear(struct vc_data *conp, struct display *p, int sy, int sx,
+ int height, int width)
+{
+ int x, y;
+ for (y=0; y<height; y++)
+ for (x=0; x<width; x++)
+ fbcon_putc(conp, ' ', sy+y, sx+x);
+}
+
/* This cannot be used together with ypan or ywrap */
void fbcon_redraw_bmove(struct display *p, int sy, int sx, int dy, int dx, int h, int w)
{
@@ -2422,5+2431,6 @@ struct display_switch fbcon_dummy = {
EXPORT_SYMBOL(fb_display);
EXPORT_SYMBOL(fbcon_redraw_bmove);
+EXPORT_SYMBOL(fbcon_redraw_clear);
EXPORT_SYMBOL(fbcon_dummy);
EXPORT_SYMBOL(fb_con);
#include <video/fbcon-cfb16.h>
#include <video/fbcon-cfb24.h>
#include <video/fbcon-cfb32.h>
+#include <video/fbcon-mac.h>
#define dac_reg (0x3c8)
#define dac_val (0x3c9)
@@ -220,8+221,13 @@ static void vesafb_set_disp(int con) break;
#endif
default:
+#ifdef FBCON_HAS_MAC
+ sw = &fbcon_mac;
+ break;
+#else
sw = &fbcon_dummy;
return;
+#endif
}
memcpy(&vesafb_sw, sw, sizeof(*sw));
display->dispsw = &vesafb_sw;
* maybe other stuff do to.
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
- * $Id: jffs_fm.c,v 1.6 2000/06/30 14:13:03 dwmw2 Exp $
+ * $Id: jffs_fm.c,v 1.8 2000/07/13 13:15:33 scote1 Exp $
*
* Ported to Linux 2.3.x and MTD:
* Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB
*
*/
#define __NO_VERSION__
-#include <linux/config.h>
#include <linux/malloc.h>
#include <linux/blkdev.h>
#include <linux/jffs.h>
@@ -68,7+67,7 @@ jffs_build_begin(struct jffs_control *c, kdev_t dev)
fmc->used_size = 0;
fmc->dirty_size = 0;
- fmc->sector_size = 65536;
+ fmc->sector_size = mtd->erasesize;
fmc->max_chunk_size = fmc->sector_size >> 1;
fmc->min_free_size = (fmc->sector_size << 1) - fmc->max_chunk_size;
fmc->mtd = mtd;
@@ -614,13+613,16 @@ jffs_flash_erasable_size(struct mtd_info *mtd, __u32 offset, __u32 size) ssize = mtd->erasesize;
if (offset % ssize) {
+ printk(KERN_WARNING "jffs_flash_erasable_size() given non-aligned offset %lx (erasesize %lx)\n", offset, ssize);
/* The offset is not sector size aligned. */
return -1;
}
else if (offset > mtd->size) {
+ printk(KERN_WARNING "jffs_flash_erasable_size given offset off the end of device (%lx > %lx)\n", offset, mtd->size);
return -2;
}
else if (offset + size > mtd->size) {
+ printk(KERN_WARNING "jffs_flash_erasable_size() given length which runs off the end of device (ofs %lx + len %lx = %lx, > %lx)\n", offset,size, offset+size, mtd->size);
return -3;
}
#include <linux/file.h>
#include <linux/poll.h>
#include <linux/malloc.h>
-#include <linux/smp_lock.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -304,7+303,6 @@ static int pipe_release(struct inode *inode, int decr, int decw)
{
down(PIPE_SEM(*inode));
- lock_kernel();
PIPE_READERS(*inode) -= decr;
PIPE_WRITERS(*inode) -= decw;
if (!PIPE_READERS(*inode) && !PIPE_WRITERS(*inode)) {
@@ -315,7+313,6 @@ pipe_release(struct inode *inode, int decr, int decw) } else {
wake_up_interruptible(PIPE_WAIT(*inode));
}
- unlock_kernel();
up(PIPE_SEM(*inode));
return 0;
@@ -368,14+365,12 @@ pipe_write_open(struct inode *inode, struct file *filp) static int
pipe_rdwr_open(struct inode *inode, struct file *filp)
{
- lock_kernel();
down(PIPE_SEM(*inode));
if (filp->f_mode & FMODE_READ)
PIPE_READERS(*inode)++;
if (filp->f_mode & FMODE_WRITE)
PIPE_WRITERS(*inode)++;
up(PIPE_SEM(*inode));
- unlock_kernel();
return 0;
}
#ifndef _ASM_SN_KLCONFIG_H
#define _ASM_SN_KLCONFIG_H
-#include <linux/config.h>
-
/*
* The KLCONFIG structures store info about the various BOARDs found
* during Hardware Discovery. In addition, it stores info about the
* that offsets of existing fields do not change.
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <asm/sn/types.h>
#if defined(CONFIG_SGI_IP27)
// XXX Stolen from <sys/SN/router.h>:
#define MAX_ROUTER_PORTS (6) /* Max. number of ports on a router */
#include <asm/sn/sn0/sn0_fru.h>
-#include <asm/sn/agent.h>
//#include <sys/graph.h>
-#include <asm/arc/types.h>
-#include <asm/arc/hinv.h>
//#include <sys/xtalk/xbow.h>
-#if defined(CONFIG_SGI_IO)
-// The hack file has to be before vector and after sn0_fru....
-#include <asm/hack.h>
-#include <asm/sn/vector.h>
-#include <asm/xtalk/xtalk.h>
-#endif /* CONFIG_SGI_IO */
#elif defined(CONFIG_SGI_IP35)
-#include <asm/hack.h>
#include <asm/sn/sn1/addrs.h>
-#include <asm/sn/vector.h>
#include <sys/sn/router.h>
-#include <asm/sn/agent.h>
#include <sys/graph.h>
+#include <asm/xtalk/xbow.h>
+#endif /* !CONFIG_SGI_IP27 && !CONFIG_SGI_IP35 */
+#if defined(CONFIG_SGI_IP27) || defined(CONFIG_SGI_IP35)
+#include <asm/sn/agent.h>
#include <asm/arc/types.h>
#include <asm/arc/hinv.h>
-#include <asm/xtalk/xbow.h>
+#if defined(CONFIG_SGI_IO) || defined(CONFIG_SGI_IP35)
+// The hack file has to be before vector and after sn0_fru....
+#include <asm/hack.h>
+#include <asm/sn/vector.h>
#include <asm/xtalk/xtalk.h>
-#endif /* !CONFIG_SGI_IP27 && !CONFIG_SGI_IP35 */
+#endif /* CONFIG_SGI_IO || CONFIG_SGI_IP35 */
+#endif /* CONFIG_SGI_IP27 || CONFIG_SGI_IP35 */
#define KLCFGINFO_MAGIC 0xbeedbabe
--- /dev/null
+/*
+ * Routines for handling backlight control on PowerBooks
+ *
+ * For now, implementation resides in arch/ppc/kernel/pmac_support.c
+ *
+ */
+#ifndef __ASM_PPC_BACKLIGHT_H
+#define __ASM_PPC_BACKLIGHT_H
+
+/* Abstract values */
+#define BACKLIGHT_OFF 0
+#define BACKLIGHT_MIN 1
+#define BACKLIGHT_MAX 0xf
+
+struct backlight_controller {
+ int (*set_enable)(int enable, int level, void *data);
+ int (*set_level)(int level, void *data);
+};
+
+extern void register_backlight_controller(struct backlight_controller *ctrler, void *data, char *type);
+extern void unregister_backlight_controller(struct backlight_controller *ctrler, void *data);
+
+extern int set_backlight_enable(int enable);
+extern int get_backlight_enable(void);
+extern int set_backlight_level(int level);
+extern int get_backlight_level(void);
+
+#endif
\ No newline at end of file
@@ -45,6+45,7 @@ enum system_feature { FEATURE_IDE2_reset,
FEATURE_Mediabay_IDE_switch, /* MB IDE bus switch */
FEATURE_Mediabay_content, /* MB content indicator enable */
+ FEATURE_Airport_reset, /* Is it actually a reset ? */
FEATURE_last,
};
@@ -70,4+71,20 @@ extern int feature_clear(struct device_node* device, enum system_feature f); extern void feature_init(void);
+/*
+ * Additional functions related to Core99 machines
+ */
+extern void feature_set_gmac_power(struct device_node* device, int power);
+
+extern void feature_set_usb_power(struct device_node* device, int power);
+
+extern void feature_set_firewire_power(struct device_node* device, int power);
+
+/*
+ * Sleep related functions. At term, they should be high-priority notifiers
+ */
+extern void feature_prepare_for_sleep(void);
+
+extern void feature_wake_up(void);
+
#endif /* __ASM_PPC_FEATURE_H */
#include <linux/config.h>
#include <asm/smp.h>
-extern unsigned int local_irq_count[NR_CPUS];
+typedef struct {
+ unsigned int __local_irq_count;
+ unsigned int __local_bh_count;
+ atomic_t __nmi_counter;
+ unsigned int __pad[5];
+} ____cacheline_aligned irq_cpustat_t;
+
+extern irq_cpustat_t irq_stat [NR_CPUS];
+
+/*
+ * Simple wrappers reducing source bloat
+ */
+#define local_irq_count(cpu) (irq_stat[(cpu)].__local_irq_count)
+#define local_bh_count(cpu) (irq_stat[(cpu)].__local_bh_count)
+#define nmi_counter(cpu) (irq_stat[(cpu)].__nmi_counter)
/*
* Are we in an interrupt context? Either doing bottom half
* or hardware interrupt processing?
*/
#define in_interrupt() ({ int __cpu = smp_processor_id(); \
- (local_irq_count[__cpu] + local_bh_count[__cpu] != 0); })
+ (local_irq_count(__cpu) + local_bh_count(__cpu) != 0); })
-#define in_irq() (local_irq_count[smp_processor_id()] != 0)
+#define in_irq() (local_irq_count(smp_processor_id()) != 0)
#ifndef CONFIG_SMP
-#define hardirq_trylock(cpu) (local_irq_count[cpu] == 0)
+#define hardirq_trylock(cpu) (local_irq_count(cpu) == 0)
#define hardirq_endlock(cpu) do { } while (0)
-#define hardirq_enter(cpu) (local_irq_count[cpu]++)
-#define hardirq_exit(cpu) (local_irq_count[cpu]--)
+#define hardirq_enter(cpu) (local_irq_count(cpu)++)
+#define hardirq_exit(cpu) (local_irq_count(cpu)--)
#define synchronize_irq() do { } while (0)
@@ -46,7+60,7 @@ static inline void hardirq_enter(int cpu) {
unsigned int loops = 10000000;
- ++local_irq_count[cpu];
+ ++local_irq_count(cpu);
atomic_inc(&global_irq_count);
while (test_bit(0,&global_irq_lock)) {
if (smp_processor_id() == global_irq_holder) {
@@ -68,7+82,7 @@ static inline void hardirq_enter(int cpu) static inline void hardirq_exit(int cpu)
{
atomic_dec(&global_irq_count);
- --local_irq_count[cpu];
+ --local_irq_count(cpu);
}
static inline int hardirq_trylock(int cpu)
-/*
- * heathrow.h: definitions for using the "Heathrow" I/O controller chip.
- *
- * Grabbed from Open Firmware definitions on a PowerBook G3 Series
- *
- * Copyright (C) 1997 Paul Mackerras.
- */
-
-/* offset from ohare base for feature control register */
-#define HEATHROW_FEATURE_REG 0x38
-
-/*
- * Bits in feature control register.
- * Bits postfixed with a _N are in inverse logic
- */
-#define HRW_MODEM_POWER_N 1 /* turns off modem power */
-#define HRW_BAY_POWER_N 2
-#define HRW_BAY_PCI_ENABLE 4
-#define HRW_BAY_IDE_ENABLE 8
-#define HRW_BAY_FLOPPY_ENABLE 0x10
-#define HRW_IDE0_ENABLE 0x20
-#define HRW_IDE0_RESET_N 0x40
-#define HRW_BAY_RESET_N 0x80
-#define HRW_IOBUS_ENABLE 0x100 /* Internal IDE ? */
-#define HRW_SCC_ENABLE 0x200
-#define HRW_MESH_ENABLE 0x400
-#define HRW_SWIM_ENABLE 0x800
-#define HRW_SOUND_POWER_N 0x1000
-#define HRW_SOUND_CLK_ENABLE 0x2000
-#define HRW_SCCA_IO 0x4000
-#define HRW_SCCB_IO 0x8000
-#define HRW_PORT_OR_DESK_VIA_N 0x10000 /* This one is 0 on PowerBook */
-#define HRW_PWM_MON_ID_N 0x20000 /* ??? (0) */
-#define HRW_HOOK_MB_CNT_N 0x40000 /* ??? (0) */
-#define HRW_SWIM_CLONE_FLOPPY 0x80000 /* ??? (0) */
-#define HRW_AUD_RUN22 0x100000 /* ??? (1) */
-#define HRW_SCSI_LINK_MODE 0x200000 /* Read ??? (1) */
-#define HRW_ARB_BYPASS 0x400000 /* ??? (0 on main, 1 on gatwick) */
-#define HRW_IDE1_RESET_N 0x800000 /* Media bay */
-#define HRW_SLOW_SCC_PCLK 0x1000000 /* ??? (0) */
-#define HRW_RESET_SCC 0x2000000 /* perhaps? */
-#define HRW_MFDC_CELL_ENABLE 0x4000000 /* ??? (0) */
-#define HRW_USE_MFDC 0x8000000 /* ??? (0) */
-#define HRW_BMAC_IO_ENABLE 0x60000000 /* two bits, not documented in OF */
-#define HRW_BMAC_RESET 0x80000000 /* not documented in OF */
-
-
-#define PADD_MODEM_POWER_N 0x00000001 /* modem power on paddington */
+/*
+ * heathrow.h: definitions for using the "Heathrow" I/O controller chip.
+ *
+ * Grabbed from Open Firmware definitions on a PowerBook G3 Series
+ *
+ * Copyright (C) 1997 Paul Mackerras.
+ */
+
+/* offset from ohare base for feature control register */
+#define HEATHROW_FEATURE_REG 0x38
+
+/*
+ * Bits in feature control register.
+ * Bits postfixed with a _N are in inverse logic
+ */
+#define HRW_RESET_SCC 0x00000001 /* Named in_use_led in OF ??? */
+#define HRW_BAY_POWER_N 0x00000002
+#define HRW_BAY_PCI_ENABLE 0x00000004
+#define HRW_BAY_IDE_ENABLE 0x00000008
+#define HRW_BAY_FLOPPY_ENABLE 0x00000010
+#define HRW_IDE0_ENABLE 0x00000020
+#define HRW_IDE0_RESET_N 0x00000040
+#define HRW_BAY_RESET_N 0x00000080
+#define HRW_IOBUS_ENABLE 0x00000100 /* Internal IDE ? */
+#define HRW_SCC_ENABLE 0x00000200
+#define HRW_MESH_ENABLE 0x00000400
+#define HRW_SWIM_ENABLE 0x00000800
+#define HRW_SOUND_POWER_N 0x00001000
+#define HRW_SOUND_CLK_ENABLE 0x00002000
+#define HRW_SCCA_IO 0x00004000
+#define HRW_SCCB_IO 0x00008000
+#define HRW_PORT_OR_DESK_VIA_N 0x00010000 /* This one is 0 on PowerBook */
+#define HRW_PWM_MON_ID_N 0x00020000 /* ??? (0) */
+#define HRW_HOOK_MB_CNT_N 0x00040000 /* ??? (0) */
+#define HRW_SWIM_CLONE_FLOPPY 0x00080000 /* ??? (0) */
+#define HRW_AUD_RUN22 0x00100000 /* ??? (1) */
+#define HRW_SCSI_LINK_MODE 0x00200000 /* Read ??? (1) */
+#define HRW_ARB_BYPASS 0x00400000 /* ??? (0 on main, 1 on gatwick) */
+#define HRW_IDE1_RESET_N 0x00800000 /* Media bay */
+#define HRW_SLOW_SCC_PCLK 0x01000000 /* ??? (0) */
+#define HRW_MODEM_POWER_N 0x02000000 /* Used by internal modem on wallstreet */
+#define HRW_MFDC_CELL_ENABLE 0x04000000 /* ??? (0) */
+#define HRW_USE_MFDC 0x08000000 /* ??? (0) */
+#define HRW_BMAC_IO_ENABLE 0x60000000 /* two bits, not documented in OF */
+#define HRW_BMAC_RESET 0x80000000 /* not documented in OF */
+
+#define PADD_MODEM_POWER_N 0x00000001 /* modem power on paddington */
@@ -74,6+74,11 @@ struct machdep_calls { unsigned char dev_fn, unsigned char offset, unsigned int val);
void (*pcibios_fixup)(void);
void (*pcibios_fixup_bus)(struct pci_bus *);
+
+ void* (*pci_dev_io_base)(unsigned char bus, unsigned char devfn);
+ void* (*pci_dev_mem_base)(unsigned char bus, unsigned char devfn);
+ int (*pci_dev_root_bridge)(unsigned char bus, unsigned char devfn);
+
/* this is for modules, since _machine can be a define -- Cort */
int ppc_machine;
};
#include <asm/rpxclassic.h>
#endif
+#if (defined(CONFIG_TQM860) || defined(CONFIG_TQM860L))
+#include <asm/tqm860.h>
+#endif
+
+#ifdef CONFIG_TQM8xxL
+#include <asm/tqm8xxL.h>
+#endif
+
/* I need this to get pt_regs.......
*/
#include <asm/ptrace.h>
@@ -6,9+6,22 @@ void pmac_find_bridges(void); /*
* pci_io_base returns the memory address at which you can access
* the I/O space for PCI bus number `bus' (or NULL on error).
+ *
+ * NOTE: This doesn't handle the new Uni-N chip which requires
+ * per-device io_base.
*/
void *pci_io_base(unsigned int bus);
+/* This version handles the new Uni-N host bridge, the iobase is now
+ * a per-device thing. I also added the memory base so PReP can
+ * be fixed to return 0xc0000000 (I didn't actually implement it)
+ */
+void *pci_dev_io_base(unsigned char bus, unsigned char devfn);
+void *pci_dev_mem_base(unsigned char bus, unsigned char devfn);
+
+/* Returns the root-bridge number (Uni-N number) of a device */
+int pci_dev_root_bridge(unsigned char bus, unsigned char devfn);
+
/*
* pci_device_loc returns the bus number and device/function number
* for a device on a PCI bus, given its device_node struct.
#ifndef __PPC_PCI_H
#define __PPC_PCI_H
+/* Values for the `which' argument to sys_pciconfig_iobase syscall. */
+#define IOBASE_BRIDGE_NUMBER 0
+#define IOBASE_MEMORY 1
+#define IOBASE_IO 2
+
+#ifdef __KERNEL__
+
/* Can be used to override the logic in pci_scan_bus for skipping
* already-configured bus numbers - to be used for buggy BIOSes
* or architectures with incomplete PCI setup by the loader.
@@ -95,4+102,6 @@ extern inline int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask) #define sg_dma_address(sg) (virt_to_bus((sg)->address))
#define sg_dma_len(sg) ((sg)->length)
+#endif /* __KERNEL__ */
+
#endif /* __PPC_PCI_H */
#include <linux/config.h>
#include <asm/ptrace.h>
-#include <asm/residual.h>
#include <asm/types.h>
/* Machine State Register (MSR) Fields */
#define _MACH_oak 0x00000800 /* IBM "Oak" 403 eval. board */
#define _MACH_walnut 0x00001000 /* IBM "Walnut" 405GP eval. board */
#define _MACH_8260 0x00002000 /* Generic 8260 */
+#define _MACH_tqm860 0x00004000 /* TQM860/L */
+#define _MACH_tqm8xxL 0x00008000 /* TQM8xxL */
/* see residual.h for these */
@@ -89,4+89,7 @@ extern void prom_drawstring(const char *c); extern void prom_drawhex(unsigned long v);
extern void prom_drawchar(char c);
+extern void map_bootx_text(void);
+
+
#endif /* _PPC_PROM_H */
extern unsigned int local_bh_count[NR_CPUS];
-#define local_bh_disable() do { local_bh_count[smp_processor_id()]++; barrier(); } while (0)
-#define local_bh_enable() do { barrier(); local_bh_count[smp_processor_id()]--; } while (0)
+#define local_bh_disable() do { local_bh_count(smp_processor_id())++; barrier(); } while (0)
+#define local_bh_enable() do { barrier(); local_bh_count(smp_processor_id())--; } while (0)
-#define in_softirq() (local_bh_count[smp_processor_id()] != 0)
+#define in_softirq() (local_bh_count(smp_processor_id()) != 0)
#endif /* __ASM_SOFTIRQ_H */
--- /dev/null
+
+/*
+ * A collection of structures, addresses, and values associated with
+ * the TQ Systems TQM860 modules. This was originally created for the
+ * MBX860, and probably needs revisions for other boards (like the 821).
+ * When this file gets out of control, we can split it up into more
+ * meaningful pieces.
+ *
+ * Based on mbx.h, Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
+ *
+ * Copyright (c) 1999 Wolfgang Denk (wd@denx.de)
+ */
+#ifndef __MACH_TQM860_DEFS
+#define __MACH_TQM860_DEFS
+
+/* A Board Information structure that is given to a program when
+ * EPPC-Bug starts it up.
+ */
+typedef struct bd_info {
+ unsigned long bi_memstart; /* start of DRAM memory */
+ unsigned long bi_memsize; /* size of DRAM memory in bytes */
+ unsigned long bi_flashstart; /* start of FLASH memory */
+ unsigned long bi_flashsize; /* size of FLASH memory */
+ unsigned long bi_flashoffset; /* reserved area for startup monitor */
+ unsigned long bi_sramstart; /* start of SRAM memory */
+ unsigned long bi_sramsize; /* size of SRAM memory */
+ unsigned long bi_immr_base; /* base of IMMR register */
+ unsigned long bi_bootflags; /* boot / reboot flag (for LynxOS) */
+ unsigned long bi_ip_addr; /* IP Address */
+ unsigned char bi_enetaddr[6]; /* Ethernet adress */
+ unsigned char bi_reserved[2]; /* -- just for alignment -- */
+ unsigned long bi_putchar; /* Addr of monitor putchar() to Console */
+ unsigned long bi_intfreq; /* Internal Freq, in MHz */
+ unsigned long bi_busfreq; /* Bus Freq, in MHz */
+ unsigned long bi_baudrate; /* Console Baudrate */
+} bd_t;
+
+/* Configuration options for TQ Systems TQM860 mini module
+ */
+
+#define TQM_RESET_ADDR 0x40000100 /* Monitor Reset Entry */
+
+#define TQM_IMMR_BASE 0xFFF00000 /* phys. addr of IMMR */
+#define TQM_IMAP_SIZE (64 * 1024) /* size of mapped area */
+
+#define TQM_CLOCKRATE 50 /* 50 MHz Clock */
+#define TQM_BAUDRATE 115200 /* Console baud rate */
+#define TQM_IP_ADDR 0x0A000063 /* IP addr: 10.0.0.99 */
+
+#define TQM_SERVER_IP "10.0.0.3" /* NFS server IP addr */
+#define TQM_SERVER_DIR "/LinuxPPC" /* NFS exported root */
+
+#define IMAP_ADDR TQM_IMMR_BASE /* physical base address of IMMR area */
+#define IMAP_SIZE TQM_IMAP_SIZE /* mapped size of IMMR area */
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS 0
+
+/* Generic 8xx type
+*/
+#define _MACH_8xx (_MACH_tqm860)
+
+#endif /* __MACH_TQM860_DEFS */
+
--- /dev/null
+
+/*
+ * A collection of structures, addresses, and values associated with
+ * the TQ Systems TQM850L modules. This was originally created for the
+ * MBX860, and probably needs revisions for other boards (like the 821).
+ * When this file gets out of control, we can split it up into more
+ * meaningful pieces.
+ *
+ * Based on mbx.h, Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
+ *
+ * Copyright (c) 1999 Wolfgang Denk (wd@denx.de)
+ */
+#ifndef __MACH_TQM8xxL_DEFS
+#define __MACH_TQM8xxL_DEFS
+
+/* A Board Information structure that is given to a program when
+ * EPPC-Bug starts it up.
+ */
+typedef struct bd_info {
+ unsigned long bi_memstart; /* start of DRAM memory */
+ unsigned long bi_memsize; /* size of DRAM memory in bytes */
+ unsigned long bi_flashstart; /* start of FLASH memory */
+ unsigned long bi_flashsize; /* size of FLASH memory */
+ unsigned long bi_flashoffset; /* reserved area for startup monitor */
+ unsigned long bi_sramstart; /* start of SRAM memory */
+ unsigned long bi_sramsize; /* size of SRAM memory */
+ unsigned long bi_immr_base; /* base of IMMR register */
+ unsigned long bi_bootflags; /* boot / reboot flag (for LynxOS) */
+ unsigned long bi_ip_addr; /* IP Address */
+ unsigned char bi_enetaddr[6]; /* Ethernet adress */
+ unsigned char bi_reserved[2]; /* -- just for alignment -- */
+ unsigned long bi_putchar; /* Addr of monitor putchar() to Console */
+ unsigned long bi_intfreq; /* Internal Freq, in MHz */
+ unsigned long bi_busfreq; /* Bus Freq, in MHz */
+ unsigned long bi_baudrate; /* Console Baudrate */
+} bd_t;
+
+/* Configuration options for TQ Systems TQM850L mini module
+ */
+
+#define TQM_RESET_ADDR 0x40000100 /* Monitor Reset Entry */
+
+#define TQM_IMMR_BASE 0xFFF00000 /* phys. addr of IMMR */
+#define TQM_IMAP_SIZE (64 * 1024) /* size of mapped area */
+
+#define TQM_CLOCKRATE 50 /* 50 MHz Clock */
+/*#define TQM_BAUDRATE 115200 */ /* Console baud rate */
+#define TQM_BAUDRATE 38400 /* Console baud rate */
+#define TQM_IP_ADDR 0x0A000063 /* IP addr: 10.0.0.99 */
+
+#define TQM_SERVER_IP "10.0.0.2" /* NFS server IP addr */
+#define TQM_SERVER_DIR "/LinuxPPC" /* NFS exported root */
+
+#define IMAP_ADDR TQM_IMMR_BASE /* physical base address of IMMR area */
+#define IMAP_SIZE TQM_IMAP_SIZE /* mapped size of IMMR area */
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS 0
+
+/* Generic 8xx type
+*/
+#define _MACH_8xx (_MACH_tqm8xxL)
+
+#endif /* __MACH_TQM8xxL_DEFS */
+
@@ -7,6+7,7 @@ struct ucontext { unsigned long uc_flags;
struct ucontext *uc_link;
stack_t uc_stack;
+ struct sigcontext_struct uc_mcontext;
sigset_t uc_sigmask; /* mask last for extensibility */
};
#define __NR_stat64 195
#define __NR_lstat64 196
#define __NR_fstat64 197
+#define __NR_sys_pciconfig_read 198
+#define __NR_sys_pciconfig_write 199
+#define __NR_sys_pciconfig_iobase 200
+#define __NR_multiplexer 201
#define __NR(n) #n
* <linux/vt_buffer.h> has already done the right job for us.
*/
-extern inline void scr_writew(u16 val, u16 *addr)
+extern inline void scr_writew(u16 val, volatile u16 *addr)
{
st_le16(addr, val);
}
-extern inline u16 scr_readw(const u16 *addr)
+extern inline u16 scr_readw(volatile const u16 *addr)
{
return ld_le16(addr);
}
/* Linux driver for Disk-On-Chip 2000 */
/* (c) 1999 Machine Vision Holdings, Inc. */
/* Author: David Woodhouse <dwmw2@mvhi.com> */
-/* $Id: doc2000.h,v 1.7 2000/06/26 20:40:53 dwmw2 Exp $ */
+/* $Id: doc2000.h,v 1.8 2000/07/10 15:46:29 dwmw2 Exp $ */
#ifndef __MTD_DOC2000_H__
#define __MTD_DOC2000_H__
#include <linux/mtd/mtd.h>
-
-#define DoC_M_CDSN_IO 0x800
#define DoC_Sig1 0
#define DoC_Sig2 1
-#define DoC_ChipID 0x1000
-#define DoC_DOCStatus 0x1001
-#define DoC_DOCControl 0x1002
-#define DoC_FloorSelect 0x1003
-#define DoC_CDSNControl 0x1004
-#define DoC_CDSNDeviceSelect 0x1005
-#define DoC_ECCConf 0x1006
-#define DoC_2k_ECCStatus 0x1007
-
-#define DoC_CDSNSlowIO 0x100d
-#define DoC_ECCSyndrome0 0x1010
-#define DoC_ECCSyndrome1 0x1011
-#define DoC_ECCSyndrome2 0x1012
-#define DoC_ECCSyndrome3 0x1013
-#define DoC_ECCSyndrome4 0x1014
-#define DoC_ECCSyndrome5 0x1015
-#define DoC_AliasResolution 0x101b
-#define DoC_ConfigInput 0x101c
-#define DoC_ReadPipeInit 0x101d
-#define DoC_WritePipeTerm 0x101e
-#define DoC_LastDataRead 0x101f
-#define DoC_NOP 0x1020
-
-#define DoC_2k_CDSN_IO 0x1800
+#define DoC_ChipID 0x1000
+#define DoC_DOCStatus 0x1001
+#define DoC_DOCControl 0x1002
+#define DoC_FloorSelect 0x1003
+#define DoC_CDSNControl 0x1004
+#define DoC_CDSNDeviceSelect 0x1005
+#define DoC_ECCConf 0x1006
+#define DoC_2k_ECCStatus 0x1007
+
+#define DoC_CDSNSlowIO 0x100d
+#define DoC_ECCSyndrome0 0x1010
+#define DoC_ECCSyndrome1 0x1011
+#define DoC_ECCSyndrome2 0x1012
+#define DoC_ECCSyndrome3 0x1013
+#define DoC_ECCSyndrome4 0x1014
+#define DoC_ECCSyndrome5 0x1015
+#define DoC_AliasResolution 0x101b
+#define DoC_ConfigInput 0x101c
+#define DoC_ReadPipeInit 0x101d
+#define DoC_WritePipeTerm 0x101e
+#define DoC_LastDataRead 0x101f
+#define DoC_NOP 0x1020
+
+#define DoC_Mil_CDSN_IO 0x0800
+#define DoC_2k_CDSN_IO 0x1800
/* How to access the device?
* On ARM, it'll be mmap'd directly with 32-bit wide accesses.
#define ReadDOC(adr, reg) readb(((unsigned long)adr) + DoC_##reg)
#define WriteDOC(d, adr, reg) writeb(d, ((unsigned long)adr) + DoC_##reg)
#endif
-#define DOC_MODE_RESET 0
-#define DOC_MODE_NORMAL 1
-#define DOC_MODE_RESERVED1 2
-#define DOC_MODE_RESERVED2 3
-
-#define DOC_MODE_MDWREN 4
-#define DOC_MODE_CLR_ERR 0x80
-
-#define DOC_ChipID_Doc2k 0x20
-#define DOC_ChipID_DocMil 0x30
-
-#define CDSN_CTRL_FR_B 0x80
-#define CDSN_CTRL_ECC_IO 0x20
-#define CDSN_CTRL_FLASH_IO 0x10
-#define CDSN_CTRL_WP 8
-#define CDSN_CTRL_ALE 4
-#define CDSN_CTRL_CLE 2
-#define CDSN_CTRL_CE 1
-
-#define DOC_ECC_RESET 0
-#define DOC_ECC_ERROR 0x80
-#define DOC_ECC_RW 0x20
-#define DOC_ECC__EN 0x08
-#define DOC_TOGGLE_BIT 0x04
-#define DOC_ECC_RESV 0x02
+
+#define DOC_MODE_RESET 0
+#define DOC_MODE_NORMAL 1
+#define DOC_MODE_RESERVED1 2
+#define DOC_MODE_RESERVED2 3
+
+#define DOC_MODE_MDWREN 4
+#define DOC_MODE_CLR_ERR 0x80
+
+#define DOC_ChipID_Doc2k 0x20
+#define DOC_ChipID_DocMil 0x30
+
+#define CDSN_CTRL_FR_B 0x80
+#define CDSN_CTRL_ECC_IO 0x20
+#define CDSN_CTRL_FLASH_IO 0x10
+#define CDSN_CTRL_WP 0x08
+#define CDSN_CTRL_ALE 0x04
+#define CDSN_CTRL_CLE 0x02
+#define CDSN_CTRL_CE 0x01
+
+#define DOC_ECC_RESET 0
+#define DOC_ECC_ERROR 0x80
+#define DOC_ECC_RW 0x20
+#define DOC_ECC__EN 0x08
+#define DOC_TOGGLE_BIT 0x04
+#define DOC_ECC_RESV 0x02
+#define DOC_ECC_IGNORE 0x01
/* We have to also set the reserved bit 1 for enable */
#define DOC_ECC_EN (DOC_ECC__EN | DOC_ECC_RESV)
+#define DOC_ECC_DIS (DOC_ECC_IGNORE | DOC_ECC_RESV)
struct Nand {
char floor, chip;
@@ -92,6+94,9 @@ struct Nand { #define MAX_FLOORS 4
#define MAX_CHIPS 4
+#define MAX_FLOORS_MIL 4
+#define MAX_CHIPS_MIL 1
+
struct DiskOnChip {
unsigned long physadr;
unsigned long virtadr;
@@ -551,6+551,7 @@ extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned if
extern int usb_register(struct usb_driver *);
extern void usb_deregister(struct usb_driver *);
+extern void usb_scan_devices(void);
/* used these for multi-interface device registration */
extern void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv);
@@ -229,6+229,7 @@ extern int set_all_vcs(int fbidx, struct fb_ops *fb, #endif
+extern void fbcon_redraw_clear(struct vc_data *, struct display *, int, int, int, int);
extern void fbcon_redraw_bmove(struct display *, int, int, int, int, int, int);
@@ -436,10+436,7 @@ signed long schedule_timeout(signed long timeout)
add_timer(&timer);
schedule();
- del_timer(&timer);
- /* RED-PEN. Timer may be running now on another cpu.
- * Pray that process will not exit enough fastly.
- */
+ del_timer_sync(&timer);
timeout = expire - jiffies;
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/mm.h>
+#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/time.h>
#include <asm/uaccess.h>
@@ -177,7+177,7 @@ void unix_gc(void) * Avoid a recursive GC.
*/
- if(!down_trylock(&unix_gc_sem))
+ if (down_trylock(&unix_gc_sem))
return;
read_lock(&unix_table_lock);