patch-2.4.3 linux/arch/ppc/kernel/m8xx_setup.c
Next file: linux/arch/ppc/kernel/open_pic.c
Previous file: linux/arch/ppc/kernel/m8260_setup.c
Back to the patch index
Back to the overall index
- Lines: 442
- Date:
Sat Mar 3 10:52:14 2001
- Orig file:
v2.4.2/linux/arch/ppc/kernel/m8xx_setup.c
- Orig date:
Wed Feb 21 18:20:14 2001
diff -u --recursive --new-file v2.4.2/linux/arch/ppc/kernel/m8xx_setup.c linux/arch/ppc/kernel/m8xx_setup.c
@@ -32,6 +32,7 @@
#include <linux/init.h>
#include <linux/blk.h>
#include <linux/ioport.h>
+#include <asm/mpc8xx.h> /* Before ide.h to avoid warning: `MAX_HWIFS' redefined */
#include <linux/ide.h>
#include <linux/bootmem.h>
@@ -41,7 +42,6 @@
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/ide.h>
-#include <asm/mpc8xx.h>
#include <asm/8xx_immap.h>
#include <asm/machdep.h>
@@ -52,19 +52,65 @@
unsigned long m8xx_get_rtc_time(void);
void m8xx_calibrate_decr(void);
-#if 0
-extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode);
-extern int mackbd_getkeycode(unsigned int scancode);
-extern int mackbd_pretranslate(unsigned char scancode, char raw_mode);
-extern int mackbd_translate(unsigned char scancode, unsigned char *keycode,
- char raw_mode);
-extern char mackbd_unexpected_up(unsigned char keycode);
-extern void mackbd_leds(unsigned char leds);
-extern void mackbd_init_hw(void);
-#endif
-
unsigned char __res[sizeof(bd_t)];
unsigned long empty_zero_page[1024];
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+
+#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
+#include "../../../drivers/ide/ide_modes.h"
+
+static void m8xx_ide_tuneproc(ide_drive_t *drive, byte pio);
+
+typedef struct ide_ioport_desc {
+ unsigned long base_off; /* Offset to PCMCIA memory */
+ ide_ioreg_t reg_off[IDE_NR_PORTS]; /* controller reg. offsets */
+ int irq; /* IRQ */
+} ide_ioport_desc_t;
+
+ide_ioport_desc_t ioport_dsc[MAX_HWIFS] = {
+#ifdef IDE0_BASE_OFFSET
+ { IDE0_BASE_OFFSET,
+ {
+ IDE0_DATA_REG_OFFSET,
+ IDE0_ERROR_REG_OFFSET,
+ IDE0_NSECTOR_REG_OFFSET,
+ IDE0_SECTOR_REG_OFFSET,
+ IDE0_LCYL_REG_OFFSET,
+ IDE0_HCYL_REG_OFFSET,
+ IDE0_SELECT_REG_OFFSET,
+ IDE0_STATUS_REG_OFFSET,
+ IDE0_CONTROL_REG_OFFSET,
+ IDE0_IRQ_REG_OFFSET,
+ },
+ IDE0_INTERRUPT,
+ },
+# ifdef IDE1_BASE_OFFSET
+ { IDE1_BASE_OFFSET,
+ {
+ IDE1_DATA_REG_OFFSET,
+ IDE1_ERROR_REG_OFFSET,
+ IDE1_NSECTOR_REG_OFFSET,
+ IDE1_SECTOR_REG_OFFSET,
+ IDE1_LCYL_REG_OFFSET,
+ IDE1_HCYL_REG_OFFSET,
+ IDE1_SELECT_REG_OFFSET,
+ IDE1_STATUS_REG_OFFSET,
+ IDE1_CONTROL_REG_OFFSET,
+ IDE1_IRQ_REG_OFFSET,
+ },
+ IDE1_INTERRUPT,
+ },
+# endif /* IDE1_BASE_OFFSET */
+#endif /* IDE0_BASE_OFFSET */
+};
+
+ide_pio_timings_t ide_pio_clocks[6];
+
+/* Make clock cycles and always round up */
+#define PCMCIA_MK_CLKS( t, T ) (( (t) * (T) + 999U ) / 1000U )
+
+#endif /* CONFIG_BLK_DEV_MPC8xx_IDE */
+#endif /* CONFIG_BLK_DEV_IDE || CONFIG_BLK_DEV_IDE_MODULE */
#ifdef CONFIG_BLK_DEV_RAM
extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
@@ -77,6 +123,8 @@
extern unsigned long find_available_memory(void);
extern void m8xx_cpm_reset(uint);
+static void ide_interrupt_handler(void* dev_id);
+
void __init adbdev_init(void)
{
}
@@ -85,12 +133,9 @@
m8xx_setup_arch(void)
{
int cpm_page;
- extern char cmd_line[];
cpm_page = (int) alloc_bootmem_pages(PAGE_SIZE);
- printk("Boot arguments: %s\n", cmd_line);
-
/* Reset the Communication Processor Module.
*/
m8xx_cpm_reset(cpm_page);
@@ -137,7 +182,7 @@
*/
void timebase_interrupt(int irq, void * dev, struct pt_regs * regs)
{
- printk("timebase_interrupt()\n");
+ printk ("timebase_interrupt()\n");
}
/* The decrementer counts at the system (internal) clock frequency divided by
@@ -164,7 +209,7 @@
fp = (binfo->bi_intfreq * 1000000) / 16;
freq = fp*60; /* try to make freq/1e6 an integer */
divisor = 60;
- printk("time_init: decrementer frequency = %d/%d\n", freq, divisor);
+ printk("Decrementer Frequency = %d/%d\n", freq, divisor);
tb_ticks_per_jiffy = freq / HZ / divisor;
tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
@@ -232,9 +277,21 @@
void
m8xx_restart(char *cmd)
{
- extern void m8xx_gorom(void);
+ __volatile__ unsigned char dummy;
+ uint msr;
- m8xx_gorom();
+ cli();
+ ((immap_t *)IMAP_ADDR)->im_clkrst.car_plprcr |= 0x00000080;
+
+ /* Clear the ME bit in MSR to cause checkstop on machine check
+ */
+ __asm__("mfmsr %0" : "=r" (msr) );
+ msr &= ~0x1000;
+ __asm__("mtmsr %0" : : "r" (msr) );
+
+ dummy = ((immap_t *)IMAP_ADDR)->im_clkrst.res[0];
+ printk("Restart failed\n");
+ while(1);
}
void
@@ -257,8 +314,8 @@
bp = (bd_t *)__res;
- len += sprintf(len+buffer,"clock\t\t: %dMHz\n"
- "bus clock\t: %dMHz\n",
+ len += sprintf(len+buffer,"clock\t\t: %ldMHz\n"
+ "bus clock\t: %ldMHz\n",
bp->bi_intfreq /*/ 1000000*/,
bp->bi_busfreq /*/ 1000000*/);
@@ -298,17 +355,13 @@
#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-/* Define this to make a PCMCIA ATA Flash card work.
-*/
-#define ATA_FLASH 1
-
/*
* IDE stuff.
*/
void
m8xx_ide_insw(ide_ioreg_t port, void *buf, int ns)
{
-#ifdef ATA_FLASH
+#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
ide_insw(port, buf, ns);
#else
ide_insw(port+_IO_BASE, buf, ns);
@@ -318,7 +371,7 @@
void
m8xx_ide_outsw(ide_ioreg_t port, void *buf, int ns)
{
-#ifdef ATA_FLASH
+#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
ide_outsw(port, buf, ns);
#else
ide_outsw(port+_IO_BASE, buf, ns);
@@ -328,8 +381,11 @@
int
m8xx_ide_default_irq(ide_ioreg_t base)
{
-#ifdef ATA_FLASH
- return PCMCIA_INTERRUPT;
+#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
+ if (base >= MAX_HWIFS)
+ return 0;
+
+ return (ioport_dsc[base].irq);
#else
return 14;
#endif
@@ -348,60 +404,105 @@
const char *device,
void *dev_id)
{
-#ifdef ATA_FLASH
+#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
return request_8xxirq(irq, handler, flags, device, dev_id);
#else
return request_irq(irq, handler, flags, device, dev_id);
#endif
}
-/* We can use an external IDE controller or wire the IDE interface to
- * the internal PCMCIA controller.
+/* We can use an external IDE controller
+ * or wire the IDE interface to the internal PCMCIA controller.
+ *
+ * See include/linux/ide.h for definition of hw_regs_t (p, base)
*/
-void __init m8xx_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+void m8xx_ide_init_hwif_ports(hw_regs_t *hw,
+ ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
{
- ide_ioreg_t port = base;
+ ide_ioreg_t *p = hw->io_ports;
int i;
-#ifdef ATA_FLASH
+#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
volatile pcmconf8xx_t *pcmp;
+
+ static unsigned long pcmcia_base = 0;
+#else
+ ide_ioreg_t port = data_port; /* ??? XXX ??? XXX */
#endif
+ unsigned long base;
-#ifdef ATA_FLASH
+#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
*p = 0;
- *irq = 0;
+ if (irq)
+ *irq = 0;
+
+ pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia));
- if (base != 0) /* Only map the first ATA flash drive */
+ if (!pcmcia_base) {
+ /* relies PCMCIA registers being set up by firmware */
+ pcmcia_base = (unsigned long) ioremap(PCMCIA_MEM_ADDR,
+ PCMCIA_MEM_SIZE);
+
+ /* Compute clock cycles for PIO timings */
+ for (i=0; i<6; ++i) {
+ bd_t *binfo = (bd_t *)__res;
+
+ ide_pio_clocks[i].hold_time =
+ PCMCIA_MK_CLKS (ide_pio_timings[i].hold_time,
+ binfo->bi_busfreq);
+ ide_pio_clocks[i].setup_time =
+ PCMCIA_MK_CLKS (ide_pio_timings[i].setup_time,
+ binfo->bi_busfreq);
+ ide_pio_clocks[i].active_time =
+ PCMCIA_MK_CLKS (ide_pio_timings[i].active_time,
+ binfo->bi_busfreq);
+ ide_pio_clocks[i].cycle_time =
+ PCMCIA_MK_CLKS (ide_pio_timings[i].cycle_time,
+ binfo->bi_busfreq);
+#if 0
+ printk ("PIO mode %d timings: %d/%d/%d => %d/%d/%d\n",
+ i,
+ ide_pio_clocks[i].setup_time,
+ ide_pio_clocks[i].active_time,
+ ide_pio_clocks[i].hold_time,
+ ide_pio_clocks[i].cycle_time,
+ ide_pio_timings[i].setup_time,
+ ide_pio_timings[i].active_time,
+ ide_pio_timings[i].hold_time,
+ ide_pio_timings[i].cycle_time);
+#endif
+ }
+ }
+
+ if (data_port >= MAX_HWIFS)
return;
- pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia));
+ base = pcmcia_base + ioport_dsc[data_port].base_off;
+
+# if (!defined(CONFIG_SPD823TS) && !defined(CONFIG_IVMS8))
+ /* SPD823TS and IVMS8 have a direct connection */
if (pcmp->pcmc_pipr & 0x18000000)
return; /* No card in slot */
+# endif /* CONFIG_SPD823TS, CONFIG_IVMS8 */
- base = (unsigned long) ioremap(PCMCIA_MEM_ADDR, 0x200);
+ for (i = 0; i < IDE_NR_PORTS; ++i) {
+ *p++ = base + ioport_dsc[data_port].reg_off[i];
+ }
- /* For the M-Systems ATA card, the first 8 registers map 1:1.
- * The following register, control/Altstatus, is located at 0x0e.
- * Following that, the irq offset, is not used, so we place it in
- * an unused location, 0x0a.
- */
- *p++ = base + 8;
- for (i = 1; i < 8; ++i)
- *p++ = base + i;
- *p++ = base + 0x0e; /* control/altstatus */
- *p = base + 0x0a; /* IRQ, not used */
- if (irq)
- *irq = PCMCIA_INTERRUPT;
+ if (irq) {
+ *irq = ioport_dsc[data_port].irq;
+ }
- /* Configure the interface for this interrupt.
- */
- pcmp->pcmc_pgcra = (mk_int_int_mask(PCMCIA_INTERRUPT) << 24) |
- (mk_int_int_mask(PCMCIA_INTERRUPT) << 16);
+ /* register routine to tune PIO mode */
+ ide_hwifs[data_port].tuneproc = m8xx_ide_tuneproc;
- /* Enable status change interrupt from slot A.
- */
- pcmp->pcmc_per = 0xff100000;
- pcmp->pcmc_pscr = ~0;
-#else
+ /* Enable Harddisk Interrupt,
+ * and make it edge sensitive
+ */
+ hw->ack_intr = (ide_ack_intr_t *)ide_interrupt_handler;
+ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel |=
+ (0x80000000 >> ioport_dsc[data_port].irq);
+
+#else /* ! CONFIG_BLK_DEV_MPC8xx_IDE */
/* Just a regular IDE drive on some I/O port.
*/
@@ -411,10 +512,84 @@
*p++ = base + 0x206;
if (irq != NULL)
*irq = 0;
-#endif
+#endif /* CONFIG_BLK_DEV_MPC8xx_IDE */
}
+#endif /* CONFIG_BLK_DEV_IDE || CONFIG_BLK_DEV_IDE_MODULE */
+
+
+/* -------------------------------------------------------------------- */
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
+
+/* PCMCIA Timing */
+#ifndef PCMCIA_SHT
+#define PCMCIA_SHT(t) ((t & 0x0F)<<16) /* Strobe Hold Time */
+#define PCMCIA_SST(t) ((t & 0x0F)<<12) /* Strobe Setup Time */
+#define PCMCIA_SL(t) ((t==32) ? 0 : ((t & 0x1F)<<7)) /* Strobe Length */
#endif
+
+/* Calculate PIO timings */
+static void
+m8xx_ide_tuneproc(ide_drive_t *drive, byte pio)
+{
+ volatile pcmconf8xx_t *pcmp;
+ ide_pio_data_t d;
+ ulong timing, mask, reg;
+
+ pio = ide_get_best_pio_mode(drive, pio, 4, &d);
+
+#if 1
+ printk("%s[%d] %s: best PIO mode: %d\n",
+ __FILE__,__LINE__,__FUNCTION__, pio);
+#endif
+ pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia));
+
+ mask = ~(PCMCIA_SHT(0xFF) | PCMCIA_SST(0xFF) | PCMCIA_SL(0xFF));
+
+ timing = PCMCIA_SHT(ide_pio_clocks[pio].hold_time )
+ | PCMCIA_SST(ide_pio_clocks[pio].setup_time )
+ | PCMCIA_SL (ide_pio_clocks[pio].active_time)
+ ;
+
+#if 1
+ printk ("Setting timing bits 0x%08lx in PCMCIA controller\n", timing);
+#endif
+ if ((reg = pcmp->pcmc_por0 & mask) != 0)
+ pcmp->pcmc_por0 = reg | timing;
+
+ if ((reg = pcmp->pcmc_por1 & mask) != 0)
+ pcmp->pcmc_por1 = reg | timing;
+
+ if ((reg = pcmp->pcmc_por2 & mask) != 0)
+ pcmp->pcmc_por2 = reg | timing;
+
+ if ((reg = pcmp->pcmc_por3 & mask) != 0)
+ pcmp->pcmc_por3 = reg | timing;
+
+ if ((reg = pcmp->pcmc_por4 & mask) != 0)
+ pcmp->pcmc_por4 = reg | timing;
+
+ if ((reg = pcmp->pcmc_por5 & mask) != 0)
+ pcmp->pcmc_por5 = reg | timing;
+
+ if ((reg = pcmp->pcmc_por6 & mask) != 0)
+ pcmp->pcmc_por6 = reg | timing;
+
+ if ((reg = pcmp->pcmc_por7 & mask) != 0)
+ pcmp->pcmc_por7 = reg | timing;
+}
+
+void ide_interrupt_handler (void *dev)
+{
+}
+
+#endif /* CONFIG_BLK_DEV_MPC8xx_IDE */
+#endif /* CONFIG_BLK_DEV_IDE || CONFIG_BLK_DEV_IDE_MODULE */
+
+/* -------------------------------------------------------------------- */
+
void __init
m8xx_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
@@ -490,7 +665,6 @@
ppc_ide_md.default_io_base = m8xx_ide_default_io_base;
ppc_ide_md.fix_driveid = ppc_generic_ide_fix_driveid;
ppc_ide_md.ide_init_hwif = m8xx_ide_init_hwif_ports;
- ppc_ide_md.ide_request_irq = m8xx_ide_request_irq;
ppc_ide_md.io_base = _IO_BASE;
#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)