]> err.no Git - linux-2.6/blobdiff - arch/powerpc/platforms/powermac/feature.c
[PATCH] powerpc: Experimental support for new G5 Macs (#2)
[linux-2.6] / arch / powerpc / platforms / powermac / feature.c
index b2928bbe92279ef0bb286e45576049bb6b79550a..d2915d64d45e3613ec1ef57671b4208a57411f11 100644 (file)
@@ -101,7 +101,8 @@ static const char *macio_names[] =
        "Keylargo",
        "Pangea",
        "Intrepid",
-       "K2"
+       "K2",
+       "Shasta",
 };
 
 
@@ -119,7 +120,7 @@ static const char *macio_names[] =
 static struct device_node *uninorth_node;
 static u32 __iomem *uninorth_base;
 static u32 uninorth_rev;
-static int uninorth_u3;
+static int uninorth_maj;
 static void __iomem *u3_ht;
 
 /*
@@ -1399,8 +1400,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);
@@ -1445,20 +1453,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;
 }
@@ -1473,7 +1514,7 @@ static long g5_reset_cpu(struct device_node *node, long param, long value)
        struct device_node *np;
 
        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");
@@ -1512,7 +1553,8 @@ 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 */
 
@@ -2427,6 +2469,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,
@@ -2539,6 +2589,11 @@ 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;
@@ -2616,7 +2671,12 @@ static void __init probe_uninorth(void)
        /* Locate G5 u3 */
        if (uninorth_node == NULL) {
                uninorth_node = of_find_node_by_name(NULL, "u3");
-               uninorth_u3 = 1;
+               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)
                return;
@@ -2629,12 +2689,13 @@ static void __init probe_uninorth(void)
                return;
        uninorth_base = ioremap(address, 0x40000);
        uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
-       if (uninorth_u3)
+       if (uninorth_maj == 3 || uninorth_maj == 4)
                u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000);
 
-       printk(KERN_INFO "Found %s memory controller & host bridge,"
-              " revision: %d\n", uninorth_u3 ? "U3" : "UniNorth",
-              uninorth_rev);
+       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
@@ -2642,7 +2703,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);
        }
 
@@ -2650,7 +2712,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);
 }
 
@@ -2701,12 +2764,14 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ
                       node->full_name);
                return;
        }
-       if (type == macio_keylargo) {
+       if (type == macio_keylargo || type == macio_keylargo2) {
                u32 *did = (u32 *)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;
@@ -2805,7 +2870,8 @@ set_initial_features(void)
        }
 
 #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
@@ -2960,26 +3026,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)
 {