Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
authorLinus Torvalds <torvalds@g5.osdl.org>
Mon, 31 Jul 2006 20:39:52 +0000 (13:39 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Mon, 31 Jul 2006 20:39:52 +0000 (13:39 -0700)
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc:
  [POWERPC] Minor comment fix for misc_64.S
  [POWERPC] Use H_CEDE on non-SMT
  [POWERPC] force 64bit mode in fwnmi handlers to workaround firmware bugs
  [POWERPC] PMAC_APM_EMU should depend on ADB_PMU
  [POWERPC] Fix new interrupt code (MPIC detection)
  [POWERPC] Fix new interrupt code (MPIC endianness)
  [POWERPC] Add cpufreq support for Xserve G5
  [POWERPC] Xserve G5 thermal control fixes
  [POWERPC] Fix mem= handling when the memory limit is > RMO size
  [POWERPC] More offb/bootx fixes
  [POWERPC] Fix legacy_serial.c error handling on 32 bits
  [POWERPC] Fix default clock for udbg_16550
  [POWERPC] Fix non-MPIC CHRPs with CONFIG_SMP set
  [POWERPC] Fix 32 bits warning in prom_init.c
  [POWERPC] Workaround Pegasos incorrect ISA "ranges"
  [POWERPC] fix up front-LED Kconfig

20 files changed:
arch/powerpc/Kconfig
arch/powerpc/configs/pmac32_defconfig
arch/powerpc/kernel/head_64.S
arch/powerpc/kernel/legacy_serial.c
arch/powerpc/kernel/misc_64.S
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/udbg_16550.c
arch/powerpc/mm/lmb.c
arch/powerpc/platforms/chrp/setup.c
arch/powerpc/platforms/maple/setup.c
arch/powerpc/platforms/powermac/bootx_init.c
arch/powerpc/platforms/powermac/cpufreq_64.c
arch/powerpc/platforms/pseries/setup.c
drivers/ide/Kconfig
drivers/macintosh/Kconfig
drivers/macintosh/therm_pm72.c
drivers/macintosh/therm_pm72.h
drivers/macintosh/via-pmu-led.c
drivers/video/offb.c

index 2643dbc3f289428ef46d836705e93e386904dafe..13e583f16ede5738c2777dfbdb552d326d7be489 100644 (file)
@@ -504,7 +504,7 @@ config CPU_FREQ_PMAC
 
 config CPU_FREQ_PMAC64
        bool "Support for some Apple G5s"
-       depends on CPU_FREQ && PMAC_SMU && PPC64
+       depends on CPU_FREQ && PPC64
        select CPU_FREQ_TABLE
        help
          This adds support for frequency switching on Apple iMac G5,
index addc79381c3b3b3bf0cf466905e287f1b2bc7b1a..3545af9896af03eac7a22069b7b5a89e65fa3730 100644 (file)
@@ -1,16 +1,18 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc5
-# Mon May 29 14:47:49 2006
+# Linux kernel version: 2.6.17
+# Mon Jul  3 14:20:49 2006
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
 CONFIG_PPC_MERGE=y
 CONFIG_MMU=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_GENERIC_NVRAM=y
@@ -29,6 +31,7 @@ CONFIG_CLASSIC32=y
 # CONFIG_PPC_82xx is not set
 # CONFIG_PPC_83xx is not set
 # CONFIG_PPC_85xx is not set
+# CONFIG_PPC_86xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_8xx is not set
@@ -39,6 +42,7 @@ CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_SMP is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
@@ -72,10 +76,12 @@ CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -119,6 +125,9 @@ CONFIG_PPC_MULTIPLATFORM=y
 # CONFIG_APUS is not set
 # CONFIG_PPC_CHRP is not set
 CONFIG_PPC_PMAC=y
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_UDBG_RTAS_CONSOLE is not set
 CONFIG_MPIC=y
 # CONFIG_PPC_RTAS is not set
 # CONFIG_MMIO_NVRAM is not set
@@ -154,6 +163,7 @@ CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT is not set
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 # CONFIG_KEXEC is not set
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -164,6 +174,7 @@ CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 CONFIG_PM=y
@@ -182,6 +193,7 @@ CONFIG_GENERIC_ISA_DMA=y
 CONFIG_PPC_INDIRECT_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -256,6 +268,8 @@ CONFIG_INET_ESP=y
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -268,6 +282,7 @@ CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -292,9 +307,11 @@ CONFIG_NETFILTER_XT_MATCH_MARK=m
 CONFIG_NETFILTER_XT_MATCH_POLICY=m
 CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 
@@ -313,6 +330,7 @@ CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
 CONFIG_IP_NF_PPTP=m
 CONFIG_IP_NF_H323=m
+# CONFIG_IP_NF_SIP is not set
 # CONFIG_IP_NF_QUEUE is not set
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
@@ -457,6 +475,7 @@ CONFIG_IRTTY_SIR=m
 # CONFIG_ALI_FIR is not set
 # CONFIG_VLSI_FIR is not set
 # CONFIG_VIA_FIR is not set
+# CONFIG_MCS_FIR is not set
 CONFIG_BT=m
 CONFIG_BT_L2CAP=m
 CONFIG_BT_SCO=m
@@ -500,6 +519,7 @@ CONFIG_WIRELESS_EXT=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
@@ -600,7 +620,6 @@ CONFIG_BLK_DEV_PDC202XX_NEW=y
 CONFIG_BLK_DEV_IDE_PMAC=y
 CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
 CONFIG_BLK_DEV_IDEDMA_PMAC=y
-CONFIG_BLK_DEV_IDE_PMAC_BLINK=y
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -661,6 +680,7 @@ CONFIG_SCSI_AIC7XXX_OLD=m
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
 # CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
@@ -705,9 +725,7 @@ CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
 CONFIG_MD_RAID1=m
 CONFIG_MD_RAID10=m
-CONFIG_MD_RAID5=m
-CONFIG_MD_RAID5_RESHAPE=y
-CONFIG_MD_RAID6=m
+# CONFIG_MD_RAID456 is not set
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=m
@@ -750,7 +768,6 @@ CONFIG_IEEE1394_OHCI1394=m
 #
 CONFIG_IEEE1394_VIDEO1394=m
 CONFIG_IEEE1394_SBP2=m
-# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
 # CONFIG_IEEE1394_ETH1394 is not set
 CONFIG_IEEE1394_DV1394=m
 CONFIG_IEEE1394_RAWIO=m
@@ -766,9 +783,12 @@ CONFIG_IEEE1394_RAWIO=m
 CONFIG_ADB=y
 CONFIG_ADB_CUDA=y
 CONFIG_ADB_PMU=y
+CONFIG_ADB_PMU_LED=y
+CONFIG_ADB_PMU_LED_IDE=y
 CONFIG_PMAC_APM_EMU=m
 CONFIG_PMAC_MEDIABAY=y
 CONFIG_PMAC_BACKLIGHT=y
+CONFIG_PMAC_BACKLIGHT_LEGACY=y
 CONFIG_INPUT_ADBHID=y
 CONFIG_MAC_EMUMOUSEBTN=y
 CONFIG_THERM_WINDTUNNEL=m
@@ -858,6 +878,7 @@ CONFIG_PCNET32=y
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
 
 #
 # Token Ring devices
@@ -908,6 +929,7 @@ CONFIG_APPLE_AIRPORT=m
 # Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
 #
 CONFIG_PRISM54=m
+# CONFIG_USB_ZD1201 is not set
 # CONFIG_HOSTAP is not set
 CONFIG_NET_WIRELESS=y
 
@@ -998,6 +1020,7 @@ CONFIG_SERIO=y
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -1029,6 +1052,7 @@ CONFIG_LEGACY_PTY_COUNT=256
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
 CONFIG_NVRAM=y
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
@@ -1040,6 +1064,7 @@ CONFIG_GEN_RTC=y
 # Ftape, the floppy tape device driver
 #
 CONFIG_AGP=m
+# CONFIG_AGP_SIS is not set
 # CONFIG_AGP_VIA is not set
 CONFIG_AGP_UNINORTH=m
 CONFIG_DRM=m
@@ -1092,6 +1117,7 @@ CONFIG_I2C_ALGOBIT=y
 CONFIG_I2C_POWERMAC=y
 # CONFIG_I2C_MPC is not set
 # CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
@@ -1156,12 +1182,13 @@ CONFIG_VIDEO_V4L2=y
 #
 # Graphics support
 #
+# CONFIG_FIRMWARE_EDID is not set
 CONFIG_FB=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 CONFIG_FB_MACMODES=y
-CONFIG_FB_FIRMWARE_EDID=y
+CONFIG_FB_BACKLIGHT=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 # CONFIG_FB_CIRRUS is not set
@@ -1178,6 +1205,7 @@ CONFIG_FB_IMSTT=y
 # CONFIG_FB_S1D13XXX is not set
 CONFIG_FB_NVIDIA=y
 CONFIG_FB_NVIDIA_I2C=y
+CONFIG_FB_NVIDIA_BACKLIGHT=y
 # CONFIG_FB_RIVA is not set
 CONFIG_FB_MATROX=y
 CONFIG_FB_MATROX_MILLENIUM=y
@@ -1187,12 +1215,15 @@ CONFIG_FB_MATROX_MYSTIQUE=y
 # CONFIG_FB_MATROX_MULTIHEAD is not set
 CONFIG_FB_RADEON=y
 CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
 # CONFIG_FB_RADEON_DEBUG is not set
 CONFIG_FB_ATY128=y
+CONFIG_FB_ATY128_BACKLIGHT=y
 CONFIG_FB_ATY=y
 CONFIG_FB_ATY_CT=y
 # CONFIG_FB_ATY_GENERIC_LCD is not set
 CONFIG_FB_ATY_GX=y
+CONFIG_FB_ATY_BACKLIGHT=y
 # CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
@@ -1221,7 +1252,11 @@ CONFIG_LOGO=y
 CONFIG_LOGO_LINUX_MONO=y
 CONFIG_LOGO_LINUX_VGA16=y
 CONFIG_LOGO_LINUX_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
 
 #
 # Sound
@@ -1278,6 +1313,18 @@ CONFIG_SND_DUMMY=m
 # CONFIG_SND_CMIPCI is not set
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
 # CONFIG_SND_EMU10K1 is not set
 # CONFIG_SND_EMU10K1X is not set
 # CONFIG_SND_ENS1370 is not set
@@ -1314,6 +1361,17 @@ CONFIG_SND_DUMMY=m
 CONFIG_SND_POWERMAC=m
 CONFIG_SND_POWERMAC_AUTO_DRC=y
 
+#
+# Apple Onboard Audio driver
+#
+CONFIG_SND_AOA=m
+CONFIG_SND_AOA_FABRIC_LAYOUT=m
+CONFIG_SND_AOA_ONYX=m
+CONFIG_SND_AOA_TAS=m
+CONFIG_SND_AOA_TOONIE=m
+CONFIG_SND_AOA_SOUNDBUS=m
+CONFIG_SND_AOA_SOUNDBUS_I2S=m
+
 #
 # USB devices
 #
@@ -1355,6 +1413,7 @@ CONFIG_USB_DYNAMIC_MINORS=y
 CONFIG_USB_EHCI_HCD=m
 CONFIG_USB_EHCI_SPLIT_ISO=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_OHCI_BIG_ENDIAN is not set
@@ -1431,7 +1490,6 @@ CONFIG_USB_NET_NET1080=m
 # CONFIG_USB_NET_RNDIS_HOST is not set
 # CONFIG_USB_NET_CDC_SUBSET is not set
 CONFIG_USB_NET_ZAURUS=m
-# CONFIG_USB_ZD1201 is not set
 CONFIG_USB_MON=y
 
 #
@@ -1499,10 +1557,12 @@ CONFIG_USB_EZUSB=y
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
+# CONFIG_USB_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_IDMOUSE is not set
+CONFIG_USB_APPLEDISPLAY=m
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
@@ -1524,7 +1584,8 @@ CONFIG_USB_EZUSB=y
 #
 # LED devices
 #
-# CONFIG_NEW_LEDS is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
 
 #
 # LED drivers
@@ -1533,6 +1594,10 @@ CONFIG_USB_EZUSB=y
 #
 # LED Triggers
 #
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
 
 #
 # InfiniBand support
@@ -1548,6 +1613,19 @@ CONFIG_USB_EZUSB=y
 #
 # CONFIG_RTC_CLASS is not set
 
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
 #
 # File systems
 #
@@ -1569,6 +1647,7 @@ CONFIG_FS_POSIX_ACL=y
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
@@ -1649,6 +1728,7 @@ CONFIG_RPCSEC_GSS_KRB5=y
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
 # CONFIG_CIFS is not set
+# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1732,6 +1812,7 @@ CONFIG_TEXTSEARCH=y
 CONFIG_TEXTSEARCH_KMP=m
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
 
 #
 # Instrumentation Support
@@ -1744,12 +1825,15 @@ CONFIG_OPROFILE=y
 #
 # CONFIG_PRINTK_TIME is not set
 # CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1763,11 +1847,7 @@ CONFIG_XMON=y
 CONFIG_XMON_DEFAULT=y
 # CONFIG_BDI_SWITCH is not set
 CONFIG_BOOTX_TEXT=y
-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS is not set
-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
 
 #
 # Security options
index e16eb2a33173142c828cfba102d248b8e982c7e8..6ff3cf506088bf2c97265bd31835115ba19b94ed 100644 (file)
@@ -191,6 +191,37 @@ exception_marker:
        ori     reg,reg,(label)@l;      /* virt addr of handler ... */
 #endif
 
+/*
+ * Equal to EXCEPTION_PROLOG_PSERIES, except that it forces 64bit mode.
+ * The firmware calls the registered system_reset_fwnmi and
+ * machine_check_fwnmi handlers in 32bit mode if the cpu happens to run
+ * a 32bit application at the time of the event.
+ * This firmware bug is present on POWER4 and JS20.
+ */
+#define EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(area, label)              \
+       mfspr   r13,SPRN_SPRG3;         /* get paca address into r13 */ \
+       std     r9,area+EX_R9(r13);     /* save r9 - r12 */             \
+       std     r10,area+EX_R10(r13);                                   \
+       std     r11,area+EX_R11(r13);                                   \
+       std     r12,area+EX_R12(r13);                                   \
+       mfspr   r9,SPRN_SPRG1;                                          \
+       std     r9,area+EX_R13(r13);                                    \
+       mfcr    r9;                                                     \
+       clrrdi  r12,r13,32;             /* get high part of &label */   \
+       mfmsr   r10;                                                    \
+       /* force 64bit mode */                                          \
+       li      r11,5;                  /* MSR_SF_LG|MSR_ISF_LG */      \
+       rldimi  r10,r11,61,0;           /* insert into top 3 bits */    \
+       /* done 64bit mode */                                           \
+       mfspr   r11,SPRN_SRR0;          /* save SRR0 */                 \
+       LOAD_HANDLER(r12,label)                                         \
+       ori     r10,r10,MSR_IR|MSR_DR|MSR_RI;                           \
+       mtspr   SPRN_SRR0,r12;                                          \
+       mfspr   r12,SPRN_SRR1;          /* and SRR1 */                  \
+       mtspr   SPRN_SRR1,r10;                                          \
+       rfid;                                                           \
+       b       .       /* prevent speculative execution */
+
 #define EXCEPTION_PROLOG_PSERIES(area, label)                          \
        mfspr   r13,SPRN_SPRG3;         /* get paca address into r13 */ \
        std     r9,area+EX_R9(r13);     /* save r9 - r12 */             \
@@ -604,14 +635,14 @@ slb_miss_user_pseries:
 system_reset_fwnmi:
        HMT_MEDIUM
        mtspr   SPRN_SPRG1,r13          /* save r13 */
-       EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
+       EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXGEN, system_reset_common)
 
        .globl machine_check_fwnmi
       .align 7
 machine_check_fwnmi:
        HMT_MEDIUM
        mtspr   SPRN_SPRG1,r13          /* save r13 */
-       EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
+       EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXMC, machine_check_common)
 
 #ifdef CONFIG_PPC_ISERIES
 /***  ISeries-LPAR interrupt handlers ***/
index 7e98e778b52ff66bbfa313ea58add73807a1cb33..359ab89748e05b7d179003fa28942c4b8edf2a9b 100644 (file)
@@ -112,7 +112,7 @@ static int __init add_legacy_port(struct device_node *np, int want_index,
 static int __init add_legacy_soc_port(struct device_node *np,
                                      struct device_node *soc_dev)
 {
-       phys_addr_t addr;
+       u64 addr;
        u32 *addrp;
        upf_t flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
 
@@ -143,7 +143,7 @@ static int __init add_legacy_isa_port(struct device_node *np,
        u32 *reg;
        char *typep;
        int index = -1;
-       phys_addr_t taddr;
+       u64 taddr;
 
        DBG(" -> add_legacy_isa_port(%s)\n", np->full_name);
 
@@ -165,10 +165,13 @@ static int __init add_legacy_isa_port(struct device_node *np,
        if (typep && *typep == 'S')
                index = simple_strtol(typep+1, NULL, 0) - 1;
 
-       /* Translate ISA address */
+       /* Translate ISA address. If it fails, we still register the port
+        * with no translated address so that it can be picked up as an IO
+        * port later by the serial driver
+        */
        taddr = of_translate_address(np, reg);
        if (taddr == OF_BAD_ADDR)
-               return -1;
+               taddr = 0;
 
        /* Add port, irq will be dealt with later */
        return add_legacy_port(np, index, UPIO_PORT, reg[1], taddr,
@@ -180,7 +183,7 @@ static int __init add_legacy_isa_port(struct device_node *np,
 static int __init add_legacy_pci_port(struct device_node *np,
                                      struct device_node *pci_dev)
 {
-       phys_addr_t addr, base;
+       u64 addr, base;
        u32 *addrp;
        unsigned int flags;
        int iotype, index = -1, lindex = 0;
index bfb407fc1aa1f5ed747e789289a5daa53260dd81..e3ed21cd3d945e6d3e5afbfb64108dc5602517f6 100644 (file)
@@ -687,7 +687,7 @@ _GLOBAL(kexec_sequence)
        /* clear out hardware hash page table and tlb */
        ld      r5,0(r27)               /* deref function descriptor */
        mtctr   r5
-       bctrl                           /* ppc_md.hash_clear_all(void); */
+       bctrl                           /* ppc_md.hpte_clear_all(void); */
 
 /*
  *   kexec image calling is:
index ebd501a59abdaf3e800d94985b81fa6f58feb080..462bced40c128de355e9bc15c16989c3cfea8c5e 100644 (file)
@@ -557,7 +557,9 @@ unsigned long prom_memparse(const char *ptr, const char **retptr)
 static void __init early_cmdline_parse(void)
 {
        struct prom_t *_prom = &RELOC(prom);
+#ifdef CONFIG_PPC64
        const char *opt;
+#endif
        char *p;
        int l = 0;
 
@@ -2030,6 +2032,39 @@ static void __init fixup_device_tree_maple(void)
 #define fixup_device_tree_maple()
 #endif
 
+#ifdef CONFIG_PPC_CHRP
+/* Pegasos lacks the "ranges" property in the isa node */
+static void __init fixup_device_tree_chrp(void)
+{
+       phandle isa;
+       u32 isa_ranges[6];
+       char *name;
+       int rc;
+
+       name = "/pci@80000000/isa@c";
+       isa = call_prom("finddevice", 1, 1, ADDR(name));
+       if (!PHANDLE_VALID(isa))
+               return;
+
+       rc = prom_getproplen(isa, "ranges");
+       if (rc != 0 && rc != PROM_ERROR)
+               return;
+
+       prom_printf("Fixing up missing ISA range on Pegasos...\n");
+
+       isa_ranges[0] = 0x1;
+       isa_ranges[1] = 0x0;
+       isa_ranges[2] = 0x01006000;
+       isa_ranges[3] = 0x0;
+       isa_ranges[4] = 0x0;
+       isa_ranges[5] = 0x00010000;
+       prom_setprop(isa, name, "ranges",
+                       isa_ranges, sizeof(isa_ranges));
+}
+#else
+#define fixup_device_tree_chrp()
+#endif
+
 #if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
 static void __init fixup_device_tree_pmac(void)
 {
@@ -2077,6 +2112,7 @@ static void __init fixup_device_tree_pmac(void)
 static void __init fixup_device_tree(void)
 {
        fixup_device_tree_maple();
+       fixup_device_tree_chrp();
        fixup_device_tree_pmac();
 }
 
index 46c56cfd1b2f9685aa69a2b4cbc879009b48c6e2..6a9bc9ce54e0a2304d5a590659822f95e4aad98a 100644 (file)
@@ -144,13 +144,15 @@ void smp_message_recv(int msg, struct pt_regs *regs)
 
 void smp_send_reschedule(int cpu)
 {
-       smp_ops->message_pass(cpu, PPC_MSG_RESCHEDULE);
+       if (likely(smp_ops))
+               smp_ops->message_pass(cpu, PPC_MSG_RESCHEDULE);
 }
 
 #ifdef CONFIG_DEBUGGER
 void smp_send_debugger_break(int cpu)
 {
-       smp_ops->message_pass(cpu, PPC_MSG_DEBUGGER_BREAK);
+       if (likely(smp_ops))
+               smp_ops->message_pass(cpu, PPC_MSG_DEBUGGER_BREAK);
 }
 #endif
 
@@ -158,7 +160,7 @@ void smp_send_debugger_break(int cpu)
 void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *))
 {
        crash_ipi_function_ptr = crash_ipi_callback;
-       if (crash_ipi_callback) {
+       if (crash_ipi_callback && smp_ops) {
                mb();
                smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_DEBUGGER_BREAK);
        }
@@ -220,6 +222,9 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
        /* Can deadlock when called with interrupts disabled */
        WARN_ON(irqs_disabled());
 
+       if (unlikely(smp_ops == NULL))
+               return -1;
+
        data.func = func;
        data.info = info;
        atomic_set(&data.started, 0);
@@ -357,7 +362,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        smp_store_cpu_info(boot_cpuid);
        cpu_callin_map[boot_cpuid] = 1;
 
-       max_cpus = smp_ops->probe();
+       if (smp_ops)
+               max_cpus = smp_ops->probe();
+       else
+               max_cpus = 1;
  
        smp_space_timers(max_cpus);
 
@@ -453,7 +461,7 @@ void generic_mach_cpu_die(void)
 
 static int __devinit cpu_enable(unsigned int cpu)
 {
-       if (smp_ops->cpu_enable)
+       if (smp_ops && smp_ops->cpu_enable)
                return smp_ops->cpu_enable(cpu);
 
        return -ENOSYS;
@@ -467,7 +475,8 @@ int __devinit __cpu_up(unsigned int cpu)
        if (!cpu_enable(cpu))
                return 0;
 
-       if (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu))
+       if (smp_ops == NULL ||
+           (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu)))
                return -EINVAL;
 
        /* Make sure callin-map entry is 0 (can be leftover a CPU
@@ -568,7 +577,8 @@ void __init smp_cpus_done(unsigned int max_cpus)
        old_mask = current->cpus_allowed;
        set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid));
        
-       smp_ops->setup_cpu(boot_cpuid);
+       if (smp_ops)
+               smp_ops->setup_cpu(boot_cpuid);
 
        set_cpus_allowed(current, old_mask);
 
index 0835b4841dea41d8157fde5a7faa37f68a7aab12..2d17f2b8eda73323444208ed4744c0f04104e6e8 100644 (file)
@@ -81,10 +81,14 @@ static int udbg_550_getc(void)
 void udbg_init_uart(void __iomem *comport, unsigned int speed,
                    unsigned int clock)
 {
-       unsigned int dll, base_bauds = clock / 16;
+       unsigned int dll, base_bauds;
 
+       if (clock == 0)
+               clock = 1843200;
        if (speed == 0)
                speed = 9600;
+
+       base_bauds = clock / 16;
        dll = base_bauds / speed;
 
        if (comport) {
index 4b17a7359924ef5e339753194a25ab5a2b59254f..716a2906a24da373a9e892e1486e24f1316d271e 100644 (file)
@@ -320,7 +320,8 @@ void __init lmb_enforce_memory_limit(unsigned long memory_limit)
                break;
        }
 
-       lmb.rmo_size = lmb.memory.region[0].size;
+       if (lmb.memory.region[0].size < lmb.rmo_size)
+               lmb.rmo_size = lmb.memory.region[0].size;
 
        /* And truncate any reserves above the limit also. */
        for (i = 0; i < lmb.reserved.cnt; i++) {
index 538e337d63e244ec423212c09a3eaa53a7481c3f..9c08ff3222900d6e0475b01967e79abfc7cda018 100644 (file)
@@ -291,10 +291,6 @@ void __init chrp_setup_arch(void)
 
        pci_create_OF_bus_map();
 
-#ifdef CONFIG_SMP
-       smp_ops = &chrp_smp_ops;
-#endif /* CONFIG_SMP */
-
        /*
         * Print the banner, then scroll down so boot progress
         * can be printed.  -- Cort
@@ -479,6 +475,14 @@ void __init chrp_init_IRQ(void)
        chrp_find_openpic();
        chrp_find_8259();
 
+#ifdef CONFIG_SMP
+       /* Pegasos has no MPIC, those ops would make it crash. It might be an
+        * option to move setting them to after we probe the PIC though
+        */
+       if (chrp_mpic != NULL)
+               smp_ops = &chrp_smp_ops;
+#endif /* CONFIG_SMP */
+
        if (_chrp_type == _CHRP_Pegasos)
                ppc_md.get_irq        = i8259_irq;
 
index cb528c9de4c36fbec879871f5e1c52524eff274c..57567dfb98192cbf5fc781c144d28d67738487ea 100644 (file)
@@ -221,10 +221,17 @@ static void __init maple_init_IRQ(void)
         * in Maple device-tree where the type of the controller is
         * open-pic and not interrupt-controller
         */
-       for_each_node_by_type(np, "open-pic") {
-               mpic_node = np;
-               break;
-       }
+
+       for_each_node_by_type(np, "interrupt-controller")
+               if (device_is_compatible(np, "open-pic")) {
+                       mpic_node = np;
+                       break;
+               }
+       if (mpic_node == NULL)
+               for_each_node_by_type(np, "open-pic") {
+                       mpic_node = np;
+                       break;
+               }
        if (mpic_node == NULL) {
                printk(KERN_ERR
                       "Failed to locate the MPIC interrupt controller\n");
@@ -252,6 +259,8 @@ static void __init maple_init_IRQ(void)
 
        /* XXX Maple specific bits */
        flags |= MPIC_BROKEN_U3 | MPIC_WANTS_RESET;
+       /* All U3/U4 are big-endian, older SLOF firmware doesn't encode this */
+       flags |= MPIC_BIG_ENDIAN;
 
        /* Setup the openpic driver. More device-tree junks, we hard code no
         * ISUs for now. I'll have to revisit some stuffs with the folks doing
index 871b002c9f90dd111963c1f2d465988647f7379a..6a026c733f6a069bffae70e1391cb1642244a847 100644 (file)
@@ -181,13 +181,18 @@ static void __init bootx_add_chosen_props(unsigned long base,
 }
 
 static void __init bootx_add_display_props(unsigned long base,
-                                          unsigned long *mem_end)
+                                          unsigned long *mem_end,
+                                          int has_real_node)
 {
        boot_infos_t *bi = bootx_info;
        u32 tmp;
 
-       bootx_dt_add_prop("linux,boot-display", NULL, 0, mem_end);
-       bootx_dt_add_prop("linux,opened", NULL, 0, mem_end);
+       if (has_real_node) {
+               bootx_dt_add_prop("linux,boot-display", NULL, 0, mem_end);
+               bootx_dt_add_prop("linux,opened", NULL, 0, mem_end);
+       } else
+               bootx_dt_add_prop("linux,bootx-noscreen", NULL, 0, mem_end);
+
        tmp = bi->dispDeviceDepth;
        bootx_dt_add_prop("linux,bootx-depth", &tmp, 4, mem_end);
        tmp = bi->dispDeviceRect[2] - bi->dispDeviceRect[0];
@@ -241,11 +246,6 @@ static void __init bootx_scan_dt_build_strings(unsigned long base,
                DBG(" detected display ! adding properties names !\n");
                bootx_dt_add_string("linux,boot-display", mem_end);
                bootx_dt_add_string("linux,opened", mem_end);
-               bootx_dt_add_string("linux,bootx-depth", mem_end);
-               bootx_dt_add_string("linux,bootx-width", mem_end);
-               bootx_dt_add_string("linux,bootx-height", mem_end);
-               bootx_dt_add_string("linux,bootx-linebytes", mem_end);
-               bootx_dt_add_string("linux,bootx-addr", mem_end);
                strncpy(bootx_disp_path, namep, 255);
        }
 
@@ -329,10 +329,13 @@ static void __init bootx_scan_dt_build_struct(unsigned long base,
                ppp = &pp->next;
        }
 
-       if (node == bootx_node_chosen)
+       if (node == bootx_node_chosen) {
                bootx_add_chosen_props(base, mem_end);
-       if (node == bootx_info->dispDeviceRegEntryOffset)
-               bootx_add_display_props(base, mem_end);
+               if (bootx_info->dispDeviceRegEntryOffset == 0)
+                       bootx_add_display_props(base, mem_end, 0);
+       }
+       else if (node == bootx_info->dispDeviceRegEntryOffset)
+               bootx_add_display_props(base, mem_end, 1);
 
        /* do all our children */
        cpp = &np->child;
@@ -374,6 +377,14 @@ static unsigned long __init bootx_flatten_dt(unsigned long start)
        mem_end += 4;
        bootx_dt_strend = mem_end;
        bootx_scan_dt_build_strings(base, 4, &mem_end);
+       /* Add some strings */
+       bootx_dt_add_string("linux,bootx-noscreen", &mem_end);
+       bootx_dt_add_string("linux,bootx-depth", &mem_end);
+       bootx_dt_add_string("linux,bootx-width", &mem_end);
+       bootx_dt_add_string("linux,bootx-height", &mem_end);
+       bootx_dt_add_string("linux,bootx-linebytes", &mem_end);
+       bootx_dt_add_string("linux,bootx-addr", &mem_end);
+       /* Wrap up strings */
        hdr->off_dt_strings = bootx_dt_strbase - mem_start;
        hdr->dt_strings_size = bootx_dt_strend - bootx_dt_strbase;
 
@@ -471,6 +482,7 @@ void __init bootx_init(unsigned long r3, unsigned long r4)
        if (bi->dispDeviceDepth == 16)
                bi->dispDeviceDepth = 15;
 
+
 #ifdef CONFIG_BOOTX_TEXT
        ptr = (unsigned long)bi->logicalDisplayBase;
        ptr += bi->dispDeviceRect[1] * bi->dispDeviceRowBytes;
@@ -508,6 +520,7 @@ void __init bootx_init(unsigned long r3, unsigned long r4)
 #ifdef CONFIG_BOOTX_TEXT
        btext_welcome(bi);
 #endif
+
        /* New BootX enters kernel with MMU off, i/os are not allowed
         * here. This hack will have been done by the boostrap anyway.
         */
index f08a14516139f5f5c042c4d4a6a1b1f8ff910a57..7b1156ea5341ced1f27b8e0a874d55b3937daca4 100644 (file)
@@ -10,6 +10,8 @@
  * that is iMac G5 and latest single CPU desktop.
  */
 
+#undef DEBUG
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <asm/smu.h>
 #include <asm/pmac_pfunc.h>
 
-#undef DEBUG
-
-#ifdef DEBUG
-#define DBG(fmt...) printk(fmt)
-#else
-#define DBG(fmt...)
-#endif
+#define DBG(fmt...) pr_debug(fmt)
 
 /* see 970FX user manual */
 
@@ -82,8 +78,6 @@ static struct freq_attr* g5_cpu_freqs_attr[] = {
 /* Power mode data is an array of the 32 bits PCR values to use for
  * the various frequencies, retrieved from the device-tree
  */
-static u32 *g5_pmode_data;
-static int g5_pmode_max;
 static int g5_pmode_cur;
 
 static void (*g5_switch_volt)(int speed_mode);
@@ -93,6 +87,11 @@ static int (*g5_query_freq)(void);
 static DEFINE_MUTEX(g5_switch_mutex);
 
 
+#ifdef CONFIG_PMAC_SMU
+
+static u32 *g5_pmode_data;
+static int g5_pmode_max;
+
 static struct smu_sdbp_fvt *g5_fvt_table;      /* table of op. points */
 static int g5_fvt_count;                       /* number of op. points */
 static int g5_fvt_cur;                         /* current op. point */
@@ -209,6 +208,16 @@ static int g5_scom_query_freq(void)
        return i;
 }
 
+/*
+ * Fake voltage switching for platforms with missing support
+ */
+
+static void g5_dummy_switch_volt(int speed_mode)
+{
+}
+
+#endif /* CONFIG_PMAC_SMU */
+
 /*
  * Platform function based voltage switching for PowerMac7,2 & 7,3
  */
@@ -248,6 +257,9 @@ static int g5_pfunc_switch_freq(int speed_mode)
        struct pmf_args args;
        u32 done = 0;
        unsigned long timeout;
+       int rc;
+
+       DBG("g5_pfunc_switch_freq(%d)\n", speed_mode);
 
        /* If frequency is going up, first ramp up the voltage */
        if (speed_mode < g5_pmode_cur)
@@ -255,9 +267,12 @@ static int g5_pfunc_switch_freq(int speed_mode)
 
        /* Do it */
        if (speed_mode == CPUFREQ_HIGH)
-               pmf_call_one(pfunc_cpu_setfreq_high, NULL);
+               rc = pmf_call_one(pfunc_cpu_setfreq_high, NULL);
        else
-               pmf_call_one(pfunc_cpu_setfreq_low, NULL);
+               rc = pmf_call_one(pfunc_cpu_setfreq_low, NULL);
+
+       if (rc)
+               printk(KERN_WARNING "cpufreq: pfunc switch error %d\n", rc);
 
        /* It's an irq GPIO so we should be able to just block here,
         * I'll do that later after I've properly tested the IRQ code for
@@ -296,13 +311,6 @@ static int g5_pfunc_query_freq(void)
        return val ? CPUFREQ_HIGH : CPUFREQ_LOW;
 }
 
-/*
- * Fake voltage switching for platforms with missing support
- */
-
-static void g5_dummy_switch_volt(int speed_mode)
-{
-}
 
 /*
  * Common interface to the cpufreq core
@@ -375,6 +383,8 @@ static struct cpufreq_driver g5_cpufreq_driver = {
 };
 
 
+#ifdef CONFIG_PMAC_SMU
+
 static int __init g5_neo2_cpufreq_init(struct device_node *cpus)
 {
        struct device_node *cpunode;
@@ -525,6 +535,9 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus)
        return rc;
 }
 
+#endif /* CONFIG_PMAC_SMU */
+
+
 static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
 {
        struct device_node *cpuid = NULL, *hwclock = NULL, *cpunode = NULL;
@@ -533,6 +546,9 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
        u64 max_freq, min_freq, ih, il;
        int has_volt = 1, rc = 0;
 
+       DBG("cpufreq: Initializing for PowerMac7,2, PowerMac7,3 and"
+           " RackMac3,1...\n");
+
        /* Get first CPU node */
        for (cpunode = NULL;
             (cpunode = of_get_next_child(cpus, cpunode)) != NULL;) {
@@ -636,6 +652,15 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
         */
        ih = *((u32 *)(eeprom + 0x10));
        il = *((u32 *)(eeprom + 0x20));
+
+       /* Check for machines with no useful settings */
+       if (il == ih) {
+               printk(KERN_WARNING "cpufreq: No low frequency mode available"
+                      " on this model !\n");
+               rc = -ENODEV;
+               goto bail;
+       }
+
        min_freq = 0;
        if (ih != 0 && il != 0)
                min_freq = (max_freq * il) / ih;
@@ -643,7 +668,7 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
        /* Sanity check */
        if (min_freq >= max_freq || min_freq < 1000) {
                printk(KERN_ERR "cpufreq: Can't calculate low frequency !\n");
-               rc = -ENODEV;
+               rc = -ENXIO;
                goto bail;
        }
        g5_cpu_freqs[0].frequency = max_freq;
@@ -690,16 +715,10 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
        return rc;
 }
 
-static int __init g5_rm31_cpufreq_init(struct device_node *cpus)
-{
-       /* NYI */
-       return 0;
-}
-
 static int __init g5_cpufreq_init(void)
 {
        struct device_node *cpus;
-       int rc;
+       int rc = 0;
 
        cpus = of_find_node_by_path("/cpus");
        if (cpus == NULL) {
@@ -708,12 +727,13 @@ static int __init g5_cpufreq_init(void)
        }
 
        if (machine_is_compatible("PowerMac7,2") ||
-           machine_is_compatible("PowerMac7,3"))
+           machine_is_compatible("PowerMac7,3") ||
+           machine_is_compatible("RackMac3,1"))
                rc = g5_pm72_cpufreq_init(cpus);
-       else if (machine_is_compatible("RackMac3,1"))
-               rc = g5_rm31_cpufreq_init(cpus);
+#ifdef CONFIG_PMAC_SMU
        else
                rc = g5_neo2_cpufreq_init(cpus);
+#endif /* CONFIG_PMAC_SMU */
 
        of_node_put(cpus);
        return rc;
index 54a52437265c50ecb5d0038a3c070c67d1945a9c..71c634e0b87cdc1cbe30df395837a1b090815e84 100644 (file)
@@ -501,7 +501,8 @@ static void pseries_dedicated_idle_sleep(void)
        }
 
        /*
-        * Cede if the other thread is not idle, so that it can
+        * If not SMT, cede processor.  If CPU is running SMT
+        * cede if the other thread is not idle, so that it can
         * go single-threaded.  If the other thread is idle,
         * we ask the hypervisor if it has pending work it
         * wants to do and cede if it does.  Otherwise we keep
@@ -514,7 +515,8 @@ static void pseries_dedicated_idle_sleep(void)
         * very low priority.  The cede enables interrupts, which
         * doesn't matter here.
         */
-       if (!lppaca[cpu ^ 1].idle || poll_pending() == H_PENDING)
+       if (!cpu_has_feature(CPU_FTR_SMT) || !lppaca[cpu ^ 1].idle
+           || poll_pending() == H_PENDING)
                cede_processor();
 
 out:
index 556958ebbf03964ca515031923fba0b95427a6b2..b6fb167e20f681980a54c9baa7ef14a0de4fea83 100644 (file)
@@ -774,20 +774,6 @@ config BLK_DEV_IDEDMA_PMAC
          to transfer data to and from memory.  Saying Y is safe and improves
          performance.
 
-config BLK_DEV_IDE_PMAC_BLINK
-       bool "Blink laptop LED on drive activity (DEPRECATED)"
-       depends on BLK_DEV_IDE_PMAC && ADB_PMU
-       select ADB_PMU_LED
-       select LEDS_TRIGGERS
-       select LEDS_TRIGGER_IDE_DISK
-       help
-         This option enables the use of the sleep LED as a hard drive
-         activity LED.
-         This option is deprecated, it only selects ADB_PMU_LED and
-         LEDS_TRIGGER_IDE_DISK and changes the code in the new led class
-         device to default to the ide-disk trigger (which should be set
-         from userspace via sysfs).
-
 config BLK_DEV_IDE_SWARM
        tristate "IDE for Sibyte evaluation boards"
        depends on SIBYTE_SB1xxx_SOC
index d162307e309ff9c54d6ae3cf76e092e54800ed4c..d5d649f5ccdb3a05f14309fd1e11af83c7486a9f 100644 (file)
@@ -90,6 +90,15 @@ config ADB_PMU_LED
          and the ide-disk LED trigger and configure appropriately through
          sysfs.
 
+config ADB_PMU_LED_IDE
+       bool "Use front LED as IDE LED by default"
+       depends on ADB_PMU_LED
+       select LEDS_TRIGGERS
+       select LEDS_TRIGGER_IDE_DISK
+       help
+         This option makes the front LED default to the IDE trigger
+         so that it blinks on IDE activity.
+
 config PMAC_SMU
        bool "Support for SMU  based PowerMacs"
        depends on PPC_PMAC64
@@ -100,7 +109,7 @@ config PMAC_SMU
 
 config PMAC_APM_EMU
        tristate "APM emulation"
-       depends on PPC_PMAC && PPC32 && PM
+       depends on PPC_PMAC && PPC32 && PM && ADB_PMU
 
 config PMAC_MEDIABAY
        bool "Support PowerBook hotswap media bay"
index c1fe0b368f7624ff12653f0f3f87d85e571939b7..20bf67244e2c1e35630e813cb5b7d1695e7925d1 100644 (file)
  *     - Use min/max macros here or there
  *     - Latest darwin updated U3H min fan speed to 20% PWM
  *
+ *  July. 06, 2006 : 1.3
+ *     - Fix setting of RPM fans on Xserve G5 (they were going too fast)
+ *      - Add missing slots fan control loop for Xserve G5
+ *     - Lower fixed slots fan speed from 50% to 40% on desktop G5s. We
+ *        still can't properly implement the control loop for these, so let's
+ *        reduce the noise a little bit, it appears that 40% still gives us
+ *        a pretty good air flow
+ *     - Add code to "tickle" the FCU regulary so it doesn't think that
+ *        we are gone while in fact, the machine just didn't need any fan
+ *        speed change lately
+ *
  */
 
 #include <linux/types.h>
 
 #include "therm_pm72.h"
 
-#define VERSION "1.2b2"
+#define VERSION "1.3"
 
 #undef DEBUG
 
@@ -146,6 +157,7 @@ static struct basckside_pid_params  backside_params;
 static struct backside_pid_state       backside_state;
 static struct drives_pid_state         drives_state;
 static struct dimm_pid_state           dimms_state;
+static struct slots_pid_state          slots_state;
 static int                             state;
 static int                             cpu_count;
 static int                             cpu_pid_type;
@@ -154,7 +166,8 @@ static struct completion            ctrl_complete;
 static int                             critical_state;
 static int                             rackmac;
 static s32                             dimm_output_clamp;
-
+static int                             fcu_rpm_shift;
+static int                             fcu_tickle_ticks;
 static DECLARE_MUTEX(driver_lock);
 
 /*
@@ -495,13 +508,20 @@ static int start_fcu(void)
        rc = fan_write_reg(0x2e, &buf, 1);
        if (rc < 0)
                return -EIO;
+       rc = fan_read_reg(0, &buf, 1);
+       if (rc < 0)
+               return -EIO;
+       fcu_rpm_shift = (buf == 1) ? 2 : 3;
+       printk(KERN_DEBUG "FCU Initialized, RPM fan shift is %d\n",
+              fcu_rpm_shift);
+
        return 0;
 }
 
 static int set_rpm_fan(int fan_index, int rpm)
 {
        unsigned char buf[2];
-       int rc, id;
+       int rc, id, min, max;
 
        if (fcu_fans[fan_index].type != FCU_FAN_RPM)
                return -EINVAL;
@@ -509,12 +529,15 @@ static int set_rpm_fan(int fan_index, int rpm)
        if (id == FCU_FAN_ABSENT_ID)
                return -EINVAL;
 
-       if (rpm < 300)
-               rpm = 300;
-       else if (rpm > 8191)
-               rpm = 8191;
-       buf[0] = rpm >> 5;
-       buf[1] = rpm << 3;
+       min = 2400 >> fcu_rpm_shift;
+       max = 56000 >> fcu_rpm_shift;
+
+       if (rpm < min)
+               rpm = min;
+       else if (rpm > max)
+               rpm = max;
+       buf[0] = rpm >> (8 - fcu_rpm_shift);
+       buf[1] = rpm << fcu_rpm_shift;
        rc = fan_write_reg(0x10 + (id * 2), buf, 2);
        if (rc < 0)
                return -EIO;
@@ -551,7 +574,7 @@ static int get_rpm_fan(int fan_index, int programmed)
        if (rc != 2)
                return -EIO;
 
-       return (buf[0] << 5) | buf[1] >> 3;
+       return (buf[0] << (8 - fcu_rpm_shift)) | buf[1] >> fcu_rpm_shift;
 }
 
 static int set_pwm_fan(int fan_index, int pwm)
@@ -609,6 +632,26 @@ static int get_pwm_fan(int fan_index)
        return (buf[0] * 1000) / 2559;
 }
 
+static void tickle_fcu(void)
+{
+       int pwm;
+
+       pwm = get_pwm_fan(SLOTS_FAN_PWM_INDEX);
+
+       DBG("FCU Tickle, slots fan is: %d\n", pwm);
+       if (pwm < 0)
+               pwm = 100;
+
+       if (!rackmac) {
+               pwm = SLOTS_FAN_DEFAULT_PWM;
+       } else if (pwm < SLOTS_PID_OUTPUT_MIN)
+               pwm = SLOTS_PID_OUTPUT_MIN;
+
+       /* That is hopefully enough to make the FCU happy */
+       set_pwm_fan(SLOTS_FAN_PWM_INDEX, pwm);
+}
+
+
 /*
  * Utility routine to read the CPU calibration EEPROM data
  * from the device-tree
@@ -715,6 +758,9 @@ BUILD_SHOW_FUNC_INT(backside_fan_pwm, backside_state.pwm)
 BUILD_SHOW_FUNC_FIX(drives_temperature, drives_state.last_temp)
 BUILD_SHOW_FUNC_INT(drives_fan_rpm, drives_state.rpm)
 
+BUILD_SHOW_FUNC_FIX(slots_temperature, slots_state.last_temp)
+BUILD_SHOW_FUNC_INT(slots_fan_pwm, slots_state.pwm)
+
 BUILD_SHOW_FUNC_FIX(dimms_temperature, dimms_state.last_temp)
 
 static DEVICE_ATTR(cpu0_temperature,S_IRUGO,show_cpu0_temperature,NULL);
@@ -735,6 +781,9 @@ static DEVICE_ATTR(backside_fan_pwm,S_IRUGO,show_backside_fan_pwm,NULL);
 static DEVICE_ATTR(drives_temperature,S_IRUGO,show_drives_temperature,NULL);
 static DEVICE_ATTR(drives_fan_rpm,S_IRUGO,show_drives_fan_rpm,NULL);
 
+static DEVICE_ATTR(slots_temperature,S_IRUGO,show_slots_temperature,NULL);
+static DEVICE_ATTR(slots_fan_pwm,S_IRUGO,show_slots_fan_pwm,NULL);
+
 static DEVICE_ATTR(dimms_temperature,S_IRUGO,show_dimms_temperature,NULL);
 
 /*
@@ -1076,6 +1125,9 @@ static void do_monitor_cpu_rack(struct cpu_pid_state *state)
        fan_min = dimm_output_clamp;
        fan_min = max(fan_min, (int)state->mpu.rminn_intake_fan);
 
+       DBG(" CPU min mpu = %d, min dimm = %d\n",
+           state->mpu.rminn_intake_fan, dimm_output_clamp);
+
        state->rpm = max(state->rpm, (int)fan_min);
        state->rpm = min(state->rpm, (int)state->mpu.rmaxn_intake_fan);
        state->intake_rpm = state->rpm;
@@ -1374,7 +1426,8 @@ static void do_monitor_drives(struct drives_pid_state *state)
        DBG("  current rpm: %d\n", state->rpm);
 
        /* Get some sensor readings */
-       temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor, DS1775_TEMP)) << 8;
+       temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor,
+                                                   DS1775_TEMP)) << 8;
        state->last_temp = temp;
        DBG("  temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp),
            FIX32TOPRINT(DRIVES_PID_INPUT_TARGET));
@@ -1575,7 +1628,7 @@ static int init_dimms_state(struct dimm_pid_state *state)
 }
 
 /*
- * Dispose of the state data for the drives control loop
+ * Dispose of the state data for the DIMM control loop
  */
 static void dispose_dimms_state(struct dimm_pid_state *state)
 {
@@ -1588,6 +1641,127 @@ static void dispose_dimms_state(struct dimm_pid_state *state)
        state->monitor = NULL;
 }
 
+/*
+ * Slots fan control loop
+ */
+static void do_monitor_slots(struct slots_pid_state *state)
+{
+       s32 temp, integral, derivative;
+       s64 integ_p, deriv_p, prop_p, sum;
+       int i, rc;
+
+       if (--state->ticks != 0)
+               return;
+       state->ticks = SLOTS_PID_INTERVAL;
+
+       DBG("slots:\n");
+
+       /* Check fan status */
+       rc = get_pwm_fan(SLOTS_FAN_PWM_INDEX);
+       if (rc < 0) {
+               printk(KERN_WARNING "Error %d reading slots fan !\n", rc);
+               /* XXX What do we do now ? */
+       } else
+               state->pwm = rc;
+       DBG("  current pwm: %d\n", state->pwm);
+
+       /* Get some sensor readings */
+       temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor,
+                                                   DS1775_TEMP)) << 8;
+       state->last_temp = temp;
+       DBG("  temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp),
+           FIX32TOPRINT(SLOTS_PID_INPUT_TARGET));
+
+       /* Store temperature and error in history array */
+       state->cur_sample = (state->cur_sample + 1) % SLOTS_PID_HISTORY_SIZE;
+       state->sample_history[state->cur_sample] = temp;
+       state->error_history[state->cur_sample] = temp - SLOTS_PID_INPUT_TARGET;
+
+       /* If first loop, fill the history table */
+       if (state->first) {
+               for (i = 0; i < (SLOTS_PID_HISTORY_SIZE - 1); i++) {
+                       state->cur_sample = (state->cur_sample + 1) %
+                               SLOTS_PID_HISTORY_SIZE;
+                       state->sample_history[state->cur_sample] = temp;
+                       state->error_history[state->cur_sample] =
+                               temp - SLOTS_PID_INPUT_TARGET;
+               }
+               state->first = 0;
+       }
+
+       /* Calculate the integral term */
+       sum = 0;
+       integral = 0;
+       for (i = 0; i < SLOTS_PID_HISTORY_SIZE; i++)
+               integral += state->error_history[i];
+       integral *= SLOTS_PID_INTERVAL;
+       DBG("  integral: %08x\n", integral);
+       integ_p = ((s64)SLOTS_PID_G_r) * (s64)integral;
+       DBG("   integ_p: %d\n", (int)(integ_p >> 36));
+       sum += integ_p;
+
+       /* Calculate the derivative term */
+       derivative = state->error_history[state->cur_sample] -
+               state->error_history[(state->cur_sample + SLOTS_PID_HISTORY_SIZE - 1)
+                                   % SLOTS_PID_HISTORY_SIZE];
+       derivative /= SLOTS_PID_INTERVAL;
+       deriv_p = ((s64)SLOTS_PID_G_d) * (s64)derivative;
+       DBG("   deriv_p: %d\n", (int)(deriv_p >> 36));
+       sum += deriv_p;
+
+       /* Calculate the proportional term */
+       prop_p = ((s64)SLOTS_PID_G_p) * (s64)(state->error_history[state->cur_sample]);
+       DBG("   prop_p: %d\n", (int)(prop_p >> 36));
+       sum += prop_p;
+
+       /* Scale sum */
+       sum >>= 36;
+
+       DBG("   sum: %d\n", (int)sum);
+       state->pwm = (s32)sum;
+
+       state->pwm = max(state->pwm, SLOTS_PID_OUTPUT_MIN);
+       state->pwm = min(state->pwm, SLOTS_PID_OUTPUT_MAX);
+
+       DBG("** DRIVES PWM: %d\n", (int)state->pwm);
+       set_pwm_fan(SLOTS_FAN_PWM_INDEX, state->pwm);
+}
+
+/*
+ * Initialize the state structure for the slots bay fan control loop
+ */
+static int init_slots_state(struct slots_pid_state *state)
+{
+       state->ticks = 1;
+       state->first = 1;
+       state->pwm = 50;
+
+       state->monitor = attach_i2c_chip(XSERVE_SLOTS_LM75, "slots_temp");
+       if (state->monitor == NULL)
+               return -ENODEV;
+
+       device_create_file(&of_dev->dev, &dev_attr_slots_temperature);
+       device_create_file(&of_dev->dev, &dev_attr_slots_fan_pwm);
+
+       return 0;
+}
+
+/*
+ * Dispose of the state data for the slots control loop
+ */
+static void dispose_slots_state(struct slots_pid_state *state)
+{
+       if (state->monitor == NULL)
+               return;
+
+       device_remove_file(&of_dev->dev, &dev_attr_slots_temperature);
+       device_remove_file(&of_dev->dev, &dev_attr_slots_fan_pwm);
+
+       detach_i2c_chip(state->monitor);
+       state->monitor = NULL;
+}
+
+
 static int call_critical_overtemp(void)
 {
        char *argv[] = { critical_overtemp_path, NULL };
@@ -1617,14 +1791,17 @@ static int main_control_loop(void *x)
                goto out;
        }
 
-       /* Set the PCI fan once for now */
-       set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM);
+       /* Set the PCI fan once for now on non-RackMac */
+       if (!rackmac)
+               set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM);
 
        /* Initialize ADCs */
        initialize_adc(&cpu_state[0]);
        if (cpu_state[1].monitor != NULL)
                initialize_adc(&cpu_state[1]);
 
+       fcu_tickle_ticks = FCU_TICKLE_TICKS;
+
        up(&driver_lock);
 
        while (state == state_attached) {
@@ -1634,6 +1811,12 @@ static int main_control_loop(void *x)
 
                down(&driver_lock);
 
+               /* Tickle the FCU just in case */
+               if (--fcu_tickle_ticks < 0) {
+                       fcu_tickle_ticks = FCU_TICKLE_TICKS;
+                       tickle_fcu();
+               }
+
                /* First, we always calculate the new DIMMs state on an Xserve */
                if (rackmac)
                        do_monitor_dimms(&dimms_state);
@@ -1654,7 +1837,9 @@ static int main_control_loop(void *x)
                }
                /* Then, the rest */
                do_monitor_backside(&backside_state);
-               if (!rackmac)
+               if (rackmac)
+                       do_monitor_slots(&slots_state);
+               else
                        do_monitor_drives(&drives_state);
                up(&driver_lock);
 
@@ -1696,6 +1881,7 @@ static void dispose_control_loops(void)
        dispose_cpu_state(&cpu_state[1]);
        dispose_backside_state(&backside_state);
        dispose_drives_state(&drives_state);
+       dispose_slots_state(&slots_state);
        dispose_dimms_state(&dimms_state);
 }
 
@@ -1745,6 +1931,8 @@ static int create_control_loops(void)
                goto fail;
        if (rackmac && init_dimms_state(&dimms_state))
                goto fail;
+       if (rackmac && init_slots_state(&slots_state))
+               goto fail;
        if (!rackmac && init_drives_state(&drives_state))
                goto fail;
 
index fc7e9b7ecaf2da93f7323cf80e4939b935d93f10..393cc9df94e164ad8cef98fd2cecfd45d2461702 100644 (file)
@@ -105,6 +105,7 @@ static char * critical_overtemp_path = "/sbin/critical_overtemp";
 #define DRIVES_DALLAS_ID       0x94
 #define BACKSIDE_MAX_ID                0x98
 #define XSERVE_DIMMS_LM87      0x25a
+#define XSERVE_SLOTS_LM75      0x290
 
 /*
  * Some MAX6690, DS1775, LM87 register definitions
@@ -198,7 +199,7 @@ struct drives_pid_state
 
 #define SLOTS_FAN_PWM_DEFAULT_ID       2
 #define SLOTS_FAN_PWM_INDEX            2
-#define        SLOTS_FAN_DEFAULT_PWM           50 /* Do better here ! */
+#define        SLOTS_FAN_DEFAULT_PWM           40 /* Do better here ! */
 
 
 /*
@@ -206,7 +207,7 @@ struct drives_pid_state
  */
 #define DIMM_PID_G_d                   0
 #define DIMM_PID_G_p                   0
-#define DIMM_PID_G_r                   0x6553600
+#define DIMM_PID_G_r                   0x06553600
 #define DIMM_PID_INPUT_TARGET          3276800
 #define DIMM_PID_INTERVAL              1
 #define DIMM_PID_OUTPUT_MAX            14000
@@ -226,6 +227,31 @@ struct dimm_pid_state
 };
 
 
+/*
+ * PID factors for the Xserve Slots control loop
+ */
+#define SLOTS_PID_G_d                  0
+#define SLOTS_PID_G_p                  0
+#define SLOTS_PID_G_r                  0x00100000
+#define SLOTS_PID_INPUT_TARGET         3200000
+#define SLOTS_PID_INTERVAL             1
+#define SLOTS_PID_OUTPUT_MAX           100
+#define SLOTS_PID_OUTPUT_MIN           20
+#define SLOTS_PID_HISTORY_SIZE         20
+
+struct slots_pid_state
+{
+       int                     ticks;
+       struct i2c_client *     monitor;
+       s32                     sample_history[SLOTS_PID_HISTORY_SIZE];
+       s32                     error_history[SLOTS_PID_HISTORY_SIZE];
+       int                     cur_sample;
+       s32                     last_temp;
+       int                     first;
+       int                     pwm;
+};
+
+
 
 /* Desktops */
 
@@ -283,6 +309,9 @@ struct cpu_pid_state
        s32                     pump_max;
 };
 
+/* Tickle FCU every 10 seconds */
+#define FCU_TICKLE_TICKS       10
+
 /*
  * Driver state
  */
index af8375ed0f5ebdf72e150fac3a45e70e573c6919..5189d5454b1f274c1f363eb5baaa9a255132bb98 100644 (file)
@@ -74,7 +74,7 @@ static void pmu_led_set(struct led_classdev *led_cdev,
 
 static struct led_classdev pmu_led = {
        .name = "pmu-front-led",
-#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK
+#ifdef CONFIG_ADB_PMU_LED_IDE
        .default_trigger = "ide-disk",
 #endif
        .brightness_set = pmu_led_set,
index ce5f3031b99b07b16f32dd899f58374d8bd03dfd..0013311e056469c65ffd5063db355ee1415936f5 100644 (file)
@@ -62,8 +62,6 @@ struct offb_par default_par;
      *  Interface used by the world
      */
 
-int offb_init(void);
-
 static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                          u_int transp, struct fb_info *info);
 static int offb_blank(int blank, struct fb_info *info);
@@ -72,11 +70,6 @@ static int offb_blank(int blank, struct fb_info *info);
 extern boot_infos_t *boot_infos;
 #endif
 
-static void offb_init_nodriver(struct device_node *);
-static void offb_init_fb(const char *name, const char *full_name,
-                        int width, int height, int depth, int pitch,
-                        unsigned long address, struct device_node *dp);
-
 static struct fb_ops offb_ops = {
        .owner          = THIS_MODULE,
        .fb_setcolreg   = offb_setcolreg,
@@ -229,123 +222,17 @@ static int offb_blank(int blank, struct fb_info *info)
        return 0;
 }
 
-    /*
-     *  Initialisation
-     */
 
-int __init offb_init(void)
+static void __iomem *offb_map_reg(struct device_node *np, int index,
+                                 unsigned long offset, unsigned long size)
 {
-       struct device_node *dp = NULL, *boot_disp = NULL;
-
-       if (fb_get_options("offb", NULL))
-               return -ENODEV;
+       struct resource r;
 
-       for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) {
-               if (get_property(dp, "linux,opened", NULL) &&
-                   get_property(dp, "linux,boot-display", NULL)) {
-                       boot_disp = dp;
-                       offb_init_nodriver(dp);
-               }
-       }
-       for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) {
-               if (get_property(dp, "linux,opened", NULL) &&
-                   dp != boot_disp)
-                       offb_init_nodriver(dp);
-       }
-
-       return 0;
-}
-
-
-static void __init offb_init_nodriver(struct device_node *dp)
-{
-       unsigned int len;
-       int i, width = 640, height = 480, depth = 8, pitch = 640;
-       unsigned int flags, rsize, addr_prop = 0;
-       unsigned long max_size = 0;
-       u64 rstart, address = OF_BAD_ADDR;
-       u32 *pp, *addrp, *up;
-       u64 asize;
-
-       pp = (u32 *)get_property(dp, "linux,bootx-depth", &len);
-       if (pp == NULL)
-               pp = (u32 *)get_property(dp, "depth", &len);
-       if (pp && len == sizeof(u32))
-               depth = *pp;
-
-       pp = (u32 *)get_property(dp, "linux,bootx-width", &len);
-       if (pp == NULL)
-               pp = (u32 *)get_property(dp, "width", &len);
-       if (pp && len == sizeof(u32))
-               width = *pp;
-
-       pp = (u32 *)get_property(dp, "linux,bootx-height", &len);
-       if (pp == NULL)
-               pp = (u32 *)get_property(dp, "height", &len);
-       if (pp && len == sizeof(u32))
-               height = *pp;
-
-       pp = (u32 *)get_property(dp, "linux,bootx-linebytes", &len);
-       if (pp == NULL)
-               pp = (u32 *)get_property(dp, "linebytes", &len);
-       if (pp && len == sizeof(u32))
-               pitch = *pp;
-       else
-               pitch = width * ((depth + 7) / 8);
-
-       rsize = (unsigned long)pitch * (unsigned long)height;
-
-       /* Ok, now we try to figure out the address of the framebuffer.
-        *
-        * Unfortunately, Open Firmware doesn't provide a standard way to do
-        * so. All we can do is a dodgy heuristic that happens to work in
-        * practice. On most machines, the "address" property contains what
-        * we need, though not on Matrox cards found in IBM machines. What I've
-        * found that appears to give good results is to go through the PCI
-        * ranges and pick one that is both big enough and if possible encloses
-        * the "address" property. If none match, we pick the biggest
-        */
-       up = (u32 *)get_property(dp, "linux,bootx-addr", &len);
-       if (up == NULL)
-               up = (u32 *)get_property(dp, "address", &len);
-       if (up && len == sizeof(u32))
-               addr_prop = *up;
-
-       for (i = 0; (addrp = of_get_address(dp, i, &asize, &flags))
-                    != NULL; i++) {
-               int match_addrp = 0;
-
-               if (!(flags & IORESOURCE_MEM))
-                       continue;
-               if (asize < rsize)
-                       continue;
-               rstart = of_translate_address(dp, addrp);
-               if (rstart == OF_BAD_ADDR)
-                       continue;
-               if (addr_prop && (rstart <= addr_prop) &&
-                   ((rstart + asize) >= (addr_prop + rsize)))
-                       match_addrp = 1;
-               if (match_addrp) {
-                       address = addr_prop;
-                       break;
-               }
-               if (rsize > max_size) {
-                       max_size = rsize;
-                       address = OF_BAD_ADDR;
-               }
-
-               if (address == OF_BAD_ADDR)
-                       address = rstart;
-       }
-       if (address == OF_BAD_ADDR && addr_prop)
-               address = (u64)addr_prop;
-       if (address != OF_BAD_ADDR) {
-               /* kludge for valkyrie */
-               if (strcmp(dp->name, "valkyrie") == 0)
-                       address += 0x1000;
-               offb_init_fb(dp->name, dp->full_name, width, height, depth,
-                            pitch, address, dp);
-       }
+       if (of_address_to_resource(np, index, &r))
+               return 0;
+       if ((r.start + offset + size) > r.end)
+               return 0;
+       return ioremap(r.start + offset, size);
 }
 
 static void __init offb_init_fb(const char *name, const char *full_name,
@@ -402,45 +289,39 @@ static void __init offb_init_fb(const char *name, const char *full_name,
 
        par->cmap_type = cmap_unknown;
        if (depth == 8) {
-
                /* Palette hacks disabled for now */
-#if 0
                if (dp && !strncmp(name, "ATY,Rage128", 11)) {
-                       unsigned long regbase = dp->addrs[2].address;
-                       par->cmap_adr = ioremap(regbase, 0x1FFF);
-                       par->cmap_type = cmap_r128;
+                       par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
+                       if (par->cmap_adr)
+                               par->cmap_type = cmap_r128;
                } else if (dp && (!strncmp(name, "ATY,RageM3pA", 12)
                                  || !strncmp(name, "ATY,RageM3p12A", 14))) {
-                       unsigned long regbase =
-                           dp->parent->addrs[2].address;
-                       par->cmap_adr = ioremap(regbase, 0x1FFF);
-                       par->cmap_type = cmap_M3A;
+                       par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
+                       if (par->cmap_adr)
+                               par->cmap_type = cmap_M3A;
                } else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) {
-                       unsigned long regbase =
-                           dp->parent->addrs[2].address;
-                       par->cmap_adr = ioremap(regbase, 0x1FFF);
-                       par->cmap_type = cmap_M3B;
+                       par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
+                       if (par->cmap_adr)
+                               par->cmap_type = cmap_M3B;
                } else if (dp && !strncmp(name, "ATY,Rage6", 9)) {
-                       unsigned long regbase = dp->addrs[1].address;
-                       par->cmap_adr = ioremap(regbase, 0x1FFF);
-                       par->cmap_type = cmap_radeon;
+                       par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff);
+                       if (par->cmap_adr)
+                               par->cmap_type = cmap_radeon;
                } else if (!strncmp(name, "ATY,", 4)) {
                        unsigned long base = address & 0xff000000UL;
                        par->cmap_adr =
                            ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
                        par->cmap_data = par->cmap_adr + 1;
                        par->cmap_type = cmap_m64;
-               } else if (device_is_compatible(dp, "pci1014,b7")) {
-                       unsigned long regbase = dp->addrs[0].address;
-                       par->cmap_adr = ioremap(regbase + 0x6000, 0x1000);
-                       par->cmap_type = cmap_gxt2000;
+               } else if (dp && device_is_compatible(dp, "pci1014,b7")) {
+                       par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000);
+                       if (par->cmap_adr)
+                               par->cmap_type = cmap_gxt2000;
                }
-#endif
-               fix->visual = par->cmap_adr ? FB_VISUAL_PSEUDOCOLOR
-                   : FB_VISUAL_STATIC_PSEUDOCOLOR;
+               fix->visual = (par->cmap_type != cmap_unknown) ?
+                       FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR;
        } else
-               fix->visual =   /* par->cmap_adr ? FB_VISUAL_DIRECTCOLOR
-                                  : */ FB_VISUAL_TRUECOLOR;
+               fix->visual = FB_VISUAL_TRUECOLOR;
 
        var->xoffset = var->yoffset = 0;
        switch (depth) {
@@ -520,5 +401,139 @@ static void __init offb_init_fb(const char *name, const char *full_name,
               info->node, full_name);
 }
 
+
+static void __init offb_init_nodriver(struct device_node *dp, int no_real_node)
+{
+       unsigned int len;
+       int i, width = 640, height = 480, depth = 8, pitch = 640;
+       unsigned int flags, rsize, addr_prop = 0;
+       unsigned long max_size = 0;
+       u64 rstart, address = OF_BAD_ADDR;
+       u32 *pp, *addrp, *up;
+       u64 asize;
+
+       pp = (u32 *)get_property(dp, "linux,bootx-depth", &len);
+       if (pp == NULL)
+               pp = (u32 *)get_property(dp, "depth", &len);
+       if (pp && len == sizeof(u32))
+               depth = *pp;
+
+       pp = (u32 *)get_property(dp, "linux,bootx-width", &len);
+       if (pp == NULL)
+               pp = (u32 *)get_property(dp, "width", &len);
+       if (pp && len == sizeof(u32))
+               width = *pp;
+
+       pp = (u32 *)get_property(dp, "linux,bootx-height", &len);
+       if (pp == NULL)
+               pp = (u32 *)get_property(dp, "height", &len);
+       if (pp && len == sizeof(u32))
+               height = *pp;
+
+       pp = (u32 *)get_property(dp, "linux,bootx-linebytes", &len);
+       if (pp == NULL)
+               pp = (u32 *)get_property(dp, "linebytes", &len);
+       if (pp && len == sizeof(u32))
+               pitch = *pp;
+       else
+               pitch = width * ((depth + 7) / 8);
+
+       rsize = (unsigned long)pitch * (unsigned long)height;
+
+       /* Ok, now we try to figure out the address of the framebuffer.
+        *
+        * Unfortunately, Open Firmware doesn't provide a standard way to do
+        * so. All we can do is a dodgy heuristic that happens to work in
+        * practice. On most machines, the "address" property contains what
+        * we need, though not on Matrox cards found in IBM machines. What I've
+        * found that appears to give good results is to go through the PCI
+        * ranges and pick one that is both big enough and if possible encloses
+        * the "address" property. If none match, we pick the biggest
+        */
+       up = (u32 *)get_property(dp, "linux,bootx-addr", &len);
+       if (up == NULL)
+               up = (u32 *)get_property(dp, "address", &len);
+       if (up && len == sizeof(u32))
+               addr_prop = *up;
+
+       /* Hack for when BootX is passing us */
+       if (no_real_node)
+               goto skip_addr;
+
+       for (i = 0; (addrp = of_get_address(dp, i, &asize, &flags))
+                    != NULL; i++) {
+               int match_addrp = 0;
+
+               if (!(flags & IORESOURCE_MEM))
+                       continue;
+               if (asize < rsize)
+                       continue;
+               rstart = of_translate_address(dp, addrp);
+               if (rstart == OF_BAD_ADDR)
+                       continue;
+               if (addr_prop && (rstart <= addr_prop) &&
+                   ((rstart + asize) >= (addr_prop + rsize)))
+                       match_addrp = 1;
+               if (match_addrp) {
+                       address = addr_prop;
+                       break;
+               }
+               if (rsize > max_size) {
+                       max_size = rsize;
+                       address = OF_BAD_ADDR;
+               }
+
+               if (address == OF_BAD_ADDR)
+                       address = rstart;
+       }
+ skip_addr:
+       if (address == OF_BAD_ADDR && addr_prop)
+               address = (u64)addr_prop;
+       if (address != OF_BAD_ADDR) {
+               /* kludge for valkyrie */
+               if (strcmp(dp->name, "valkyrie") == 0)
+                       address += 0x1000;
+               offb_init_fb(no_real_node ? "bootx" : dp->name,
+                            no_real_node ? "display" : dp->full_name,
+                            width, height, depth, pitch, address,
+                            no_real_node ? dp : NULL);
+       }
+}
+
+static int __init offb_init(void)
+{
+       struct device_node *dp = NULL, *boot_disp = NULL;
+
+       if (fb_get_options("offb", NULL))
+               return -ENODEV;
+
+       /* Check if we have a MacOS display without a node spec */
+       if (get_property(of_chosen, "linux,bootx-noscreen", NULL) != NULL) {
+               /* The old code tried to work out which node was the MacOS
+                * display based on the address. I'm dropping that since the
+                * lack of a node spec only happens with old BootX versions
+                * (users can update) and with this code, they'll still get
+                * a display (just not the palette hacks).
+                */
+               offb_init_nodriver(of_chosen, 1);
+       }
+
+       for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) {
+               if (get_property(dp, "linux,opened", NULL) &&
+                   get_property(dp, "linux,boot-display", NULL)) {
+                       boot_disp = dp;
+                       offb_init_nodriver(dp, 0);
+               }
+       }
+       for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) {
+               if (get_property(dp, "linux,opened", NULL) &&
+                   dp != boot_disp)
+                       offb_init_nodriver(dp, 0);
+       }
+
+       return 0;
+}
+
+
 module_init(offb_init);
 MODULE_LICENSE("GPL");