patch-2.4.19 linux-2.4.19/arch/sparc64/kernel/pci_schizo.c

Next file: linux-2.4.19/arch/sparc64/kernel/power.c
Previous file: linux-2.4.19/arch/sparc64/kernel/pci_sabre.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.18/arch/sparc64/kernel/pci_schizo.c linux-2.4.19/arch/sparc64/kernel/pci_schizo.c
@@ -1,4 +1,4 @@
-/* $Id: pci_schizo.c,v 1.23 2001/11/14 13:17:56 davem Exp $
+/* $Id: pci_schizo.c,v 1.23.2.2 2002/03/11 07:55:24 davem Exp $
  * pci_schizo.c: SCHIZO specific PCI controller support.
  *
  * Copyright (C) 2001 David S. Miller (davem@redhat.com)
@@ -291,8 +291,8 @@
 /*0x0c*/0, 0, 0, 0,	/* PCI slot 3  Int A, B, C, D	*/
 /*0x10*/0, 0, 0, 0,	/* PCI slot 4  Int A, B, C, D	*/
 /*0x14*/0, 0, 0, 0,	/* PCI slot 5  Int A, B, C, D	*/
-/*0x18*/3,		/* SCSI				*/
-/*0x19*/3,		/* second SCSI			*/
+/*0x18*/4,		/* SCSI				*/
+/*0x19*/4,		/* second SCSI			*/
 /*0x1a*/0,		/* UNKNOWN			*/
 /*0x1b*/0,		/* UNKNOWN			*/
 /*0x1c*/8,		/* Parallel			*/
@@ -302,7 +302,7 @@
 /*0x20*/13,		/* Audio Record			*/
 /*0x21*/14,		/* Audio Playback		*/
 /*0x22*/12,		/* Serial			*/
-/*0x23*/2,		/* EBUS I2C 			*/
+/*0x23*/4,		/* EBUS I2C 			*/
 /*0x24*/10,		/* RTC Clock			*/
 /*0x25*/11,		/* Floppy			*/
 /*0x26*/0,		/* UNKNOWN			*/
@@ -344,7 +344,7 @@
 
 	ret = schizo_pil_table[ino];
 	if (ret == 0 && pdev == NULL) {
-		ret = 1;
+		ret = 4;
 	} else if (ret == 0) {
 		switch ((pdev->class >> 16) & 0xff) {
 		case PCI_BASE_CLASS_STORAGE:
@@ -367,7 +367,7 @@
 			break;
 
 		default:
-			ret = 1;
+			ret = 4;
 			break;
 		};
 	}
@@ -383,7 +383,7 @@
 	struct ino_bucket *bucket;
 	unsigned long imap, iclr, pbm_off;
 	unsigned long imap_off, iclr_off;
-	int pil, inofixup = 0;
+	int pil;
 
 	if (pbm == &p->pbm_A)
 		pbm_off = SCHIZO_PBM_A_REGS_OFF;
@@ -395,6 +395,10 @@
 
 	/* Now build the IRQ bucket. */
 	pil = schizo_ino_to_pil(pdev, ino);
+
+	if (PIL_RESERVED(pil))
+		BUG();
+
 	imap = p->controller_regs + pbm_off + imap_off;
 	imap += 4;
 
@@ -402,10 +406,13 @@
 	iclr = p->controller_regs + pbm_off + iclr_off;
 	iclr += 4;
 
-	if (ino < 0x18)
-		inofixup = ino & 0x03;
-
-	bucket = __bucket(build_irq(pil, inofixup, iclr, imap));
+	/* On Schizo, no inofixup occurs.  This is because each
+	 * INO has it's own IMAP register.  On Psycho and Sabre
+	 * there is only one IMAP register for each PCI slot even
+	 * though four different INOs can be generated by each
+	 * PCI slot.
+	 */
+	bucket = __bucket(build_irq(pil, 0, iclr, imap));
 	bucket->flags |= IBF_PCI;
 
 	return __irq(bucket);
@@ -1078,15 +1085,22 @@
 
 #define SCHIZO_PCIA_CTRL	(SCHIZO_PBM_A_REGS_OFF + 0x2000UL)
 #define SCHIZO_PCIB_CTRL	(SCHIZO_PBM_B_REGS_OFF + 0x2000UL)
-#define SCHIZO_PCICTRL_BUNUS	(1UL << 63UL)
+#define SCHIZO_PCICTRL_BUS_UNUS	(1UL << 63UL)
 #define SCHIZO_PCICTRL_ESLCK	(1UL << 51UL)
+#define SCHIZO_PCICTRL_ERRSLOT	(7UL << 48UL)
 #define SCHIZO_PCICTRL_TTO_ERR	(1UL << 38UL)
 #define SCHIZO_PCICTRL_RTRY_ERR	(1UL << 37UL)
 #define SCHIZO_PCICTRL_DTO_ERR	(1UL << 36UL)
 #define SCHIZO_PCICTRL_SBH_ERR	(1UL << 35UL)
 #define SCHIZO_PCICTRL_SERR	(1UL << 34UL)
+#define SCHIZO_PCICTRL_PCISPD	(1UL << 33UL)
+#define SCHIZO_PCICTRL_PTO	(3UL << 24UL)
+#define SCHIZO_PCICTRL_DTO_INT	(1UL << 19UL)
 #define SCHIZO_PCICTRL_SBH_INT	(1UL << 18UL)
 #define SCHIZO_PCICTRL_EEN	(1UL << 17UL)
+#define SCHIZO_PCICTRL_PARK	(1UL << 16UL)
+#define SCHIZO_PCICTRL_PCIRST	(1UL <<  8UL)
+#define SCHIZO_PCICTRL_ARB	(0x3fUL << 0UL)
 
 static void __init schizo_register_error_handlers(struct pci_controller_info *p)
 {
@@ -1163,7 +1177,7 @@
 	 * bits for each PBM.
 	 */
 	tmp = schizo_read(base + SCHIZO_PCIA_CTRL);
-	tmp |= (SCHIZO_PCICTRL_BUNUS |
+	tmp |= (SCHIZO_PCICTRL_BUS_UNUS |
 		SCHIZO_PCICTRL_ESLCK |
 		SCHIZO_PCICTRL_TTO_ERR |
 		SCHIZO_PCICTRL_RTRY_ERR |
@@ -1175,7 +1189,7 @@
 	schizo_write(base + SCHIZO_PCIA_CTRL, tmp);
 
 	tmp = schizo_read(base + SCHIZO_PCIB_CTRL);
-	tmp |= (SCHIZO_PCICTRL_BUNUS |
+	tmp |= (SCHIZO_PCICTRL_BUS_UNUS |
 		SCHIZO_PCICTRL_ESLCK |
 		SCHIZO_PCICTRL_TTO_ERR |
 		SCHIZO_PCICTRL_RTRY_ERR |
@@ -1412,7 +1426,14 @@
 	int where, size, is_64bit;
 
 	res = &pdev->resource[resource];
-	where = PCI_BASE_ADDRESS_0 + (resource * 4);
+	if (resource < 6) {
+		where = PCI_BASE_ADDRESS_0 + (resource * 4);
+	} else if (resource == PCI_ROM_RESOURCE) {
+		where = pdev->rom_base_reg;
+	} else {
+		/* Somebody might have asked allocation of a non-standard resource */
+		return;
+	}
 
 	is_64bit = 0;
 	if (res->flags & IORESOURCE_IO)
@@ -1428,6 +1449,10 @@
 	pci_read_config_dword(pdev, where, &reg);
 	reg = ((reg & size) |
 	       (((u32)(res->start - root->start)) & ~size));
+	if (resource == PCI_ROM_RESOURCE) {
+		reg |= PCI_ROM_ADDRESS_ENABLE;
+		res->flags |= PCI_ROM_ADDRESS_ENABLE;
+	}
 	pci_write_config_dword(pdev, where, reg);
 
 	/* This knows that the upper 32-bits of the address
@@ -1458,24 +1483,12 @@
 #define SCHIZO_PCI_B_IO_MATCH		0x00070UL
 #define SCHIZO_PCI_B_IO_MASK		0x00078UL
 
-/* VAL must be non-zero. */
-static unsigned long strip_to_lowest_bit_set(unsigned long val)
-{
-	unsigned long tmp;
-
-	tmp = 1UL;
-	while (!(tmp & val))
-		tmp <<= 1UL;
-
-	return tmp;
-}
-
 static void schizo_determine_mem_io_space(struct pci_pbm_info *pbm,
 					  int is_pbm_a, unsigned long reg_base)
 {
 	u64 mem_match, mem_mask;
 	u64 io_match;
-	u64 long a, b;
+	u64 a;
 
 	if (is_pbm_a) {
 		mem_match = reg_base + SCHIZO_PCI_A_MEM_MATCH;
@@ -1487,11 +1500,12 @@
 	mem_mask = mem_match + 0x8UL;
 
 	a = schizo_read(mem_match) & ~0x8000000000000000UL;
-	b = strip_to_lowest_bit_set(schizo_read(mem_mask));
 
-	/* It should be 2GB in size. */
+	/* It should be 2GB in size but the decode is set for the full
+	 * 4GB so we have to add the 2G by hand.
+	 */
 	pbm->mem_space.start = a;
-	pbm->mem_space.end = a + (b - 1UL);
+	pbm->mem_space.end = a + 0x80000000;
 	pbm->mem_space.flags = IORESOURCE_MEM;
 
 	/* This 32MB area is divided into two pieces.  The first
@@ -1738,6 +1752,22 @@
 	schizo_pbm_strbuf_init(p, pbm, is_pbm_a);
 }
 
+#define SCHIZO_PCIA_IRQ_RETRY	(SCHIZO_PBM_A_REGS_OFF + 0x1a00UL)
+#define SCHIZO_PCIB_IRQ_RETRY	(SCHIZO_PBM_B_REGS_OFF + 0x1a00UL)
+#define  SCHIZO_IRQ_RETRY_INF	 0xffUL
+
+#define SCHIZO_PCIA_DIAG	(SCHIZO_PBM_A_REGS_OFF + 0x2020UL)
+#define SCHIZO_PCIB_DIAG	(SCHIZO_PBM_B_REGS_OFF + 0x2020UL)
+#define  SCHIZO_PCIDIAG_D_BADECC	(1UL << 10UL) /* Disable BAD ECC errors */
+#define  SCHIZO_PCIDIAG_D_BYPASS	(1UL <<  9UL) /* Disable MMU bypass mode */
+#define  SCHIZO_PCIDIAG_D_TTO		(1UL <<  8UL) /* Disable TTO errors */
+#define  SCHIZO_PCIDIAG_D_RTRYARB	(1UL <<  7UL) /* Disable retry arbitration */
+#define  SCHIZO_PCIDIAG_D_RETRY		(1UL <<  6UL) /* Disable retry limit */
+#define  SCHIZO_PCIDIAG_D_INTSYNC	(1UL <<  5UL) /* Disable interrupt/DMA synch */
+#define  SCHIZO_PCIDIAG_I_DMA_PARITY	(1UL <<  3UL) /* Invert DMA parity */
+#define  SCHIZO_PCIDIAG_I_PIOD_PARITY	(1UL <<  2UL) /* Invert PIO data parity */
+#define  SCHIZO_PCIDIAG_I_PIOA_PARITY	(1UL <<  1U)L /* Invert PIO address parity */
+
 static void schizo_controller_hwinit(struct pci_controller_info *p)
 {
 	unsigned long pbm_a_base, pbm_b_base;
@@ -1747,17 +1777,37 @@
 	pbm_b_base = p->controller_regs + SCHIZO_PBM_B_REGS_OFF;
 
 	/* Set IRQ retry to infinity. */
-	schizo_write(pbm_a_base + 0x1a00UL, 0xff);
-	schizo_write(pbm_b_base + 0x1a00UL, 0xff);
+	schizo_write(p->controller_regs + SCHIZO_PCIA_IRQ_RETRY,
+		     SCHIZO_IRQ_RETRY_INF);
+	schizo_write(p->controller_regs + SCHIZO_PCIB_IRQ_RETRY,
+		     SCHIZO_IRQ_RETRY_INF);
+
+	/* Enable arbiter for all PCI slots.  Also, disable PCI interval
+	 * timer so that DTO (Discard TimeOuts) are not reported because
+	 * some Schizo revisions report them erroneously.
+	 */
 
-	/* Enable arbiter for all PCI slots. */
-	tmp = schizo_read(pbm_a_base + 0x2000UL);
-	tmp |= 0x3fUL;
-	schizo_write(pbm_a_base + 0x2000UL, tmp);
-
-	tmp = schizo_read(pbm_b_base + 0x2000UL);
-	tmp |= 0x3fUL;
-	schizo_write(pbm_b_base + 0x2000UL, tmp);
+	tmp = schizo_read(p->controller_regs + SCHIZO_PCIA_CTRL);
+	tmp |= SCHIZO_PCICTRL_ARB;
+	tmp &= ~SCHIZO_PCICTRL_PTO;
+	schizo_write(p->controller_regs + SCHIZO_PCIA_CTRL, tmp);
+
+	tmp = schizo_read(p->controller_regs + SCHIZO_PCIB_CTRL);
+	tmp |= SCHIZO_PCICTRL_ARB;
+	tmp &= ~SCHIZO_PCICTRL_PTO;
+	schizo_write(p->controller_regs + SCHIZO_PCIB_CTRL, tmp);
+
+	/* Disable TTO error reporting (won't happen anyway since we
+	 * disabled the PCI interval timer above) and retry arbitration
+	 * (can cause hangs in some Schizo revisions).
+	 */
+	tmp = schizo_read(p->controller_regs + SCHIZO_PCIA_DIAG);
+	tmp |= (SCHIZO_PCIDIAG_D_TTO | SCHIZO_PCIDIAG_D_RTRYARB);
+	schizo_write(p->controller_regs + SCHIZO_PCIA_DIAG, tmp);
+
+	tmp = schizo_read(p->controller_regs + SCHIZO_PCIB_DIAG);
+	tmp |= (SCHIZO_PCIDIAG_D_TTO | SCHIZO_PCIDIAG_D_RTRYARB);
+	schizo_write(p->controller_regs + SCHIZO_PCIB_DIAG, tmp);
 }
 
 void __init schizo_init(int node, char *model_name)

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)