]> git.hungrycats.org Git - linux/commitdiff
PPC32: powermac update from Ben Herrenschmidt.
authorPaul Mackerras <paulus@samba.org>
Fri, 10 May 2002 03:26:22 +0000 (13:26 +1000)
committerPaul Mackerras <paulus@samba.org>
Fri, 10 May 2002 03:26:22 +0000 (13:26 +1000)
This adds support for recent powermac models and fixes a few bugs.

17 files changed:
arch/ppc/kernel/cputable.c
arch/ppc/kernel/idle.c
arch/ppc/kernel/l2cr.S
arch/ppc/kernel/pci.c
arch/ppc/kernel/setup.c
arch/ppc/platforms/chrp_setup.c
arch/ppc/platforms/pmac_feature.c
arch/ppc/platforms/pmac_nvram.c
arch/ppc/platforms/pmac_pci.c
arch/ppc/platforms/pmac_pic.c
arch/ppc/platforms/pmac_setup.c
arch/ppc/platforms/pmac_smp.c
include/asm-ppc/cputable.h
include/asm-ppc/heathrow.h
include/asm-ppc/mediabay.h
include/asm-ppc/pmac_feature.h
include/asm-ppc/processor.h

index d6f8eccb3d76802564b5c03dbe37c910a1e8980f..329cfde5312e4dd6b380c0350cc043721857f338 100644 (file)
@@ -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,
index 846e5b83d41bfc0869ffa08e55cfe1278458f13f..30c2f797b47c2825f1f8e430202a90977132da68 100644 (file)
@@ -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
index b3ec25cca7031bc9ee8586c5931e6eda7fa30e1a..b5bdc1e18e23c1cd827b336685abaacc4607f4e4 100644 (file)
@@ -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 ---
  */
index 13ed868b0f0c76ab3d00fc052ea8d1f5cc3c028b..9be110830ebc3ab6c1a3ece74c58674ee01d272b 100644 (file)
@@ -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;
 
index 267a699a50f42d7bd2517887fc906b1c239e3a31..69099965ad552da403c788a99b471de885a1dc0d 100644 (file)
@@ -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)
 {
@@ -521,13 +542,34 @@ int __init ppc_setup_l2cr(char *str)
        if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR) {
                unsigned long val = simple_strtoul(str, NULL, 0);
                printk(KERN_INFO "l2cr set to %lx\n", val);
-                _set_L2CR(0);           /* force invalidate by disable cache */
-                _set_L2CR(val);         /* and enable it */
+               _set_L2CR(0);           /* force invalidate by disable cache */
+               _set_L2CR(val);         /* and enable it */
        }
        return 1;
 }
 __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 */
index da4a55fb7250af9065e41fe7223d573796c32287..85e2fd42d7a91aba43b9411e6e8499fd38143347 100644 (file)
@@ -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");
index ee134a1b84cf95b2d21ae8a7e697da3574833443..2bfeab37d7fadc6dd1662867e94245f945bb8702 100644 (file)
@@ -193,13 +193,14 @@ simple_feature_tweak(struct device_node* node, int type, int reg, u32 mask, int
 }
 
 static int __pmac
-generic_scc_enable(struct device_node* node, u32 enable_mask, u32 reset_mask,
-       int param, int value)
+ohare_htw_scc_enable(struct device_node* node, int param, int value)
 {
        struct macio_chip*      macio;
        unsigned long           chan_mask;
        unsigned long           fcr;
        unsigned long           flags;
+       int                     htw;
+       unsigned long           rmask;
        
        macio = macio_find(node, 0);
        if (!macio)
@@ -211,20 +212,32 @@ generic_scc_enable(struct device_node* node, u32 enable_mask, u32 reset_mask,
        else
                return -ENODEV;
 
+       htw = (macio->type == macio_heathrow || macio->type == macio_paddington
+               || macio->type == macio_gatwick);
        if (value) {
+#ifdef CONFIG_ADB_PMU
+               if ((param & 0xfff) == PMAC_SCC_IRDA)
+                       pmu_enable_irled(1);
+#endif /* CONFIG_ADB_PMU */            
                LOCK(flags);
                fcr = MACIO_IN32(OHARE_FCR);
                /* Check if scc cell need enabling */
                if (!(fcr & OH_SCC_ENABLE)) {
-                       fcr |= enable_mask;
-                       MACIO_OUT32(OHARE_FCR, fcr);
-                       fcr |= reset_mask;
-                       MACIO_OUT32(OHARE_FCR, fcr);
+                       fcr |= OH_SCC_ENABLE;
+                       if (htw) {
+                               fcr &= ~HRW_SCC_TRANS_EN_N;
+                               MACIO_OUT32(OHARE_FCR, fcr);
+                               fcr |= (rmask = HRW_RESET_SCC);
+                               MACIO_OUT32(OHARE_FCR, fcr);
+                       } else {
+                               fcr |= (rmask = OH_SCC_RESET);
+                               MACIO_OUT32(OHARE_FCR, fcr);
+                       }
                        UNLOCK(flags);
                        (void)MACIO_IN32(OHARE_FCR);
                        mdelay(15);
                        LOCK(flags);
-                       fcr &= ~reset_mask;
+                       fcr &= ~rmask;
                        MACIO_OUT32(OHARE_FCR, fcr);
                }
                if (chan_mask & MACIO_FLAG_SCCA_ON)
@@ -247,31 +260,20 @@ generic_scc_enable(struct device_node* node, u32 enable_mask, u32 reset_mask,
                        fcr &= ~OH_SCCB_IO;
                MACIO_OUT32(OHARE_FCR, fcr);
                if ((fcr & (OH_SCCA_IO | OH_SCCB_IO)) == 0) {
-                       fcr &= ~enable_mask;
+                       fcr &= ~OH_SCC_ENABLE;
+                       if (htw)
+                               fcr |= HRW_SCC_TRANS_EN_N;
                        MACIO_OUT32(OHARE_FCR, fcr);
                }
                macio->flags &= ~(chan_mask);
                UNLOCK(flags);
                mdelay(10);
-       }
-       return 0;
-}
-
-static int __pmac
-ohare_scc_enable(struct device_node* node, int param, int value)
-{
-       int rc;
-
 #ifdef CONFIG_ADB_PMU
-       if (value && (param & 0xfff) == PMAC_SCC_IRDA)
-               pmu_enable_irled(1);
+               if ((param & 0xfff) == PMAC_SCC_IRDA)
+                       pmu_enable_irled(0);
 #endif /* CONFIG_ADB_PMU */            
-       rc = generic_scc_enable(node, OH_SCC_ENABLE, OH_SCC_RESET, param, value);
-#ifdef CONFIG_ADB_PMU
-       if ((param & 0xfff) == PMAC_SCC_IRDA && (rc || !value))
-               pmu_enable_irled(0);
-#endif /* CONFIG_ADB_PMU */            
-       return rc;
+       }
+       return 0;
 }
 
 static int __pmac
@@ -340,27 +342,6 @@ ohare_sleep_state(struct device_node* node, int param, int value)
        return 0;
 }
 
-static int __pmac
-heathrow_scc_enable(struct device_node* node, int param, int value)
-{
-       int rc;
-       
-#ifdef CONFIG_ADB_PMU
-       if (value && param == PMAC_SCC_IRDA)
-               pmu_enable_irled(1);
-#endif /* CONFIG_ADB_PMU */            
-       /* Fixme: It's possible that wallstreet (heathrow) is different
-        * than other paddington machines. I still have to figure that
-        * out exactly, for now, the paddington values are used
-        */
-       rc = generic_scc_enable(node, HRW_SCC_ENABLE, PADD_RESET_SCC, param, value);
-#ifdef CONFIG_ADB_PMU
-       if (param == PMAC_SCC_IRDA && (rc || !value))
-               pmu_enable_irled(0);
-#endif /* CONFIG_ADB_PMU */            
-       return rc;
-}
-
 static int __pmac
 heathrow_modem_enable(struct device_node* node, int param, int value)
 {
@@ -382,16 +363,10 @@ heathrow_modem_enable(struct device_node* node, int param, int value)
        if (pmac_mb.model_id != PMAC_TYPE_YOSEMITE &&
            pmac_mb.model_id != PMAC_TYPE_YIKES) {
                LOCK(flags);
-               /* We use the paddington values as they seem to work properly
-                * on the wallstreet (heathrow) as well. I can't tell why we
-                * had to flip them on older feature.c, the fact is that new
-                * code uses the paddington values which are also the ones used
-                * in Darwin, and that works on wallstreet !
-                */
                if (value)
-                       MACIO_BIC(HEATHROW_FCR, PADD_MODEM_POWER_N);
+                       MACIO_BIC(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
                else
-                       MACIO_BIS(HEATHROW_FCR, PADD_MODEM_POWER_N);
+                       MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
                UNLOCK(flags);
                (void)MACIO_IN32(HEATHROW_FCR);
                mdelay(250);
@@ -400,17 +375,13 @@ heathrow_modem_enable(struct device_node* node, int param, int value)
                LOCK(flags);
                MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);
                (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
-               UNLOCK(flags);
-               mdelay(250);
-               LOCK(flags);
+               UNLOCK(flags); mdelay(250); LOCK(flags);
                MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio);
                (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
-               UNLOCK(flags);
-               mdelay(250);
-               LOCK(flags);
+               UNLOCK(flags); mdelay(250); LOCK(flags);
                MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);
                (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
-               UNLOCK(flags);
+               UNLOCK(flags); mdelay(250);
        }
        return 0;
 }
@@ -618,11 +589,14 @@ heathrow_sleep(struct macio_chip* macio, int secondary)
                /* This seems to be necessary as well or the fan
                 * keeps coming up and battery drains fast */
                MACIO_BIC(HEATHROW_FCR, HRW_IOBUS_ENABLE);
+               /* Make sure eth is down even if module or sleep
+                * won't work properly */
+               MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE | HRW_BMAC_RESET);
        }
        /* Make sure modem is shut down */
        MACIO_OUT8(HRW_GPIO_MODEM_RESET,
                MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1);
-       MACIO_BIS(HEATHROW_FCR, PADD_MODEM_POWER_N);
+       MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
        MACIO_BIC(HEATHROW_FCR, OH_SCCA_IO|OH_SCCB_IO|HRW_SCC_ENABLE);
 
        /* Let things settle */
@@ -814,7 +788,7 @@ core99_modem_enable(struct device_node* node, int param, int value)
                UNLOCK(flags); mdelay(250); LOCK(flags);
                MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
                (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
-               UNLOCK(flags); mdelay(250); LOCK(flags);
+               UNLOCK(flags); mdelay(250);
        }
        return 0;
 }
@@ -1471,7 +1445,7 @@ pangea_modem_enable(struct device_node* node, int param, int value)
                UNLOCK(flags); mdelay(250); LOCK(flags);
                MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
                (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
-               UNLOCK(flags); mdelay(250); LOCK(flags);
+               UNLOCK(flags); mdelay(250);
        }
        return 0;
 }
@@ -1487,7 +1461,8 @@ generic_get_mb_info(struct device_node* node, int param, int value)
                        return pmac_mb.board_flags;
                case PMAC_MB_INFO_NAME: 
                        /* hack hack hack... but should work */
-                       return (int)pmac_mb.model_name;
+                       *((const char **)value) = pmac_mb.model_name;
+                       break;
        }
        return 0;
 }
@@ -1509,7 +1484,7 @@ static struct feature_table_entry any_features[]  __pmacdata = {
  * to have issues with turning on/off those asic cells
  */
 static struct feature_table_entry ohare_features[]  __pmacdata = {
-       { PMAC_FTR_SCC_ENABLE,          ohare_scc_enable },
+       { PMAC_FTR_SCC_ENABLE,          ohare_htw_scc_enable },
        { PMAC_FTR_SWIM3_ENABLE,        ohare_floppy_enable },
        { PMAC_FTR_MESH_ENABLE,         ohare_mesh_enable },
        { PMAC_FTR_IDE_ENABLE,          ohare_ide_enable},
@@ -1535,7 +1510,7 @@ static struct feature_table_entry heathrow_desktop_features[]  __pmacdata = {
  * powerbooks.
  */
 static struct feature_table_entry heathrow_laptop_features[]  __pmacdata = {
-       { PMAC_FTR_SCC_ENABLE,          heathrow_scc_enable },
+       { PMAC_FTR_SCC_ENABLE,          ohare_htw_scc_enable },
        { PMAC_FTR_MODEM_ENABLE,        heathrow_modem_enable },
        { PMAC_FTR_SWIM3_ENABLE,        heathrow_floppy_enable },
        { PMAC_FTR_MESH_ENABLE,         heathrow_mesh_enable },
@@ -1551,7 +1526,7 @@ static struct feature_table_entry heathrow_laptop_features[]  __pmacdata = {
  * The lombard (101) powerbook, first iMac models, B&W G3 and Yikes G4.
  */
 static struct feature_table_entry paddington_features[]  __pmacdata = {
-       { PMAC_FTR_SCC_ENABLE,          heathrow_scc_enable },
+       { PMAC_FTR_SCC_ENABLE,          ohare_htw_scc_enable },
        { PMAC_FTR_MODEM_ENABLE,        heathrow_modem_enable },
        { PMAC_FTR_SWIM3_ENABLE,        heathrow_floppy_enable },
        { PMAC_FTR_MESH_ENABLE,         heathrow_mesh_enable },
@@ -1625,6 +1600,10 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
                PMAC_TYPE_PSURGE,               NULL,
                0
        },
+       {       "AAPL,ShinerESB",               "Apple Network Server",
+               PMAC_TYPE_ANS,                  NULL,
+               0
+       },
        {       "AAPL,e407",                    "Alchemy",
                PMAC_TYPE_ALCHEMY,              NULL,
                0
@@ -1665,6 +1644,10 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
                PMAC_TYPE_PANGEA_IMAC,          pangea_features,
                PMAC_MB_CAN_SLEEP
        },
+       {       "PowerBook4,2",                 "iBook 2 with 14\" LCD",
+               PMAC_TYPE_IBOOK2,               pangea_features,
+               PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
+       },
        {       "PowerBook4,1",                 "iBook 2",
                PMAC_TYPE_IBOOK2,               pangea_features,
                PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
@@ -1732,6 +1715,10 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
                PMAC_TYPE_TITANIUM2,            core99_features,
                PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
        },
+       {       "PowerBook3,4",                 "PowerBook Titanium III",
+               PMAC_TYPE_TITANIUM3,            core99_features,
+               PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
+       },
 };
 
 /*
@@ -1745,13 +1732,12 @@ pmac_do_feature_call(unsigned int selector, ...)
        feature_call func = NULL;
        va_list args;
        
-       if (!pmac_mb.features)
-               return -ENODEV;
-       for (i=0; pmac_mb.features[i].function; i++)
-               if (pmac_mb.features[i].selector == selector) {
-                       func = pmac_mb.features[i].function;
-                       break;
-               }
+       if (pmac_mb.features)
+               for (i=0; pmac_mb.features[i].function; i++)
+                       if (pmac_mb.features[i].selector == selector) {
+                               func = pmac_mb.features[i].function;
+                               break;
+                       }
        if (!func)
                for (i=0; any_features[i].function; i++)
                        if (any_features[i].selector == selector) {
@@ -2070,11 +2056,21 @@ set_initial_features(void)
                }
        }
 
-       /* On all machines, switch sound off */
+       /* On all machines that support sound PM, switch sound off */
        if (macio_chips[0].of_node)
                pmac_do_feature_call(PMAC_FTR_SOUND_CHIP_ENABLE,
                        macio_chips[0].of_node, 0, 0);
 
+       /* While on some desktop G3s, we turn it back on */
+       if (macio_chips[0].of_node && macio_chips[0].type == macio_heathrow
+               && (pmac_mb.model_id == PMAC_TYPE_GOSSAMER ||
+                   pmac_mb.model_id == PMAC_TYPE_SILK)) {
+               struct macio_chip* macio = &macio_chips[0];
+               MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
+               MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
+       }
+
+
        /* On all machines, switch modem & serial ports off */
        np = find_devices("ch-a");
        while(np) {
@@ -2113,7 +2109,7 @@ pmac_feature_init(void)
        set_initial_features();
 }
 
-void __init
+int __init
 pmac_feature_late_init(void)
 {
        struct device_node* np;
@@ -2127,4 +2123,7 @@ pmac_feature_late_init(void)
        np = find_devices("interrupt-controller");
        if (np)
                request_OF_resource(np, 0, NULL);
+       return 0;
 }
+
+device_initcall(pmac_feature_late_init);
index fc59a82f79b4eefc865957629f002376379a5c5a..eebac822e7095e8b9c3111da6bcd4b4b686019ce 100644 (file)
@@ -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);
 }
index 33e6f4e54fb6909e61a59101944ef57e2e64178b..ae83bda20b47e88fa4e69f13c8c6dee2b5b6eb54 100644 (file)
@@ -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,
-                * PCI_INTERRUPT_LINE config register properly, so we
-                * should find the device node and se if it has an
-                * AAPL,interrupts property.
-                */
-               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;
-               }
+       /*
+        * Open Firmware often doesn't initialize the
+        * PCI_INTERRUPT_LINE config register properly, so we
+        * should find the device node and apply the interrupt
+        * obtained from the OF device-tree
+        */
+       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);
        }
index a2e1ecf02fd07dc107da776c294f10be43614ff4..afb8c61eb554cb8874850e7b86ba9c5a883d5d3c 100644 (file)
@@ -1,6 +1,23 @@
 /*
  * 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>
index 1f6b23d8651f8e5ee0dfafa16d76adb48492ac80..1bef730ffbe2e4241c55d4261a19aad73635f457 100644 (file)
@@ -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,56 +143,23 @@ 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: ");
        np = find_devices("device-tree");
@@ -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)
@@ -341,11 +316,6 @@ pmac_setup_arch(void)
                printk(KERN_INFO "L2CR overriden (0x%x), backside cache is %s\n",
                        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);
@@ -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;
index 0adbc8e263abe165b5e78bd8b71cdacbc69db153..2b7fb4456f99aaff8eef29d6a8caf982285fd950 100644 (file)
@@ -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);
 }
 
index e8861a61f88f5232a0a041aaf5243e42669c1b7c..2df2962f6ced9ac07480de99555f6527bee07874 100644 (file)
@@ -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__
 
index 9b202255e51fe71b63567c2f1ebf226568d912f8..e393fd2d2cd5323a37250cb0f85d88ea61c48e89 100644 (file)
@@ -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 */
 /* 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
 
index ee700af0ede3c34735cded0330992f509141db38..653279302c5c0eff1ea927d6a1f799884be40899 100644 (file)
@@ -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);
 
index 3670cde23854974a1ecfcf354825b8715359e436..712aea7aeef3e65c793fd0b347f0269bf74333f2 100644 (file)
  */
 
 /* 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))
 
index 27cf6dc42ed11f5b50ffc4d55f48724164f8cdf1..5470864acb7338f13de016d0dafe98a0651ecd7f 100644 (file)
 #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)
 #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. */
 #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 */
 #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 */