Commit 62d06165 authored by Paul Mackerras's avatar Paul Mackerras

PPC32: Improved support for PReP platforms, forward-ported from 2.4.

parent a0e3935f
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/open_pic.h> #include <asm/open_pic.h>
extern void (*setup_ibm_pci)(char *irq_lo, char *irq_hi);
/* Which PCI interrupt line does a given device [slot] use? */ /* Which PCI interrupt line does a given device [slot] use? */
/* Note: This really should be two dimensional based in slot/pin used */ /* Note: This really should be two dimensional based in slot/pin used */
...@@ -612,6 +613,7 @@ static unsigned char prep_pci_intpins[4][4] __prepdata = ...@@ -612,6 +613,7 @@ static unsigned char prep_pci_intpins[4][4] __prepdata =
#define ELCRM_INT7_LVL 0x80 #define ELCRM_INT7_LVL 0x80
#define ELCRM_INT5_LVL 0x20 #define ELCRM_INT5_LVL 0x20
#if 0
/* /*
* PCI config space access. * PCI config space access.
*/ */
...@@ -686,6 +688,7 @@ static struct pci_ops prep_pci_ops = ...@@ -686,6 +688,7 @@ static struct pci_ops prep_pci_ops =
prep_read_config, prep_read_config,
prep_write_config prep_write_config
}; };
#endif
#define MOTOROLA_CPUTYPE_REG 0x800 #define MOTOROLA_CPUTYPE_REG 0x800
#define MOTOROLA_BASETYPE_REG 0x803 #define MOTOROLA_BASETYPE_REG 0x803
...@@ -695,7 +698,7 @@ static struct pci_ops prep_pci_ops = ...@@ -695,7 +698,7 @@ static struct pci_ops prep_pci_ops =
static u_char prep_openpic_initsenses[] __initdata = { static u_char prep_openpic_initsenses[] __initdata = {
(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* MVME2600_INT_SIO */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* MVME2600_INT_SIO */
(IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_FALCON_ECC_ERR */ (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_FALCN_ECC_ERR */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_ETHERNET */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_ETHERNET */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_SCSI */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_SCSI */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_GRAPHICS */ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_GRAPHICS */
...@@ -834,32 +837,51 @@ struct mot_info { ...@@ -834,32 +837,51 @@ struct mot_info {
void __init void __init
ibm_prep_init(void) ibm_prep_init(void)
{ {
u32 addr;
#ifdef CONFIG_PREP_RESIDUAL #ifdef CONFIG_PREP_RESIDUAL
u32 addr, real_addr, len;
PPC_DEVICE *mpic; PPC_DEVICE *mpic;
#endif PnP_TAG_PACKET *pkt;
/* Use the PReP residual data to determine if an OpenPIC is
* present. If so, get the large vendor packet which will
* tell us the base address and length in memory.
* If we are successful, ioremap the memory area and set
* OpenPIC_Addr (this indicates that the OpenPIC was found).
*/
mpic = residual_find_device(-1, NULL, SystemPeripheral,
ProgrammableInterruptController, MPIC, 0);
if (!mpic)
return;
pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
mpic->AllocatedOffset, 9, 0);
if (!pkt)
return;
#define p pkt->L4_Pack.L4_Data.L4_PPCPack
if (!((p.PPCData[0] == 2) && (p.PPCData[1] == 32)))
return; /* not a 32-bit memory address */
real_addr = ld_le32((unsigned int *) (p.PPCData + 4));
if (real_addr == 0xffffffff)
return;
if (inb(0x0852) == 0xd5) { /* Adjust address to be as seen by CPU */
/* This is for the 43p-140 */ addr = real_addr + PREP_ISA_MEM_BASE;
early_read_config_dword(0, 0, PCI_DEVFN(13, 0),
PCI_BASE_ADDRESS_0, &addr); len = ld_le32((unsigned int *) (p.PPCData + 12));
if (addr != 0xffffffff if (!len)
&& !(addr & PCI_BASE_ADDRESS_SPACE_IO) return;
&& (addr &= PCI_BASE_ADDRESS_MEM_MASK) != 0) { #undef p
addr += PREP_ISA_MEM_BASE; OpenPIC_Addr = ioremap(addr, len);
OpenPIC_Addr = ioremap(addr, 0x40000);
ppc_md.get_irq = openpic_get_irq; ppc_md.get_irq = openpic_get_irq;
OpenPIC_InitSenses = prep_openpic_initsenses; OpenPIC_InitSenses = prep_openpic_initsenses;
OpenPIC_NumInitSenses = sizeof(prep_openpic_initsenses); OpenPIC_NumInitSenses = sizeof(prep_openpic_initsenses);
}
}
#ifdef CONFIG_PREP_RESIDUAL printk(KERN_INFO "MPIC at 0x%08x (0x%08x), length 0x%08x "
mpic = residual_find_device(-1, NULL, SystemPeripheral, "mapped to 0x%p\n", addr, real_addr, len, OpenPIC_Addr);
ProgrammableInterruptController, MPIC, 0);
if (mpic != NULL)
printk("mpic = %p\n", mpic);
#endif #endif
} }
...@@ -879,6 +901,47 @@ ibm43p_pci_map_non0(struct pci_dev *dev) ...@@ -879,6 +901,47 @@ ibm43p_pci_map_non0(struct pci_dev *dev)
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
} }
void __init
prep_sandalfoot_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
{
Motherboard_map_name = "IBM 6015/7020 (Sandalfoot/Sandalbow)";
Motherboard_map = ibm6015_pci_IRQ_map;
Motherboard_routes = ibm6015_pci_IRQ_routes;
*irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
*irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */
}
void __init
prep_thinkpad_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
{
Motherboard_map_name = "IBM Thinkpad 850/860";
Motherboard_map = Nobis_pci_IRQ_map;
Motherboard_routes = Nobis_pci_IRQ_routes;
*irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
*irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */
}
void __init
prep_carolina_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
{
Motherboard_map_name = "IBM 7248, PowerSeries 830/850 (Carolina)";
Motherboard_map = ibm8xx_pci_IRQ_map;
Motherboard_routes = ibm8xx_pci_IRQ_routes;
*irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
*irq_edge_mask_hi = 0xA4; /* irq's 10, 13, 15 level-triggered */
}
void __init
prep_tiger1_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
{
Motherboard_map_name = "IBM 43P-140 (Tiger1)";
Motherboard_map = ibm43p_pci_IRQ_map;
Motherboard_routes = ibm43p_pci_IRQ_routes;
Motherboard_non0 = ibm43p_pci_map_non0;
*irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
*irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */
}
void __init void __init
prep_route_pci_interrupts(void) prep_route_pci_interrupts(void)
{ {
...@@ -948,52 +1011,12 @@ prep_route_pci_interrupts(void) ...@@ -948,52 +1011,12 @@ prep_route_pci_interrupts(void)
outb( (irq_mode >> 8) & 0xff, 0x4d1 ); outb( (irq_mode >> 8) & 0xff, 0x4d1 );
} }
} else if ( _prep_type == _PREP_IBM ) { } else if ( _prep_type == _PREP_IBM ) {
unsigned char planar_id = inb(0x0852);
unsigned char irq_edge_mask_lo, irq_edge_mask_hi; unsigned char irq_edge_mask_lo, irq_edge_mask_hi;
printk("IBM ID: %08x\n", planar_id); setup_ibm_pci(&irq_edge_mask_lo, &irq_edge_mask_hi);
switch(planar_id) {
case 0xff:
Motherboard_map_name = "IBM Thinkpad 850/860";
Motherboard_map = Nobis_pci_IRQ_map;
Motherboard_routes = Nobis_pci_IRQ_routes;
irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */
break;
case 0xfc:
Motherboard_map_name = "IBM 6015/7020 (Sandalfoot/Sandalbow)";
Motherboard_map = ibm6015_pci_IRQ_map;
Motherboard_routes = ibm6015_pci_IRQ_routes;
irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */
break;
case 0xd5:
Motherboard_map_name = "IBM 43P-140 (Tiger1)";
Motherboard_map = ibm43p_pci_IRQ_map;
Motherboard_routes = ibm43p_pci_IRQ_routes;
Motherboard_non0 = ibm43p_pci_map_non0;
irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */
break;
default:
printk(KERN_ERR "Unknown IBM motherboard! Defaulting to Carolina.\n");
case 0xf0: /* PowerSeries 830/850 */
case 0xf1: /* PowerSeries 830/850 */
case 0xf2: /* PowerSeries 830/850 */
case 0xf4: /* 7248-43P */
case 0xf5: /* 7248-43P */
case 0xf6: /* 7248-43P */
case 0xf7: /* 7248-43P (missing from Carolina Tech Spec) */
Motherboard_map_name = "IBM PS830/PS850/7248 (Carolina)";
Motherboard_map = ibm8xx_pci_IRQ_map;
Motherboard_routes = ibm8xx_pci_IRQ_routes;
irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
irq_edge_mask_hi = 0xA4; /* irq's 10, 13, 15 level-triggered */
break;
}
outb(inb(0x04d0)|irq_edge_mask_lo, 0x04d0); /* primary 8259 */ outb(inb(0x04d0)|irq_edge_mask_lo, 0x4d0); /* primary 8259 */
outb(inb(0x04d1)|irq_edge_mask_hi, 0x04d1); /* cascaded 8259 */ outb(inb(0x04d1)|irq_edge_mask_hi, 0x4d1); /* cascaded 8259 */
} else { } else {
printk("No known machine pci routing!\n"); printk("No known machine pci routing!\n");
return; return;
...@@ -1151,7 +1174,6 @@ prep_pcibios_fixup(void) ...@@ -1151,7 +1174,6 @@ prep_pcibios_fixup(void)
struct pci_dev *dev; struct pci_dev *dev;
extern unsigned char *Motherboard_map; extern unsigned char *Motherboard_map;
extern unsigned char *Motherboard_routes; extern unsigned char *Motherboard_routes;
unsigned char i;
prep_route_pci_interrupts(); prep_route_pci_interrupts();
...@@ -1182,38 +1204,6 @@ prep_pcibios_fixup(void) ...@@ -1182,38 +1204,6 @@ prep_pcibios_fixup(void)
*/ */
unsigned char d = PCI_SLOT(dev->devfn); unsigned char d = PCI_SLOT(dev->devfn);
dev->irq = Motherboard_routes[Motherboard_map[d]]; dev->irq = Motherboard_routes[Motherboard_map[d]];
for ( i = 0 ; i <= 5 ; i++ ) {
/*
* Relocate PCI I/O resources if necessary so the
* standard 256MB BAT covers them.
*/
if ( (pci_resource_flags(dev, i) & IORESOURCE_IO) &&
(dev->resource[i].start > 0x10000000)) {
printk("Relocating PCI address %lx -> %lx\n",
dev->resource[i].start,
(dev->resource[i].start &
0x00FFFFFF)| 0x01000000);
dev->resource[i].start =
(dev->resource[i].start & 0x00FFFFFF)
| 0x01000000;
pci_write_config_dword(dev,
PCI_BASE_ADDRESS_0 + (i*0x4),
dev->resource[i].start);
dev->resource[i].end =
(dev->resource[i].end & 0x00FFFFFF)
| 0x01000000;
}
}
#if 0
/*
* If we have residual data and if it knows about this
* device ask it what the irq is.
* -- Cort
*/
ppcd = residual_find_device_id( ~0L, dev->device,
-1,-1,-1, 0);
#endif
} }
} }
...@@ -1270,9 +1260,8 @@ prep_find_bridges(void) ...@@ -1270,9 +1260,8 @@ prep_find_bridges(void)
prep_init_resource(&hose->io_resource, 0, 0x007fffff, IORESOURCE_IO); prep_init_resource(&hose->io_resource, 0, 0x007fffff, IORESOURCE_IO);
prep_init_resource(&hose->mem_resources[0], 0xc0000000, 0xfeffffff, prep_init_resource(&hose->mem_resources[0], 0xc0000000, 0xfeffffff,
IORESOURCE_MEM); IORESOURCE_MEM);
/* XXX why can't we use the indirect config space access method? */ setup_indirect_pci(hose, PREP_ISA_IO_BASE + 0xcf8,
hose->cfg_data = ioremap(PREP_ISA_IO_BASE + 0x800000, 0x800000); PREP_ISA_IO_BASE + 0xcfc);
hose->ops = &prep_pci_ops;
printk("PReP architecture\n"); printk("PReP architecture\n");
#ifdef CONFIG_PREP_RESIDUAL #ifdef CONFIG_PREP_RESIDUAL
......
...@@ -80,6 +80,12 @@ extern char saved_command_line[]; ...@@ -80,6 +80,12 @@ extern char saved_command_line[];
int _prep_type; int _prep_type;
extern void prep_sandalfoot_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
extern void prep_thinkpad_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
extern void prep_carolina_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
extern void prep_tiger1_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
#define cached_21 (((char *)(ppc_cached_irq_mask))[3]) #define cached_21 (((char *)(ppc_cached_irq_mask))[3])
#define cached_A1 (((char *)(ppc_cached_irq_mask))[2]) #define cached_A1 (((char *)(ppc_cached_irq_mask))[2])
...@@ -100,39 +106,305 @@ EXPORT_SYMBOL(ppc_cs4232_dma); ...@@ -100,39 +106,305 @@ EXPORT_SYMBOL(ppc_cs4232_dma);
EXPORT_SYMBOL(ppc_cs4232_dma2); EXPORT_SYMBOL(ppc_cs4232_dma2);
#endif #endif
static int __prep /* useful ISA ports */
prep_show_cpuinfo(struct seq_file *m) #define PREP_SYSCTL 0x81c
/* present in the IBM reference design; possibly identical in Mot boxes: */
#define PREP_IBM_SIMM_ID 0x803 /* SIMM size: 32 or 8 MiB */
#define PREP_IBM_SIMM_PRESENCE 0x804
#define PREP_IBM_EQUIPMENT 0x80c
#define PREP_IBM_L2INFO 0x80d
#define PREP_IBM_PM1 0x82a /* power management register 1 */
#define PREP_IBM_PLANAR 0x852 /* planar ID - identifies the motherboard */
#define PREP_IBM_DISP 0x8c0 /* 4-digit LED display */
/* Equipment Present Register masks: */
#define PREP_IBM_EQUIPMENT_RESERVED 0x80
#define PREP_IBM_EQUIPMENT_SCSIFUSE 0x40
#define PREP_IBM_EQUIPMENT_L2_COPYBACK 0x08
#define PREP_IBM_EQUIPMENT_L2_256 0x04
#define PREP_IBM_EQUIPMENT_CPU 0x02
#define PREP_IBM_EQUIPMENT_L2 0x01
/* planar ID values: */
/* Sandalfoot/Sandalbow (6015/7020) */
#define PREP_IBM_SANDALFOOT 0xfc
/* Woodfield, Thinkpad 850/860 (6042/7249) */
#define PREP_IBM_THINKPAD 0xff /* planar ID unimplemented */
/* PowerSeries 830/850 (6050/6070) */
#define PREP_IBM_CAROLINA_IDE_0 0xf0
#define PREP_IBM_CAROLINA_IDE_1 0xf1
#define PREP_IBM_CAROLINA_IDE_2 0xf2
/* 7248-43P */
#define PREP_IBM_CAROLINA_SCSI_0 0xf4
#define PREP_IBM_CAROLINA_SCSI_1 0xf5
#define PREP_IBM_CAROLINA_SCSI_2 0xf6
#define PREP_IBM_CAROLINA_SCSI_3 0xf7 /* missing from Carolina Tech Spec */
/* Tiger1 (7043-140) */
#define PREP_IBM_TIGER1_133 0xd1
#define PREP_IBM_TIGER1_166 0xd2
#define PREP_IBM_TIGER1_180 0xd3
#define PREP_IBM_TIGER1_xxx 0xd4 /* unknown, but probably exists */
#define PREP_IBM_TIGER1_333 0xd5 /* missing from Tiger Tech Spec */
/* setup_ibm_pci:
* set Motherboard_map_name, Motherboard_map, Motherboard_routes.
* return 8259 edge/level masks.
*/
void (*setup_ibm_pci)(char *irq_lo, char *irq_hi);
extern char *Motherboard_map_name; /* for use in *_cpuinfo */
/*
* As found in the PReP reference implementation.
* Used by Thinkpad, Sandalfoot (6015/7020), and all Motorola PReP.
*/
static void __init
prep_gen_enable_l2(void)
{
outb(inb(PREP_SYSCTL) | 0x3, PREP_SYSCTL);
}
/* Used by Carolina and Tiger1 */
static void __init
prep_carolina_enable_l2(void)
{
outb(inb(PREP_SYSCTL) | 0xc0, PREP_SYSCTL);
}
/* cpuinfo code common to all IBM PReP */
static void __prep
prep_ibm_cpuinfo(struct seq_file *m)
{ {
extern char *Motherboard_map_name; unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT);
int cachew;
seq_printf(m, "machine\t\t: PReP %s\n", Motherboard_map_name); seq_printf(m, "machine\t\t: PReP %s\n", Motherboard_map_name);
switch ( _prep_type ) { seq_printf(m, "upgrade cpu\t: ");
case _PREP_IBM: if (equip_reg & PREP_IBM_EQUIPMENT_CPU) {
cachew = inw(0x80c); seq_printf(m, "not ");
if (cachew & (1<<6)) }
seq_printf(m, "Upgrade CPU\n"); seq_printf(m, "present\n");
seq_printf(m, "L2\t\t: ");
if (cachew & (1<<7)) { /* print info about the SCSI fuse */
seq_printf(m, "scsi fuse\t: ");
if (equip_reg & PREP_IBM_EQUIPMENT_SCSIFUSE)
seq_printf(m, "ok");
else
seq_printf(m, "bad");
seq_printf(m, "\n");
#ifdef CONFIG_PREP_RESIDUAL
/* print info about SIMMs */
if (res->ResidualLength != 0) {
int i;
seq_printf(m, "simms\t\t: ");
for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) {
if (res->Memories[i].SIMMSize != 0)
seq_printf(m, "%d:%ldMiB ", i,
(res->Memories[i].SIMMSize > 1024) ?
res->Memories[i].SIMMSize>>20 :
res->Memories[i].SIMMSize);
}
seq_printf(m, "\n");
}
#endif
}
static int __prep
prep_sandalfoot_cpuinfo(struct seq_file *m)
{
unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT);
prep_ibm_cpuinfo(m);
/* report amount and type of L2 cache present */
seq_printf(m, "L2 cache\t: ");
if (equip_reg & PREP_IBM_EQUIPMENT_L2) {
seq_printf(m, "not present");
} else {
if (equip_reg & PREP_IBM_EQUIPMENT_L2_256)
seq_printf(m, "256KiB");
else
seq_printf(m, "unknown size");
if (equip_reg & PREP_IBM_EQUIPMENT_L2_COPYBACK)
seq_printf(m, ", copy-back");
else
seq_printf(m, ", write-through");
}
seq_printf(m, "\n");
return 0;
}
static int __prep
prep_thinkpad_cpuinfo(struct seq_file *m)
{
unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT);
char *cpubus_speed, *pci_speed;
prep_ibm_cpuinfo(m);
/* report amount and type of L2 cache present */
seq_printf(m, "l2 cache\t: ");
if ((equip_reg & 0x1) == 0) {
switch ((equip_reg & 0xc) >> 2) {
case 0x0:
seq_printf(m, "128KiB look-aside 2-way write-through\n");
break;
case 0x1:
seq_printf(m, "512KiB look-aside direct-mapped write-back\n");
break;
case 0x2:
seq_printf(m, "256KiB look-aside 2-way write-through\n");
break;
case 0x3:
seq_printf(m, "256KiB look-aside direct-mapped write-back\n");
break;
}
} else {
seq_printf(m, "not present\n"); seq_printf(m, "not present\n");
goto no_l2;
} }
seq_printf(m, "%sKb,", (cachew & (1 << 10))? "512" : "256");
seq_printf(m, "%ssync\n", (cachew & (1 << 15))? "" : "a"); /* report bus speeds because we can */
if ((equip_reg & 0x80) == 0) {
switch ((equip_reg & 0x30) >> 4) {
case 0x1:
cpubus_speed = "50";
pci_speed = "25";
break; break;
case _PREP_Motorola: case 0x3:
cachew = *((unsigned char *)CACHECRBA); cpubus_speed = "66";
seq_printf(m, "L2\t\t: "); pci_speed = "33";
break;
default:
cpubus_speed = "unknown";
pci_speed = "unknown";
break;
}
} else {
switch ((equip_reg & 0x30) >> 4) {
case 0x1:
cpubus_speed = "25";
pci_speed = "25";
break;
case 0x2:
cpubus_speed = "60";
pci_speed = "30";
break;
case 0x3:
cpubus_speed = "33";
pci_speed = "33";
break;
default:
cpubus_speed = "unknown";
pci_speed = "unknown";
break;
}
}
seq_printf(m, "60x bus\t\t: %sMHz\n", cpubus_speed);
seq_printf(m, "pci bus\t\t: %sMHz\n", pci_speed);
return 0;
}
static int __prep
prep_carolina_cpuinfo(struct seq_file *m)
{
unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT);
prep_ibm_cpuinfo(m);
/* report amount and type of L2 cache present */
seq_printf(m, "l2 cache\t: ");
if ((equip_reg & 0x1) == 0) {
unsigned int l2_reg = inb(PREP_IBM_L2INFO);
/* L2 size */
if ((l2_reg & 0x60) == 0)
seq_printf(m, "256KiB");
else if ((l2_reg & 0x60) == 1)
seq_printf(m, "512KiB");
else
seq_printf(m, "unknown size");
/* L2 type */
if ((l2_reg & 0x3) == 0)
seq_printf(m, ", async");
else if ((l2_reg & 0x3) == 1)
seq_printf(m, ", sync");
else
seq_printf(m, ", unknown type");
seq_printf(m, "\n");
} else {
seq_printf(m, "not present\n");
}
return 0;
}
static int __prep
prep_tiger1_cpuinfo(struct seq_file *m)
{
unsigned int l2_reg = inb(PREP_IBM_L2INFO);
prep_ibm_cpuinfo(m);
/* report amount and type of L2 cache present */
seq_printf(m, "l2 cache\t: ");
if ((l2_reg & 0xf) == 0xf) {
seq_printf(m, "not present\n");
} else {
if (l2_reg & 0x8)
seq_printf(m, "async, ");
else
seq_printf(m, "sync burst, ");
if (l2_reg & 0x4)
seq_printf(m, "parity, ");
else
seq_printf(m, "no parity, ");
switch (l2_reg & 0x3) {
case 0x0:
seq_printf(m, "256KiB\n");
break;
case 0x1:
seq_printf(m, "512KiB\n");
break;
case 0x2:
seq_printf(m, "1MiB\n");
break;
default:
seq_printf(m, "unknown size\n");
break;
}
}
return 0;
}
/* Used by all Motorola PReP */
static int __prep
prep_mot_cpuinfo(struct seq_file *m)
{
unsigned int cachew = *((unsigned char *)CACHECRBA);
seq_printf(m, "machine\t\t: PReP %s\n", Motherboard_map_name);
/* report amount and type of L2 cache present */
seq_printf(m, "l2 cache\t: ");
switch (cachew & L2CACHE_MASK) { switch (cachew & L2CACHE_MASK) {
case L2CACHE_512KB: case L2CACHE_512KB:
seq_printf(m, "512Kb"); seq_printf(m, "512KiB");
break; break;
case L2CACHE_256KB: case L2CACHE_256KB:
seq_printf(m, "256Kb"); seq_printf(m, "256KiB");
break; break;
case L2CACHE_1MB: case L2CACHE_1MB:
seq_printf(m, "1MB"); seq_printf(m, "1MiB");
break; break;
case L2CACHE_NONE: case L2CACHE_NONE:
seq_printf(m, "none\n"); seq_printf(m, "none\n");
...@@ -148,26 +420,21 @@ prep_show_cpuinfo(struct seq_file *m) ...@@ -148,26 +420,21 @@ prep_show_cpuinfo(struct seq_file *m)
seq_printf(m, " SRAM:"); seq_printf(m, " SRAM:");
switch ( ((cachew & 0xf0) >> 4) & ~(0x3) ) { switch ( ((cachew & 0xf0) >> 4) & ~(0x3) ) {
case 1: seq_printf(m, "synchronous,parity,flow-through\n"); case 1: seq_printf(m, "synchronous, parity, flow-through\n");
break; break;
case 2: seq_printf(m, "asynchronous,no parity\n"); case 2: seq_printf(m, "asynchronous, no parity\n");
break; break;
case 3: seq_printf(m, "asynchronous,parity\n"); case 3: seq_printf(m, "asynchronous, parity\n");
break; break;
default:seq_printf(m, "synchronous,pipelined,no parity\n"); default:seq_printf(m, "synchronous, pipelined, no parity\n");
break;
}
break;
default:
break; break;
} }
no_l2: no_l2:
#ifdef CONFIG_PREP_RESIDUAL #ifdef CONFIG_PREP_RESIDUAL
/* print info about SIMMs */
if (res->ResidualLength != 0) { if (res->ResidualLength != 0) {
int i; int i;
/* print info about SIMMs */
seq_printf(m, "simms\t\t: "); seq_printf(m, "simms\t\t: ");
for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) { for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) {
if (res->Memories[i].SIMMSize != 0) if (res->Memories[i].SIMMSize != 0)
...@@ -183,6 +450,112 @@ prep_show_cpuinfo(struct seq_file *m) ...@@ -183,6 +450,112 @@ prep_show_cpuinfo(struct seq_file *m)
return 0; return 0;
} }
static void __prep
prep_tiger1_progress(char *msg, unsigned short code)
{
outw(code, PREP_IBM_DISP);
}
static void __prep
prep_restart(char *cmd)
{
#define PREP_SP92 0x92 /* Special Port 92 */
local_irq_disable(); /* no interrupts */
/* set exception prefix high - to the prom */
_nmask_and_or_msr(0, MSR_IP);
/* make sure bit 0 (reset) is a 0 */
outb( inb(PREP_SP92) & ~1L , PREP_SP92);
/* signal a reset to system control port A - soft reset */
outb( inb(PREP_SP92) | 1 , PREP_SP92);
while ( 1 ) ;
/* not reached */
#undef PREP_SP92
}
static void __prep
prep_halt(void)
{
local_irq_disable(); /* no interrupts */
/* set exception prefix high - to the prom */
_nmask_and_or_msr(0, MSR_IP);
while ( 1 ) ;
/* not reached */
}
/* Carrera is the power manager in the Thinkpads. Unfortunately not much is
* known about it, so we can't power down.
*/
static void __prep
prep_carrera_poweroff(void)
{
prep_halt();
}
/*
* On most IBM PReP's, power management is handled by a Signetics 87c750
* behind the Utah component on the ISA bus. To access the 750 you must write
* a series of nibbles to port 0x82a (decoded by the Utah). This is described
* somewhat in the IBM Carolina Technical Specification.
* -Hollis
*/
static void __prep
utah_sig87c750_setbit(unsigned int bytenum, unsigned int bitnum, int value)
{
/*
* byte1: 0 0 0 1 0 d a5 a4
* byte2: 0 0 0 1 a3 a2 a1 a0
*
* d = the bit's value, enabled or disabled
* (a5 a4 a3) = the byte number, minus 20
* (a2 a1 a0) = the bit number
*
* example: set the 5th bit of byte 21 (21.5)
* a5 a4 a3 = 001 (byte 1)
* a2 a1 a0 = 101 (bit 5)
*
* byte1 = 0001 0100 (0x14)
* byte2 = 0001 1101 (0x1d)
*/
unsigned char byte1=0x10, byte2=0x10;
/* the 750's '20.0' is accessed as '0.0' through Utah (which adds 20) */
bytenum -= 20;
byte1 |= (!!value) << 2; /* set d */
byte1 |= (bytenum >> 1) & 0x3; /* set a5, a4 */
byte2 |= (bytenum & 0x1) << 3; /* set a3 */
byte2 |= bitnum & 0x7; /* set a2, a1, a0 */
outb(byte1, PREP_IBM_PM1); /* first nibble */
mb();
udelay(100); /* important: let controller recover */
outb(byte2, PREP_IBM_PM1); /* second nibble */
mb();
udelay(100); /* important: let controller recover */
}
static void __prep
prep_sig750_poweroff(void)
{
/* tweak the power manager found in most IBM PRePs (except Thinkpads) */
local_irq_disable();
/* set exception prefix high - to the prom */
_nmask_and_or_msr(0, MSR_IP);
utah_sig87c750_setbit(21, 5, 1); /* set bit 21.5, "PMEXEC_OFF" */
while (1) ;
/* not reached */
}
static int __prep static int __prep
prep_show_percpuinfo(struct seq_file *m, int i) prep_show_percpuinfo(struct seq_file *m, int i)
{ {
...@@ -314,6 +687,7 @@ static void __init ...@@ -314,6 +687,7 @@ static void __init
prep_setup_arch(void) prep_setup_arch(void)
{ {
unsigned char reg; unsigned char reg;
int is_ide=0;
/* init to some ~sane value until calibrate_delay() runs */ /* init to some ~sane value until calibrate_delay() runs */
loops_per_jiffy = 50000000; loops_per_jiffy = 50000000;
...@@ -328,17 +702,65 @@ prep_setup_arch(void) ...@@ -328,17 +702,65 @@ prep_setup_arch(void)
outb(reg, SIO_CONFIG_RD); outb(reg, SIO_CONFIG_RD);
outb(reg, SIO_CONFIG_RD); /* Have to write twice to change! */ outb(reg, SIO_CONFIG_RD); /* Have to write twice to change! */
/* we should determine this according to what we find! -- Cort */
switch ( _prep_type ) switch ( _prep_type )
{ {
case _PREP_IBM: case _PREP_IBM:
/* Enable L2. Assume we don't need to flush -- Cort*/ reg = inb(PREP_IBM_PLANAR);
*(unsigned char *)(0x8000081c) |= 3; printk(KERN_INFO "IBM planar ID: %08x", reg);
ROOT_DEV = Root_HDA1; switch (reg) {
case PREP_IBM_SANDALFOOT:
prep_gen_enable_l2();
setup_ibm_pci = prep_sandalfoot_setup_pci;
ppc_md.power_off = prep_sig750_poweroff;
ppc_md.show_cpuinfo = prep_sandalfoot_cpuinfo;
break;
case PREP_IBM_THINKPAD:
prep_gen_enable_l2();
setup_ibm_pci = prep_thinkpad_setup_pci;
ppc_md.power_off = prep_carrera_poweroff;
ppc_md.show_cpuinfo = prep_thinkpad_cpuinfo;
break;
default:
printk(" -- unknown! Assuming Carolina");
case PREP_IBM_CAROLINA_IDE_0:
case PREP_IBM_CAROLINA_IDE_1:
case PREP_IBM_CAROLINA_IDE_2:
is_ide = 1;
case PREP_IBM_CAROLINA_SCSI_0:
case PREP_IBM_CAROLINA_SCSI_1:
case PREP_IBM_CAROLINA_SCSI_2:
case PREP_IBM_CAROLINA_SCSI_3:
prep_carolina_enable_l2();
setup_ibm_pci = prep_carolina_setup_pci;
ppc_md.power_off = prep_sig750_poweroff;
ppc_md.show_cpuinfo = prep_carolina_cpuinfo;
break;
case PREP_IBM_TIGER1_133:
case PREP_IBM_TIGER1_166:
case PREP_IBM_TIGER1_180:
case PREP_IBM_TIGER1_xxx:
case PREP_IBM_TIGER1_333:
prep_carolina_enable_l2();
setup_ibm_pci = prep_tiger1_setup_pci;
ppc_md.power_off = prep_sig750_poweroff;
ppc_md.show_cpuinfo = prep_tiger1_cpuinfo;
ppc_md.progress = prep_tiger1_progress;
break;
}
printk("\n");
/* default root device */
if (is_ide)
ROOT_DEV = MKDEV(IDE0_MAJOR, 3);
else
ROOT_DEV = MKDEV(SCSI_DISK0_MAJOR, 3);
break; break;
case _PREP_Motorola: case _PREP_Motorola:
/* Enable L2. Assume we don't need to flush -- Cort*/ prep_gen_enable_l2();
*(unsigned char *)(0x8000081c) |= 3; ppc_md.power_off = prep_halt;
ppc_md.show_cpuinfo = prep_mot_cpuinfo;
#ifdef CONFIG_BLK_DEV_INITRD #ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start) if (initrd_start)
ROOT_DEV = Root_RAM0; ROOT_DEV = Root_RAM0;
...@@ -552,104 +974,6 @@ mk48t59_calibrate_decr(void) ...@@ -552,104 +974,6 @@ mk48t59_calibrate_decr(void)
tb_to_us = mulhwu_scale_factor(freq, 1000000); tb_to_us = mulhwu_scale_factor(freq, 1000000);
} }
static void __prep
prep_restart(char *cmd)
{
unsigned long i = 10000;
local_irq_disable();
/* set exception prefix high - to the prom */
_nmask_and_or_msr(0, MSR_IP);
/* make sure bit 0 (reset) is a 0 */
outb( inb(0x92) & ~1L , 0x92 );
/* signal a reset to system control port A - soft reset */
outb( inb(0x92) | 1 , 0x92 );
while ( i != 0 ) i++;
panic("restart failed\n");
}
static void __prep
prep_halt(void)
{
/* set exception prefix high - to the prom */
_nmask_and_or_msr(MSR_EE, MSR_IP);
/* make sure bit 0 (reset) is a 0 */
outb( inb(0x92) & ~1L , 0x92 );
/* signal a reset to system control port A - soft reset */
outb( inb(0x92) | 1 , 0x92 );
while ( 1 ) ;
/*
* Not reached
*/
}
/*
* On IBM PReP's, power management is handled by a Signetics 87c750 behind the
* Utah component on the ISA bus. To access the 750 you must write a series of
* nibbles to port 0x82a (decoded by the Utah). This is described somewhat in
* the IBM Carolina Technical Specification.
* -Hollis
*/
static void __prep
utah_sig87c750_setbit(unsigned int bytenum, unsigned int bitnum, int value)
{
/*
* byte1: 0 0 0 1 0 d a5 a4
* byte2: 0 0 0 1 a3 a2 a1 a0
*
* d = the bit's value, enabled or disabled
* (a5 a4 a3) = the byte number, minus 20
* (a2 a1 a0) = the bit number
*
* example: set the 5th bit of byte 21 (21.5)
* a5 a4 a3 = 001 (byte 1)
* a2 a1 a0 = 101 (bit 5)
*
* byte1 = 0001 0100 (0x14)
* byte2 = 0001 1101 (0x1d)
*/
unsigned char byte1=0x10, byte2=0x10;
const unsigned int pm_reg_1=0x82a; /* ISA address */
/* the 750's '20.0' is accessed as '0.0' through Utah (which adds 20) */
bytenum -= 20;
byte1 |= (!!value) << 2; /* set d */
byte1 |= (bytenum >> 1) & 0x3; /* set a5, a4 */
byte2 |= (bytenum & 0x1) << 3; /* set a3 */
byte2 |= bitnum & 0x7; /* set a2, a1, a0 */
outb(byte1, pm_reg_1); /* first nibble */
mb();
udelay(100); /* important: let controller recover */
outb(byte2, pm_reg_1); /* second nibble */
mb();
udelay(100); /* important: let controller recover */
}
static void __prep
prep_power_off(void)
{
if ( _prep_type == _PREP_IBM) {
/* set exception prefix high - to the prom */
_nmask_and_or_msr(MSR_EE, MSR_IP);
utah_sig87c750_setbit(21, 5, 1); /* set bit 21.5, "PMEXEC_OFF" */
while ( 1 ) ;
/* not reached */
} else {
prep_halt();
}
}
static unsigned int __prep static unsigned int __prep
prep_irq_cannonicalize(u_int irq) prep_irq_cannonicalize(u_int irq)
{ {
...@@ -728,7 +1052,7 @@ smp_prep_kick_cpu(int nr) ...@@ -728,7 +1052,7 @@ smp_prep_kick_cpu(int nr)
{ {
*(unsigned long *)KERNELBASE = nr; *(unsigned long *)KERNELBASE = nr;
asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory"); asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
printk("CPU1 reset, waiting\n"); printk("CPU1 released, waiting\n");
} }
static void __init static void __init
...@@ -812,14 +1136,14 @@ prep_init(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -812,14 +1136,14 @@ prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.setup_arch = prep_setup_arch; ppc_md.setup_arch = prep_setup_arch;
ppc_md.show_percpuinfo = prep_show_percpuinfo; ppc_md.show_percpuinfo = prep_show_percpuinfo;
ppc_md.show_cpuinfo = prep_show_cpuinfo; ppc_md.show_cpuinfo = NULL; /* set in prep_setup_arch() */
ppc_md.irq_cannonicalize = prep_irq_cannonicalize; ppc_md.irq_cannonicalize = prep_irq_cannonicalize;
ppc_md.init_IRQ = prep_init_IRQ; ppc_md.init_IRQ = prep_init_IRQ;
/* this gets changed later on if we have an OpenPIC -- Cort */ /* this gets changed later on if we have an OpenPIC -- Cort */
ppc_md.get_irq = i8259_irq; ppc_md.get_irq = i8259_irq;
ppc_md.restart = prep_restart; ppc_md.restart = prep_restart;
ppc_md.power_off = prep_power_off; ppc_md.power_off = NULL; /* set in prep_setup_arch() */
ppc_md.halt = prep_halt; ppc_md.halt = prep_halt;
ppc_md.nvram_read_val = prep_nvram_read_val; ppc_md.nvram_read_val = prep_nvram_read_val;
......
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