of: add 'of_' prefix to machine_is_compatible()
[safe/jmp/linux-2.6] / arch / powerpc / platforms / powermac / feature.c
index 2cba670..33e815f 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  arch/ppc/platforms/pmac_feature.c
- *
  *  Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au)
  *                          Ben. Herrenschmidt (benh@kernel.crashing.org)
  *
@@ -18,7 +16,6 @@
  *   - Split split split...
  *
  */
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -58,12 +55,11 @@ extern int powersave_lowspeed;
 extern int powersave_nap;
 extern struct device_node *k2_skiplist[2];
 
-
 /*
  * We use a single global lock to protect accesses. Each driver has
  * to take care of its own locking
  */
-static DEFINE_SPINLOCK(feature_lock);
+DEFINE_SPINLOCK(feature_lock);
 
 #define LOCK(flags)    spin_lock_irqsave(&feature_lock, flags);
 #define UNLOCK(flags)  spin_unlock_irqrestore(&feature_lock, flags);
@@ -101,26 +97,17 @@ static const char *macio_names[] =
        "Keylargo",
        "Pangea",
        "Intrepid",
-       "K2"
+       "K2",
+       "Shasta",
 };
 
 
+struct device_node *uninorth_node;
+u32 __iomem *uninorth_base;
 
-/*
- * Uninorth reg. access. Note that Uni-N regs are big endian
- */
-
-#define UN_REG(r)      (uninorth_base + ((r) >> 2))
-#define UN_IN(r)       (in_be32(UN_REG(r)))
-#define UN_OUT(r,v)    (out_be32(UN_REG(r), (v)))
-#define UN_BIS(r,v)    (UN_OUT((r), UN_IN(r) | (v)))
-#define UN_BIC(r,v)    (UN_OUT((r), UN_IN(r) & ~(v)))
-
-static struct device_node *uninorth_node;
-static u32 __iomem *uninorth_base;
 static u32 uninorth_rev;
-static int uninorth_u3;
-static void __iomem *u3_ht;
+static int uninorth_maj;
+static void __iomem *u3_ht_base;
 
 /*
  * For each motherboard family, we have a table of functions pointers
@@ -499,10 +486,6 @@ static long heathrow_sound_enable(struct device_node *node, long param,
 
 static u32 save_fcr[6];
 static u32 save_mbcr;
-static u32 save_gpio_levels[2];
-static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT];
-static u8 save_gpio_normal[KEYLARGO_GPIO_CNT];
-static u32 save_unin_clock_ctl;
 static struct dbdma_regs save_dbdma[13];
 static struct dbdma_regs save_alt_dbdma[13];
 
@@ -827,6 +810,7 @@ core99_ata100_enable(struct device_node *node, long value)
        unsigned long flags;
        struct pci_dev *pdev = NULL;
        u8 pbus, pid;
+       int rc;
 
        if (uninorth_rev < 0x24)
                return -ENODEV;
@@ -842,11 +826,15 @@ core99_ata100_enable(struct device_node *node, long value)
 
        if (value) {
                if (pci_device_from_OF_node(node, &pbus, &pid) == 0)
-                       pdev = pci_find_slot(pbus, pid);
+                       pdev = pci_get_bus_and_slot(pbus, pid);
                if (pdev == NULL)
                        return 0;
-               pci_enable_device(pdev);
-               pci_set_master(pdev);
+               rc = pci_enable_device(pdev);
+               if (rc == 0)
+                       pci_set_master(pdev);
+               pci_dev_put(pdev);
+               if (rc)
+                       return rc;
        }
        return 0;
 }
@@ -1058,6 +1046,7 @@ core99_reset_cpu(struct device_node *node, long param, long value)
        unsigned long flags;
        struct macio_chip *macio;
        struct device_node *np;
+       struct device_node *cpus;
        const int dflt_reset_lines[] = {        KL_GPIO_RESET_CPU0,
                                                KL_GPIO_RESET_CPU1,
                                                KL_GPIO_RESET_CPU2,
@@ -1067,12 +1056,12 @@ core99_reset_cpu(struct device_node *node, long param, long value)
        if (macio->type != macio_keylargo)
                return -ENODEV;
 
-       np = find_path_device("/cpus");
-       if (np == NULL)
+       cpus = of_find_node_by_path("/cpus");
+       if (cpus == NULL)
                return -ENODEV;
-       for (np = np->child; np != NULL; np = np->sibling) {
-               u32 *num = (u32 *)get_property(np, "reg", NULL);
-               u32 *rst = (u32 *)get_property(np, "soft-reset", NULL);
+       for (np = cpus->child; np != NULL; np = np->sibling) {
+               const u32 *num = of_get_property(np, "reg", NULL);
+               const u32 *rst = of_get_property(np, "soft-reset", NULL);
                if (num == NULL || rst == NULL)
                        continue;
                if (param == *num) {
@@ -1080,6 +1069,7 @@ core99_reset_cpu(struct device_node *node, long param, long value)
                        break;
                }
        }
+       of_node_put(cpus);
        if (np == NULL || reset_io == 0)
                reset_io = dflt_reset_lines[param];
 
@@ -1100,7 +1090,7 @@ core99_usb_enable(struct device_node *node, long param, long value)
 {
        struct macio_chip *macio;
        unsigned long flags;
-       char *prop;
+       const char *prop;
        int number;
        u32 reg;
 
@@ -1109,7 +1099,7 @@ core99_usb_enable(struct device_node *node, long param, long value)
            macio->type != macio_intrepid)
                return -ENODEV;
 
-       prop = (char *)get_property(node, "AAPL,clock-id", NULL);
+       prop = of_get_property(node, "AAPL,clock-id", NULL);
        if (!prop)
                return -ENODEV;
        if (strncmp(prop, "usb0u048", 8) == 0)
@@ -1399,8 +1389,15 @@ static long g5_fw_enable(struct device_node *node, long param, long value)
 static long g5_mpic_enable(struct device_node *node, long param, long value)
 {
        unsigned long flags;
+       struct device_node *parent = of_get_parent(node);
+       int is_u3;
 
-       if (node->parent == NULL || strcmp(node->parent->name, "u3"))
+       if (parent == NULL)
+               return 0;
+       is_u3 = strcmp(parent->name, "u3") == 0 ||
+               strcmp(parent->name, "u4") == 0;
+       of_node_put(parent);
+       if (!is_u3)
                return 0;
 
        LOCK(flags);
@@ -1423,7 +1420,7 @@ static long g5_eth_phy_reset(struct device_node *node, long param, long value)
        phy = of_get_next_child(node, NULL);
        if (!phy)
                return -ENODEV;
-       need_reset = device_is_compatible(phy, "B5221");
+       need_reset = of_device_is_compatible(phy, "B5221");
        of_node_put(phy);
        if (!need_reset)
                return 0;
@@ -1445,20 +1442,53 @@ static long g5_i2s_enable(struct device_node *node, long param, long value)
        /* Very crude implementation for now */
        struct macio_chip *macio = &macio_chips[0];
        unsigned long flags;
-
-       if (value == 0)
-               return 0; /* don't disable yet */
+       int cell;
+       u32 fcrs[3][3] = {
+               { 0,
+                 K2_FCR1_I2S0_CELL_ENABLE |
+                 K2_FCR1_I2S0_CLK_ENABLE_BIT | K2_FCR1_I2S0_ENABLE,
+                 KL3_I2S0_CLK18_ENABLE
+               },
+               { KL0_SCC_A_INTF_ENABLE,
+                 K2_FCR1_I2S1_CELL_ENABLE |
+                 K2_FCR1_I2S1_CLK_ENABLE_BIT | K2_FCR1_I2S1_ENABLE,
+                 KL3_I2S1_CLK18_ENABLE
+               },
+               { KL0_SCC_B_INTF_ENABLE,
+                 SH_FCR1_I2S2_CELL_ENABLE |
+                 SH_FCR1_I2S2_CLK_ENABLE_BIT | SH_FCR1_I2S2_ENABLE,
+                 SH_FCR3_I2S2_CLK18_ENABLE
+               },
+       };
+
+       if (macio->type != macio_keylargo2 && macio->type != macio_shasta)
+               return -ENODEV;
+       if (strncmp(node->name, "i2s-", 4))
+               return -ENODEV;
+       cell = node->name[4] - 'a';
+       switch(cell) {
+       case 0:
+       case 1:
+               break;
+       case 2:
+               if (macio->type == macio_shasta)
+                       break;
+       default:
+               return -ENODEV;
+       }
 
        LOCK(flags);
-       MACIO_BIS(KEYLARGO_FCR3, KL3_CLK45_ENABLE | KL3_CLK49_ENABLE |
-                 KL3_I2S0_CLK18_ENABLE);
-       udelay(10);
-       MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_I2S0_CELL_ENABLE |
-                 K2_FCR1_I2S0_CLK_ENABLE_BIT | K2_FCR1_I2S0_ENABLE);
+       if (value) {
+               MACIO_BIC(KEYLARGO_FCR0, fcrs[cell][0]);
+               MACIO_BIS(KEYLARGO_FCR1, fcrs[cell][1]);
+               MACIO_BIS(KEYLARGO_FCR3, fcrs[cell][2]);
+       } else {
+               MACIO_BIC(KEYLARGO_FCR3, fcrs[cell][2]);
+               MACIO_BIC(KEYLARGO_FCR1, fcrs[cell][1]);
+               MACIO_BIS(KEYLARGO_FCR0, fcrs[cell][0]);
+       }
        udelay(10);
-       MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_I2S0_RESET);
        UNLOCK(flags);
-       udelay(10);
 
        return 0;
 }
@@ -1471,17 +1501,18 @@ static long g5_reset_cpu(struct device_node *node, long param, long value)
        unsigned long flags;
        struct macio_chip *macio;
        struct device_node *np;
+       struct device_node *cpus;
 
        macio = &macio_chips[0];
-       if (macio->type != macio_keylargo2)
+       if (macio->type != macio_keylargo2 && macio->type != macio_shasta)
                return -ENODEV;
 
-       np = find_path_device("/cpus");
-       if (np == NULL)
+       cpus = of_find_node_by_path("/cpus");
+       if (cpus == NULL)
                return -ENODEV;
-       for (np = np->child; np != NULL; np = np->sibling) {
-               u32 *num = (u32 *)get_property(np, "reg", NULL);
-               u32 *rst = (u32 *)get_property(np, "soft-reset", NULL);
+       for (np = cpus->child; np != NULL; np = np->sibling) {
+               const u32 *num = of_get_property(np, "reg", NULL);
+               const u32 *rst = of_get_property(np, "soft-reset", NULL);
                if (num == NULL || rst == NULL)
                        continue;
                if (param == *num) {
@@ -1489,6 +1520,7 @@ static long g5_reset_cpu(struct device_node *node, long param, long value)
                        break;
                }
        }
+       of_node_put(cpus);
        if (np == NULL || reset_io == 0)
                return -ENODEV;
 
@@ -1512,14 +1544,21 @@ static long g5_reset_cpu(struct device_node *node, long param, long value)
  */
 void g5_phy_disable_cpu1(void)
 {
-       UN_OUT(U3_API_PHY_CONFIG_1, 0);
+       if (uninorth_maj == 3)
+               UN_OUT(U3_API_PHY_CONFIG_1, 0);
 }
 #endif /* CONFIG_POWER4 */
 
 #ifndef CONFIG_POWER4
 
-static void
-keylargo_shutdown(struct macio_chip *macio, int sleep_mode)
+
+#ifdef CONFIG_PM
+static u32 save_gpio_levels[2];
+static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT];
+static u8 save_gpio_normal[KEYLARGO_GPIO_CNT];
+static u32 save_unin_clock_ctl;
+
+static void keylargo_shutdown(struct macio_chip *macio, int sleep_mode)
 {
        u32 temp;
 
@@ -1572,8 +1611,7 @@ keylargo_shutdown(struct macio_chip *macio, int sleep_mode)
        (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
 }
 
-static void
-pangea_shutdown(struct macio_chip *macio, int sleep_mode)
+static void pangea_shutdown(struct macio_chip *macio, int sleep_mode)
 {
        u32 temp;
 
@@ -1606,8 +1644,7 @@ pangea_shutdown(struct macio_chip *macio, int sleep_mode)
        (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
 }
 
-static void
-intrepid_shutdown(struct macio_chip *macio, int sleep_mode)
+static void intrepid_shutdown(struct macio_chip *macio, int sleep_mode)
 {
        u32 temp;
 
@@ -1615,10 +1652,10 @@ intrepid_shutdown(struct macio_chip *macio, int sleep_mode)
                  KL0_SCC_CELL_ENABLE);
 
        MACIO_BIC(KEYLARGO_FCR1,
-                 /*KL1_USB2_CELL_ENABLE |*/
                KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
                KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
-               KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE);
+               KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
+               KL1_EIDE0_ENABLE);
        if (pmac_mb.board_flags & PMAC_MB_MOBILE)
                MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N);
 
@@ -1635,113 +1672,6 @@ intrepid_shutdown(struct macio_chip *macio, int sleep_mode)
 }
 
 
-void pmac_tweak_clock_spreading(int enable)
-{
-       struct macio_chip *macio = &macio_chips[0];
-
-       /* Hack for doing clock spreading on some machines PowerBooks and
-        * iBooks. This implements the "platform-do-clockspreading" OF
-        * property as decoded manually on various models. For safety, we also
-        * check the product ID in the device-tree in cases we'll whack the i2c
-        * chip to make reasonably sure we won't set wrong values in there
-        *
-        * Of course, ultimately, we have to implement a real parser for
-        * the platform-do-* stuff...
-        */
-
-       if (macio->type == macio_intrepid) {
-               if (enable)
-                       UN_OUT(UNI_N_CLOCK_SPREADING, 2);
-               else
-                       UN_OUT(UNI_N_CLOCK_SPREADING, 0);
-               mdelay(40);
-       }
-
-       while (machine_is_compatible("PowerBook5,2") ||
-              machine_is_compatible("PowerBook5,3") ||
-              machine_is_compatible("PowerBook6,2") ||
-              machine_is_compatible("PowerBook6,3")) {
-               struct device_node *ui2c = of_find_node_by_type(NULL, "i2c");
-               struct device_node *dt = of_find_node_by_name(NULL, "device-tree");
-               u8 buffer[9];
-               u32 *productID;
-               int i, rc, changed = 0;
-
-               if (dt == NULL)
-                       break;
-               productID = (u32 *)get_property(dt, "pid#", NULL);
-               if (productID == NULL)
-                       break;
-               while(ui2c) {
-                       struct device_node *p = of_get_parent(ui2c);
-                       if (p && !strcmp(p->name, "uni-n"))
-                               break;
-                       ui2c = of_find_node_by_type(ui2c, "i2c");
-               }
-               if (ui2c == NULL)
-                       break;
-               DBG("Trying to bump clock speed for PID: %08x...\n", *productID);
-               rc = pmac_low_i2c_open(ui2c, 1);
-               if (rc != 0)
-                       break;
-               pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
-               rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);
-               DBG("read result: %d,", rc);
-               if (rc != 0) {
-                       pmac_low_i2c_close(ui2c);
-                       break;
-               }
-               for (i=0; i<9; i++)
-                       DBG(" %02x", buffer[i]);
-               DBG("\n");
-
-               switch(*productID) {
-               case 0x1182:    /* AlBook 12" rev 2 */
-               case 0x1183:    /* iBook G4 12" */
-                       buffer[0] = (buffer[0] & 0x8f) | 0x70;
-                       buffer[2] = (buffer[2] & 0x7f) | 0x00;
-                       buffer[5] = (buffer[5] & 0x80) | 0x31;
-                       buffer[6] = (buffer[6] & 0x40) | 0xb0;
-                       buffer[7] = (buffer[7] & 0x00) | (enable ? 0xc0 : 0xba);
-                       buffer[8] = (buffer[8] & 0x00) | 0x30;
-                       changed = 1;
-                       break;
-               case 0x3142:    /* AlBook 15" (ATI M10) */
-               case 0x3143:    /* AlBook 17" (ATI M10) */
-                       buffer[0] = (buffer[0] & 0xaf) | 0x50;
-                       buffer[2] = (buffer[2] & 0x7f) | 0x00;
-                       buffer[5] = (buffer[5] & 0x80) | 0x31;
-                       buffer[6] = (buffer[6] & 0x40) | 0xb0;
-                       buffer[7] = (buffer[7] & 0x00) | (enable ? 0xd0 : 0xc0);
-                       buffer[8] = (buffer[8] & 0x00) | 0x30;
-                       changed = 1;
-                       break;
-               default:
-                       DBG("i2c-hwclock: Machine model not handled\n");
-                       break;
-               }
-               if (!changed) {
-                       pmac_low_i2c_close(ui2c);
-                       break;
-               }
-               pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_stdsub);
-               rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_write, 0x80, buffer, 9);
-               DBG("write result: %d,", rc);
-               pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
-               rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);
-               DBG("read result: %d,", rc);
-               if (rc != 0) {
-                       pmac_low_i2c_close(ui2c);
-                       break;
-               }
-               for (i=0; i<9; i++)
-                       DBG(" %02x", buffer[i]);
-               pmac_low_i2c_close(ui2c);
-               break;
-       }
-}
-
-
 static int
 core99_sleep(void)
 {
@@ -1898,6 +1828,8 @@ core99_wake_up(void)
        return 0;
 }
 
+#endif /* CONFIG_PM */
+
 static long
 core99_sleep_state(struct device_node *node, long param, long value)
 {
@@ -1919,10 +1851,13 @@ core99_sleep_state(struct device_node *node, long param, long value)
        if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
                return -EPERM;
 
+#ifdef CONFIG_PM
        if (value == 1)
                return core99_sleep();
        else if (value == 0)
                return core99_wake_up();
+
+#endif /* CONFIG_PM */
        return 0;
 }
 
@@ -2046,7 +1981,9 @@ static struct feature_table_entry core99_features[] = {
        { PMAC_FTR_USB_ENABLE,          core99_usb_enable },
        { PMAC_FTR_1394_ENABLE,         core99_firewire_enable },
        { PMAC_FTR_1394_CABLE_POWER,    core99_firewire_cable_power },
+#ifdef CONFIG_PM
        { PMAC_FTR_SLEEP_STATE,         core99_sleep_state },
+#endif
 #ifdef CONFIG_SMP
        { PMAC_FTR_RESET_CPU,           core99_reset_cpu },
 #endif /* CONFIG_SMP */
@@ -2252,7 +2189,7 @@ static struct pmac_mb_def pmac_mb_defs[] = {
        },
        {       "PowerMac10,1",                 "Mac mini",
                PMAC_TYPE_UNKNOWN_INTREPID,     intrepid_features,
-               PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER,
+               PMAC_MB_MAY_SLEEP,
        },
        {       "iMac,1",                       "iMac (first generation)",
                PMAC_TYPE_ORIG_IMAC,            paddington_features,
@@ -2362,6 +2299,14 @@ static struct pmac_mb_def pmac_mb_defs[] = {
                PMAC_TYPE_UNKNOWN_INTREPID,     intrepid_features,
                PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
        },
+       {       "PowerBook5,8",                 "PowerBook G4 15\"",
+               PMAC_TYPE_UNKNOWN_INTREPID,     intrepid_features,
+               PMAC_MB_MAY_SLEEP  | PMAC_MB_MOBILE,
+       },
+       {       "PowerBook5,9",                 "PowerBook G4 17\"",
+               PMAC_TYPE_UNKNOWN_INTREPID,     intrepid_features,
+               PMAC_MB_MAY_SLEEP | PMAC_MB_MOBILE,
+       },
        {       "PowerBook6,1",                 "PowerBook G4 12\"",
                PMAC_TYPE_UNKNOWN_INTREPID,     intrepid_features,
                PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
@@ -2382,6 +2327,10 @@ static struct pmac_mb_def pmac_mb_defs[] = {
                PMAC_TYPE_UNKNOWN_INTREPID,     intrepid_features,
                PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
        },
+       {       "PowerBook6,7",                 "iBook G4",
+               PMAC_TYPE_UNKNOWN_INTREPID,     intrepid_features,
+               PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
+       },
        {       "PowerBook6,8",                 "PowerBook G4 12\"",
                PMAC_TYPE_UNKNOWN_INTREPID,     intrepid_features,
                PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
@@ -2404,6 +2353,14 @@ static struct pmac_mb_def pmac_mb_defs[] = {
                PMAC_TYPE_POWERMAC_G5_U3L,      g5_features,
                0,
        },
+       {       "PowerMac11,2",                 "PowerMac G5 Dual Core",
+               PMAC_TYPE_POWERMAC_G5_U3L,      g5_features,
+               0,
+       },
+       {       "PowerMac12,1",                 "iMac G5 (iSight)",
+               PMAC_TYPE_POWERMAC_G5_U3L,      g5_features,
+               0,
+       },
        {       "RackMac3,1",                   "XServe G5",
                PMAC_TYPE_XSERVE_G5,            g5_features,
                0,
@@ -2453,22 +2410,23 @@ static int __init probe_motherboard(void)
        struct macio_chip *macio = &macio_chips[0];
        const char *model = NULL;
        struct device_node *dt;
+       int ret = 0;
 
        /* Lookup known motherboard type in device-tree. First try an
         * exact match on the "model" property, then try a "compatible"
         * match is none is found.
         */
-       dt = find_devices("device-tree");
+       dt = of_find_node_by_name(NULL, "device-tree");
        if (dt != NULL)
-               model = (const char *) get_property(dt, "model", NULL);
-       for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
+               model = of_get_property(dt, "model", NULL);
+       for(i=0; model && i<ARRAY_SIZE(pmac_mb_defs); i++) {
            if (strcmp(model, pmac_mb_defs[i].model_string) == 0) {
                pmac_mb = pmac_mb_defs[i];
                goto found;
            }
        }
-       for(i=0; i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
-           if (machine_is_compatible(pmac_mb_defs[i].model_string)) {
+       for(i=0; i<ARRAY_SIZE(pmac_mb_defs); i++) {
+           if (of_machine_is_compatible(pmac_mb_defs[i].model_string)) {
                pmac_mb = pmac_mb_defs[i];
                goto found;
            }
@@ -2516,17 +2474,25 @@ static int __init probe_motherboard(void)
                pmac_mb.model_name = "Unknown K2-based";
                pmac_mb.features = g5_features;
                break;
+       case macio_shasta:
+               pmac_mb.model_id = PMAC_TYPE_UNKNOWN_SHASTA;
+               pmac_mb.model_name = "Unknown Shasta-based";
+               pmac_mb.features = g5_features;
+               break;
 #endif /* CONFIG_POWER4 */
        default:
-               return -ENODEV;
+               ret = -ENODEV;
+               goto done;
        }
 found:
 #ifndef CONFIG_POWER4
        /* Fixup Hooper vs. Comet */
        if (pmac_mb.model_id == PMAC_TYPE_HOOPER) {
                u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4);
-               if (!mach_id_ptr)
-                       return -ENODEV;
+               if (!mach_id_ptr) {
+                       ret = -ENODEV;
+                       goto done;
+               }
                /* Here, I used to disable the media-bay on comet. It
                 * appears this is wrong, the floppy connector is actually
                 * a kind of media-bay and works with the current driver.
@@ -2535,9 +2501,7 @@ found:
                        pmac_mb.model_id = PMAC_TYPE_COMET;
                iounmap(mach_id_ptr);
        }
-#endif /* CONFIG_POWER4 */
 
-#ifdef CONFIG_6xx
        /* Set default value of powersave_nap on machines that support it.
         * It appears that uninorth rev 3 has a problem with it, we don't
         * enable it on those. In theory, the flush-on-lock property is
@@ -2545,20 +2509,28 @@ found:
         * that all Apple OF revs did it properly, I do it the paranoid way.
         */
        while (uninorth_base && uninorth_rev > 3) {
-               struct device_node *np = find_path_device("/cpus");
-               if (!np || !np->child) {
+               struct device_node *cpus = of_find_node_by_path("/cpus");
+               struct device_node *np;
+
+               if (!cpus || !cpus->child) {
                        printk(KERN_WARNING "Can't find CPU(s) in device tree !\n");
+                       of_node_put(cpus);
                        break;
                }
-               np = np->child;
+               np = cpus->child;
                /* Nap mode not supported on SMP */
-               if (np->sibling)
+               if (np->sibling) {
+                       of_node_put(cpus);
                        break;
+               }
                /* Nap mode not supported if flush-on-lock property is present */
-               if (get_property(np, "flush-on-lock", NULL))
+               if (of_get_property(np, "flush-on-lock", NULL)) {
+                       of_node_put(cpus);
                        break;
+               }
+               of_node_put(cpus);
                powersave_nap = 1;
-               printk(KERN_INFO "Processor NAP mode on idle enabled.\n");
+               printk(KERN_DEBUG "Processor NAP mode on idle enabled.\n");
                break;
        }
 
@@ -2566,10 +2538,11 @@ found:
         * NAP mode
         */
        powersave_lowspeed = 1;
-#endif /* CONFIG_6xx */
-#ifdef CONFIG_POWER4
+
+#else /* CONFIG_POWER4 */
        powersave_nap = 1;
-#endif
+#endif  /* CONFIG_POWER4 */
+
        /* Check for "mobile" machine */
        if (model && (strncmp(model, "PowerBook", 9) == 0
                   || strncmp(model, "iBook", 5) == 0))
@@ -2577,36 +2550,60 @@ found:
 
 
        printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name);
-       return 0;
+done:
+       of_node_put(dt);
+       return ret;
 }
 
 /* Initialize the Core99 UniNorth host bridge and memory controller
  */
 static void __init probe_uninorth(void)
 {
+       const u32 *addrp;
+       phys_addr_t address;
        unsigned long actrl;
 
        /* Locate core99 Uni-N */
        uninorth_node = of_find_node_by_name(NULL, "uni-n");
+       uninorth_maj = 1;
+
        /* Locate G5 u3 */
        if (uninorth_node == NULL) {
                uninorth_node = of_find_node_by_name(NULL, "u3");
-               uninorth_u3 = 1;
-       }
-       if (uninorth_node && uninorth_node->n_addrs > 0) {
-               unsigned long address = uninorth_node->addrs[0].address;
-               uninorth_base = ioremap(address, 0x40000);
-               uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
-               if (uninorth_u3)
-                       u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000);
-       } else
-               uninorth_node = NULL;
-
-       if (!uninorth_node)
+               uninorth_maj = 3;
+       }
+       /* Locate G5 u4 */
+       if (uninorth_node == NULL) {
+               uninorth_node = of_find_node_by_name(NULL, "u4");
+               uninorth_maj = 4;
+       }
+       if (uninorth_node == NULL) {
+               uninorth_maj = 0;
                return;
+       }
 
-       printk(KERN_INFO "Found %s memory controller & host bridge, revision: %d\n",
-              uninorth_u3 ? "U3" : "UniNorth", uninorth_rev);
+       addrp = of_get_property(uninorth_node, "reg", NULL);
+       if (addrp == NULL)
+               return;
+       address = of_translate_address(uninorth_node, addrp);
+       if (address == 0)
+               return;
+       uninorth_base = ioremap(address, 0x40000);
+       if (uninorth_base == NULL)
+               return;
+       uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
+       if (uninorth_maj == 3 || uninorth_maj == 4) {
+               u3_ht_base = ioremap(address + U3_HT_CONFIG_BASE, 0x1000);
+               if (u3_ht_base == NULL) {
+                       iounmap(uninorth_base);
+                       return;
+               }
+       }
+
+       printk(KERN_INFO "Found %s memory controller & host bridge"
+              " @ 0x%08x revision: 0x%02x\n", uninorth_maj == 3 ? "U3" :
+              uninorth_maj == 4 ? "U4" : "UniNorth",
+              (unsigned int)address, uninorth_rev);
        printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base);
 
        /* Set the arbitrer QAck delay according to what Apple does
@@ -2614,7 +2611,8 @@ static void __init probe_uninorth(void)
        if (uninorth_rev < 0x11) {
                actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK;
                actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 :
-                       UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
+                       UNI_N_ARB_CTRL_QACK_DELAY) <<
+                       UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
                UN_OUT(UNI_N_ARB_CTRL, actrl);
        }
 
@@ -2622,7 +2620,8 @@ static void __init probe_uninorth(void)
         * revs 1.5 to 2.O and Pangea. Seem to toggle the UniN Maxbus/PCI
         * memory timeout
         */
-       if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) || uninorth_rev == 0xc0)
+       if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) ||
+           uninorth_rev == 0xc0)
                UN_OUT(0x2160, UN_IN(0x2160) & 0x00ffffff);
 }
 
@@ -2630,18 +2629,17 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ
 {
        struct device_node*     node;
        int                     i;
-       volatile u32 __iomem *  base;
-       u32*                    revp;
+       volatile u32 __iomem    *base;
+       const u32               *addrp, *revp;
+       phys_addr_t             addr;
+       u64                     size;
 
-       node = find_devices(name);
-       if (!node || !node->n_addrs)
-               return;
-       if (compat)
-               do {
-                       if (device_is_compatible(node, compat))
-                               break;
-                       node = node->next;
-               } while (node);
+       for (node = NULL; (node = of_find_node_by_name(node, name)) != NULL;) {
+               if (!compat)
+                       break;
+               if (of_device_is_compatible(node, compat))
+                       break;
+       }
        if (!node)
                return;
        for(i=0; i<MAX_MACIO_CHIPS; i++) {
@@ -2650,29 +2648,45 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ
                if (macio_chips[i].of_node == node)
                        return;
        }
+
        if (i >= MAX_MACIO_CHIPS) {
                printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n");
                printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name);
                return;
        }
-       base = ioremap(node->addrs[0].address, node->addrs[0].size);
+       addrp = of_get_pci_address(node, 0, &size, NULL);
+       if (addrp == NULL) {
+               printk(KERN_ERR "pmac_feature: %s: can't find base !\n",
+                      node->full_name);
+               return;
+       }
+       addr = of_translate_address(node, addrp);
+       if (addr == 0) {
+               printk(KERN_ERR "pmac_feature: %s, can't translate base !\n",
+                      node->full_name);
+               return;
+       }
+       base = ioremap(addr, (unsigned long)size);
        if (!base) {
-               printk(KERN_ERR "pmac_feature: Can't map mac-io chip !\n");
+               printk(KERN_ERR "pmac_feature: %s, can't map mac-io chip !\n",
+                      node->full_name);
                return;
        }
-       if (type == macio_keylargo) {
-               u32 *did = (u32 *)get_property(node, "device-id", NULL);
+       if (type == macio_keylargo || type == macio_keylargo2) {
+               const u32 *did = of_get_property(node, "device-id", NULL);
                if (*did == 0x00000025)
                        type = macio_pangea;
                if (*did == 0x0000003e)
                        type = macio_intrepid;
+               if (*did == 0x0000004f)
+                       type = macio_shasta;
        }
        macio_chips[i].of_node  = node;
        macio_chips[i].type     = type;
        macio_chips[i].base     = base;
-       macio_chips[i].flags    = MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON;
+       macio_chips[i].flags    = MACIO_FLAG_SCCA_ON | MACIO_FLAG_SCCB_ON;
        macio_chips[i].name     = macio_names[type];
-       revp = (u32 *)get_property(node, "revision-id", NULL);
+       revp = of_get_property(node, "revision-id", NULL);
        if (revp)
                macio_chips[i].rev = *revp;
        printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n",
@@ -2715,19 +2729,19 @@ static void __init
 initial_serial_shutdown(struct device_node *np)
 {
        int len;
-       struct slot_names_prop {
+       const struct slot_names_prop {
                int     count;
                char    name[1];
        } *slots;
-       char *conn;
+       const char *conn;
        int port_type = PMAC_SCC_ASYNC;
        int modem = 0;
 
-       slots = (struct slot_names_prop *)get_property(np, "slot-names", &len);
-       conn = get_property(np, "AAPL,connector", &len);
+       slots = of_get_property(np, "slot-names", &len);
+       conn = of_get_property(np, "AAPL,connector", &len);
        if (conn && (strcmp(conn, "infrared") == 0))
                port_type = PMAC_SCC_IRDA;
-       else if (device_is_compatible(np, "cobalt"))
+       else if (of_device_is_compatible(np, "cobalt"))
                modem = 1;
        else if (slots && slots->count > 0) {
                if (strcmp(slots->name, "IrDA") == 0)
@@ -2752,19 +2766,22 @@ set_initial_features(void)
         * differenciate them all and since that hack was there for a long
         * time, I'll keep it around
         */
-       if (macio_chips[0].type == macio_ohare && !find_devices("via-pmu")) {
-               struct macio_chip *macio = &macio_chips[0];
-               MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES);
-       } else if (macio_chips[0].type == macio_ohare) {
+       if (macio_chips[0].type == macio_ohare) {
                struct macio_chip *macio = &macio_chips[0];
-               MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
+               np = of_find_node_by_name(NULL, "via-pmu");
+               if (np)
+                       MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
+               else
+                       MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES);
+               of_node_put(np);
        } else if (macio_chips[1].type == macio_ohare) {
                struct macio_chip *macio = &macio_chips[1];
                MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
        }
 
 #ifdef CONFIG_POWER4
-       if (macio_chips[0].type == macio_keylargo2) {
+       if (macio_chips[0].type == macio_keylargo2 ||
+           macio_chips[0].type == macio_shasta) {
 #ifndef CONFIG_SMP
                /* On SMP machines running UP, we have the second CPU eating
                 * bus cycles. We need to take it off the bus. This is done
@@ -2783,7 +2800,7 @@ set_initial_features(void)
                 */
                np = of_find_node_by_name(NULL, "ethernet");
                while(np) {
-                       if (device_is_compatible(np, "K2-GMAC"))
+                       if (of_device_is_compatible(np, "K2-GMAC"))
                                g5_gmac_enable(np, 0, 1);
                        np = of_find_node_by_name(np, "ethernet");
                }
@@ -2795,7 +2812,7 @@ set_initial_features(void)
                 */
                np = of_find_node_by_name(NULL, "firewire");
                while(np) {
-                       if (device_is_compatible(np, "pci106b,5811")) {
+                       if (of_device_is_compatible(np, "pci106b,5811")) {
                                macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
                                g5_fw_enable(np, 0, 1);
                        }
@@ -2813,8 +2830,8 @@ set_initial_features(void)
                np = of_find_node_by_name(NULL, "ethernet");
                while(np) {
                        if (np->parent
-                           && device_is_compatible(np->parent, "uni-north")
-                           && device_is_compatible(np, "gmac"))
+                           && of_device_is_compatible(np->parent, "uni-north")
+                           && of_device_is_compatible(np, "gmac"))
                                core99_gmac_enable(np, 0, 1);
                        np = of_find_node_by_name(np, "ethernet");
                }
@@ -2827,10 +2844,10 @@ set_initial_features(void)
                np = of_find_node_by_name(NULL, "firewire");
                while(np) {
                        if (np->parent
-                           && device_is_compatible(np->parent, "uni-north")
-                           && (device_is_compatible(np, "pci106b,18") ||
-                               device_is_compatible(np, "pci106b,30") ||
-                               device_is_compatible(np, "pci11c1,5811"))) {
+                           && of_device_is_compatible(np->parent, "uni-north")
+                           && (of_device_is_compatible(np, "pci106b,18") ||
+                               of_device_is_compatible(np, "pci106b,30") ||
+                               of_device_is_compatible(np, "pci11c1,5811"))) {
                                macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
                                core99_firewire_enable(np, 0, 1);
                        }
@@ -2841,22 +2858,21 @@ set_initial_features(void)
                np = of_find_node_by_name(NULL, "ata-6");
                while(np) {
                        if (np->parent
-                           && device_is_compatible(np->parent, "uni-north")
-                           && device_is_compatible(np, "kauai-ata")) {
+                           && of_device_is_compatible(np->parent, "uni-north")
+                           && of_device_is_compatible(np, "kauai-ata")) {
                                core99_ata100_enable(np, 1);
                        }
                        np = of_find_node_by_name(np, "ata-6");
                }
 
                /* Switch airport off */
-               np = find_devices("radio");
-               while(np) {
+               for_each_node_by_name(np, "radio") {
                        if (np && np->parent == macio_chips[0].of_node) {
                                macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON;
                                core99_airport_enable(np, 0, 0);
                        }
-                       np = np->next;
                }
+               of_node_put(np);
        }
 
        /* On all machines that support sound PM, switch sound off */
@@ -2873,25 +2889,15 @@ set_initial_features(void)
                MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
        }
 
-       /* Some machine models need the clock chip to be properly setup for
-        * clock spreading now. This should be a platform function but we
-        * don't do these at the moment
-        */
-       pmac_tweak_clock_spreading(1);
-
 #endif /* CONFIG_POWER4 */
 
        /* On all machines, switch modem & serial ports off */
-       np = find_devices("ch-a");
-       while(np) {
+       for_each_node_by_name(np, "ch-a")
                initial_serial_shutdown(np);
-               np = np->next;
-       }
-       np = find_devices("ch-b");
-       while(np) {
+       of_node_put(np);
+       for_each_node_by_name(np, "ch-b")
                initial_serial_shutdown(np);
-               np = np->next;
-       }
+       of_node_put(np);
 }
 
 void __init
@@ -2906,9 +2912,6 @@ pmac_feature_init(void)
                return;
        }
 
-       /* Setup low-level i2c stuffs */
-       pmac_init_low_i2c();
-
        /* Probe machine type */
        if (probe_motherboard())
                printk(KERN_WARNING "Unknown PowerMac !\n");
@@ -2919,26 +2922,6 @@ pmac_feature_init(void)
        set_initial_features();
 }
 
-int __init pmac_feature_late_init(void)
-{
-#if 0
-       struct device_node *np;
-
-       /* Request some resources late */
-       if (uninorth_node)
-               request_OF_resource(uninorth_node, 0, NULL);
-       np = find_devices("hammerhead");
-       if (np)
-               request_OF_resource(np, 0, NULL);
-       np = find_devices("interrupt-controller");
-       if (np)
-               request_OF_resource(np, 0, NULL);
-#endif
-       return 0;
-}
-
-device_initcall(pmac_feature_late_init);
-
 #if 0
 static void dump_HT_speeds(char *name, u32 cfg, u32 frq)
 {
@@ -2956,15 +2939,14 @@ static void dump_HT_speeds(char *name, u32 cfg, u32 frq)
 
 void __init pmac_check_ht_link(void)
 {
-#if 0 /* Disabled for now */
        u32     ufreq, freq, ucfg, cfg;
        struct device_node *pcix_node;
        u8      px_bus, px_devfn;
        struct pci_controller *px_hose;
 
-       (void)in_be32(u3_ht + U3_HT_LINK_COMMAND);
-       ucfg = cfg = in_be32(u3_ht + U3_HT_LINK_CONFIG);
-       ufreq = freq = in_be32(u3_ht + U3_HT_LINK_FREQ);
+       (void)in_be32(u3_ht_base + U3_HT_LINK_COMMAND);
+       ucfg = cfg = in_be32(u3_ht_base + U3_HT_LINK_CONFIG);
+       ufreq = freq = in_be32(u3_ht_base + U3_HT_LINK_FREQ);
        dump_HT_speeds("U3 HyperTransport", cfg, freq);
 
        pcix_node = of_find_compatible_node(NULL, "pci", "pci-x");
@@ -2987,10 +2969,8 @@ void __init pmac_check_ht_link(void)
        early_read_config_dword(px_hose, px_bus, px_devfn, 0xc8, &cfg);
        early_read_config_dword(px_hose, px_bus, px_devfn, 0xd0, &freq);
        dump_HT_speeds("PCI-X HT Downlink", cfg, freq);
-#endif
 }
-
-#endif /* CONFIG_POWER4 */
+#endif /* 0 */
 
 /*
  * Early video resume hook
@@ -3001,7 +2981,7 @@ static void *pmac_early_vresume_data;
 
 void pmac_set_early_video_resume(void (*proc)(void *data), void *data)
 {
-       if (_machine != _MACH_Pmac)
+       if (!machine_is(powermac))
                return;
        preempt_disable();
        pmac_early_vresume_proc = proc;
@@ -3060,3 +3040,8 @@ void pmac_resume_agp_for_card(struct pci_dev *dev)
        pmac_agp_resume(pmac_agp_bridge);
 }
 EXPORT_SYMBOL(pmac_resume_agp_for_card);
+
+int pmac_get_uninorth_variant(void)
+{
+       return uninorth_maj;
+}