aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2005-05-01 11:58:42 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-01 11:58:42 -0400
commitb20cc8aff258eea5a2339107605ebea949fa6ecf (patch)
tree0c860a2ca131233edeb1d4517e788a71990685df
parent146a4b3bdfb5641bfbf975e29680b482b8b343ba (diff)
[PATCH] ppc32: Fix a sleep issues on some laptops
Some earlier models of aluminium powerbooks and ibook G4s have a clock chip that requires some tweaking before and after sleep. It seems that without that magic incantation to disable and re-enable clock spreading, RAM isn't properly refreshed during sleep. This fixes it. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/ppc/platforms/pmac_feature.c214
1 files changed, 114 insertions, 100 deletions
diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c
index 46cbf36722db..be41f6fa66a2 100644
--- a/arch/ppc/platforms/pmac_feature.c
+++ b/arch/ppc/platforms/pmac_feature.c
@@ -1590,6 +1590,112 @@ intrepid_shutdown(struct macio_chip* macio, int sleep_mode)
1590 mdelay(10); 1590 mdelay(10);
1591} 1591}
1592 1592
1593
1594static void __pmac pmac_tweak_clock_spreading(struct macio_chip* macio, int enable)
1595{
1596 /* Hack for doing clock spreading on some machines PowerBooks and
1597 * iBooks. This implements the "platform-do-clockspreading" OF
1598 * property as decoded manually on various models. For safety, we also
1599 * check the product ID in the device-tree in cases we'll whack the i2c
1600 * chip to make reasonably sure we won't set wrong values in there
1601 *
1602 * Of course, ultimately, we have to implement a real parser for
1603 * the platform-do-* stuff...
1604 */
1605
1606 if (macio->type == macio_intrepid) {
1607 if (enable)
1608 UN_OUT(UNI_N_CLOCK_SPREADING, 2);
1609 else
1610 UN_OUT(UNI_N_CLOCK_SPREADING, 0);
1611 mdelay(40);
1612 }
1613
1614 while (machine_is_compatible("PowerBook5,2") ||
1615 machine_is_compatible("PowerBook5,3") ||
1616 machine_is_compatible("PowerBook6,2") ||
1617 machine_is_compatible("PowerBook6,3")) {
1618 struct device_node *ui2c = of_find_node_by_type(NULL, "i2c");
1619 struct device_node *dt = of_find_node_by_name(NULL, "device-tree");
1620 u8 buffer[9];
1621 u32 *productID;
1622 int i, rc, changed = 0;
1623
1624 if (dt == NULL)
1625 break;
1626 productID = (u32 *)get_property(dt, "pid#", NULL);
1627 if (productID == NULL)
1628 break;
1629 while(ui2c) {
1630 struct device_node *p = of_get_parent(ui2c);
1631 if (p && !strcmp(p->name, "uni-n"))
1632 break;
1633 ui2c = of_find_node_by_type(ui2c, "i2c");
1634 }
1635 if (ui2c == NULL)
1636 break;
1637 DBG("Trying to bump clock speed for PID: %08x...\n", *productID);
1638 rc = pmac_low_i2c_open(ui2c, 1);
1639 if (rc != 0)
1640 break;
1641 pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
1642 rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);
1643 DBG("read result: %d,", rc);
1644 if (rc != 0) {
1645 pmac_low_i2c_close(ui2c);
1646 break;
1647 }
1648 for (i=0; i<9; i++)
1649 DBG(" %02x", buffer[i]);
1650 DBG("\n");
1651
1652 switch(*productID) {
1653 case 0x1182: /* AlBook 12" rev 2 */
1654 case 0x1183: /* iBook G4 12" */
1655 buffer[0] = (buffer[0] & 0x8f) | 0x70;
1656 buffer[2] = (buffer[2] & 0x7f) | 0x00;
1657 buffer[5] = (buffer[5] & 0x80) | 0x31;
1658 buffer[6] = (buffer[6] & 0x40) | 0xb0;
1659 buffer[7] = (buffer[7] & 0x00) | (enable ? 0xc0 : 0xba);
1660 buffer[8] = (buffer[8] & 0x00) | 0x30;
1661 changed = 1;
1662 break;
1663 case 0x3142: /* AlBook 15" (ATI M10) */
1664 case 0x3143: /* AlBook 17" (ATI M10) */
1665 buffer[0] = (buffer[0] & 0xaf) | 0x50;
1666 buffer[2] = (buffer[2] & 0x7f) | 0x00;
1667 buffer[5] = (buffer[5] & 0x80) | 0x31;
1668 buffer[6] = (buffer[6] & 0x40) | 0xb0;
1669 buffer[7] = (buffer[7] & 0x00) | (enable ? 0xd0 : 0xc0);
1670 buffer[8] = (buffer[8] & 0x00) | 0x30;
1671 changed = 1;
1672 break;
1673 default:
1674 DBG("i2c-hwclock: Machine model not handled\n");
1675 break;
1676 }
1677 if (!changed) {
1678 pmac_low_i2c_close(ui2c);
1679 break;
1680 }
1681 pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_stdsub);
1682 rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_write, 0x80, buffer, 9);
1683 DBG("write result: %d,", rc);
1684 pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
1685 rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);
1686 DBG("read result: %d,", rc);
1687 if (rc != 0) {
1688 pmac_low_i2c_close(ui2c);
1689 break;
1690 }
1691 for (i=0; i<9; i++)
1692 DBG(" %02x", buffer[i]);
1693 pmac_low_i2c_close(ui2c);
1694 break;
1695 }
1696}
1697
1698
1593static int __pmac 1699static int __pmac
1594core99_sleep(void) 1700core99_sleep(void)
1595{ 1701{
@@ -1601,11 +1707,8 @@ core99_sleep(void)
1601 macio->type != macio_intrepid) 1707 macio->type != macio_intrepid)
1602 return -ENODEV; 1708 return -ENODEV;
1603 1709
1604 /* The device-tree contains that in the hwclock node */ 1710 /* Disable clock spreading */
1605 if (macio->type == macio_intrepid) { 1711 pmac_tweak_clock_spreading(macio, 0);
1606 UN_OUT(UNI_N_CLOCK_SPREADING, 0);
1607 mdelay(40);
1608 }
1609 1712
1610 /* We power off the wireless slot in case it was not done 1713 /* We power off the wireless slot in case it was not done
1611 * by the driver. We don't power it on automatically however 1714 * by the driver. We don't power it on automatically however
@@ -1749,11 +1852,8 @@ core99_wake_up(void)
1749 UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl); 1852 UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl);
1750 udelay(100); 1853 udelay(100);
1751 1854
1752 /* Restore clock spreading */ 1855 /* Enable clock spreading */
1753 if (macio->type == macio_intrepid) { 1856 pmac_tweak_clock_spreading(macio, 1);
1754 UN_OUT(UNI_N_CLOCK_SPREADING, 2);
1755 mdelay(40);
1756 }
1757 1857
1758 return 0; 1858 return 0;
1759} 1859}
@@ -2718,97 +2818,11 @@ set_initial_features(void)
2718 MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N); 2818 MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
2719 } 2819 }
2720 2820
2721 /* Hack for bumping clock speed on the new PowerBooks and the 2821 /* Some machine models need the clock chip to be properly setup for
2722 * iBook G4. This implements the "platform-do-clockspreading" OF 2822 * clock spreading now. This should be a platform function but we
2723 * property. For safety, we also check the product ID in the 2823 * don't do these at the moment
2724 * device-tree to make reasonably sure we won't set wrong values
2725 * in the clock chip.
2726 *
2727 * Of course, ultimately, we have to implement a real parser for
2728 * the platform-do-* stuff...
2729 */ 2824 */
2730 while (machine_is_compatible("PowerBook5,2") || 2825 pmac_tweak_clock_spreading(&macio_chips[0], 1);
2731 machine_is_compatible("PowerBook5,3") ||
2732 machine_is_compatible("PowerBook6,2") ||
2733 machine_is_compatible("PowerBook6,3")) {
2734 struct device_node *ui2c = of_find_node_by_type(NULL, "i2c");
2735 struct device_node *dt = of_find_node_by_name(NULL, "device-tree");
2736 u8 buffer[9];
2737 u32 *productID;
2738 int i, rc, changed = 0;
2739
2740 if (dt == NULL)
2741 break;
2742 productID = (u32 *)get_property(dt, "pid#", NULL);
2743 if (productID == NULL)
2744 break;
2745 while(ui2c) {
2746 struct device_node *p = of_get_parent(ui2c);
2747 if (p && !strcmp(p->name, "uni-n"))
2748 break;
2749 ui2c = of_find_node_by_type(ui2c, "i2c");
2750 }
2751 if (ui2c == NULL)
2752 break;
2753 DBG("Trying to bump clock speed for PID: %08x...\n", *productID);
2754 rc = pmac_low_i2c_open(ui2c, 1);
2755 if (rc != 0)
2756 break;
2757 pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
2758 rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);
2759 DBG("read result: %d,", rc);
2760 if (rc != 0) {
2761 pmac_low_i2c_close(ui2c);
2762 break;
2763 }
2764 for (i=0; i<9; i++)
2765 DBG(" %02x", buffer[i]);
2766 DBG("\n");
2767
2768 switch(*productID) {
2769 case 0x1182: /* AlBook 12" rev 2 */
2770 case 0x1183: /* iBook G4 12" */
2771 buffer[0] = (buffer[0] & 0x8f) | 0x70;
2772 buffer[2] = (buffer[2] & 0x7f) | 0x00;
2773 buffer[5] = (buffer[5] & 0x80) | 0x31;
2774 buffer[6] = (buffer[6] & 0x40) | 0xb0;
2775 buffer[7] = (buffer[7] & 0x00) | 0xc0;
2776 buffer[8] = (buffer[8] & 0x00) | 0x30;
2777 changed = 1;
2778 break;
2779 case 0x3142: /* AlBook 15" (ATI M10) */
2780 case 0x3143: /* AlBook 17" (ATI M10) */
2781 buffer[0] = (buffer[0] & 0xaf) | 0x50;
2782 buffer[2] = (buffer[2] & 0x7f) | 0x00;
2783 buffer[5] = (buffer[5] & 0x80) | 0x31;
2784 buffer[6] = (buffer[6] & 0x40) | 0xb0;
2785 buffer[7] = (buffer[7] & 0x00) | 0xd0;
2786 buffer[8] = (buffer[8] & 0x00) | 0x30;
2787 changed = 1;
2788 break;
2789 default:
2790 DBG("i2c-hwclock: Machine model not handled\n");
2791 break;
2792 }
2793 if (!changed) {
2794 pmac_low_i2c_close(ui2c);
2795 break;
2796 }
2797 pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_stdsub);
2798 rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_write, 0x80, buffer, 9);
2799 DBG("write result: %d,", rc);
2800 pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
2801 rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);
2802 DBG("read result: %d,", rc);
2803 if (rc != 0) {
2804 pmac_low_i2c_close(ui2c);
2805 break;
2806 }
2807 for (i=0; i<9; i++)
2808 DBG(" %02x", buffer[i]);
2809 pmac_low_i2c_close(ui2c);
2810 break;
2811 }
2812 2826
2813#endif /* CONFIG_POWER4 */ 2827#endif /* CONFIG_POWER4 */
2814 2828