Commit 5a2c26bd authored by Paul Mackerras's avatar Paul Mackerras

PPC32: powermac update from Ben Herrenschmidt.

This adds support for recent powermac models and fixes a few bugs.
parent b0d46fe5
......@@ -28,6 +28,8 @@ extern void __setup_cpu_750(int cpu_nr);
extern void __setup_cpu_7400(int cpu_nr);
extern void __setup_cpu_7410(int cpu_nr);
extern void __setup_cpu_7450(int cpu_nr);
extern void __setup_cpu_7450_23(int cpu_nr);
extern void __setup_cpu_7455(int cpu_nr);
extern void __setup_cpu_power3(int cpu_nr);
extern void __setup_cpu_8xx(int cpu_nr);
extern void __setup_cpu_generic(int cpu_nr);
......@@ -61,21 +63,24 @@ struct cpu_spec cpu_specs[] = {
},
{ /* 603 */
0xffff0000, 0x00030000, "603",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB,
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
CPU_FTR_CAN_NAP,
COMMON_PPC,
32, 32,
__setup_cpu_603
},
{ /* 603e */
0xffff0000, 0x00060000, "603e",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB,
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
CPU_FTR_CAN_NAP,
COMMON_PPC,
32, 32,
__setup_cpu_603
},
{ /* 603ev */
0xffff0000, 0x00070000, "603ev",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB,
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
CPU_FTR_CAN_NAP,
COMMON_PPC,
32, 32,
__setup_cpu_603
......@@ -115,7 +120,7 @@ struct cpu_spec cpu_specs[] = {
{ /* 740/750 (0x4202, don't support TAU ?) */
0xffffffff, 0x00084202, "740/750",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
CPU_FTR_L2CR | CPU_FTR_HPTE_TABLE,
CPU_FTR_L2CR | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP,
COMMON_PPC,
32, 32,
__setup_cpu_750
......@@ -123,7 +128,7 @@ struct cpu_spec cpu_specs[] = {
{ /* 745/755 */
0xfffff000, 0x00083000, "745/755",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE,
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP,
COMMON_PPC,
32, 32,
__setup_cpu_750
......@@ -131,7 +136,7 @@ struct cpu_spec cpu_specs[] = {
{ /* 750CX (80100 and 8010x?) */
0xfffffff0, 0x00080100, "750CX",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE,
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP,
COMMON_PPC,
32, 32,
__setup_cpu_750
......@@ -139,7 +144,7 @@ struct cpu_spec cpu_specs[] = {
{ /* 750CX (82201 and 82202) */
0xfffffff0, 0x00082200, "750CX",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE,
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP,
COMMON_PPC,
32, 32,
__setup_cpu_750
......@@ -147,7 +152,7 @@ struct cpu_spec cpu_specs[] = {
{ /* 750CXe (82214) */
0xfffffff0, 0x00082210, "750CXe",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE,
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP,
COMMON_PPC,
32, 32,
__setup_cpu_750
......@@ -163,7 +168,8 @@ struct cpu_spec cpu_specs[] = {
{ /* 7400 rev 1.1 ? (no TAU) */
0xffffffff, 0x000c1101, "7400 (1.1)",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE,
CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE |
CPU_FTR_CAN_NAP,
COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC,
32, 32,
__setup_cpu_7400
......@@ -171,7 +177,8 @@ struct cpu_spec cpu_specs[] = {
{ /* 7400 */
0xffff0000, 0x000c0000, "7400",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE,
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE |
CPU_FTR_CAN_NAP,
COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC,
32, 32,
__setup_cpu_7400
......@@ -179,7 +186,8 @@ struct cpu_spec cpu_specs[] = {
{ /* 7410 */
0xffff0000, 0x800c0000, "7410",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE,
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE |
CPU_FTR_CAN_NAP,
COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC,
32, 32,
__setup_cpu_7410
......@@ -187,21 +195,39 @@ struct cpu_spec cpu_specs[] = {
{ /* 7450 2.0 - no doze/nap */
0xffffffff, 0x80000200, "7450",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP |
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450,
COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC,
32, 32,
__setup_cpu_7450
},
{ /* 7450 others */
0xffff0000, 0x80000000, "7450",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP |
{ /* 7450 2.1 */
0xffffffff, 0x80000201, "7450",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450,
COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC,
32, 32,
__setup_cpu_7450
},
{ /* 7450 2.3 and newer */
0xffff0000, 0x80000000, "7450",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450,
COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC,
32, 32,
__setup_cpu_7450_23
},
{ /* 7455 */
0xffff0000, 0x80010000, "7455",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450,
COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC,
32, 32,
__setup_cpu_7455
},
{ /* 82xx (8240, 8245, 8260 are all 603e cores) */
0x7fff0000, 0x00810000, "82xx",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB,
......
......@@ -56,7 +56,9 @@ void default_idle(void)
{
int do_power_save = 0;
if (cur_cpu_spec[smp_processor_id()]->cpu_features & CPU_FTR_CAN_DOZE)
/* Check if CPU can powersave */
if (cur_cpu_spec[smp_processor_id()]->cpu_features &
(CPU_FTR_CAN_DOZE | CPU_FTR_CAN_NAP))
do_power_save = 1;
#ifdef CONFIG_PPC_ISERIES
......@@ -112,7 +114,7 @@ void power_save(void)
/* 7450 has no DOZE mode mode, we return if powersave_nap
* isn't enabled
*/
if (!nap && cur_cpu_spec[smp_processor_id()]->cpu_features & CPU_FTR_SPEC7450)
if (!(nap || (cur_cpu_spec[smp_processor_id()]->cpu_features & CPU_FTR_CAN_DOZE)))
return;
/*
* Disable interrupts to prevent a lost wakeup
......
......@@ -134,6 +134,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_L2CR)
The bit moved on the 7450.....
****/
/* TODO: use HW flush assist when available */
lis r4,0x0002
mtctr r4
li r4,0
......@@ -154,10 +156,18 @@ END_FTR_SECTION_IFCLR(CPU_FTR_L2CR)
2:
/* Set up the L2CR configuration bits (and switch L2 off) */
/* CPU errata: Make sure the mtspr below is already in the
* L1 icache
*/
b 20f
21:
sync
mtspr L2CR,r3
sync
b 22f
20:
b 21b
22:
/* Before we perform the global invalidation, we must disable dynamic
* power management via HID0[DPM] to work around a processor bug where
* DPM can possibly interfere with the state machine in the processor
......@@ -223,5 +233,147 @@ BEGIN_FTR_SECTION
END_FTR_SECTION_IFSET(CPU_FTR_L2CR)
blr
/*
* Here is a similar routine for dealing with the L3 cache
* on the 745x family of chips
*/
_GLOBAL(_set_L3CR)
/* Make sure this is a 745x chip */
BEGIN_FTR_SECTION
li r3,-1
blr
END_FTR_SECTION_IFCLR(CPU_FTR_L3CR)
/* Turn off interrupts and data relocation. */
mfmsr r7 /* Save MSR in r7 */
rlwinm r4,r7,0,17,15
rlwinm r4,r4,0,28,26 /* Turn off DR bit */
sync
mtmsr r4
isync
/* Stop DST streams */
dssall 0
/* Get the current enable bit of the L3CR into r4 */
mfspr r4,SPRN_L3CR
/* Tweak some bits */
rlwinm r5,r3,0,0,0 /* r5 contains the new enable bit */
rlwinm r3,r3,0,22,20 /* Turn off the invalidate bit */
rlwinm r3,r3,0,1,31 /* Turn off the enable bit */
rlwinm r3,r3,0,5,3 /* Turn off the clken bit */
/* Check to see if we need to flush */
rlwinm. r4,r4,0,0,0
beq 2f
/* Flush the cache. First, read the first 4MB of memory (physical) to
* put new data in the cache. (Actually we only need
* the size of the L3 cache plus the size of the L1+L2 cache, but 4MB will
* cover everything just to be safe).
*/
/* TODO: use HW flush assist */
lis r4,0x0002
mtctr r4
li r4,0
1:
lwzx r0,r0,r4
addi r4,r4,32 /* Go to start of next cache line */
bdnz 1b
/* Now, flush the first 4MB of memory */
lis r4,0x0002
mtctr r4
li r4,0
sync
1:
dcbf r0,r4
addi r4,r4,32 /* Go to start of next cache line */
bdnz 1b
2:
/* Set up the L3CR configuration bits (and switch L3 off) */
sync
mtspr SPRN_L3CR,r3
sync
/* Before we perform the global invalidation, we must disable dynamic
* power management via HID0[DPM] to work around a processor bug where
* DPM can possibly interfere with the state machine in the processor
* that invalidates the L3 cache tags. Hrm... This is necessary for L2,
* is it for L3 as well ? --BenH.
*/
mfspr r8,HID0 /* Save HID0 in r8 */
rlwinm r4,r8,0,12,10 /* Turn off HID0[DPM] */
sync
mtspr HID0,r4 /* Disable DPM */
sync
oris r3,r3,L3CR_L3RES@h /* Set reserved bit 5 */
mtspr SPRN_L3CR,r3
sync
oris r3,r3,L3CR_L3CLKEN@h /* Set clken */
mtspr SPRN_L3CR,r3
sync
/* Wait for stabilize */
li r0,128
mtctr r0
1: bdnz 1b
/* Perform a global invalidation */
ori r3,r3,0x0400
sync
mtspr SPRN_L3CR,r3
sync
isync
/* We wait for the L3I bit to clear...... */
10: mfspr r3,SPRN_L3CR
andi. r4,r3,0x0400
bne 10b
/* Clear CLKEN */
rlwinm r3,r3,0,5,3 /* Turn off the clken bit */
mtspr SPRN_L3CR,r3
sync
/* Wait for stabilize */
li r0,128
mtctr r0
1: bdnz 1b
/* Restore HID0[DPM] to whatever it was before */
sync
mtspr 1008,r8
sync
/* See if we need to enable the cache */
cmplwi r5,0
beq 4f
/* Enable the cache */
oris r3,r3,(L3CR_L3E | L3CR_L3CLKEN)@h
mtspr SPRN_L3CR,r3
sync
/* Restore MSR (restores EE and DR bits to original state) */
4: SYNC
mtmsr r7
isync
blr
_GLOBAL(_get_L3CR)
/* Return the L3CR contents */
li r3,0
BEGIN_FTR_SECTION
mfspr r3,SPRN_L3CR
END_FTR_SECTION_IFSET(CPU_FTR_L3CR)
blr
/* --- End of PowerLogix code ---
*/
......@@ -189,14 +189,24 @@ pcibios_fixup_cardbus(struct pci_dev* dev)
if (_machine != _MACH_Pmac)
return;
/*
* Fix the interrupt routing on the TI1211 chip on the 1999
* G3 powerbook, which doesn't get initialized properly by OF.
* Same problem with the 1410 of the new titanium pbook which
* has the same register.
* Fix the interrupt routing on the various cardbus bridges
* used on powerbooks
*/
if (dev->vendor == PCI_VENDOR_ID_TI
&& (dev->device == PCI_DEVICE_ID_TI_1211 ||
dev->device == PCI_DEVICE_ID_TI_1410)) {
if (dev->vendor != PCI_VENDOR_ID_TI)
return;
if (dev->device == PCI_DEVICE_ID_TI_1130 ||
dev->device == PCI_DEVICE_ID_TI_1131) {
u8 val;
/* Enable PCI interrupt */
if (pci_read_config_byte(dev, 0x91, &val) == 0)
pci_write_config_byte(dev, 0x91, val | 0x30);
/* Disable ISA interrupt mode */
if (pci_read_config_byte(dev, 0x92, &val) == 0)
pci_write_config_byte(dev, 0x92, val & ~0x06);
}
if (dev->device == PCI_DEVICE_ID_TI_1210 ||
dev->device == PCI_DEVICE_ID_TI_1211 ||
dev->device == PCI_DEVICE_ID_TI_1410) {
u8 val;
/* 0x8c == TI122X_IRQMUX, 2 says to route the INTA
signal out the MFUNC0 pin */
......@@ -223,7 +233,8 @@ pcibios_fixup_cardbus(struct pci_dev* dev)
* which might have be mirrored at 0x0100-0x03ff..
*/
void
pcibios_align_resource(void *data, struct resource *res, unsigned long size)
pcibios_align_resource(void *data, struct resource *res, unsigned long size,
unsigned long align)
{
struct pci_dev *dev = data;
......
......@@ -35,6 +35,7 @@
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/pmac_feature.h>
#include <asm/sections.h>
#if defined CONFIG_KGDB
#include <asm/kgdb.h>
......@@ -230,7 +231,6 @@ int show_cpuinfo(struct seq_file *m, void *v)
return 0;
}
static void *c_start(struct seq_file *m, loff_t *pos)
{
int i = *pos;
......@@ -309,6 +309,27 @@ early_init(int r3, int r4, int r5)
}
#ifdef CONFIG_ALL_PPC
/*
* Assume here that all clock rates are the same in a
* smp system. -- Cort
*/
int __openfirmware
of_show_percpuinfo(struct seq_file *m, int i)
{
struct device_node *cpu_node;
int *fp, s;
cpu_node = find_type_devices("cpu");
if (!cpu_node)
return 0;
for (s = 0; s < i && cpu_node->next; s++)
cpu_node = cpu_node->next;
fp = (int *) get_property(cpu_node, "clock-frequency", NULL);
if (fp)
seq_printf(m, "clock\t\t: %dMHz\n", *fp / 1000000);
return 0;
}
void __init
intuit_machine_type(void)
{
......@@ -528,6 +549,27 @@ int __init ppc_setup_l2cr(char *str)
}
__setup("l2cr=", ppc_setup_l2cr);
#ifdef CONFIG_NVRAM
/* Generic nvram hooks we now look into ppc_md.nvram_read_val
* on pmac too ;)
* //XX Those 2 could be moved to headers
*/
unsigned char
nvram_read_byte(int addr)
{
if (ppc_md.nvram_read_val)
return ppc_md.nvram_read_val(addr);
return 0xff;
}
void
nvram_write_byte(unsigned char val, int addr)
{
if (ppc_md.nvram_write_val)
ppc_md.nvram_write_val(val, addr);
}
#endif /* CONFIG_NVRAM */
int __init ppc_init(void)
{
/* clear the progress line */
......
......@@ -433,7 +433,8 @@ void __init
chrp_init2(void)
{
#ifdef CONFIG_NVRAM
pmac_nvram_init();
// XX replace this in a more saner way
// pmac_nvram_init();
#endif
request_region(0x20,0x20,"pic1");
......
This diff is collapsed.
......@@ -2,7 +2,17 @@
* BK Id: %F% %I% %G% %U% %#%
*/
/*
* Miscellaneous procedures for dealing with the PowerMac hardware.
* arch/ppc/platforms/pmac_nvram.c
*
* Copyright (C) 2002 Benjamin Herrenschmidt (benh@kernel.crashing.org)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Todo: - cleanup some coding horrors in the flash code
* - add support for the OF persistent properties
*/
#include <linux/config.h>
#include <linux/module.h>
......@@ -75,7 +85,7 @@ static char nvram_image[NVRAM_SIZE] __pmacdata;
extern int pmac_newworld;
static u8 __openfirmware
static u8 __pmac
chrp_checksum(struct chrp_header* hdr)
{
u8 *ptr;
......@@ -314,8 +324,8 @@ pmac_nvram_update(void)
printk("nvram: Error writing bank %d\n", core99_bank);
}
unsigned char __openfirmware
nvram_read_byte(int addr)
unsigned char __pmac
pmac_nvram_read_byte(int addr)
{
switch (nvram_naddrs) {
#ifdef CONFIG_ADB_PMU
......@@ -342,8 +352,8 @@ nvram_read_byte(int addr)
return 0;
}
void __openfirmware
nvram_write_byte(unsigned char val, int addr)
void __pmac
pmac_nvram_write_byte(int addr, unsigned char val)
{
switch (nvram_naddrs) {
#ifdef CONFIG_ADB_PMU
......@@ -388,7 +398,7 @@ pmac_xpram_read(int xpaddr)
if (offset < 0)
return 0;
return nvram_read_byte(xpaddr + offset);
return pmac_nvram_read_byte(xpaddr + offset);
}
void __pmac
......@@ -399,5 +409,5 @@ pmac_xpram_write(int xpaddr, u8 data)
if (offset < 0)
return;
nvram_write_byte(xpaddr + offset, data);
pmac_nvram_write_byte(data, xpaddr + offset);
}
......@@ -3,12 +3,14 @@
*/
/*
* Support for PCI bridges found on Power Macintoshes.
* At present the "bandit" and "chaos" bridges are supported.
* Fortunately you access configuration space in the same
* way with either bridge.
*
* This includes support for bandit, chaos, grackle (motorola
* MPC106), and uninorth
*
* Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au)
*
* Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
......@@ -256,21 +258,12 @@ init_bandit(struct pci_controller *bp)
rev = in_8(bp->cfg_data);
if (rev != BANDIT_REVID)
printk(KERN_WARNING
"Unknown revision %d for bandit at %08lx\n",
rev, bp->io_base_phys);
"Unknown revision %d for bandit\n", rev);
} else if (vendev != (BANDIT_DEVID_2 << 16) + PCI_VENDOR_ID_APPLE) {
printk(KERN_WARNING "bandit isn't? (%x)\n", vendev);
return;
}
/* read the revision id */
out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID);
udelay(2);
rev = in_8(bp->cfg_data);
if (rev != BANDIT_REVID)
printk(KERN_WARNING "Unknown revision %d for bandit at %08lx\n",
rev, bp->io_base_phys);
/* read the word at offset 0x50 */
out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC);
udelay(2);
......@@ -280,8 +273,7 @@ init_bandit(struct pci_controller *bp)
magic |= BANDIT_COHERENT;
udelay(2);
out_le32((volatile unsigned int *)bp->cfg_data, magic);
printk(KERN_INFO "Cache coherency enabled for bandit/PSX at %08lx\n",
bp->io_base_phys);
printk(KERN_INFO "Cache coherency enabled for bandit/PSX\n");
}
......@@ -490,26 +482,16 @@ pcibios_fixup_OF_interrupts(void)
{
struct pci_dev* dev;
pci_for_each_dev(dev)
{
/*
* Open Firmware often doesn't initialize the,
* Open Firmware often doesn't initialize the
* PCI_INTERRUPT_LINE config register properly, so we
* should find the device node and se if it has an
* AAPL,interrupts property.
* should find the device node and apply the interrupt
* obtained from the OF device-tree
*/
unsigned char pin;
struct device_node* node;
if (pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin) || !pin)
continue; /* No interrupt generated -> no fixup */
node = pci_device_to_OF_node(dev);
if (!node) {
printk("No OF node for device %x:%x\n", dev->bus->number, dev->devfn >> 3);
continue;
}
pci_for_each_dev(dev) {
struct device_node* node = pci_device_to_OF_node(dev);
/* this is the node, see if it has interrupts */
if (node->n_intrs > 0)
if (node && node->n_intrs > 0)
dev->irq = node->intrs[0].line;
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
}
......
/*
* BK Id: %F% %I% %G% %U% %#%
*/
/*
* Support for the interrupt controllers found on Power Macintosh,
* currently Apple's "Grand Central" interrupt controller in all
* it's incarnations. OpenPIC support used on newer machines is
* in a separate file
*
* Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au)
*
* Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
*/
#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/init.h>
......
......@@ -13,6 +13,8 @@
* Derived from "arch/alpha/kernel/setup.c"
* Copyright (C) 1995 Linus Torvalds
*
* Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
......@@ -106,9 +108,11 @@ extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
extern char pckbd_unexpected_up(unsigned char keycode);
extern int keyboard_sends_linux_keycodes;
extern void pmac_nvram_update(void);
extern unsigned char pmac_nvram_read_byte(int addr);
extern void pmac_nvram_write_byte(int addr, unsigned char val);
extern int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial);
extern void pmac_pcibios_after_init(void);
extern int of_show_percpuinfo(struct seq_file *m, int i);
extern kdev_t sd_find_target(void *host, int tgt);
......@@ -139,55 +143,22 @@ sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;
#ifdef CONFIG_SMP
extern struct smp_ops_t psurge_smp_ops;
extern struct smp_ops_t core99_smp_ops;
volatile static long int core99_l2_cache;
void __init
core99_init_l2(void)
{
int cpu = smp_processor_id();
if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR))
return;
if (cpu == 0){
core99_l2_cache = _get_L2CR();
printk("CPU0: L2CR is %lx\n", core99_l2_cache);
} else {
printk("CPU%d: L2CR was %lx\n", cpu, _get_L2CR());
_set_L2CR(0);
_set_L2CR(core99_l2_cache);
printk("CPU%d: L2CR set to %lx\n", cpu, core99_l2_cache);
}
}
#endif /* CONFIG_SMP */
/*
* Assume here that all clock rates are the same in a
* smp system. -- Cort
*/
int __openfirmware
of_show_percpuinfo(struct seq_file *m, int i)
{
struct device_node *cpu_node;
int *fp, s;
cpu_node = find_type_devices("cpu");
if (!cpu_node)
return 0;
for (s = 0; s < i && cpu_node->next; s++)
cpu_node = cpu_node->next;
fp = (int *) get_property(cpu_node, "clock-frequency", NULL);
if (fp)
seq_printf(m, "clock\t\t: %dMHz\n", *fp / 1000000);
return 0;
}
int __pmac
pmac_show_cpuinfo(struct seq_file *m)
{
struct device_node *np;
char *pp;
int plen;
int mbmodel = pmac_call_feature(PMAC_FTR_GET_MB_INFO,
NULL, PMAC_MB_INFO_MODEL, 0);
unsigned int mbflags = (unsigned int)pmac_call_feature(PMAC_FTR_GET_MB_INFO,
NULL, PMAC_MB_INFO_FLAGS, 0);
char* mbname;
if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME, (int)&mbname) != 0)
mbname = "Unknown";
/* find motherboard type */
seq_printf(m, "machine\t\t: ");
......@@ -212,6 +183,10 @@ pmac_show_cpuinfo(struct seq_file *m)
} else
seq_printf(m, "PowerMac\n");
/* print parsed model */
seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname);
seq_printf(m, "pmac flags\t: %08x\n", mbflags);
/* find l2 cache info */
np = find_devices("l2-cache");
if (np == 0)
......@@ -342,11 +317,6 @@ pmac_setup_arch(void)
ppc_override_l2cr_value, (ppc_override_l2cr_value & 0x80000000)
? "enabled" : "disabled");
#ifdef CONFIG_SMP
/* somewhat of a hack */
core99_init_l2();
#endif
#ifdef CONFIG_KGDB
zs_kgdb_hook(0);
#endif
......@@ -420,21 +390,6 @@ int boot_target;
int boot_part;
extern kdev_t boot_dev;
void __init
pmac_init2(void)
{
#ifdef CONFIG_ADB_PMU
via_pmu_start();
#endif
#ifdef CONFIG_ADB_CUDA
via_cuda_start();
#endif
#ifdef CONFIG_PMAC_PBOOK
media_bay_init();
#endif
pmac_feature_late_init();
}
#ifdef CONFIG_SCSI
void __init
note_scsi_host(struct device_node *node, void *host)
......@@ -736,7 +691,6 @@ pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.irq_cannonicalize = NULL;
ppc_md.init_IRQ = pmac_pic_init;
ppc_md.get_irq = pmac_get_irq; /* Changed later on ... */
ppc_md.init = pmac_init2;
ppc_md.pcibios_fixup = pmac_pcibios_fixup;
ppc_md.pcibios_enable_device_hook = pmac_pci_enable_device_hook;
......@@ -751,6 +705,11 @@ pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.get_rtc_time = pmac_get_rtc_time;
ppc_md.calibrate_decr = pmac_calibrate_decr;
#ifdef CONFIG_NVRAM
ppc_md.nvram_read_val = pmac_nvram_read_byte;
ppc_md.nvram_write_val = pmac_nvram_write_byte;
#endif
ppc_md.find_end_of_memory = pmac_find_end_of_memory;
ppc_md.feature_call = pmac_do_feature_call;
......
......@@ -105,8 +105,140 @@ static int psurge_type;
#define PSURGE_QUAD_COTTON 2
#define PSURGE_QUAD_ICEGRASS 3
/* l2 cache stuff for dual G4 macs */
extern void core99_init_l2(void);
volatile static long int core99_l2_cache;
volatile static long int core99_l3_cache;
static void __init
core99_init_caches(void)
{
int cpu = smp_processor_id();
if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR))
return;
if (cpu == 0){
core99_l2_cache = _get_L2CR();
printk("CPU0: L2CR is %lx\n", core99_l2_cache);
} else {
printk("CPU%d: L2CR was %lx\n", cpu, _get_L2CR());
_set_L2CR(0);
_set_L2CR(core99_l2_cache);
printk("CPU%d: L2CR set to %lx\n", cpu, core99_l2_cache);
}
if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR))
return;
if (cpu == 0){
core99_l3_cache = _get_L3CR();
printk("CPU0: L3CR is %lx\n", core99_l3_cache);
} else {
printk("CPU%d: L3CR was %lx\n", cpu, _get_L3CR());
_set_L3CR(0);
_set_L3CR(core99_l3_cache);
printk("CPU%d: L3CR set to %lx\n", cpu, core99_l3_cache);
}
}
/* Some CPU registers have to be saved from the first CPU and
* applied to others. Note that we override what is setup by
* the cputable intentionally.
*/
#define reg_hid0 0
#define reg_hid1 1
#define reg_msscr0 2
#define reg_msssr0 3
#define reg_ictrl 4
#define reg_ldstcr 5
#define reg_ldstdb 6
#define reg_count 7
static unsigned long cpu_regs[reg_count];
static void __pmac
cpu_setup_grab(void)
{
unsigned int pvers = mfspr(SPRN_PVR)>>16;
/* Read cache setting of CPU 0 */
core99_init_caches();
/* 7400/7410/7450 */
if (pvers == 0x8000 || pvers == 0x000c || pvers == 0x800c) {
cpu_regs[reg_hid0] = mfspr(SPRN_HID0);
cpu_regs[reg_msscr0] = mfspr(SPRN_MSSCR0);
cpu_regs[reg_msssr0] = mfspr(SPRN_MSSSR0);
}
/* 7450 only */
if (pvers == 0x8000) {
cpu_regs[reg_hid1] = mfspr(SPRN_HID1);
cpu_regs[reg_ictrl] = mfspr(SPRN_ICTRL);
cpu_regs[reg_ldstcr] = mfspr(SPRN_LDSTCR);
cpu_regs[reg_ldstdb] = mfspr(SPRN_LDSTDB);
}
flush_dcache_range((unsigned long)cpu_regs, (unsigned long)&cpu_regs[reg_count]);
}
static void __pmac
cpu_setup_apply(int cpu_nr)
{
unsigned int pvers = mfspr(SPRN_PVR)>>16;
/* Apply cache setting from CPU 0 */
core99_init_caches();
/* 7400/7410/7450 */
if (pvers == 0x8000 || pvers == 0x000c || pvers == 0x800c) {
unsigned long tmp;
__asm__ __volatile__ (
"lwz %0,4*"stringify(reg_hid0)"(%1)\n"
"sync\n"
"mtspr "stringify(SPRN_HID0)", %0\n"
"isync;sync\n"
"lwz %0, 4*"stringify(reg_msscr0)"(%1)\n"
"sync\n"
"mtspr "stringify(SPRN_MSSCR0)", %0\n"
"isync;sync\n"
// "lwz %0, "stringify(reg_msssr0)"(%1)\n"
// "sync\n"
// "mtspr "stringify(SPRN_MSSSR0)", %0\n"
// "isync;sync\n"
: "=&r" (tmp) : "r" (cpu_regs));
}
/* 7410 only */
if (pvers == 0x800c) {
unsigned long tmp;
__asm__ __volatile__ (
"li %0, 0\n"
"sync\n"
"mtspr "stringify(SPRN_L2CR2)", %0\n"
"isync;sync\n"
: "=&r" (tmp));
}
/* 7450 only */
if (pvers == 0x8000) {
unsigned long tmp;
__asm__ __volatile__ (
"lwz %0, 4*"stringify(reg_hid1)"(%1)\n"
"sync\n"
"mtspr "stringify(SPRN_HID1)", %0\n"
"isync;sync\n"
"lwz %0, 4*"stringify(reg_ictrl)"(%1)\n"
"sync\n"
"mtspr "stringify(SPRN_ICTRL)", %0\n"
"isync;sync\n"
"lwz %0, 4*"stringify(reg_ldstcr)"(%1)\n"
"sync\n"
"mtspr "stringify(SPRN_LDSTCR)", %0\n"
"isync;sync\n"
"lwz %0, 4*"stringify(reg_ldstdb)"(%1)\n"
"sync\n"
"mtspr "stringify(SPRN_LDSTDB)", %0\n"
"isync;sync\n"
: "=&r" (tmp) : "r" (cpu_regs));
}
}
/*
* Set and clear IPIs for powersurge.
......@@ -383,6 +515,7 @@ smp_core99_probe(void)
{
struct device_node *cpus;
int i, ncpus = 1;
extern int powersave_nap;
if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345);
cpus = find_type_devices("cpu");
......@@ -394,6 +527,8 @@ smp_core99_probe(void)
openpic_request_IPIs();
for (i = 1; i < ncpus; ++i)
smp_hw_index[i] = i;
powersave_nap = 0;
cpu_setup_grab();
}
return ncpus;
......@@ -404,17 +539,11 @@ smp_core99_kick_cpu(int nr)
{
unsigned long save_vector, new_vector;
unsigned long flags;
#if 1 /* New way... */
volatile unsigned long *vector
= ((volatile unsigned long *)(KERNELBASE+0x100));
if (nr < 1 || nr > 3)
return;
#else
volatile unsigned long *vector
= ((volatile unsigned long *)(KERNELBASE+0x500));
if (nr != 1)
return;
#endif
if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346);
local_irq_save(flags);
......@@ -463,13 +592,15 @@ smp_core99_kick_cpu(int nr)
static void __init
smp_core99_setup_cpu(int cpu_nr)
{
/* Setup some registers */
if (cpu_nr != 0)
cpu_setup_apply(cpu_nr);
/* Setup openpic */
do_openpic_setup_cpu();
/* Setup L2 */
if (cpu_nr != 0)
core99_init_l2();
else
/* Setup L2/L3 */
if (cpu_nr == 0)
if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349);
}
......
......@@ -67,6 +67,8 @@ extern struct cpu_spec *cur_cpu_spec[];
#define CPU_FTR_604_PERF_MON 0x00000080
#define CPU_FTR_601 0x00000100
#define CPU_FTR_HPTE_TABLE 0x00000200
#define CPU_FTR_CAN_NAP 0x00000400
#define CPU_FTR_L3CR 0x00000800
#ifdef __ASSEMBLY__
......
......@@ -25,7 +25,7 @@
* Bits in feature control register.
* Bits postfixed with a _N are in inverse logic
*/
#define HRW_RESET_SCC 0x00000001 /* actually controls transceiver... */
#define HRW_SCC_TRANS_EN_N 0x00000001 /* Also controls modem power */
#define HRW_BAY_POWER_N 0x00000002
#define HRW_BAY_PCI_ENABLE 0x00000004
#define HRW_BAY_IDE_ENABLE 0x00000008
......@@ -51,7 +51,7 @@
#define HRW_ARB_BYPASS 0x00400000 /* Disable internal PCI arbitrer */
#define HRW_IDE1_RESET_N 0x00800000 /* Media bay */
#define HRW_SLOW_SCC_PCLK 0x01000000 /* ??? (0) */
#define HRW_MODEM_POWER_N 0x02000000 /* Used by internal modem on wallstreet */
#define HRW_RESET_SCC 0x02000000
#define HRW_MFDC_CELL_ENABLE 0x04000000 /* ??? (0) */
#define HRW_USE_MFDC 0x08000000 /* ??? (0) */
#define HRW_BMAC_IO_ENABLE 0x60000000 /* two bits, not documented in OF */
......@@ -60,10 +60,6 @@
/* We OR those features at boot on desktop G3s */
#define HRW_DEFAULTS (HRW_SCCA_IO | HRW_SCCB_IO | HRW_SCC_ENABLE)
/* Those seem to be different on paddington */
#define PADD_MODEM_POWER_N 0x00000001 /* modem power on paddington */
#define PADD_RESET_SCC 0x02000000 /* check this please */
/* Looks like Heathrow has some sort of GPIOs as well... */
#define HRW_GPIO_MODEM_RESET 0x6d
......@@ -20,7 +20,6 @@
#define MB_POWER 6 /* media bay contains a Power device (???) */
#define MB_NO 7 /* media bay contains nothing */
void media_bay_init(void);
int check_media_bay(struct device_node *which_bay, int what);
int check_media_bay_by_base(unsigned long base, int what);
......
......@@ -38,9 +38,11 @@
*/
/* PowerSurge are the first generation of PCI Pmacs. This include
* all of the Grand-Central based machines
* all of the Grand-Central based machines. We currently don't
* differenciate most of them.
*/
#define PMAC_TYPE_PSURGE 0x10 /* PowerSurge */
#define PMAC_TYPE_ANS 0x11 /* Apple Network Server */
/* Here is the infamous serie of OHare based machines
*/
......@@ -84,6 +86,7 @@
#define PMAC_TYPE_PISMO 0x46 /* Pismo PowerBook */
#define PMAC_TYPE_TITANIUM 0x47 /* Titanium PowerBook */
#define PMAC_TYPE_TITANIUM2 0x48 /* Titanium II PowerBook */
#define PMAC_TYPE_TITANIUM3 0x49 /* Titanium III PowerBook (with L3) */
#define PMAC_TYPE_UNKNOWN_CORE99 0x5f
/* MacRISC2 machines based on the Pangea chipset
......@@ -245,7 +248,6 @@ static inline int pmac_call_feature(int selector, struct device_node* node,
/* Don't use those directly, they are for the sake of pmac_setup.c */
extern int pmac_do_feature_call(unsigned int selector, ...);
extern void pmac_feature_init(void);
extern void pmac_feature_late_init(void);
#define PMAC_FTR_DEF(x) ((_MACH_Pmac << 16) | (x))
......
......@@ -214,10 +214,11 @@
#define HID0_EBD (1<<28) /* Enable Bus Data Parity */
#define HID0_SBCLK (1<<27)
#define HID0_EICE (1<<26)
#define HID0_TBEN (1<<26) /* Timebase enable - 7450 */
#define HID0_TBEN (1<<26) /* Timebase enable - 745x */
#define HID0_ECLK (1<<25)
#define HID0_PAR (1<<24)
#define HID0_STEN (1<<24) /* S/W Tablewalk enable - 7450 */
#define HID0_STEN (1<<24) /* Software table search enable - 745x */
#define HID0_HIGH_BAT (1<<23) /* Enable high BATs - 7455 */
#define HID0_DOZE (1<<23)
#define HID0_NAP (1<<22)
#define HID0_SLEEP (1<<21)
......@@ -235,10 +236,10 @@
#define HID0_SGE (1<<7) /* Store Gathering Enable */
#define HID0_SIED (1<<7) /* Serial Instr. Execution [Disable] */
#define HID0_DFCA (1<<6) /* Data Cache Flush Assist */
#define HID0_LRSTK (1<<4) /* Link register stack - 745x */
#define HID0_BTIC (1<<5) /* Branch Target Instr Cache Enable */
#define HID0_LRSTK (1<<4) /* Link Stack enable - 7450 */
#define HID0_ABE (1<<3) /* Address Broadcast Enable */
#define HID0_FOLD (1<<3) /* Branch Folding enable - 7450 */
#define HID0_FOLD (1<<3) /* Branch Folding enable - 745x */
#define HID0_BHTE (1<<2) /* Branch History Table Enable */
#define HID0_BTCD (1<<1) /* Branch target cache disable */
#define HID0_NOPDST (1<<1) /* No-op dst, dstt, etc. instr. */
......@@ -308,6 +309,24 @@
#define SPRN_L2CR2 0x3f8
#define SPRN_L3CR 0x3FA /* Level 3 Cache Control Regsiter (7450) */
#define L3CR_L3E 0x80000000 /* L3 enable */
#define L3CR_L3PE 0x40000000 /* L3 data parity enable */
#define L3CR_L3APE 0x20000000 /* L3 addr parity enable */
#define L3CR_L3SIZ 0x10000000 /* L3 size */
#define L3CR_L3CLKEN 0x08000000 /* L3 clock enable */
#define L3CR_L3RES 0x04000000 /* L3 special reserved bit */
#define L3CR_L3CLKDIV 0x03800000 /* L3 clock divisor */
#define L3CR_L3IO 0x00400000 /* L3 instruction only */
#define L3CR_L3SPO 0x00040000 /* L3 sample point override */
#define L3CR_L3CKSP 0x00030000 /* L3 clock sample point */
#define L3CR_L3PSP 0x0000e000 /* L3 P-clock sample point */
#define L3CR_L3REP 0x00001000 /* L3 replacement algorithm */
#define L3CR_L3HWF 0x00000800 /* L3 hardware flush */
#define L3CR_L3I 0x00000400 /* L3 global invalidate */
#define L3CR_L3RT 0x00000300 /* L3 SRAM type */
#define L3CR_L3NIRCA 0x00000080 /* L3 non-integer ratio clock adj. */
#define L3CR_L3DO 0x00000040 /* L3 data only mode */
#define L3CR_PMEN 0x00000004 /* L3 private memory enable */
#define L3CR_PMSIZ 0x00000001 /* L3 private memory size */
#define SPRN_MSSCR0 0x3f6 /* Memory Subsystem Control Register 0 */
#define SPRN_MSSSR0 0x3f7 /* Memory Subsystem Status Register 1 */
#define SPRN_LDSTCR 0x3f8 /* Load/Store control register */
......@@ -471,6 +490,8 @@
#define SPRG7 SPRN_SPRG7
#define SRR0 SPRN_SRR0 /* Save and Restore Register 0 */
#define SRR1 SPRN_SRR1 /* Save and Restore Register 1 */
#define SRR2 SPRN_SRR2 /* Save and Restore Register 2 */
#define SRR3 SPRN_SRR3 /* Save and Restore Register 3 */
#define TBRL SPRN_TBRL /* Time Base Read Lower Register */
#define TBRU SPRN_TBRU /* Time Base Read Upper Register */
#define TBWL SPRN_TBWL /* Time Base Write Lower Register */
......
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