Commit bf4a5a18 authored by Tom Rini's avatar Tom Rini Committed by Linus Torvalds

[PATCH] ppc32: Add support for Sandpoint X2

Adrian Cox has modified the Sandpoint code to once again work on the older
X2 version of the board.  The older version has a number of are on the
older version.
Signed-off-by: default avatarAdrian Cox <adrian@humboldt.co.uk>
Signed-off-by: default avatarTom Rini <trini@kernel.crashing.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 934a5fc9
......@@ -60,11 +60,6 @@
* of the amount of memory in the system. Once a method of determining
* what version of DINK initializes the system for us, if applicable, is
* found, we can hopefully stop hardcoding 32MB of RAM.
*
* It is important to note that this code only supports the Sandpoint X3
* (all flavors) platform, and it does not support the X2 anymore. Code
* that at one time worked on the X2 can be found at:
* ftp://source.mvista.com/pub/linuxppc/obsolete/sandpoint/
*/
#include <linux/config.h>
......@@ -107,9 +102,13 @@
#include "sandpoint.h"
/* Set non-zero if an X2 Sandpoint detected. */
static int sandpoint_is_x2;
unsigned char __res[sizeof(bd_t)];
static void sandpoint_halt(void);
static void sandpoint_probe_type(void);
/*
* Define all of the IRQ senses and polarities. Taken from the
......@@ -129,7 +128,7 @@ static u_char sandpoint_openpic_initsenses[] __initdata = {
* Motorola SPS Sandpoint interrupt routing.
*/
static inline int
sandpoint_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
x3_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
{
static char pci_irq_table[][4] =
/*
......@@ -149,6 +148,27 @@ sandpoint_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
return PCI_IRQ_TABLE_LOOKUP;
}
static inline int
x2_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
{
static char pci_irq_table[][4] =
/*
* PCI IDSEL/INTPIN->INTLINE
* A B C D
*/
{
{ 18, 0, 0, 0 }, /* IDSEL 11 - i8259 on Windbond */
{ 0, 0, 0, 0 }, /* IDSEL 12 - unused */
{ 16, 17, 18, 19 }, /* IDSEL 13 - PCI slot 1 */
{ 17, 18, 19, 16 }, /* IDSEL 14 - PCI slot 2 */
{ 18, 19, 16, 17 }, /* IDSEL 15 - PCI slot 3 */
{ 19, 16, 17, 18 }, /* IDSEL 16 - PCI slot 4 */
};
const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4;
return PCI_IRQ_TABLE_LOOKUP;
}
static void __init
sandpoint_setup_winbond_83553(struct pci_controller *hose)
{
......@@ -216,6 +236,18 @@ sandpoint_setup_winbond_83553(struct pci_controller *hose)
return;
}
/* On the sandpoint X2, we must avoid sending configuration cycles to
* device #12 (IDSEL addr = AD12).
*/
static int
x2_exclude_device(u_char bus, u_char devfn)
{
if ((bus == 0) && (PCI_SLOT(devfn) == SANDPOINT_HOST_BRIDGE_IDSEL))
return PCIBIOS_DEVICE_NOT_FOUND;
else
return PCIBIOS_SUCCESSFUL;
}
static void __init
sandpoint_find_bridges(void)
{
......@@ -241,7 +273,11 @@ sandpoint_find_bridges(void)
ppc_md.pcibios_fixup = NULL;
ppc_md.pcibios_fixup_bus = NULL;
ppc_md.pci_swizzle = common_swizzle;
ppc_md.pci_map_irq = sandpoint_map_irq;
if (sandpoint_is_x2) {
ppc_md.pci_map_irq = x2_map_irq;
ppc_md.pci_exclude_device = x2_exclude_device;
} else
ppc_md.pci_map_irq = x3_map_irq;
}
else {
if (ppc_md.progress)
......@@ -255,6 +291,11 @@ sandpoint_find_bridges(void)
static void __init
sandpoint_setup_arch(void)
{
/* Probe for Sandpoint model */
sandpoint_probe_type();
if (sandpoint_is_x2)
epic_serial_mode = 0;
loops_per_jiffy = 100000000 / HZ;
#ifdef CONFIG_BLK_DEV_INITRD
......@@ -318,14 +359,49 @@ sandpoint_setup_arch(void)
SANDPOINT_87308_CFG_OUTB(0x30, 0x01); \
}
/*
* To probe the Sandpoint type, we need to check for a connection between GPIO
* pins 6 and 7 on the NS87308 SuperIO.
*/
static void __init sandpoint_probe_type(void)
{
u8 x;
/* First, ensure that the GPIO pins are enabled. */
SANDPOINT_87308_SELECT_DEV(0x07); /* Select GPIO logical device */
SANDPOINT_87308_CFG_OUTB(0x60, 0x07); /* Base address 0x700 */
SANDPOINT_87308_CFG_OUTB(0x61, 0x00);
SANDPOINT_87308_CFG_OUTB(0x30, 0x01); /* Enable */
/* Now, set pin 7 to output and pin 6 to input. */
outb((inb(0x701) | 0x80) & 0xbf, 0x701);
/* Set push-pull output */
outb(inb(0x702) | 0x80, 0x702);
/* Set pull-up on input */
outb(inb(0x703) | 0x40, 0x703);
/* Set output high and check */
x = inb(0x700);
outb(x | 0x80, 0x700);
x = inb(0x700);
sandpoint_is_x2 = ! (x & 0x40);
if (ppc_md.progress && sandpoint_is_x2)
ppc_md.progress("High output says X2", 0);
/* Set output low and check */
outb(x & 0x7f, 0x700);
sandpoint_is_x2 |= inb(0x700) & 0x40;
if (ppc_md.progress && sandpoint_is_x2)
ppc_md.progress("Low output says X2", 0);
if (ppc_md.progress && ! sandpoint_is_x2)
ppc_md.progress("Sandpoint is X3", 0);
}
/*
* Fix IDE interrupts.
*/
static int __init
sandpoint_fix_winbond_83553(void)
{
/* Make all 8259 interrupt level sensitive */
outb(0xf8, 0x4d0);
/* Make some 8259 interrupt level sensitive */
outb(0xe0, 0x4d0);
outb(0xde, 0x4d1);
return 0;
......@@ -398,7 +474,7 @@ sandpoint_init_IRQ(void)
OpenPIC_NumInitSenses = sizeof(sandpoint_openpic_initsenses);
mpc10x_set_openpic();
openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
openpic_hookup_cascade(sandpoint_is_x2 ? 17 : NUM_8259_INTERRUPTS, "82c59 cascade",
i8259_irq);
/*
......
......@@ -43,7 +43,7 @@
#ifdef CONFIG_MPC10X_OPENPIC
#ifdef CONFIG_EPIC_SERIAL_MODE
#define EPIC_IRQ_BASE 16
#define EPIC_IRQ_BASE (epic_serial_mode ? 16 : 5)
#else
#define EPIC_IRQ_BASE 5
#endif
......@@ -69,20 +69,16 @@ static struct ocp_def mpc10x_i2c_ocp = {
.vendor = OCP_VENDOR_MOTOROLA,
.function = OCP_FUNC_IIC,
.index = 0,
.irq = MPC10X_I2C_IRQ,
.additions = &mpc10x_i2c_data
};
static struct ocp_def mpc10x_dma_ocp[2] = {
{ .vendor = OCP_VENDOR_MOTOROLA,
.function = OCP_FUNC_DMA,
.index = 0,
.irq = MPC10X_DMA0_IRQ
},
.index = 0 },
{ .vendor = OCP_VENDOR_MOTOROLA,
.function = OCP_FUNC_DMA,
.index = 1,
.irq = MPC10X_DMA1_IRQ }
.index = 1 }
};
/* Set resources to match bridge memory map */
......@@ -292,12 +288,15 @@ mpc10x_bridge_init(struct pci_controller *hose,
MPC10X_EUMB_EPIC_SIZE);
#endif
mpc10x_i2c_ocp.paddr = phys_eumb_base + MPC10X_EUMB_I2C_OFFSET;
mpc10x_i2c_ocp.irq = MPC10X_I2C_IRQ;
ocp_add_one_device(&mpc10x_i2c_ocp);
mpc10x_dma_ocp[0].paddr = phys_eumb_base +
MPC10X_EUMB_DMA_OFFSET + 0x100;
mpc10x_dma_ocp[0].irq = MPC10X_DMA0_IRQ;
ocp_add_one_device(&mpc10x_dma_ocp[0]);
mpc10x_dma_ocp[1].paddr = phys_eumb_base +
MPC10X_EUMB_DMA_OFFSET + 0x200;
mpc10x_dma_ocp[1].irq = MPC10X_DMA1_IRQ;
ocp_add_one_device(&mpc10x_dma_ocp[1]);
}
......
......@@ -261,6 +261,9 @@ static void openpic_safe_writefield_IPI(volatile u_int *addr, u_int mask, u_int
#endif /* CONFIG_SMP */
#ifdef CONFIG_EPIC_SERIAL_MODE
/* On platforms that may use EPIC serial mode, the default is enabled. */
int epic_serial_mode = 1;
static void __init openpic_eicr_set_clk(u_int clkval)
{
openpic_writefield(&OpenPIC->Global.Global_Configuration1,
......@@ -415,8 +418,10 @@ void __init openpic_init(int offset)
openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
openpic_disable_8259_pass_through();
#ifdef CONFIG_EPIC_SERIAL_MODE
openpic_eicr_set_clk(7); /* Slowest value until we know better */
openpic_enable_sie();
if (epic_serial_mode) {
openpic_eicr_set_clk(7); /* Slowest value until we know better */
openpic_enable_sie();
}
#endif
openpic_set_priority(0);
......
......@@ -36,6 +36,7 @@ extern struct hw_interrupt_type open_pic_ipi;
extern u_int OpenPIC_NumInitSenses;
extern u_char *OpenPIC_InitSenses;
extern void* OpenPIC_Addr;
extern int epic_serial_mode;
/* Exported functions */
extern void openpic_set_sources(int first_irq, int num_irqs, void *isr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment