ae0d7cbc99
This patch causes the kernel to mux the SERIRQ interrupt to the SERIRQ pin of the PIIX4 and to enable that interrupt. The kernel depends upon the interrupt when using the SuperIO UARTs (ttyS0 & ttyS1) but previously would not configure it, instead relying upon the bootloader having done so. If that is not the case then the typical result is that the system appears to hang once it reaches userland as no output is displayed on the UART. Signed-off-by: Paul Burton <paul.burton@imgtec.com> Reviewed-by: Markos Chandras <markos.chandras@imgtec.com> Signed-off-by: John Crispin <blogic@openwrt.org> Patchwork: http://patchwork.linux-mips.org/patch/6182/
140 lines
4.1 KiB
C
140 lines
4.1 KiB
C
#include <linux/init.h>
|
|
#include <linux/pci.h>
|
|
#include <asm/mips-boards/piix4.h>
|
|
|
|
/* PCI interrupt pins */
|
|
#define PCIA 1
|
|
#define PCIB 2
|
|
#define PCIC 3
|
|
#define PCID 4
|
|
|
|
/* This table is filled in by interrogating the PIIX4 chip */
|
|
static char pci_irq[5] = {
|
|
};
|
|
|
|
static char irq_tab[][5] __initdata = {
|
|
/* INTA INTB INTC INTD */
|
|
{0, 0, 0, 0, 0 }, /* 0: GT64120 PCI bridge */
|
|
{0, 0, 0, 0, 0 }, /* 1: Unused */
|
|
{0, 0, 0, 0, 0 }, /* 2: Unused */
|
|
{0, 0, 0, 0, 0 }, /* 3: Unused */
|
|
{0, 0, 0, 0, 0 }, /* 4: Unused */
|
|
{0, 0, 0, 0, 0 }, /* 5: Unused */
|
|
{0, 0, 0, 0, 0 }, /* 6: Unused */
|
|
{0, 0, 0, 0, 0 }, /* 7: Unused */
|
|
{0, 0, 0, 0, 0 }, /* 8: Unused */
|
|
{0, 0, 0, 0, 0 }, /* 9: Unused */
|
|
{0, 0, 0, 0, PCID }, /* 10: PIIX4 USB */
|
|
{0, PCIB, 0, 0, 0 }, /* 11: AMD 79C973 Ethernet */
|
|
{0, PCIC, 0, 0, 0 }, /* 12: Crystal 4281 Sound */
|
|
{0, 0, 0, 0, 0 }, /* 13: Unused */
|
|
{0, 0, 0, 0, 0 }, /* 14: Unused */
|
|
{0, 0, 0, 0, 0 }, /* 15: Unused */
|
|
{0, 0, 0, 0, 0 }, /* 16: Unused */
|
|
{0, 0, 0, 0, 0 }, /* 17: Bonito/SOC-it PCI Bridge*/
|
|
{0, PCIA, PCIB, PCIC, PCID }, /* 18: PCI Slot 1 */
|
|
{0, PCIB, PCIC, PCID, PCIA }, /* 19: PCI Slot 2 */
|
|
{0, PCIC, PCID, PCIA, PCIB }, /* 20: PCI Slot 3 */
|
|
{0, PCID, PCIA, PCIB, PCIC } /* 21: PCI Slot 4 */
|
|
};
|
|
|
|
int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
|
|
{
|
|
int virq;
|
|
virq = irq_tab[slot][pin];
|
|
return pci_irq[virq];
|
|
}
|
|
|
|
/* Do platform specific device initialization at pci_enable_device() time */
|
|
int pcibios_plat_dev_init(struct pci_dev *dev)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static void malta_piix_func0_fixup(struct pci_dev *pdev)
|
|
{
|
|
unsigned char reg_val;
|
|
u32 reg_val32;
|
|
/* PIIX PIRQC[A:D] irq mappings */
|
|
static int piixirqmap[PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_MAX] = {
|
|
0, 0, 0, 3,
|
|
4, 5, 6, 7,
|
|
0, 9, 10, 11,
|
|
12, 0, 14, 15
|
|
};
|
|
int i;
|
|
|
|
/* Interrogate PIIX4 to get PCI IRQ mapping */
|
|
for (i = 0; i <= 3; i++) {
|
|
pci_read_config_byte(pdev, PIIX4_FUNC0_PIRQRC+i, ®_val);
|
|
if (reg_val & PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_DISABLE)
|
|
pci_irq[PCIA+i] = 0; /* Disabled */
|
|
else
|
|
pci_irq[PCIA+i] = piixirqmap[reg_val &
|
|
PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_MASK];
|
|
}
|
|
|
|
/* Done by YAMON 2.00 onwards */
|
|
if (PCI_SLOT(pdev->devfn) == 10) {
|
|
/*
|
|
* Set top of main memory accessible by ISA or DMA
|
|
* devices to 16 Mb.
|
|
*/
|
|
pci_read_config_byte(pdev, PIIX4_FUNC0_TOM, ®_val);
|
|
pci_write_config_byte(pdev, PIIX4_FUNC0_TOM, reg_val |
|
|
PIIX4_FUNC0_TOM_TOP_OF_MEMORY_MASK);
|
|
}
|
|
|
|
/* Mux SERIRQ to its pin */
|
|
pci_read_config_dword(pdev, PIIX4_FUNC0_GENCFG, ®_val32);
|
|
pci_write_config_dword(pdev, PIIX4_FUNC0_GENCFG,
|
|
reg_val32 | PIIX4_FUNC0_GENCFG_SERIRQ);
|
|
|
|
/* Enable SERIRQ */
|
|
pci_read_config_byte(pdev, PIIX4_FUNC0_SERIRQC, ®_val);
|
|
reg_val |= PIIX4_FUNC0_SERIRQC_EN | PIIX4_FUNC0_SERIRQC_CONT;
|
|
pci_write_config_byte(pdev, PIIX4_FUNC0_SERIRQC, reg_val);
|
|
}
|
|
|
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
|
|
malta_piix_func0_fixup);
|
|
|
|
static void malta_piix_func1_fixup(struct pci_dev *pdev)
|
|
{
|
|
unsigned char reg_val;
|
|
|
|
/* Done by YAMON 2.02 onwards */
|
|
if (PCI_SLOT(pdev->devfn) == 10) {
|
|
/*
|
|
* IDE Decode enable.
|
|
*/
|
|
pci_read_config_byte(pdev, PIIX4_FUNC1_IDETIM_PRIMARY_HI,
|
|
®_val);
|
|
pci_write_config_byte(pdev, PIIX4_FUNC1_IDETIM_PRIMARY_HI,
|
|
reg_val|PIIX4_FUNC1_IDETIM_PRIMARY_HI_IDE_DECODE_EN);
|
|
pci_read_config_byte(pdev, PIIX4_FUNC1_IDETIM_SECONDARY_HI,
|
|
®_val);
|
|
pci_write_config_byte(pdev, PIIX4_FUNC1_IDETIM_SECONDARY_HI,
|
|
reg_val|PIIX4_FUNC1_IDETIM_SECONDARY_HI_IDE_DECODE_EN);
|
|
}
|
|
}
|
|
|
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB,
|
|
malta_piix_func1_fixup);
|
|
|
|
/* Enable PCI 2.1 compatibility in PIIX4 */
|
|
static void quirk_dlcsetup(struct pci_dev *dev)
|
|
{
|
|
u8 odlc, ndlc;
|
|
|
|
(void) pci_read_config_byte(dev, PIIX4_FUNC0_DLC, &odlc);
|
|
/* Enable passive releases and delayed transaction */
|
|
ndlc = odlc | PIIX4_FUNC0_DLC_USBPR_EN |
|
|
PIIX4_FUNC0_DLC_PASSIVE_RELEASE_EN |
|
|
PIIX4_FUNC0_DLC_DELAYED_TRANSACTION_EN;
|
|
(void) pci_write_config_byte(dev, PIIX4_FUNC0_DLC, ndlc);
|
|
}
|
|
|
|
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
|
|
quirk_dlcsetup);
|