diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2005-12-13 21:10:10 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-01-08 23:03:17 -0500 |
commit | 1beb6a7d6cbed3ac03500ce9b5b9bb632c512039 (patch) | |
tree | 727aa76da5a82fca449dadf3cebbadc414ad6555 /arch/powerpc/platforms/powermac/feature.c | |
parent | cd0c7f06803be06a5cf4564aa5a900f4b6aea603 (diff) |
[PATCH] powerpc: Experimental support for new G5 Macs (#2)
This adds some very basic support for the new machines, including the
Quad G5 (tested), and other new dual core based machines and iMac G5
iSight (untested). This is still experimental ! There is no thermal
control yet, there is no proper handing of MSIs, etc.. but it
boots, I have all 4 cores up on my machine. Compared to the previous
version of this patch, this one adds DART IOMMU support for the U4
chipset and thus should work fine on setups with more than 2Gb of RAM.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/powermac/feature.c')
-rw-r--r-- | arch/powerpc/platforms/powermac/feature.c | 65 |
1 files changed, 48 insertions, 17 deletions
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index b1f896952b1b..d2915d64d45e 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c | |||
@@ -101,7 +101,8 @@ static const char *macio_names[] = | |||
101 | "Keylargo", | 101 | "Keylargo", |
102 | "Pangea", | 102 | "Pangea", |
103 | "Intrepid", | 103 | "Intrepid", |
104 | "K2" | 104 | "K2", |
105 | "Shasta", | ||
105 | }; | 106 | }; |
106 | 107 | ||
107 | 108 | ||
@@ -119,7 +120,7 @@ static const char *macio_names[] = | |||
119 | static struct device_node *uninorth_node; | 120 | static struct device_node *uninorth_node; |
120 | static u32 __iomem *uninorth_base; | 121 | static u32 __iomem *uninorth_base; |
121 | static u32 uninorth_rev; | 122 | static u32 uninorth_rev; |
122 | static int uninorth_u3; | 123 | static int uninorth_maj; |
123 | static void __iomem *u3_ht; | 124 | static void __iomem *u3_ht; |
124 | 125 | ||
125 | /* | 126 | /* |
@@ -1399,8 +1400,15 @@ static long g5_fw_enable(struct device_node *node, long param, long value) | |||
1399 | static long g5_mpic_enable(struct device_node *node, long param, long value) | 1400 | static long g5_mpic_enable(struct device_node *node, long param, long value) |
1400 | { | 1401 | { |
1401 | unsigned long flags; | 1402 | unsigned long flags; |
1403 | struct device_node *parent = of_get_parent(node); | ||
1404 | int is_u3; | ||
1402 | 1405 | ||
1403 | if (node->parent == NULL || strcmp(node->parent->name, "u3")) | 1406 | if (parent == NULL) |
1407 | return 0; | ||
1408 | is_u3 = strcmp(parent->name, "u3") == 0 || | ||
1409 | strcmp(parent->name, "u4") == 0; | ||
1410 | of_node_put(parent); | ||
1411 | if (!is_u3) | ||
1404 | return 0; | 1412 | return 0; |
1405 | 1413 | ||
1406 | LOCK(flags); | 1414 | LOCK(flags); |
@@ -1464,7 +1472,7 @@ static long g5_i2s_enable(struct device_node *node, long param, long value) | |||
1464 | }, | 1472 | }, |
1465 | }; | 1473 | }; |
1466 | 1474 | ||
1467 | if (macio->type != macio_keylargo2 /* && macio->type != macio_shasta*/) | 1475 | if (macio->type != macio_keylargo2 && macio->type != macio_shasta) |
1468 | return -ENODEV; | 1476 | return -ENODEV; |
1469 | if (strncmp(node->name, "i2s-", 4)) | 1477 | if (strncmp(node->name, "i2s-", 4)) |
1470 | return -ENODEV; | 1478 | return -ENODEV; |
@@ -1473,11 +1481,9 @@ static long g5_i2s_enable(struct device_node *node, long param, long value) | |||
1473 | case 0: | 1481 | case 0: |
1474 | case 1: | 1482 | case 1: |
1475 | break; | 1483 | break; |
1476 | #if 0 | ||
1477 | case 2: | 1484 | case 2: |
1478 | if (macio->type == macio_shasta) | 1485 | if (macio->type == macio_shasta) |
1479 | break; | 1486 | break; |
1480 | #endif | ||
1481 | default: | 1487 | default: |
1482 | return -ENODEV; | 1488 | return -ENODEV; |
1483 | } | 1489 | } |
@@ -1508,7 +1514,7 @@ static long g5_reset_cpu(struct device_node *node, long param, long value) | |||
1508 | struct device_node *np; | 1514 | struct device_node *np; |
1509 | 1515 | ||
1510 | macio = &macio_chips[0]; | 1516 | macio = &macio_chips[0]; |
1511 | if (macio->type != macio_keylargo2) | 1517 | if (macio->type != macio_keylargo2 && macio->type != macio_shasta) |
1512 | return -ENODEV; | 1518 | return -ENODEV; |
1513 | 1519 | ||
1514 | np = find_path_device("/cpus"); | 1520 | np = find_path_device("/cpus"); |
@@ -1547,7 +1553,8 @@ static long g5_reset_cpu(struct device_node *node, long param, long value) | |||
1547 | */ | 1553 | */ |
1548 | void g5_phy_disable_cpu1(void) | 1554 | void g5_phy_disable_cpu1(void) |
1549 | { | 1555 | { |
1550 | UN_OUT(U3_API_PHY_CONFIG_1, 0); | 1556 | if (uninorth_maj == 3) |
1557 | UN_OUT(U3_API_PHY_CONFIG_1, 0); | ||
1551 | } | 1558 | } |
1552 | #endif /* CONFIG_POWER4 */ | 1559 | #endif /* CONFIG_POWER4 */ |
1553 | 1560 | ||
@@ -2462,6 +2469,14 @@ static struct pmac_mb_def pmac_mb_defs[] = { | |||
2462 | PMAC_TYPE_POWERMAC_G5_U3L, g5_features, | 2469 | PMAC_TYPE_POWERMAC_G5_U3L, g5_features, |
2463 | 0, | 2470 | 0, |
2464 | }, | 2471 | }, |
2472 | { "PowerMac11,2", "PowerMac G5 Dual Core", | ||
2473 | PMAC_TYPE_POWERMAC_G5_U3L, g5_features, | ||
2474 | 0, | ||
2475 | }, | ||
2476 | { "PowerMac12,1", "iMac G5 (iSight)", | ||
2477 | PMAC_TYPE_POWERMAC_G5_U3L, g5_features, | ||
2478 | 0, | ||
2479 | }, | ||
2465 | { "RackMac3,1", "XServe G5", | 2480 | { "RackMac3,1", "XServe G5", |
2466 | PMAC_TYPE_XSERVE_G5, g5_features, | 2481 | PMAC_TYPE_XSERVE_G5, g5_features, |
2467 | 0, | 2482 | 0, |
@@ -2574,6 +2589,11 @@ static int __init probe_motherboard(void) | |||
2574 | pmac_mb.model_name = "Unknown K2-based"; | 2589 | pmac_mb.model_name = "Unknown K2-based"; |
2575 | pmac_mb.features = g5_features; | 2590 | pmac_mb.features = g5_features; |
2576 | break; | 2591 | break; |
2592 | case macio_shasta: | ||
2593 | pmac_mb.model_id = PMAC_TYPE_UNKNOWN_SHASTA; | ||
2594 | pmac_mb.model_name = "Unknown Shasta-based"; | ||
2595 | pmac_mb.features = g5_features; | ||
2596 | break; | ||
2577 | #endif /* CONFIG_POWER4 */ | 2597 | #endif /* CONFIG_POWER4 */ |
2578 | default: | 2598 | default: |
2579 | return -ENODEV; | 2599 | return -ENODEV; |
@@ -2651,7 +2671,12 @@ static void __init probe_uninorth(void) | |||
2651 | /* Locate G5 u3 */ | 2671 | /* Locate G5 u3 */ |
2652 | if (uninorth_node == NULL) { | 2672 | if (uninorth_node == NULL) { |
2653 | uninorth_node = of_find_node_by_name(NULL, "u3"); | 2673 | uninorth_node = of_find_node_by_name(NULL, "u3"); |
2654 | uninorth_u3 = 1; | 2674 | uninorth_maj = 3; |
2675 | } | ||
2676 | /* Locate G5 u4 */ | ||
2677 | if (uninorth_node == NULL) { | ||
2678 | uninorth_node = of_find_node_by_name(NULL, "u4"); | ||
2679 | uninorth_maj = 4; | ||
2655 | } | 2680 | } |
2656 | if (uninorth_node == NULL) | 2681 | if (uninorth_node == NULL) |
2657 | return; | 2682 | return; |
@@ -2664,12 +2689,13 @@ static void __init probe_uninorth(void) | |||
2664 | return; | 2689 | return; |
2665 | uninorth_base = ioremap(address, 0x40000); | 2690 | uninorth_base = ioremap(address, 0x40000); |
2666 | uninorth_rev = in_be32(UN_REG(UNI_N_VERSION)); | 2691 | uninorth_rev = in_be32(UN_REG(UNI_N_VERSION)); |
2667 | if (uninorth_u3) | 2692 | if (uninorth_maj == 3 || uninorth_maj == 4) |
2668 | u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000); | 2693 | u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000); |
2669 | 2694 | ||
2670 | printk(KERN_INFO "Found %s memory controller & host bridge," | 2695 | printk(KERN_INFO "Found %s memory controller & host bridge" |
2671 | " revision: %d\n", uninorth_u3 ? "U3" : "UniNorth", | 2696 | " @ 0x%08x revision: 0x%02x\n", uninorth_maj == 3 ? "U3" : |
2672 | uninorth_rev); | 2697 | uninorth_maj == 4 ? "U4" : "UniNorth", |
2698 | (unsigned int)address, uninorth_rev); | ||
2673 | printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base); | 2699 | printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base); |
2674 | 2700 | ||
2675 | /* Set the arbitrer QAck delay according to what Apple does | 2701 | /* Set the arbitrer QAck delay according to what Apple does |
@@ -2677,7 +2703,8 @@ static void __init probe_uninorth(void) | |||
2677 | if (uninorth_rev < 0x11) { | 2703 | if (uninorth_rev < 0x11) { |
2678 | actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK; | 2704 | actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK; |
2679 | actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 : | 2705 | actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 : |
2680 | UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT; | 2706 | UNI_N_ARB_CTRL_QACK_DELAY) << |
2707 | UNI_N_ARB_CTRL_QACK_DELAY_SHIFT; | ||
2681 | UN_OUT(UNI_N_ARB_CTRL, actrl); | 2708 | UN_OUT(UNI_N_ARB_CTRL, actrl); |
2682 | } | 2709 | } |
2683 | 2710 | ||
@@ -2685,7 +2712,8 @@ static void __init probe_uninorth(void) | |||
2685 | * revs 1.5 to 2.O and Pangea. Seem to toggle the UniN Maxbus/PCI | 2712 | * revs 1.5 to 2.O and Pangea. Seem to toggle the UniN Maxbus/PCI |
2686 | * memory timeout | 2713 | * memory timeout |
2687 | */ | 2714 | */ |
2688 | if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) || uninorth_rev == 0xc0) | 2715 | if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) || |
2716 | uninorth_rev == 0xc0) | ||
2689 | UN_OUT(0x2160, UN_IN(0x2160) & 0x00ffffff); | 2717 | UN_OUT(0x2160, UN_IN(0x2160) & 0x00ffffff); |
2690 | } | 2718 | } |
2691 | 2719 | ||
@@ -2736,12 +2764,14 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ | |||
2736 | node->full_name); | 2764 | node->full_name); |
2737 | return; | 2765 | return; |
2738 | } | 2766 | } |
2739 | if (type == macio_keylargo) { | 2767 | if (type == macio_keylargo || type == macio_keylargo2) { |
2740 | u32 *did = (u32 *)get_property(node, "device-id", NULL); | 2768 | u32 *did = (u32 *)get_property(node, "device-id", NULL); |
2741 | if (*did == 0x00000025) | 2769 | if (*did == 0x00000025) |
2742 | type = macio_pangea; | 2770 | type = macio_pangea; |
2743 | if (*did == 0x0000003e) | 2771 | if (*did == 0x0000003e) |
2744 | type = macio_intrepid; | 2772 | type = macio_intrepid; |
2773 | if (*did == 0x0000004f) | ||
2774 | type = macio_shasta; | ||
2745 | } | 2775 | } |
2746 | macio_chips[i].of_node = node; | 2776 | macio_chips[i].of_node = node; |
2747 | macio_chips[i].type = type; | 2777 | macio_chips[i].type = type; |
@@ -2840,7 +2870,8 @@ set_initial_features(void) | |||
2840 | } | 2870 | } |
2841 | 2871 | ||
2842 | #ifdef CONFIG_POWER4 | 2872 | #ifdef CONFIG_POWER4 |
2843 | if (macio_chips[0].type == macio_keylargo2) { | 2873 | if (macio_chips[0].type == macio_keylargo2 || |
2874 | macio_chips[0].type == macio_shasta) { | ||
2844 | #ifndef CONFIG_SMP | 2875 | #ifndef CONFIG_SMP |
2845 | /* On SMP machines running UP, we have the second CPU eating | 2876 | /* On SMP machines running UP, we have the second CPU eating |
2846 | * bus cycles. We need to take it off the bus. This is done | 2877 | * bus cycles. We need to take it off the bus. This is done |