···151151SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \152152 -e s/arm.*/arm/ -e s/sa110/arm/ \153153 -e s/s390x/s390/ -e s/parisc64/parisc/ \154154- -e s/ppc64/powerpc/ )154154+ -e s/ppc.*/powerpc/ )155155156156# Cross compiling and selecting different set of gcc/bin-utils157157# ---------------------------------------------------------------------------
+10-11
arch/powerpc/Kconfig
···7878 bool7979 default n80808181-config CRASH_DUMP8282- bool "kernel crash dumps (EXPERIMENTAL)"8383- depends on PPC_MULTIPLATFORM8484- depends on EXPERIMENTAL8585- help8686- Build a kernel suitable for use as a kdump capture kernel.8787- The kernel will be linked at a different address than normal, and8888- so can only be used for Kdump.8989-9090- Don't change this unless you know what you are doing.9191-9281config GENERIC_TBSYNC9382 bool9483 default y if PPC32 && SMP···572583 initially work for you. It may help to enable device hotplugging573584 support. As of this writing the exact hardware interface is574585 strongly in flux, so no good recommendation can be made.586586+587587+config CRASH_DUMP588588+ bool "kernel crash dumps (EXPERIMENTAL)"589589+ depends on PPC_MULTIPLATFORM && PPC64 && EXPERIMENTAL590590+ help591591+ Build a kernel suitable for use as a kdump capture kernel.592592+ The kernel will be linked at a different address than normal, and593593+ so can only be used for Kdump.594594+595595+ Don't change this unless you know what you are doing.575596576597config EMBEDDEDBOOT577598 bool
···11#22# Automatically generated make config: don't edit33-# Linux kernel version: 2.6.15-rc544-# Tue Dec 13 17:24:05 200533+# Linux kernel version: 2.6.1544+# Sat Jan 14 16:26:08 200655#66# CONFIG_PPC64 is not set77CONFIG_PPC32=y···1515CONFIG_GENERIC_NVRAM=y1616CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y1717CONFIG_ARCH_MAY_HAVE_PC_FDC=y1818+CONFIG_PPC_OF=y1919+# CONFIG_PPC_UDBG_16550 is not set2020+# CONFIG_CRASH_DUMP is not set2121+# CONFIG_GENERIC_TBSYNC is not set18221923#2024# Processor support2125#2222-CONFIG_6xx=y2626+CONFIG_CLASSIC32=y2327# CONFIG_PPC_52xx is not set2428# CONFIG_PPC_82xx is not set2529# CONFIG_PPC_83xx is not set···3228# CONFIG_8xx is not set3329# CONFIG_E200 is not set3430# CONFIG_E500 is not set3131+CONFIG_6xx=y3532CONFIG_PPC_FPU=y3633CONFIG_ALTIVEC=y3734CONFIG_PPC_STD_MMU=y···5853# CONFIG_BSD_PROCESS_ACCT is not set5954CONFIG_SYSCTL=y6055# CONFIG_AUDIT is not set6161-CONFIG_HOTPLUG=y6262-CONFIG_KOBJECT_UEVENT=y6356CONFIG_IKCONFIG=y6457CONFIG_IKCONFIG_PROC=y6558CONFIG_INITRAMFS_SOURCE=""5959+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set6660# CONFIG_EMBEDDED is not set6761CONFIG_KALLSYMS=y6862# CONFIG_KALLSYMS_ALL is not set6963# CONFIG_KALLSYMS_EXTRA_PASS is not set6464+CONFIG_HOTPLUG=y7065CONFIG_PRINTK=y7166CONFIG_BUG=y6767+CONFIG_ELF_CORE=y7268CONFIG_BASE_FULL=y7369CONFIG_FUTEX=y7470CONFIG_EPOLL=y···7872CONFIG_CC_ALIGN_LABELS=07973CONFIG_CC_ALIGN_LOOPS=08074CONFIG_CC_ALIGN_JUMPS=07575+CONFIG_SLAB=y8176# CONFIG_TINY_SHMEM is not set8277CONFIG_BASE_SMALL=07878+# CONFIG_SLOB is not set83798480#8581# Loadable module support···121113# CONFIG_APUS is not set122114# CONFIG_PPC_CHRP is not set123115CONFIG_PPC_PMAC=y124124-CONFIG_PPC_OF=y125116CONFIG_MPIC=y126117# CONFIG_PPC_RTAS is not set127118# CONFIG_MMIO_NVRAM is not set128128-# CONFIG_CRASH_DUMP is not set129119CONFIG_PPC_MPC106=y130130-# CONFIG_GENERIC_TBSYNC is not set131120CONFIG_CPU_FREQ=y132121CONFIG_CPU_FREQ_TABLE=y133122# CONFIG_CPU_FREQ_DEBUG is not set···200195# PC-card bridges201196#202197CONFIG_YENTA=m198198+CONFIG_YENTA_O2=y199199+CONFIG_YENTA_RICOH=y200200+CONFIG_YENTA_TI=y201201+CONFIG_YENTA_ENE_TUNE=y202202+CONFIG_YENTA_TOSHIBA=y203203# CONFIG_PD6729 is not set204204# CONFIG_I82092 is not set205205CONFIG_PCCARD_NONSTATIC=m···474464#475465# CONFIG_STANDALONE is not set476466CONFIG_PREVENT_FIRMWARE_BUILD=y477477-CONFIG_FW_LOADER=m467467+CONFIG_FW_LOADER=y478468# CONFIG_DEBUG_DRIVER is not set479469480470#···501491# Block devices502492#503493# CONFIG_BLK_DEV_FD is not set504504-CONFIG_MAC_FLOPPY=y494494+CONFIG_MAC_FLOPPY=m505495# CONFIG_BLK_CPQ_DA is not set506496# CONFIG_BLK_CPQ_CISS_DA is not set507497# CONFIG_BLK_DEV_DAC960 is not set···613603# SCSI Transport Attributes614604#615605CONFIG_SCSI_SPI_ATTRS=y616616-# CONFIG_SCSI_FC_ATTRS is not set606606+CONFIG_SCSI_FC_ATTRS=y617607# CONFIG_SCSI_ISCSI_ATTRS is not set618608# CONFIG_SCSI_SAS_ATTRS is not set619609···655645# CONFIG_SCSI_QLOGIC_FC is not set656646# CONFIG_SCSI_QLOGIC_1280 is not set657647CONFIG_SCSI_QLA2XXX=y658658-# CONFIG_SCSI_QLA21XX is not set659659-# CONFIG_SCSI_QLA22XX is not set660660-# CONFIG_SCSI_QLA2300 is not set661661-# CONFIG_SCSI_QLA2322 is not set662662-# CONFIG_SCSI_QLA6312 is not set663663-# CONFIG_SCSI_QLA24XX is not set648648+# CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE is not set664649# CONFIG_SCSI_LPFC is not set665650# CONFIG_SCSI_DC395x is not set666651# CONFIG_SCSI_DC390T is not set···663658# CONFIG_SCSI_DEBUG is not set664659CONFIG_SCSI_MESH=y665660CONFIG_SCSI_MESH_SYNC_RATE=5666666-CONFIG_SCSI_MESH_RESET_DELAY_MS=1000661661+CONFIG_SCSI_MESH_RESET_DELAY_MS=4000667662CONFIG_SCSI_MAC53C94=y668663669664#···732727CONFIG_IEEE1394_ETH1394=m733728CONFIG_IEEE1394_DV1394=m734729CONFIG_IEEE1394_RAWIO=m735735-# CONFIG_IEEE1394_CMP is not set736730737731#738732# I2O device support···744740CONFIG_ADB=y745741CONFIG_ADB_CUDA=y746742CONFIG_ADB_PMU=y747747-CONFIG_PMAC_APM_EMU=y743743+CONFIG_PMAC_APM_EMU=m748744CONFIG_PMAC_MEDIABAY=y749745CONFIG_PMAC_BACKLIGHT=y750746CONFIG_INPUT_ADBHID=y···823819# CONFIG_R8169 is not set824820# CONFIG_SIS190 is not set825821# CONFIG_SKGE is not set822822+# CONFIG_SKY2 is not set826823# CONFIG_SK98LIN is not set827824# CONFIG_VIA_VELOCITY is not set828825# CONFIG_TIGON3 is not set···983978CONFIG_SERIAL_8250=m984979# CONFIG_SERIAL_8250_CS is not set985980CONFIG_SERIAL_8250_NR_UARTS=4981981+CONFIG_SERIAL_8250_RUNTIME_UARTS=4986982# CONFIG_SERIAL_8250_EXTENDED is not set987983988984#989985# Non-8250 serial port support990986#991987CONFIG_SERIAL_CORE=m992992-# CONFIG_SERIAL_PMACZILOG is not set993993-# CONFIG_SERIAL_JSM is not set988988+CONFIG_SERIAL_PMACZILOG=m994989CONFIG_UNIX98_PTYS=y995990CONFIG_LEGACY_PTYS=y996991CONFIG_LEGACY_PTY_COUNT=256···10631058# CONFIG_I2C_I801 is not set10641059# CONFIG_I2C_I810 is not set10651060# CONFIG_I2C_PIIX4 is not set10661066-CONFIG_I2C_KEYWEST=m10611061+CONFIG_I2C_POWERMAC=y10671062# CONFIG_I2C_MPC is not set10681063# CONFIG_I2C_NFORCE2 is not set10691064# CONFIG_I2C_PARPORT_LIGHT is not set···11651160CONFIG_FB_ATY=y11661161CONFIG_FB_ATY_CT=y11671162# CONFIG_FB_ATY_GENERIC_LCD is not set11681168-# CONFIG_FB_ATY_XL_INIT is not set11691163CONFIG_FB_ATY_GX=y11701164# CONFIG_FB_SAVAGE is not set11711165# CONFIG_FB_SIS is not set···11731169CONFIG_FB_3DFX=y11741170# CONFIG_FB_3DFX_ACCEL is not set11751171# CONFIG_FB_VOODOO1 is not set11761176-# CONFIG_FB_CYBLA is not set11771172# CONFIG_FB_TRIDENT is not set11781173# CONFIG_FB_VIRTUAL is not set11791174···12171214CONFIG_SND_MIXER_OSS=m12181215CONFIG_SND_PCM_OSS=m12191216CONFIG_SND_SEQUENCER_OSS=y12171217+# CONFIG_SND_DYNAMIC_MINORS is not set12181218+CONFIG_SND_SUPPORT_OLD_API=y12201219# CONFIG_SND_VERBOSE_PRINTK is not set12211220# CONFIG_SND_DEBUG is not set12221222-CONFIG_SND_GENERIC_DRIVER=y1223122112241222#12251223# Generic devices···12341230#12351231# PCI devices12361232#12331233+# CONFIG_SND_AD1889 is not set12341234+# CONFIG_SND_ALS4000 is not set12371235# CONFIG_SND_ALI5451 is not set12381236# CONFIG_SND_ATIIXP is not set12391237# CONFIG_SND_ATIIXP_MODEM is not set···12441238# CONFIG_SND_AU8830 is not set12451239# CONFIG_SND_AZT3328 is not set12461240# CONFIG_SND_BT87X is not set12471247-# CONFIG_SND_CS46XX is not set12411241+# CONFIG_SND_CA0106 is not set12421242+# CONFIG_SND_CMIPCI is not set12481243# CONFIG_SND_CS4281 is not set12441244+# CONFIG_SND_CS46XX is not set12491245# CONFIG_SND_EMU10K1 is not set12501246# CONFIG_SND_EMU10K1X is not set12511251-# CONFIG_SND_CA0106 is not set12521252-# CONFIG_SND_KORG1212 is not set12531253-# CONFIG_SND_MIXART is not set12541254-# CONFIG_SND_NM256 is not set12551255-# CONFIG_SND_RME32 is not set12561256-# CONFIG_SND_RME96 is not set12571257-# CONFIG_SND_RME9652 is not set12581258-# CONFIG_SND_HDSP is not set12591259-# CONFIG_SND_HDSPM is not set12601260-# CONFIG_SND_TRIDENT is not set12611261-# CONFIG_SND_YMFPCI is not set12621262-# CONFIG_SND_AD1889 is not set12631263-# CONFIG_SND_ALS4000 is not set12641264-# CONFIG_SND_CMIPCI is not set12651247# CONFIG_SND_ENS1370 is not set12661248# CONFIG_SND_ENS1371 is not set12671249# CONFIG_SND_ES1938 is not set12681250# CONFIG_SND_ES1968 is not set12691269-# CONFIG_SND_MAESTRO3 is not set12701251# CONFIG_SND_FM801 is not set12521252+# CONFIG_SND_HDA_INTEL is not set12531253+# CONFIG_SND_HDSP is not set12541254+# CONFIG_SND_HDSPM is not set12711255# CONFIG_SND_ICE1712 is not set12721256# CONFIG_SND_ICE1724 is not set12731257# CONFIG_SND_INTEL8X0 is not set12741258# CONFIG_SND_INTEL8X0M is not set12591259+# CONFIG_SND_KORG1212 is not set12601260+# CONFIG_SND_MAESTRO3 is not set12611261+# CONFIG_SND_MIXART is not set12621262+# CONFIG_SND_NM256 is not set12631263+# CONFIG_SND_PCXHR is not set12641264+# CONFIG_SND_RME32 is not set12651265+# CONFIG_SND_RME96 is not set12661266+# CONFIG_SND_RME9652 is not set12751267# CONFIG_SND_SONICVIBES is not set12681268+# CONFIG_SND_TRIDENT is not set12761269# CONFIG_SND_VIA82XX is not set12771270# CONFIG_SND_VIA82XX_MODEM is not set12781271# CONFIG_SND_VX222 is not set12791279-# CONFIG_SND_HDA_INTEL is not set12721272+# CONFIG_SND_YMFPCI is not set1280127312811274#12821275# ALSA PowerMac devices12831276#12841277CONFIG_SND_POWERMAC=m12851285-# CONFIG_SND_POWERMAC_AUTO_DRC is not set12781278+CONFIG_SND_POWERMAC_AUTO_DRC=y1286127912871280#12881281# USB devices···13411336# may also be needed; see USB_STORAGE Help for more information13421337#13431338# CONFIG_USB_STORAGE is not set13391339+# CONFIG_USB_LIBUSUAL is not set1344134013451341#13461342# USB Input Devices···13611355# CONFIG_USB_YEALINK is not set13621356# CONFIG_USB_XPAD is not set13631357# CONFIG_USB_ATI_REMOTE is not set13581358+# CONFIG_USB_ATI_REMOTE2 is not set13641359# CONFIG_USB_KEYSPAN_REMOTE is not set13651360CONFIG_USB_APPLETOUCH=y13661361···15081501# CONFIG_JFS_FS is not set15091502# CONFIG_FS_POSIX_ACL is not set15101503# CONFIG_XFS_FS is not set15041504+# CONFIG_OCFS2_FS is not set15111505# CONFIG_MINIX_FS is not set15121506# CONFIG_ROMFS_FS is not set15131507CONFIG_INOTIFY=y···15481540# CONFIG_HUGETLB_PAGE is not set15491541CONFIG_RAMFS=y15501542CONFIG_RELAYFS_FS=m15431543+# CONFIG_CONFIGFS_FS is not set1551154415521545#15531546# Miscellaneous filesystems···16791670# Kernel hacking16801671#16811672# CONFIG_PRINTK_TIME is not set16821682-CONFIG_DEBUG_KERNEL=y16831673# CONFIG_MAGIC_SYSRQ is not set16741674+CONFIG_DEBUG_KERNEL=y16841675CONFIG_LOG_BUF_SHIFT=1416851676CONFIG_DETECT_SOFTLOCKUP=y16861677# CONFIG_SCHEDSTATS is not set16871678# CONFIG_DEBUG_SLAB is not set16791679+# CONFIG_DEBUG_MUTEXES is not set16881680# CONFIG_DEBUG_SPINLOCK is not set16891681# CONFIG_DEBUG_SPINLOCK_SLEEP is not set16901682# CONFIG_DEBUG_KOBJECT is not set···16981688CONFIG_XMON_DEFAULT=y16991689# CONFIG_BDI_SWITCH is not set17001690CONFIG_BOOTX_TEXT=y16911691+# CONFIG_PPC_EARLY_DEBUG_LPAR is not set16921692+# CONFIG_PPC_EARLY_DEBUG_G5 is not set16931693+# CONFIG_PPC_EARLY_DEBUG_RTAS is not set16941694+# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set16951695+# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set1701169617021697#17031698# Security options
···8484 * squirrelled away. ELF notes happen to provide8585 * all of that that no need to invent something new.8686 */8787- buf = &crash_notes[cpu][0];8787+ buf = (u32*)per_cpu_ptr(crash_notes, cpu);8888+ if (!buf) 8989+ return;9090+8891 memset(&prstatus, 0, sizeof(prstatus));8992 prstatus.pr_pid = current->pid;9093 elf_core_copy_regs(&prstatus.pr_reg, regs);9194 buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus,9295 sizeof(prstatus));9396 final_note(buf);9494-}9595-9696-/* FIXME Merge this with xmon_save_regs ?? */9797-static inline void crash_get_current_regs(struct pt_regs *regs)9898-{9999- unsigned long tmp1, tmp2;100100-101101- __asm__ __volatile__ (102102- "std 0,0(%2)\n"103103- "std 1,8(%2)\n"104104- "std 2,16(%2)\n"105105- "std 3,24(%2)\n"106106- "std 4,32(%2)\n"107107- "std 5,40(%2)\n"108108- "std 6,48(%2)\n"109109- "std 7,56(%2)\n"110110- "std 8,64(%2)\n"111111- "std 9,72(%2)\n"112112- "std 10,80(%2)\n"113113- "std 11,88(%2)\n"114114- "std 12,96(%2)\n"115115- "std 13,104(%2)\n"116116- "std 14,112(%2)\n"117117- "std 15,120(%2)\n"118118- "std 16,128(%2)\n"119119- "std 17,136(%2)\n"120120- "std 18,144(%2)\n"121121- "std 19,152(%2)\n"122122- "std 20,160(%2)\n"123123- "std 21,168(%2)\n"124124- "std 22,176(%2)\n"125125- "std 23,184(%2)\n"126126- "std 24,192(%2)\n"127127- "std 25,200(%2)\n"128128- "std 26,208(%2)\n"129129- "std 27,216(%2)\n"130130- "std 28,224(%2)\n"131131- "std 29,232(%2)\n"132132- "std 30,240(%2)\n"133133- "std 31,248(%2)\n"134134- "mfmsr %0\n"135135- "std %0, 264(%2)\n"136136- "mfctr %0\n"137137- "std %0, 280(%2)\n"138138- "mflr %0\n"139139- "std %0, 288(%2)\n"140140- "bl 1f\n"141141- "1: mflr %1\n"142142- "std %1, 256(%2)\n"143143- "mtlr %0\n"144144- "mfxer %0\n"145145- "std %0, 296(%2)\n"146146- : "=&r" (tmp1), "=&r" (tmp2)147147- : "b" (regs));148148-}149149-150150-/* We may have saved_regs from where the error came from151151- * or it is NULL if via a direct panic().152152- */153153-static void crash_save_self(struct pt_regs *saved_regs)154154-{155155- struct pt_regs regs;156156- int cpu;157157-158158- cpu = smp_processor_id();159159- if (saved_regs)160160- memcpy(®s, saved_regs, sizeof(regs));161161- else162162- crash_get_current_regs(®s);163163- crash_save_this_cpu(®s, cpu);16497}1659816699#ifdef CONFIG_SMP···193260 */194261 crashing_cpu = smp_processor_id();195262 crash_kexec_prepare_cpus();196196- crash_save_self(regs);263263+ crash_save_this_cpu(regs, crashing_cpu);197264}
+1897
arch/powerpc/kernel/pci_32.c
···11+/*22+ * Common pmac/prep/chrp pci routines. -- Cort33+ */44+55+#include <linux/config.h>66+#include <linux/kernel.h>77+#include <linux/pci.h>88+#include <linux/delay.h>99+#include <linux/string.h>1010+#include <linux/init.h>1111+#include <linux/capability.h>1212+#include <linux/sched.h>1313+#include <linux/errno.h>1414+#include <linux/bootmem.h>1515+1616+#include <asm/processor.h>1717+#include <asm/io.h>1818+#include <asm/prom.h>1919+#include <asm/sections.h>2020+#include <asm/pci-bridge.h>2121+#include <asm/byteorder.h>2222+#include <asm/irq.h>2323+#include <asm/uaccess.h>2424+#include <asm/machdep.h>2525+2626+#undef DEBUG2727+2828+#ifdef DEBUG2929+#define DBG(x...) printk(x)3030+#else3131+#define DBG(x...)3232+#endif3333+3434+unsigned long isa_io_base = 0;3535+unsigned long isa_mem_base = 0;3636+unsigned long pci_dram_offset = 0;3737+int pcibios_assign_bus_offset = 1;3838+3939+void pcibios_make_OF_bus_map(void);4040+4141+static int pci_relocate_bridge_resource(struct pci_bus *bus, int i);4242+static int probe_resource(struct pci_bus *parent, struct resource *pr,4343+ struct resource *res, struct resource **conflict);4444+static void update_bridge_base(struct pci_bus *bus, int i);4545+static void pcibios_fixup_resources(struct pci_dev* dev);4646+static void fixup_broken_pcnet32(struct pci_dev* dev);4747+static int reparent_resources(struct resource *parent, struct resource *res);4848+static void fixup_cpc710_pci64(struct pci_dev* dev);4949+#ifdef CONFIG_PPC_OF5050+static u8* pci_to_OF_bus_map;5151+#endif5252+5353+/* By default, we don't re-assign bus numbers. We do this only on5454+ * some pmacs5555+ */5656+int pci_assign_all_buses;5757+5858+struct pci_controller* hose_head;5959+struct pci_controller** hose_tail = &hose_head;6060+6161+static int pci_bus_count;6262+6363+static void6464+fixup_broken_pcnet32(struct pci_dev* dev)6565+{6666+ if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) {6767+ dev->vendor = PCI_VENDOR_ID_AMD;6868+ pci_write_config_word(dev, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);6969+ }7070+}7171+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32);7272+7373+static void7474+fixup_cpc710_pci64(struct pci_dev* dev)7575+{7676+ /* Hide the PCI64 BARs from the kernel as their content doesn't7777+ * fit well in the resource management7878+ */7979+ dev->resource[0].start = dev->resource[0].end = 0;8080+ dev->resource[0].flags = 0;8181+ dev->resource[1].start = dev->resource[1].end = 0;8282+ dev->resource[1].flags = 0;8383+}8484+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CPC710_PCI64, fixup_cpc710_pci64);8585+8686+static void8787+pcibios_fixup_resources(struct pci_dev *dev)8888+{8989+ struct pci_controller* hose = (struct pci_controller *)dev->sysdata;9090+ int i;9191+ unsigned long offset;9292+9393+ if (!hose) {9494+ printk(KERN_ERR "No hose for PCI dev %s!\n", pci_name(dev));9595+ return;9696+ }9797+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {9898+ struct resource *res = dev->resource + i;9999+ if (!res->flags)100100+ continue;101101+ if (res->end == 0xffffffff) {102102+ DBG("PCI:%s Resource %d [%08lx-%08lx] is unassigned\n",103103+ pci_name(dev), i, res->start, res->end);104104+ res->end -= res->start;105105+ res->start = 0;106106+ res->flags |= IORESOURCE_UNSET;107107+ continue;108108+ }109109+ offset = 0;110110+ if (res->flags & IORESOURCE_MEM) {111111+ offset = hose->pci_mem_offset;112112+ } else if (res->flags & IORESOURCE_IO) {113113+ offset = (unsigned long) hose->io_base_virt114114+ - isa_io_base;115115+ }116116+ if (offset != 0) {117117+ res->start += offset;118118+ res->end += offset;119119+#ifdef DEBUG120120+ printk("Fixup res %d (%lx) of dev %s: %lx -> %lx\n",121121+ i, res->flags, pci_name(dev),122122+ res->start - offset, res->start);123123+#endif124124+ }125125+ }126126+127127+ /* Call machine specific resource fixup */128128+ if (ppc_md.pcibios_fixup_resources)129129+ ppc_md.pcibios_fixup_resources(dev);130130+}131131+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources);132132+133133+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,134134+ struct resource *res)135135+{136136+ unsigned long offset = 0;137137+ struct pci_controller *hose = dev->sysdata;138138+139139+ if (hose && res->flags & IORESOURCE_IO)140140+ offset = (unsigned long)hose->io_base_virt - isa_io_base;141141+ else if (hose && res->flags & IORESOURCE_MEM)142142+ offset = hose->pci_mem_offset;143143+ region->start = res->start - offset;144144+ region->end = res->end - offset;145145+}146146+EXPORT_SYMBOL(pcibios_resource_to_bus);147147+148148+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,149149+ struct pci_bus_region *region)150150+{151151+ unsigned long offset = 0;152152+ struct pci_controller *hose = dev->sysdata;153153+154154+ if (hose && res->flags & IORESOURCE_IO)155155+ offset = (unsigned long)hose->io_base_virt - isa_io_base;156156+ else if (hose && res->flags & IORESOURCE_MEM)157157+ offset = hose->pci_mem_offset;158158+ res->start = region->start + offset;159159+ res->end = region->end + offset;160160+}161161+EXPORT_SYMBOL(pcibios_bus_to_resource);162162+163163+/*164164+ * We need to avoid collisions with `mirrored' VGA ports165165+ * and other strange ISA hardware, so we always want the166166+ * addresses to be allocated in the 0x000-0x0ff region167167+ * modulo 0x400.168168+ *169169+ * Why? Because some silly external IO cards only decode170170+ * the low 10 bits of the IO address. The 0x00-0xff region171171+ * is reserved for motherboard devices that decode all 16172172+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,173173+ * but we want to try to avoid allocating at 0x2900-0x2bff174174+ * which might have be mirrored at 0x0100-0x03ff..175175+ */176176+void pcibios_align_resource(void *data, struct resource *res, unsigned long size,177177+ unsigned long align)178178+{179179+ struct pci_dev *dev = data;180180+181181+ if (res->flags & IORESOURCE_IO) {182182+ unsigned long start = res->start;183183+184184+ if (size > 0x100) {185185+ printk(KERN_ERR "PCI: I/O Region %s/%d too large"186186+ " (%ld bytes)\n", pci_name(dev),187187+ dev->resource - res, size);188188+ }189189+190190+ if (start & 0x300) {191191+ start = (start + 0x3ff) & ~0x3ff;192192+ res->start = start;193193+ }194194+ }195195+}196196+EXPORT_SYMBOL(pcibios_align_resource);197197+198198+/*199199+ * Handle resources of PCI devices. If the world were perfect, we could200200+ * just allocate all the resource regions and do nothing more. It isn't.201201+ * On the other hand, we cannot just re-allocate all devices, as it would202202+ * require us to know lots of host bridge internals. So we attempt to203203+ * keep as much of the original configuration as possible, but tweak it204204+ * when it's found to be wrong.205205+ *206206+ * Known BIOS problems we have to work around:207207+ * - I/O or memory regions not configured208208+ * - regions configured, but not enabled in the command register209209+ * - bogus I/O addresses above 64K used210210+ * - expansion ROMs left enabled (this may sound harmless, but given211211+ * the fact the PCI specs explicitly allow address decoders to be212212+ * shared between expansion ROMs and other resource regions, it's213213+ * at least dangerous)214214+ *215215+ * Our solution:216216+ * (1) Allocate resources for all buses behind PCI-to-PCI bridges.217217+ * This gives us fixed barriers on where we can allocate.218218+ * (2) Allocate resources for all enabled devices. If there is219219+ * a collision, just mark the resource as unallocated. Also220220+ * disable expansion ROMs during this step.221221+ * (3) Try to allocate resources for disabled devices. If the222222+ * resources were assigned correctly, everything goes well,223223+ * if they weren't, they won't disturb allocation of other224224+ * resources.225225+ * (4) Assign new addresses to resources which were either226226+ * not configured at all or misconfigured. If explicitly227227+ * requested by the user, configure expansion ROM address228228+ * as well.229229+ */230230+231231+static void __init232232+pcibios_allocate_bus_resources(struct list_head *bus_list)233233+{234234+ struct pci_bus *bus;235235+ int i;236236+ struct resource *res, *pr;237237+238238+ /* Depth-First Search on bus tree */239239+ list_for_each_entry(bus, bus_list, node) {240240+ for (i = 0; i < 4; ++i) {241241+ if ((res = bus->resource[i]) == NULL || !res->flags242242+ || res->start > res->end)243243+ continue;244244+ if (bus->parent == NULL)245245+ pr = (res->flags & IORESOURCE_IO)?246246+ &ioport_resource: &iomem_resource;247247+ else {248248+ pr = pci_find_parent_resource(bus->self, res);249249+ if (pr == res) {250250+ /* this happens when the generic PCI251251+ * code (wrongly) decides that this252252+ * bridge is transparent -- paulus253253+ */254254+ continue;255255+ }256256+ }257257+258258+ DBG("PCI: bridge rsrc %lx..%lx (%lx), parent %p\n",259259+ res->start, res->end, res->flags, pr);260260+ if (pr) {261261+ if (request_resource(pr, res) == 0)262262+ continue;263263+ /*264264+ * Must be a conflict with an existing entry.265265+ * Move that entry (or entries) under the266266+ * bridge resource and try again.267267+ */268268+ if (reparent_resources(pr, res) == 0)269269+ continue;270270+ }271271+ printk(KERN_ERR "PCI: Cannot allocate resource region "272272+ "%d of PCI bridge %d\n", i, bus->number);273273+ if (pci_relocate_bridge_resource(bus, i))274274+ bus->resource[i] = NULL;275275+ }276276+ pcibios_allocate_bus_resources(&bus->children);277277+ }278278+}279279+280280+/*281281+ * Reparent resource children of pr that conflict with res282282+ * under res, and make res replace those children.283283+ */284284+static int __init285285+reparent_resources(struct resource *parent, struct resource *res)286286+{287287+ struct resource *p, **pp;288288+ struct resource **firstpp = NULL;289289+290290+ for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) {291291+ if (p->end < res->start)292292+ continue;293293+ if (res->end < p->start)294294+ break;295295+ if (p->start < res->start || p->end > res->end)296296+ return -1; /* not completely contained */297297+ if (firstpp == NULL)298298+ firstpp = pp;299299+ }300300+ if (firstpp == NULL)301301+ return -1; /* didn't find any conflicting entries? */302302+ res->parent = parent;303303+ res->child = *firstpp;304304+ res->sibling = *pp;305305+ *firstpp = res;306306+ *pp = NULL;307307+ for (p = res->child; p != NULL; p = p->sibling) {308308+ p->parent = res;309309+ DBG(KERN_INFO "PCI: reparented %s [%lx..%lx] under %s\n",310310+ p->name, p->start, p->end, res->name);311311+ }312312+ return 0;313313+}314314+315315+/*316316+ * A bridge has been allocated a range which is outside the range317317+ * of its parent bridge, so it needs to be moved.318318+ */319319+static int __init320320+pci_relocate_bridge_resource(struct pci_bus *bus, int i)321321+{322322+ struct resource *res, *pr, *conflict;323323+ unsigned long try, size;324324+ int j;325325+ struct pci_bus *parent = bus->parent;326326+327327+ if (parent == NULL) {328328+ /* shouldn't ever happen */329329+ printk(KERN_ERR "PCI: can't move host bridge resource\n");330330+ return -1;331331+ }332332+ res = bus->resource[i];333333+ if (res == NULL)334334+ return -1;335335+ pr = NULL;336336+ for (j = 0; j < 4; j++) {337337+ struct resource *r = parent->resource[j];338338+ if (!r)339339+ continue;340340+ if ((res->flags ^ r->flags) & (IORESOURCE_IO | IORESOURCE_MEM))341341+ continue;342342+ if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH)) {343343+ pr = r;344344+ break;345345+ }346346+ if (res->flags & IORESOURCE_PREFETCH)347347+ pr = r;348348+ }349349+ if (pr == NULL)350350+ return -1;351351+ size = res->end - res->start;352352+ if (pr->start > pr->end || size > pr->end - pr->start)353353+ return -1;354354+ try = pr->end;355355+ for (;;) {356356+ res->start = try - size;357357+ res->end = try;358358+ if (probe_resource(bus->parent, pr, res, &conflict) == 0)359359+ break;360360+ if (conflict->start <= pr->start + size)361361+ return -1;362362+ try = conflict->start - 1;363363+ }364364+ if (request_resource(pr, res)) {365365+ DBG(KERN_ERR "PCI: huh? couldn't move to %lx..%lx\n",366366+ res->start, res->end);367367+ return -1; /* "can't happen" */368368+ }369369+ update_bridge_base(bus, i);370370+ printk(KERN_INFO "PCI: bridge %d resource %d moved to %lx..%lx\n",371371+ bus->number, i, res->start, res->end);372372+ return 0;373373+}374374+375375+static int __init376376+probe_resource(struct pci_bus *parent, struct resource *pr,377377+ struct resource *res, struct resource **conflict)378378+{379379+ struct pci_bus *bus;380380+ struct pci_dev *dev;381381+ struct resource *r;382382+ int i;383383+384384+ for (r = pr->child; r != NULL; r = r->sibling) {385385+ if (r->end >= res->start && res->end >= r->start) {386386+ *conflict = r;387387+ return 1;388388+ }389389+ }390390+ list_for_each_entry(bus, &parent->children, node) {391391+ for (i = 0; i < 4; ++i) {392392+ if ((r = bus->resource[i]) == NULL)393393+ continue;394394+ if (!r->flags || r->start > r->end || r == res)395395+ continue;396396+ if (pci_find_parent_resource(bus->self, r) != pr)397397+ continue;398398+ if (r->end >= res->start && res->end >= r->start) {399399+ *conflict = r;400400+ return 1;401401+ }402402+ }403403+ }404404+ list_for_each_entry(dev, &parent->devices, bus_list) {405405+ for (i = 0; i < 6; ++i) {406406+ r = &dev->resource[i];407407+ if (!r->flags || (r->flags & IORESOURCE_UNSET))408408+ continue;409409+ if (pci_find_parent_resource(dev, r) != pr)410410+ continue;411411+ if (r->end >= res->start && res->end >= r->start) {412412+ *conflict = r;413413+ return 1;414414+ }415415+ }416416+ }417417+ return 0;418418+}419419+420420+static void __init421421+update_bridge_base(struct pci_bus *bus, int i)422422+{423423+ struct resource *res = bus->resource[i];424424+ u8 io_base_lo, io_limit_lo;425425+ u16 mem_base, mem_limit;426426+ u16 cmd;427427+ unsigned long start, end, off;428428+ struct pci_dev *dev = bus->self;429429+ struct pci_controller *hose = dev->sysdata;430430+431431+ if (!hose) {432432+ printk("update_bridge_base: no hose?\n");433433+ return;434434+ }435435+ pci_read_config_word(dev, PCI_COMMAND, &cmd);436436+ pci_write_config_word(dev, PCI_COMMAND,437437+ cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY));438438+ if (res->flags & IORESOURCE_IO) {439439+ off = (unsigned long) hose->io_base_virt - isa_io_base;440440+ start = res->start - off;441441+ end = res->end - off;442442+ io_base_lo = (start >> 8) & PCI_IO_RANGE_MASK;443443+ io_limit_lo = (end >> 8) & PCI_IO_RANGE_MASK;444444+ if (end > 0xffff) {445445+ pci_write_config_word(dev, PCI_IO_BASE_UPPER16,446446+ start >> 16);447447+ pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16,448448+ end >> 16);449449+ io_base_lo |= PCI_IO_RANGE_TYPE_32;450450+ } else451451+ io_base_lo |= PCI_IO_RANGE_TYPE_16;452452+ pci_write_config_byte(dev, PCI_IO_BASE, io_base_lo);453453+ pci_write_config_byte(dev, PCI_IO_LIMIT, io_limit_lo);454454+455455+ } else if ((res->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH))456456+ == IORESOURCE_MEM) {457457+ off = hose->pci_mem_offset;458458+ mem_base = ((res->start - off) >> 16) & PCI_MEMORY_RANGE_MASK;459459+ mem_limit = ((res->end - off) >> 16) & PCI_MEMORY_RANGE_MASK;460460+ pci_write_config_word(dev, PCI_MEMORY_BASE, mem_base);461461+ pci_write_config_word(dev, PCI_MEMORY_LIMIT, mem_limit);462462+463463+ } else if ((res->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH))464464+ == (IORESOURCE_MEM | IORESOURCE_PREFETCH)) {465465+ off = hose->pci_mem_offset;466466+ mem_base = ((res->start - off) >> 16) & PCI_PREF_RANGE_MASK;467467+ mem_limit = ((res->end - off) >> 16) & PCI_PREF_RANGE_MASK;468468+ pci_write_config_word(dev, PCI_PREF_MEMORY_BASE, mem_base);469469+ pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT, mem_limit);470470+471471+ } else {472472+ DBG(KERN_ERR "PCI: ugh, bridge %s res %d has flags=%lx\n",473473+ pci_name(dev), i, res->flags);474474+ }475475+ pci_write_config_word(dev, PCI_COMMAND, cmd);476476+}477477+478478+static inline void alloc_resource(struct pci_dev *dev, int idx)479479+{480480+ struct resource *pr, *r = &dev->resource[idx];481481+482482+ DBG("PCI:%s: Resource %d: %08lx-%08lx (f=%lx)\n",483483+ pci_name(dev), idx, r->start, r->end, r->flags);484484+ pr = pci_find_parent_resource(dev, r);485485+ if (!pr || request_resource(pr, r) < 0) {486486+ printk(KERN_ERR "PCI: Cannot allocate resource region %d"487487+ " of device %s\n", idx, pci_name(dev));488488+ if (pr)489489+ DBG("PCI: parent is %p: %08lx-%08lx (f=%lx)\n",490490+ pr, pr->start, pr->end, pr->flags);491491+ /* We'll assign a new address later */492492+ r->flags |= IORESOURCE_UNSET;493493+ r->end -= r->start;494494+ r->start = 0;495495+ }496496+}497497+498498+static void __init499499+pcibios_allocate_resources(int pass)500500+{501501+ struct pci_dev *dev = NULL;502502+ int idx, disabled;503503+ u16 command;504504+ struct resource *r;505505+506506+ for_each_pci_dev(dev) {507507+ pci_read_config_word(dev, PCI_COMMAND, &command);508508+ for (idx = 0; idx < 6; idx++) {509509+ r = &dev->resource[idx];510510+ if (r->parent) /* Already allocated */511511+ continue;512512+ if (!r->flags || (r->flags & IORESOURCE_UNSET))513513+ continue; /* Not assigned at all */514514+ if (r->flags & IORESOURCE_IO)515515+ disabled = !(command & PCI_COMMAND_IO);516516+ else517517+ disabled = !(command & PCI_COMMAND_MEMORY);518518+ if (pass == disabled)519519+ alloc_resource(dev, idx);520520+ }521521+ if (pass)522522+ continue;523523+ r = &dev->resource[PCI_ROM_RESOURCE];524524+ if (r->flags & IORESOURCE_ROM_ENABLE) {525525+ /* Turn the ROM off, leave the resource region, but keep it unregistered. */526526+ u32 reg;527527+ DBG("PCI: Switching off ROM of %s\n", pci_name(dev));528528+ r->flags &= ~IORESOURCE_ROM_ENABLE;529529+ pci_read_config_dword(dev, dev->rom_base_reg, ®);530530+ pci_write_config_dword(dev, dev->rom_base_reg,531531+ reg & ~PCI_ROM_ADDRESS_ENABLE);532532+ }533533+ }534534+}535535+536536+static void __init537537+pcibios_assign_resources(void)538538+{539539+ struct pci_dev *dev = NULL;540540+ int idx;541541+ struct resource *r;542542+543543+ for_each_pci_dev(dev) {544544+ int class = dev->class >> 8;545545+546546+ /* Don't touch classless devices and host bridges */547547+ if (!class || class == PCI_CLASS_BRIDGE_HOST)548548+ continue;549549+550550+ for (idx = 0; idx < 6; idx++) {551551+ r = &dev->resource[idx];552552+553553+ /*554554+ * We shall assign a new address to this resource,555555+ * either because the BIOS (sic) forgot to do so556556+ * or because we have decided the old address was557557+ * unusable for some reason.558558+ */559559+ if ((r->flags & IORESOURCE_UNSET) && r->end &&560560+ (!ppc_md.pcibios_enable_device_hook ||561561+ !ppc_md.pcibios_enable_device_hook(dev, 1))) {562562+ r->flags &= ~IORESOURCE_UNSET;563563+ pci_assign_resource(dev, idx);564564+ }565565+ }566566+567567+#if 0 /* don't assign ROMs */568568+ r = &dev->resource[PCI_ROM_RESOURCE];569569+ r->end -= r->start;570570+ r->start = 0;571571+ if (r->end)572572+ pci_assign_resource(dev, PCI_ROM_RESOURCE);573573+#endif574574+ }575575+}576576+577577+578578+int579579+pcibios_enable_resources(struct pci_dev *dev, int mask)580580+{581581+ u16 cmd, old_cmd;582582+ int idx;583583+ struct resource *r;584584+585585+ pci_read_config_word(dev, PCI_COMMAND, &cmd);586586+ old_cmd = cmd;587587+ for (idx=0; idx<6; idx++) {588588+ /* Only set up the requested stuff */589589+ if (!(mask & (1<<idx)))590590+ continue;591591+592592+ r = &dev->resource[idx];593593+ if (r->flags & IORESOURCE_UNSET) {594594+ printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));595595+ return -EINVAL;596596+ }597597+ if (r->flags & IORESOURCE_IO)598598+ cmd |= PCI_COMMAND_IO;599599+ if (r->flags & IORESOURCE_MEM)600600+ cmd |= PCI_COMMAND_MEMORY;601601+ }602602+ if (dev->resource[PCI_ROM_RESOURCE].start)603603+ cmd |= PCI_COMMAND_MEMORY;604604+ if (cmd != old_cmd) {605605+ printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);606606+ pci_write_config_word(dev, PCI_COMMAND, cmd);607607+ }608608+ return 0;609609+}610610+611611+static int next_controller_index;612612+613613+struct pci_controller * __init614614+pcibios_alloc_controller(void)615615+{616616+ struct pci_controller *hose;617617+618618+ hose = (struct pci_controller *)alloc_bootmem(sizeof(*hose));619619+ memset(hose, 0, sizeof(struct pci_controller));620620+621621+ *hose_tail = hose;622622+ hose_tail = &hose->next;623623+624624+ hose->index = next_controller_index++;625625+626626+ return hose;627627+}628628+629629+#ifdef CONFIG_PPC_OF630630+/*631631+ * Functions below are used on OpenFirmware machines.632632+ */633633+static void634634+make_one_node_map(struct device_node* node, u8 pci_bus)635635+{636636+ int *bus_range;637637+ int len;638638+639639+ if (pci_bus >= pci_bus_count)640640+ return;641641+ bus_range = (int *) get_property(node, "bus-range", &len);642642+ if (bus_range == NULL || len < 2 * sizeof(int)) {643643+ printk(KERN_WARNING "Can't get bus-range for %s, "644644+ "assuming it starts at 0\n", node->full_name);645645+ pci_to_OF_bus_map[pci_bus] = 0;646646+ } else647647+ pci_to_OF_bus_map[pci_bus] = bus_range[0];648648+649649+ for (node=node->child; node != 0;node = node->sibling) {650650+ struct pci_dev* dev;651651+ unsigned int *class_code, *reg;652652+653653+ class_code = (unsigned int *) get_property(node, "class-code", NULL);654654+ if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&655655+ (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))656656+ continue;657657+ reg = (unsigned int *)get_property(node, "reg", NULL);658658+ if (!reg)659659+ continue;660660+ dev = pci_find_slot(pci_bus, ((reg[0] >> 8) & 0xff));661661+ if (!dev || !dev->subordinate)662662+ continue;663663+ make_one_node_map(node, dev->subordinate->number);664664+ }665665+}666666+667667+void668668+pcibios_make_OF_bus_map(void)669669+{670670+ int i;671671+ struct pci_controller* hose;672672+ u8* of_prop_map;673673+674674+ pci_to_OF_bus_map = (u8*)kmalloc(pci_bus_count, GFP_KERNEL);675675+ if (!pci_to_OF_bus_map) {676676+ printk(KERN_ERR "Can't allocate OF bus map !\n");677677+ return;678678+ }679679+680680+ /* We fill the bus map with invalid values, that helps681681+ * debugging.682682+ */683683+ for (i=0; i<pci_bus_count; i++)684684+ pci_to_OF_bus_map[i] = 0xff;685685+686686+ /* For each hose, we begin searching bridges */687687+ for(hose=hose_head; hose; hose=hose->next) {688688+ struct device_node* node; 689689+ node = (struct device_node *)hose->arch_data;690690+ if (!node)691691+ continue;692692+ make_one_node_map(node, hose->first_busno);693693+ }694694+ of_prop_map = get_property(find_path_device("/"), "pci-OF-bus-map", NULL);695695+ if (of_prop_map)696696+ memcpy(of_prop_map, pci_to_OF_bus_map, pci_bus_count);697697+#ifdef DEBUG698698+ printk("PCI->OF bus map:\n");699699+ for (i=0; i<pci_bus_count; i++) {700700+ if (pci_to_OF_bus_map[i] == 0xff)701701+ continue;702702+ printk("%d -> %d\n", i, pci_to_OF_bus_map[i]);703703+ }704704+#endif705705+}706706+707707+typedef int (*pci_OF_scan_iterator)(struct device_node* node, void* data);708708+709709+static struct device_node*710710+scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void* data)711711+{712712+ struct device_node* sub_node;713713+714714+ for (; node != 0;node = node->sibling) {715715+ unsigned int *class_code;716716+717717+ if (filter(node, data))718718+ return node;719719+720720+ /* For PCI<->PCI bridges or CardBus bridges, we go down721721+ * Note: some OFs create a parent node "multifunc-device" as722722+ * a fake root for all functions of a multi-function device,723723+ * we go down them as well.724724+ */725725+ class_code = (unsigned int *) get_property(node, "class-code", NULL);726726+ if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&727727+ (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) &&728728+ strcmp(node->name, "multifunc-device"))729729+ continue;730730+ sub_node = scan_OF_pci_childs(node->child, filter, data);731731+ if (sub_node)732732+ return sub_node;733733+ }734734+ return NULL;735735+}736736+737737+static int738738+scan_OF_pci_childs_iterator(struct device_node* node, void* data)739739+{740740+ unsigned int *reg;741741+ u8* fdata = (u8*)data;742742+743743+ reg = (unsigned int *) get_property(node, "reg", NULL);744744+ if (reg && ((reg[0] >> 8) & 0xff) == fdata[1]745745+ && ((reg[0] >> 16) & 0xff) == fdata[0])746746+ return 1;747747+ return 0;748748+}749749+750750+static struct device_node*751751+scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)752752+{753753+ u8 filter_data[2] = {bus, dev_fn};754754+755755+ return scan_OF_pci_childs(node, scan_OF_pci_childs_iterator, filter_data);756756+}757757+758758+/*759759+ * Scans the OF tree for a device node matching a PCI device760760+ */761761+struct device_node *762762+pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)763763+{764764+ struct pci_controller *hose;765765+ struct device_node *node;766766+ int busnr;767767+768768+ if (!have_of)769769+ return NULL;770770+771771+ /* Lookup the hose */772772+ busnr = bus->number;773773+ hose = pci_bus_to_hose(busnr);774774+ if (!hose)775775+ return NULL;776776+777777+ /* Check it has an OF node associated */778778+ node = (struct device_node *) hose->arch_data;779779+ if (!node)780780+ return NULL;781781+782782+ /* Fixup bus number according to what OF think it is. */783783+#ifdef CONFIG_PPC_PMAC784784+ /* The G5 need a special case here. Basically, we don't remap all785785+ * busses on it so we don't create the pci-OF-map. However, we do786786+ * remap the AGP bus and so have to deal with it. A future better787787+ * fix has to be done by making the remapping per-host and always788788+ * filling the pci_to_OF map. --BenH789789+ */790790+ if (_machine == _MACH_Pmac && busnr >= 0xf0)791791+ busnr -= 0xf0;792792+ else793793+#endif794794+ if (pci_to_OF_bus_map)795795+ busnr = pci_to_OF_bus_map[busnr];796796+ if (busnr == 0xff)797797+ return NULL;798798+799799+ /* Now, lookup childs of the hose */800800+ return scan_OF_childs_for_device(node->child, busnr, devfn);801801+}802802+EXPORT_SYMBOL(pci_busdev_to_OF_node);803803+804804+struct device_node*805805+pci_device_to_OF_node(struct pci_dev *dev)806806+{807807+ return pci_busdev_to_OF_node(dev->bus, dev->devfn);808808+}809809+EXPORT_SYMBOL(pci_device_to_OF_node);810810+811811+/* This routine is meant to be used early during boot, when the812812+ * PCI bus numbers have not yet been assigned, and you need to813813+ * issue PCI config cycles to an OF device.814814+ * It could also be used to "fix" RTAS config cycles if you want815815+ * to set pci_assign_all_buses to 1 and still use RTAS for PCI816816+ * config cycles.817817+ */818818+struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)819819+{820820+ if (!have_of)821821+ return NULL;822822+ while(node) {823823+ struct pci_controller* hose;824824+ for (hose=hose_head;hose;hose=hose->next)825825+ if (hose->arch_data == node)826826+ return hose;827827+ node=node->parent;828828+ }829829+ return NULL;830830+}831831+832832+static int833833+find_OF_pci_device_filter(struct device_node* node, void* data)834834+{835835+ return ((void *)node == data);836836+}837837+838838+/*839839+ * Returns the PCI device matching a given OF node840840+ */841841+int842842+pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn)843843+{844844+ unsigned int *reg;845845+ struct pci_controller* hose;846846+ struct pci_dev* dev = NULL;847847+848848+ if (!have_of)849849+ return -ENODEV;850850+ /* Make sure it's really a PCI device */851851+ hose = pci_find_hose_for_OF_device(node);852852+ if (!hose || !hose->arch_data)853853+ return -ENODEV;854854+ if (!scan_OF_pci_childs(((struct device_node*)hose->arch_data)->child,855855+ find_OF_pci_device_filter, (void *)node))856856+ return -ENODEV;857857+ reg = (unsigned int *) get_property(node, "reg", NULL);858858+ if (!reg)859859+ return -ENODEV;860860+ *bus = (reg[0] >> 16) & 0xff;861861+ *devfn = ((reg[0] >> 8) & 0xff);862862+863863+ /* Ok, here we need some tweak. If we have already renumbered864864+ * all busses, we can't rely on the OF bus number any more.865865+ * the pci_to_OF_bus_map is not enough as several PCI busses866866+ * may match the same OF bus number.867867+ */868868+ if (!pci_to_OF_bus_map)869869+ return 0;870870+871871+ for_each_pci_dev(dev)872872+ if (pci_to_OF_bus_map[dev->bus->number] == *bus &&873873+ dev->devfn == *devfn) {874874+ *bus = dev->bus->number;875875+ pci_dev_put(dev);876876+ return 0;877877+ }878878+879879+ return -ENODEV;880880+}881881+EXPORT_SYMBOL(pci_device_from_OF_node);882882+883883+void __init884884+pci_process_bridge_OF_ranges(struct pci_controller *hose,885885+ struct device_node *dev, int primary)886886+{887887+ static unsigned int static_lc_ranges[256] __initdata;888888+ unsigned int *dt_ranges, *lc_ranges, *ranges, *prev;889889+ unsigned int size;890890+ int rlen = 0, orig_rlen;891891+ int memno = 0;892892+ struct resource *res;893893+ int np, na = prom_n_addr_cells(dev);894894+ np = na + 5;895895+896896+ /* First we try to merge ranges to fix a problem with some pmacs897897+ * that can have more than 3 ranges, fortunately using contiguous898898+ * addresses -- BenH899899+ */900900+ dt_ranges = (unsigned int *) get_property(dev, "ranges", &rlen);901901+ if (!dt_ranges)902902+ return;903903+ /* Sanity check, though hopefully that never happens */904904+ if (rlen > sizeof(static_lc_ranges)) {905905+ printk(KERN_WARNING "OF ranges property too large !\n");906906+ rlen = sizeof(static_lc_ranges);907907+ }908908+ lc_ranges = static_lc_ranges;909909+ memcpy(lc_ranges, dt_ranges, rlen);910910+ orig_rlen = rlen;911911+912912+ /* Let's work on a copy of the "ranges" property instead of damaging913913+ * the device-tree image in memory914914+ */915915+ ranges = lc_ranges;916916+ prev = NULL;917917+ while ((rlen -= np * sizeof(unsigned int)) >= 0) {918918+ if (prev) {919919+ if (prev[0] == ranges[0] && prev[1] == ranges[1] &&920920+ (prev[2] + prev[na+4]) == ranges[2] &&921921+ (prev[na+2] + prev[na+4]) == ranges[na+2]) {922922+ prev[na+4] += ranges[na+4];923923+ ranges[0] = 0;924924+ ranges += np;925925+ continue;926926+ }927927+ }928928+ prev = ranges;929929+ ranges += np;930930+ }931931+932932+ /*933933+ * The ranges property is laid out as an array of elements,934934+ * each of which comprises:935935+ * cells 0 - 2: a PCI address936936+ * cells 3 or 3+4: a CPU physical address937937+ * (size depending on dev->n_addr_cells)938938+ * cells 4+5 or 5+6: the size of the range939939+ */940940+ ranges = lc_ranges;941941+ rlen = orig_rlen;942942+ while (ranges && (rlen -= np * sizeof(unsigned int)) >= 0) {943943+ res = NULL;944944+ size = ranges[na+4];945945+ switch ((ranges[0] >> 24) & 0x3) {946946+ case 1: /* I/O space */947947+ if (ranges[2] != 0)948948+ break;949949+ hose->io_base_phys = ranges[na+2];950950+ /* limit I/O space to 16MB */951951+ if (size > 0x01000000)952952+ size = 0x01000000;953953+ hose->io_base_virt = ioremap(ranges[na+2], size);954954+ if (primary)955955+ isa_io_base = (unsigned long) hose->io_base_virt;956956+ res = &hose->io_resource;957957+ res->flags = IORESOURCE_IO;958958+ res->start = ranges[2];959959+ DBG("PCI: IO 0x%lx -> 0x%lx\n",960960+ res->start, res->start + size - 1);961961+ break;962962+ case 2: /* memory space */963963+ memno = 0;964964+ if (ranges[1] == 0 && ranges[2] == 0965965+ && ranges[na+4] <= (16 << 20)) {966966+ /* 1st 16MB, i.e. ISA memory area */967967+ if (primary)968968+ isa_mem_base = ranges[na+2];969969+ memno = 1;970970+ }971971+ while (memno < 3 && hose->mem_resources[memno].flags)972972+ ++memno;973973+ if (memno == 0)974974+ hose->pci_mem_offset = ranges[na+2] - ranges[2];975975+ if (memno < 3) {976976+ res = &hose->mem_resources[memno];977977+ res->flags = IORESOURCE_MEM;978978+ if(ranges[0] & 0x40000000)979979+ res->flags |= IORESOURCE_PREFETCH;980980+ res->start = ranges[na+2];981981+ DBG("PCI: MEM[%d] 0x%lx -> 0x%lx\n", memno,982982+ res->start, res->start + size - 1);983983+ }984984+ break;985985+ }986986+ if (res != NULL) {987987+ res->name = dev->full_name;988988+ res->end = res->start + size - 1;989989+ res->parent = NULL;990990+ res->sibling = NULL;991991+ res->child = NULL;992992+ }993993+ ranges += np;994994+ }995995+}996996+997997+/* We create the "pci-OF-bus-map" property now so it appears in the998998+ * /proc device tree999999+ */10001000+void __init10011001+pci_create_OF_bus_map(void)10021002+{10031003+ struct property* of_prop;10041004+10051005+ of_prop = (struct property*) alloc_bootmem(sizeof(struct property) + 256);10061006+ if (of_prop && find_path_device("/")) {10071007+ memset(of_prop, -1, sizeof(struct property) + 256);10081008+ of_prop->name = "pci-OF-bus-map";10091009+ of_prop->length = 256;10101010+ of_prop->value = (unsigned char *)&of_prop[1];10111011+ prom_add_property(find_path_device("/"), of_prop);10121012+ }10131013+}10141014+10151015+static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)10161016+{10171017+ struct pci_dev *pdev;10181018+ struct device_node *np;10191019+10201020+ pdev = to_pci_dev (dev);10211021+ np = pci_device_to_OF_node(pdev);10221022+ if (np == NULL || np->full_name == NULL)10231023+ return 0;10241024+ return sprintf(buf, "%s", np->full_name);10251025+}10261026+static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);10271027+10281028+#else /* CONFIG_PPC_OF */10291029+void pcibios_make_OF_bus_map(void)10301030+{10311031+}10321032+#endif /* CONFIG_PPC_OF */10331033+10341034+/* Add sysfs properties */10351035+void pcibios_add_platform_entries(struct pci_dev *pdev)10361036+{10371037+#ifdef CONFIG_PPC_OF10381038+ device_create_file(&pdev->dev, &dev_attr_devspec);10391039+#endif /* CONFIG_PPC_OF */10401040+}10411041+10421042+10431043+#ifdef CONFIG_PPC_PMAC10441044+/*10451045+ * This set of routines checks for PCI<->PCI bridges that have closed10461046+ * IO resources and have child devices. It tries to re-open an IO10471047+ * window on them.10481048+ *10491049+ * This is a _temporary_ fix to workaround a problem with Apple's OF10501050+ * closing IO windows on P2P bridges when the OF drivers of cards10511051+ * below this bridge don't claim any IO range (typically ATI or10521052+ * Adaptec).10531053+ *10541054+ * A more complete fix would be to use drivers/pci/setup-bus.c, which10551055+ * involves a working pcibios_fixup_pbus_ranges(), some more care about10561056+ * ordering when creating the host bus resources, and maybe a few more10571057+ * minor tweaks10581058+ */10591059+10601060+/* Initialize bridges with base/limit values we have collected */10611061+static void __init10621062+do_update_p2p_io_resource(struct pci_bus *bus, int enable_vga)10631063+{10641064+ struct pci_dev *bridge = bus->self;10651065+ struct pci_controller* hose = (struct pci_controller *)bridge->sysdata;10661066+ u32 l;10671067+ u16 w;10681068+ struct resource res;10691069+10701070+ if (bus->resource[0] == NULL)10711071+ return;10721072+ res = *(bus->resource[0]);10731073+10741074+ DBG("Remapping Bus %d, bridge: %s\n", bus->number, pci_name(bridge));10751075+ res.start -= ((unsigned long) hose->io_base_virt - isa_io_base);10761076+ res.end -= ((unsigned long) hose->io_base_virt - isa_io_base);10771077+ DBG(" IO window: %08lx-%08lx\n", res.start, res.end);10781078+10791079+ /* Set up the top and bottom of the PCI I/O segment for this bus. */10801080+ pci_read_config_dword(bridge, PCI_IO_BASE, &l);10811081+ l &= 0xffff000f;10821082+ l |= (res.start >> 8) & 0x00f0;10831083+ l |= res.end & 0xf000;10841084+ pci_write_config_dword(bridge, PCI_IO_BASE, l);10851085+10861086+ if ((l & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {10871087+ l = (res.start >> 16) | (res.end & 0xffff0000);10881088+ pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, l);10891089+ }10901090+10911091+ pci_read_config_word(bridge, PCI_COMMAND, &w);10921092+ w |= PCI_COMMAND_IO;10931093+ pci_write_config_word(bridge, PCI_COMMAND, w);10941094+10951095+#if 0 /* Enabling this causes XFree 4.2.0 to hang during PCI probe */10961096+ if (enable_vga) {10971097+ pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &w);10981098+ w |= PCI_BRIDGE_CTL_VGA;10991099+ pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, w);11001100+ }11011101+#endif11021102+}11031103+11041104+/* This function is pretty basic and actually quite broken for the11051105+ * general case, it's enough for us right now though. It's supposed11061106+ * to tell us if we need to open an IO range at all or not and what11071107+ * size.11081108+ */11091109+static int __init11101110+check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga)11111111+{11121112+ struct pci_dev *dev;11131113+ int i;11141114+ int rc = 0;11151115+11161116+#define push_end(res, size) do { unsigned long __sz = (size) ; \11171117+ res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \11181118+ } while (0)11191119+11201120+ list_for_each_entry(dev, &bus->devices, bus_list) {11211121+ u16 class = dev->class >> 8;11221122+11231123+ if (class == PCI_CLASS_DISPLAY_VGA ||11241124+ class == PCI_CLASS_NOT_DEFINED_VGA)11251125+ *found_vga = 1;11261126+ if (class >> 8 == PCI_BASE_CLASS_BRIDGE && dev->subordinate)11271127+ rc |= check_for_io_childs(dev->subordinate, res, found_vga);11281128+ if (class == PCI_CLASS_BRIDGE_CARDBUS)11291129+ push_end(res, 0xfff);11301130+11311131+ for (i=0; i<PCI_NUM_RESOURCES; i++) {11321132+ struct resource *r;11331133+ unsigned long r_size;11341134+11351135+ if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI11361136+ && i >= PCI_BRIDGE_RESOURCES)11371137+ continue;11381138+ r = &dev->resource[i];11391139+ r_size = r->end - r->start;11401140+ if (r_size < 0xfff)11411141+ r_size = 0xfff;11421142+ if (r->flags & IORESOURCE_IO && (r_size) != 0) {11431143+ rc = 1;11441144+ push_end(res, r_size);11451145+ }11461146+ }11471147+ }11481148+11491149+ return rc;11501150+}11511151+11521152+/* Here we scan all P2P bridges of a given level that have a closed11531153+ * IO window. Note that the test for the presence of a VGA card should11541154+ * be improved to take into account already configured P2P bridges,11551155+ * currently, we don't see them and might end up configuring 2 bridges11561156+ * with VGA pass through enabled11571157+ */11581158+static void __init11591159+do_fixup_p2p_level(struct pci_bus *bus)11601160+{11611161+ struct pci_bus *b;11621162+ int i, parent_io;11631163+ int has_vga = 0;11641164+11651165+ for (parent_io=0; parent_io<4; parent_io++)11661166+ if (bus->resource[parent_io]11671167+ && bus->resource[parent_io]->flags & IORESOURCE_IO)11681168+ break;11691169+ if (parent_io >= 4)11701170+ return;11711171+11721172+ list_for_each_entry(b, &bus->children, node) {11731173+ struct pci_dev *d = b->self;11741174+ struct pci_controller* hose = (struct pci_controller *)d->sysdata;11751175+ struct resource *res = b->resource[0];11761176+ struct resource tmp_res;11771177+ unsigned long max;11781178+ int found_vga = 0;11791179+11801180+ memset(&tmp_res, 0, sizeof(tmp_res));11811181+ tmp_res.start = bus->resource[parent_io]->start;11821182+11831183+ /* We don't let low addresses go through that closed P2P bridge, well,11841184+ * that may not be necessary but I feel safer that way11851185+ */11861186+ if (tmp_res.start == 0)11871187+ tmp_res.start = 0x1000;11881188+11891189+ if (!list_empty(&b->devices) && res && res->flags == 0 &&11901190+ res != bus->resource[parent_io] &&11911191+ (d->class >> 8) == PCI_CLASS_BRIDGE_PCI &&11921192+ check_for_io_childs(b, &tmp_res, &found_vga)) {11931193+ u8 io_base_lo;11941194+11951195+ printk(KERN_INFO "Fixing up IO bus %s\n", b->name);11961196+11971197+ if (found_vga) {11981198+ if (has_vga) {11991199+ printk(KERN_WARNING "Skipping VGA, already active"12001200+ " on bus segment\n");12011201+ found_vga = 0;12021202+ } else12031203+ has_vga = 1;12041204+ }12051205+ pci_read_config_byte(d, PCI_IO_BASE, &io_base_lo);12061206+12071207+ if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32)12081208+ max = ((unsigned long) hose->io_base_virt12091209+ - isa_io_base) + 0xffffffff;12101210+ else12111211+ max = ((unsigned long) hose->io_base_virt12121212+ - isa_io_base) + 0xffff;12131213+12141214+ *res = tmp_res;12151215+ res->flags = IORESOURCE_IO;12161216+ res->name = b->name;12171217+12181218+ /* Find a resource in the parent where we can allocate */12191219+ for (i = 0 ; i < 4; i++) {12201220+ struct resource *r = bus->resource[i];12211221+ if (!r)12221222+ continue;12231223+ if ((r->flags & IORESOURCE_IO) == 0)12241224+ continue;12251225+ DBG("Trying to allocate from %08lx, size %08lx from parent"12261226+ " res %d: %08lx -> %08lx\n",12271227+ res->start, res->end, i, r->start, r->end);12281228+12291229+ if (allocate_resource(r, res, res->end + 1, res->start, max,12301230+ res->end + 1, NULL, NULL) < 0) {12311231+ DBG("Failed !\n");12321232+ continue;12331233+ }12341234+ do_update_p2p_io_resource(b, found_vga);12351235+ break;12361236+ }12371237+ }12381238+ do_fixup_p2p_level(b);12391239+ }12401240+}12411241+12421242+static void12431243+pcibios_fixup_p2p_bridges(void)12441244+{12451245+ struct pci_bus *b;12461246+12471247+ list_for_each_entry(b, &pci_root_buses, node)12481248+ do_fixup_p2p_level(b);12491249+}12501250+12511251+#endif /* CONFIG_PPC_PMAC */12521252+12531253+static int __init12541254+pcibios_init(void)12551255+{12561256+ struct pci_controller *hose;12571257+ struct pci_bus *bus;12581258+ int next_busno;12591259+12601260+ printk(KERN_INFO "PCI: Probing PCI hardware\n");12611261+12621262+ /* Scan all of the recorded PCI controllers. */12631263+ for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {12641264+ if (pci_assign_all_buses)12651265+ hose->first_busno = next_busno;12661266+ hose->last_busno = 0xff;12671267+ bus = pci_scan_bus(hose->first_busno, hose->ops, hose);12681268+ hose->last_busno = bus->subordinate;12691269+ if (pci_assign_all_buses || next_busno <= hose->last_busno)12701270+ next_busno = hose->last_busno + pcibios_assign_bus_offset;12711271+ }12721272+ pci_bus_count = next_busno;12731273+12741274+ /* OpenFirmware based machines need a map of OF bus12751275+ * numbers vs. kernel bus numbers since we may have to12761276+ * remap them.12771277+ */12781278+ if (pci_assign_all_buses && have_of)12791279+ pcibios_make_OF_bus_map();12801280+12811281+ /* Do machine dependent PCI interrupt routing */12821282+ if (ppc_md.pci_swizzle && ppc_md.pci_map_irq)12831283+ pci_fixup_irqs(ppc_md.pci_swizzle, ppc_md.pci_map_irq);12841284+12851285+ /* Call machine dependent fixup */12861286+ if (ppc_md.pcibios_fixup)12871287+ ppc_md.pcibios_fixup();12881288+12891289+ /* Allocate and assign resources */12901290+ pcibios_allocate_bus_resources(&pci_root_buses);12911291+ pcibios_allocate_resources(0);12921292+ pcibios_allocate_resources(1);12931293+#ifdef CONFIG_PPC_PMAC12941294+ pcibios_fixup_p2p_bridges();12951295+#endif /* CONFIG_PPC_PMAC */12961296+ pcibios_assign_resources();12971297+12981298+ /* Call machine dependent post-init code */12991299+ if (ppc_md.pcibios_after_init)13001300+ ppc_md.pcibios_after_init();13011301+13021302+ return 0;13031303+}13041304+13051305+subsys_initcall(pcibios_init);13061306+13071307+unsigned char __init13081308+common_swizzle(struct pci_dev *dev, unsigned char *pinp)13091309+{13101310+ struct pci_controller *hose = dev->sysdata;13111311+13121312+ if (dev->bus->number != hose->first_busno) {13131313+ u8 pin = *pinp;13141314+ do {13151315+ pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));13161316+ /* Move up the chain of bridges. */13171317+ dev = dev->bus->self;13181318+ } while (dev->bus->self);13191319+ *pinp = pin;13201320+13211321+ /* The slot is the idsel of the last bridge. */13221322+ }13231323+ return PCI_SLOT(dev->devfn);13241324+}13251325+13261326+unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,13271327+ unsigned long start, unsigned long size)13281328+{13291329+ return start;13301330+}13311331+13321332+void __init pcibios_fixup_bus(struct pci_bus *bus)13331333+{13341334+ struct pci_controller *hose = (struct pci_controller *) bus->sysdata;13351335+ unsigned long io_offset;13361336+ struct resource *res;13371337+ int i;13381338+13391339+ io_offset = (unsigned long)hose->io_base_virt - isa_io_base;13401340+ if (bus->parent == NULL) {13411341+ /* This is a host bridge - fill in its resources */13421342+ hose->bus = bus;13431343+13441344+ bus->resource[0] = res = &hose->io_resource;13451345+ if (!res->flags) {13461346+ if (io_offset)13471347+ printk(KERN_ERR "I/O resource not set for host"13481348+ " bridge %d\n", hose->index);13491349+ res->start = 0;13501350+ res->end = IO_SPACE_LIMIT;13511351+ res->flags = IORESOURCE_IO;13521352+ }13531353+ res->start += io_offset;13541354+ res->end += io_offset;13551355+13561356+ for (i = 0; i < 3; ++i) {13571357+ res = &hose->mem_resources[i];13581358+ if (!res->flags) {13591359+ if (i > 0)13601360+ continue;13611361+ printk(KERN_ERR "Memory resource not set for "13621362+ "host bridge %d\n", hose->index);13631363+ res->start = hose->pci_mem_offset;13641364+ res->end = ~0U;13651365+ res->flags = IORESOURCE_MEM;13661366+ }13671367+ bus->resource[i+1] = res;13681368+ }13691369+ } else {13701370+ /* This is a subordinate bridge */13711371+ pci_read_bridge_bases(bus);13721372+13731373+ for (i = 0; i < 4; ++i) {13741374+ if ((res = bus->resource[i]) == NULL)13751375+ continue;13761376+ if (!res->flags)13771377+ continue;13781378+ if (io_offset && (res->flags & IORESOURCE_IO)) {13791379+ res->start += io_offset;13801380+ res->end += io_offset;13811381+ } else if (hose->pci_mem_offset13821382+ && (res->flags & IORESOURCE_MEM)) {13831383+ res->start += hose->pci_mem_offset;13841384+ res->end += hose->pci_mem_offset;13851385+ }13861386+ }13871387+ }13881388+13891389+ if (ppc_md.pcibios_fixup_bus)13901390+ ppc_md.pcibios_fixup_bus(bus);13911391+}13921392+13931393+char __init *pcibios_setup(char *str)13941394+{13951395+ return str;13961396+}13971397+13981398+/* the next one is stolen from the alpha port... */13991399+void __init14001400+pcibios_update_irq(struct pci_dev *dev, int irq)14011401+{14021402+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);14031403+ /* XXX FIXME - update OF device tree node interrupt property */14041404+}14051405+14061406+int pcibios_enable_device(struct pci_dev *dev, int mask)14071407+{14081408+ u16 cmd, old_cmd;14091409+ int idx;14101410+ struct resource *r;14111411+14121412+ if (ppc_md.pcibios_enable_device_hook)14131413+ if (ppc_md.pcibios_enable_device_hook(dev, 0))14141414+ return -EINVAL;14151415+14161416+ pci_read_config_word(dev, PCI_COMMAND, &cmd);14171417+ old_cmd = cmd;14181418+ for (idx=0; idx<6; idx++) {14191419+ r = &dev->resource[idx];14201420+ if (r->flags & IORESOURCE_UNSET) {14211421+ printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));14221422+ return -EINVAL;14231423+ }14241424+ if (r->flags & IORESOURCE_IO)14251425+ cmd |= PCI_COMMAND_IO;14261426+ if (r->flags & IORESOURCE_MEM)14271427+ cmd |= PCI_COMMAND_MEMORY;14281428+ }14291429+ if (cmd != old_cmd) {14301430+ printk("PCI: Enabling device %s (%04x -> %04x)\n",14311431+ pci_name(dev), old_cmd, cmd);14321432+ pci_write_config_word(dev, PCI_COMMAND, cmd);14331433+ }14341434+ return 0;14351435+}14361436+14371437+struct pci_controller*14381438+pci_bus_to_hose(int bus)14391439+{14401440+ struct pci_controller* hose = hose_head;14411441+14421442+ for (; hose; hose = hose->next)14431443+ if (bus >= hose->first_busno && bus <= hose->last_busno)14441444+ return hose;14451445+ return NULL;14461446+}14471447+14481448+void __iomem *14491449+pci_bus_io_base(unsigned int bus)14501450+{14511451+ struct pci_controller *hose;14521452+14531453+ hose = pci_bus_to_hose(bus);14541454+ if (!hose)14551455+ return NULL;14561456+ return hose->io_base_virt;14571457+}14581458+14591459+unsigned long14601460+pci_bus_io_base_phys(unsigned int bus)14611461+{14621462+ struct pci_controller *hose;14631463+14641464+ hose = pci_bus_to_hose(bus);14651465+ if (!hose)14661466+ return 0;14671467+ return hose->io_base_phys;14681468+}14691469+14701470+unsigned long14711471+pci_bus_mem_base_phys(unsigned int bus)14721472+{14731473+ struct pci_controller *hose;14741474+14751475+ hose = pci_bus_to_hose(bus);14761476+ if (!hose)14771477+ return 0;14781478+ return hose->pci_mem_offset;14791479+}14801480+14811481+unsigned long14821482+pci_resource_to_bus(struct pci_dev *pdev, struct resource *res)14831483+{14841484+ /* Hack alert again ! See comments in chrp_pci.c14851485+ */14861486+ struct pci_controller* hose =14871487+ (struct pci_controller *)pdev->sysdata;14881488+ if (hose && res->flags & IORESOURCE_MEM)14891489+ return res->start - hose->pci_mem_offset;14901490+ /* We may want to do something with IOs here... */14911491+ return res->start;14921492+}14931493+14941494+14951495+static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,14961496+ unsigned long *offset,14971497+ enum pci_mmap_state mmap_state)14981498+{14991499+ struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);15001500+ unsigned long io_offset = 0;15011501+ int i, res_bit;15021502+15031503+ if (hose == 0)15041504+ return NULL; /* should never happen */15051505+15061506+ /* If memory, add on the PCI bridge address offset */15071507+ if (mmap_state == pci_mmap_mem) {15081508+ *offset += hose->pci_mem_offset;15091509+ res_bit = IORESOURCE_MEM;15101510+ } else {15111511+ io_offset = hose->io_base_virt - ___IO_BASE;15121512+ *offset += io_offset;15131513+ res_bit = IORESOURCE_IO;15141514+ }15151515+15161516+ /*15171517+ * Check that the offset requested corresponds to one of the15181518+ * resources of the device.15191519+ */15201520+ for (i = 0; i <= PCI_ROM_RESOURCE; i++) {15211521+ struct resource *rp = &dev->resource[i];15221522+ int flags = rp->flags;15231523+15241524+ /* treat ROM as memory (should be already) */15251525+ if (i == PCI_ROM_RESOURCE)15261526+ flags |= IORESOURCE_MEM;15271527+15281528+ /* Active and same type? */15291529+ if ((flags & res_bit) == 0)15301530+ continue;15311531+15321532+ /* In the range of this resource? */15331533+ if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end)15341534+ continue;15351535+15361536+ /* found it! construct the final physical address */15371537+ if (mmap_state == pci_mmap_io)15381538+ *offset += hose->io_base_phys - io_offset;15391539+ return rp;15401540+ }15411541+15421542+ return NULL;15431543+}15441544+15451545+/*15461546+ * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci15471547+ * device mapping.15481548+ */15491549+static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,15501550+ pgprot_t protection,15511551+ enum pci_mmap_state mmap_state,15521552+ int write_combine)15531553+{15541554+ unsigned long prot = pgprot_val(protection);15551555+15561556+ /* Write combine is always 0 on non-memory space mappings. On15571557+ * memory space, if the user didn't pass 1, we check for a15581558+ * "prefetchable" resource. This is a bit hackish, but we use15591559+ * this to workaround the inability of /sysfs to provide a write15601560+ * combine bit15611561+ */15621562+ if (mmap_state != pci_mmap_mem)15631563+ write_combine = 0;15641564+ else if (write_combine == 0) {15651565+ if (rp->flags & IORESOURCE_PREFETCH)15661566+ write_combine = 1;15671567+ }15681568+15691569+ /* XXX would be nice to have a way to ask for write-through */15701570+ prot |= _PAGE_NO_CACHE;15711571+ if (write_combine)15721572+ prot &= ~_PAGE_GUARDED;15731573+ else15741574+ prot |= _PAGE_GUARDED;15751575+15761576+ printk("PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start,15771577+ prot);15781578+15791579+ return __pgprot(prot);15801580+}15811581+15821582+/*15831583+ * This one is used by /dev/mem and fbdev who have no clue about the15841584+ * PCI device, it tries to find the PCI device first and calls the15851585+ * above routine15861586+ */15871587+pgprot_t pci_phys_mem_access_prot(struct file *file,15881588+ unsigned long pfn,15891589+ unsigned long size,15901590+ pgprot_t protection)15911591+{15921592+ struct pci_dev *pdev = NULL;15931593+ struct resource *found = NULL;15941594+ unsigned long prot = pgprot_val(protection);15951595+ unsigned long offset = pfn << PAGE_SHIFT;15961596+ int i;15971597+15981598+ if (page_is_ram(pfn))15991599+ return prot;16001600+16011601+ prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;16021602+16031603+ for_each_pci_dev(pdev) {16041604+ for (i = 0; i <= PCI_ROM_RESOURCE; i++) {16051605+ struct resource *rp = &pdev->resource[i];16061606+ int flags = rp->flags;16071607+16081608+ /* Active and same type? */16091609+ if ((flags & IORESOURCE_MEM) == 0)16101610+ continue;16111611+ /* In the range of this resource? */16121612+ if (offset < (rp->start & PAGE_MASK) ||16131613+ offset > rp->end)16141614+ continue;16151615+ found = rp;16161616+ break;16171617+ }16181618+ if (found)16191619+ break;16201620+ }16211621+ if (found) {16221622+ if (found->flags & IORESOURCE_PREFETCH)16231623+ prot &= ~_PAGE_GUARDED;16241624+ pci_dev_put(pdev);16251625+ }16261626+16271627+ DBG("non-PCI map for %lx, prot: %lx\n", offset, prot);16281628+16291629+ return __pgprot(prot);16301630+}16311631+16321632+16331633+/*16341634+ * Perform the actual remap of the pages for a PCI device mapping, as16351635+ * appropriate for this architecture. The region in the process to map16361636+ * is described by vm_start and vm_end members of VMA, the base physical16371637+ * address is found in vm_pgoff.16381638+ * The pci device structure is provided so that architectures may make mapping16391639+ * decisions on a per-device or per-bus basis.16401640+ *16411641+ * Returns a negative error code on failure, zero on success.16421642+ */16431643+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,16441644+ enum pci_mmap_state mmap_state,16451645+ int write_combine)16461646+{16471647+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;16481648+ struct resource *rp;16491649+ int ret;16501650+16511651+ rp = __pci_mmap_make_offset(dev, &offset, mmap_state);16521652+ if (rp == NULL)16531653+ return -EINVAL;16541654+16551655+ vma->vm_pgoff = offset >> PAGE_SHIFT;16561656+ vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;16571657+ vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,16581658+ vma->vm_page_prot,16591659+ mmap_state, write_combine);16601660+16611661+ ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,16621662+ vma->vm_end - vma->vm_start, vma->vm_page_prot);16631663+16641664+ return ret;16651665+}16661666+16671667+/* Obsolete functions. Should be removed once the symbios driver16681668+ * is fixed16691669+ */16701670+unsigned long16711671+phys_to_bus(unsigned long pa)16721672+{16731673+ struct pci_controller *hose;16741674+ int i;16751675+16761676+ for (hose = hose_head; hose; hose = hose->next) {16771677+ for (i = 0; i < 3; ++i) {16781678+ if (pa >= hose->mem_resources[i].start16791679+ && pa <= hose->mem_resources[i].end) {16801680+ /*16811681+ * XXX the hose->pci_mem_offset really16821682+ * only applies to mem_resources[0].16831683+ * We need a way to store an offset for16841684+ * the others. -- paulus16851685+ */16861686+ if (i == 0)16871687+ pa -= hose->pci_mem_offset;16881688+ return pa;16891689+ }16901690+ }16911691+ }16921692+ /* hmmm, didn't find it */16931693+ return 0;16941694+}16951695+16961696+unsigned long16971697+pci_phys_to_bus(unsigned long pa, int busnr)16981698+{16991699+ struct pci_controller* hose = pci_bus_to_hose(busnr);17001700+ if (!hose)17011701+ return pa;17021702+ return pa - hose->pci_mem_offset;17031703+}17041704+17051705+unsigned long17061706+pci_bus_to_phys(unsigned int ba, int busnr)17071707+{17081708+ struct pci_controller* hose = pci_bus_to_hose(busnr);17091709+ if (!hose)17101710+ return ba;17111711+ return ba + hose->pci_mem_offset;17121712+}17131713+17141714+/* Provide information on locations of various I/O regions in physical17151715+ * memory. Do this on a per-card basis so that we choose the right17161716+ * root bridge.17171717+ * Note that the returned IO or memory base is a physical address17181718+ */17191719+17201720+long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)17211721+{17221722+ struct pci_controller* hose;17231723+ long result = -EOPNOTSUPP;17241724+17251725+ /* Argh ! Please forgive me for that hack, but that's the17261726+ * simplest way to get existing XFree to not lockup on some17271727+ * G5 machines... So when something asks for bus 0 io base17281728+ * (bus 0 is HT root), we return the AGP one instead.17291729+ */17301730+#ifdef CONFIG_PPC_PMAC17311731+ if (_machine == _MACH_Pmac && machine_is_compatible("MacRISC4"))17321732+ if (bus == 0)17331733+ bus = 0xf0;17341734+#endif /* CONFIG_PPC_PMAC */17351735+17361736+ hose = pci_bus_to_hose(bus);17371737+ if (!hose)17381738+ return -ENODEV;17391739+17401740+ switch (which) {17411741+ case IOBASE_BRIDGE_NUMBER:17421742+ return (long)hose->first_busno;17431743+ case IOBASE_MEMORY:17441744+ return (long)hose->pci_mem_offset;17451745+ case IOBASE_IO:17461746+ return (long)hose->io_base_phys;17471747+ case IOBASE_ISA_IO:17481748+ return (long)isa_io_base;17491749+ case IOBASE_ISA_MEM:17501750+ return (long)isa_mem_base;17511751+ }17521752+17531753+ return result;17541754+}17551755+17561756+void pci_resource_to_user(const struct pci_dev *dev, int bar,17571757+ const struct resource *rsrc,17581758+ u64 *start, u64 *end)17591759+{17601760+ struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);17611761+ unsigned long offset = 0;17621762+17631763+ if (hose == NULL)17641764+ return;17651765+17661766+ if (rsrc->flags & IORESOURCE_IO)17671767+ offset = ___IO_BASE - hose->io_base_virt + hose->io_base_phys;17681768+17691769+ *start = rsrc->start + offset;17701770+ *end = rsrc->end + offset;17711771+}17721772+17731773+void __init17741774+pci_init_resource(struct resource *res, unsigned long start, unsigned long end,17751775+ int flags, char *name)17761776+{17771777+ res->start = start;17781778+ res->end = end;17791779+ res->flags = flags;17801780+ res->name = name;17811781+ res->parent = NULL;17821782+ res->sibling = NULL;17831783+ res->child = NULL;17841784+}17851785+17861786+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)17871787+{17881788+ unsigned long start = pci_resource_start(dev, bar);17891789+ unsigned long len = pci_resource_len(dev, bar);17901790+ unsigned long flags = pci_resource_flags(dev, bar);17911791+17921792+ if (!len)17931793+ return NULL;17941794+ if (max && len > max)17951795+ len = max;17961796+ if (flags & IORESOURCE_IO)17971797+ return ioport_map(start, len);17981798+ if (flags & IORESOURCE_MEM)17991799+ /* Not checking IORESOURCE_CACHEABLE because PPC does18001800+ * not currently distinguish between ioremap and18011801+ * ioremap_nocache.18021802+ */18031803+ return ioremap(start, len);18041804+ /* What? */18051805+ return NULL;18061806+}18071807+18081808+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)18091809+{18101810+ /* Nothing to do */18111811+}18121812+EXPORT_SYMBOL(pci_iomap);18131813+EXPORT_SYMBOL(pci_iounmap);18141814+18151815+unsigned long pci_address_to_pio(phys_addr_t address)18161816+{18171817+ struct pci_controller* hose = hose_head;18181818+18191819+ for (; hose; hose = hose->next) {18201820+ unsigned int size = hose->io_resource.end -18211821+ hose->io_resource.start + 1;18221822+ if (address >= hose->io_base_phys &&18231823+ address < (hose->io_base_phys + size)) {18241824+ unsigned long base =18251825+ (unsigned long)hose->io_base_virt - _IO_BASE;18261826+ return base + (address - hose->io_base_phys);18271827+ }18281828+ }18291829+ return (unsigned int)-1;18301830+}18311831+EXPORT_SYMBOL(pci_address_to_pio);18321832+18331833+/*18341834+ * Null PCI config access functions, for the case when we can't18351835+ * find a hose.18361836+ */18371837+#define NULL_PCI_OP(rw, size, type) \18381838+static int \18391839+null_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \18401840+{ \18411841+ return PCIBIOS_DEVICE_NOT_FOUND; \18421842+}18431843+18441844+static int18451845+null_read_config(struct pci_bus *bus, unsigned int devfn, int offset,18461846+ int len, u32 *val)18471847+{18481848+ return PCIBIOS_DEVICE_NOT_FOUND;18491849+}18501850+18511851+static int18521852+null_write_config(struct pci_bus *bus, unsigned int devfn, int offset,18531853+ int len, u32 val)18541854+{18551855+ return PCIBIOS_DEVICE_NOT_FOUND;18561856+}18571857+18581858+static struct pci_ops null_pci_ops =18591859+{18601860+ null_read_config,18611861+ null_write_config18621862+};18631863+18641864+/*18651865+ * These functions are used early on before PCI scanning is done18661866+ * and all of the pci_dev and pci_bus structures have been created.18671867+ */18681868+static struct pci_bus *18691869+fake_pci_bus(struct pci_controller *hose, int busnr)18701870+{18711871+ static struct pci_bus bus;18721872+18731873+ if (hose == 0) {18741874+ hose = pci_bus_to_hose(busnr);18751875+ if (hose == 0)18761876+ printk(KERN_ERR "Can't find hose for PCI bus %d!\n", busnr);18771877+ }18781878+ bus.number = busnr;18791879+ bus.sysdata = hose;18801880+ bus.ops = hose? hose->ops: &null_pci_ops;18811881+ return &bus;18821882+}18831883+18841884+#define EARLY_PCI_OP(rw, size, type) \18851885+int early_##rw##_config_##size(struct pci_controller *hose, int bus, \18861886+ int devfn, int offset, type value) \18871887+{ \18881888+ return pci_bus_##rw##_config_##size(fake_pci_bus(hose, bus), \18891889+ devfn, offset, value); \18901890+}18911891+18921892+EARLY_PCI_OP(read, byte, u8 *)18931893+EARLY_PCI_OP(read, word, u16 *)18941894+EARLY_PCI_OP(read, dword, u32 *)18951895+EARLY_PCI_OP(write, byte, u8)18961896+EARLY_PCI_OP(write, word, u16)18971897+EARLY_PCI_OP(write, dword, u32)
···316316 char* disp_name;317317 int *bus_range;318318 int primary = 1;319319- struct property *of_prop;320319321320 DBG("Adding PCI host bridge %s\n", dev->full_name);322321
+50-35
arch/powerpc/platforms/maple/setup.c
···7171#define DBG(fmt...)7272#endif73737474+static unsigned long maple_find_nvram_base(void)7575+{7676+ struct device_node *rtcs;7777+ unsigned long result = 0;7878+7979+ /* find NVRAM device */8080+ rtcs = of_find_compatible_node(NULL, "nvram", "AMD8111");8181+ if (rtcs) {8282+ struct resource r;8383+ if (of_address_to_resource(rtcs, 0, &r)) {8484+ printk(KERN_EMERG "Maple: Unable to translate NVRAM"8585+ " address\n");8686+ goto bail;8787+ }8888+ if (!(r.flags & IORESOURCE_IO)) {8989+ printk(KERN_EMERG "Maple: NVRAM address isn't PIO!\n");9090+ goto bail;9191+ }9292+ result = r.start;9393+ } else9494+ printk(KERN_EMERG "Maple: Unable to find NVRAM\n");9595+ bail:9696+ of_node_put(rtcs);9797+ return result;9898+}9999+74100static void maple_restart(char *cmd)75101{76102 unsigned int maple_nvram_base;77103 unsigned int maple_nvram_offset;78104 unsigned int maple_nvram_command;7979- struct device_node *rtcs;105105+ struct device_node *sp;801068181- /* find NVRAM device */8282- rtcs = find_compatible_devices("nvram", "AMD8111");8383- if (rtcs && rtcs->addrs) {8484- maple_nvram_base = rtcs->addrs[0].address;8585- } else {8686- printk(KERN_EMERG "Maple: Unable to find NVRAM\n");8787- printk(KERN_EMERG "Maple: Manual Restart Required\n");8888- return;8989- }107107+ maple_nvram_base = maple_find_nvram_base();108108+ if (maple_nvram_base == 0)109109+ goto fail;9011091111 /* find service processor device */9292- rtcs = find_devices("service-processor");9393- if (!rtcs) {112112+ sp = of_find_node_by_name(NULL, "service-processor");113113+ if (!sp) {94114 printk(KERN_EMERG "Maple: Unable to find Service Processor\n");9595- printk(KERN_EMERG "Maple: Manual Restart Required\n");9696- return;115115+ goto fail;97116 }9898- maple_nvram_offset = *(unsigned int*) get_property(rtcs,117117+ maple_nvram_offset = *(unsigned int*) get_property(sp,99118 "restart-addr", NULL);100100- maple_nvram_command = *(unsigned int*) get_property(rtcs,119119+ maple_nvram_command = *(unsigned int*) get_property(sp,101120 "restart-value", NULL);121121+ of_node_put(sp);102122103123 /* send command */104124 outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);105125 for (;;) ;126126+ fail:127127+ printk(KERN_EMERG "Maple: Manual Restart Required\n");106128}107129108130static void maple_power_off(void)···132110 unsigned int maple_nvram_base;133111 unsigned int maple_nvram_offset;134112 unsigned int maple_nvram_command;135135- struct device_node *rtcs;113113+ struct device_node *sp;136114137137- /* find NVRAM device */138138- rtcs = find_compatible_devices("nvram", "AMD8111");139139- if (rtcs && rtcs->addrs) {140140- maple_nvram_base = rtcs->addrs[0].address;141141- } else {142142- printk(KERN_EMERG "Maple: Unable to find NVRAM\n");143143- printk(KERN_EMERG "Maple: Manual Power-Down Required\n");144144- return;145145- }115115+ maple_nvram_base = maple_find_nvram_base();116116+ if (maple_nvram_base == 0)117117+ goto fail;146118147119 /* find service processor device */148148- rtcs = find_devices("service-processor");149149- if (!rtcs) {120120+ sp = of_find_node_by_name(NULL, "service-processor");121121+ if (!sp) {150122 printk(KERN_EMERG "Maple: Unable to find Service Processor\n");151151- printk(KERN_EMERG "Maple: Manual Power-Down Required\n");152152- return;123123+ goto fail;153124 }154154- maple_nvram_offset = *(unsigned int*) get_property(rtcs,125125+ maple_nvram_offset = *(unsigned int*) get_property(sp,155126 "power-off-addr", NULL);156156- maple_nvram_command = *(unsigned int*) get_property(rtcs,127127+ maple_nvram_command = *(unsigned int*) get_property(sp,157128 "power-off-value", NULL);129129+ of_node_put(sp);158130159131 /* send command */160132 outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);161133 for (;;) ;134134+ fail:135135+ printk(KERN_EMERG "Maple: Manual Power-Down Required\n");162136}163137164138static void maple_halt(void)···197179 */198180static void __init maple_init_early(void)199181{200200- unsigned int default_speed;201201- u64 physport;202202-203182 DBG(" -> maple_init_early\n");204183205184 /* Initialize hash table, from now on, we can take hash faults
+18-5
arch/powerpc/platforms/maple/time.c
···168168 struct rtc_time tm;169169 struct device_node *rtcs;170170171171- rtcs = find_compatible_devices("rtc", "pnpPNP,b00");172172- if (rtcs && rtcs->addrs) {173173- maple_rtc_addr = rtcs->addrs[0].address;174174- printk(KERN_INFO "Maple: Found RTC at 0x%x\n", maple_rtc_addr);175175- } else {171171+ rtcs = of_find_compatible_node(NULL, "rtc", "pnpPNP,b00");172172+ if (rtcs) {173173+ struct resource r;174174+ if (of_address_to_resource(rtcs, 0, &r)) {175175+ printk(KERN_EMERG "Maple: Unable to translate RTC"176176+ " address\n");177177+ goto bail;178178+ }179179+ if (!(r.flags & IORESOURCE_IO)) {180180+ printk(KERN_EMERG "Maple: RTC address isn't PIO!\n");181181+ goto bail;182182+ }183183+ maple_rtc_addr = r.start;184184+ printk(KERN_INFO "Maple: Found RTC at IO 0x%x\n",185185+ maple_rtc_addr);186186+ }187187+ bail:188188+ if (maple_rtc_addr == 0) {176189 maple_rtc_addr = RTC_PORT(0); /* legacy address */177190 printk(KERN_INFO "Maple: No device node for RTC, assuming "178191 "legacy address (0x%x)\n", maple_rtc_addr);
+22-51
arch/ppc/Kconfig
···5858 help5959 There are four types of PowerPC chips supported. The more common6060 types (601, 603, 604, 740, 750, 7400), the Motorola embedded6161- versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the IBM embedded6262- versions (403 and 405) and the high end 64 bit Power processors6363- (POWER 3, POWER4, and IBM 970 also known as G5)6161+ versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the IBM6262+ embedded versions (403 and 405) and the POWER3 processor.6363+ (For support for more recent 64-bit processors, set ARCH=powerpc.)6464 Unless you are building a kernel for one of the embedded processor6565- systems, 64 bit IBM RS/6000 or an Apple G5, choose 6xx.6565+ systems or a POWER3-based IBM RS/6000, choose 6xx.6666 Note that the kernel runs in 32-bit mode even on 64-bit chips.6767 Also note that because the 52xx, 82xx, & 83xx family has a 603e core,6868 specific support for that chipset is asked later on.···7676config POWER37777 select PPC_FPU7878 bool "POWER3"7979-8080-config POWER48181- select PPC_FPU8282- bool "POWER4 and 970 (G5)"83798480config 8xx8581 bool "8xx"···119123120124config ALTIVEC121125 bool "AltiVec Support"122122- depends on 6xx || POWER4126126+ depends on 6xx123127 depends on !8260 && !83xx124128 ---help---125129 This option enables kernel support for the Altivec extensions to the···231235232236source "drivers/cpufreq/Kconfig"233237234234-config CPU_FREQ_PMAC235235- bool "Support for Apple PowerBooks"236236- depends on CPU_FREQ && ADB_PMU237237- select CPU_FREQ_TABLE238238- help239239- This adds support for frequency switching on Apple PowerBooks,240240- this currently includes some models of iBook & Titanium241241- PowerBook.242242-243238config PPC601_SYNC_FIX244239 bool "Workarounds for PPC601 bugs"245245- depends on 6xx && (PPC_PREP || PPC_PMAC)240240+ depends on 6xx && PPC_PREP246241 help247242 Some versions of the PPC601 (the first PowerPC chip) have bugs which248243 mean that extra synchronization instructions are required near···245258246259 If in doubt, say Y here.247260248248-config HOTPLUG_CPU249249- bool "Support for enabling/disabling CPUs"250250- depends on SMP && HOTPLUG && EXPERIMENTAL && PPC_PMAC251251- ---help---252252- Say Y here to be able to disable and re-enable individual253253- CPUs at runtime on SMP machines.254254-255255- Say N if you are unsure.256256-257261source arch/ppc/platforms/4xx/Kconfig258262source arch/ppc/platforms/85xx/Kconfig259263260264config PPC64BRIDGE261265 bool262262- depends on POWER3 || POWER4266266+ depends on POWER3263267 default y264268265269config PPC_STD_MMU266270 bool267267- depends on 6xx || POWER3 || POWER4271271+ depends on 6xx || POWER3268272 default y269273270274config NOT_COHERENT_CACHE···483505484506choice485507 prompt "Machine Type"486486- depends on 6xx || POWER3 || POWER4508508+ depends on 6xx || POWER3487509 default PPC_MULTIPLATFORM488510 ---help---489511 Linux currently supports several different kinds of PowerPC-based···494516 Platform) machines (including all of the recent IBM RS/6000 and495517 pSeries machines), and several embedded PowerPC systems containing496518 4xx, 6xx, 7xx, 8xx, 74xx, and 82xx processors. Currently, the497497- default option is to build a kernel which works on the first three.519519+ default option is to build a kernel which works on PReP and CHRP.498520499499- Select CHRP/PowerMac/PReP if configuring for an IBM RS/6000 or500500- pSeries machine, a Power Macintosh (including iMacs, iBooks and501501- Powerbooks), or a PReP machine.521521+ Note that support for Apple machines is now only available with522522+ ARCH=powerpc, and has been removed from this menu. If you wish523523+ to build a kernel for an Apple machine, exit this configuration524524+ process and re-run it with ARCH=powerpc.525525+526526+ Select CHRP/PReP if configuring for an IBM RS/6000 or527527+ pSeries machine, or a PReP machine.502528503529 Select Gemini if configuring for a Synergy Microsystems' Gemini504530 series Single Board Computer. More information is available at:···512530 available at: <http://linux-apus.sourceforge.net/>.513531514532config PPC_MULTIPLATFORM515515- bool "CHRP/PowerMac/PReP"533533+ bool "CHRP/PReP"516534517535config APUS518536 bool "Amiga-APUS"···750768 on it (826x, 827x, 8560).751769752770config PPC_CHRP753753- bool771771+ bool "Support for CHRP (Common Hardware Reference Platform) machines"754772 depends on PPC_MULTIPLATFORM755773 select PPC_I8259756774 select PPC_INDIRECT_PCI757775 default y758776759759-config PPC_PMAC760760- bool761761- depends on PPC_MULTIPLATFORM762762- select PPC_INDIRECT_PCI763763- default y764764-765765-config PPC_PMAC64766766- bool767767- depends on PPC_PMAC && POWER4768768- default y769769-770777config PPC_PREP771771- bool778778+ bool "Support for PReP (PowerPC Reference Platform) machines"772779 depends on PPC_MULTIPLATFORM773780 select PPC_I8259774781 select PPC_INDIRECT_PCI···765794766795config PPC_OF767796 bool768768- depends on PPC_PMAC || PPC_CHRP797797+ depends on PPC_CHRP769798 default y770799771800config PPC_GEN550···1137116611381167config GENERIC_ISA_DMA11391168 bool11401140- depends on POWER3 || POWER4 || 6xx && !CPM211691169+ depends on POWER3 || 6xx && !CPM211411170 default y1142117111431172config PPC_I8259
+1-1
arch/ppc/boot/Makefile
···1818bootdir-y := simple1919bootdir-$(CONFIG_PPC_OF) += openfirmware2020subdir-y := lib common images2121-subdir-$(CONFIG_PPC_OF) += of12752121+subdir-$(CONFIG_PPC_MULTIPLATFORM) += of127522222323# for cleaning2424subdir- += simple openfirmware
···204204 mtctr r5205205 bctr206206207207-#if defined(CONFIG_CPU_FREQ_PMAC) && defined(CONFIG_6xx)208208-209209-/* This gets called by via-pmu.c to switch the PLL selection210210- * on 750fx CPU. This function should really be moved to some211211- * other place (as most of the cpufreq code in via-pmu212212- */213213-_GLOBAL(low_choose_750fx_pll)214214- /* Clear MSR:EE */215215- mfmsr r7216216- rlwinm r0,r7,0,17,15217217- mtmsr r0218218-219219- /* If switching to PLL1, disable HID0:BTIC */220220- cmplwi cr0,r3,0221221- beq 1f222222- mfspr r5,SPRN_HID0223223- rlwinm r5,r5,0,27,25224224- sync225225- mtspr SPRN_HID0,r5226226- isync227227- sync228228-229229-1:230230- /* Calc new HID1 value */231231- mfspr r4,SPRN_HID1 /* Build a HID1:PS bit from parameter */232232- rlwinm r5,r3,16,15,15 /* Clear out HID1:PS from value read */233233- rlwinm r4,r4,0,16,14 /* Could have I used rlwimi here ? */234234- or r4,r4,r5235235- mtspr SPRN_HID1,r4236236-237237- /* Store new HID1 image */238238- rlwinm r6,r1,0,0,18239239- lwz r6,TI_CPU(r6)240240- slwi r6,r6,2241241- addis r6,r6,nap_save_hid1@ha242242- stw r4,nap_save_hid1@l(r6)243243-244244- /* If switching to PLL0, enable HID0:BTIC */245245- cmplwi cr0,r3,0246246- bne 1f247247- mfspr r5,SPRN_HID0248248- ori r5,r5,HID0_BTIC249249- sync250250- mtspr SPRN_HID0,r5251251- isync252252- sync253253-254254-1:255255- /* Return */256256- mtmsr r7257257- blr258258-259259-_GLOBAL(low_choose_7447a_dfs)260260- /* Clear MSR:EE */261261- mfmsr r7262262- rlwinm r0,r7,0,17,15263263- mtmsr r0264264-265265- /* Calc new HID1 value */266266- mfspr r4,SPRN_HID1267267- insrwi r4,r3,1,9 /* insert parameter into bit 9 */268268- sync269269- mtspr SPRN_HID1,r4270270- sync271271- isync272272-273273- /* Return */274274- mtmsr r7275275- blr276276-277277-#endif /* CONFIG_CPU_FREQ_PMAC && CONFIG_6xx */278278-279207/*280208 * complement mask on the msr then "or" some values on.281209 * _nmask_and_or_msr(nmask, value_to_or)
+2-238
arch/ppc/kernel/pci.c
···11/*22- * Common pmac/prep/chrp pci routines. -- Cort22+ * Common prep/chrp pci routines. -- Cort33 */4455#include <linux/config.h>···5050static u8* pci_to_OF_bus_map;5151#endif52525353-/* By default, we don't re-assign bus numbers. We do this only on5454- * some pmacs5353+/* By default, we don't re-assign bus numbers.5554 */5655int pci_assign_all_buses;5756···779780 return NULL;780781781782 /* Fixup bus number according to what OF think it is. */782782-#ifdef CONFIG_PPC_PMAC783783- /* The G5 need a special case here. Basically, we don't remap all784784- * busses on it so we don't create the pci-OF-map. However, we do785785- * remap the AGP bus and so have to deal with it. A future better786786- * fix has to be done by making the remapping per-host and always787787- * filling the pci_to_OF map. --BenH788788- */789789- if (_machine == _MACH_Pmac && busnr >= 0xf0)790790- busnr -= 0xf0;791791- else792792-#endif793783 if (pci_to_OF_bus_map)794784 busnr = pci_to_OF_bus_map[busnr];795785 if (busnr == 0xff)···10281040}102910411030104210311031-#ifdef CONFIG_PPC_PMAC10321032-/*10331033- * This set of routines checks for PCI<->PCI bridges that have closed10341034- * IO resources and have child devices. It tries to re-open an IO10351035- * window on them.10361036- *10371037- * This is a _temporary_ fix to workaround a problem with Apple's OF10381038- * closing IO windows on P2P bridges when the OF drivers of cards10391039- * below this bridge don't claim any IO range (typically ATI or10401040- * Adaptec).10411041- *10421042- * A more complete fix would be to use drivers/pci/setup-bus.c, which10431043- * involves a working pcibios_fixup_pbus_ranges(), some more care about10441044- * ordering when creating the host bus resources, and maybe a few more10451045- * minor tweaks10461046- */10471047-10481048-/* Initialize bridges with base/limit values we have collected */10491049-static void __init10501050-do_update_p2p_io_resource(struct pci_bus *bus, int enable_vga)10511051-{10521052- struct pci_dev *bridge = bus->self;10531053- struct pci_controller* hose = (struct pci_controller *)bridge->sysdata;10541054- u32 l;10551055- u16 w;10561056- struct resource res;10571057-10581058- if (bus->resource[0] == NULL)10591059- return;10601060- res = *(bus->resource[0]);10611061-10621062- DBG("Remapping Bus %d, bridge: %s\n", bus->number, pci_name(bridge));10631063- res.start -= ((unsigned long) hose->io_base_virt - isa_io_base);10641064- res.end -= ((unsigned long) hose->io_base_virt - isa_io_base);10651065- DBG(" IO window: %08lx-%08lx\n", res.start, res.end);10661066-10671067- /* Set up the top and bottom of the PCI I/O segment for this bus. */10681068- pci_read_config_dword(bridge, PCI_IO_BASE, &l);10691069- l &= 0xffff000f;10701070- l |= (res.start >> 8) & 0x00f0;10711071- l |= res.end & 0xf000;10721072- pci_write_config_dword(bridge, PCI_IO_BASE, l);10731073-10741074- if ((l & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {10751075- l = (res.start >> 16) | (res.end & 0xffff0000);10761076- pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, l);10771077- }10781078-10791079- pci_read_config_word(bridge, PCI_COMMAND, &w);10801080- w |= PCI_COMMAND_IO;10811081- pci_write_config_word(bridge, PCI_COMMAND, w);10821082-10831083-#if 0 /* Enabling this causes XFree 4.2.0 to hang during PCI probe */10841084- if (enable_vga) {10851085- pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &w);10861086- w |= PCI_BRIDGE_CTL_VGA;10871087- pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, w);10881088- }10891089-#endif10901090-}10911091-10921092-/* This function is pretty basic and actually quite broken for the10931093- * general case, it's enough for us right now though. It's supposed10941094- * to tell us if we need to open an IO range at all or not and what10951095- * size.10961096- */10971097-static int __init10981098-check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga)10991099-{11001100- struct pci_dev *dev;11011101- int i;11021102- int rc = 0;11031103-11041104-#define push_end(res, size) do { unsigned long __sz = (size) ; \11051105- res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \11061106- } while (0)11071107-11081108- list_for_each_entry(dev, &bus->devices, bus_list) {11091109- u16 class = dev->class >> 8;11101110-11111111- if (class == PCI_CLASS_DISPLAY_VGA ||11121112- class == PCI_CLASS_NOT_DEFINED_VGA)11131113- *found_vga = 1;11141114- if (class >> 8 == PCI_BASE_CLASS_BRIDGE && dev->subordinate)11151115- rc |= check_for_io_childs(dev->subordinate, res, found_vga);11161116- if (class == PCI_CLASS_BRIDGE_CARDBUS)11171117- push_end(res, 0xfff);11181118-11191119- for (i=0; i<PCI_NUM_RESOURCES; i++) {11201120- struct resource *r;11211121- unsigned long r_size;11221122-11231123- if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI11241124- && i >= PCI_BRIDGE_RESOURCES)11251125- continue;11261126- r = &dev->resource[i];11271127- r_size = r->end - r->start;11281128- if (r_size < 0xfff)11291129- r_size = 0xfff;11301130- if (r->flags & IORESOURCE_IO && (r_size) != 0) {11311131- rc = 1;11321132- push_end(res, r_size);11331133- }11341134- }11351135- }11361136-11371137- return rc;11381138-}11391139-11401140-/* Here we scan all P2P bridges of a given level that have a closed11411141- * IO window. Note that the test for the presence of a VGA card should11421142- * be improved to take into account already configured P2P bridges,11431143- * currently, we don't see them and might end up configuring 2 bridges11441144- * with VGA pass through enabled11451145- */11461146-static void __init11471147-do_fixup_p2p_level(struct pci_bus *bus)11481148-{11491149- struct pci_bus *b;11501150- int i, parent_io;11511151- int has_vga = 0;11521152-11531153- for (parent_io=0; parent_io<4; parent_io++)11541154- if (bus->resource[parent_io]11551155- && bus->resource[parent_io]->flags & IORESOURCE_IO)11561156- break;11571157- if (parent_io >= 4)11581158- return;11591159-11601160- list_for_each_entry(b, &bus->children, node) {11611161- struct pci_dev *d = b->self;11621162- struct pci_controller* hose = (struct pci_controller *)d->sysdata;11631163- struct resource *res = b->resource[0];11641164- struct resource tmp_res;11651165- unsigned long max;11661166- int found_vga = 0;11671167-11681168- memset(&tmp_res, 0, sizeof(tmp_res));11691169- tmp_res.start = bus->resource[parent_io]->start;11701170-11711171- /* We don't let low addresses go through that closed P2P bridge, well,11721172- * that may not be necessary but I feel safer that way11731173- */11741174- if (tmp_res.start == 0)11751175- tmp_res.start = 0x1000;11761176-11771177- if (!list_empty(&b->devices) && res && res->flags == 0 &&11781178- res != bus->resource[parent_io] &&11791179- (d->class >> 8) == PCI_CLASS_BRIDGE_PCI &&11801180- check_for_io_childs(b, &tmp_res, &found_vga)) {11811181- u8 io_base_lo;11821182-11831183- printk(KERN_INFO "Fixing up IO bus %s\n", b->name);11841184-11851185- if (found_vga) {11861186- if (has_vga) {11871187- printk(KERN_WARNING "Skipping VGA, already active"11881188- " on bus segment\n");11891189- found_vga = 0;11901190- } else11911191- has_vga = 1;11921192- }11931193- pci_read_config_byte(d, PCI_IO_BASE, &io_base_lo);11941194-11951195- if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32)11961196- max = ((unsigned long) hose->io_base_virt11971197- - isa_io_base) + 0xffffffff;11981198- else11991199- max = ((unsigned long) hose->io_base_virt12001200- - isa_io_base) + 0xffff;12011201-12021202- *res = tmp_res;12031203- res->flags = IORESOURCE_IO;12041204- res->name = b->name;12051205-12061206- /* Find a resource in the parent where we can allocate */12071207- for (i = 0 ; i < 4; i++) {12081208- struct resource *r = bus->resource[i];12091209- if (!r)12101210- continue;12111211- if ((r->flags & IORESOURCE_IO) == 0)12121212- continue;12131213- DBG("Trying to allocate from %08lx, size %08lx from parent"12141214- " res %d: %08lx -> %08lx\n",12151215- res->start, res->end, i, r->start, r->end);12161216-12171217- if (allocate_resource(r, res, res->end + 1, res->start, max,12181218- res->end + 1, NULL, NULL) < 0) {12191219- DBG("Failed !\n");12201220- continue;12211221- }12221222- do_update_p2p_io_resource(b, found_vga);12231223- break;12241224- }12251225- }12261226- do_fixup_p2p_level(b);12271227- }12281228-}12291229-12301230-static void12311231-pcibios_fixup_p2p_bridges(void)12321232-{12331233- struct pci_bus *b;12341234-12351235- list_for_each_entry(b, &pci_root_buses, node)12361236- do_fixup_p2p_level(b);12371237-}12381238-12391239-#endif /* CONFIG_PPC_PMAC */12401240-12411043static int __init12421044pcibios_init(void)12431045{···10681290 pcibios_allocate_bus_resources(&pci_root_buses);10691291 pcibios_allocate_resources(0);10701292 pcibios_allocate_resources(1);10711071-#ifdef CONFIG_PPC_PMAC10721072- pcibios_fixup_p2p_bridges();10731073-#endif /* CONFIG_PPC_PMAC */10741293 pcibios_assign_resources();1075129410761295 /* Call machine dependent post-init code */···14961721{14971722 struct pci_controller* hose;14981723 long result = -EOPNOTSUPP;14991499-15001500- /* Argh ! Please forgive me for that hack, but that's the15011501- * simplest way to get existing XFree to not lockup on some15021502- * G5 machines... So when something asks for bus 0 io base15031503- * (bus 0 is HT root), we return the AGP one instead.15041504- */15051505-#ifdef CONFIG_PPC_PMAC15061506- if (_machine == _MACH_Pmac && machine_is_compatible("MacRISC4"))15071507- if (bus == 0)15081508- bus = 0xf0;15091509-#endif /* CONFIG_PPC_PMAC */1510172415111725 hose = pci_bus_to_hose(bus);15121726 if (!hose)
···11/*22- * Common prep/pmac/chrp boot and setup code.22+ * Common prep/chrp boot and setup code.33 */4455#include <linux/config.h>···3535#include <asm/machdep.h>3636#include <asm/uaccess.h>3737#include <asm/system.h>3838-#include <asm/pmac_feature.h>3938#include <asm/sections.h>4039#include <asm/nvram.h>4140#include <asm/xmon.h>···54555556extern void platform_init(unsigned long r3, unsigned long r4,5657 unsigned long r5, unsigned long r6, unsigned long r7);5757-extern void bootx_init(unsigned long r4, unsigned long phys);5858extern void identify_cpu(unsigned long offset, unsigned long cpu);5959extern void do_cpu_ftr_fixups(unsigned long offset);6060extern void reloc_got2(unsigned long offset);···7779EXPORT_SYMBOL(_machine);78807981extern void prep_init(unsigned long r3, unsigned long r4,8080- unsigned long r5, unsigned long r6, unsigned long r7);8181-extern void pmac_init(unsigned long r3, unsigned long r4,8282 unsigned long r5, unsigned long r6, unsigned long r7);8383extern void chrp_init(unsigned long r3, unsigned long r4,8484 unsigned long r5, unsigned long r6, unsigned long r7);···320324 identify_cpu(offset, 0);321325 do_cpu_ftr_fixups(offset);322326323323-#if defined(CONFIG_PPC_MULTIPLATFORM)327327+#if defined(CONFIG_PPC_OF)324328 reloc_got2(offset);325325-326326- /* If we came here from BootX, clear the screen,327327- * set up some pointers and return. */328328- if ((r3 == 0x426f6f58) && (r5 == 0))329329- bootx_init(r4, phys);330329331330 /*332331 * don't do anything on prep333332 * for now, don't use bootinfo because it breaks yaboot 0.5334333 * and assume that if we didn't find a magic number, we have OF335334 */336336- else if (*(unsigned long *)(0) != 0xdeadc0de)335335+ if (*(unsigned long *)(0) != 0xdeadc0de)337336 phys = prom_init(r3, r4, (prom_entry)r5);338337339338 reloc_got2(-offset);···415424 }416425#endif417426427427+#ifdef CONFIG_PPC_OF418428 have_of = 1;419429420430 /* prom_init has already been called from __start */···487495#endif /* CONFIG_ADB */488496489497 switch (_machine) {490490-#ifdef CONFIG_PPC_PMAC491491- case _MACH_Pmac:492492- pmac_init(r3, r4, r5, r6, r7);493493- break;494494-#endif495498#ifdef CONFIG_PPC_CHRP496499 case _MACH_chrp:497500 chrp_init(r3, r4, r5, r6, r7);498501 break;499502#endif500503 }504504+#endif /* CONFIG_PPC_OF */501505}506506+#endif /* CONFIG_PPC_MULTIPLATFORM */502507508508+#ifdef CONFIG_PPC_OF503509#ifdef CONFIG_SERIAL_CORE_CONSOLE504510extern char *of_stdout_device;505511···554564}555565console_initcall(set_preferred_console);556566#endif /* CONFIG_SERIAL_CORE_CONSOLE */557557-#endif /* CONFIG_PPC_MULTIPLATFORM */567567+#endif /* CONFIG_PPC_OF */558568559569struct bi_record *find_bootinfo(void)560570{···736746737747 if (ppc_md.init_early)738748 ppc_md.init_early();739739-740740-#ifdef CONFIG_PPC_MULTIPLATFORM741741- /* This could be called "early setup arch", it must be done742742- * now because xmon need it743743- */744744- if (_machine == _MACH_Pmac)745745- pmac_feature_init(); /* New cool way */746746-#endif747749748750#ifdef CONFIG_XMON749751 xmon_init(1);
+2-11
arch/ppc/kernel/traps.c
···3838#include <asm/io.h>3939#include <asm/reg.h>4040#include <asm/xmon.h>4141-#ifdef CONFIG_PMAC_BACKLIGHT4242-#include <asm/backlight.h>4343-#endif4441#include <asm/pmc.h>45424643#ifdef CONFIG_XMON···8285 int nl = 0;8386 console_verbose();8487 spin_lock_irq(&die_lock);8585-#ifdef CONFIG_PMAC_BACKLIGHT8686- if (_machine == _MACH_Pmac) {8787- set_backlight_enable(1);8888- set_backlight_level(BACKLIGHT_MAX);8989- }9090-#endif9188 printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);9289#ifdef CONFIG_PREEMPT9390 printk("PREEMPT ");···150159 */151160static inline int check_io_access(struct pt_regs *regs)152161{153153-#if defined CONFIG_PPC_PMAC || defined CONFIG_8xx162162+#if defined CONFIG_8xx154163 unsigned long msr = regs->msr;155164 const struct exception_table_entry *entry;156165 unsigned int *nip = (unsigned int *)regs->nip;···187196 return 1;188197 }189198 }190190-#endif /* CONFIG_PPC_PMAC */199199+#endif /* CONFIG_8xx */191200 return 0;192201}193202
-29
arch/ppc/mm/init.c
···6767int mem_init_done;6868int init_bootmem_done;6969int boot_mapsize;7070-#ifdef CONFIG_PPC_PMAC7171-unsigned long agp_special_page;7272-EXPORT_SYMBOL(agp_special_page);7373-#endif74707571extern char _end[];7672extern char etext[], _stext[];···420424 addr += PAGE_SIZE)421425 SetPageReserved(virt_to_page(addr));422426#endif423423-#ifdef CONFIG_PPC_PMAC424424- if (agp_special_page)425425- SetPageReserved(virt_to_page(agp_special_page));426426-#endif427427 for (addr = PAGE_OFFSET; addr < (unsigned long)high_memory;428428 addr += PAGE_SIZE) {429429 if (!PageReserved(virt_to_page(addr)))···454462 codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10),455463 initpages<< (PAGE_SHIFT-10),456464 (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));457457-458458-#ifdef CONFIG_PPC_PMAC459459- if (agp_special_page)460460- printk(KERN_INFO "AGP special page: 0x%08lx\n", agp_special_page);461461-#endif462465463466 mem_init_done = 1;464467}···499512 if (rtas_data)500513 mem_pieces_remove(&phys_avail, rtas_data, rtas_size, 1);501514#endif502502-#ifdef CONFIG_PPC_PMAC503503- /* Because of some uninorth weirdness, we need a page of504504- * memory as high as possible (it must be outside of the505505- * bus address seen as the AGP aperture). It will be used506506- * by the r128 DRM driver507507- *508508- * FIXME: We need to make sure that page doesn't overlap any of the\509509- * above. This could be done by improving mem_pieces_find to be able510510- * to do a backward search from the end of the list.511511- */512512- if (_machine == _MACH_Pmac && find_devices("uni-north-agp")) {513513- agp_special_page = (total_memory - PAGE_SIZE);514514- mem_pieces_remove(&phys_avail, agp_special_page, PAGE_SIZE, 0);515515- agp_special_page = (unsigned long)__va(agp_special_page);516516- }517517-#endif /* CONFIG_PPC_PMAC */518515}519516520517/* Mark some memory as reserved by removing it from phys_avail. */
···5353#include <asm/i8259.h>5454#include <asm/open_pic.h>5555#include <asm/xmon.h>5656+#include "mem_pieces.h"56575758unsigned long chrp_get_rtc_time(void);5859int chrp_set_rtc_time(unsigned long nowtime);···6665void rtas_indicator_progress(char *, unsigned short);6766void btext_progress(char *, unsigned short);68676969-extern unsigned long pmac_find_end_of_memory(void);7068extern int of_show_percpuinfo(struct seq_file *, int);71697270int _chrp_type;···467467 ppc_md.progress(" Have fun! ", 0x7777);468468}469469470470+static struct device_node *memory_node;471471+472472+static int __init get_mem_prop(char *name, struct mem_pieces *mp)473473+{474474+ struct reg_property *rp;475475+ int i, s;476476+ unsigned int *ip;477477+ int nac = prom_n_addr_cells(memory_node);478478+ int nsc = prom_n_size_cells(memory_node);479479+480480+ ip = (unsigned int *) get_property(memory_node, name, &s);481481+ if (ip == NULL) {482482+ printk(KERN_ERR "error: couldn't get %s property on /memory\n",483483+ name);484484+ return 0;485485+ }486486+ s /= (nsc + nac) * 4;487487+ rp = mp->regions;488488+ for (i = 0; i < s; ++i, ip += nac+nsc) {489489+ if (nac >= 2 && ip[nac-2] != 0)490490+ continue;491491+ rp->address = ip[nac-1];492492+ if (nsc >= 2 && ip[nac+nsc-2] != 0)493493+ rp->size = ~0U;494494+ else495495+ rp->size = ip[nac+nsc-1];496496+ ++rp;497497+ }498498+ mp->n_regions = rp - mp->regions;499499+500500+ /* Make sure the pieces are sorted. */501501+ mem_pieces_sort(mp);502502+ mem_pieces_coalesce(mp);503503+ return 1;504504+}505505+506506+static unsigned long __init chrp_find_end_of_memory(void)507507+{508508+ unsigned long a, total;509509+ struct mem_pieces phys_mem;510510+511511+ /*512512+ * Find out where physical memory is, and check that it513513+ * starts at 0 and is contiguous. It seems that RAM is514514+ * always physically contiguous on Power Macintoshes.515515+ *516516+ * Supporting discontiguous physical memory isn't hard,517517+ * it just makes the virtual <-> physical mapping functions518518+ * more complicated (or else you end up wasting space519519+ * in mem_map).520520+ */521521+ memory_node = find_devices("memory");522522+ if (memory_node == NULL || !get_mem_prop("reg", &phys_mem)523523+ || phys_mem.n_regions == 0)524524+ panic("No RAM??");525525+ a = phys_mem.regions[0].address;526526+ if (a != 0)527527+ panic("RAM doesn't start at physical address 0");528528+ total = phys_mem.regions[0].size;529529+530530+ if (phys_mem.n_regions > 1) {531531+ printk("RAM starting at 0x%x is not contiguous\n",532532+ phys_mem.regions[1].address);533533+ printk("Using RAM from 0 to 0x%lx\n", total-1);534534+ }535535+536536+ return total;537537+}538538+470539void __init471540chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,472541 unsigned long r6, unsigned long r7)···594525 ppc_md.get_rtc_time = chrp_get_rtc_time;595526 ppc_md.calibrate_decr = chrp_calibrate_decr;596527597597- ppc_md.find_end_of_memory = pmac_find_end_of_memory;528528+ ppc_md.find_end_of_memory = chrp_find_end_of_memory;598529599530 if (rtas_data) {600531 struct device_node *rtas;
+63-1
arch/ppc/platforms/chrp_time.c
···163163 return mktime(year, mon, day, hour, min, sec);164164}165165166166+/*167167+ * Calibrate the decrementer frequency with the VIA timer 1.168168+ */169169+#define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */170170+171171+/* VIA registers */172172+#define RS 0x200 /* skip between registers */173173+#define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */174174+#define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */175175+#define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */176176+#define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */177177+#define ACR (11*RS) /* Auxiliary control register */178178+#define IFR (13*RS) /* Interrupt flag register */179179+180180+/* Bits in ACR */181181+#define T1MODE 0xc0 /* Timer 1 mode */182182+#define T1MODE_CONT 0x40 /* continuous interrupts */183183+184184+/* Bits in IFR and IER */185185+#define T1_INT 0x40 /* Timer 1 interrupt */186186+187187+static int __init chrp_via_calibrate_decr(void)188188+{189189+ struct device_node *vias;190190+ volatile unsigned char __iomem *via;191191+ int count = VIA_TIMER_FREQ_6 / 100;192192+ unsigned int dstart, dend;193193+194194+ vias = find_devices("via-cuda");195195+ if (vias == 0)196196+ vias = find_devices("via");197197+ if (vias == 0 || vias->n_addrs == 0)198198+ return 0;199199+ via = ioremap(vias->addrs[0].address, vias->addrs[0].size);200200+201201+ /* set timer 1 for continuous interrupts */202202+ out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT);203203+ /* set the counter to a small value */204204+ out_8(&via[T1CH], 2);205205+ /* set the latch to `count' */206206+ out_8(&via[T1LL], count);207207+ out_8(&via[T1LH], count >> 8);208208+ /* wait until it hits 0 */209209+ while ((in_8(&via[IFR]) & T1_INT) == 0)210210+ ;211211+ dstart = get_dec();212212+ /* clear the interrupt & wait until it hits 0 again */213213+ in_8(&via[T1CL]);214214+ while ((in_8(&via[IFR]) & T1_INT) == 0)215215+ ;216216+ dend = get_dec();217217+218218+ tb_ticks_per_jiffy = (dstart - dend) / ((6 * HZ)/100);219219+ tb_to_us = mulhwu_scale_factor(dstart - dend, 60000);220220+221221+ printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n",222222+ tb_ticks_per_jiffy, dstart - dend);223223+224224+ iounmap(via);225225+226226+ return 1;227227+}166228167229void __init chrp_calibrate_decr(void)168230{169231 struct device_node *cpu;170232 unsigned int freq, *fp;171233172172- if (via_calibrate_decr())234234+ if (chrp_via_calibrate_decr())173235 return;174236175237 /*
-202
arch/ppc/platforms/pmac_backlight.c
···11-/*22- * Miscellaneous procedures for dealing with the PowerMac hardware.33- * Contains support for the backlight.44- *55- * Copyright (C) 2000 Benjamin Herrenschmidt66- *77- */88-99-#include <linux/config.h>1010-#include <linux/kernel.h>1111-#include <linux/module.h>1212-#include <linux/stddef.h>1313-#include <linux/reboot.h>1414-#include <linux/nvram.h>1515-#include <linux/console.h>1616-#include <asm/sections.h>1717-#include <asm/ptrace.h>1818-#include <asm/io.h>1919-#include <asm/pgtable.h>2020-#include <asm/system.h>2121-#include <asm/prom.h>2222-#include <asm/machdep.h>2323-#include <asm/nvram.h>2424-#include <asm/backlight.h>2525-2626-#include <linux/adb.h>2727-#include <linux/pmu.h>2828-2929-static struct backlight_controller *backlighter;3030-static void* backlighter_data;3131-static int backlight_autosave;3232-static int backlight_level = BACKLIGHT_MAX;3333-static int backlight_enabled = 1;3434-static int backlight_req_level = -1;3535-static int backlight_req_enable = -1;3636-3737-static void backlight_callback(void *);3838-static DECLARE_WORK(backlight_work, backlight_callback, NULL);3939-4040-void register_backlight_controller(struct backlight_controller *ctrler,4141- void *data, char *type)4242-{4343- struct device_node* bk_node;4444- char *prop;4545- int valid = 0;4646-4747- /* There's already a matching controller, bail out */4848- if (backlighter != NULL)4949- return;5050-5151- bk_node = find_devices("backlight");5252-5353-#ifdef CONFIG_ADB_PMU5454- /* Special case for the old PowerBook since I can't test on it */5555- backlight_autosave = machine_is_compatible("AAPL,3400/2400")5656- || machine_is_compatible("AAPL,3500");5757- if ((backlight_autosave5858- || machine_is_compatible("AAPL,PowerBook1998")5959- || machine_is_compatible("PowerBook1,1"))6060- && !strcmp(type, "pmu"))6161- valid = 1;6262-#endif6363- if (bk_node) {6464- prop = get_property(bk_node, "backlight-control", NULL);6565- if (prop && !strncmp(prop, type, strlen(type)))6666- valid = 1;6767- }6868- if (!valid)6969- return;7070- backlighter = ctrler;7171- backlighter_data = data;7272-7373- if (bk_node && !backlight_autosave)7474- prop = get_property(bk_node, "bklt", NULL);7575- else7676- prop = NULL;7777- if (prop) {7878- backlight_level = ((*prop)+1) >> 1;7979- if (backlight_level > BACKLIGHT_MAX)8080- backlight_level = BACKLIGHT_MAX;8181- }8282-8383-#ifdef CONFIG_ADB_PMU8484- if (backlight_autosave) {8585- struct adb_request req;8686- pmu_request(&req, NULL, 2, 0xd9, 0);8787- while (!req.complete)8888- pmu_poll();8989- backlight_level = req.reply[0] >> 4;9090- }9191-#endif9292- acquire_console_sem();9393- if (!backlighter->set_enable(1, backlight_level, data))9494- backlight_enabled = 1;9595- release_console_sem();9696-9797- printk(KERN_INFO "Registered \"%s\" backlight controller,"9898- "level: %d/15\n", type, backlight_level);9999-}100100-EXPORT_SYMBOL(register_backlight_controller);101101-102102-void unregister_backlight_controller(struct backlight_controller103103- *ctrler, void *data)104104-{105105- /* We keep the current backlight level (for now) */106106- if (ctrler == backlighter && data == backlighter_data)107107- backlighter = NULL;108108-}109109-EXPORT_SYMBOL(unregister_backlight_controller);110110-111111-static int __set_backlight_enable(int enable)112112-{113113- int rc;114114-115115- if (!backlighter)116116- return -ENODEV;117117- acquire_console_sem();118118- rc = backlighter->set_enable(enable, backlight_level,119119- backlighter_data);120120- if (!rc)121121- backlight_enabled = enable;122122- release_console_sem();123123- return rc;124124-}125125-int set_backlight_enable(int enable)126126-{127127- if (!backlighter)128128- return -ENODEV;129129- backlight_req_enable = enable;130130- schedule_work(&backlight_work);131131- return 0;132132-}133133-134134-EXPORT_SYMBOL(set_backlight_enable);135135-136136-int get_backlight_enable(void)137137-{138138- if (!backlighter)139139- return -ENODEV;140140- return backlight_enabled;141141-}142142-EXPORT_SYMBOL(get_backlight_enable);143143-144144-static int __set_backlight_level(int level)145145-{146146- int rc = 0;147147-148148- if (!backlighter)149149- return -ENODEV;150150- if (level < BACKLIGHT_MIN)151151- level = BACKLIGHT_OFF;152152- if (level > BACKLIGHT_MAX)153153- level = BACKLIGHT_MAX;154154- acquire_console_sem();155155- if (backlight_enabled)156156- rc = backlighter->set_level(level, backlighter_data);157157- if (!rc)158158- backlight_level = level;159159- release_console_sem();160160- if (!rc && !backlight_autosave) {161161- level <<=1;162162- if (level & 0x10)163163- level |= 0x01;164164- // -- todo: save to property "bklt"165165- }166166- return rc;167167-}168168-int set_backlight_level(int level)169169-{170170- if (!backlighter)171171- return -ENODEV;172172- backlight_req_level = level;173173- schedule_work(&backlight_work);174174- return 0;175175-}176176-177177-EXPORT_SYMBOL(set_backlight_level);178178-179179-int get_backlight_level(void)180180-{181181- if (!backlighter)182182- return -ENODEV;183183- return backlight_level;184184-}185185-EXPORT_SYMBOL(get_backlight_level);186186-187187-static void backlight_callback(void *dummy)188188-{189189- int level, enable;190190-191191- do {192192- level = backlight_req_level;193193- enable = backlight_req_enable;194194- mb();195195-196196- if (level >= 0)197197- __set_backlight_level(level);198198- if (enable >= 0)199199- __set_backlight_enable(enable);200200- } while(cmpxchg(&backlight_req_level, level, -1) != level ||201201- cmpxchg(&backlight_req_enable, enable, -1) != enable);202202-}
-359
arch/ppc/platforms/pmac_cache.S
···11-/*22- * This file contains low-level cache management functions33- * used for sleep and CPU speed changes on Apple machines.44- * (In fact the only thing that is Apple-specific is that we assume55- * that we can read from ROM at physical address 0xfff00000.)66- *77- * Copyright (C) 2004 Paul Mackerras (paulus@samba.org) and88- * Benjamin Herrenschmidt (benh@kernel.crashing.org)99- *1010- * This program is free software; you can redistribute it and/or1111- * modify it under the terms of the GNU General Public License1212- * as published by the Free Software Foundation; either version1313- * 2 of the License, or (at your option) any later version.1414- *1515- */1616-1717-#include <linux/config.h>1818-#include <asm/processor.h>1919-#include <asm/ppc_asm.h>2020-#include <asm/cputable.h>2121-2222-/*2323- * Flush and disable all data caches (dL1, L2, L3). This is used2424- * when going to sleep, when doing a PMU based cpufreq transition,2525- * or when "offlining" a CPU on SMP machines. This code is over2626- * paranoid, but I've had enough issues with various CPU revs and2727- * bugs that I decided it was worth beeing over cautious2828- */2929-3030-_GLOBAL(flush_disable_caches)3131-#ifndef CONFIG_6xx3232- blr3333-#else3434-BEGIN_FTR_SECTION3535- b flush_disable_745x3636-END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)3737-BEGIN_FTR_SECTION3838- b flush_disable_75x3939-END_FTR_SECTION_IFSET(CPU_FTR_L2CR)4040- b __flush_disable_L14141-4242-/* This is the code for G3 and 74[01]0 */4343-flush_disable_75x:4444- mflr r104545-4646- /* Turn off EE and DR in MSR */4747- mfmsr r114848- rlwinm r0,r11,0,~MSR_EE4949- rlwinm r0,r0,0,~MSR_DR5050- sync5151- mtmsr r05252- isync5353-5454- /* Stop DST streams */5555-BEGIN_FTR_SECTION5656- DSSALL5757- sync5858-END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)5959-6060- /* Stop DPM */6161- mfspr r8,SPRN_HID0 /* Save SPRN_HID0 in r8 */6262- rlwinm r4,r8,0,12,10 /* Turn off HID0[DPM] */6363- sync6464- mtspr SPRN_HID0,r4 /* Disable DPM */6565- sync6666-6767- /* Disp-flush L1. We have a weird problem here that I never6868- * totally figured out. On 750FX, using the ROM for the flush6969- * results in a non-working flush. We use that workaround for7070- * now until I finally understand what's going on. --BenH7171- */7272-7373- /* ROM base by default */7474- lis r4,0xfff07575- mfpvr r37676- srwi r3,r3,167777- cmplwi cr0,r3,0x70007878- bne+ 1f7979- /* RAM base on 750FX */8080- li r4,08181-1: li r4,0x40008282- mtctr r48383-1: lwz r0,0(r4)8484- addi r4,r4,328585- bdnz 1b8686- sync8787- isync8888-8989- /* Disable / invalidate / enable L1 data */9090- mfspr r3,SPRN_HID09191- rlwinm r3,r3,0,~(HID0_DCE | HID0_ICE)9292- mtspr SPRN_HID0,r39393- sync9494- isync9595- ori r3,r3,(HID0_DCE|HID0_DCI|HID0_ICE|HID0_ICFI)9696- sync9797- isync9898- mtspr SPRN_HID0,r39999- xori r3,r3,(HID0_DCI|HID0_ICFI)100100- mtspr SPRN_HID0,r3101101- sync102102-103103- /* Get the current enable bit of the L2CR into r4 */104104- mfspr r5,SPRN_L2CR105105- /* Set to data-only (pre-745x bit) */106106- oris r3,r5,L2CR_L2DO@h107107- b 2f108108- /* When disabling L2, code must be in L1 */109109- .balign 32110110-1: mtspr SPRN_L2CR,r3111111-3: sync112112- isync113113- b 1f114114-2: b 3f115115-3: sync116116- isync117117- b 1b118118-1: /* disp-flush L2. The interesting thing here is that the L2 can be119119- * up to 2Mb ... so using the ROM, we'll end up wrapping back to memory120120- * but that is probbaly fine. We disp-flush over 4Mb to be safe121121- */122122- lis r4,2123123- mtctr r4124124- lis r4,0xfff0125125-1: lwz r0,0(r4)126126- addi r4,r4,32127127- bdnz 1b128128- sync129129- isync130130- lis r4,2131131- mtctr r4132132- lis r4,0xfff0133133-1: dcbf 0,r4134134- addi r4,r4,32135135- bdnz 1b136136- sync137137- isync138138-139139- /* now disable L2 */140140- rlwinm r5,r5,0,~L2CR_L2E141141- b 2f142142- /* When disabling L2, code must be in L1 */143143- .balign 32144144-1: mtspr SPRN_L2CR,r5145145-3: sync146146- isync147147- b 1f148148-2: b 3f149149-3: sync150150- isync151151- b 1b152152-1: sync153153- isync154154- /* Invalidate L2. This is pre-745x, we clear the L2I bit ourselves */155155- oris r4,r5,L2CR_L2I@h156156- mtspr SPRN_L2CR,r4157157- sync158158- isync159159-160160- /* Wait for the invalidation to complete */161161-1: mfspr r3,SPRN_L2CR162162- rlwinm. r0,r3,0,31,31163163- bne 1b164164-165165- /* Clear L2I */166166- xoris r4,r4,L2CR_L2I@h167167- sync168168- mtspr SPRN_L2CR,r4169169- sync170170-171171- /* now disable the L1 data cache */172172- mfspr r0,SPRN_HID0173173- rlwinm r0,r0,0,~(HID0_DCE|HID0_ICE)174174- mtspr SPRN_HID0,r0175175- sync176176- isync177177-178178- /* Restore HID0[DPM] to whatever it was before */179179- sync180180- mfspr r0,SPRN_HID0181181- rlwimi r0,r8,0,11,11 /* Turn back HID0[DPM] */182182- mtspr SPRN_HID0,r0183183- sync184184-185185- /* restore DR and EE */186186- sync187187- mtmsr r11188188- isync189189-190190- mtlr r10191191- blr192192-193193-/* This code is for 745x processors */194194-flush_disable_745x:195195- /* Turn off EE and DR in MSR */196196- mfmsr r11197197- rlwinm r0,r11,0,~MSR_EE198198- rlwinm r0,r0,0,~MSR_DR199199- sync200200- mtmsr r0201201- isync202202-203203- /* Stop prefetch streams */204204- DSSALL205205- sync206206-207207- /* Disable L2 prefetching */208208- mfspr r0,SPRN_MSSCR0209209- rlwinm r0,r0,0,0,29210210- mtspr SPRN_MSSCR0,r0211211- sync212212- isync213213- lis r4,0214214- dcbf 0,r4215215- dcbf 0,r4216216- dcbf 0,r4217217- dcbf 0,r4218218- dcbf 0,r4219219- dcbf 0,r4220220- dcbf 0,r4221221- dcbf 0,r4222222-223223- /* Due to a bug with the HW flush on some CPU revs, we occasionally224224- * experience data corruption. I'm adding a displacement flush along225225- * with a dcbf loop over a few Mb to "help". The problem isn't totally226226- * fixed by this in theory, but at least, in practice, I couldn't reproduce227227- * it even with a big hammer...228228- */229229-230230- lis r4,0x0002231231- mtctr r4232232- li r4,0233233-1:234234- lwz r0,0(r4)235235- addi r4,r4,32 /* Go to start of next cache line */236236- bdnz 1b237237- isync238238-239239- /* Now, flush the first 4MB of memory */240240- lis r4,0x0002241241- mtctr r4242242- li r4,0243243- sync244244-1:245245- dcbf 0,r4246246- addi r4,r4,32 /* Go to start of next cache line */247247- bdnz 1b248248-249249- /* Flush and disable the L1 data cache */250250- mfspr r6,SPRN_LDSTCR251251- lis r3,0xfff0 /* read from ROM for displacement flush */252252- li r4,0xfe /* start with only way 0 unlocked */253253- li r5,128 /* 128 lines in each way */254254-1: mtctr r5255255- rlwimi r6,r4,0,24,31256256- mtspr SPRN_LDSTCR,r6257257- sync258258- isync259259-2: lwz r0,0(r3) /* touch each cache line */260260- addi r3,r3,32261261- bdnz 2b262262- rlwinm r4,r4,1,24,30 /* move on to the next way */263263- ori r4,r4,1264264- cmpwi r4,0xff /* all done? */265265- bne 1b266266- /* now unlock the L1 data cache */267267- li r4,0268268- rlwimi r6,r4,0,24,31269269- sync270270- mtspr SPRN_LDSTCR,r6271271- sync272272- isync273273-274274- /* Flush the L2 cache using the hardware assist */275275- mfspr r3,SPRN_L2CR276276- cmpwi r3,0 /* check if it is enabled first */277277- bge 4f278278- oris r0,r3,(L2CR_L2IO_745x|L2CR_L2DO_745x)@h279279- b 2f280280- /* When disabling/locking L2, code must be in L1 */281281- .balign 32282282-1: mtspr SPRN_L2CR,r0 /* lock the L2 cache */283283-3: sync284284- isync285285- b 1f286286-2: b 3f287287-3: sync288288- isync289289- b 1b290290-1: sync291291- isync292292- ori r0,r3,L2CR_L2HWF_745x293293- sync294294- mtspr SPRN_L2CR,r0 /* set the hardware flush bit */295295-3: mfspr r0,SPRN_L2CR /* wait for it to go to 0 */296296- andi. r0,r0,L2CR_L2HWF_745x297297- bne 3b298298- sync299299- rlwinm r3,r3,0,~L2CR_L2E300300- b 2f301301- /* When disabling L2, code must be in L1 */302302- .balign 32303303-1: mtspr SPRN_L2CR,r3 /* disable the L2 cache */304304-3: sync305305- isync306306- b 1f307307-2: b 3f308308-3: sync309309- isync310310- b 1b311311-1: sync312312- isync313313- oris r4,r3,L2CR_L2I@h314314- mtspr SPRN_L2CR,r4315315- sync316316- isync317317-1: mfspr r4,SPRN_L2CR318318- andis. r0,r4,L2CR_L2I@h319319- bne 1b320320- sync321321-322322-BEGIN_FTR_SECTION323323- /* Flush the L3 cache using the hardware assist */324324-4: mfspr r3,SPRN_L3CR325325- cmpwi r3,0 /* check if it is enabled */326326- bge 6f327327- oris r0,r3,L3CR_L3IO@h328328- ori r0,r0,L3CR_L3DO329329- sync330330- mtspr SPRN_L3CR,r0 /* lock the L3 cache */331331- sync332332- isync333333- ori r0,r0,L3CR_L3HWF334334- sync335335- mtspr SPRN_L3CR,r0 /* set the hardware flush bit */336336-5: mfspr r0,SPRN_L3CR /* wait for it to go to zero */337337- andi. r0,r0,L3CR_L3HWF338338- bne 5b339339- rlwinm r3,r3,0,~L3CR_L3E340340- sync341341- mtspr SPRN_L3CR,r3 /* disable the L3 cache */342342- sync343343- ori r4,r3,L3CR_L3I344344- mtspr SPRN_L3CR,r4345345-1: mfspr r4,SPRN_L3CR346346- andi. r0,r4,L3CR_L3I347347- bne 1b348348- sync349349-END_FTR_SECTION_IFSET(CPU_FTR_L3CR)350350-351351-6: mfspr r0,SPRN_HID0 /* now disable the L1 data cache */352352- rlwinm r0,r0,0,~HID0_DCE353353- mtspr SPRN_HID0,r0354354- sync355355- isync356356- mtmsr r11 /* restore DR and EE */357357- isync358358- blr359359-#endif /* CONFIG_6xx */
-735
arch/ppc/platforms/pmac_cpufreq.c
···11-/*22- * arch/ppc/platforms/pmac_cpufreq.c33- *44- * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>55- * Copyright (C) 2004 John Steele Scott <toojays@toojays.net>66- *77- * This program is free software; you can redistribute it and/or modify88- * it under the terms of the GNU General Public License version 2 as99- * published by the Free Software Foundation.1010- *1111- * TODO: Need a big cleanup here. Basically, we need to have different1212- * cpufreq_driver structures for the different type of HW instead of the1313- * current mess. We also need to better deal with the detection of the1414- * type of machine.1515- *1616- */1717-1818-#include <linux/config.h>1919-#include <linux/module.h>2020-#include <linux/types.h>2121-#include <linux/errno.h>2222-#include <linux/kernel.h>2323-#include <linux/delay.h>2424-#include <linux/sched.h>2525-#include <linux/adb.h>2626-#include <linux/pmu.h>2727-#include <linux/slab.h>2828-#include <linux/cpufreq.h>2929-#include <linux/init.h>3030-#include <linux/sysdev.h>3131-#include <linux/i2c.h>3232-#include <linux/hardirq.h>3333-#include <asm/prom.h>3434-#include <asm/machdep.h>3535-#include <asm/irq.h>3636-#include <asm/pmac_feature.h>3737-#include <asm/mmu_context.h>3838-#include <asm/sections.h>3939-#include <asm/cputable.h>4040-#include <asm/time.h>4141-#include <asm/system.h>4242-#include <asm/open_pic.h>4343-#include <asm/keylargo.h>4444-4545-/* WARNING !!! This will cause calibrate_delay() to be called,4646- * but this is an __init function ! So you MUST go edit4747- * init/main.c to make it non-init before enabling DEBUG_FREQ4848- */4949-#undef DEBUG_FREQ5050-5151-/*5252- * There is a problem with the core cpufreq code on SMP kernels,5353- * it won't recalculate the Bogomips properly5454- */5555-#ifdef CONFIG_SMP5656-#warning "WARNING, CPUFREQ not recommended on SMP kernels"5757-#endif5858-5959-extern void low_choose_7447a_dfs(int dfs);6060-extern void low_choose_750fx_pll(int pll);6161-extern void low_sleep_handler(void);6262-6363-/*6464- * Currently, PowerMac cpufreq supports only high & low frequencies6565- * that are set by the firmware6666- */6767-static unsigned int low_freq;6868-static unsigned int hi_freq;6969-static unsigned int cur_freq;7070-static unsigned int sleep_freq;7171-7272-/*7373- * Different models uses different mecanisms to switch the frequency7474- */7575-static int (*set_speed_proc)(int low_speed);7676-static unsigned int (*get_speed_proc)(void);7777-7878-/*7979- * Some definitions used by the various speedprocs8080- */8181-static u32 voltage_gpio;8282-static u32 frequency_gpio;8383-static u32 slew_done_gpio;8484-static int no_schedule;8585-static int has_cpu_l2lve;8686-static int is_pmu_based;8787-8888-/* There are only two frequency states for each processor. Values8989- * are in kHz for the time being.9090- */9191-#define CPUFREQ_HIGH 09292-#define CPUFREQ_LOW 19393-9494-static struct cpufreq_frequency_table pmac_cpu_freqs[] = {9595- {CPUFREQ_HIGH, 0},9696- {CPUFREQ_LOW, 0},9797- {0, CPUFREQ_TABLE_END},9898-};9999-100100-static struct freq_attr* pmac_cpu_freqs_attr[] = {101101- &cpufreq_freq_attr_scaling_available_freqs,102102- NULL,103103-};104104-105105-static inline void local_delay(unsigned long ms)106106-{107107- if (no_schedule)108108- mdelay(ms);109109- else110110- msleep(ms);111111-}112112-113113-static inline void wakeup_decrementer(void)114114-{115115- set_dec(tb_ticks_per_jiffy);116116- /* No currently-supported powerbook has a 601,117117- * so use get_tbl, not native118118- */119119- last_jiffy_stamp(0) = tb_last_stamp = get_tbl();120120-}121121-122122-#ifdef DEBUG_FREQ123123-static inline void debug_calc_bogomips(void)124124-{125125- /* This will cause a recalc of bogomips and display the126126- * result. We backup/restore the value to avoid affecting the127127- * core cpufreq framework's own calculation.128128- */129129- extern void calibrate_delay(void);130130-131131- unsigned long save_lpj = loops_per_jiffy;132132- calibrate_delay();133133- loops_per_jiffy = save_lpj;134134-}135135-#endif /* DEBUG_FREQ */136136-137137-/* Switch CPU speed under 750FX CPU control138138- */139139-static int cpu_750fx_cpu_speed(int low_speed)140140-{141141- u32 hid2;142142-143143- if (low_speed == 0) {144144- /* ramping up, set voltage first */145145- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);146146- /* Make sure we sleep for at least 1ms */147147- local_delay(10);148148-149149- /* tweak L2 for high voltage */150150- if (has_cpu_l2lve) {151151- hid2 = mfspr(SPRN_HID2);152152- hid2 &= ~0x2000;153153- mtspr(SPRN_HID2, hid2);154154- }155155- }156156-#ifdef CONFIG_6xx157157- low_choose_750fx_pll(low_speed);158158-#endif159159- if (low_speed == 1) {160160- /* tweak L2 for low voltage */161161- if (has_cpu_l2lve) {162162- hid2 = mfspr(SPRN_HID2);163163- hid2 |= 0x2000;164164- mtspr(SPRN_HID2, hid2);165165- }166166-167167- /* ramping down, set voltage last */168168- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04);169169- local_delay(10);170170- }171171-172172- return 0;173173-}174174-175175-static unsigned int cpu_750fx_get_cpu_speed(void)176176-{177177- if (mfspr(SPRN_HID1) & HID1_PS)178178- return low_freq;179179- else180180- return hi_freq;181181-}182182-183183-/* Switch CPU speed using DFS */184184-static int dfs_set_cpu_speed(int low_speed)185185-{186186- if (low_speed == 0) {187187- /* ramping up, set voltage first */188188- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);189189- /* Make sure we sleep for at least 1ms */190190- local_delay(1);191191- }192192-193193- /* set frequency */194194-#ifdef CONFIG_6xx195195- low_choose_7447a_dfs(low_speed);196196-#endif197197- udelay(100);198198-199199- if (low_speed == 1) {200200- /* ramping down, set voltage last */201201- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04);202202- local_delay(1);203203- }204204-205205- return 0;206206-}207207-208208-static unsigned int dfs_get_cpu_speed(void)209209-{210210- if (mfspr(SPRN_HID1) & HID1_DFS)211211- return low_freq;212212- else213213- return hi_freq;214214-}215215-216216-217217-/* Switch CPU speed using slewing GPIOs218218- */219219-static int gpios_set_cpu_speed(int low_speed)220220-{221221- int gpio, timeout = 0;222222-223223- /* If ramping up, set voltage first */224224- if (low_speed == 0) {225225- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);226226- /* Delay is way too big but it's ok, we schedule */227227- local_delay(10);228228- }229229-230230- /* Set frequency */231231- gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0);232232- if (low_speed == ((gpio & 0x01) == 0))233233- goto skip;234234-235235- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, frequency_gpio,236236- low_speed ? 0x04 : 0x05);237237- udelay(200);238238- do {239239- if (++timeout > 100)240240- break;241241- local_delay(1);242242- gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, slew_done_gpio, 0);243243- } while((gpio & 0x02) == 0);244244- skip:245245- /* If ramping down, set voltage last */246246- if (low_speed == 1) {247247- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04);248248- /* Delay is way too big but it's ok, we schedule */249249- local_delay(10);250250- }251251-252252-#ifdef DEBUG_FREQ253253- debug_calc_bogomips();254254-#endif255255-256256- return 0;257257-}258258-259259-/* Switch CPU speed under PMU control260260- */261261-static int pmu_set_cpu_speed(int low_speed)262262-{263263- struct adb_request req;264264- unsigned long save_l2cr;265265- unsigned long save_l3cr;266266- unsigned int pic_prio;267267- unsigned long flags;268268-269269- preempt_disable();270270-271271-#ifdef DEBUG_FREQ272272- printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1));273273-#endif274274- pmu_suspend();275275-276276- /* Disable all interrupt sources on openpic */277277- pic_prio = openpic_get_priority();278278- openpic_set_priority(0xf);279279-280280- /* Make sure the decrementer won't interrupt us */281281- asm volatile("mtdec %0" : : "r" (0x7fffffff));282282- /* Make sure any pending DEC interrupt occuring while we did283283- * the above didn't re-enable the DEC */284284- mb();285285- asm volatile("mtdec %0" : : "r" (0x7fffffff));286286-287287- /* We can now disable MSR_EE */288288- local_irq_save(flags);289289-290290- /* Giveup the FPU & vec */291291- enable_kernel_fp();292292-293293-#ifdef CONFIG_ALTIVEC294294- if (cpu_has_feature(CPU_FTR_ALTIVEC))295295- enable_kernel_altivec();296296-#endif /* CONFIG_ALTIVEC */297297-298298- /* Save & disable L2 and L3 caches */299299- save_l3cr = _get_L3CR(); /* (returns -1 if not available) */300300- save_l2cr = _get_L2CR(); /* (returns -1 if not available) */301301-302302- /* Send the new speed command. My assumption is that this command303303- * will cause PLL_CFG[0..3] to be changed next time CPU goes to sleep304304- */305305- pmu_request(&req, NULL, 6, PMU_CPU_SPEED, 'W', 'O', 'O', 'F', low_speed);306306- while (!req.complete)307307- pmu_poll();308308-309309- /* Prepare the northbridge for the speed transition */310310- pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,1);311311-312312- /* Call low level code to backup CPU state and recover from313313- * hardware reset314314- */315315- low_sleep_handler();316316-317317- /* Restore the northbridge */318318- pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,0);319319-320320- /* Restore L2 cache */321321- if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)322322- _set_L2CR(save_l2cr);323323- /* Restore L3 cache */324324- if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0)325325- _set_L3CR(save_l3cr);326326-327327- /* Restore userland MMU context */328328- set_context(current->active_mm->context, current->active_mm->pgd);329329-330330-#ifdef DEBUG_FREQ331331- printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1));332332-#endif333333-334334- /* Restore low level PMU operations */335335- pmu_unlock();336336-337337- /* Restore decrementer */338338- wakeup_decrementer();339339-340340- /* Restore interrupts */341341- openpic_set_priority(pic_prio);342342-343343- /* Let interrupts flow again ... */344344- local_irq_restore(flags);345345-346346-#ifdef DEBUG_FREQ347347- debug_calc_bogomips();348348-#endif349349-350350- pmu_resume();351351-352352- preempt_enable();353353-354354- return 0;355355-}356356-357357-static int do_set_cpu_speed(int speed_mode, int notify)358358-{359359- struct cpufreq_freqs freqs;360360- unsigned long l3cr;361361- static unsigned long prev_l3cr;362362-363363- freqs.old = cur_freq;364364- freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;365365- freqs.cpu = smp_processor_id();366366-367367- if (freqs.old == freqs.new)368368- return 0;369369-370370- if (notify)371371- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);372372- if (speed_mode == CPUFREQ_LOW &&373373- cpu_has_feature(CPU_FTR_L3CR)) {374374- l3cr = _get_L3CR();375375- if (l3cr & L3CR_L3E) {376376- prev_l3cr = l3cr;377377- _set_L3CR(0);378378- }379379- }380380- set_speed_proc(speed_mode == CPUFREQ_LOW);381381- if (speed_mode == CPUFREQ_HIGH &&382382- cpu_has_feature(CPU_FTR_L3CR)) {383383- l3cr = _get_L3CR();384384- if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr)385385- _set_L3CR(prev_l3cr);386386- }387387- if (notify)388388- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);389389- cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;390390-391391- return 0;392392-}393393-394394-static unsigned int pmac_cpufreq_get_speed(unsigned int cpu)395395-{396396- return cur_freq;397397-}398398-399399-static int pmac_cpufreq_verify(struct cpufreq_policy *policy)400400-{401401- return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs);402402-}403403-404404-static int pmac_cpufreq_target( struct cpufreq_policy *policy,405405- unsigned int target_freq,406406- unsigned int relation)407407-{408408- unsigned int newstate = 0;409409-410410- if (cpufreq_frequency_table_target(policy, pmac_cpu_freqs,411411- target_freq, relation, &newstate))412412- return -EINVAL;413413-414414- return do_set_cpu_speed(newstate, 1);415415-}416416-417417-unsigned int pmac_get_one_cpufreq(int i)418418-{419419- /* Supports only one CPU for now */420420- return (i == 0) ? cur_freq : 0;421421-}422422-423423-static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)424424-{425425- if (policy->cpu != 0)426426- return -ENODEV;427427-428428- policy->governor = CPUFREQ_DEFAULT_GOVERNOR;429429- policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;430430- policy->cur = cur_freq;431431-432432- cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu);433433- return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs);434434-}435435-436436-static u32 read_gpio(struct device_node *np)437437-{438438- u32 *reg = (u32 *)get_property(np, "reg", NULL);439439- u32 offset;440440-441441- if (reg == NULL)442442- return 0;443443- /* That works for all keylargos but shall be fixed properly444444- * some day... The problem is that it seems we can't rely445445- * on the "reg" property of the GPIO nodes, they are either446446- * relative to the base of KeyLargo or to the base of the447447- * GPIO space, and the device-tree doesn't help.448448- */449449- offset = *reg;450450- if (offset < KEYLARGO_GPIO_LEVELS0)451451- offset += KEYLARGO_GPIO_LEVELS0;452452- return offset;453453-}454454-455455-static int pmac_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg)456456-{457457- /* Ok, this could be made a bit smarter, but let's be robust for now. We458458- * always force a speed change to high speed before sleep, to make sure459459- * we have appropriate voltage and/or bus speed for the wakeup process,460460- * and to make sure our loops_per_jiffies are "good enough", that is will461461- * not cause too short delays if we sleep in low speed and wake in high462462- * speed..463463- */464464- no_schedule = 1;465465- sleep_freq = cur_freq;466466- if (cur_freq == low_freq && !is_pmu_based)467467- do_set_cpu_speed(CPUFREQ_HIGH, 0);468468- return 0;469469-}470470-471471-static int pmac_cpufreq_resume(struct cpufreq_policy *policy)472472-{473473- /* If we resume, first check if we have a get() function */474474- if (get_speed_proc)475475- cur_freq = get_speed_proc();476476- else477477- cur_freq = 0;478478-479479- /* We don't, hrm... we don't really know our speed here, best480480- * is that we force a switch to whatever it was, which is481481- * probably high speed due to our suspend() routine482482- */483483- do_set_cpu_speed(sleep_freq == low_freq ?484484- CPUFREQ_LOW : CPUFREQ_HIGH, 0);485485-486486- no_schedule = 0;487487- return 0;488488-}489489-490490-static struct cpufreq_driver pmac_cpufreq_driver = {491491- .verify = pmac_cpufreq_verify,492492- .target = pmac_cpufreq_target,493493- .get = pmac_cpufreq_get_speed,494494- .init = pmac_cpufreq_cpu_init,495495- .suspend = pmac_cpufreq_suspend,496496- .resume = pmac_cpufreq_resume,497497- .flags = CPUFREQ_PM_NO_WARN,498498- .attr = pmac_cpu_freqs_attr,499499- .name = "powermac",500500- .owner = THIS_MODULE,501501-};502502-503503-504504-static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode)505505-{506506- struct device_node *volt_gpio_np = of_find_node_by_name(NULL,507507- "voltage-gpio");508508- struct device_node *freq_gpio_np = of_find_node_by_name(NULL,509509- "frequency-gpio");510510- struct device_node *slew_done_gpio_np = of_find_node_by_name(NULL,511511- "slewing-done");512512- u32 *value;513513-514514- /*515515- * Check to see if it's GPIO driven or PMU only516516- *517517- * The way we extract the GPIO address is slightly hackish, but it518518- * works well enough for now. We need to abstract the whole GPIO519519- * stuff sooner or later anyway520520- */521521-522522- if (volt_gpio_np)523523- voltage_gpio = read_gpio(volt_gpio_np);524524- if (freq_gpio_np)525525- frequency_gpio = read_gpio(freq_gpio_np);526526- if (slew_done_gpio_np)527527- slew_done_gpio = read_gpio(slew_done_gpio_np);528528-529529- /* If we use the frequency GPIOs, calculate the min/max speeds based530530- * on the bus frequencies531531- */532532- if (frequency_gpio && slew_done_gpio) {533533- int lenp, rc;534534- u32 *freqs, *ratio;535535-536536- freqs = (u32 *)get_property(cpunode, "bus-frequencies", &lenp);537537- lenp /= sizeof(u32);538538- if (freqs == NULL || lenp != 2) {539539- printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n");540540- return 1;541541- }542542- ratio = (u32 *)get_property(cpunode, "processor-to-bus-ratio*2", NULL);543543- if (ratio == NULL) {544544- printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n");545545- return 1;546546- }547547-548548- /* Get the min/max bus frequencies */549549- low_freq = min(freqs[0], freqs[1]);550550- hi_freq = max(freqs[0], freqs[1]);551551-552552- /* Grrrr.. It _seems_ that the device-tree is lying on the low bus553553- * frequency, it claims it to be around 84Mhz on some models while554554- * it appears to be approx. 101Mhz on all. Let's hack around here...555555- * fortunately, we don't need to be too precise556556- */557557- if (low_freq < 98000000)558558- low_freq = 101000000;559559-560560- /* Convert those to CPU core clocks */561561- low_freq = (low_freq * (*ratio)) / 2000;562562- hi_freq = (hi_freq * (*ratio)) / 2000;563563-564564- /* Now we get the frequencies, we read the GPIO to see what is out current565565- * speed566566- */567567- rc = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0);568568- cur_freq = (rc & 0x01) ? hi_freq : low_freq;569569-570570- set_speed_proc = gpios_set_cpu_speed;571571- return 1;572572- }573573-574574- /* If we use the PMU, look for the min & max frequencies in the575575- * device-tree576576- */577577- value = (u32 *)get_property(cpunode, "min-clock-frequency", NULL);578578- if (!value)579579- return 1;580580- low_freq = (*value) / 1000;581581- /* The PowerBook G4 12" (PowerBook6,1) has an error in the device-tree582582- * here */583583- if (low_freq < 100000)584584- low_freq *= 10;585585-586586- value = (u32 *)get_property(cpunode, "max-clock-frequency", NULL);587587- if (!value)588588- return 1;589589- hi_freq = (*value) / 1000;590590- set_speed_proc = pmu_set_cpu_speed;591591- is_pmu_based = 1;592592-593593- return 0;594594-}595595-596596-static int pmac_cpufreq_init_7447A(struct device_node *cpunode)597597-{598598- struct device_node *volt_gpio_np;599599-600600- if (get_property(cpunode, "dynamic-power-step", NULL) == NULL)601601- return 1;602602-603603- volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select");604604- if (volt_gpio_np)605605- voltage_gpio = read_gpio(volt_gpio_np);606606- if (!voltage_gpio){607607- printk(KERN_ERR "cpufreq: missing cpu-vcore-select gpio\n");608608- return 1;609609- }610610-611611- /* OF only reports the high frequency */612612- hi_freq = cur_freq;613613- low_freq = cur_freq/2;614614-615615- /* Read actual frequency from CPU */616616- cur_freq = dfs_get_cpu_speed();617617- set_speed_proc = dfs_set_cpu_speed;618618- get_speed_proc = dfs_get_cpu_speed;619619-620620- return 0;621621-}622622-623623-static int pmac_cpufreq_init_750FX(struct device_node *cpunode)624624-{625625- struct device_node *volt_gpio_np;626626- u32 pvr, *value;627627-628628- if (get_property(cpunode, "dynamic-power-step", NULL) == NULL)629629- return 1;630630-631631- hi_freq = cur_freq;632632- value = (u32 *)get_property(cpunode, "reduced-clock-frequency", NULL);633633- if (!value)634634- return 1;635635- low_freq = (*value) / 1000;636636-637637- volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select");638638- if (volt_gpio_np)639639- voltage_gpio = read_gpio(volt_gpio_np);640640-641641- pvr = mfspr(SPRN_PVR);642642- has_cpu_l2lve = !((pvr & 0xf00) == 0x100);643643-644644- set_speed_proc = cpu_750fx_cpu_speed;645645- get_speed_proc = cpu_750fx_get_cpu_speed;646646- cur_freq = cpu_750fx_get_cpu_speed();647647-648648- return 0;649649-}650650-651651-/* Currently, we support the following machines:652652- *653653- * - Titanium PowerBook 1Ghz (PMU based, 667Mhz & 1Ghz)654654- * - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz)655655- * - Titanium PowerBook 400 (PMU based, 300Mhz & 400Mhz)656656- * - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz)657657- * - iBook2 500/600 (PMU based, 400Mhz & 500/600Mhz)658658- * - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage)659659- * - Recent MacRISC3 laptops660660- * - All new machines with 7447A CPUs661661- */662662-static int __init pmac_cpufreq_setup(void)663663-{664664- struct device_node *cpunode;665665- u32 *value;666666-667667- if (strstr(cmd_line, "nocpufreq"))668668- return 0;669669-670670- /* Assume only one CPU */671671- cpunode = find_type_devices("cpu");672672- if (!cpunode)673673- goto out;674674-675675- /* Get current cpu clock freq */676676- value = (u32 *)get_property(cpunode, "clock-frequency", NULL);677677- if (!value)678678- goto out;679679- cur_freq = (*value) / 1000;680680-681681- /* Check for 7447A based MacRISC3 */682682- if (machine_is_compatible("MacRISC3") &&683683- get_property(cpunode, "dynamic-power-step", NULL) &&684684- PVR_VER(mfspr(SPRN_PVR)) == 0x8003) {685685- pmac_cpufreq_init_7447A(cpunode);686686- /* Check for other MacRISC3 machines */687687- } else if (machine_is_compatible("PowerBook3,4") ||688688- machine_is_compatible("PowerBook3,5") ||689689- machine_is_compatible("MacRISC3")) {690690- pmac_cpufreq_init_MacRISC3(cpunode);691691- /* Else check for iBook2 500/600 */692692- } else if (machine_is_compatible("PowerBook4,1")) {693693- hi_freq = cur_freq;694694- low_freq = 400000;695695- set_speed_proc = pmu_set_cpu_speed;696696- is_pmu_based = 1;697697- }698698- /* Else check for TiPb 550 */699699- else if (machine_is_compatible("PowerBook3,3") && cur_freq == 550000) {700700- hi_freq = cur_freq;701701- low_freq = 500000;702702- set_speed_proc = pmu_set_cpu_speed;703703- is_pmu_based = 1;704704- }705705- /* Else check for TiPb 400 & 500 */706706- else if (machine_is_compatible("PowerBook3,2")) {707707- /* We only know about the 400 MHz and the 500Mhz model708708- * they both have 300 MHz as low frequency709709- */710710- if (cur_freq < 350000 || cur_freq > 550000)711711- goto out;712712- hi_freq = cur_freq;713713- low_freq = 300000;714714- set_speed_proc = pmu_set_cpu_speed;715715- is_pmu_based = 1;716716- }717717- /* Else check for 750FX */718718- else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000)719719- pmac_cpufreq_init_750FX(cpunode);720720-out:721721- if (set_speed_proc == NULL)722722- return -ENODEV;723723-724724- pmac_cpu_freqs[CPUFREQ_LOW].frequency = low_freq;725725- pmac_cpu_freqs[CPUFREQ_HIGH].frequency = hi_freq;726726-727727- printk(KERN_INFO "Registering PowerMac CPU frequency driver\n");728728- printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n",729729- low_freq/1000, hi_freq/1000, cur_freq/1000);730730-731731- return cpufreq_register_driver(&pmac_cpufreq_driver);732732-}733733-734734-module_init(pmac_cpufreq_setup);735735-
-3023
arch/ppc/platforms/pmac_feature.c
···11-/*22- * arch/ppc/platforms/pmac_feature.c33- *44- * Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au)55- * Ben. Herrenschmidt (benh@kernel.crashing.org)66- *77- * This program is free software; you can redistribute it and/or88- * modify it under the terms of the GNU General Public License99- * as published by the Free Software Foundation; either version1010- * 2 of the License, or (at your option) any later version.1111- *1212- * TODO:1313- *1414- * - Replace mdelay with some schedule loop if possible1515- * - Shorten some obfuscated delays on some routines (like modem1616- * power)1717- * - Refcount some clocks (see darwin)1818- * - Split split split...1919- *2020- */2121-#include <linux/config.h>2222-#include <linux/types.h>2323-#include <linux/init.h>2424-#include <linux/delay.h>2525-#include <linux/kernel.h>2626-#include <linux/sched.h>2727-#include <linux/spinlock.h>2828-#include <linux/adb.h>2929-#include <linux/pmu.h>3030-#include <linux/ioport.h>3131-#include <linux/pci.h>3232-#include <asm/sections.h>3333-#include <asm/errno.h>3434-#include <asm/ohare.h>3535-#include <asm/heathrow.h>3636-#include <asm/keylargo.h>3737-#include <asm/uninorth.h>3838-#include <asm/io.h>3939-#include <asm/prom.h>4040-#include <asm/machdep.h>4141-#include <asm/pmac_feature.h>4242-#include <asm/dbdma.h>4343-#include <asm/pci-bridge.h>4444-#include <asm/pmac_low_i2c.h>4545-4646-#undef DEBUG_FEATURE4747-4848-#ifdef DEBUG_FEATURE4949-#define DBG(fmt,...) printk(KERN_DEBUG fmt)5050-#else5151-#define DBG(fmt,...)5252-#endif5353-5454-#ifdef CONFIG_6xx5555-extern int powersave_lowspeed;5656-#endif5757-5858-extern int powersave_nap;5959-extern struct device_node *k2_skiplist[2];6060-6161-6262-/*6363- * We use a single global lock to protect accesses. Each driver has6464- * to take care of its own locking6565- */6666-static DEFINE_SPINLOCK(feature_lock);6767-6868-#define LOCK(flags) spin_lock_irqsave(&feature_lock, flags);6969-#define UNLOCK(flags) spin_unlock_irqrestore(&feature_lock, flags);7070-7171-7272-/*7373- * Instance of some macio stuffs7474- */7575-struct macio_chip macio_chips[MAX_MACIO_CHIPS];7676-7777-struct macio_chip* macio_find(struct device_node* child, int type)7878-{7979- while(child) {8080- int i;8181-8282- for (i=0; i < MAX_MACIO_CHIPS && macio_chips[i].of_node; i++)8383- if (child == macio_chips[i].of_node &&8484- (!type || macio_chips[i].type == type))8585- return &macio_chips[i];8686- child = child->parent;8787- }8888- return NULL;8989-}9090-EXPORT_SYMBOL_GPL(macio_find);9191-9292-static const char* macio_names[] =9393-{9494- "Unknown",9595- "Grand Central",9696- "OHare",9797- "OHareII",9898- "Heathrow",9999- "Gatwick",100100- "Paddington",101101- "Keylargo",102102- "Pangea",103103- "Intrepid",104104- "K2"105105-};106106-107107-108108-109109-/*110110- * Uninorth reg. access. Note that Uni-N regs are big endian111111- */112112-113113-#define UN_REG(r) (uninorth_base + ((r) >> 2))114114-#define UN_IN(r) (in_be32(UN_REG(r)))115115-#define UN_OUT(r,v) (out_be32(UN_REG(r), (v)))116116-#define UN_BIS(r,v) (UN_OUT((r), UN_IN(r) | (v)))117117-#define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v)))118118-119119-static struct device_node* uninorth_node;120120-static u32 __iomem * uninorth_base;121121-static u32 uninorth_rev;122122-static int uninorth_u3;123123-static void __iomem *u3_ht;124124-125125-/*126126- * For each motherboard family, we have a table of functions pointers127127- * that handle the various features.128128- */129129-130130-typedef long (*feature_call)(struct device_node* node, long param, long value);131131-132132-struct feature_table_entry {133133- unsigned int selector;134134- feature_call function;135135-};136136-137137-struct pmac_mb_def138138-{139139- const char* model_string;140140- const char* model_name;141141- int model_id;142142- struct feature_table_entry* features;143143- unsigned long board_flags;144144-};145145-static struct pmac_mb_def pmac_mb;146146-147147-/*148148- * Here are the chip specific feature functions149149- */150150-151151-static inline int152152-simple_feature_tweak(struct device_node* node, int type, int reg, u32 mask, int value)153153-{154154- struct macio_chip* macio;155155- unsigned long flags;156156-157157- macio = macio_find(node, type);158158- if (!macio)159159- return -ENODEV;160160- LOCK(flags);161161- if (value)162162- MACIO_BIS(reg, mask);163163- else164164- MACIO_BIC(reg, mask);165165- (void)MACIO_IN32(reg);166166- UNLOCK(flags);167167-168168- return 0;169169-}170170-171171-#ifndef CONFIG_POWER4172172-173173-static long174174-ohare_htw_scc_enable(struct device_node* node, long param, long value)175175-{176176- struct macio_chip* macio;177177- unsigned long chan_mask;178178- unsigned long fcr;179179- unsigned long flags;180180- int htw, trans;181181- unsigned long rmask;182182-183183- macio = macio_find(node, 0);184184- if (!macio)185185- return -ENODEV;186186- if (!strcmp(node->name, "ch-a"))187187- chan_mask = MACIO_FLAG_SCCA_ON;188188- else if (!strcmp(node->name, "ch-b"))189189- chan_mask = MACIO_FLAG_SCCB_ON;190190- else191191- return -ENODEV;192192-193193- htw = (macio->type == macio_heathrow || macio->type == macio_paddington194194- || macio->type == macio_gatwick);195195- /* On these machines, the HRW_SCC_TRANS_EN_N bit mustn't be touched */196196- trans = (pmac_mb.model_id != PMAC_TYPE_YOSEMITE &&197197- pmac_mb.model_id != PMAC_TYPE_YIKES);198198- if (value) {199199-#ifdef CONFIG_ADB_PMU200200- if ((param & 0xfff) == PMAC_SCC_IRDA)201201- pmu_enable_irled(1);202202-#endif /* CONFIG_ADB_PMU */203203- LOCK(flags);204204- fcr = MACIO_IN32(OHARE_FCR);205205- /* Check if scc cell need enabling */206206- if (!(fcr & OH_SCC_ENABLE)) {207207- fcr |= OH_SCC_ENABLE;208208- if (htw) {209209- /* Side effect: this will also power up the210210- * modem, but it's too messy to figure out on which211211- * ports this controls the tranceiver and on which212212- * it controls the modem213213- */214214- if (trans)215215- fcr &= ~HRW_SCC_TRANS_EN_N;216216- MACIO_OUT32(OHARE_FCR, fcr);217217- fcr |= (rmask = HRW_RESET_SCC);218218- MACIO_OUT32(OHARE_FCR, fcr);219219- } else {220220- fcr |= (rmask = OH_SCC_RESET);221221- MACIO_OUT32(OHARE_FCR, fcr);222222- }223223- UNLOCK(flags);224224- (void)MACIO_IN32(OHARE_FCR);225225- mdelay(15);226226- LOCK(flags);227227- fcr &= ~rmask;228228- MACIO_OUT32(OHARE_FCR, fcr);229229- }230230- if (chan_mask & MACIO_FLAG_SCCA_ON)231231- fcr |= OH_SCCA_IO;232232- if (chan_mask & MACIO_FLAG_SCCB_ON)233233- fcr |= OH_SCCB_IO;234234- MACIO_OUT32(OHARE_FCR, fcr);235235- macio->flags |= chan_mask;236236- UNLOCK(flags);237237- if (param & PMAC_SCC_FLAG_XMON)238238- macio->flags |= MACIO_FLAG_SCC_LOCKED;239239- } else {240240- if (macio->flags & MACIO_FLAG_SCC_LOCKED)241241- return -EPERM;242242- LOCK(flags);243243- fcr = MACIO_IN32(OHARE_FCR);244244- if (chan_mask & MACIO_FLAG_SCCA_ON)245245- fcr &= ~OH_SCCA_IO;246246- if (chan_mask & MACIO_FLAG_SCCB_ON)247247- fcr &= ~OH_SCCB_IO;248248- MACIO_OUT32(OHARE_FCR, fcr);249249- if ((fcr & (OH_SCCA_IO | OH_SCCB_IO)) == 0) {250250- fcr &= ~OH_SCC_ENABLE;251251- if (htw && trans)252252- fcr |= HRW_SCC_TRANS_EN_N;253253- MACIO_OUT32(OHARE_FCR, fcr);254254- }255255- macio->flags &= ~(chan_mask);256256- UNLOCK(flags);257257- mdelay(10);258258-#ifdef CONFIG_ADB_PMU259259- if ((param & 0xfff) == PMAC_SCC_IRDA)260260- pmu_enable_irled(0);261261-#endif /* CONFIG_ADB_PMU */262262- }263263- return 0;264264-}265265-266266-static long267267-ohare_floppy_enable(struct device_node* node, long param, long value)268268-{269269- return simple_feature_tweak(node, macio_ohare,270270- OHARE_FCR, OH_FLOPPY_ENABLE, value);271271-}272272-273273-static long274274-ohare_mesh_enable(struct device_node* node, long param, long value)275275-{276276- return simple_feature_tweak(node, macio_ohare,277277- OHARE_FCR, OH_MESH_ENABLE, value);278278-}279279-280280-static long281281-ohare_ide_enable(struct device_node* node, long param, long value)282282-{283283- switch(param) {284284- case 0:285285- /* For some reason, setting the bit in set_initial_features()286286- * doesn't stick. I'm still investigating... --BenH.287287- */288288- if (value)289289- simple_feature_tweak(node, macio_ohare,290290- OHARE_FCR, OH_IOBUS_ENABLE, 1);291291- return simple_feature_tweak(node, macio_ohare,292292- OHARE_FCR, OH_IDE0_ENABLE, value);293293- case 1:294294- return simple_feature_tweak(node, macio_ohare,295295- OHARE_FCR, OH_BAY_IDE_ENABLE, value);296296- default:297297- return -ENODEV;298298- }299299-}300300-301301-static long302302-ohare_ide_reset(struct device_node* node, long param, long value)303303-{304304- switch(param) {305305- case 0:306306- return simple_feature_tweak(node, macio_ohare,307307- OHARE_FCR, OH_IDE0_RESET_N, !value);308308- case 1:309309- return simple_feature_tweak(node, macio_ohare,310310- OHARE_FCR, OH_IDE1_RESET_N, !value);311311- default:312312- return -ENODEV;313313- }314314-}315315-316316-static long317317-ohare_sleep_state(struct device_node* node, long param, long value)318318-{319319- struct macio_chip* macio = &macio_chips[0];320320-321321- if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)322322- return -EPERM;323323- if (value == 1) {324324- MACIO_BIC(OHARE_FCR, OH_IOBUS_ENABLE);325325- } else if (value == 0) {326326- MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);327327- }328328-329329- return 0;330330-}331331-332332-static long333333-heathrow_modem_enable(struct device_node* node, long param, long value)334334-{335335- struct macio_chip* macio;336336- u8 gpio;337337- unsigned long flags;338338-339339- macio = macio_find(node, macio_unknown);340340- if (!macio)341341- return -ENODEV;342342- gpio = MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1;343343- if (!value) {344344- LOCK(flags);345345- MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio);346346- UNLOCK(flags);347347- (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);348348- mdelay(250);349349- }350350- if (pmac_mb.model_id != PMAC_TYPE_YOSEMITE &&351351- pmac_mb.model_id != PMAC_TYPE_YIKES) {352352- LOCK(flags);353353- if (value)354354- MACIO_BIC(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);355355- else356356- MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);357357- UNLOCK(flags);358358- (void)MACIO_IN32(HEATHROW_FCR);359359- mdelay(250);360360- }361361- if (value) {362362- LOCK(flags);363363- MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);364364- (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);365365- UNLOCK(flags); mdelay(250); LOCK(flags);366366- MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio);367367- (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);368368- UNLOCK(flags); mdelay(250); LOCK(flags);369369- MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);370370- (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);371371- UNLOCK(flags); mdelay(250);372372- }373373- return 0;374374-}375375-376376-static long377377-heathrow_floppy_enable(struct device_node* node, long param, long value)378378-{379379- return simple_feature_tweak(node, macio_unknown,380380- HEATHROW_FCR,381381- HRW_SWIM_ENABLE|HRW_BAY_FLOPPY_ENABLE,382382- value);383383-}384384-385385-static long386386-heathrow_mesh_enable(struct device_node* node, long param, long value)387387-{388388- struct macio_chip* macio;389389- unsigned long flags;390390-391391- macio = macio_find(node, macio_unknown);392392- if (!macio)393393- return -ENODEV;394394- LOCK(flags);395395- /* Set clear mesh cell enable */396396- if (value)397397- MACIO_BIS(HEATHROW_FCR, HRW_MESH_ENABLE);398398- else399399- MACIO_BIC(HEATHROW_FCR, HRW_MESH_ENABLE);400400- (void)MACIO_IN32(HEATHROW_FCR);401401- udelay(10);402402- /* Set/Clear termination power */403403- if (value)404404- MACIO_BIC(HEATHROW_MBCR, 0x04000000);405405- else406406- MACIO_BIS(HEATHROW_MBCR, 0x04000000);407407- (void)MACIO_IN32(HEATHROW_MBCR);408408- udelay(10);409409- UNLOCK(flags);410410-411411- return 0;412412-}413413-414414-static long415415-heathrow_ide_enable(struct device_node* node, long param, long value)416416-{417417- switch(param) {418418- case 0:419419- return simple_feature_tweak(node, macio_unknown,420420- HEATHROW_FCR, HRW_IDE0_ENABLE, value);421421- case 1:422422- return simple_feature_tweak(node, macio_unknown,423423- HEATHROW_FCR, HRW_BAY_IDE_ENABLE, value);424424- default:425425- return -ENODEV;426426- }427427-}428428-429429-static long430430-heathrow_ide_reset(struct device_node* node, long param, long value)431431-{432432- switch(param) {433433- case 0:434434- return simple_feature_tweak(node, macio_unknown,435435- HEATHROW_FCR, HRW_IDE0_RESET_N, !value);436436- case 1:437437- return simple_feature_tweak(node, macio_unknown,438438- HEATHROW_FCR, HRW_IDE1_RESET_N, !value);439439- default:440440- return -ENODEV;441441- }442442-}443443-444444-static long445445-heathrow_bmac_enable(struct device_node* node, long param, long value)446446-{447447- struct macio_chip* macio;448448- unsigned long flags;449449-450450- macio = macio_find(node, 0);451451- if (!macio)452452- return -ENODEV;453453- if (value) {454454- LOCK(flags);455455- MACIO_BIS(HEATHROW_FCR, HRW_BMAC_IO_ENABLE);456456- MACIO_BIS(HEATHROW_FCR, HRW_BMAC_RESET);457457- UNLOCK(flags);458458- (void)MACIO_IN32(HEATHROW_FCR);459459- mdelay(10);460460- LOCK(flags);461461- MACIO_BIC(HEATHROW_FCR, HRW_BMAC_RESET);462462- UNLOCK(flags);463463- (void)MACIO_IN32(HEATHROW_FCR);464464- mdelay(10);465465- } else {466466- LOCK(flags);467467- MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE);468468- UNLOCK(flags);469469- }470470- return 0;471471-}472472-473473-static long474474-heathrow_sound_enable(struct device_node* node, long param, long value)475475-{476476- struct macio_chip* macio;477477- unsigned long flags;478478-479479- /* B&W G3 and Yikes don't support that properly (the480480- * sound appear to never come back after beeing shut down).481481- */482482- if (pmac_mb.model_id == PMAC_TYPE_YOSEMITE ||483483- pmac_mb.model_id == PMAC_TYPE_YIKES)484484- return 0;485485-486486- macio = macio_find(node, 0);487487- if (!macio)488488- return -ENODEV;489489- if (value) {490490- LOCK(flags);491491- MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);492492- MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);493493- UNLOCK(flags);494494- (void)MACIO_IN32(HEATHROW_FCR);495495- } else {496496- LOCK(flags);497497- MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N);498498- MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);499499- UNLOCK(flags);500500- }501501- return 0;502502-}503503-504504-static u32 save_fcr[6];505505-static u32 save_mbcr;506506-static u32 save_gpio_levels[2];507507-static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT];508508-static u8 save_gpio_normal[KEYLARGO_GPIO_CNT];509509-static u32 save_unin_clock_ctl;510510-static struct dbdma_regs save_dbdma[13];511511-static struct dbdma_regs save_alt_dbdma[13];512512-513513-static void514514-dbdma_save(struct macio_chip* macio, struct dbdma_regs* save)515515-{516516- int i;517517-518518- /* Save state & config of DBDMA channels */519519- for (i=0; i<13; i++) {520520- volatile struct dbdma_regs __iomem * chan = (void __iomem *)521521- (macio->base + ((0x8000+i*0x100)>>2));522522- save[i].cmdptr_hi = in_le32(&chan->cmdptr_hi);523523- save[i].cmdptr = in_le32(&chan->cmdptr);524524- save[i].intr_sel = in_le32(&chan->intr_sel);525525- save[i].br_sel = in_le32(&chan->br_sel);526526- save[i].wait_sel = in_le32(&chan->wait_sel);527527- }528528-}529529-530530-static void531531-dbdma_restore(struct macio_chip* macio, struct dbdma_regs* save)532532-{533533- int i;534534-535535- /* Save state & config of DBDMA channels */536536- for (i=0; i<13; i++) {537537- volatile struct dbdma_regs __iomem * chan = (void __iomem *)538538- (macio->base + ((0x8000+i*0x100)>>2));539539- out_le32(&chan->control, (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16);540540- while (in_le32(&chan->status) & ACTIVE)541541- mb();542542- out_le32(&chan->cmdptr_hi, save[i].cmdptr_hi);543543- out_le32(&chan->cmdptr, save[i].cmdptr);544544- out_le32(&chan->intr_sel, save[i].intr_sel);545545- out_le32(&chan->br_sel, save[i].br_sel);546546- out_le32(&chan->wait_sel, save[i].wait_sel);547547- }548548-}549549-550550-static void551551-heathrow_sleep(struct macio_chip* macio, int secondary)552552-{553553- if (secondary) {554554- dbdma_save(macio, save_alt_dbdma);555555- save_fcr[2] = MACIO_IN32(0x38);556556- save_fcr[3] = MACIO_IN32(0x3c);557557- } else {558558- dbdma_save(macio, save_dbdma);559559- save_fcr[0] = MACIO_IN32(0x38);560560- save_fcr[1] = MACIO_IN32(0x3c);561561- save_mbcr = MACIO_IN32(0x34);562562- /* Make sure sound is shut down */563563- MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N);564564- MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);565565- /* This seems to be necessary as well or the fan566566- * keeps coming up and battery drains fast */567567- MACIO_BIC(HEATHROW_FCR, HRW_IOBUS_ENABLE);568568- MACIO_BIC(HEATHROW_FCR, HRW_IDE0_RESET_N);569569- /* Make sure eth is down even if module or sleep570570- * won't work properly */571571- MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE | HRW_BMAC_RESET);572572- }573573- /* Make sure modem is shut down */574574- MACIO_OUT8(HRW_GPIO_MODEM_RESET,575575- MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1);576576- MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);577577- MACIO_BIC(HEATHROW_FCR, OH_SCCA_IO|OH_SCCB_IO|HRW_SCC_ENABLE);578578-579579- /* Let things settle */580580- (void)MACIO_IN32(HEATHROW_FCR);581581-}582582-583583-static void584584-heathrow_wakeup(struct macio_chip* macio, int secondary)585585-{586586- if (secondary) {587587- MACIO_OUT32(0x38, save_fcr[2]);588588- (void)MACIO_IN32(0x38);589589- mdelay(1);590590- MACIO_OUT32(0x3c, save_fcr[3]);591591- (void)MACIO_IN32(0x38);592592- mdelay(10);593593- dbdma_restore(macio, save_alt_dbdma);594594- } else {595595- MACIO_OUT32(0x38, save_fcr[0] | HRW_IOBUS_ENABLE);596596- (void)MACIO_IN32(0x38);597597- mdelay(1);598598- MACIO_OUT32(0x3c, save_fcr[1]);599599- (void)MACIO_IN32(0x38);600600- mdelay(1);601601- MACIO_OUT32(0x34, save_mbcr);602602- (void)MACIO_IN32(0x38);603603- mdelay(10);604604- dbdma_restore(macio, save_dbdma);605605- }606606-}607607-608608-static long609609-heathrow_sleep_state(struct device_node* node, long param, long value)610610-{611611- if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)612612- return -EPERM;613613- if (value == 1) {614614- if (macio_chips[1].type == macio_gatwick)615615- heathrow_sleep(&macio_chips[0], 1);616616- heathrow_sleep(&macio_chips[0], 0);617617- } else if (value == 0) {618618- heathrow_wakeup(&macio_chips[0], 0);619619- if (macio_chips[1].type == macio_gatwick)620620- heathrow_wakeup(&macio_chips[0], 1);621621- }622622- return 0;623623-}624624-625625-static long626626-core99_scc_enable(struct device_node* node, long param, long value)627627-{628628- struct macio_chip* macio;629629- unsigned long flags;630630- unsigned long chan_mask;631631- u32 fcr;632632-633633- macio = macio_find(node, 0);634634- if (!macio)635635- return -ENODEV;636636- if (!strcmp(node->name, "ch-a"))637637- chan_mask = MACIO_FLAG_SCCA_ON;638638- else if (!strcmp(node->name, "ch-b"))639639- chan_mask = MACIO_FLAG_SCCB_ON;640640- else641641- return -ENODEV;642642-643643- if (value) {644644- int need_reset_scc = 0;645645- int need_reset_irda = 0;646646-647647- LOCK(flags);648648- fcr = MACIO_IN32(KEYLARGO_FCR0);649649- /* Check if scc cell need enabling */650650- if (!(fcr & KL0_SCC_CELL_ENABLE)) {651651- fcr |= KL0_SCC_CELL_ENABLE;652652- need_reset_scc = 1;653653- }654654- if (chan_mask & MACIO_FLAG_SCCA_ON) {655655- fcr |= KL0_SCCA_ENABLE;656656- /* Don't enable line drivers for I2S modem */657657- if ((param & 0xfff) == PMAC_SCC_I2S1)658658- fcr &= ~KL0_SCC_A_INTF_ENABLE;659659- else660660- fcr |= KL0_SCC_A_INTF_ENABLE;661661- }662662- if (chan_mask & MACIO_FLAG_SCCB_ON) {663663- fcr |= KL0_SCCB_ENABLE;664664- /* Perform irda specific inits */665665- if ((param & 0xfff) == PMAC_SCC_IRDA) {666666- fcr &= ~KL0_SCC_B_INTF_ENABLE;667667- fcr |= KL0_IRDA_ENABLE;668668- fcr |= KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE;669669- fcr |= KL0_IRDA_SOURCE1_SEL;670670- fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0);671671- fcr &= ~(KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND);672672- need_reset_irda = 1;673673- } else674674- fcr |= KL0_SCC_B_INTF_ENABLE;675675- }676676- MACIO_OUT32(KEYLARGO_FCR0, fcr);677677- macio->flags |= chan_mask;678678- if (need_reset_scc) {679679- MACIO_BIS(KEYLARGO_FCR0, KL0_SCC_RESET);680680- (void)MACIO_IN32(KEYLARGO_FCR0);681681- UNLOCK(flags);682682- mdelay(15);683683- LOCK(flags);684684- MACIO_BIC(KEYLARGO_FCR0, KL0_SCC_RESET);685685- }686686- if (need_reset_irda) {687687- MACIO_BIS(KEYLARGO_FCR0, KL0_IRDA_RESET);688688- (void)MACIO_IN32(KEYLARGO_FCR0);689689- UNLOCK(flags);690690- mdelay(15);691691- LOCK(flags);692692- MACIO_BIC(KEYLARGO_FCR0, KL0_IRDA_RESET);693693- }694694- UNLOCK(flags);695695- if (param & PMAC_SCC_FLAG_XMON)696696- macio->flags |= MACIO_FLAG_SCC_LOCKED;697697- } else {698698- if (macio->flags & MACIO_FLAG_SCC_LOCKED)699699- return -EPERM;700700- LOCK(flags);701701- fcr = MACIO_IN32(KEYLARGO_FCR0);702702- if (chan_mask & MACIO_FLAG_SCCA_ON)703703- fcr &= ~KL0_SCCA_ENABLE;704704- if (chan_mask & MACIO_FLAG_SCCB_ON) {705705- fcr &= ~KL0_SCCB_ENABLE;706706- /* Perform irda specific clears */707707- if ((param & 0xfff) == PMAC_SCC_IRDA) {708708- fcr &= ~KL0_IRDA_ENABLE;709709- fcr &= ~(KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE);710710- fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0);711711- fcr &= ~(KL0_IRDA_SOURCE1_SEL|KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND);712712- }713713- }714714- MACIO_OUT32(KEYLARGO_FCR0, fcr);715715- if ((fcr & (KL0_SCCA_ENABLE | KL0_SCCB_ENABLE)) == 0) {716716- fcr &= ~KL0_SCC_CELL_ENABLE;717717- MACIO_OUT32(KEYLARGO_FCR0, fcr);718718- }719719- macio->flags &= ~(chan_mask);720720- UNLOCK(flags);721721- mdelay(10);722722- }723723- return 0;724724-}725725-726726-static long727727-core99_modem_enable(struct device_node* node, long param, long value)728728-{729729- struct macio_chip* macio;730730- u8 gpio;731731- unsigned long flags;732732-733733- /* Hack for internal USB modem */734734- if (node == NULL) {735735- if (macio_chips[0].type != macio_keylargo)736736- return -ENODEV;737737- node = macio_chips[0].of_node;738738- }739739- macio = macio_find(node, 0);740740- if (!macio)741741- return -ENODEV;742742- gpio = MACIO_IN8(KL_GPIO_MODEM_RESET);743743- gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE;744744- gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA;745745-746746- if (!value) {747747- LOCK(flags);748748- MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);749749- UNLOCK(flags);750750- (void)MACIO_IN8(KL_GPIO_MODEM_RESET);751751- mdelay(250);752752- }753753- LOCK(flags);754754- if (value) {755755- MACIO_BIC(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);756756- UNLOCK(flags);757757- (void)MACIO_IN32(KEYLARGO_FCR2);758758- mdelay(250);759759- } else {760760- MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);761761- UNLOCK(flags);762762- }763763- if (value) {764764- LOCK(flags);765765- MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);766766- (void)MACIO_IN8(KL_GPIO_MODEM_RESET);767767- UNLOCK(flags); mdelay(250); LOCK(flags);768768- MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);769769- (void)MACIO_IN8(KL_GPIO_MODEM_RESET);770770- UNLOCK(flags); mdelay(250); LOCK(flags);771771- MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);772772- (void)MACIO_IN8(KL_GPIO_MODEM_RESET);773773- UNLOCK(flags); mdelay(250);774774- }775775- return 0;776776-}777777-778778-static long779779-pangea_modem_enable(struct device_node* node, long param, long value)780780-{781781- struct macio_chip* macio;782782- u8 gpio;783783- unsigned long flags;784784-785785- /* Hack for internal USB modem */786786- if (node == NULL) {787787- if (macio_chips[0].type != macio_pangea &&788788- macio_chips[0].type != macio_intrepid)789789- return -ENODEV;790790- node = macio_chips[0].of_node;791791- }792792- macio = macio_find(node, 0);793793- if (!macio)794794- return -ENODEV;795795- gpio = MACIO_IN8(KL_GPIO_MODEM_RESET);796796- gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE;797797- gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA;798798-799799- if (!value) {800800- LOCK(flags);801801- MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);802802- UNLOCK(flags);803803- (void)MACIO_IN8(KL_GPIO_MODEM_RESET);804804- mdelay(250);805805- }806806- LOCK(flags);807807- if (value) {808808- MACIO_OUT8(KL_GPIO_MODEM_POWER,809809- KEYLARGO_GPIO_OUTPUT_ENABLE);810810- UNLOCK(flags);811811- (void)MACIO_IN32(KEYLARGO_FCR2);812812- mdelay(250);813813- } else {814814- MACIO_OUT8(KL_GPIO_MODEM_POWER,815815- KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);816816- UNLOCK(flags);817817- }818818- if (value) {819819- LOCK(flags);820820- MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);821821- (void)MACIO_IN8(KL_GPIO_MODEM_RESET);822822- UNLOCK(flags); mdelay(250); LOCK(flags);823823- MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);824824- (void)MACIO_IN8(KL_GPIO_MODEM_RESET);825825- UNLOCK(flags); mdelay(250); LOCK(flags);826826- MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);827827- (void)MACIO_IN8(KL_GPIO_MODEM_RESET);828828- UNLOCK(flags); mdelay(250);829829- }830830- return 0;831831-}832832-833833-static long834834-core99_ata100_enable(struct device_node* node, long value)835835-{836836- unsigned long flags;837837- struct pci_dev *pdev = NULL;838838- u8 pbus, pid;839839-840840- if (uninorth_rev < 0x24)841841- return -ENODEV;842842-843843- LOCK(flags);844844- if (value)845845- UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100);846846- else847847- UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100);848848- (void)UN_IN(UNI_N_CLOCK_CNTL);849849- UNLOCK(flags);850850- udelay(20);851851-852852- if (value) {853853- if (pci_device_from_OF_node(node, &pbus, &pid) == 0)854854- pdev = pci_find_slot(pbus, pid);855855- if (pdev == NULL)856856- return 0;857857- pci_enable_device(pdev);858858- pci_set_master(pdev);859859- }860860- return 0;861861-}862862-863863-static long864864-core99_ide_enable(struct device_node* node, long param, long value)865865-{866866- /* Bus ID 0 to 2 are KeyLargo based IDE, busID 3 is U2867867- * based ata-100868868- */869869- switch(param) {870870- case 0:871871- return simple_feature_tweak(node, macio_unknown,872872- KEYLARGO_FCR1, KL1_EIDE0_ENABLE, value);873873- case 1:874874- return simple_feature_tweak(node, macio_unknown,875875- KEYLARGO_FCR1, KL1_EIDE1_ENABLE, value);876876- case 2:877877- return simple_feature_tweak(node, macio_unknown,878878- KEYLARGO_FCR1, KL1_UIDE_ENABLE, value);879879- case 3:880880- return core99_ata100_enable(node, value);881881- default:882882- return -ENODEV;883883- }884884-}885885-886886-static long887887-core99_ide_reset(struct device_node* node, long param, long value)888888-{889889- switch(param) {890890- case 0:891891- return simple_feature_tweak(node, macio_unknown,892892- KEYLARGO_FCR1, KL1_EIDE0_RESET_N, !value);893893- case 1:894894- return simple_feature_tweak(node, macio_unknown,895895- KEYLARGO_FCR1, KL1_EIDE1_RESET_N, !value);896896- case 2:897897- return simple_feature_tweak(node, macio_unknown,898898- KEYLARGO_FCR1, KL1_UIDE_RESET_N, !value);899899- default:900900- return -ENODEV;901901- }902902-}903903-904904-static long905905-core99_gmac_enable(struct device_node* node, long param, long value)906906-{907907- unsigned long flags;908908-909909- LOCK(flags);910910- if (value)911911- UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);912912- else913913- UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);914914- (void)UN_IN(UNI_N_CLOCK_CNTL);915915- UNLOCK(flags);916916- udelay(20);917917-918918- return 0;919919-}920920-921921-static long922922-core99_gmac_phy_reset(struct device_node* node, long param, long value)923923-{924924- unsigned long flags;925925- struct macio_chip* macio;926926-927927- macio = &macio_chips[0];928928- if (macio->type != macio_keylargo && macio->type != macio_pangea &&929929- macio->type != macio_intrepid)930930- return -ENODEV;931931-932932- LOCK(flags);933933- MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE);934934- (void)MACIO_IN8(KL_GPIO_ETH_PHY_RESET);935935- UNLOCK(flags);936936- mdelay(10);937937- LOCK(flags);938938- MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, /*KEYLARGO_GPIO_OUTPUT_ENABLE | */939939- KEYLARGO_GPIO_OUTOUT_DATA);940940- UNLOCK(flags);941941- mdelay(10);942942-943943- return 0;944944-}945945-946946-static long947947-core99_sound_chip_enable(struct device_node* node, long param, long value)948948-{949949- struct macio_chip* macio;950950- unsigned long flags;951951-952952- macio = macio_find(node, 0);953953- if (!macio)954954- return -ENODEV;955955-956956- /* Do a better probe code, screamer G4 desktops &957957- * iMacs can do that too, add a recalibrate in958958- * the driver as well959959- */960960- if (pmac_mb.model_id == PMAC_TYPE_PISMO ||961961- pmac_mb.model_id == PMAC_TYPE_TITANIUM) {962962- LOCK(flags);963963- if (value)964964- MACIO_OUT8(KL_GPIO_SOUND_POWER,965965- KEYLARGO_GPIO_OUTPUT_ENABLE |966966- KEYLARGO_GPIO_OUTOUT_DATA);967967- else968968- MACIO_OUT8(KL_GPIO_SOUND_POWER,969969- KEYLARGO_GPIO_OUTPUT_ENABLE);970970- (void)MACIO_IN8(KL_GPIO_SOUND_POWER);971971- UNLOCK(flags);972972- }973973- return 0;974974-}975975-976976-static long977977-core99_airport_enable(struct device_node* node, long param, long value)978978-{979979- struct macio_chip* macio;980980- unsigned long flags;981981- int state;982982-983983- macio = macio_find(node, 0);984984- if (!macio)985985- return -ENODEV;986986-987987- /* Hint: we allow passing of macio itself for the sake of the988988- * sleep code989989- */990990- if (node != macio->of_node &&991991- (!node->parent || node->parent != macio->of_node))992992- return -ENODEV;993993- state = (macio->flags & MACIO_FLAG_AIRPORT_ON) != 0;994994- if (value == state)995995- return 0;996996- if (value) {997997- /* This code is a reproduction of OF enable-cardslot998998- * and init-wireless methods, slightly hacked until999999- * I got it working.10001000- */10011001- LOCK(flags);10021002- MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 5);10031003- (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf);10041004- UNLOCK(flags);10051005- mdelay(10);10061006- LOCK(flags);10071007- MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 4);10081008- (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf);10091009- UNLOCK(flags);10101010-10111011- mdelay(10);10121012-10131013- LOCK(flags);10141014- MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16);10151015- (void)MACIO_IN32(KEYLARGO_FCR2);10161016- udelay(10);10171017- MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xb, 0);10181018- (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xb);10191019- udelay(10);10201020- MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xa, 0x28);10211021- (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xa);10221022- udelay(10);10231023- MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xd, 0x28);10241024- (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xd);10251025- udelay(10);10261026- MACIO_OUT8(KEYLARGO_GPIO_0+0xd, 0x28);10271027- (void)MACIO_IN8(KEYLARGO_GPIO_0+0xd);10281028- udelay(10);10291029- MACIO_OUT8(KEYLARGO_GPIO_0+0xe, 0x28);10301030- (void)MACIO_IN8(KEYLARGO_GPIO_0+0xe);10311031- UNLOCK(flags);10321032- udelay(10);10331033- MACIO_OUT32(0x1c000, 0);10341034- mdelay(1);10351035- MACIO_OUT8(0x1a3e0, 0x41);10361036- (void)MACIO_IN8(0x1a3e0);10371037- udelay(10);10381038- LOCK(flags);10391039- MACIO_BIS(KEYLARGO_FCR2, KL2_CARDSEL_16);10401040- (void)MACIO_IN32(KEYLARGO_FCR2);10411041- UNLOCK(flags);10421042- mdelay(100);10431043-10441044- macio->flags |= MACIO_FLAG_AIRPORT_ON;10451045- } else {10461046- LOCK(flags);10471047- MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16);10481048- (void)MACIO_IN32(KEYLARGO_FCR2);10491049- MACIO_OUT8(KL_GPIO_AIRPORT_0, 0);10501050- MACIO_OUT8(KL_GPIO_AIRPORT_1, 0);10511051- MACIO_OUT8(KL_GPIO_AIRPORT_2, 0);10521052- MACIO_OUT8(KL_GPIO_AIRPORT_3, 0);10531053- MACIO_OUT8(KL_GPIO_AIRPORT_4, 0);10541054- (void)MACIO_IN8(KL_GPIO_AIRPORT_4);10551055- UNLOCK(flags);10561056-10571057- macio->flags &= ~MACIO_FLAG_AIRPORT_ON;10581058- }10591059- return 0;10601060-}10611061-10621062-#ifdef CONFIG_SMP10631063-static long10641064-core99_reset_cpu(struct device_node* node, long param, long value)10651065-{10661066- unsigned int reset_io = 0;10671067- unsigned long flags;10681068- struct macio_chip* macio;10691069- struct device_node* np;10701070- const int dflt_reset_lines[] = { KL_GPIO_RESET_CPU0,10711071- KL_GPIO_RESET_CPU1,10721072- KL_GPIO_RESET_CPU2,10731073- KL_GPIO_RESET_CPU3 };10741074-10751075- macio = &macio_chips[0];10761076- if (macio->type != macio_keylargo)10771077- return -ENODEV;10781078-10791079- np = find_path_device("/cpus");10801080- if (np == NULL)10811081- return -ENODEV;10821082- for (np = np->child; np != NULL; np = np->sibling) {10831083- u32* num = (u32 *)get_property(np, "reg", NULL);10841084- u32* rst = (u32 *)get_property(np, "soft-reset", NULL);10851085- if (num == NULL || rst == NULL)10861086- continue;10871087- if (param == *num) {10881088- reset_io = *rst;10891089- break;10901090- }10911091- }10921092- if (np == NULL || reset_io == 0)10931093- reset_io = dflt_reset_lines[param];10941094-10951095- LOCK(flags);10961096- MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);10971097- (void)MACIO_IN8(reset_io);10981098- udelay(1);10991099- MACIO_OUT8(reset_io, 0);11001100- (void)MACIO_IN8(reset_io);11011101- UNLOCK(flags);11021102-11031103- return 0;11041104-}11051105-#endif /* CONFIG_SMP */11061106-11071107-static long11081108-core99_usb_enable(struct device_node* node, long param, long value)11091109-{11101110- struct macio_chip* macio;11111111- unsigned long flags;11121112- char* prop;11131113- int number;11141114- u32 reg;11151115-11161116- macio = &macio_chips[0];11171117- if (macio->type != macio_keylargo && macio->type != macio_pangea &&11181118- macio->type != macio_intrepid)11191119- return -ENODEV;11201120-11211121- prop = (char *)get_property(node, "AAPL,clock-id", NULL);11221122- if (!prop)11231123- return -ENODEV;11241124- if (strncmp(prop, "usb0u048", 8) == 0)11251125- number = 0;11261126- else if (strncmp(prop, "usb1u148", 8) == 0)11271127- number = 2;11281128- else if (strncmp(prop, "usb2u248", 8) == 0)11291129- number = 4;11301130- else11311131- return -ENODEV;11321132-11331133- /* Sorry for the brute-force locking, but this is only used during11341134- * sleep and the timing seem to be critical11351135- */11361136- LOCK(flags);11371137- if (value) {11381138- /* Turn ON */11391139- if (number == 0) {11401140- MACIO_BIC(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));11411141- (void)MACIO_IN32(KEYLARGO_FCR0);11421142- UNLOCK(flags);11431143- mdelay(1);11441144- LOCK(flags);11451145- MACIO_BIS(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);11461146- } else if (number == 2) {11471147- MACIO_BIC(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));11481148- UNLOCK(flags);11491149- (void)MACIO_IN32(KEYLARGO_FCR0);11501150- mdelay(1);11511151- LOCK(flags);11521152- MACIO_BIS(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);11531153- } else if (number == 4) {11541154- MACIO_BIC(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1));11551155- UNLOCK(flags);11561156- (void)MACIO_IN32(KEYLARGO_FCR1);11571157- mdelay(1);11581158- LOCK(flags);11591159- MACIO_BIS(KEYLARGO_FCR1, KL1_USB2_CELL_ENABLE);11601160- }11611161- if (number < 4) {11621162- reg = MACIO_IN32(KEYLARGO_FCR4);11631163- reg &= ~(KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) |11641164- KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number));11651165- reg &= ~(KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) |11661166- KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1));11671167- MACIO_OUT32(KEYLARGO_FCR4, reg);11681168- (void)MACIO_IN32(KEYLARGO_FCR4);11691169- udelay(10);11701170- } else {11711171- reg = MACIO_IN32(KEYLARGO_FCR3);11721172- reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) |11731173- KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0));11741174- reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) |11751175- KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1));11761176- MACIO_OUT32(KEYLARGO_FCR3, reg);11771177- (void)MACIO_IN32(KEYLARGO_FCR3);11781178- udelay(10);11791179- }11801180- if (macio->type == macio_intrepid) {11811181- /* wait for clock stopped bits to clear */11821182- u32 test0 = 0, test1 = 0;11831183- u32 status0, status1;11841184- int timeout = 1000;11851185-11861186- UNLOCK(flags);11871187- switch (number) {11881188- case 0:11891189- test0 = UNI_N_CLOCK_STOPPED_USB0;11901190- test1 = UNI_N_CLOCK_STOPPED_USB0PCI;11911191- break;11921192- case 2:11931193- test0 = UNI_N_CLOCK_STOPPED_USB1;11941194- test1 = UNI_N_CLOCK_STOPPED_USB1PCI;11951195- break;11961196- case 4:11971197- test0 = UNI_N_CLOCK_STOPPED_USB2;11981198- test1 = UNI_N_CLOCK_STOPPED_USB2PCI;11991199- break;12001200- }12011201- do {12021202- if (--timeout <= 0) {12031203- printk(KERN_ERR "core99_usb_enable: "12041204- "Timeout waiting for clocks\n");12051205- break;12061206- }12071207- mdelay(1);12081208- status0 = UN_IN(UNI_N_CLOCK_STOP_STATUS0);12091209- status1 = UN_IN(UNI_N_CLOCK_STOP_STATUS1);12101210- } while ((status0 & test0) | (status1 & test1));12111211- LOCK(flags);12121212- }12131213- } else {12141214- /* Turn OFF */12151215- if (number < 4) {12161216- reg = MACIO_IN32(KEYLARGO_FCR4);12171217- reg |= KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) |12181218- KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number);12191219- reg |= KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) |12201220- KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1);12211221- MACIO_OUT32(KEYLARGO_FCR4, reg);12221222- (void)MACIO_IN32(KEYLARGO_FCR4);12231223- udelay(1);12241224- } else {12251225- reg = MACIO_IN32(KEYLARGO_FCR3);12261226- reg |= KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) |12271227- KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0);12281228- reg |= KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) |12291229- KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1);12301230- MACIO_OUT32(KEYLARGO_FCR3, reg);12311231- (void)MACIO_IN32(KEYLARGO_FCR3);12321232- udelay(1);12331233- }12341234- if (number == 0) {12351235- if (macio->type != macio_intrepid)12361236- MACIO_BIC(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);12371237- (void)MACIO_IN32(KEYLARGO_FCR0);12381238- udelay(1);12391239- MACIO_BIS(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));12401240- (void)MACIO_IN32(KEYLARGO_FCR0);12411241- } else if (number == 2) {12421242- if (macio->type != macio_intrepid)12431243- MACIO_BIC(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);12441244- (void)MACIO_IN32(KEYLARGO_FCR0);12451245- udelay(1);12461246- MACIO_BIS(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));12471247- (void)MACIO_IN32(KEYLARGO_FCR0);12481248- } else if (number == 4) {12491249- udelay(1);12501250- MACIO_BIS(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1));12511251- (void)MACIO_IN32(KEYLARGO_FCR1);12521252- }12531253- udelay(1);12541254- }12551255- UNLOCK(flags);12561256-12571257- return 0;12581258-}12591259-12601260-static long12611261-core99_firewire_enable(struct device_node* node, long param, long value)12621262-{12631263- unsigned long flags;12641264- struct macio_chip* macio;12651265-12661266- macio = &macio_chips[0];12671267- if (macio->type != macio_keylargo && macio->type != macio_pangea &&12681268- macio->type != macio_intrepid)12691269- return -ENODEV;12701270- if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED))12711271- return -ENODEV;12721272-12731273- LOCK(flags);12741274- if (value) {12751275- UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);12761276- (void)UN_IN(UNI_N_CLOCK_CNTL);12771277- } else {12781278- UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);12791279- (void)UN_IN(UNI_N_CLOCK_CNTL);12801280- }12811281- UNLOCK(flags);12821282- mdelay(1);12831283-12841284- return 0;12851285-}12861286-12871287-static long12881288-core99_firewire_cable_power(struct device_node* node, long param, long value)12891289-{12901290- unsigned long flags;12911291- struct macio_chip* macio;12921292-12931293- /* Trick: we allow NULL node */12941294- if ((pmac_mb.board_flags & PMAC_MB_HAS_FW_POWER) == 0)12951295- return -ENODEV;12961296- macio = &macio_chips[0];12971297- if (macio->type != macio_keylargo && macio->type != macio_pangea &&12981298- macio->type != macio_intrepid)12991299- return -ENODEV;13001300- if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED))13011301- return -ENODEV;13021302-13031303- LOCK(flags);13041304- if (value) {13051305- MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 0);13061306- MACIO_IN8(KL_GPIO_FW_CABLE_POWER);13071307- udelay(10);13081308- } else {13091309- MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 4);13101310- MACIO_IN8(KL_GPIO_FW_CABLE_POWER); udelay(10);13111311- }13121312- UNLOCK(flags);13131313- mdelay(1);13141314-13151315- return 0;13161316-}13171317-13181318-static long13191319-intrepid_aack_delay_enable(struct device_node* node, long param, long value)13201320-{13211321- unsigned long flags;13221322-13231323- if (uninorth_rev < 0xd2)13241324- return -ENODEV;13251325-13261326- LOCK(flags);13271327- if (param)13281328- UN_BIS(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE);13291329- else13301330- UN_BIC(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE);13311331- UNLOCK(flags);13321332-13331333- return 0;13341334-}13351335-13361336-13371337-#endif /* CONFIG_POWER4 */13381338-13391339-static long13401340-core99_read_gpio(struct device_node* node, long param, long value)13411341-{13421342- struct macio_chip* macio = &macio_chips[0];13431343-13441344- return MACIO_IN8(param);13451345-}13461346-13471347-13481348-static long13491349-core99_write_gpio(struct device_node* node, long param, long value)13501350-{13511351- struct macio_chip* macio = &macio_chips[0];13521352-13531353- MACIO_OUT8(param, (u8)(value & 0xff));13541354- return 0;13551355-}13561356-13571357-#ifdef CONFIG_POWER413581358-13591359-static long13601360-g5_gmac_enable(struct device_node* node, long param, long value)13611361-{13621362- struct macio_chip* macio = &macio_chips[0];13631363- unsigned long flags;13641364- u8 pbus, pid;13651365-13661366- LOCK(flags);13671367- if (value) {13681368- MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE);13691369- mb();13701370- k2_skiplist[0] = NULL;13711371- } else {13721372- k2_skiplist[0] = node;13731373- mb();13741374- MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE);13751375- }13761376-13771377- UNLOCK(flags);13781378- mdelay(1);13791379-13801380- return 0;13811381-}13821382-13831383-static long13841384-g5_fw_enable(struct device_node* node, long param, long value)13851385-{13861386- struct macio_chip* macio = &macio_chips[0];13871387- unsigned long flags;13881388-13891389- LOCK(flags);13901390- if (value) {13911391- MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE);13921392- mb();13931393- k2_skiplist[1] = NULL;13941394- } else {13951395- k2_skiplist[1] = node;13961396- mb();13971397- MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE);13981398- }13991399-14001400- UNLOCK(flags);14011401- mdelay(1);14021402-14031403- return 0;14041404-}14051405-14061406-static long14071407-g5_mpic_enable(struct device_node* node, long param, long value)14081408-{14091409- unsigned long flags;14101410-14111411- if (node->parent == NULL || strcmp(node->parent->name, "u3"))14121412- return 0;14131413-14141414- LOCK(flags);14151415- UN_BIS(U3_TOGGLE_REG, U3_MPIC_RESET | U3_MPIC_OUTPUT_ENABLE);14161416- UNLOCK(flags);14171417-14181418- return 0;14191419-}14201420-14211421-#ifdef CONFIG_SMP14221422-static long14231423-g5_reset_cpu(struct device_node* node, long param, long value)14241424-{14251425- unsigned int reset_io = 0;14261426- unsigned long flags;14271427- struct macio_chip* macio;14281428- struct device_node* np;14291429-14301430- macio = &macio_chips[0];14311431- if (macio->type != macio_keylargo2)14321432- return -ENODEV;14331433-14341434- np = find_path_device("/cpus");14351435- if (np == NULL)14361436- return -ENODEV;14371437- for (np = np->child; np != NULL; np = np->sibling) {14381438- u32* num = (u32 *)get_property(np, "reg", NULL);14391439- u32* rst = (u32 *)get_property(np, "soft-reset", NULL);14401440- if (num == NULL || rst == NULL)14411441- continue;14421442- if (param == *num) {14431443- reset_io = *rst;14441444- break;14451445- }14461446- }14471447- if (np == NULL || reset_io == 0)14481448- return -ENODEV;14491449-14501450- LOCK(flags);14511451- MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);14521452- (void)MACIO_IN8(reset_io);14531453- udelay(1);14541454- MACIO_OUT8(reset_io, 0);14551455- (void)MACIO_IN8(reset_io);14561456- UNLOCK(flags);14571457-14581458- return 0;14591459-}14601460-#endif /* CONFIG_SMP */14611461-14621462-/*14631463- * This can be called from pmac_smp so isn't static14641464- *14651465- * This takes the second CPU off the bus on dual CPU machines14661466- * running UP14671467- */14681468-void g5_phy_disable_cpu1(void)14691469-{14701470- UN_OUT(U3_API_PHY_CONFIG_1, 0);14711471-}14721472-14731473-#endif /* CONFIG_POWER4 */14741474-14751475-#ifndef CONFIG_POWER414761476-14771477-static void14781478-keylargo_shutdown(struct macio_chip* macio, int sleep_mode)14791479-{14801480- u32 temp;14811481-14821482- if (sleep_mode) {14831483- mdelay(1);14841484- MACIO_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND);14851485- (void)MACIO_IN32(KEYLARGO_FCR0);14861486- mdelay(1);14871487- }14881488-14891489- MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |14901490- KL0_SCC_CELL_ENABLE |14911491- KL0_IRDA_ENABLE | KL0_IRDA_CLK32_ENABLE |14921492- KL0_IRDA_CLK19_ENABLE);14931493-14941494- MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK);14951495- MACIO_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_IDE_ENABLE);14961496-14971497- MACIO_BIC(KEYLARGO_FCR1,14981498- KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |14991499- KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |15001500- KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |15011501- KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |15021502- KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |15031503- KL1_EIDE0_ENABLE | KL1_EIDE0_RESET_N |15041504- KL1_EIDE1_ENABLE | KL1_EIDE1_RESET_N |15051505- KL1_UIDE_ENABLE);15061506-15071507- MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);15081508- MACIO_BIC(KEYLARGO_FCR2, KL2_IOBUS_ENABLE);15091509-15101510- temp = MACIO_IN32(KEYLARGO_FCR3);15111511- if (macio->rev >= 2) {15121512- temp |= KL3_SHUTDOWN_PLL2X;15131513- if (sleep_mode)15141514- temp |= KL3_SHUTDOWN_PLL_TOTAL;15151515- }15161516-15171517- temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |15181518- KL3_SHUTDOWN_PLLKW35;15191519- if (sleep_mode)15201520- temp |= KL3_SHUTDOWN_PLLKW12;15211521- temp &= ~(KL3_CLK66_ENABLE | KL3_CLK49_ENABLE | KL3_CLK45_ENABLE15221522- | KL3_CLK31_ENABLE | KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE);15231523- if (sleep_mode)15241524- temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);15251525- MACIO_OUT32(KEYLARGO_FCR3, temp);15261526-15271527- /* Flush posted writes & wait a bit */15281528- (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);15291529-}15301530-15311531-static void15321532-pangea_shutdown(struct macio_chip* macio, int sleep_mode)15331533-{15341534- u32 temp;15351535-15361536- MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |15371537- KL0_SCC_CELL_ENABLE |15381538- KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE);15391539-15401540- MACIO_BIC(KEYLARGO_FCR1,15411541- KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |15421542- KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |15431543- KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |15441544- KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |15451545- KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |15461546- KL1_UIDE_ENABLE);15471547- if (pmac_mb.board_flags & PMAC_MB_MOBILE)15481548- MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N);15491549-15501550- MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);15511551-15521552- temp = MACIO_IN32(KEYLARGO_FCR3);15531553- temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |15541554- KL3_SHUTDOWN_PLLKW35;15551555- temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | KL3_CLK31_ENABLE15561556- | KL3_I2S0_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE);15571557- if (sleep_mode)15581558- temp &= ~(KL3_VIA_CLK16_ENABLE | KL3_TIMER_CLK18_ENABLE);15591559- MACIO_OUT32(KEYLARGO_FCR3, temp);15601560-15611561- /* Flush posted writes & wait a bit */15621562- (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);15631563-}15641564-15651565-static void15661566-intrepid_shutdown(struct macio_chip* macio, int sleep_mode)15671567-{15681568- u32 temp;15691569-15701570- MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |15711571- KL0_SCC_CELL_ENABLE);15721572-15731573- MACIO_BIC(KEYLARGO_FCR1,15741574- /*KL1_USB2_CELL_ENABLE |*/15751575- KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |15761576- KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |15771577- KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE);15781578- if (pmac_mb.board_flags & PMAC_MB_MOBILE)15791579- MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N);15801580-15811581- temp = MACIO_IN32(KEYLARGO_FCR3);15821582- temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE |15831583- KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE);15841584- if (sleep_mode)15851585- temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_IT_VIA_CLK32_ENABLE);15861586- MACIO_OUT32(KEYLARGO_FCR3, temp);15871587-15881588- /* Flush posted writes & wait a bit */15891589- (void)MACIO_IN32(KEYLARGO_FCR0);15901590- mdelay(10);15911591-}15921592-15931593-15941594-void pmac_tweak_clock_spreading(int enable)15951595-{15961596- struct macio_chip* macio = &macio_chips[0];15971597-15981598- /* Hack for doing clock spreading on some machines PowerBooks and15991599- * iBooks. This implements the "platform-do-clockspreading" OF16001600- * property as decoded manually on various models. For safety, we also16011601- * check the product ID in the device-tree in cases we'll whack the i2c16021602- * chip to make reasonably sure we won't set wrong values in there16031603- *16041604- * Of course, ultimately, we have to implement a real parser for16051605- * the platform-do-* stuff...16061606- */16071607-16081608- if (macio->type == macio_intrepid) {16091609- struct device_node *clock =16101610- of_find_node_by_path("/uni-n@f8000000/hw-clock");16111611- if (clock && get_property(clock, "platform-do-clockspreading",16121612- NULL)) {16131613- printk(KERN_INFO "%sabling clock spreading on Intrepid"16141614- " ASIC\n", enable ? "En" : "Dis");16151615- if (enable)16161616- UN_OUT(UNI_N_CLOCK_SPREADING, 2);16171617- else16181618- UN_OUT(UNI_N_CLOCK_SPREADING, 0);16191619- mdelay(40);16201620- }16211621- of_node_put(clock);16221622- }16231623-16241624- while (machine_is_compatible("PowerBook5,2") ||16251625- machine_is_compatible("PowerBook5,3") ||16261626- machine_is_compatible("PowerBook6,2") ||16271627- machine_is_compatible("PowerBook6,3")) {16281628- struct device_node *ui2c = of_find_node_by_type(NULL, "i2c");16291629- struct device_node *dt = of_find_node_by_name(NULL, "device-tree");16301630- u8 buffer[9];16311631- u32 *productID;16321632- int i, rc, changed = 0;16331633-16341634- if (dt == NULL)16351635- break;16361636- productID = (u32 *)get_property(dt, "pid#", NULL);16371637- if (productID == NULL)16381638- break;16391639- while(ui2c) {16401640- struct device_node *p = of_get_parent(ui2c);16411641- if (p && !strcmp(p->name, "uni-n"))16421642- break;16431643- ui2c = of_find_node_by_type(ui2c, "i2c");16441644- }16451645- if (ui2c == NULL)16461646- break;16471647- DBG("Trying to bump clock speed for PID: %08x...\n", *productID);16481648- rc = pmac_low_i2c_open(ui2c, 1);16491649- if (rc != 0)16501650- break;16511651- pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);16521652- rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);16531653- DBG("read result: %d,", rc);16541654- if (rc != 0) {16551655- pmac_low_i2c_close(ui2c);16561656- break;16571657- }16581658- for (i=0; i<9; i++)16591659- DBG(" %02x", buffer[i]);16601660- DBG("\n");16611661-16621662- switch(*productID) {16631663- case 0x1182: /* AlBook 12" rev 2 */16641664- case 0x1183: /* iBook G4 12" */16651665- buffer[0] = (buffer[0] & 0x8f) | 0x70;16661666- buffer[2] = (buffer[2] & 0x7f) | 0x00;16671667- buffer[5] = (buffer[5] & 0x80) | 0x31;16681668- buffer[6] = (buffer[6] & 0x40) | 0xb0;16691669- buffer[7] = (buffer[7] & 0x00) | (enable ? 0xc0 : 0xba);16701670- buffer[8] = (buffer[8] & 0x00) | 0x30;16711671- changed = 1;16721672- break;16731673- case 0x3142: /* AlBook 15" (ATI M10) */16741674- case 0x3143: /* AlBook 17" (ATI M10) */16751675- buffer[0] = (buffer[0] & 0xaf) | 0x50;16761676- buffer[2] = (buffer[2] & 0x7f) | 0x00;16771677- buffer[5] = (buffer[5] & 0x80) | 0x31;16781678- buffer[6] = (buffer[6] & 0x40) | 0xb0;16791679- buffer[7] = (buffer[7] & 0x00) | (enable ? 0xd0 : 0xc0);16801680- buffer[8] = (buffer[8] & 0x00) | 0x30;16811681- changed = 1;16821682- break;16831683- default:16841684- DBG("i2c-hwclock: Machine model not handled\n");16851685- break;16861686- }16871687- if (!changed) {16881688- pmac_low_i2c_close(ui2c);16891689- break;16901690- }16911691- printk(KERN_INFO "%sabling clock spreading on i2c clock chip\n",16921692- enable ? "En" : "Dis");16931693- pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_stdsub);16941694- rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_write, 0x80, buffer, 9);16951695- DBG("write result: %d,", rc);16961696- pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);16971697- rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);16981698- DBG("read result: %d,", rc);16991699- if (rc != 0) {17001700- pmac_low_i2c_close(ui2c);17011701- break;17021702- }17031703- for (i=0; i<9; i++)17041704- DBG(" %02x", buffer[i]);17051705- pmac_low_i2c_close(ui2c);17061706- break;17071707- }17081708-}17091709-17101710-17111711-static int17121712-core99_sleep(void)17131713-{17141714- struct macio_chip* macio;17151715- int i;17161716-17171717- macio = &macio_chips[0];17181718- if (macio->type != macio_keylargo && macio->type != macio_pangea &&17191719- macio->type != macio_intrepid)17201720- return -ENODEV;17211721-17221722- /* We power off the wireless slot in case it was not done17231723- * by the driver. We don't power it on automatically however17241724- */17251725- if (macio->flags & MACIO_FLAG_AIRPORT_ON)17261726- core99_airport_enable(macio->of_node, 0, 0);17271727-17281728- /* We power off the FW cable. Should be done by the driver... */17291729- if (macio->flags & MACIO_FLAG_FW_SUPPORTED) {17301730- core99_firewire_enable(NULL, 0, 0);17311731- core99_firewire_cable_power(NULL, 0, 0);17321732- }17331733-17341734- /* We make sure int. modem is off (in case driver lost it) */17351735- if (macio->type == macio_keylargo)17361736- core99_modem_enable(macio->of_node, 0, 0);17371737- else17381738- pangea_modem_enable(macio->of_node, 0, 0);17391739-17401740- /* We make sure the sound is off as well */17411741- core99_sound_chip_enable(macio->of_node, 0, 0);17421742-17431743- /*17441744- * Save various bits of KeyLargo17451745- */17461746-17471747- /* Save the state of the various GPIOs */17481748- save_gpio_levels[0] = MACIO_IN32(KEYLARGO_GPIO_LEVELS0);17491749- save_gpio_levels[1] = MACIO_IN32(KEYLARGO_GPIO_LEVELS1);17501750- for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)17511751- save_gpio_extint[i] = MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+i);17521752- for (i=0; i<KEYLARGO_GPIO_CNT; i++)17531753- save_gpio_normal[i] = MACIO_IN8(KEYLARGO_GPIO_0+i);17541754-17551755- /* Save the FCRs */17561756- if (macio->type == macio_keylargo)17571757- save_mbcr = MACIO_IN32(KEYLARGO_MBCR);17581758- save_fcr[0] = MACIO_IN32(KEYLARGO_FCR0);17591759- save_fcr[1] = MACIO_IN32(KEYLARGO_FCR1);17601760- save_fcr[2] = MACIO_IN32(KEYLARGO_FCR2);17611761- save_fcr[3] = MACIO_IN32(KEYLARGO_FCR3);17621762- save_fcr[4] = MACIO_IN32(KEYLARGO_FCR4);17631763- if (macio->type == macio_pangea || macio->type == macio_intrepid)17641764- save_fcr[5] = MACIO_IN32(KEYLARGO_FCR5);17651765-17661766- /* Save state & config of DBDMA channels */17671767- dbdma_save(macio, save_dbdma);17681768-17691769- /*17701770- * Turn off as much as we can17711771- */17721772- if (macio->type == macio_pangea)17731773- pangea_shutdown(macio, 1);17741774- else if (macio->type == macio_intrepid)17751775- intrepid_shutdown(macio, 1);17761776- else if (macio->type == macio_keylargo)17771777- keylargo_shutdown(macio, 1);17781778-17791779- /*17801780- * Put the host bridge to sleep17811781- */17821782-17831783- save_unin_clock_ctl = UN_IN(UNI_N_CLOCK_CNTL);17841784- /* Note: do not switch GMAC off, driver does it when necessary, WOL must keep it17851785- * enabled !17861786- */17871787- UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl &17881788- ~(/*UNI_N_CLOCK_CNTL_GMAC|*/UNI_N_CLOCK_CNTL_FW/*|UNI_N_CLOCK_CNTL_PCI*/));17891789- udelay(100);17901790- UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING);17911791- UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_SLEEP);17921792- mdelay(10);17931793-17941794- /*17951795- * FIXME: A bit of black magic with OpenPIC (don't ask me why)17961796- */17971797- if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) {17981798- MACIO_BIS(0x506e0, 0x00400000);17991799- MACIO_BIS(0x506e0, 0x80000000);18001800- }18011801- return 0;18021802-}18031803-18041804-static int18051805-core99_wake_up(void)18061806-{18071807- struct macio_chip* macio;18081808- int i;18091809-18101810- macio = &macio_chips[0];18111811- if (macio->type != macio_keylargo && macio->type != macio_pangea &&18121812- macio->type != macio_intrepid)18131813- return -ENODEV;18141814-18151815- /*18161816- * Wakeup the host bridge18171817- */18181818- UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL);18191819- udelay(10);18201820- UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING);18211821- udelay(10);18221822-18231823- /*18241824- * Restore KeyLargo18251825- */18261826-18271827- if (macio->type == macio_keylargo) {18281828- MACIO_OUT32(KEYLARGO_MBCR, save_mbcr);18291829- (void)MACIO_IN32(KEYLARGO_MBCR); udelay(10);18301830- }18311831- MACIO_OUT32(KEYLARGO_FCR0, save_fcr[0]);18321832- (void)MACIO_IN32(KEYLARGO_FCR0); udelay(10);18331833- MACIO_OUT32(KEYLARGO_FCR1, save_fcr[1]);18341834- (void)MACIO_IN32(KEYLARGO_FCR1); udelay(10);18351835- MACIO_OUT32(KEYLARGO_FCR2, save_fcr[2]);18361836- (void)MACIO_IN32(KEYLARGO_FCR2); udelay(10);18371837- MACIO_OUT32(KEYLARGO_FCR3, save_fcr[3]);18381838- (void)MACIO_IN32(KEYLARGO_FCR3); udelay(10);18391839- MACIO_OUT32(KEYLARGO_FCR4, save_fcr[4]);18401840- (void)MACIO_IN32(KEYLARGO_FCR4); udelay(10);18411841- if (macio->type == macio_pangea || macio->type == macio_intrepid) {18421842- MACIO_OUT32(KEYLARGO_FCR5, save_fcr[5]);18431843- (void)MACIO_IN32(KEYLARGO_FCR5); udelay(10);18441844- }18451845-18461846- dbdma_restore(macio, save_dbdma);18471847-18481848- MACIO_OUT32(KEYLARGO_GPIO_LEVELS0, save_gpio_levels[0]);18491849- MACIO_OUT32(KEYLARGO_GPIO_LEVELS1, save_gpio_levels[1]);18501850- for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)18511851- MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+i, save_gpio_extint[i]);18521852- for (i=0; i<KEYLARGO_GPIO_CNT; i++)18531853- MACIO_OUT8(KEYLARGO_GPIO_0+i, save_gpio_normal[i]);18541854-18551855- /* FIXME more black magic with OpenPIC ... */18561856- if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) {18571857- MACIO_BIC(0x506e0, 0x00400000);18581858- MACIO_BIC(0x506e0, 0x80000000);18591859- }18601860-18611861- UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl);18621862- udelay(100);18631863-18641864- return 0;18651865-}18661866-18671867-static long18681868-core99_sleep_state(struct device_node* node, long param, long value)18691869-{18701870- /* Param == 1 means to enter the "fake sleep" mode that is18711871- * used for CPU speed switch18721872- */18731873- if (param == 1) {18741874- if (value == 1) {18751875- UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING);18761876- UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_IDLE2);18771877- } else {18781878- UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL);18791879- udelay(10);18801880- UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING);18811881- udelay(10);18821882- }18831883- return 0;18841884- }18851885- if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)18861886- return -EPERM;18871887-18881888- if (value == 1)18891889- return core99_sleep();18901890- else if (value == 0)18911891- return core99_wake_up();18921892- return 0;18931893-}18941894-18951895-#endif /* CONFIG_POWER4 */18961896-18971897-static long18981898-generic_dev_can_wake(struct device_node* node, long param, long value)18991899-{19001900- /* Todo: eventually check we are really dealing with on-board19011901- * video device ...19021902- */19031903-19041904- if (pmac_mb.board_flags & PMAC_MB_MAY_SLEEP)19051905- pmac_mb.board_flags |= PMAC_MB_CAN_SLEEP;19061906- return 0;19071907-}19081908-19091909-static long19101910-generic_get_mb_info(struct device_node* node, long param, long value)19111911-{19121912- switch(param) {19131913- case PMAC_MB_INFO_MODEL:19141914- return pmac_mb.model_id;19151915- case PMAC_MB_INFO_FLAGS:19161916- return pmac_mb.board_flags;19171917- case PMAC_MB_INFO_NAME:19181918- /* hack hack hack... but should work */19191919- *((const char **)value) = pmac_mb.model_name;19201920- return 0;19211921- }19221922- return -EINVAL;19231923-}19241924-19251925-19261926-/*19271927- * Table definitions19281928- */19291929-19301930-/* Used on any machine19311931- */19321932-static struct feature_table_entry any_features[] = {19331933- { PMAC_FTR_GET_MB_INFO, generic_get_mb_info },19341934- { PMAC_FTR_DEVICE_CAN_WAKE, generic_dev_can_wake },19351935- { 0, NULL }19361936-};19371937-19381938-#ifndef CONFIG_POWER419391939-19401940-/* OHare based motherboards. Currently, we only use these on the19411941- * 2400,3400 and 3500 series powerbooks. Some older desktops seem19421942- * to have issues with turning on/off those asic cells19431943- */19441944-static struct feature_table_entry ohare_features[] = {19451945- { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable },19461946- { PMAC_FTR_SWIM3_ENABLE, ohare_floppy_enable },19471947- { PMAC_FTR_MESH_ENABLE, ohare_mesh_enable },19481948- { PMAC_FTR_IDE_ENABLE, ohare_ide_enable},19491949- { PMAC_FTR_IDE_RESET, ohare_ide_reset},19501950- { PMAC_FTR_SLEEP_STATE, ohare_sleep_state },19511951- { 0, NULL }19521952-};19531953-19541954-/* Heathrow desktop machines (Beige G3).19551955- * Separated as some features couldn't be properly tested19561956- * and the serial port control bits appear to confuse it.19571957- */19581958-static struct feature_table_entry heathrow_desktop_features[] = {19591959- { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable },19601960- { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable },19611961- { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable },19621962- { PMAC_FTR_IDE_RESET, heathrow_ide_reset },19631963- { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable },19641964- { 0, NULL }19651965-};19661966-19671967-/* Heathrow based laptop, that is the Wallstreet and mainstreet19681968- * powerbooks.19691969- */19701970-static struct feature_table_entry heathrow_laptop_features[] = {19711971- { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable },19721972- { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable },19731973- { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable },19741974- { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable },19751975- { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable },19761976- { PMAC_FTR_IDE_RESET, heathrow_ide_reset },19771977- { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable },19781978- { PMAC_FTR_SOUND_CHIP_ENABLE, heathrow_sound_enable },19791979- { PMAC_FTR_SLEEP_STATE, heathrow_sleep_state },19801980- { 0, NULL }19811981-};19821982-19831983-/* Paddington based machines19841984- * The lombard (101) powerbook, first iMac models, B&W G3 and Yikes G4.19851985- */19861986-static struct feature_table_entry paddington_features[] = {19871987- { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable },19881988- { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable },19891989- { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable },19901990- { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable },19911991- { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable },19921992- { PMAC_FTR_IDE_RESET, heathrow_ide_reset },19931993- { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable },19941994- { PMAC_FTR_SOUND_CHIP_ENABLE, heathrow_sound_enable },19951995- { PMAC_FTR_SLEEP_STATE, heathrow_sleep_state },19961996- { 0, NULL }19971997-};19981998-19991999-/* Core99 & MacRISC 2 machines (all machines released since the20002000- * iBook (included), that is all AGP machines, except pangea20012001- * chipset. The pangea chipset is the "combo" UniNorth/KeyLargo20022002- * used on iBook2 & iMac "flow power".20032003- */20042004-static struct feature_table_entry core99_features[] = {20052005- { PMAC_FTR_SCC_ENABLE, core99_scc_enable },20062006- { PMAC_FTR_MODEM_ENABLE, core99_modem_enable },20072007- { PMAC_FTR_IDE_ENABLE, core99_ide_enable },20082008- { PMAC_FTR_IDE_RESET, core99_ide_reset },20092009- { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },20102010- { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },20112011- { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable },20122012- { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable },20132013- { PMAC_FTR_USB_ENABLE, core99_usb_enable },20142014- { PMAC_FTR_1394_ENABLE, core99_firewire_enable },20152015- { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },20162016- { PMAC_FTR_SLEEP_STATE, core99_sleep_state },20172017-#ifdef CONFIG_SMP20182018- { PMAC_FTR_RESET_CPU, core99_reset_cpu },20192019-#endif /* CONFIG_SMP */20202020- { PMAC_FTR_READ_GPIO, core99_read_gpio },20212021- { PMAC_FTR_WRITE_GPIO, core99_write_gpio },20222022- { 0, NULL }20232023-};20242024-20252025-/* RackMac20262026- */20272027-static struct feature_table_entry rackmac_features[] = {20282028- { PMAC_FTR_SCC_ENABLE, core99_scc_enable },20292029- { PMAC_FTR_IDE_ENABLE, core99_ide_enable },20302030- { PMAC_FTR_IDE_RESET, core99_ide_reset },20312031- { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },20322032- { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },20332033- { PMAC_FTR_USB_ENABLE, core99_usb_enable },20342034- { PMAC_FTR_1394_ENABLE, core99_firewire_enable },20352035- { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },20362036- { PMAC_FTR_SLEEP_STATE, core99_sleep_state },20372037-#ifdef CONFIG_SMP20382038- { PMAC_FTR_RESET_CPU, core99_reset_cpu },20392039-#endif /* CONFIG_SMP */20402040- { PMAC_FTR_READ_GPIO, core99_read_gpio },20412041- { PMAC_FTR_WRITE_GPIO, core99_write_gpio },20422042- { 0, NULL }20432043-};20442044-20452045-/* Pangea features20462046- */20472047-static struct feature_table_entry pangea_features[] = {20482048- { PMAC_FTR_SCC_ENABLE, core99_scc_enable },20492049- { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable },20502050- { PMAC_FTR_IDE_ENABLE, core99_ide_enable },20512051- { PMAC_FTR_IDE_RESET, core99_ide_reset },20522052- { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },20532053- { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },20542054- { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable },20552055- { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable },20562056- { PMAC_FTR_USB_ENABLE, core99_usb_enable },20572057- { PMAC_FTR_1394_ENABLE, core99_firewire_enable },20582058- { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },20592059- { PMAC_FTR_SLEEP_STATE, core99_sleep_state },20602060- { PMAC_FTR_READ_GPIO, core99_read_gpio },20612061- { PMAC_FTR_WRITE_GPIO, core99_write_gpio },20622062- { 0, NULL }20632063-};20642064-20652065-/* Intrepid features20662066- */20672067-static struct feature_table_entry intrepid_features[] = {20682068- { PMAC_FTR_SCC_ENABLE, core99_scc_enable },20692069- { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable },20702070- { PMAC_FTR_IDE_ENABLE, core99_ide_enable },20712071- { PMAC_FTR_IDE_RESET, core99_ide_reset },20722072- { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },20732073- { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },20742074- { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable },20752075- { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable },20762076- { PMAC_FTR_USB_ENABLE, core99_usb_enable },20772077- { PMAC_FTR_1394_ENABLE, core99_firewire_enable },20782078- { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },20792079- { PMAC_FTR_SLEEP_STATE, core99_sleep_state },20802080- { PMAC_FTR_READ_GPIO, core99_read_gpio },20812081- { PMAC_FTR_WRITE_GPIO, core99_write_gpio },20822082- { PMAC_FTR_AACK_DELAY_ENABLE, intrepid_aack_delay_enable },20832083- { 0, NULL }20842084-};20852085-20862086-#else /* CONFIG_POWER4 */20872087-20882088-/* G5 features20892089- */20902090-static struct feature_table_entry g5_features[] = {20912091- { PMAC_FTR_GMAC_ENABLE, g5_gmac_enable },20922092- { PMAC_FTR_1394_ENABLE, g5_fw_enable },20932093- { PMAC_FTR_ENABLE_MPIC, g5_mpic_enable },20942094-#ifdef CONFIG_SMP20952095- { PMAC_FTR_RESET_CPU, g5_reset_cpu },20962096-#endif /* CONFIG_SMP */20972097- { PMAC_FTR_READ_GPIO, core99_read_gpio },20982098- { PMAC_FTR_WRITE_GPIO, core99_write_gpio },20992099- { 0, NULL }21002100-};21012101-21022102-#endif /* CONFIG_POWER4 */21032103-21042104-static struct pmac_mb_def pmac_mb_defs[] = {21052105-#ifndef CONFIG_POWER421062106- /*21072107- * Desktops21082108- */21092109-21102110- { "AAPL,8500", "PowerMac 8500/8600",21112111- PMAC_TYPE_PSURGE, NULL,21122112- 021132113- },21142114- { "AAPL,9500", "PowerMac 9500/9600",21152115- PMAC_TYPE_PSURGE, NULL,21162116- 021172117- },21182118- { "AAPL,7200", "PowerMac 7200",21192119- PMAC_TYPE_PSURGE, NULL,21202120- 021212121- },21222122- { "AAPL,7300", "PowerMac 7200/7300",21232123- PMAC_TYPE_PSURGE, NULL,21242124- 021252125- },21262126- { "AAPL,7500", "PowerMac 7500",21272127- PMAC_TYPE_PSURGE, NULL,21282128- 021292129- },21302130- { "AAPL,ShinerESB", "Apple Network Server",21312131- PMAC_TYPE_ANS, NULL,21322132- 021332133- },21342134- { "AAPL,e407", "Alchemy",21352135- PMAC_TYPE_ALCHEMY, NULL,21362136- 021372137- },21382138- { "AAPL,e411", "Gazelle",21392139- PMAC_TYPE_GAZELLE, NULL,21402140- 021412141- },21422142- { "AAPL,Gossamer", "PowerMac G3 (Gossamer)",21432143- PMAC_TYPE_GOSSAMER, heathrow_desktop_features,21442144- 021452145- },21462146- { "AAPL,PowerMac G3", "PowerMac G3 (Silk)",21472147- PMAC_TYPE_SILK, heathrow_desktop_features,21482148- 021492149- },21502150- { "PowerMac1,1", "Blue&White G3",21512151- PMAC_TYPE_YOSEMITE, paddington_features,21522152- 021532153- },21542154- { "PowerMac1,2", "PowerMac G4 PCI Graphics",21552155- PMAC_TYPE_YIKES, paddington_features,21562156- 021572157- },21582158- { "PowerMac2,1", "iMac FireWire",21592159- PMAC_TYPE_FW_IMAC, core99_features,21602160- PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE9921612161- },21622162- { "PowerMac2,2", "iMac FireWire",21632163- PMAC_TYPE_FW_IMAC, core99_features,21642164- PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE9921652165- },21662166- { "PowerMac3,1", "PowerMac G4 AGP Graphics",21672167- PMAC_TYPE_SAWTOOTH, core99_features,21682168- PMAC_MB_OLD_CORE9921692169- },21702170- { "PowerMac3,2", "PowerMac G4 AGP Graphics",21712171- PMAC_TYPE_SAWTOOTH, core99_features,21722172- PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE9921732173- },21742174- { "PowerMac3,3", "PowerMac G4 AGP Graphics",21752175- PMAC_TYPE_SAWTOOTH, core99_features,21762176- PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE9921772177- },21782178- { "PowerMac3,4", "PowerMac G4 Silver",21792179- PMAC_TYPE_QUICKSILVER, core99_features,21802180- PMAC_MB_MAY_SLEEP21812181- },21822182- { "PowerMac3,5", "PowerMac G4 Silver",21832183- PMAC_TYPE_QUICKSILVER, core99_features,21842184- PMAC_MB_MAY_SLEEP21852185- },21862186- { "PowerMac3,6", "PowerMac G4 Windtunnel",21872187- PMAC_TYPE_WINDTUNNEL, core99_features,21882188- PMAC_MB_MAY_SLEEP,21892189- },21902190- { "PowerMac4,1", "iMac \"Flower Power\"",21912191- PMAC_TYPE_PANGEA_IMAC, pangea_features,21922192- PMAC_MB_MAY_SLEEP21932193- },21942194- { "PowerMac4,2", "Flat panel iMac",21952195- PMAC_TYPE_FLAT_PANEL_IMAC, pangea_features,21962196- PMAC_MB_CAN_SLEEP21972197- },21982198- { "PowerMac4,4", "eMac",21992199- PMAC_TYPE_EMAC, core99_features,22002200- PMAC_MB_MAY_SLEEP22012201- },22022202- { "PowerMac5,1", "PowerMac G4 Cube",22032203- PMAC_TYPE_CUBE, core99_features,22042204- PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE9922052205- },22062206- { "PowerMac6,1", "Flat panel iMac",22072207- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,22082208- PMAC_MB_MAY_SLEEP,22092209- },22102210- { "PowerMac6,3", "Flat panel iMac",22112211- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,22122212- PMAC_MB_MAY_SLEEP,22132213- },22142214- { "PowerMac6,4", "eMac",22152215- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,22162216- PMAC_MB_MAY_SLEEP,22172217- },22182218- { "PowerMac10,1", "Mac mini",22192219- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,22202220- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER,22212221- },22222222- { "iMac,1", "iMac (first generation)",22232223- PMAC_TYPE_ORIG_IMAC, paddington_features,22242224- 022252225- },22262226-22272227- /*22282228- * Xserve's22292229- */22302230-22312231- { "RackMac1,1", "XServe",22322232- PMAC_TYPE_RACKMAC, rackmac_features,22332233- 0,22342234- },22352235- { "RackMac1,2", "XServe rev. 2",22362236- PMAC_TYPE_RACKMAC, rackmac_features,22372237- 0,22382238- },22392239-22402240- /*22412241- * Laptops22422242- */22432243-22442244- { "AAPL,3400/2400", "PowerBook 3400",22452245- PMAC_TYPE_HOOPER, ohare_features,22462246- PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE22472247- },22482248- { "AAPL,3500", "PowerBook 3500",22492249- PMAC_TYPE_KANGA, ohare_features,22502250- PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE22512251- },22522252- { "AAPL,PowerBook1998", "PowerBook Wallstreet",22532253- PMAC_TYPE_WALLSTREET, heathrow_laptop_features,22542254- PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE22552255- },22562256- { "PowerBook1,1", "PowerBook 101 (Lombard)",22572257- PMAC_TYPE_101_PBOOK, paddington_features,22582258- PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE22592259- },22602260- { "PowerBook2,1", "iBook (first generation)",22612261- PMAC_TYPE_ORIG_IBOOK, core99_features,22622262- PMAC_MB_CAN_SLEEP | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE22632263- },22642264- { "PowerBook2,2", "iBook FireWire",22652265- PMAC_TYPE_FW_IBOOK, core99_features,22662266- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER |22672267- PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE22682268- },22692269- { "PowerBook3,1", "PowerBook Pismo",22702270- PMAC_TYPE_PISMO, core99_features,22712271- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER |22722272- PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE22732273- },22742274- { "PowerBook3,2", "PowerBook Titanium",22752275- PMAC_TYPE_TITANIUM, core99_features,22762276- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE22772277- },22782278- { "PowerBook3,3", "PowerBook Titanium II",22792279- PMAC_TYPE_TITANIUM2, core99_features,22802280- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE22812281- },22822282- { "PowerBook3,4", "PowerBook Titanium III",22832283- PMAC_TYPE_TITANIUM3, core99_features,22842284- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE22852285- },22862286- { "PowerBook3,5", "PowerBook Titanium IV",22872287- PMAC_TYPE_TITANIUM4, core99_features,22882288- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE22892289- },22902290- { "PowerBook4,1", "iBook 2",22912291- PMAC_TYPE_IBOOK2, pangea_features,22922292- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE22932293- },22942294- { "PowerBook4,2", "iBook 2",22952295- PMAC_TYPE_IBOOK2, pangea_features,22962296- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE22972297- },22982298- { "PowerBook4,3", "iBook 2 rev. 2",22992299- PMAC_TYPE_IBOOK2, pangea_features,23002300- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE23012301- },23022302- { "PowerBook5,1", "PowerBook G4 17\"",23032303- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,23042304- PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,23052305- },23062306- { "PowerBook5,2", "PowerBook G4 15\"",23072307- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,23082308- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,23092309- },23102310- { "PowerBook5,3", "PowerBook G4 17\"",23112311- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,23122312- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,23132313- },23142314- { "PowerBook5,4", "PowerBook G4 15\"",23152315- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,23162316- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,23172317- },23182318- { "PowerBook5,5", "PowerBook G4 17\"",23192319- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,23202320- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,23212321- },23222322- { "PowerBook5,6", "PowerBook G4 15\"",23232323- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,23242324- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,23252325- },23262326- { "PowerBook5,7", "PowerBook G4 17\"",23272327- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,23282328- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,23292329- },23302330- { "PowerBook5,8", "PowerBook G4 15\"",23312331- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,23322332- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,23332333- },23342334- { "PowerBook5,9", "PowerBook G4 17\"",23352335- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,23362336- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,23372337- },23382338- { "PowerBook6,1", "PowerBook G4 12\"",23392339- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,23402340- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,23412341- },23422342- { "PowerBook6,2", "PowerBook G4",23432343- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,23442344- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,23452345- },23462346- { "PowerBook6,3", "iBook G4",23472347- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,23482348- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,23492349- },23502350- { "PowerBook6,4", "PowerBook G4 12\"",23512351- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,23522352- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,23532353- },23542354- { "PowerBook6,5", "iBook G4",23552355- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,23562356- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,23572357- },23582358- { "PowerBook6,7", "iBook G4",23592359- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,23602360- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,23612361- },23622362- { "PowerBook6,8", "PowerBook G4 12\"",23632363- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,23642364- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,23652365- },23662366-#else /* CONFIG_POWER4 */23672367- { "PowerMac7,2", "PowerMac G5",23682368- PMAC_TYPE_POWERMAC_G5, g5_features,23692369- 0,23702370- },23712371-#endif /* CONFIG_POWER4 */23722372-};23732373-23742374-/*23752375- * The toplevel feature_call callback23762376- */23772377-long23782378-pmac_do_feature_call(unsigned int selector, ...)23792379-{23802380- struct device_node* node;23812381- long param, value;23822382- int i;23832383- feature_call func = NULL;23842384- va_list args;23852385-23862386- if (pmac_mb.features)23872387- for (i=0; pmac_mb.features[i].function; i++)23882388- if (pmac_mb.features[i].selector == selector) {23892389- func = pmac_mb.features[i].function;23902390- break;23912391- }23922392- if (!func)23932393- for (i=0; any_features[i].function; i++)23942394- if (any_features[i].selector == selector) {23952395- func = any_features[i].function;23962396- break;23972397- }23982398- if (!func)23992399- return -ENODEV;24002400-24012401- va_start(args, selector);24022402- node = (struct device_node*)va_arg(args, void*);24032403- param = va_arg(args, long);24042404- value = va_arg(args, long);24052405- va_end(args);24062406-24072407- return func(node, param, value);24082408-}24092409-24102410-static int __init24112411-probe_motherboard(void)24122412-{24132413- int i;24142414- struct macio_chip* macio = &macio_chips[0];24152415- const char* model = NULL;24162416- struct device_node *dt;24172417-24182418- /* Lookup known motherboard type in device-tree. First try an24192419- * exact match on the "model" property, then try a "compatible"24202420- * match is none is found.24212421- */24222422- dt = find_devices("device-tree");24232423- if (dt != NULL)24242424- model = (const char *) get_property(dt, "model", NULL);24252425- for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {24262426- if (strcmp(model, pmac_mb_defs[i].model_string) == 0) {24272427- pmac_mb = pmac_mb_defs[i];24282428- goto found;24292429- }24302430- }24312431- for(i=0; i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {24322432- if (machine_is_compatible(pmac_mb_defs[i].model_string)) {24332433- pmac_mb = pmac_mb_defs[i];24342434- goto found;24352435- }24362436- }24372437-24382438- /* Fallback to selection depending on mac-io chip type */24392439- switch(macio->type) {24402440-#ifndef CONFIG_POWER424412441- case macio_grand_central:24422442- pmac_mb.model_id = PMAC_TYPE_PSURGE;24432443- pmac_mb.model_name = "Unknown PowerSurge";24442444- break;24452445- case macio_ohare:24462446- pmac_mb.model_id = PMAC_TYPE_UNKNOWN_OHARE;24472447- pmac_mb.model_name = "Unknown OHare-based";24482448- break;24492449- case macio_heathrow:24502450- pmac_mb.model_id = PMAC_TYPE_UNKNOWN_HEATHROW;24512451- pmac_mb.model_name = "Unknown Heathrow-based";24522452- pmac_mb.features = heathrow_desktop_features;24532453- break;24542454- case macio_paddington:24552455- pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PADDINGTON;24562456- pmac_mb.model_name = "Unknown Paddington-based";24572457- pmac_mb.features = paddington_features;24582458- break;24592459- case macio_keylargo:24602460- pmac_mb.model_id = PMAC_TYPE_UNKNOWN_CORE99;24612461- pmac_mb.model_name = "Unknown Keylargo-based";24622462- pmac_mb.features = core99_features;24632463- break;24642464- case macio_pangea:24652465- pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PANGEA;24662466- pmac_mb.model_name = "Unknown Pangea-based";24672467- pmac_mb.features = pangea_features;24682468- break;24692469- case macio_intrepid:24702470- pmac_mb.model_id = PMAC_TYPE_UNKNOWN_INTREPID;24712471- pmac_mb.model_name = "Unknown Intrepid-based";24722472- pmac_mb.features = intrepid_features;24732473- break;24742474-#else /* CONFIG_POWER4 */24752475- case macio_keylargo2:24762476- pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2;24772477- pmac_mb.model_name = "Unknown G5";24782478- pmac_mb.features = g5_features;24792479- break;24802480-#endif /* CONFIG_POWER4 */24812481- default:24822482- return -ENODEV;24832483- }24842484-found:24852485-#ifndef CONFIG_POWER424862486- /* Fixup Hooper vs. Comet */24872487- if (pmac_mb.model_id == PMAC_TYPE_HOOPER) {24882488- u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4);24892489- if (!mach_id_ptr)24902490- return -ENODEV;24912491- /* Here, I used to disable the media-bay on comet. It24922492- * appears this is wrong, the floppy connector is actually24932493- * a kind of media-bay and works with the current driver.24942494- */24952495- if (__raw_readl(mach_id_ptr) & 0x20000000UL)24962496- pmac_mb.model_id = PMAC_TYPE_COMET;24972497- iounmap(mach_id_ptr);24982498- }24992499-#endif /* CONFIG_POWER4 */25002500-25012501-#ifdef CONFIG_6xx25022502- /* Set default value of powersave_nap on machines that support it.25032503- * It appears that uninorth rev 3 has a problem with it, we don't25042504- * enable it on those. In theory, the flush-on-lock property is25052505- * supposed to be set when not supported, but I'm not very confident25062506- * that all Apple OF revs did it properly, I do it the paranoid way.25072507- */25082508- while (uninorth_base && uninorth_rev > 3) {25092509- struct device_node* np = find_path_device("/cpus");25102510- if (!np || !np->child) {25112511- printk(KERN_WARNING "Can't find CPU(s) in device tree !\n");25122512- break;25132513- }25142514- np = np->child;25152515- /* Nap mode not supported on SMP */25162516- if (np->sibling)25172517- break;25182518- /* Nap mode not supported if flush-on-lock property is present */25192519- if (get_property(np, "flush-on-lock", NULL))25202520- break;25212521- powersave_nap = 1;25222522- printk(KERN_INFO "Processor NAP mode on idle enabled.\n");25232523- break;25242524- }25252525-25262526- /* On CPUs that support it (750FX), lowspeed by default during25272527- * NAP mode25282528- */25292529- powersave_lowspeed = 1;25302530-#endif /* CONFIG_6xx */25312531-#ifdef CONFIG_POWER425322532- powersave_nap = 1;25332533-#endif25342534- /* Check for "mobile" machine */25352535- if (model && (strncmp(model, "PowerBook", 9) == 025362536- || strncmp(model, "iBook", 5) == 0))25372537- pmac_mb.board_flags |= PMAC_MB_MOBILE;25382538-25392539-25402540- printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name);25412541- return 0;25422542-}25432543-25442544-/* Initialize the Core99 UniNorth host bridge and memory controller25452545- */25462546-static void __init25472547-probe_uninorth(void)25482548-{25492549- unsigned long actrl;25502550-25512551- /* Locate core99 Uni-N */25522552- uninorth_node = of_find_node_by_name(NULL, "uni-n");25532553- /* Locate G5 u3 */25542554- if (uninorth_node == NULL) {25552555- uninorth_node = of_find_node_by_name(NULL, "u3");25562556- uninorth_u3 = 1;25572557- }25582558- if (uninorth_node && uninorth_node->n_addrs > 0) {25592559- unsigned long address = uninorth_node->addrs[0].address;25602560- uninorth_base = ioremap(address, 0x40000);25612561- uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));25622562- if (uninorth_u3)25632563- u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000);25642564- } else25652565- uninorth_node = NULL;25662566-25672567- if (!uninorth_node)25682568- return;25692569-25702570- printk(KERN_INFO "Found %s memory controller & host bridge, revision: %d\n",25712571- uninorth_u3 ? "U3" : "UniNorth", uninorth_rev);25722572- printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base);25732573-25742574- /* Set the arbitrer QAck delay according to what Apple does25752575- */25762576- if (uninorth_rev < 0x11) {25772577- actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK;25782578- actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 :25792579- UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;25802580- UN_OUT(UNI_N_ARB_CTRL, actrl);25812581- }25822582-25832583- /* Some more magic as done by them in recent MacOS X on UniNorth25842584- * revs 1.5 to 2.O and Pangea. Seem to toggle the UniN Maxbus/PCI25852585- * memory timeout25862586- */25872587- if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) || uninorth_rev == 0xc0)25882588- UN_OUT(0x2160, UN_IN(0x2160) & 0x00ffffff);25892589-}25902590-25912591-static void __init25922592-probe_one_macio(const char* name, const char* compat, int type)25932593-{25942594- struct device_node* node;25952595- int i;25962596- volatile u32 __iomem * base;25972597- u32* revp;25982598-25992599- node = find_devices(name);26002600- if (!node || !node->n_addrs)26012601- return;26022602- if (compat)26032603- do {26042604- if (device_is_compatible(node, compat))26052605- break;26062606- node = node->next;26072607- } while (node);26082608- if (!node)26092609- return;26102610- for(i=0; i<MAX_MACIO_CHIPS; i++) {26112611- if (!macio_chips[i].of_node)26122612- break;26132613- if (macio_chips[i].of_node == node)26142614- return;26152615- }26162616- if (i >= MAX_MACIO_CHIPS) {26172617- printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n");26182618- printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name);26192619- return;26202620- }26212621- base = ioremap(node->addrs[0].address, node->addrs[0].size);26222622- if (!base) {26232623- printk(KERN_ERR "pmac_feature: Can't map mac-io chip !\n");26242624- return;26252625- }26262626- if (type == macio_keylargo) {26272627- u32* did = (u32 *)get_property(node, "device-id", NULL);26282628- if (*did == 0x00000025)26292629- type = macio_pangea;26302630- if (*did == 0x0000003e)26312631- type = macio_intrepid;26322632- }26332633- macio_chips[i].of_node = node;26342634- macio_chips[i].type = type;26352635- macio_chips[i].base = base;26362636- macio_chips[i].flags = MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON;26372637- macio_chips[i].name = macio_names[type];26382638- revp = (u32 *)get_property(node, "revision-id", NULL);26392639- if (revp)26402640- macio_chips[i].rev = *revp;26412641- printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n",26422642- macio_names[type], macio_chips[i].rev, macio_chips[i].base);26432643-}26442644-26452645-static int __init26462646-probe_macios(void)26472647-{26482648- /* Warning, ordering is important */26492649- probe_one_macio("gc", NULL, macio_grand_central);26502650- probe_one_macio("ohare", NULL, macio_ohare);26512651- probe_one_macio("pci106b,7", NULL, macio_ohareII);26522652- probe_one_macio("mac-io", "keylargo", macio_keylargo);26532653- probe_one_macio("mac-io", "paddington", macio_paddington);26542654- probe_one_macio("mac-io", "gatwick", macio_gatwick);26552655- probe_one_macio("mac-io", "heathrow", macio_heathrow);26562656- probe_one_macio("mac-io", "K2-Keylargo", macio_keylargo2);26572657-26582658- /* Make sure the "main" macio chip appear first */26592659- if (macio_chips[0].type == macio_gatwick26602660- && macio_chips[1].type == macio_heathrow) {26612661- struct macio_chip temp = macio_chips[0];26622662- macio_chips[0] = macio_chips[1];26632663- macio_chips[1] = temp;26642664- }26652665- if (macio_chips[0].type == macio_ohareII26662666- && macio_chips[1].type == macio_ohare) {26672667- struct macio_chip temp = macio_chips[0];26682668- macio_chips[0] = macio_chips[1];26692669- macio_chips[1] = temp;26702670- }26712671- macio_chips[0].lbus.index = 0;26722672- macio_chips[1].lbus.index = 1;26732673-26742674- return (macio_chips[0].of_node == NULL) ? -ENODEV : 0;26752675-}26762676-26772677-static void __init26782678-initial_serial_shutdown(struct device_node* np)26792679-{26802680- int len;26812681- struct slot_names_prop {26822682- int count;26832683- char name[1];26842684- } *slots;26852685- char *conn;26862686- int port_type = PMAC_SCC_ASYNC;26872687- int modem = 0;26882688-26892689- slots = (struct slot_names_prop *)get_property(np, "slot-names", &len);26902690- conn = get_property(np, "AAPL,connector", &len);26912691- if (conn && (strcmp(conn, "infrared") == 0))26922692- port_type = PMAC_SCC_IRDA;26932693- else if (device_is_compatible(np, "cobalt"))26942694- modem = 1;26952695- else if (slots && slots->count > 0) {26962696- if (strcmp(slots->name, "IrDA") == 0)26972697- port_type = PMAC_SCC_IRDA;26982698- else if (strcmp(slots->name, "Modem") == 0)26992699- modem = 1;27002700- }27012701- if (modem)27022702- pmac_call_feature(PMAC_FTR_MODEM_ENABLE, np, 0, 0);27032703- pmac_call_feature(PMAC_FTR_SCC_ENABLE, np, port_type, 0);27042704-}27052705-27062706-static void __init27072707-set_initial_features(void)27082708-{27092709- struct device_node* np;27102710-27112711- /* That hack appears to be necessary for some StarMax motherboards27122712- * but I'm not too sure it was audited for side-effects on other27132713- * ohare based machines...27142714- * Since I still have difficulties figuring the right way to27152715- * differenciate them all and since that hack was there for a long27162716- * time, I'll keep it around27172717- */27182718- if (macio_chips[0].type == macio_ohare && !find_devices("via-pmu")) {27192719- struct macio_chip* macio = &macio_chips[0];27202720- MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES);27212721- } else if (macio_chips[0].type == macio_ohare) {27222722- struct macio_chip* macio = &macio_chips[0];27232723- MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);27242724- } else if (macio_chips[1].type == macio_ohare) {27252725- struct macio_chip* macio = &macio_chips[1];27262726- MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);27272727- }27282728-27292729-#ifdef CONFIG_POWER427302730- if (macio_chips[0].type == macio_keylargo2) {27312731-#ifndef CONFIG_SMP27322732- /* On SMP machines running UP, we have the second CPU eating27332733- * bus cycles. We need to take it off the bus. This is done27342734- * from pmac_smp for SMP kernels running on one CPU27352735- */27362736- np = of_find_node_by_type(NULL, "cpu");27372737- if (np != NULL)27382738- np = of_find_node_by_type(np, "cpu");27392739- if (np != NULL) {27402740- g5_phy_disable_cpu1();27412741- of_node_put(np);27422742- }27432743-#endif /* CONFIG_SMP */27442744- /* Enable GMAC for now for PCI probing. It will be disabled27452745- * later on after PCI probe27462746- */27472747- np = of_find_node_by_name(NULL, "ethernet");27482748- while(np) {27492749- if (device_is_compatible(np, "K2-GMAC"))27502750- g5_gmac_enable(np, 0, 1);27512751- np = of_find_node_by_name(np, "ethernet");27522752- }27532753-27542754- /* Enable FW before PCI probe. Will be disabled later on27552755- * Note: We should have a batter way to check that we are27562756- * dealing with uninorth internal cell and not a PCI cell27572757- * on the external PCI. The code below works though.27582758- */27592759- np = of_find_node_by_name(NULL, "firewire");27602760- while(np) {27612761- if (device_is_compatible(np, "pci106b,5811")) {27622762- macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;27632763- g5_fw_enable(np, 0, 1);27642764- }27652765- np = of_find_node_by_name(np, "firewire");27662766- }27672767- }27682768-#else /* CONFIG_POWER4 */27692769-27702770- if (macio_chips[0].type == macio_keylargo ||27712771- macio_chips[0].type == macio_pangea ||27722772- macio_chips[0].type == macio_intrepid) {27732773- /* Enable GMAC for now for PCI probing. It will be disabled27742774- * later on after PCI probe27752775- */27762776- np = of_find_node_by_name(NULL, "ethernet");27772777- while(np) {27782778- if (np->parent27792779- && device_is_compatible(np->parent, "uni-north")27802780- && device_is_compatible(np, "gmac"))27812781- core99_gmac_enable(np, 0, 1);27822782- np = of_find_node_by_name(np, "ethernet");27832783- }27842784-27852785- /* Enable FW before PCI probe. Will be disabled later on27862786- * Note: We should have a batter way to check that we are27872787- * dealing with uninorth internal cell and not a PCI cell27882788- * on the external PCI. The code below works though.27892789- */27902790- np = of_find_node_by_name(NULL, "firewire");27912791- while(np) {27922792- if (np->parent27932793- && device_is_compatible(np->parent, "uni-north")27942794- && (device_is_compatible(np, "pci106b,18") ||27952795- device_is_compatible(np, "pci106b,30") ||27962796- device_is_compatible(np, "pci11c1,5811"))) {27972797- macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;27982798- core99_firewire_enable(np, 0, 1);27992799- }28002800- np = of_find_node_by_name(np, "firewire");28012801- }28022802-28032803- /* Enable ATA-100 before PCI probe. */28042804- np = of_find_node_by_name(NULL, "ata-6");28052805- while(np) {28062806- if (np->parent28072807- && device_is_compatible(np->parent, "uni-north")28082808- && device_is_compatible(np, "kauai-ata")) {28092809- core99_ata100_enable(np, 1);28102810- }28112811- np = of_find_node_by_name(np, "ata-6");28122812- }28132813-28142814- /* Switch airport off */28152815- np = find_devices("radio");28162816- while(np) {28172817- if (np && np->parent == macio_chips[0].of_node) {28182818- macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON;28192819- core99_airport_enable(np, 0, 0);28202820- }28212821- np = np->next;28222822- }28232823- }28242824-28252825- /* On all machines that support sound PM, switch sound off */28262826- if (macio_chips[0].of_node)28272827- pmac_do_feature_call(PMAC_FTR_SOUND_CHIP_ENABLE,28282828- macio_chips[0].of_node, 0, 0);28292829-28302830- /* While on some desktop G3s, we turn it back on */28312831- if (macio_chips[0].of_node && macio_chips[0].type == macio_heathrow28322832- && (pmac_mb.model_id == PMAC_TYPE_GOSSAMER ||28332833- pmac_mb.model_id == PMAC_TYPE_SILK)) {28342834- struct macio_chip* macio = &macio_chips[0];28352835- MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);28362836- MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);28372837- }28382838-28392839- /* Some machine models need the clock chip to be properly setup for28402840- * clock spreading now. This should be a platform function but we28412841- * don't do these at the moment28422842- */28432843- pmac_tweak_clock_spreading(1);28442844-28452845-#endif /* CONFIG_POWER4 */28462846-28472847- /* On all machines, switch modem & serial ports off */28482848- np = find_devices("ch-a");28492849- while(np) {28502850- initial_serial_shutdown(np);28512851- np = np->next;28522852- }28532853- np = find_devices("ch-b");28542854- while(np) {28552855- initial_serial_shutdown(np);28562856- np = np->next;28572857- }28582858-}28592859-28602860-void __init28612861-pmac_feature_init(void)28622862-{28632863- /* Detect the UniNorth memory controller */28642864- probe_uninorth();28652865-28662866- /* Probe mac-io controllers */28672867- if (probe_macios()) {28682868- printk(KERN_WARNING "No mac-io chip found\n");28692869- return;28702870- }28712871-28722872- /* Setup low-level i2c stuffs */28732873- pmac_init_low_i2c();28742874-28752875- /* Probe machine type */28762876- if (probe_motherboard())28772877- printk(KERN_WARNING "Unknown PowerMac !\n");28782878-28792879- /* Set some initial features (turn off some chips that will28802880- * be later turned on)28812881- */28822882- set_initial_features();28832883-}28842884-28852885-int __init28862886-pmac_feature_late_init(void)28872887-{28882888- struct device_node* np;28892889-28902890- /* Request some resources late */28912891- if (uninorth_node)28922892- request_OF_resource(uninorth_node, 0, NULL);28932893- np = find_devices("hammerhead");28942894- if (np)28952895- request_OF_resource(np, 0, NULL);28962896- np = find_devices("interrupt-controller");28972897- if (np)28982898- request_OF_resource(np, 0, NULL);28992899- return 0;29002900-}29012901-29022902-device_initcall(pmac_feature_late_init);29032903-29042904-#ifdef CONFIG_POWER429052905-29062906-static void dump_HT_speeds(char *name, u32 cfg, u32 frq)29072907-{29082908- int freqs[16] = { 200,300,400,500,600,800,1000,0,0,0,0,0,0,0,0,0 };29092909- int bits[8] = { 8,16,0,32,2,4,0,0 };29102910- int freq = (frq >> 8) & 0xf;29112911-29122912- if (freqs[freq] == 0)29132913- printk("%s: Unknown HT link frequency %x\n", name, freq);29142914- else29152915- printk("%s: %d MHz on main link, (%d in / %d out) bits width\n",29162916- name, freqs[freq],29172917- bits[(cfg >> 28) & 0x7], bits[(cfg >> 24) & 0x7]);29182918-}29192919-29202920-void __init pmac_check_ht_link(void)29212921-{29222922- u32 ufreq, freq, ucfg, cfg;29232923- struct device_node *pcix_node;29242924- u8 px_bus, px_devfn;29252925- struct pci_controller *px_hose;29262926-29272927- (void)in_be32(u3_ht + U3_HT_LINK_COMMAND);29282928- ucfg = cfg = in_be32(u3_ht + U3_HT_LINK_CONFIG);29292929- ufreq = freq = in_be32(u3_ht + U3_HT_LINK_FREQ);29302930- dump_HT_speeds("U3 HyperTransport", cfg, freq);29312931-29322932- pcix_node = of_find_compatible_node(NULL, "pci", "pci-x");29332933- if (pcix_node == NULL) {29342934- printk("No PCI-X bridge found\n");29352935- return;29362936- }29372937- if (pci_device_from_OF_node(pcix_node, &px_bus, &px_devfn) != 0) {29382938- printk("PCI-X bridge found but not matched to pci\n");29392939- return;29402940- }29412941- px_hose = pci_find_hose_for_OF_device(pcix_node);29422942- if (px_hose == NULL) {29432943- printk("PCI-X bridge found but not matched to host\n");29442944- return;29452945- } 29462946- early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg);29472947- early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq);29482948- dump_HT_speeds("PCI-X HT Uplink", cfg, freq);29492949- early_read_config_dword(px_hose, px_bus, px_devfn, 0xc8, &cfg);29502950- early_read_config_dword(px_hose, px_bus, px_devfn, 0xd0, &freq);29512951- dump_HT_speeds("PCI-X HT Downlink", cfg, freq);29522952-}29532953-29542954-#endif /* CONFIG_POWER4 */29552955-29562956-/*29572957- * Early video resume hook29582958- */29592959-29602960-static void (*pmac_early_vresume_proc)(void *data);29612961-static void *pmac_early_vresume_data;29622962-29632963-void pmac_set_early_video_resume(void (*proc)(void *data), void *data)29642964-{29652965- if (_machine != _MACH_Pmac)29662966- return;29672967- preempt_disable();29682968- pmac_early_vresume_proc = proc;29692969- pmac_early_vresume_data = data;29702970- preempt_enable();29712971-}29722972-EXPORT_SYMBOL(pmac_set_early_video_resume);29732973-29742974-void pmac_call_early_video_resume(void)29752975-{29762976- if (pmac_early_vresume_proc)29772977- pmac_early_vresume_proc(pmac_early_vresume_data);29782978-}29792979-29802980-/*29812981- * AGP related suspend/resume code29822982- */29832983-29842984-static struct pci_dev *pmac_agp_bridge;29852985-static int (*pmac_agp_suspend)(struct pci_dev *bridge);29862986-static int (*pmac_agp_resume)(struct pci_dev *bridge);29872987-29882988-void pmac_register_agp_pm(struct pci_dev *bridge,29892989- int (*suspend)(struct pci_dev *bridge),29902990- int (*resume)(struct pci_dev *bridge))29912991-{29922992- if (suspend || resume) {29932993- pmac_agp_bridge = bridge;29942994- pmac_agp_suspend = suspend;29952995- pmac_agp_resume = resume;29962996- return;29972997- }29982998- if (bridge != pmac_agp_bridge)29992999- return;30003000- pmac_agp_suspend = pmac_agp_resume = NULL;30013001- return;30023002-}30033003-EXPORT_SYMBOL(pmac_register_agp_pm);30043004-30053005-void pmac_suspend_agp_for_card(struct pci_dev *dev)30063006-{30073007- if (pmac_agp_bridge == NULL || pmac_agp_suspend == NULL)30083008- return;30093009- if (pmac_agp_bridge->bus != dev->bus)30103010- return;30113011- pmac_agp_suspend(pmac_agp_bridge);30123012-}30133013-EXPORT_SYMBOL(pmac_suspend_agp_for_card);30143014-30153015-void pmac_resume_agp_for_card(struct pci_dev *dev)30163016-{30173017- if (pmac_agp_bridge == NULL || pmac_agp_resume == NULL)30183018- return;30193019- if (pmac_agp_bridge->bus != dev->bus)30203020- return;30213021- pmac_agp_resume(pmac_agp_bridge);30223022-}30233023-EXPORT_SYMBOL(pmac_resume_agp_for_card);
-511
arch/ppc/platforms/pmac_low_i2c.c
···11-/*22- * arch/ppc/platforms/pmac_low_i2c.c33- *44- * Copyright (C) 2003 Ben. Herrenschmidt (benh@kernel.crashing.org)55- *66- * This program is free software; you can redistribute it and/or77- * modify it under the terms of the GNU General Public License88- * as published by the Free Software Foundation; either version99- * 2 of the License, or (at your option) any later version.1010- *1111- * This file contains some low-level i2c access routines that1212- * need to be used by various bits of the PowerMac platform code1313- * at times where the real asynchronous & interrupt driven driver1414- * cannot be used. The API borrows some semantics from the darwin1515- * driver in order to ease the implementation of the platform1616- * properties parser1717- */1818-1919-#include <linux/config.h>2020-#include <linux/types.h>2121-#include <linux/delay.h>2222-#include <linux/sched.h>2323-#include <linux/init.h>2424-#include <linux/module.h>2525-#include <linux/adb.h>2626-#include <linux/pmu.h>2727-#include <asm/keylargo.h>2828-#include <asm/uninorth.h>2929-#include <asm/io.h>3030-#include <asm/prom.h>3131-#include <asm/machdep.h>3232-#include <asm/pmac_low_i2c.h>3333-3434-#define MAX_LOW_I2C_HOST 43535-3636-#if 13737-#define DBG(x...) do {\3838- printk(KERN_DEBUG "KW:" x); \3939- } while(0)4040-#else4141-#define DBGG(x...)4242-#endif4343-4444-struct low_i2c_host;4545-4646-typedef int (*low_i2c_func_t)(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len);4747-4848-struct low_i2c_host4949-{5050- struct device_node *np; /* OF device node */5151- struct semaphore mutex; /* Access mutex for use by i2c-keywest */5252- low_i2c_func_t func; /* Access function */5353- int is_open : 1; /* Poor man's access control */5454- int mode; /* Current mode */5555- int channel; /* Current channel */5656- int num_channels; /* Number of channels */5757- void __iomem * base; /* For keywest-i2c, base address */5858- int bsteps; /* And register stepping */5959- int speed; /* And speed */6060-};6161-6262-static struct low_i2c_host low_i2c_hosts[MAX_LOW_I2C_HOST];6363-6464-/* No locking is necessary on allocation, we are running way before6565- * anything can race with us6666- */6767-static struct low_i2c_host *find_low_i2c_host(struct device_node *np)6868-{6969- int i;7070-7171- for (i = 0; i < MAX_LOW_I2C_HOST; i++)7272- if (low_i2c_hosts[i].np == np)7373- return &low_i2c_hosts[i];7474- return NULL;7575-}7676-7777-/*7878- *7979- * i2c-keywest implementation (UniNorth, U2, U3, Keylargo's)8080- *8181- */8282-8383-/*8484- * Keywest i2c definitions borrowed from drivers/i2c/i2c-keywest.h,8585- * should be moved somewhere in include/asm-ppc/8686- */8787-/* Register indices */8888-typedef enum {8989- reg_mode = 0,9090- reg_control,9191- reg_status,9292- reg_isr,9393- reg_ier,9494- reg_addr,9595- reg_subaddr,9696- reg_data9797-} reg_t;9898-9999-100100-/* Mode register */101101-#define KW_I2C_MODE_100KHZ 0x00102102-#define KW_I2C_MODE_50KHZ 0x01103103-#define KW_I2C_MODE_25KHZ 0x02104104-#define KW_I2C_MODE_DUMB 0x00105105-#define KW_I2C_MODE_STANDARD 0x04106106-#define KW_I2C_MODE_STANDARDSUB 0x08107107-#define KW_I2C_MODE_COMBINED 0x0C108108-#define KW_I2C_MODE_MODE_MASK 0x0C109109-#define KW_I2C_MODE_CHAN_MASK 0xF0110110-111111-/* Control register */112112-#define KW_I2C_CTL_AAK 0x01113113-#define KW_I2C_CTL_XADDR 0x02114114-#define KW_I2C_CTL_STOP 0x04115115-#define KW_I2C_CTL_START 0x08116116-117117-/* Status register */118118-#define KW_I2C_STAT_BUSY 0x01119119-#define KW_I2C_STAT_LAST_AAK 0x02120120-#define KW_I2C_STAT_LAST_RW 0x04121121-#define KW_I2C_STAT_SDA 0x08122122-#define KW_I2C_STAT_SCL 0x10123123-124124-/* IER & ISR registers */125125-#define KW_I2C_IRQ_DATA 0x01126126-#define KW_I2C_IRQ_ADDR 0x02127127-#define KW_I2C_IRQ_STOP 0x04128128-#define KW_I2C_IRQ_START 0x08129129-#define KW_I2C_IRQ_MASK 0x0F130130-131131-/* State machine states */132132-enum {133133- state_idle,134134- state_addr,135135- state_read,136136- state_write,137137- state_stop,138138- state_dead139139-};140140-141141-#define WRONG_STATE(name) do {\142142- printk(KERN_DEBUG "KW: wrong state. Got %s, state: %s (isr: %02x)\n", \143143- name, __kw_state_names[state], isr); \144144- } while(0)145145-146146-static const char *__kw_state_names[] = {147147- "state_idle",148148- "state_addr",149149- "state_read",150150- "state_write",151151- "state_stop",152152- "state_dead"153153-};154154-155155-static inline u8 __kw_read_reg(struct low_i2c_host *host, reg_t reg)156156-{157157- return in_8(host->base + (((unsigned)reg) << host->bsteps));158158-}159159-160160-static inline void __kw_write_reg(struct low_i2c_host *host, reg_t reg, u8 val)161161-{162162- out_8(host->base + (((unsigned)reg) << host->bsteps), val);163163- (void)__kw_read_reg(host, reg_subaddr);164164-}165165-166166-#define kw_write_reg(reg, val) __kw_write_reg(host, reg, val) 167167-#define kw_read_reg(reg) __kw_read_reg(host, reg) 168168-169169-170170-/* Don't schedule, the g5 fan controller is too171171- * timing sensitive172172- */173173-static u8 kw_wait_interrupt(struct low_i2c_host* host)174174-{175175- int i;176176- u8 isr;177177-178178- for (i = 0; i < 200000; i++) {179179- isr = kw_read_reg(reg_isr) & KW_I2C_IRQ_MASK;180180- if (isr != 0)181181- return isr;182182- udelay(1);183183- }184184- return isr;185185-}186186-187187-static int kw_handle_interrupt(struct low_i2c_host *host, int state, int rw, int *rc, u8 **data, int *len, u8 isr)188188-{189189- u8 ack;190190-191191- if (isr == 0) {192192- if (state != state_stop) {193193- DBG("KW: Timeout !\n");194194- *rc = -EIO;195195- goto stop;196196- }197197- if (state == state_stop) {198198- ack = kw_read_reg(reg_status);199199- if (!(ack & KW_I2C_STAT_BUSY)) {200200- state = state_idle;201201- kw_write_reg(reg_ier, 0x00);202202- }203203- }204204- return state;205205- }206206-207207- if (isr & KW_I2C_IRQ_ADDR) {208208- ack = kw_read_reg(reg_status);209209- if (state != state_addr) {210210- kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);211211- WRONG_STATE("KW_I2C_IRQ_ADDR"); 212212- *rc = -EIO;213213- goto stop;214214- }215215- if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { 216216- *rc = -ENODEV;217217- DBG("KW: NAK on address\n");218218- return state_stop; 219219- } else {220220- if (rw) {221221- state = state_read;222222- if (*len > 1)223223- kw_write_reg(reg_control, KW_I2C_CTL_AAK);224224- } else {225225- state = state_write;226226- kw_write_reg(reg_data, **data);227227- (*data)++; (*len)--;228228- }229229- }230230- kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);231231- }232232-233233- if (isr & KW_I2C_IRQ_DATA) {234234- if (state == state_read) {235235- **data = kw_read_reg(reg_data);236236- (*data)++; (*len)--;237237- kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);238238- if ((*len) == 0)239239- state = state_stop;240240- else if ((*len) == 1)241241- kw_write_reg(reg_control, 0);242242- } else if (state == state_write) {243243- ack = kw_read_reg(reg_status);244244- if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {245245- DBG("KW: nack on data write\n");246246- *rc = -EIO;247247- goto stop;248248- } else if (*len) {249249- kw_write_reg(reg_data, **data);250250- (*data)++; (*len)--;251251- } else {252252- kw_write_reg(reg_control, KW_I2C_CTL_STOP);253253- state = state_stop;254254- *rc = 0;255255- }256256- kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);257257- } else {258258- kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);259259- WRONG_STATE("KW_I2C_IRQ_DATA"); 260260- if (state != state_stop) {261261- *rc = -EIO;262262- goto stop;263263- }264264- }265265- }266266-267267- if (isr & KW_I2C_IRQ_STOP) {268268- kw_write_reg(reg_isr, KW_I2C_IRQ_STOP);269269- if (state != state_stop) {270270- WRONG_STATE("KW_I2C_IRQ_STOP");271271- *rc = -EIO;272272- }273273- return state_idle;274274- }275275-276276- if (isr & KW_I2C_IRQ_START)277277- kw_write_reg(reg_isr, KW_I2C_IRQ_START);278278-279279- return state;280280-281281- stop:282282- kw_write_reg(reg_control, KW_I2C_CTL_STOP); 283283- return state_stop;284284-}285285-286286-static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr, u8 *data, int len)287287-{288288- u8 mode_reg = host->speed;289289- int state = state_addr;290290- int rc = 0;291291-292292- /* Setup mode & subaddress if any */293293- switch(host->mode) {294294- case pmac_low_i2c_mode_dumb:295295- printk(KERN_ERR "low_i2c: Dumb mode not supported !\n");296296- return -EINVAL;297297- case pmac_low_i2c_mode_std:298298- mode_reg |= KW_I2C_MODE_STANDARD;299299- break;300300- case pmac_low_i2c_mode_stdsub:301301- mode_reg |= KW_I2C_MODE_STANDARDSUB;302302- kw_write_reg(reg_subaddr, subaddr);303303- break;304304- case pmac_low_i2c_mode_combined:305305- mode_reg |= KW_I2C_MODE_COMBINED;306306- kw_write_reg(reg_subaddr, subaddr);307307- break;308308- }309309-310310- /* Setup channel & clear pending irqs */311311- kw_write_reg(reg_isr, kw_read_reg(reg_isr));312312- kw_write_reg(reg_mode, mode_reg | (host->channel << 4));313313- kw_write_reg(reg_status, 0);314314-315315- /* Set up address and r/w bit */316316- kw_write_reg(reg_addr, addr);317317-318318- /* Start sending address & disable interrupt*/319319- kw_write_reg(reg_ier, 0 /*KW_I2C_IRQ_MASK*/);320320- kw_write_reg(reg_control, KW_I2C_CTL_XADDR);321321-322322- /* State machine, to turn into an interrupt handler */323323- while(state != state_idle) {324324- u8 isr = kw_wait_interrupt(host);325325- state = kw_handle_interrupt(host, state, addr & 1, &rc, &data, &len, isr);326326- }327327-328328- return rc;329329-}330330-331331-static void keywest_low_i2c_add(struct device_node *np)332332-{333333- struct low_i2c_host *host = find_low_i2c_host(NULL);334334- unsigned long *psteps, *prate, steps, aoffset = 0;335335- struct device_node *parent;336336-337337- if (host == NULL) {338338- printk(KERN_ERR "low_i2c: Can't allocate host for %s\n",339339- np->full_name);340340- return;341341- }342342- memset(host, 0, sizeof(*host));343343-344344- init_MUTEX(&host->mutex);345345- host->np = of_node_get(np); 346346- psteps = (unsigned long *)get_property(np, "AAPL,address-step", NULL);347347- steps = psteps ? (*psteps) : 0x10;348348- for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++)349349- steps >>= 1;350350- parent = of_get_parent(np);351351- host->num_channels = 1;352352- if (parent && parent->name[0] == 'u') {353353- host->num_channels = 2;354354- aoffset = 3;355355- }356356- /* Select interface rate */357357- host->speed = KW_I2C_MODE_100KHZ;358358- prate = (unsigned long *)get_property(np, "AAPL,i2c-rate", NULL);359359- if (prate) switch(*prate) {360360- case 100:361361- host->speed = KW_I2C_MODE_100KHZ;362362- break;363363- case 50:364364- host->speed = KW_I2C_MODE_50KHZ;365365- break;366366- case 25:367367- host->speed = KW_I2C_MODE_25KHZ;368368- break;369369- } 370370- host->mode = pmac_low_i2c_mode_std;371371- host->base = ioremap(np->addrs[0].address + aoffset,372372- np->addrs[0].size);373373- host->func = keywest_low_i2c_func;374374-}375375-376376-/*377377- *378378- * PMU implementation379379- *380380- */381381-382382-383383-#ifdef CONFIG_ADB_PMU384384-385385-static int pmu_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len)386386-{387387- // TODO388388- return -ENODEV;389389-}390390-391391-static void pmu_low_i2c_add(struct device_node *np)392392-{393393- struct low_i2c_host *host = find_low_i2c_host(NULL);394394-395395- if (host == NULL) {396396- printk(KERN_ERR "low_i2c: Can't allocate host for %s\n",397397- np->full_name);398398- return;399399- }400400- memset(host, 0, sizeof(*host));401401-402402- init_MUTEX(&host->mutex);403403- host->np = of_node_get(np); 404404- host->num_channels = 3;405405- host->mode = pmac_low_i2c_mode_std;406406- host->func = pmu_low_i2c_func;407407-}408408-409409-#endif /* CONFIG_ADB_PMU */410410-411411-void __init pmac_init_low_i2c(void)412412-{413413- struct device_node *np;414414-415415- /* Probe keywest-i2c busses */416416- np = of_find_compatible_node(NULL, "i2c", "keywest-i2c");417417- while(np) {418418- keywest_low_i2c_add(np);419419- np = of_find_compatible_node(np, "i2c", "keywest-i2c");420420- }421421-422422-#ifdef CONFIG_ADB_PMU423423- /* Probe PMU busses */424424- np = of_find_node_by_name(NULL, "via-pmu");425425- if (np)426426- pmu_low_i2c_add(np);427427-#endif /* CONFIG_ADB_PMU */428428-429429- /* TODO: Add CUDA support as well */430430-}431431-432432-int pmac_low_i2c_lock(struct device_node *np)433433-{434434- struct low_i2c_host *host = find_low_i2c_host(np);435435-436436- if (!host)437437- return -ENODEV;438438- down(&host->mutex);439439- return 0;440440-}441441-EXPORT_SYMBOL(pmac_low_i2c_lock);442442-443443-int pmac_low_i2c_unlock(struct device_node *np)444444-{445445- struct low_i2c_host *host = find_low_i2c_host(np);446446-447447- if (!host)448448- return -ENODEV;449449- up(&host->mutex);450450- return 0;451451-}452452-EXPORT_SYMBOL(pmac_low_i2c_unlock);453453-454454-455455-int pmac_low_i2c_open(struct device_node *np, int channel)456456-{457457- struct low_i2c_host *host = find_low_i2c_host(np);458458-459459- if (!host)460460- return -ENODEV;461461-462462- if (channel >= host->num_channels)463463- return -EINVAL;464464-465465- down(&host->mutex);466466- host->is_open = 1;467467- host->channel = channel;468468-469469- return 0;470470-}471471-EXPORT_SYMBOL(pmac_low_i2c_open);472472-473473-int pmac_low_i2c_close(struct device_node *np)474474-{475475- struct low_i2c_host *host = find_low_i2c_host(np);476476-477477- if (!host)478478- return -ENODEV;479479-480480- host->is_open = 0;481481- up(&host->mutex);482482-483483- return 0;484484-}485485-EXPORT_SYMBOL(pmac_low_i2c_close);486486-487487-int pmac_low_i2c_setmode(struct device_node *np, int mode)488488-{489489- struct low_i2c_host *host = find_low_i2c_host(np);490490-491491- if (!host)492492- return -ENODEV;493493- WARN_ON(!host->is_open);494494- host->mode = mode;495495-496496- return 0;497497-}498498-EXPORT_SYMBOL(pmac_low_i2c_setmode);499499-500500-int pmac_low_i2c_xfer(struct device_node *np, u8 addrdir, u8 subaddr, u8 *data, int len)501501-{502502- struct low_i2c_host *host = find_low_i2c_host(np);503503-504504- if (!host)505505- return -ENODEV;506506- WARN_ON(!host->is_open);507507-508508- return host->func(host, addrdir, subaddr, data, len);509509-}510510-EXPORT_SYMBOL(pmac_low_i2c_xfer);511511-
-584
arch/ppc/platforms/pmac_nvram.c
···11-/*22- * arch/ppc/platforms/pmac_nvram.c33- *44- * Copyright (C) 2002 Benjamin Herrenschmidt (benh@kernel.crashing.org)55- *66- * This program is free software; you can redistribute it and/or77- * modify it under the terms of the GNU General Public License88- * as published by the Free Software Foundation; either version99- * 2 of the License, or (at your option) any later version.1010- *1111- * Todo: - add support for the OF persistent properties1212- */1313-#include <linux/config.h>1414-#include <linux/module.h>1515-#include <linux/kernel.h>1616-#include <linux/stddef.h>1717-#include <linux/string.h>1818-#include <linux/nvram.h>1919-#include <linux/init.h>2020-#include <linux/slab.h>2121-#include <linux/delay.h>2222-#include <linux/errno.h>2323-#include <linux/adb.h>2424-#include <linux/pmu.h>2525-#include <linux/bootmem.h>2626-#include <linux/completion.h>2727-#include <linux/spinlock.h>2828-#include <asm/sections.h>2929-#include <asm/io.h>3030-#include <asm/system.h>3131-#include <asm/prom.h>3232-#include <asm/machdep.h>3333-#include <asm/nvram.h>3434-3535-#define DEBUG3636-3737-#ifdef DEBUG3838-#define DBG(x...) printk(x)3939-#else4040-#define DBG(x...)4141-#endif4242-4343-#define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */4444-4545-#define CORE99_SIGNATURE 0x5a4646-#define CORE99_ADLER_START 0x144747-4848-/* On Core99, nvram is either a sharp, a micron or an AMD flash */4949-#define SM_FLASH_STATUS_DONE 0x805050-#define SM_FLASH_STATUS_ERR 0x385151-#define SM_FLASH_CMD_ERASE_CONFIRM 0xd05252-#define SM_FLASH_CMD_ERASE_SETUP 0x205353-#define SM_FLASH_CMD_RESET 0xff5454-#define SM_FLASH_CMD_WRITE_SETUP 0x405555-#define SM_FLASH_CMD_CLEAR_STATUS 0x505656-#define SM_FLASH_CMD_READ_STATUS 0x705757-5858-/* CHRP NVRAM header */5959-struct chrp_header {6060- u8 signature;6161- u8 cksum;6262- u16 len;6363- char name[12];6464- u8 data[0];6565-};6666-6767-struct core99_header {6868- struct chrp_header hdr;6969- u32 adler;7070- u32 generation;7171- u32 reserved[2];7272-};7373-7474-/*7575- * Read and write the non-volatile RAM on PowerMacs and CHRP machines.7676- */7777-static int nvram_naddrs;7878-static volatile unsigned char *nvram_addr;7979-static volatile unsigned char *nvram_data;8080-static int nvram_mult, is_core_99;8181-static int core99_bank = 0;8282-static int nvram_partitions[3];8383-static DEFINE_SPINLOCK(nv_lock);8484-8585-extern int pmac_newworld;8686-extern int system_running;8787-8888-static int (*core99_write_bank)(int bank, u8* datas);8989-static int (*core99_erase_bank)(int bank);9090-9191-static char *nvram_image;9292-9393-9494-static unsigned char core99_nvram_read_byte(int addr)9595-{9696- if (nvram_image == NULL)9797- return 0xff;9898- return nvram_image[addr];9999-}100100-101101-static void core99_nvram_write_byte(int addr, unsigned char val)102102-{103103- if (nvram_image == NULL)104104- return;105105- nvram_image[addr] = val;106106-}107107-108108-109109-static unsigned char direct_nvram_read_byte(int addr)110110-{111111- return in_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult]);112112-}113113-114114-static void direct_nvram_write_byte(int addr, unsigned char val)115115-{116116- out_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult], val);117117-}118118-119119-120120-static unsigned char indirect_nvram_read_byte(int addr)121121-{122122- unsigned char val;123123- unsigned long flags;124124-125125- spin_lock_irqsave(&nv_lock, flags);126126- out_8(nvram_addr, addr >> 5);127127- val = in_8(&nvram_data[(addr & 0x1f) << 4]);128128- spin_unlock_irqrestore(&nv_lock, flags);129129-130130- return val;131131-}132132-133133-static void indirect_nvram_write_byte(int addr, unsigned char val)134134-{135135- unsigned long flags;136136-137137- spin_lock_irqsave(&nv_lock, flags);138138- out_8(nvram_addr, addr >> 5);139139- out_8(&nvram_data[(addr & 0x1f) << 4], val);140140- spin_unlock_irqrestore(&nv_lock, flags);141141-}142142-143143-144144-#ifdef CONFIG_ADB_PMU145145-146146-static void pmu_nvram_complete(struct adb_request *req)147147-{148148- if (req->arg)149149- complete((struct completion *)req->arg);150150-}151151-152152-static unsigned char pmu_nvram_read_byte(int addr)153153-{154154- struct adb_request req;155155- DECLARE_COMPLETION(req_complete); 156156-157157- req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;158158- if (pmu_request(&req, pmu_nvram_complete, 3, PMU_READ_NVRAM,159159- (addr >> 8) & 0xff, addr & 0xff))160160- return 0xff;161161- if (system_state == SYSTEM_RUNNING)162162- wait_for_completion(&req_complete);163163- while (!req.complete)164164- pmu_poll();165165- return req.reply[0];166166-}167167-168168-static void pmu_nvram_write_byte(int addr, unsigned char val)169169-{170170- struct adb_request req;171171- DECLARE_COMPLETION(req_complete); 172172-173173- req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;174174- if (pmu_request(&req, pmu_nvram_complete, 4, PMU_WRITE_NVRAM,175175- (addr >> 8) & 0xff, addr & 0xff, val))176176- return;177177- if (system_state == SYSTEM_RUNNING)178178- wait_for_completion(&req_complete);179179- while (!req.complete)180180- pmu_poll();181181-}182182-183183-#endif /* CONFIG_ADB_PMU */184184-185185-186186-static u8 chrp_checksum(struct chrp_header* hdr)187187-{188188- u8 *ptr;189189- u16 sum = hdr->signature;190190- for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++)191191- sum += *ptr;192192- while (sum > 0xFF)193193- sum = (sum & 0xFF) + (sum>>8);194194- return sum;195195-}196196-197197-static u32 core99_calc_adler(u8 *buffer)198198-{199199- int cnt;200200- u32 low, high;201201-202202- buffer += CORE99_ADLER_START;203203- low = 1;204204- high = 0;205205- for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) {206206- if ((cnt % 5000) == 0) {207207- high %= 65521UL;208208- high %= 65521UL;209209- }210210- low += buffer[cnt];211211- high += low;212212- }213213- low %= 65521UL;214214- high %= 65521UL;215215-216216- return (high << 16) | low;217217-}218218-219219-static u32 core99_check(u8* datas)220220-{221221- struct core99_header* hdr99 = (struct core99_header*)datas;222222-223223- if (hdr99->hdr.signature != CORE99_SIGNATURE) {224224- DBG("Invalid signature\n");225225- return 0;226226- }227227- if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) {228228- DBG("Invalid checksum\n");229229- return 0;230230- }231231- if (hdr99->adler != core99_calc_adler(datas)) {232232- DBG("Invalid adler\n");233233- return 0;234234- }235235- return hdr99->generation;236236-}237237-238238-static int sm_erase_bank(int bank)239239-{240240- int stat, i;241241- unsigned long timeout;242242-243243- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;244244-245245- DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank);246246-247247- out_8(base, SM_FLASH_CMD_ERASE_SETUP);248248- out_8(base, SM_FLASH_CMD_ERASE_CONFIRM);249249- timeout = 0;250250- do {251251- if (++timeout > 1000000) {252252- printk(KERN_ERR "nvram: Sharp/Miron flash erase timeout !\n");253253- break;254254- }255255- out_8(base, SM_FLASH_CMD_READ_STATUS);256256- stat = in_8(base);257257- } while (!(stat & SM_FLASH_STATUS_DONE));258258-259259- out_8(base, SM_FLASH_CMD_CLEAR_STATUS);260260- out_8(base, SM_FLASH_CMD_RESET);261261-262262- for (i=0; i<NVRAM_SIZE; i++)263263- if (base[i] != 0xff) {264264- printk(KERN_ERR "nvram: Sharp/Micron flash erase failed !\n");265265- return -ENXIO;266266- }267267- return 0;268268-}269269-270270-static int sm_write_bank(int bank, u8* datas)271271-{272272- int i, stat = 0;273273- unsigned long timeout;274274-275275- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;276276-277277- DBG("nvram: Sharp/Micron Writing bank %d...\n", bank);278278-279279- for (i=0; i<NVRAM_SIZE; i++) {280280- out_8(base+i, SM_FLASH_CMD_WRITE_SETUP);281281- udelay(1);282282- out_8(base+i, datas[i]);283283- timeout = 0;284284- do {285285- if (++timeout > 1000000) {286286- printk(KERN_ERR "nvram: Sharp/Micron flash write timeout !\n");287287- break;288288- }289289- out_8(base, SM_FLASH_CMD_READ_STATUS);290290- stat = in_8(base);291291- } while (!(stat & SM_FLASH_STATUS_DONE));292292- if (!(stat & SM_FLASH_STATUS_DONE))293293- break;294294- }295295- out_8(base, SM_FLASH_CMD_CLEAR_STATUS);296296- out_8(base, SM_FLASH_CMD_RESET);297297- for (i=0; i<NVRAM_SIZE; i++)298298- if (base[i] != datas[i]) {299299- printk(KERN_ERR "nvram: Sharp/Micron flash write failed !\n");300300- return -ENXIO;301301- }302302- return 0;303303-}304304-305305-static int amd_erase_bank(int bank)306306-{307307- int i, stat = 0;308308- unsigned long timeout;309309-310310- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;311311-312312- DBG("nvram: AMD Erasing bank %d...\n", bank);313313-314314- /* Unlock 1 */315315- out_8(base+0x555, 0xaa);316316- udelay(1);317317- /* Unlock 2 */318318- out_8(base+0x2aa, 0x55);319319- udelay(1);320320-321321- /* Sector-Erase */322322- out_8(base+0x555, 0x80);323323- udelay(1);324324- out_8(base+0x555, 0xaa);325325- udelay(1);326326- out_8(base+0x2aa, 0x55);327327- udelay(1);328328- out_8(base, 0x30);329329- udelay(1);330330-331331- timeout = 0;332332- do {333333- if (++timeout > 1000000) {334334- printk(KERN_ERR "nvram: AMD flash erase timeout !\n");335335- break;336336- }337337- stat = in_8(base) ^ in_8(base);338338- } while (stat != 0);339339-340340- /* Reset */341341- out_8(base, 0xf0);342342- udelay(1);343343-344344- for (i=0; i<NVRAM_SIZE; i++)345345- if (base[i] != 0xff) {346346- printk(KERN_ERR "nvram: AMD flash erase failed !\n");347347- return -ENXIO;348348- }349349- return 0;350350-}351351-352352-static int amd_write_bank(int bank, u8* datas)353353-{354354- int i, stat = 0;355355- unsigned long timeout;356356-357357- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;358358-359359- DBG("nvram: AMD Writing bank %d...\n", bank);360360-361361- for (i=0; i<NVRAM_SIZE; i++) {362362- /* Unlock 1 */363363- out_8(base+0x555, 0xaa);364364- udelay(1);365365- /* Unlock 2 */366366- out_8(base+0x2aa, 0x55);367367- udelay(1);368368-369369- /* Write single word */370370- out_8(base+0x555, 0xa0);371371- udelay(1);372372- out_8(base+i, datas[i]);373373-374374- timeout = 0;375375- do {376376- if (++timeout > 1000000) {377377- printk(KERN_ERR "nvram: AMD flash write timeout !\n");378378- break;379379- }380380- stat = in_8(base) ^ in_8(base);381381- } while (stat != 0);382382- if (stat != 0)383383- break;384384- }385385-386386- /* Reset */387387- out_8(base, 0xf0);388388- udelay(1);389389-390390- for (i=0; i<NVRAM_SIZE; i++)391391- if (base[i] != datas[i]) {392392- printk(KERN_ERR "nvram: AMD flash write failed !\n");393393- return -ENXIO;394394- }395395- return 0;396396-}397397-398398-static void __init lookup_partitions(void)399399-{400400- u8 buffer[17];401401- int i, offset;402402- struct chrp_header* hdr;403403-404404- if (pmac_newworld) {405405- nvram_partitions[pmac_nvram_OF] = -1;406406- nvram_partitions[pmac_nvram_XPRAM] = -1;407407- nvram_partitions[pmac_nvram_NR] = -1;408408- hdr = (struct chrp_header *)buffer;409409-410410- offset = 0;411411- buffer[16] = 0;412412- do {413413- for (i=0;i<16;i++)414414- buffer[i] = nvram_read_byte(offset+i);415415- if (!strcmp(hdr->name, "common"))416416- nvram_partitions[pmac_nvram_OF] = offset + 0x10;417417- if (!strcmp(hdr->name, "APL,MacOS75")) {418418- nvram_partitions[pmac_nvram_XPRAM] = offset + 0x10;419419- nvram_partitions[pmac_nvram_NR] = offset + 0x110;420420- }421421- offset += (hdr->len * 0x10);422422- } while(offset < NVRAM_SIZE);423423- } else {424424- nvram_partitions[pmac_nvram_OF] = 0x1800;425425- nvram_partitions[pmac_nvram_XPRAM] = 0x1300;426426- nvram_partitions[pmac_nvram_NR] = 0x1400;427427- }428428- DBG("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]);429429- DBG("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]);430430- DBG("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]);431431-}432432-433433-static void core99_nvram_sync(void)434434-{435435- struct core99_header* hdr99;436436- unsigned long flags;437437-438438- if (!is_core_99 || !nvram_data || !nvram_image)439439- return;440440-441441- spin_lock_irqsave(&nv_lock, flags);442442- if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE,443443- NVRAM_SIZE))444444- goto bail;445445-446446- DBG("Updating nvram...\n");447447-448448- hdr99 = (struct core99_header*)nvram_image;449449- hdr99->generation++;450450- hdr99->hdr.signature = CORE99_SIGNATURE;451451- hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr);452452- hdr99->adler = core99_calc_adler(nvram_image);453453- core99_bank = core99_bank ? 0 : 1;454454- if (core99_erase_bank)455455- if (core99_erase_bank(core99_bank)) {456456- printk("nvram: Error erasing bank %d\n", core99_bank);457457- goto bail;458458- }459459- if (core99_write_bank)460460- if (core99_write_bank(core99_bank, nvram_image))461461- printk("nvram: Error writing bank %d\n", core99_bank);462462- bail:463463- spin_unlock_irqrestore(&nv_lock, flags);464464-465465-#ifdef DEBUG466466- mdelay(2000);467467-#endif468468-}469469-470470-void __init pmac_nvram_init(void)471471-{472472- struct device_node *dp;473473-474474- nvram_naddrs = 0;475475-476476- dp = find_devices("nvram");477477- if (dp == NULL) {478478- printk(KERN_ERR "Can't find NVRAM device\n");479479- return;480480- }481481- nvram_naddrs = dp->n_addrs;482482- is_core_99 = device_is_compatible(dp, "nvram,flash");483483- if (is_core_99) {484484- int i;485485- u32 gen_bank0, gen_bank1;486486-487487- if (nvram_naddrs < 1) {488488- printk(KERN_ERR "nvram: no address\n");489489- return;490490- }491491- nvram_image = alloc_bootmem(NVRAM_SIZE);492492- if (nvram_image == NULL) {493493- printk(KERN_ERR "nvram: can't allocate ram image\n");494494- return;495495- }496496- nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2);497497- nvram_naddrs = 1; /* Make sure we get the correct case */498498-499499- DBG("nvram: Checking bank 0...\n");500500-501501- gen_bank0 = core99_check((u8 *)nvram_data);502502- gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE);503503- core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0;504504-505505- DBG("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1);506506- DBG("nvram: Active bank is: %d\n", core99_bank);507507-508508- for (i=0; i<NVRAM_SIZE; i++)509509- nvram_image[i] = nvram_data[i + core99_bank*NVRAM_SIZE];510510-511511- ppc_md.nvram_read_val = core99_nvram_read_byte;512512- ppc_md.nvram_write_val = core99_nvram_write_byte;513513- ppc_md.nvram_sync = core99_nvram_sync;514514- /* 515515- * Maybe we could be smarter here though making an exclusive list516516- * of known flash chips is a bit nasty as older OF didn't provide us517517- * with a useful "compatible" entry. A solution would be to really518518- * identify the chip using flash id commands and base ourselves on519519- * a list of known chips IDs520520- */521521- if (device_is_compatible(dp, "amd-0137")) {522522- core99_erase_bank = amd_erase_bank;523523- core99_write_bank = amd_write_bank;524524- } else {525525- core99_erase_bank = sm_erase_bank;526526- core99_write_bank = sm_write_bank;527527- }528528- } else if (_machine == _MACH_chrp && nvram_naddrs == 1) {529529- nvram_data = ioremap(dp->addrs[0].address + isa_mem_base,530530- dp->addrs[0].size);531531- nvram_mult = 1;532532- ppc_md.nvram_read_val = direct_nvram_read_byte;533533- ppc_md.nvram_write_val = direct_nvram_write_byte;534534- } else if (nvram_naddrs == 1) {535535- nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size);536536- nvram_mult = (dp->addrs[0].size + NVRAM_SIZE - 1) / NVRAM_SIZE;537537- ppc_md.nvram_read_val = direct_nvram_read_byte;538538- ppc_md.nvram_write_val = direct_nvram_write_byte;539539- } else if (nvram_naddrs == 2) {540540- nvram_addr = ioremap(dp->addrs[0].address, dp->addrs[0].size);541541- nvram_data = ioremap(dp->addrs[1].address, dp->addrs[1].size);542542- ppc_md.nvram_read_val = indirect_nvram_read_byte;543543- ppc_md.nvram_write_val = indirect_nvram_write_byte;544544- } else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) {545545-#ifdef CONFIG_ADB_PMU546546- nvram_naddrs = -1;547547- ppc_md.nvram_read_val = pmu_nvram_read_byte;548548- ppc_md.nvram_write_val = pmu_nvram_write_byte;549549-#endif /* CONFIG_ADB_PMU */550550- } else {551551- printk(KERN_ERR "Don't know how to access NVRAM with %d addresses\n",552552- nvram_naddrs);553553- }554554- lookup_partitions();555555-}556556-557557-int pmac_get_partition(int partition)558558-{559559- return nvram_partitions[partition];560560-}561561-562562-u8 pmac_xpram_read(int xpaddr)563563-{564564- int offset = nvram_partitions[pmac_nvram_XPRAM];565565-566566- if (offset < 0)567567- return 0xff;568568-569569- return ppc_md.nvram_read_val(xpaddr + offset);570570-}571571-572572-void pmac_xpram_write(int xpaddr, u8 data)573573-{574574- int offset = nvram_partitions[pmac_nvram_XPRAM];575575-576576- if (offset < 0)577577- return;578578-579579- ppc_md.nvram_write_val(xpaddr + offset, data);580580-}581581-582582-EXPORT_SYMBOL(pmac_get_partition);583583-EXPORT_SYMBOL(pmac_xpram_read);584584-EXPORT_SYMBOL(pmac_xpram_write);
-1124
arch/ppc/platforms/pmac_pci.c
···11-/*22- * Support for PCI bridges found on Power Macintoshes.33- * At present the "bandit" and "chaos" bridges are supported.44- * Fortunately you access configuration space in the same55- * way with either bridge.66- *77- * Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au)88- *99- * This program is free software; you can redistribute it and/or1010- * modify it under the terms of the GNU General Public License1111- * as published by the Free Software Foundation; either version1212- * 2 of the License, or (at your option) any later version.1313- */1414-1515-#include <linux/kernel.h>1616-#include <linux/pci.h>1717-#include <linux/delay.h>1818-#include <linux/string.h>1919-#include <linux/init.h>2020-2121-#include <asm/sections.h>2222-#include <asm/io.h>2323-#include <asm/prom.h>2424-#include <asm/pci-bridge.h>2525-#include <asm/machdep.h>2626-#include <asm/pmac_feature.h>2727-2828-#undef DEBUG2929-3030-#ifdef DEBUG3131-#ifdef CONFIG_XMON3232-extern void xmon_printf(const char *fmt, ...);3333-#define DBG(x...) xmon_printf(x)3434-#else3535-#define DBG(x...) printk(x)3636-#endif3737-#else3838-#define DBG(x...)3939-#endif4040-4141-static int add_bridge(struct device_node *dev);4242-extern void pmac_check_ht_link(void);4343-4444-/* XXX Could be per-controller, but I don't think we risk anything by4545- * assuming we won't have both UniNorth and Bandit */4646-static int has_uninorth;4747-#ifdef CONFIG_POWER44848-static struct pci_controller *u3_agp;4949-#endif /* CONFIG_POWER4 */5050-5151-extern u8 pci_cache_line_size;5252-extern int pcibios_assign_bus_offset;5353-5454-struct device_node *k2_skiplist[2];5555-5656-/*5757- * Magic constants for enabling cache coherency in the bandit/PSX bridge.5858- */5959-#define BANDIT_DEVID_2 86060-#define BANDIT_REVID 36161-6262-#define BANDIT_DEVNUM 116363-#define BANDIT_MAGIC 0x506464-#define BANDIT_COHERENT 0x406565-6666-static int __init6767-fixup_one_level_bus_range(struct device_node *node, int higher)6868-{6969- for (; node != 0;node = node->sibling) {7070- int * bus_range;7171- unsigned int *class_code;7272- int len;7373-7474- /* For PCI<->PCI bridges or CardBus bridges, we go down */7575- class_code = (unsigned int *) get_property(node, "class-code", NULL);7676- if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&7777- (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))7878- continue;7979- bus_range = (int *) get_property(node, "bus-range", &len);8080- if (bus_range != NULL && len > 2 * sizeof(int)) {8181- if (bus_range[1] > higher)8282- higher = bus_range[1];8383- }8484- higher = fixup_one_level_bus_range(node->child, higher);8585- }8686- return higher;8787-}8888-8989-/* This routine fixes the "bus-range" property of all bridges in the9090- * system since they tend to have their "last" member wrong on macs9191- *9292- * Note that the bus numbers manipulated here are OF bus numbers, they9393- * are not Linux bus numbers.9494- */9595-static void __init9696-fixup_bus_range(struct device_node *bridge)9797-{9898- int * bus_range;9999- int len;100100-101101- /* Lookup the "bus-range" property for the hose */102102- bus_range = (int *) get_property(bridge, "bus-range", &len);103103- if (bus_range == NULL || len < 2 * sizeof(int)) {104104- printk(KERN_WARNING "Can't get bus-range for %s\n",105105- bridge->full_name);106106- return;107107- }108108- bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]);109109-}110110-111111-/*112112- * Apple MacRISC (U3, UniNorth, Bandit, Chaos) PCI controllers.113113- *114114- * The "Bandit" version is present in all early PCI PowerMacs,115115- * and up to the first ones using Grackle. Some machines may116116- * have 2 bandit controllers (2 PCI busses).117117- *118118- * "Chaos" is used in some "Bandit"-type machines as a bridge119119- * for the separate display bus. It is accessed the same120120- * way as bandit, but cannot be probed for devices. It therefore121121- * has its own config access functions.122122- *123123- * The "UniNorth" version is present in all Core99 machines124124- * (iBook, G4, new IMacs, and all the recent Apple machines).125125- * It contains 3 controllers in one ASIC.126126- *127127- * The U3 is the bridge used on G5 machines. It contains an128128- * AGP bus which is dealt with the old UniNorth access routines129129- * and a HyperTransport bus which uses its own set of access130130- * functions.131131- */132132-133133-#define MACRISC_CFA0(devfn, off) \134134- ((1 << (unsigned long)PCI_SLOT(dev_fn)) \135135- | (((unsigned long)PCI_FUNC(dev_fn)) << 8) \136136- | (((unsigned long)(off)) & 0xFCUL))137137-138138-#define MACRISC_CFA1(bus, devfn, off) \139139- ((((unsigned long)(bus)) << 16) \140140- |(((unsigned long)(devfn)) << 8) \141141- |(((unsigned long)(off)) & 0xFCUL) \142142- |1UL)143143-144144-static void volatile __iomem *145145-macrisc_cfg_access(struct pci_controller* hose, u8 bus, u8 dev_fn, u8 offset)146146-{147147- unsigned int caddr;148148-149149- if (bus == hose->first_busno) {150150- if (dev_fn < (11 << 3))151151- return NULL;152152- caddr = MACRISC_CFA0(dev_fn, offset);153153- } else154154- caddr = MACRISC_CFA1(bus, dev_fn, offset);155155-156156- /* Uninorth will return garbage if we don't read back the value ! */157157- do {158158- out_le32(hose->cfg_addr, caddr);159159- } while (in_le32(hose->cfg_addr) != caddr);160160-161161- offset &= has_uninorth ? 0x07 : 0x03;162162- return hose->cfg_data + offset;163163-}164164-165165-static int166166-macrisc_read_config(struct pci_bus *bus, unsigned int devfn, int offset,167167- int len, u32 *val)168168-{169169- struct pci_controller *hose = bus->sysdata;170170- void volatile __iomem *addr;171171-172172- addr = macrisc_cfg_access(hose, bus->number, devfn, offset);173173- if (!addr)174174- return PCIBIOS_DEVICE_NOT_FOUND;175175- /*176176- * Note: the caller has already checked that offset is177177- * suitably aligned and that len is 1, 2 or 4.178178- */179179- switch (len) {180180- case 1:181181- *val = in_8(addr);182182- break;183183- case 2:184184- *val = in_le16(addr);185185- break;186186- default:187187- *val = in_le32(addr);188188- break;189189- }190190- return PCIBIOS_SUCCESSFUL;191191-}192192-193193-static int194194-macrisc_write_config(struct pci_bus *bus, unsigned int devfn, int offset,195195- int len, u32 val)196196-{197197- struct pci_controller *hose = bus->sysdata;198198- void volatile __iomem *addr;199199-200200- addr = macrisc_cfg_access(hose, bus->number, devfn, offset);201201- if (!addr)202202- return PCIBIOS_DEVICE_NOT_FOUND;203203- /*204204- * Note: the caller has already checked that offset is205205- * suitably aligned and that len is 1, 2 or 4.206206- */207207- switch (len) {208208- case 1:209209- out_8(addr, val);210210- (void) in_8(addr);211211- break;212212- case 2:213213- out_le16(addr, val);214214- (void) in_le16(addr);215215- break;216216- default:217217- out_le32(addr, val);218218- (void) in_le32(addr);219219- break;220220- }221221- return PCIBIOS_SUCCESSFUL;222222-}223223-224224-static struct pci_ops macrisc_pci_ops =225225-{226226- macrisc_read_config,227227- macrisc_write_config228228-};229229-230230-/*231231- * Verifiy that a specific (bus, dev_fn) exists on chaos232232- */233233-static int234234-chaos_validate_dev(struct pci_bus *bus, int devfn, int offset)235235-{236236- struct device_node *np;237237- u32 *vendor, *device;238238-239239- np = pci_busdev_to_OF_node(bus, devfn);240240- if (np == NULL)241241- return PCIBIOS_DEVICE_NOT_FOUND;242242-243243- vendor = (u32 *)get_property(np, "vendor-id", NULL);244244- device = (u32 *)get_property(np, "device-id", NULL);245245- if (vendor == NULL || device == NULL)246246- return PCIBIOS_DEVICE_NOT_FOUND;247247-248248- if ((*vendor == 0x106b) && (*device == 3) && (offset >= 0x10)249249- && (offset != 0x14) && (offset != 0x18) && (offset <= 0x24))250250- return PCIBIOS_BAD_REGISTER_NUMBER;251251-252252- return PCIBIOS_SUCCESSFUL;253253-}254254-255255-static int256256-chaos_read_config(struct pci_bus *bus, unsigned int devfn, int offset,257257- int len, u32 *val)258258-{259259- int result = chaos_validate_dev(bus, devfn, offset);260260- if (result == PCIBIOS_BAD_REGISTER_NUMBER)261261- *val = ~0U;262262- if (result != PCIBIOS_SUCCESSFUL)263263- return result;264264- return macrisc_read_config(bus, devfn, offset, len, val);265265-}266266-267267-static int268268-chaos_write_config(struct pci_bus *bus, unsigned int devfn, int offset,269269- int len, u32 val)270270-{271271- int result = chaos_validate_dev(bus, devfn, offset);272272- if (result != PCIBIOS_SUCCESSFUL)273273- return result;274274- return macrisc_write_config(bus, devfn, offset, len, val);275275-}276276-277277-static struct pci_ops chaos_pci_ops =278278-{279279- chaos_read_config,280280- chaos_write_config281281-};282282-283283-#ifdef CONFIG_POWER4284284-285285-/*286286- * These versions of U3 HyperTransport config space access ops do not287287- * implement self-view of the HT host yet288288- */289289-290290-#define U3_HT_CFA0(devfn, off) \291291- ((((unsigned long)devfn) << 8) | offset)292292-#define U3_HT_CFA1(bus, devfn, off) \293293- (U3_HT_CFA0(devfn, off) \294294- + (((unsigned long)bus) << 16) \295295- + 0x01000000UL)296296-297297-static void volatile __iomem *298298-u3_ht_cfg_access(struct pci_controller* hose, u8 bus, u8 devfn, u8 offset)299299-{300300- if (bus == hose->first_busno) {301301- /* For now, we don't self probe U3 HT bridge */302302- if (PCI_FUNC(devfn) != 0 || PCI_SLOT(devfn) > 7 ||303303- PCI_SLOT(devfn) < 1)304304- return 0;305305- return hose->cfg_data + U3_HT_CFA0(devfn, offset);306306- } else307307- return hose->cfg_data + U3_HT_CFA1(bus, devfn, offset);308308-}309309-310310-static int311311-u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, int offset,312312- int len, u32 *val)313313-{314314- struct pci_controller *hose = bus->sysdata;315315- void volatile __iomem *addr;316316- int i;317317-318318- struct device_node *np = pci_busdev_to_OF_node(bus, devfn);319319- if (np == NULL)320320- return PCIBIOS_DEVICE_NOT_FOUND;321321-322322- /*323323- * When a device in K2 is powered down, we die on config324324- * cycle accesses. Fix that here.325325- */326326- for (i=0; i<2; i++)327327- if (k2_skiplist[i] == np) {328328- switch (len) {329329- case 1:330330- *val = 0xff; break;331331- case 2:332332- *val = 0xffff; break;333333- default:334334- *val = 0xfffffffful; break;335335- }336336- return PCIBIOS_SUCCESSFUL;337337- }338338-339339- addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);340340- if (!addr)341341- return PCIBIOS_DEVICE_NOT_FOUND;342342- /*343343- * Note: the caller has already checked that offset is344344- * suitably aligned and that len is 1, 2 or 4.345345- */346346- switch (len) {347347- case 1:348348- *val = in_8(addr);349349- break;350350- case 2:351351- *val = in_le16(addr);352352- break;353353- default:354354- *val = in_le32(addr);355355- break;356356- }357357- return PCIBIOS_SUCCESSFUL;358358-}359359-360360-static int361361-u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, int offset,362362- int len, u32 val)363363-{364364- struct pci_controller *hose = bus->sysdata;365365- void volatile __iomem *addr;366366- int i;367367-368368- struct device_node *np = pci_busdev_to_OF_node(bus, devfn);369369- if (np == NULL)370370- return PCIBIOS_DEVICE_NOT_FOUND;371371- /*372372- * When a device in K2 is powered down, we die on config373373- * cycle accesses. Fix that here.374374- */375375- for (i=0; i<2; i++)376376- if (k2_skiplist[i] == np)377377- return PCIBIOS_SUCCESSFUL;378378-379379- addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);380380- if (!addr)381381- return PCIBIOS_DEVICE_NOT_FOUND;382382- /*383383- * Note: the caller has already checked that offset is384384- * suitably aligned and that len is 1, 2 or 4.385385- */386386- switch (len) {387387- case 1:388388- out_8(addr, val);389389- (void) in_8(addr);390390- break;391391- case 2:392392- out_le16(addr, val);393393- (void) in_le16(addr);394394- break;395395- default:396396- out_le32(addr, val);397397- (void) in_le32(addr);398398- break;399399- }400400- return PCIBIOS_SUCCESSFUL;401401-}402402-403403-static struct pci_ops u3_ht_pci_ops =404404-{405405- u3_ht_read_config,406406- u3_ht_write_config407407-};408408-409409-#endif /* CONFIG_POWER4 */410410-411411-/*412412- * For a bandit bridge, turn on cache coherency if necessary.413413- * N.B. we could clean this up using the hose ops directly.414414- */415415-static void __init416416-init_bandit(struct pci_controller *bp)417417-{418418- unsigned int vendev, magic;419419- int rev;420420-421421- /* read the word at offset 0 in config space for device 11 */422422- out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID);423423- udelay(2);424424- vendev = in_le32(bp->cfg_data);425425- if (vendev == (PCI_DEVICE_ID_APPLE_BANDIT << 16) +426426- PCI_VENDOR_ID_APPLE) {427427- /* read the revision id */428428- out_le32(bp->cfg_addr,429429- (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID);430430- udelay(2);431431- rev = in_8(bp->cfg_data);432432- if (rev != BANDIT_REVID)433433- printk(KERN_WARNING434434- "Unknown revision %d for bandit\n", rev);435435- } else if (vendev != (BANDIT_DEVID_2 << 16) + PCI_VENDOR_ID_APPLE) {436436- printk(KERN_WARNING "bandit isn't? (%x)\n", vendev);437437- return;438438- }439439-440440- /* read the word at offset 0x50 */441441- out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC);442442- udelay(2);443443- magic = in_le32(bp->cfg_data);444444- if ((magic & BANDIT_COHERENT) != 0)445445- return;446446- magic |= BANDIT_COHERENT;447447- udelay(2);448448- out_le32(bp->cfg_data, magic);449449- printk(KERN_INFO "Cache coherency enabled for bandit/PSX\n");450450-}451451-452452-453453-/*454454- * Tweak the PCI-PCI bridge chip on the blue & white G3s.455455- */456456-static void __init457457-init_p2pbridge(void)458458-{459459- struct device_node *p2pbridge;460460- struct pci_controller* hose;461461- u8 bus, devfn;462462- u16 val;463463-464464- /* XXX it would be better here to identify the specific465465- PCI-PCI bridge chip we have. */466466- if ((p2pbridge = find_devices("pci-bridge")) == 0467467- || p2pbridge->parent == NULL468468- || strcmp(p2pbridge->parent->name, "pci") != 0)469469- return;470470- if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) {471471- DBG("Can't find PCI infos for PCI<->PCI bridge\n");472472- return;473473- }474474- /* Warning: At this point, we have not yet renumbered all busses.475475- * So we must use OF walking to find out hose476476- */477477- hose = pci_find_hose_for_OF_device(p2pbridge);478478- if (!hose) {479479- DBG("Can't find hose for PCI<->PCI bridge\n");480480- return;481481- }482482- if (early_read_config_word(hose, bus, devfn,483483- PCI_BRIDGE_CONTROL, &val) < 0) {484484- printk(KERN_ERR "init_p2pbridge: couldn't read bridge control\n");485485- return;486486- }487487- val &= ~PCI_BRIDGE_CTL_MASTER_ABORT;488488- early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val);489489-}490490-491491-/*492492- * Some Apple desktop machines have a NEC PD720100A USB2 controller493493- * on the motherboard. Open Firmware, on these, will disable the494494- * EHCI part of it so it behaves like a pair of OHCI's. This fixup495495- * code re-enables it ;)496496- */497497-static void __init498498-fixup_nec_usb2(void)499499-{500500- struct device_node *nec;501501-502502- for (nec = NULL; (nec = of_find_node_by_name(nec, "usb")) != NULL;) {503503- struct pci_controller *hose;504504- u32 data, *prop;505505- u8 bus, devfn;506506-507507- prop = (u32 *)get_property(nec, "vendor-id", NULL);508508- if (prop == NULL)509509- continue;510510- if (0x1033 != *prop)511511- continue;512512- prop = (u32 *)get_property(nec, "device-id", NULL);513513- if (prop == NULL)514514- continue;515515- if (0x0035 != *prop)516516- continue;517517- prop = (u32 *)get_property(nec, "reg", NULL);518518- if (prop == NULL)519519- continue;520520- devfn = (prop[0] >> 8) & 0xff;521521- bus = (prop[0] >> 16) & 0xff;522522- if (PCI_FUNC(devfn) != 0)523523- continue;524524- hose = pci_find_hose_for_OF_device(nec);525525- if (!hose)526526- continue;527527- early_read_config_dword(hose, bus, devfn, 0xe4, &data);528528- if (data & 1UL) {529529- printk("Found NEC PD720100A USB2 chip with disabled EHCI, fixing up...\n");530530- data &= ~1UL;531531- early_write_config_dword(hose, bus, devfn, 0xe4, data);532532- early_write_config_byte(hose, bus, devfn | 2, PCI_INTERRUPT_LINE,533533- nec->intrs[0].line);534534- }535535- }536536-}537537-538538-void __init539539-pmac_find_bridges(void)540540-{541541- struct device_node *np, *root;542542- struct device_node *ht = NULL;543543-544544- root = of_find_node_by_path("/");545545- if (root == NULL) {546546- printk(KERN_CRIT "pmac_find_bridges: can't find root of device tree\n");547547- return;548548- }549549- for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) {550550- if (np->name == NULL)551551- continue;552552- if (strcmp(np->name, "bandit") == 0553553- || strcmp(np->name, "chaos") == 0554554- || strcmp(np->name, "pci") == 0) {555555- if (add_bridge(np) == 0)556556- of_node_get(np);557557- }558558- if (strcmp(np->name, "ht") == 0) {559559- of_node_get(np);560560- ht = np;561561- }562562- }563563- of_node_put(root);564564-565565- /* Probe HT last as it relies on the agp resources to be already566566- * setup567567- */568568- if (ht && add_bridge(ht) != 0)569569- of_node_put(ht);570570-571571- init_p2pbridge();572572- fixup_nec_usb2();573573-574574- /* We are still having some issues with the Xserve G4, enabling575575- * some offset between bus number and domains for now when we576576- * assign all busses should help for now577577- */578578- if (pci_assign_all_buses)579579- pcibios_assign_bus_offset = 0x10;580580-581581-#ifdef CONFIG_POWER4 582582- /* There is something wrong with DMA on U3/HT. I haven't figured out583583- * the details yet, but if I set the cache line size to 128 bytes like584584- * it should, I'm getting memory corruption caused by devices like585585- * sungem (even without the MWI bit set, but maybe sungem doesn't586586- * care). Right now, it appears that setting up a 64 bytes line size587587- * works properly, 64 bytes beeing the max transfer size of HT, I588588- * suppose this is related the way HT/PCI are hooked together. I still589589- * need to dive into more specs though to be really sure of what's590590- * going on. --BenH.591591- *592592- * Ok, apparently, it's just that HT can't do more than 64 bytes593593- * transactions. MWI seem to be meaningless there as well, it may594594- * be worth nop'ing out pci_set_mwi too though I haven't done that595595- * yet.596596- *597597- * Note that it's a bit different for whatever is in the AGP slot.598598- * For now, I don't care, but this can become a real issue, we599599- * should probably hook pci_set_mwi anyway to make sure it sets600600- * the real cache line size in there.601601- */602602- if (machine_is_compatible("MacRISC4"))603603- pci_cache_line_size = 16; /* 64 bytes */604604-605605- pmac_check_ht_link();606606-#endif /* CONFIG_POWER4 */607607-}608608-609609-#define GRACKLE_CFA(b, d, o) (0x80 | ((b) << 8) | ((d) << 16) \610610- | (((o) & ~3) << 24))611611-612612-#define GRACKLE_PICR1_STG 0x00000040613613-#define GRACKLE_PICR1_LOOPSNOOP 0x00000010614614-615615-/* N.B. this is called before bridges is initialized, so we can't616616- use grackle_pcibios_{read,write}_config_dword. */617617-static inline void grackle_set_stg(struct pci_controller* bp, int enable)618618-{619619- unsigned int val;620620-621621- out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));622622- val = in_le32(bp->cfg_data);623623- val = enable? (val | GRACKLE_PICR1_STG) :624624- (val & ~GRACKLE_PICR1_STG);625625- out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));626626- out_le32(bp->cfg_data, val);627627- (void)in_le32(bp->cfg_data);628628-}629629-630630-static inline void grackle_set_loop_snoop(struct pci_controller *bp, int enable)631631-{632632- unsigned int val;633633-634634- out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));635635- val = in_le32(bp->cfg_data);636636- val = enable? (val | GRACKLE_PICR1_LOOPSNOOP) :637637- (val & ~GRACKLE_PICR1_LOOPSNOOP);638638- out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));639639- out_le32(bp->cfg_data, val);640640- (void)in_le32(bp->cfg_data);641641-}642642-643643-static int __init644644-setup_uninorth(struct pci_controller* hose, struct reg_property* addr)645645-{646646- pci_assign_all_buses = 1;647647- has_uninorth = 1;648648- hose->ops = ¯isc_pci_ops;649649- hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);650650- hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);651651- /* We "know" that the bridge at f2000000 has the PCI slots. */652652- return addr->address == 0xf2000000;653653-}654654-655655-static void __init656656-setup_bandit(struct pci_controller* hose, struct reg_property* addr)657657-{658658- hose->ops = ¯isc_pci_ops;659659- hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);660660- hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);661661- init_bandit(hose);662662-}663663-664664-static void __init665665-setup_chaos(struct pci_controller* hose, struct reg_property* addr)666666-{667667- /* assume a `chaos' bridge */668668- hose->ops = &chaos_pci_ops;669669- hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);670670- hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);671671-}672672-673673-#ifdef CONFIG_POWER4674674-675675-static void __init676676-setup_u3_agp(struct pci_controller* hose, struct reg_property* addr)677677-{678678- /* On G5, we move AGP up to high bus number so we don't need679679- * to reassign bus numbers for HT. If we ever have P2P bridges680680- * on AGP, we'll have to move pci_assign_all_buses to the681681- * pci_controller structure so we enable it for AGP and not for682682- * HT childs.683683- * We hard code the address because of the different size of684684- * the reg address cell, we shall fix that by killing struct685685- * reg_property and using some accessor functions instead686686- */687687- hose->first_busno = 0xf0;688688- hose->last_busno = 0xff;689689- has_uninorth = 1;690690- hose->ops = ¯isc_pci_ops;691691- hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);692692- hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000);693693-694694- u3_agp = hose;695695-}696696-697697-static void __init698698-setup_u3_ht(struct pci_controller* hose, struct reg_property *addr)699699-{700700- struct device_node *np = (struct device_node *)hose->arch_data;701701- int i, cur;702702-703703- hose->ops = &u3_ht_pci_ops;704704-705705- /* We hard code the address because of the different size of706706- * the reg address cell, we shall fix that by killing struct707707- * reg_property and using some accessor functions instead708708- */709709- hose->cfg_data = ioremap(0xf2000000, 0x02000000);710710-711711- /*712712- * /ht node doesn't expose a "ranges" property, so we "remove" regions that713713- * have been allocated to AGP. So far, this version of the code doesn't assign714714- * any of the 0xfxxxxxxx "fine" memory regions to /ht.715715- * We need to fix that sooner or later by either parsing all child "ranges"716716- * properties or figuring out the U3 address space decoding logic and717717- * then read its configuration register (if any).718718- */719719- hose->io_base_phys = 0xf4000000;720720- hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000);721721- isa_io_base = (unsigned long) hose->io_base_virt;722722- hose->io_resource.name = np->full_name;723723- hose->io_resource.start = 0;724724- hose->io_resource.end = 0x003fffff;725725- hose->io_resource.flags = IORESOURCE_IO;726726- hose->pci_mem_offset = 0;727727- hose->first_busno = 0;728728- hose->last_busno = 0xef;729729- hose->mem_resources[0].name = np->full_name;730730- hose->mem_resources[0].start = 0x80000000;731731- hose->mem_resources[0].end = 0xefffffff;732732- hose->mem_resources[0].flags = IORESOURCE_MEM;733733-734734- if (u3_agp == NULL) {735735- DBG("U3 has no AGP, using full resource range\n");736736- return;737737- }738738-739739- /* We "remove" the AGP resources from the resources allocated to HT, that740740- * is we create "holes". However, that code does assumptions that so far741741- * happen to be true (cross fingers...), typically that resources in the742742- * AGP node are properly ordered743743- */744744- cur = 0;745745- for (i=0; i<3; i++) {746746- struct resource *res = &u3_agp->mem_resources[i];747747- if (res->flags != IORESOURCE_MEM)748748- continue;749749- /* We don't care about "fine" resources */750750- if (res->start >= 0xf0000000)751751- continue;752752- /* Check if it's just a matter of "shrinking" us in one direction */753753- if (hose->mem_resources[cur].start == res->start) {754754- DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n",755755- cur, hose->mem_resources[cur].start, res->end + 1);756756- hose->mem_resources[cur].start = res->end + 1;757757- continue;758758- }759759- if (hose->mem_resources[cur].end == res->end) {760760- DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n",761761- cur, hose->mem_resources[cur].end, res->start - 1);762762- hose->mem_resources[cur].end = res->start - 1;763763- continue;764764- }765765- /* No, it's not the case, we need a hole */766766- if (cur == 2) {767767- /* not enough resources to make a hole, we drop part of the range */768768- printk(KERN_WARNING "Running out of resources for /ht host !\n");769769- hose->mem_resources[cur].end = res->start - 1;770770- continue;771771- } 772772- cur++;773773- DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n",774774- cur-1, res->start - 1, cur, res->end + 1);775775- hose->mem_resources[cur].name = np->full_name;776776- hose->mem_resources[cur].flags = IORESOURCE_MEM;777777- hose->mem_resources[cur].start = res->end + 1;778778- hose->mem_resources[cur].end = hose->mem_resources[cur-1].end;779779- hose->mem_resources[cur-1].end = res->start - 1;780780- }781781-}782782-783783-#endif /* CONFIG_POWER4 */784784-785785-void __init786786-setup_grackle(struct pci_controller *hose)787787-{788788- setup_indirect_pci(hose, 0xfec00000, 0xfee00000);789789- if (machine_is_compatible("AAPL,PowerBook1998"))790790- grackle_set_loop_snoop(hose, 1);791791-#if 0 /* Disabled for now, HW problems ??? */792792- grackle_set_stg(hose, 1);793793-#endif794794-}795795-796796-/*797797- * We assume that if we have a G3 powermac, we have one bridge called798798- * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise,799799- * if we have one or more bandit or chaos bridges, we don't have a MPC106.800800- */801801-static int __init802802-add_bridge(struct device_node *dev)803803-{804804- int len;805805- struct pci_controller *hose;806806- struct reg_property *addr;807807- char* disp_name;808808- int *bus_range;809809- int primary = 1;810810-811811- DBG("Adding PCI host bridge %s\n", dev->full_name);812812-813813- addr = (struct reg_property *) get_property(dev, "reg", &len);814814- if (addr == NULL || len < sizeof(*addr)) {815815- printk(KERN_WARNING "Can't use %s: no address\n",816816- dev->full_name);817817- return -ENODEV;818818- }819819- bus_range = (int *) get_property(dev, "bus-range", &len);820820- if (bus_range == NULL || len < 2 * sizeof(int)) {821821- printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",822822- dev->full_name);823823- }824824-825825- hose = pcibios_alloc_controller();826826- if (!hose)827827- return -ENOMEM;828828- hose->arch_data = dev;829829- hose->first_busno = bus_range ? bus_range[0] : 0;830830- hose->last_busno = bus_range ? bus_range[1] : 0xff;831831-832832- disp_name = NULL;833833-#ifdef CONFIG_POWER4834834- if (device_is_compatible(dev, "u3-agp")) {835835- setup_u3_agp(hose, addr);836836- disp_name = "U3-AGP";837837- primary = 0;838838- } else if (device_is_compatible(dev, "u3-ht")) {839839- setup_u3_ht(hose, addr);840840- disp_name = "U3-HT";841841- primary = 1;842842- } else843843-#endif /* CONFIG_POWER4 */844844- if (device_is_compatible(dev, "uni-north")) {845845- primary = setup_uninorth(hose, addr);846846- disp_name = "UniNorth";847847- } else if (strcmp(dev->name, "pci") == 0) {848848- /* XXX assume this is a mpc106 (grackle) */849849- setup_grackle(hose);850850- disp_name = "Grackle (MPC106)";851851- } else if (strcmp(dev->name, "bandit") == 0) {852852- setup_bandit(hose, addr);853853- disp_name = "Bandit";854854- } else if (strcmp(dev->name, "chaos") == 0) {855855- setup_chaos(hose, addr);856856- disp_name = "Chaos";857857- primary = 0;858858- }859859- printk(KERN_INFO "Found %s PCI host bridge at 0x%08x. Firmware bus number: %d->%d\n",860860- disp_name, addr->address, hose->first_busno, hose->last_busno);861861- DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",862862- hose, hose->cfg_addr, hose->cfg_data);863863-864864- /* Interpret the "ranges" property */865865- /* This also maps the I/O region and sets isa_io/mem_base */866866- pci_process_bridge_OF_ranges(hose, dev, primary);867867-868868- /* Fixup "bus-range" OF property */869869- fixup_bus_range(dev);870870-871871- return 0;872872-}873873-874874-static void __init875875-pcibios_fixup_OF_interrupts(void)876876-{877877- struct pci_dev* dev = NULL;878878-879879- /*880880- * Open Firmware often doesn't initialize the881881- * PCI_INTERRUPT_LINE config register properly, so we882882- * should find the device node and apply the interrupt883883- * obtained from the OF device-tree884884- */885885- for_each_pci_dev(dev) {886886- struct device_node *node;887887- node = pci_device_to_OF_node(dev);888888- /* this is the node, see if it has interrupts */889889- if (node && node->n_intrs > 0)890890- dev->irq = node->intrs[0].line;891891- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);892892- }893893-}894894-895895-void __init896896-pmac_pcibios_fixup(void)897897-{898898- /* Fixup interrupts according to OF tree */899899- pcibios_fixup_OF_interrupts();900900-}901901-902902-int903903-pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)904904-{905905- struct device_node* node;906906- int updatecfg = 0;907907- int uninorth_child;908908-909909- node = pci_device_to_OF_node(dev);910910-911911- /* We don't want to enable USB controllers absent from the OF tree912912- * (iBook second controller)913913- */914914- if (dev->vendor == PCI_VENDOR_ID_APPLE915915- && (dev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x10))916916- && !node) {917917- printk(KERN_INFO "Apple USB OHCI %s disabled by firmware\n",918918- pci_name(dev));919919- return -EINVAL;920920- }921921-922922- if (!node)923923- return 0;924924-925925- uninorth_child = node->parent &&926926- device_is_compatible(node->parent, "uni-north");927927-928928- /* Firewire & GMAC were disabled after PCI probe, the driver is929929- * claiming them, we must re-enable them now.930930- */931931- if (uninorth_child && !strcmp(node->name, "firewire") &&932932- (device_is_compatible(node, "pci106b,18") ||933933- device_is_compatible(node, "pci106b,30") ||934934- device_is_compatible(node, "pci11c1,5811"))) {935935- pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, node, 0, 1);936936- pmac_call_feature(PMAC_FTR_1394_ENABLE, node, 0, 1);937937- updatecfg = 1;938938- }939939- if (uninorth_child && !strcmp(node->name, "ethernet") &&940940- device_is_compatible(node, "gmac")) {941941- pmac_call_feature(PMAC_FTR_GMAC_ENABLE, node, 0, 1);942942- updatecfg = 1;943943- }944944-945945- if (updatecfg) {946946- u16 cmd;947947-948948- /*949949- * Make sure PCI is correctly configured950950- *951951- * We use old pci_bios versions of the function since, by952952- * default, gmac is not powered up, and so will be absent953953- * from the kernel initial PCI lookup.954954- *955955- * Should be replaced by 2.4 new PCI mechanisms and really956956- * register the device.957957- */958958- pci_read_config_word(dev, PCI_COMMAND, &cmd);959959- cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;960960- pci_write_config_word(dev, PCI_COMMAND, cmd);961961- pci_write_config_byte(dev, PCI_LATENCY_TIMER, 16);962962- pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, pci_cache_line_size);963963- }964964-965965- return 0;966966-}967967-968968-/* We power down some devices after they have been probed. They'll969969- * be powered back on later on970970- */971971-void __init972972-pmac_pcibios_after_init(void)973973-{974974- struct device_node* nd;975975-976976-#ifdef CONFIG_BLK_DEV_IDE977977- struct pci_dev *dev = NULL;978978-979979- /* OF fails to initialize IDE controllers on macs980980- * (and maybe other machines)981981- *982982- * Ideally, this should be moved to the IDE layer, but we need983983- * to check specifically with Andre Hedrick how to do it cleanly984984- * since the common IDE code seem to care about the fact that the985985- * BIOS may have disabled a controller.986986- *987987- * -- BenH988988- */989989- for_each_pci_dev(dev) {990990- if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE)991991- pci_enable_device(dev);992992- }993993-#endif /* CONFIG_BLK_DEV_IDE */994994-995995- nd = find_devices("firewire");996996- while (nd) {997997- if (nd->parent && (device_is_compatible(nd, "pci106b,18") ||998998- device_is_compatible(nd, "pci106b,30") ||999999- device_is_compatible(nd, "pci11c1,5811"))10001000- && device_is_compatible(nd->parent, "uni-north")) {10011001- pmac_call_feature(PMAC_FTR_1394_ENABLE, nd, 0, 0);10021002- pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0);10031003- }10041004- nd = nd->next;10051005- }10061006- nd = find_devices("ethernet");10071007- while (nd) {10081008- if (nd->parent && device_is_compatible(nd, "gmac")10091009- && device_is_compatible(nd->parent, "uni-north"))10101010- pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0);10111011- nd = nd->next;10121012- }10131013-}10141014-10151015-void pmac_pci_fixup_cardbus(struct pci_dev* dev)10161016-{10171017- if (_machine != _MACH_Pmac)10181018- return;10191019- /*10201020- * Fix the interrupt routing on the various cardbus bridges10211021- * used on powerbooks10221022- */10231023- if (dev->vendor != PCI_VENDOR_ID_TI)10241024- return;10251025- if (dev->device == PCI_DEVICE_ID_TI_1130 ||10261026- dev->device == PCI_DEVICE_ID_TI_1131) {10271027- u8 val;10281028- /* Enable PCI interrupt */10291029- if (pci_read_config_byte(dev, 0x91, &val) == 0)10301030- pci_write_config_byte(dev, 0x91, val | 0x30);10311031- /* Disable ISA interrupt mode */10321032- if (pci_read_config_byte(dev, 0x92, &val) == 0)10331033- pci_write_config_byte(dev, 0x92, val & ~0x06);10341034- }10351035- if (dev->device == PCI_DEVICE_ID_TI_1210 ||10361036- dev->device == PCI_DEVICE_ID_TI_1211 ||10371037- dev->device == PCI_DEVICE_ID_TI_1410 ||10381038- dev->device == PCI_DEVICE_ID_TI_1510) {10391039- u8 val;10401040- /* 0x8c == TI122X_IRQMUX, 2 says to route the INTA10411041- signal out the MFUNC0 pin */10421042- if (pci_read_config_byte(dev, 0x8c, &val) == 0)10431043- pci_write_config_byte(dev, 0x8c, (val & ~0x0f) | 2);10441044- /* Disable ISA interrupt mode */10451045- if (pci_read_config_byte(dev, 0x92, &val) == 0)10461046- pci_write_config_byte(dev, 0x92, val & ~0x06);10471047- }10481048-}10491049-10501050-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_ANY_ID, pmac_pci_fixup_cardbus);10511051-10521052-void pmac_pci_fixup_pciata(struct pci_dev* dev)10531053-{10541054- u8 progif = 0;10551055-10561056- /*10571057- * On PowerMacs, we try to switch any PCI ATA controller to10581058- * fully native mode10591059- */10601060- if (_machine != _MACH_Pmac)10611061- return;10621062- /* Some controllers don't have the class IDE */10631063- if (dev->vendor == PCI_VENDOR_ID_PROMISE)10641064- switch(dev->device) {10651065- case PCI_DEVICE_ID_PROMISE_20246:10661066- case PCI_DEVICE_ID_PROMISE_20262:10671067- case PCI_DEVICE_ID_PROMISE_20263:10681068- case PCI_DEVICE_ID_PROMISE_20265:10691069- case PCI_DEVICE_ID_PROMISE_20267:10701070- case PCI_DEVICE_ID_PROMISE_20268:10711071- case PCI_DEVICE_ID_PROMISE_20269:10721072- case PCI_DEVICE_ID_PROMISE_20270:10731073- case PCI_DEVICE_ID_PROMISE_20271:10741074- case PCI_DEVICE_ID_PROMISE_20275:10751075- case PCI_DEVICE_ID_PROMISE_20276:10761076- case PCI_DEVICE_ID_PROMISE_20277:10771077- goto good;10781078- }10791079- /* Others, check PCI class */10801080- if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)10811081- return;10821082- good:10831083- pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);10841084- if ((progif & 5) != 5) {10851085- printk(KERN_INFO "Forcing PCI IDE into native mode: %s\n", pci_name(dev));10861086- (void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5);10871087- if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) ||10881088- (progif & 5) != 5)10891089- printk(KERN_ERR "Rewrite of PROGIF failed !\n");10901090- }10911091-}10921092-DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pmac_pci_fixup_pciata);10931093-10941094-10951095-/*10961096- * Disable second function on K2-SATA, it's broken10971097- * and disable IO BARs on first one10981098- */10991099-void pmac_pci_fixup_k2_sata(struct pci_dev* dev)11001100-{11011101- int i;11021102- u16 cmd;11031103-11041104- if (PCI_FUNC(dev->devfn) > 0) {11051105- pci_read_config_word(dev, PCI_COMMAND, &cmd);11061106- cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY);11071107- pci_write_config_word(dev, PCI_COMMAND, cmd);11081108- for (i = 0; i < 6; i++) {11091109- dev->resource[i].start = dev->resource[i].end = 0;11101110- dev->resource[i].flags = 0;11111111- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0);11121112- }11131113- } else {11141114- pci_read_config_word(dev, PCI_COMMAND, &cmd);11151115- cmd &= ~PCI_COMMAND_IO;11161116- pci_write_config_word(dev, PCI_COMMAND, cmd);11171117- for (i = 0; i < 5; i++) {11181118- dev->resource[i].start = dev->resource[i].end = 0;11191119- dev->resource[i].flags = 0;11201120- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0);11211121- }11221122- }11231123-}11241124-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, pmac_pci_fixup_k2_sata);
-693
arch/ppc/platforms/pmac_pic.c
···11-/*22- * Support for the interrupt controllers found on Power Macintosh,33- * currently Apple's "Grand Central" interrupt controller in all44- * it's incarnations. OpenPIC support used on newer machines is55- * in a separate file66- *77- * Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au)88- *99- * Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org)1010- *1111- * This program is free software; you can redistribute it and/or1212- * modify it under the terms of the GNU General Public License1313- * as published by the Free Software Foundation; either version1414- * 2 of the License, or (at your option) any later version.1515- *1616- */1717-1818-#include <linux/config.h>1919-#include <linux/stddef.h>2020-#include <linux/init.h>2121-#include <linux/sched.h>2222-#include <linux/signal.h>2323-#include <linux/pci.h>2424-#include <linux/interrupt.h>2525-#include <linux/sysdev.h>2626-#include <linux/adb.h>2727-#include <linux/pmu.h>2828-2929-#include <asm/sections.h>3030-#include <asm/io.h>3131-#include <asm/smp.h>3232-#include <asm/prom.h>3333-#include <asm/pci-bridge.h>3434-#include <asm/time.h>3535-#include <asm/open_pic.h>3636-#include <asm/xmon.h>3737-#include <asm/pmac_feature.h>3838-#include <asm/machdep.h>3939-4040-#include "pmac_pic.h"4141-4242-/*4343- * XXX this should be in xmon.h, but putting it there means xmon.h4444- * has to include <linux/interrupt.h> (to get irqreturn_t), which4545- * causes all sorts of problems. -- paulus4646- */4747-extern irqreturn_t xmon_irq(int, void *, struct pt_regs *);4848-4949-struct pmac_irq_hw {5050- unsigned int event;5151- unsigned int enable;5252- unsigned int ack;5353- unsigned int level;5454-};5555-5656-/* Default addresses */5757-static volatile struct pmac_irq_hw *pmac_irq_hw[4] = {5858- (struct pmac_irq_hw *) 0xf3000020,5959- (struct pmac_irq_hw *) 0xf3000010,6060- (struct pmac_irq_hw *) 0xf4000020,6161- (struct pmac_irq_hw *) 0xf4000010,6262-};6363-6464-#define GC_LEVEL_MASK 0x3ff000006565-#define OHARE_LEVEL_MASK 0x1ff000006666-#define HEATHROW_LEVEL_MASK 0x1ff000006767-6868-static int max_irqs;6969-static int max_real_irqs;7070-static u32 level_mask[4];7171-7272-static DEFINE_SPINLOCK(pmac_pic_lock);7373-7474-7575-#define GATWICK_IRQ_POOL_SIZE 107676-static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE];7777-7878-#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)7979-static unsigned long ppc_lost_interrupts[NR_MASK_WORDS];8080-8181-/*8282- * Mark an irq as "lost". This is only used on the pmac8383- * since it can lose interrupts (see pmac_set_irq_mask).8484- * -- Cort8585- */8686-void8787-__set_lost(unsigned long irq_nr, int nokick)8888-{8989- if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) {9090- atomic_inc(&ppc_n_lost_interrupts);9191- if (!nokick)9292- set_dec(1);9393- }9494-}9595-9696-static void9797-pmac_mask_and_ack_irq(unsigned int irq_nr)9898-{9999- unsigned long bit = 1UL << (irq_nr & 0x1f);100100- int i = irq_nr >> 5;101101- unsigned long flags;102102-103103- if ((unsigned)irq_nr >= max_irqs)104104- return;105105-106106- clear_bit(irq_nr, ppc_cached_irq_mask);107107- if (test_and_clear_bit(irq_nr, ppc_lost_interrupts))108108- atomic_dec(&ppc_n_lost_interrupts);109109- spin_lock_irqsave(&pmac_pic_lock, flags);110110- out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);111111- out_le32(&pmac_irq_hw[i]->ack, bit);112112- do {113113- /* make sure ack gets to controller before we enable114114- interrupts */115115- mb();116116- } while((in_le32(&pmac_irq_hw[i]->enable) & bit)117117- != (ppc_cached_irq_mask[i] & bit));118118- spin_unlock_irqrestore(&pmac_pic_lock, flags);119119-}120120-121121-static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)122122-{123123- unsigned long bit = 1UL << (irq_nr & 0x1f);124124- int i = irq_nr >> 5;125125- unsigned long flags;126126-127127- if ((unsigned)irq_nr >= max_irqs)128128- return;129129-130130- spin_lock_irqsave(&pmac_pic_lock, flags);131131- /* enable unmasked interrupts */132132- out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);133133-134134- do {135135- /* make sure mask gets to controller before we136136- return to user */137137- mb();138138- } while((in_le32(&pmac_irq_hw[i]->enable) & bit)139139- != (ppc_cached_irq_mask[i] & bit));140140-141141- /*142142- * Unfortunately, setting the bit in the enable register143143- * when the device interrupt is already on *doesn't* set144144- * the bit in the flag register or request another interrupt.145145- */146146- if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level))147147- __set_lost((ulong)irq_nr, nokicklost);148148- spin_unlock_irqrestore(&pmac_pic_lock, flags);149149-}150150-151151-/* When an irq gets requested for the first client, if it's an152152- * edge interrupt, we clear any previous one on the controller153153- */154154-static unsigned int pmac_startup_irq(unsigned int irq_nr)155155-{156156- unsigned long bit = 1UL << (irq_nr & 0x1f);157157- int i = irq_nr >> 5;158158-159159- if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0)160160- out_le32(&pmac_irq_hw[i]->ack, bit);161161- set_bit(irq_nr, ppc_cached_irq_mask);162162- pmac_set_irq_mask(irq_nr, 0);163163-164164- return 0;165165-}166166-167167-static void pmac_mask_irq(unsigned int irq_nr)168168-{169169- clear_bit(irq_nr, ppc_cached_irq_mask);170170- pmac_set_irq_mask(irq_nr, 0);171171- mb();172172-}173173-174174-static void pmac_unmask_irq(unsigned int irq_nr)175175-{176176- set_bit(irq_nr, ppc_cached_irq_mask);177177- pmac_set_irq_mask(irq_nr, 0);178178-}179179-180180-static void pmac_end_irq(unsigned int irq_nr)181181-{182182- if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))183183- && irq_desc[irq_nr].action) {184184- set_bit(irq_nr, ppc_cached_irq_mask);185185- pmac_set_irq_mask(irq_nr, 1);186186- }187187-}188188-189189-190190-struct hw_interrupt_type pmac_pic = {191191- .typename = " PMAC-PIC ",192192- .startup = pmac_startup_irq,193193- .enable = pmac_unmask_irq,194194- .disable = pmac_mask_irq,195195- .ack = pmac_mask_and_ack_irq,196196- .end = pmac_end_irq,197197-};198198-199199-struct hw_interrupt_type gatwick_pic = {200200- .typename = " GATWICK ",201201- .startup = pmac_startup_irq,202202- .enable = pmac_unmask_irq,203203- .disable = pmac_mask_irq,204204- .ack = pmac_mask_and_ack_irq,205205- .end = pmac_end_irq,206206-};207207-208208-static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)209209-{210210- int irq, bits;211211-212212- for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) {213213- int i = irq >> 5;214214- bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];215215- /* We must read level interrupts from the level register */216216- bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]);217217- bits &= ppc_cached_irq_mask[i];218218- if (bits == 0)219219- continue;220220- irq += __ilog2(bits);221221- __do_IRQ(irq, regs);222222- return IRQ_HANDLED;223223- }224224- printk("gatwick irq not from gatwick pic\n");225225- return IRQ_NONE;226226-}227227-228228-int229229-pmac_get_irq(struct pt_regs *regs)230230-{231231- int irq;232232- unsigned long bits = 0;233233-234234-#ifdef CONFIG_SMP235235- void psurge_smp_message_recv(struct pt_regs *);236236-237237- /* IPI's are a hack on the powersurge -- Cort */238238- if ( smp_processor_id() != 0 ) {239239- psurge_smp_message_recv(regs);240240- return -2; /* ignore, already handled */241241- }242242-#endif /* CONFIG_SMP */243243- for (irq = max_real_irqs; (irq -= 32) >= 0; ) {244244- int i = irq >> 5;245245- bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];246246- /* We must read level interrupts from the level register */247247- bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]);248248- bits &= ppc_cached_irq_mask[i];249249- if (bits == 0)250250- continue;251251- irq += __ilog2(bits);252252- break;253253- }254254-255255- return irq;256256-}257257-258258-/* This routine will fix some missing interrupt values in the device tree259259- * on the gatwick mac-io controller used by some PowerBooks260260- */261261-static void __init262262-pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)263263-{264264- struct device_node *node;265265- int count;266266-267267- memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool));268268- node = gw->child;269269- count = 0;270270- while(node)271271- {272272- /* Fix SCC */273273- if (strcasecmp(node->name, "escc") == 0)274274- if (node->child) {275275- if (node->child->n_intrs < 3) {276276- node->child->intrs = &gatwick_int_pool[count];277277- count += 3;278278- }279279- node->child->n_intrs = 3;280280- node->child->intrs[0].line = 15+irq_base;281281- node->child->intrs[1].line = 4+irq_base;282282- node->child->intrs[2].line = 5+irq_base;283283- printk(KERN_INFO "irq: fixed SCC on second controller (%d,%d,%d)\n",284284- node->child->intrs[0].line,285285- node->child->intrs[1].line,286286- node->child->intrs[2].line);287287- }288288- /* Fix media-bay & left SWIM */289289- if (strcasecmp(node->name, "media-bay") == 0) {290290- struct device_node* ya_node;291291-292292- if (node->n_intrs == 0)293293- node->intrs = &gatwick_int_pool[count++];294294- node->n_intrs = 1;295295- node->intrs[0].line = 29+irq_base;296296- printk(KERN_INFO "irq: fixed media-bay on second controller (%d)\n",297297- node->intrs[0].line);298298-299299- ya_node = node->child;300300- while(ya_node)301301- {302302- if (strcasecmp(ya_node->name, "floppy") == 0) {303303- if (ya_node->n_intrs < 2) {304304- ya_node->intrs = &gatwick_int_pool[count];305305- count += 2;306306- }307307- ya_node->n_intrs = 2;308308- ya_node->intrs[0].line = 19+irq_base;309309- ya_node->intrs[1].line = 1+irq_base;310310- printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n",311311- ya_node->intrs[0].line, ya_node->intrs[1].line);312312- }313313- if (strcasecmp(ya_node->name, "ata4") == 0) {314314- if (ya_node->n_intrs < 2) {315315- ya_node->intrs = &gatwick_int_pool[count];316316- count += 2;317317- }318318- ya_node->n_intrs = 2;319319- ya_node->intrs[0].line = 14+irq_base;320320- ya_node->intrs[1].line = 3+irq_base;321321- printk(KERN_INFO "irq: fixed ide on second controller (%d,%d)\n",322322- ya_node->intrs[0].line, ya_node->intrs[1].line);323323- }324324- ya_node = ya_node->sibling;325325- }326326- }327327- node = node->sibling;328328- }329329- if (count > 10) {330330- printk("WARNING !! Gatwick interrupt pool overflow\n");331331- printk(" GATWICK_IRQ_POOL_SIZE = %d\n", GATWICK_IRQ_POOL_SIZE);332332- printk(" requested = %d\n", count);333333- }334334-}335335-336336-/*337337- * The PowerBook 3400/2400/3500 can have a combo ethernet/modem338338- * card which includes an ohare chip that acts as a second interrupt339339- * controller. If we find this second ohare, set it up and fix the340340- * interrupt value in the device tree for the ethernet chip.341341- */342342-static int __init enable_second_ohare(void)343343-{344344- unsigned char bus, devfn;345345- unsigned short cmd;346346- unsigned long addr;347347- struct device_node *irqctrler = find_devices("pci106b,7");348348- struct device_node *ether;349349-350350- if (irqctrler == NULL || irqctrler->n_addrs <= 0)351351- return -1;352352- addr = (unsigned long) ioremap(irqctrler->addrs[0].address, 0x40);353353- pmac_irq_hw[1] = (volatile struct pmac_irq_hw *)(addr + 0x20);354354- max_irqs = 64;355355- if (pci_device_from_OF_node(irqctrler, &bus, &devfn) == 0) {356356- struct pci_controller* hose = pci_find_hose_for_OF_device(irqctrler);357357- if (!hose)358358- printk(KERN_ERR "Can't find PCI hose for OHare2 !\n");359359- else {360360- early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd);361361- cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;362362- cmd &= ~PCI_COMMAND_IO;363363- early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd);364364- }365365- }366366-367367- /* Fix interrupt for the modem/ethernet combo controller. The number368368- in the device tree (27) is bogus (correct for the ethernet-only369369- board but not the combo ethernet/modem board).370370- The real interrupt is 28 on the second controller -> 28+32 = 60.371371- */372372- ether = find_devices("pci1011,14");373373- if (ether && ether->n_intrs > 0) {374374- ether->intrs[0].line = 60;375375- printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n",376376- ether->intrs[0].line);377377- }378378-379379- /* Return the interrupt number of the cascade */380380- return irqctrler->intrs[0].line;381381-}382382-383383-#ifdef CONFIG_POWER4384384-static irqreturn_t k2u3_action(int cpl, void *dev_id, struct pt_regs *regs)385385-{386386- int irq;387387-388388- irq = openpic2_get_irq(regs);389389- if (irq != -1)390390- __do_IRQ(irq, regs);391391- return IRQ_HANDLED;392392-}393393-394394-static struct irqaction k2u3_cascade_action = {395395- .handler = k2u3_action,396396- .flags = 0,397397- .mask = CPU_MASK_NONE,398398- .name = "U3->K2 Cascade",399399-};400400-#endif /* CONFIG_POWER4 */401401-402402-#ifdef CONFIG_XMON403403-static struct irqaction xmon_action = {404404- .handler = xmon_irq,405405- .flags = 0,406406- .mask = CPU_MASK_NONE,407407- .name = "NMI - XMON"408408-};409409-#endif410410-411411-static struct irqaction gatwick_cascade_action = {412412- .handler = gatwick_action,413413- .flags = SA_INTERRUPT,414414- .mask = CPU_MASK_NONE,415415- .name = "cascade",416416-};417417-418418-void __init pmac_pic_init(void)419419-{420420- int i;421421- struct device_node *irqctrler = NULL;422422- struct device_node *irqctrler2 = NULL;423423- struct device_node *np;424424- unsigned long addr;425425- int irq_cascade = -1;426426-427427- /* We first try to detect Apple's new Core99 chipset, since mac-io428428- * is quite different on those machines and contains an IBM MPIC2.429429- */430430- np = find_type_devices("open-pic");431431- while(np) {432432- if (np->parent && !strcmp(np->parent->name, "u3"))433433- irqctrler2 = np;434434- else435435- irqctrler = np;436436- np = np->next;437437- }438438- if (irqctrler != NULL)439439- {440440- if (irqctrler->n_addrs > 0)441441- {442442- unsigned char senses[128];443443-444444- printk(KERN_INFO "PowerMac using OpenPIC irq controller at 0x%08x\n",445445- irqctrler->addrs[0].address);446446-447447- prom_get_irq_senses(senses, 0, 128);448448- OpenPIC_InitSenses = senses;449449- OpenPIC_NumInitSenses = 128;450450- ppc_md.get_irq = openpic_get_irq;451451- pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler, 0, 0);452452- OpenPIC_Addr = ioremap(irqctrler->addrs[0].address,453453- irqctrler->addrs[0].size);454454- openpic_init(0);455455-456456-#ifdef CONFIG_POWER4457457- if (irqctrler2 != NULL && irqctrler2->n_intrs > 0 &&458458- irqctrler2->n_addrs > 0) {459459- printk(KERN_INFO "Slave OpenPIC at 0x%08x hooked on IRQ %d\n",460460- irqctrler2->addrs[0].address,461461- irqctrler2->intrs[0].line);462462- pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler2, 0, 0);463463- OpenPIC2_Addr = ioremap(irqctrler2->addrs[0].address,464464- irqctrler2->addrs[0].size);465465- prom_get_irq_senses(senses, PMAC_OPENPIC2_OFFSET,466466- PMAC_OPENPIC2_OFFSET+128);467467- OpenPIC_InitSenses = senses;468468- OpenPIC_NumInitSenses = 128;469469- openpic2_init(PMAC_OPENPIC2_OFFSET);470470-471471- if (setup_irq(irqctrler2->intrs[0].line,472472- &k2u3_cascade_action))473473- printk("Unable to get OpenPIC IRQ for cascade\n");474474- }475475-#endif /* CONFIG_POWER4 */476476-477477-#ifdef CONFIG_XMON478478- {479479- struct device_node* pswitch;480480- int nmi_irq;481481-482482- pswitch = find_devices("programmer-switch");483483- if (pswitch && pswitch->n_intrs) {484484- nmi_irq = pswitch->intrs[0].line;485485- openpic_init_nmi_irq(nmi_irq);486486- setup_irq(nmi_irq, &xmon_action);487487- }488488- }489489-#endif /* CONFIG_XMON */490490- return;491491- }492492- irqctrler = NULL;493493- }494494-495495- /* Get the level/edge settings, assume if it's not496496- * a Grand Central nor an OHare, then it's an Heathrow497497- * (or Paddington).498498- */499499- if (find_devices("gc"))500500- level_mask[0] = GC_LEVEL_MASK;501501- else if (find_devices("ohare")) {502502- level_mask[0] = OHARE_LEVEL_MASK;503503- /* We might have a second cascaded ohare */504504- level_mask[1] = OHARE_LEVEL_MASK;505505- } else {506506- level_mask[0] = HEATHROW_LEVEL_MASK;507507- level_mask[1] = 0;508508- /* We might have a second cascaded heathrow */509509- level_mask[2] = HEATHROW_LEVEL_MASK;510510- level_mask[3] = 0;511511- }512512-513513- /*514514- * G3 powermacs and 1999 G3 PowerBooks have 64 interrupts,515515- * 1998 G3 Series PowerBooks have 128,516516- * other powermacs have 32.517517- * The combo ethernet/modem card for the Powerstar powerbooks518518- * (2400/3400/3500, ohare based) has a second ohare chip519519- * effectively making a total of 64.520520- */521521- max_irqs = max_real_irqs = 32;522522- irqctrler = find_devices("mac-io");523523- if (irqctrler)524524- {525525- max_real_irqs = 64;526526- if (irqctrler->next)527527- max_irqs = 128;528528- else529529- max_irqs = 64;530530- }531531- for ( i = 0; i < max_real_irqs ; i++ )532532- irq_desc[i].handler = &pmac_pic;533533-534534- /* get addresses of first controller */535535- if (irqctrler) {536536- if (irqctrler->n_addrs > 0) {537537- addr = (unsigned long)538538- ioremap(irqctrler->addrs[0].address, 0x40);539539- for (i = 0; i < 2; ++i)540540- pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)541541- (addr + (2 - i) * 0x10);542542- }543543-544544- /* get addresses of second controller */545545- irqctrler = irqctrler->next;546546- if (irqctrler && irqctrler->n_addrs > 0) {547547- addr = (unsigned long)548548- ioremap(irqctrler->addrs[0].address, 0x40);549549- for (i = 2; i < 4; ++i)550550- pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)551551- (addr + (4 - i) * 0x10);552552- irq_cascade = irqctrler->intrs[0].line;553553- if (device_is_compatible(irqctrler, "gatwick"))554554- pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs);555555- }556556- } else {557557- /* older powermacs have a GC (grand central) or ohare at558558- f3000000, with interrupt control registers at f3000020. */559559- addr = (unsigned long) ioremap(0xf3000000, 0x40);560560- pmac_irq_hw[0] = (volatile struct pmac_irq_hw *) (addr + 0x20);561561- }562562-563563- /* PowerBooks 3400 and 3500 can have a second controller in a second564564- ohare chip, on the combo ethernet/modem card */565565- if (machine_is_compatible("AAPL,3400/2400")566566- || machine_is_compatible("AAPL,3500"))567567- irq_cascade = enable_second_ohare();568568-569569- /* disable all interrupts in all controllers */570570- for (i = 0; i * 32 < max_irqs; ++i)571571- out_le32(&pmac_irq_hw[i]->enable, 0);572572- /* mark level interrupts */573573- for (i = 0; i < max_irqs; i++)574574- if (level_mask[i >> 5] & (1UL << (i & 0x1f)))575575- irq_desc[i].status = IRQ_LEVEL;576576-577577- /* get interrupt line of secondary interrupt controller */578578- if (irq_cascade >= 0) {579579- printk(KERN_INFO "irq: secondary controller on irq %d\n",580580- (int)irq_cascade);581581- for ( i = max_real_irqs ; i < max_irqs ; i++ )582582- irq_desc[i].handler = &gatwick_pic;583583- setup_irq(irq_cascade, &gatwick_cascade_action);584584- }585585- printk("System has %d possible interrupts\n", max_irqs);586586- if (max_irqs != max_real_irqs)587587- printk(KERN_DEBUG "%d interrupts on main controller\n",588588- max_real_irqs);589589-590590-#ifdef CONFIG_XMON591591- setup_irq(20, &xmon_action);592592-#endif /* CONFIG_XMON */593593-}594594-595595-#ifdef CONFIG_PM596596-/*597597- * These procedures are used in implementing sleep on the powerbooks.598598- * sleep_save_intrs() saves the states of all interrupt enables599599- * and disables all interrupts except for the nominated one.600600- * sleep_restore_intrs() restores the states of all interrupt enables.601601- */602602-unsigned long sleep_save_mask[2];603603-604604-/* This used to be passed by the PMU driver but that link got605605- * broken with the new driver model. We use this tweak for now...606606- */607607-static int pmacpic_find_viaint(void)608608-{609609- int viaint = -1;610610-611611-#ifdef CONFIG_ADB_PMU612612- struct device_node *np;613613-614614- if (pmu_get_model() != PMU_OHARE_BASED)615615- goto not_found;616616- np = of_find_node_by_name(NULL, "via-pmu");617617- if (np == NULL)618618- goto not_found;619619- viaint = np->intrs[0].line;620620-#endif /* CONFIG_ADB_PMU */621621-622622-not_found:623623- return viaint;624624-}625625-626626-static int pmacpic_suspend(struct sys_device *sysdev, pm_message_t state)627627-{628628- int viaint = pmacpic_find_viaint();629629-630630- sleep_save_mask[0] = ppc_cached_irq_mask[0];631631- sleep_save_mask[1] = ppc_cached_irq_mask[1];632632- ppc_cached_irq_mask[0] = 0;633633- ppc_cached_irq_mask[1] = 0;634634- if (viaint > 0)635635- set_bit(viaint, ppc_cached_irq_mask);636636- out_le32(&pmac_irq_hw[0]->enable, ppc_cached_irq_mask[0]);637637- if (max_real_irqs > 32)638638- out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]);639639- (void)in_le32(&pmac_irq_hw[0]->event);640640- /* make sure mask gets to controller before we return to caller */641641- mb();642642- (void)in_le32(&pmac_irq_hw[0]->enable);643643-644644- return 0;645645-}646646-647647-static int pmacpic_resume(struct sys_device *sysdev)648648-{649649- int i;650650-651651- out_le32(&pmac_irq_hw[0]->enable, 0);652652- if (max_real_irqs > 32)653653- out_le32(&pmac_irq_hw[1]->enable, 0);654654- mb();655655- for (i = 0; i < max_real_irqs; ++i)656656- if (test_bit(i, sleep_save_mask))657657- pmac_unmask_irq(i);658658-659659- return 0;660660-}661661-662662-#endif /* CONFIG_PM */663663-664664-static struct sysdev_class pmacpic_sysclass = {665665- set_kset_name("pmac_pic"),666666-};667667-668668-static struct sys_device device_pmacpic = {669669- .id = 0,670670- .cls = &pmacpic_sysclass,671671-};672672-673673-static struct sysdev_driver driver_pmacpic = {674674-#ifdef CONFIG_PM675675- .suspend = &pmacpic_suspend,676676- .resume = &pmacpic_resume,677677-#endif /* CONFIG_PM */678678-};679679-680680-static int __init init_pmacpic_sysfs(void)681681-{682682- if (max_irqs == 0)683683- return -ENODEV;684684-685685- printk(KERN_DEBUG "Registering pmac pic with sysfs...\n");686686- sysdev_class_register(&pmacpic_sysclass);687687- sysdev_register(&device_pmacpic);688688- sysdev_driver_register(&pmacpic_sysclass, &driver_pmacpic);689689- return 0;690690-}691691-692692-subsys_initcall(init_pmacpic_sysfs);693693-
···11-/*22- * arch/ppc/platforms/setup.c33- *44- * PowerPC version55- * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)66- *77- * Adapted for Power Macintosh by Paul Mackerras88- * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)99- *1010- * Derived from "arch/alpha/kernel/setup.c"1111- * Copyright (C) 1995 Linus Torvalds1212- *1313- * Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org)1414- *1515- * This program is free software; you can redistribute it and/or1616- * modify it under the terms of the GNU General Public License1717- * as published by the Free Software Foundation; either version1818- * 2 of the License, or (at your option) any later version.1919- *2020- */2121-2222-/*2323- * bootup setup stuff..2424- */2525-2626-#include <linux/config.h>2727-#include <linux/init.h>2828-#include <linux/errno.h>2929-#include <linux/sched.h>3030-#include <linux/kernel.h>3131-#include <linux/mm.h>3232-#include <linux/stddef.h>3333-#include <linux/unistd.h>3434-#include <linux/ptrace.h>3535-#include <linux/slab.h>3636-#include <linux/user.h>3737-#include <linux/a.out.h>3838-#include <linux/tty.h>3939-#include <linux/string.h>4040-#include <linux/delay.h>4141-#include <linux/ioport.h>4242-#include <linux/major.h>4343-#include <linux/initrd.h>4444-#include <linux/vt_kern.h>4545-#include <linux/console.h>4646-#include <linux/ide.h>4747-#include <linux/pci.h>4848-#include <linux/adb.h>4949-#include <linux/cuda.h>5050-#include <linux/pmu.h>5151-#include <linux/seq_file.h>5252-#include <linux/root_dev.h>5353-#include <linux/bitops.h>5454-#include <linux/suspend.h>5555-5656-#include <asm/reg.h>5757-#include <asm/sections.h>5858-#include <asm/prom.h>5959-#include <asm/system.h>6060-#include <asm/pgtable.h>6161-#include <asm/io.h>6262-#include <asm/pci-bridge.h>6363-#include <asm/ohare.h>6464-#include <asm/mediabay.h>6565-#include <asm/machdep.h>6666-#include <asm/dma.h>6767-#include <asm/bootx.h>6868-#include <asm/cputable.h>6969-#include <asm/btext.h>7070-#include <asm/pmac_feature.h>7171-#include <asm/time.h>7272-#include <asm/of_device.h>7373-#include <asm/mmu_context.h>7474-7575-#include "pmac_pic.h"7676-#include "mem_pieces.h"7777-7878-#undef SHOW_GATWICK_IRQS7979-8080-extern long pmac_time_init(void);8181-extern unsigned long pmac_get_rtc_time(void);8282-extern int pmac_set_rtc_time(unsigned long nowtime);8383-extern void pmac_read_rtc_time(void);8484-extern void pmac_calibrate_decr(void);8585-extern void pmac_pcibios_fixup(void);8686-extern void pmac_find_bridges(void);8787-extern unsigned long pmac_ide_get_base(int index);8888-extern void pmac_ide_init_hwif_ports(hw_regs_t *hw,8989- unsigned long data_port, unsigned long ctrl_port, int *irq);9090-9191-extern void pmac_nvram_update(void);9292-extern unsigned char pmac_nvram_read_byte(int addr);9393-extern void pmac_nvram_write_byte(int addr, unsigned char val);9494-extern int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial);9595-extern void pmac_pcibios_after_init(void);9696-extern int of_show_percpuinfo(struct seq_file *m, int i);9797-9898-struct device_node *memory_node;9999-100100-unsigned char drive_info;101101-102102-int ppc_override_l2cr = 0;103103-int ppc_override_l2cr_value;104104-int has_l2cache = 0;105105-106106-static int current_root_goodness = -1;107107-108108-extern int pmac_newworld;109109-110110-#define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */111111-112112-extern void zs_kgdb_hook(int tty_num);113113-static void ohare_init(void);114114-#ifdef CONFIG_BOOTX_TEXT115115-static void pmac_progress(char *s, unsigned short hex);116116-#endif117117-118118-sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;119119-120120-#ifdef CONFIG_SMP121121-extern struct smp_ops_t psurge_smp_ops;122122-extern struct smp_ops_t core99_smp_ops;123123-#endif /* CONFIG_SMP */124124-125125-static int126126-pmac_show_cpuinfo(struct seq_file *m)127127-{128128- struct device_node *np;129129- char *pp;130130- int plen;131131- int mbmodel = pmac_call_feature(PMAC_FTR_GET_MB_INFO,132132- NULL, PMAC_MB_INFO_MODEL, 0);133133- unsigned int mbflags = (unsigned int)pmac_call_feature(PMAC_FTR_GET_MB_INFO,134134- NULL, PMAC_MB_INFO_FLAGS, 0);135135- char* mbname;136136-137137- if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME, (int)&mbname) != 0)138138- mbname = "Unknown";139139-140140- /* find motherboard type */141141- seq_printf(m, "machine\t\t: ");142142- np = find_devices("device-tree");143143- if (np != NULL) {144144- pp = (char *) get_property(np, "model", NULL);145145- if (pp != NULL)146146- seq_printf(m, "%s\n", pp);147147- else148148- seq_printf(m, "PowerMac\n");149149- pp = (char *) get_property(np, "compatible", &plen);150150- if (pp != NULL) {151151- seq_printf(m, "motherboard\t:");152152- while (plen > 0) {153153- int l = strlen(pp) + 1;154154- seq_printf(m, " %s", pp);155155- plen -= l;156156- pp += l;157157- }158158- seq_printf(m, "\n");159159- }160160- } else161161- seq_printf(m, "PowerMac\n");162162-163163- /* print parsed model */164164- seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname);165165- seq_printf(m, "pmac flags\t: %08x\n", mbflags);166166-167167- /* find l2 cache info */168168- np = find_devices("l2-cache");169169- if (np == 0)170170- np = find_type_devices("cache");171171- if (np != 0) {172172- unsigned int *ic = (unsigned int *)173173- get_property(np, "i-cache-size", NULL);174174- unsigned int *dc = (unsigned int *)175175- get_property(np, "d-cache-size", NULL);176176- seq_printf(m, "L2 cache\t:");177177- has_l2cache = 1;178178- if (get_property(np, "cache-unified", NULL) != 0 && dc) {179179- seq_printf(m, " %dK unified", *dc / 1024);180180- } else {181181- if (ic)182182- seq_printf(m, " %dK instruction", *ic / 1024);183183- if (dc)184184- seq_printf(m, "%s %dK data",185185- (ic? " +": ""), *dc / 1024);186186- }187187- pp = get_property(np, "ram-type", NULL);188188- if (pp)189189- seq_printf(m, " %s", pp);190190- seq_printf(m, "\n");191191- }192192-193193- /* find ram info */194194- np = find_devices("memory");195195- if (np != 0) {196196- int n;197197- struct reg_property *reg = (struct reg_property *)198198- get_property(np, "reg", &n);199199-200200- if (reg != 0) {201201- unsigned long total = 0;202202-203203- for (n /= sizeof(struct reg_property); n > 0; --n)204204- total += (reg++)->size;205205- seq_printf(m, "memory\t\t: %luMB\n", total >> 20);206206- }207207- }208208-209209- /* Checks "l2cr-value" property in the registry */210210- np = find_devices("cpus");211211- if (np == 0)212212- np = find_type_devices("cpu");213213- if (np != 0) {214214- unsigned int *l2cr = (unsigned int *)215215- get_property(np, "l2cr-value", NULL);216216- if (l2cr != 0) {217217- seq_printf(m, "l2cr override\t: 0x%x\n", *l2cr);218218- }219219- }220220-221221- /* Indicate newworld/oldworld */222222- seq_printf(m, "pmac-generation\t: %s\n",223223- pmac_newworld ? "NewWorld" : "OldWorld");224224-225225-226226- return 0;227227-}228228-229229-static int230230-pmac_show_percpuinfo(struct seq_file *m, int i)231231-{232232-#ifdef CONFIG_CPU_FREQ_PMAC233233- extern unsigned int pmac_get_one_cpufreq(int i);234234- unsigned int freq = pmac_get_one_cpufreq(i);235235- if (freq != 0) {236236- seq_printf(m, "clock\t\t: %dMHz\n", freq/1000);237237- return 0;238238- }239239-#endif /* CONFIG_CPU_FREQ_PMAC */240240- return of_show_percpuinfo(m, i);241241-}242242-243243-static volatile u32 *sysctrl_regs;244244-245245-void __init246246-pmac_setup_arch(void)247247-{248248- struct device_node *cpu;249249- int *fp;250250- unsigned long pvr;251251-252252- pvr = PVR_VER(mfspr(SPRN_PVR));253253-254254- /* Set loops_per_jiffy to a half-way reasonable value,255255- for use until calibrate_delay gets called. */256256- cpu = find_type_devices("cpu");257257- if (cpu != 0) {258258- fp = (int *) get_property(cpu, "clock-frequency", NULL);259259- if (fp != 0) {260260- if (pvr == 4 || pvr >= 8)261261- /* 604, G3, G4 etc. */262262- loops_per_jiffy = *fp / HZ;263263- else264264- /* 601, 603, etc. */265265- loops_per_jiffy = *fp / (2*HZ);266266- } else267267- loops_per_jiffy = 50000000 / HZ;268268- }269269-270270- /* this area has the CPU identification register271271- and some registers used by smp boards */272272- sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000);273273- ohare_init();274274-275275- /* Lookup PCI hosts */276276- pmac_find_bridges();277277-278278- /* Checks "l2cr-value" property in the registry */279279- if (cpu_has_feature(CPU_FTR_L2CR)) {280280- struct device_node *np = find_devices("cpus");281281- if (np == 0)282282- np = find_type_devices("cpu");283283- if (np != 0) {284284- unsigned int *l2cr = (unsigned int *)285285- get_property(np, "l2cr-value", NULL);286286- if (l2cr != 0) {287287- ppc_override_l2cr = 1;288288- ppc_override_l2cr_value = *l2cr;289289- _set_L2CR(0);290290- _set_L2CR(ppc_override_l2cr_value);291291- }292292- }293293- }294294-295295- if (ppc_override_l2cr)296296- printk(KERN_INFO "L2CR overriden (0x%x), backside cache is %s\n",297297- ppc_override_l2cr_value, (ppc_override_l2cr_value & 0x80000000)298298- ? "enabled" : "disabled");299299-300300-#ifdef CONFIG_KGDB301301- zs_kgdb_hook(0);302302-#endif303303-304304-#ifdef CONFIG_ADB_CUDA305305- find_via_cuda();306306-#else307307- if (find_devices("via-cuda")) {308308- printk("WARNING ! Your machine is Cuda based but your kernel\n");309309- printk(" wasn't compiled with CONFIG_ADB_CUDA option !\n");310310- }311311-#endif312312-#ifdef CONFIG_ADB_PMU313313- find_via_pmu();314314-#else315315- if (find_devices("via-pmu")) {316316- printk("WARNING ! Your machine is PMU based but your kernel\n");317317- printk(" wasn't compiled with CONFIG_ADB_PMU option !\n");318318- }319319-#endif320320-#ifdef CONFIG_NVRAM321321- pmac_nvram_init();322322-#endif323323-#ifdef CONFIG_BLK_DEV_INITRD324324- if (initrd_start)325325- ROOT_DEV = Root_RAM0;326326- else327327-#endif328328- ROOT_DEV = DEFAULT_ROOT_DEVICE;329329-330330-#ifdef CONFIG_SMP331331- /* Check for Core99 */332332- if (find_devices("uni-n") || find_devices("u3"))333333- smp_ops = &core99_smp_ops;334334- else335335- smp_ops = &psurge_smp_ops;336336-#endif /* CONFIG_SMP */337337-338338- pci_create_OF_bus_map();339339-}340340-341341-static void __init ohare_init(void)342342-{343343- /*344344- * Turn on the L2 cache.345345- * We assume that we have a PSX memory controller iff346346- * we have an ohare I/O controller.347347- */348348- if (find_devices("ohare") != NULL) {349349- if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) {350350- if (sysctrl_regs[4] & 0x10)351351- sysctrl_regs[4] |= 0x04000020;352352- else353353- sysctrl_regs[4] |= 0x04000000;354354- if(has_l2cache)355355- printk(KERN_INFO "Level 2 cache enabled\n");356356- }357357- }358358-}359359-360360-extern char *bootpath;361361-extern char *bootdevice;362362-void *boot_host;363363-int boot_target;364364-int boot_part;365365-extern dev_t boot_dev;366366-367367-#ifdef CONFIG_SCSI368368-void __init369369-note_scsi_host(struct device_node *node, void *host)370370-{371371- int l;372372- char *p;373373-374374- l = strlen(node->full_name);375375- if (bootpath != NULL && bootdevice != NULL376376- && strncmp(node->full_name, bootdevice, l) == 0377377- && (bootdevice[l] == '/' || bootdevice[l] == 0)) {378378- boot_host = host;379379- /*380380- * There's a bug in OF 1.0.5. (Why am I not surprised.)381381- * If you pass a path like scsi/sd@1:0 to canon, it returns382382- * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0383383- * That is, the scsi target number doesn't get preserved.384384- * So we pick the target number out of bootpath and use that.385385- */386386- p = strstr(bootpath, "/sd@");387387- if (p != NULL) {388388- p += 4;389389- boot_target = simple_strtoul(p, NULL, 10);390390- p = strchr(p, ':');391391- if (p != NULL)392392- boot_part = simple_strtoul(p + 1, NULL, 10);393393- }394394- }395395-}396396-#endif397397-398398-#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)399399-static dev_t __init400400-find_ide_boot(void)401401-{402402- char *p;403403- int n;404404- dev_t __init pmac_find_ide_boot(char *bootdevice, int n);405405-406406- if (bootdevice == NULL)407407- return 0;408408- p = strrchr(bootdevice, '/');409409- if (p == NULL)410410- return 0;411411- n = p - bootdevice;412412-413413- return pmac_find_ide_boot(bootdevice, n);414414-}415415-#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */416416-417417-static void __init418418-find_boot_device(void)419419-{420420-#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)421421- boot_dev = find_ide_boot();422422-#endif423423-}424424-425425-static int initializing = 1;426426-/* TODO: Merge the suspend-to-ram with the common code !!!427427- * currently, this is a stub implementation for suspend-to-disk428428- * only429429- */430430-431431-#ifdef CONFIG_SOFTWARE_SUSPEND432432-433433-static int pmac_pm_prepare(suspend_state_t state)434434-{435435- printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);436436-437437- return 0;438438-}439439-440440-static int pmac_pm_enter(suspend_state_t state)441441-{442442- printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);443443-444444- /* Giveup the lazy FPU & vec so we don't have to back them445445- * up from the low level code446446- */447447- enable_kernel_fp();448448-449449-#ifdef CONFIG_ALTIVEC450450- if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)451451- enable_kernel_altivec();452452-#endif /* CONFIG_ALTIVEC */453453-454454- return 0;455455-}456456-457457-static int pmac_pm_finish(suspend_state_t state)458458-{459459- printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);460460-461461- /* Restore userland MMU context */462462- set_context(current->active_mm->context, current->active_mm->pgd);463463-464464- return 0;465465-}466466-467467-static struct pm_ops pmac_pm_ops = {468468- .pm_disk_mode = PM_DISK_SHUTDOWN,469469- .prepare = pmac_pm_prepare,470470- .enter = pmac_pm_enter,471471- .finish = pmac_pm_finish,472472-};473473-474474-#endif /* CONFIG_SOFTWARE_SUSPEND */475475-476476-static int pmac_late_init(void)477477-{478478- initializing = 0;479479-#ifdef CONFIG_SOFTWARE_SUSPEND480480- pm_set_ops(&pmac_pm_ops);481481-#endif /* CONFIG_SOFTWARE_SUSPEND */482482- return 0;483483-}484484-485485-late_initcall(pmac_late_init);486486-487487-/* can't be __init - can be called whenever a disk is first accessed */488488-void489489-note_bootable_part(dev_t dev, int part, int goodness)490490-{491491- static int found_boot = 0;492492- char *p;493493-494494- if (!initializing)495495- return;496496- if ((goodness <= current_root_goodness) &&497497- ROOT_DEV != DEFAULT_ROOT_DEVICE)498498- return;499499- p = strstr(saved_command_line, "root=");500500- if (p != NULL && (p == saved_command_line || p[-1] == ' '))501501- return;502502-503503- if (!found_boot) {504504- find_boot_device();505505- found_boot = 1;506506- }507507- if (!boot_dev || dev == boot_dev) {508508- ROOT_DEV = dev + part;509509- boot_dev = 0;510510- current_root_goodness = goodness;511511- }512512-}513513-514514-static void515515-pmac_restart(char *cmd)516516-{517517-#ifdef CONFIG_ADB_CUDA518518- struct adb_request req;519519-#endif /* CONFIG_ADB_CUDA */520520-521521- switch (sys_ctrler) {522522-#ifdef CONFIG_ADB_CUDA523523- case SYS_CTRLER_CUDA:524524- cuda_request(&req, NULL, 2, CUDA_PACKET,525525- CUDA_RESET_SYSTEM);526526- for (;;)527527- cuda_poll();528528- break;529529-#endif /* CONFIG_ADB_CUDA */530530-#ifdef CONFIG_ADB_PMU531531- case SYS_CTRLER_PMU:532532- pmu_restart();533533- break;534534-#endif /* CONFIG_ADB_PMU */535535- default: ;536536- }537537-}538538-539539-static void540540-pmac_power_off(void)541541-{542542-#ifdef CONFIG_ADB_CUDA543543- struct adb_request req;544544-#endif /* CONFIG_ADB_CUDA */545545-546546- switch (sys_ctrler) {547547-#ifdef CONFIG_ADB_CUDA548548- case SYS_CTRLER_CUDA:549549- cuda_request(&req, NULL, 2, CUDA_PACKET,550550- CUDA_POWERDOWN);551551- for (;;)552552- cuda_poll();553553- break;554554-#endif /* CONFIG_ADB_CUDA */555555-#ifdef CONFIG_ADB_PMU556556- case SYS_CTRLER_PMU:557557- pmu_shutdown();558558- break;559559-#endif /* CONFIG_ADB_PMU */560560- default: ;561561- }562562-}563563-564564-static void565565-pmac_halt(void)566566-{567567- pmac_power_off();568568-}569569-570570-/*571571- * Read in a property describing some pieces of memory.572572- */573573-574574-static int __init575575-get_mem_prop(char *name, struct mem_pieces *mp)576576-{577577- struct reg_property *rp;578578- int i, s;579579- unsigned int *ip;580580- int nac = prom_n_addr_cells(memory_node);581581- int nsc = prom_n_size_cells(memory_node);582582-583583- ip = (unsigned int *) get_property(memory_node, name, &s);584584- if (ip == NULL) {585585- printk(KERN_ERR "error: couldn't get %s property on /memory\n",586586- name);587587- return 0;588588- }589589- s /= (nsc + nac) * 4;590590- rp = mp->regions;591591- for (i = 0; i < s; ++i, ip += nac+nsc) {592592- if (nac >= 2 && ip[nac-2] != 0)593593- continue;594594- rp->address = ip[nac-1];595595- if (nsc >= 2 && ip[nac+nsc-2] != 0)596596- rp->size = ~0U;597597- else598598- rp->size = ip[nac+nsc-1];599599- ++rp;600600- }601601- mp->n_regions = rp - mp->regions;602602-603603- /* Make sure the pieces are sorted. */604604- mem_pieces_sort(mp);605605- mem_pieces_coalesce(mp);606606- return 1;607607-}608608-609609-/*610610- * On systems with Open Firmware, collect information about611611- * physical RAM and which pieces are already in use.612612- * At this point, we have (at least) the first 8MB mapped with a BAT.613613- * Our text, data, bss use something over 1MB, starting at 0.614614- * Open Firmware may be using 1MB at the 4MB point.615615- */616616-unsigned long __init617617-pmac_find_end_of_memory(void)618618-{619619- unsigned long a, total;620620- struct mem_pieces phys_mem;621621-622622- /*623623- * Find out where physical memory is, and check that it624624- * starts at 0 and is contiguous. It seems that RAM is625625- * always physically contiguous on Power Macintoshes.626626- *627627- * Supporting discontiguous physical memory isn't hard,628628- * it just makes the virtual <-> physical mapping functions629629- * more complicated (or else you end up wasting space630630- * in mem_map).631631- */632632- memory_node = find_devices("memory");633633- if (memory_node == NULL || !get_mem_prop("reg", &phys_mem)634634- || phys_mem.n_regions == 0)635635- panic("No RAM??");636636- a = phys_mem.regions[0].address;637637- if (a != 0)638638- panic("RAM doesn't start at physical address 0");639639- total = phys_mem.regions[0].size;640640-641641- if (phys_mem.n_regions > 1) {642642- printk("RAM starting at 0x%x is not contiguous\n",643643- phys_mem.regions[1].address);644644- printk("Using RAM from 0 to 0x%lx\n", total-1);645645- }646646-647647- return total;648648-}649649-650650-void __init651651-pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,652652- unsigned long r6, unsigned long r7)653653-{654654- /* isa_io_base gets set in pmac_find_bridges */655655- isa_mem_base = PMAC_ISA_MEM_BASE;656656- pci_dram_offset = PMAC_PCI_DRAM_OFFSET;657657- ISA_DMA_THRESHOLD = ~0L;658658- DMA_MODE_READ = 1;659659- DMA_MODE_WRITE = 2;660660-661661- ppc_md.setup_arch = pmac_setup_arch;662662- ppc_md.show_cpuinfo = pmac_show_cpuinfo;663663- ppc_md.show_percpuinfo = pmac_show_percpuinfo;664664- ppc_md.init_IRQ = pmac_pic_init;665665- ppc_md.get_irq = pmac_get_irq; /* Changed later on ... */666666-667667- ppc_md.pcibios_fixup = pmac_pcibios_fixup;668668- ppc_md.pcibios_enable_device_hook = pmac_pci_enable_device_hook;669669- ppc_md.pcibios_after_init = pmac_pcibios_after_init;670670- ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;671671-672672- ppc_md.restart = pmac_restart;673673- ppc_md.power_off = pmac_power_off;674674- ppc_md.halt = pmac_halt;675675-676676- ppc_md.time_init = pmac_time_init;677677- ppc_md.set_rtc_time = pmac_set_rtc_time;678678- ppc_md.get_rtc_time = pmac_get_rtc_time;679679- ppc_md.calibrate_decr = pmac_calibrate_decr;680680-681681- ppc_md.find_end_of_memory = pmac_find_end_of_memory;682682-683683- ppc_md.feature_call = pmac_do_feature_call;684684-685685-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)686686-#ifdef CONFIG_BLK_DEV_IDE_PMAC687687- ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports;688688- ppc_ide_md.default_io_base = pmac_ide_get_base;689689-#endif /* CONFIG_BLK_DEV_IDE_PMAC */690690-#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */691691-692692-#ifdef CONFIG_BOOTX_TEXT693693- ppc_md.progress = pmac_progress;694694-#endif /* CONFIG_BOOTX_TEXT */695695-696696- if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0);697697-698698-}699699-700700-#ifdef CONFIG_BOOTX_TEXT701701-static void __init702702-pmac_progress(char *s, unsigned short hex)703703-{704704- if (boot_text_mapped) {705705- btext_drawstring(s);706706- btext_drawchar('\n');707707- }708708-}709709-#endif /* CONFIG_BOOTX_TEXT */710710-711711-static int __init712712-pmac_declare_of_platform_devices(void)713713-{714714- struct device_node *np;715715-716716- np = find_devices("uni-n");717717- if (np) {718718- for (np = np->child; np != NULL; np = np->sibling)719719- if (strncmp(np->name, "i2c", 3) == 0) {720720- of_platform_device_create(np, "uni-n-i2c",721721- NULL);722722- break;723723- }724724- }725725- np = find_devices("u3");726726- if (np) {727727- for (np = np->child; np != NULL; np = np->sibling)728728- if (strncmp(np->name, "i2c", 3) == 0) {729729- of_platform_device_create(np, "u3-i2c",730730- NULL);731731- break;732732- }733733- }734734-735735- np = find_devices("valkyrie");736736- if (np)737737- of_platform_device_create(np, "valkyrie", NULL);738738- np = find_devices("platinum");739739- if (np)740740- of_platform_device_create(np, "platinum", NULL);741741-742742- return 0;743743-}744744-745745-device_initcall(pmac_declare_of_platform_devices);
-396
arch/ppc/platforms/pmac_sleep.S
···11-/*22- * This file contains sleep low-level functions for PowerBook G3.33- * Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org)44- * and Paul Mackerras (paulus@samba.org).55- *66- * This program is free software; you can redistribute it and/or77- * modify it under the terms of the GNU General Public License88- * as published by the Free Software Foundation; either version99- * 2 of the License, or (at your option) any later version.1010- *1111- */1212-1313-#include <linux/config.h>1414-#include <asm/processor.h>1515-#include <asm/page.h>1616-#include <asm/ppc_asm.h>1717-#include <asm/cputable.h>1818-#include <asm/cache.h>1919-#include <asm/thread_info.h>2020-#include <asm/asm-offsets.h>2121-2222-#define MAGIC 0x4c617273 /* 'Lars' */2323-2424-/*2525- * Structure for storing CPU registers on the stack.2626- */2727-#define SL_SP 02828-#define SL_PC 42929-#define SL_MSR 83030-#define SL_SDR1 0xc3131-#define SL_SPRG0 0x10 /* 4 sprg's */3232-#define SL_DBAT0 0x203333-#define SL_IBAT0 0x283434-#define SL_DBAT1 0x303535-#define SL_IBAT1 0x383636-#define SL_DBAT2 0x403737-#define SL_IBAT2 0x483838-#define SL_DBAT3 0x503939-#define SL_IBAT3 0x584040-#define SL_TB 0x604141-#define SL_R2 0x684242-#define SL_CR 0x6c4343-#define SL_R12 0x70 /* r12 to r31 */4444-#define SL_SIZE (SL_R12 + 80)4545-4646- .section .text4747- .align 54848-4949-#if defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ_PMAC)5050-5151-/* This gets called by via-pmu.c late during the sleep process.5252- * The PMU was already send the sleep command and will shut us down5353- * soon. We need to save all that is needed and setup the wakeup5454- * vector that will be called by the ROM on wakeup5555- */5656-_GLOBAL(low_sleep_handler)5757-#ifndef CONFIG_6xx5858- blr5959-#else6060- mflr r06161- stw r0,4(r1)6262- stwu r1,-SL_SIZE(r1)6363- mfcr r06464- stw r0,SL_CR(r1)6565- stw r2,SL_R2(r1)6666- stmw r12,SL_R12(r1)6767-6868- /* Save MSR & SDR1 */6969- mfmsr r47070- stw r4,SL_MSR(r1)7171- mfsdr1 r47272- stw r4,SL_SDR1(r1)7373-7474- /* Get a stable timebase and save it */7575-1: mftbu r47676- stw r4,SL_TB(r1)7777- mftb r57878- stw r5,SL_TB+4(r1)7979- mftbu r38080- cmpw r3,r48181- bne 1b8282-8383- /* Save SPRGs */8484- mfsprg r4,08585- stw r4,SL_SPRG0(r1)8686- mfsprg r4,18787- stw r4,SL_SPRG0+4(r1)8888- mfsprg r4,28989- stw r4,SL_SPRG0+8(r1)9090- mfsprg r4,39191- stw r4,SL_SPRG0+12(r1)9292-9393- /* Save BATs */9494- mfdbatu r4,09595- stw r4,SL_DBAT0(r1)9696- mfdbatl r4,09797- stw r4,SL_DBAT0+4(r1)9898- mfdbatu r4,19999- stw r4,SL_DBAT1(r1)100100- mfdbatl r4,1101101- stw r4,SL_DBAT1+4(r1)102102- mfdbatu r4,2103103- stw r4,SL_DBAT2(r1)104104- mfdbatl r4,2105105- stw r4,SL_DBAT2+4(r1)106106- mfdbatu r4,3107107- stw r4,SL_DBAT3(r1)108108- mfdbatl r4,3109109- stw r4,SL_DBAT3+4(r1)110110- mfibatu r4,0111111- stw r4,SL_IBAT0(r1)112112- mfibatl r4,0113113- stw r4,SL_IBAT0+4(r1)114114- mfibatu r4,1115115- stw r4,SL_IBAT1(r1)116116- mfibatl r4,1117117- stw r4,SL_IBAT1+4(r1)118118- mfibatu r4,2119119- stw r4,SL_IBAT2(r1)120120- mfibatl r4,2121121- stw r4,SL_IBAT2+4(r1)122122- mfibatu r4,3123123- stw r4,SL_IBAT3(r1)124124- mfibatl r4,3125125- stw r4,SL_IBAT3+4(r1)126126-127127- /* Backup various CPU config stuffs */128128- bl __save_cpu_setup129129-130130- /* The ROM can wake us up via 2 different vectors:131131- * - On wallstreet & lombard, we must write a magic132132- * value 'Lars' at address 4 and a pointer to a133133- * memory location containing the PC to resume from134134- * at address 0.135135- * - On Core99, we must store the wakeup vector at136136- * address 0x80 and eventually it's parameters137137- * at address 0x84. I've have some trouble with those138138- * parameters however and I no longer use them.139139- */140140- lis r5,grackle_wake_up@ha141141- addi r5,r5,grackle_wake_up@l142142- tophys(r5,r5)143143- stw r5,SL_PC(r1)144144- lis r4,KERNELBASE@h145145- tophys(r5,r1)146146- addi r5,r5,SL_PC147147- lis r6,MAGIC@ha148148- addi r6,r6,MAGIC@l149149- stw r5,0(r4)150150- stw r6,4(r4)151151- /* Setup stuffs at 0x80-0x84 for Core99 */152152- lis r3,core99_wake_up@ha153153- addi r3,r3,core99_wake_up@l154154- tophys(r3,r3)155155- stw r3,0x80(r4)156156- stw r5,0x84(r4)157157- /* Store a pointer to our backup storage into158158- * a kernel global159159- */160160- lis r3,sleep_storage@ha161161- addi r3,r3,sleep_storage@l162162- stw r5,0(r3)163163-164164- .globl low_cpu_die165165-low_cpu_die:166166- /* Flush & disable all caches */167167- bl flush_disable_caches168168-169169- /* Turn off data relocation. */170170- mfmsr r3 /* Save MSR in r7 */171171- rlwinm r3,r3,0,28,26 /* Turn off DR bit */172172- sync173173- mtmsr r3174174- isync175175-176176-BEGIN_FTR_SECTION177177- /* Flush any pending L2 data prefetches to work around HW bug */178178- sync179179- lis r3,0xfff0180180- lwz r0,0(r3) /* perform cache-inhibited load to ROM */181181- sync /* (caches are disabled at this point) */182182-END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)183183-184184-/*185185- * Set the HID0 and MSR for sleep.186186- */187187- mfspr r2,SPRN_HID0188188- rlwinm r2,r2,0,10,7 /* clear doze, nap */189189- oris r2,r2,HID0_SLEEP@h190190- sync191191- isync192192- mtspr SPRN_HID0,r2193193- sync194194-195195-/* This loop puts us back to sleep in case we have a spurrious196196- * wakeup so that the host bridge properly stays asleep. The197197- * CPU will be turned off, either after a known time (about 1198198- * second) on wallstreet & lombard, or as soon as the CPU enters199199- * SLEEP mode on core99200200- */201201- mfmsr r2202202- oris r2,r2,MSR_POW@h203203-1: sync204204- mtmsr r2205205- isync206206- b 1b207207-208208-/*209209- * Here is the resume code.210210- */211211-212212-213213-/*214214- * Core99 machines resume here215215- * r4 has the physical address of SL_PC(sp) (unused)216216- */217217-_GLOBAL(core99_wake_up)218218- /* Make sure HID0 no longer contains any sleep bit and that data cache219219- * is disabled220220- */221221- mfspr r3,SPRN_HID0222222- rlwinm r3,r3,0,11,7 /* clear SLEEP, NAP, DOZE bits */223223- rlwinm 3,r3,0,18,15 /* clear DCE, ICE */224224- mtspr SPRN_HID0,r3225225- sync226226- isync227227-228228- /* sanitize MSR */229229- mfmsr r3230230- ori r3,r3,MSR_EE|MSR_IP231231- xori r3,r3,MSR_EE|MSR_IP232232- sync233233- isync234234- mtmsr r3235235- sync236236- isync237237-238238- /* Recover sleep storage */239239- lis r3,sleep_storage@ha240240- addi r3,r3,sleep_storage@l241241- tophys(r3,r3)242242- lwz r1,0(r3)243243-244244- /* Pass thru to older resume code ... */245245-/*246246- * Here is the resume code for older machines.247247- * r1 has the physical address of SL_PC(sp).248248- */249249-250250-grackle_wake_up:251251-252252- /* Restore the kernel's segment registers before253253- * we do any r1 memory access as we are not sure they254254- * are in a sane state above the first 256Mb region255255- */256256- li r0,16 /* load up segment register values */257257- mtctr r0 /* for context 0 */258258- lis r3,0x2000 /* Ku = 1, VSID = 0 */259259- li r4,0260260-3: mtsrin r3,r4261261- addi r3,r3,0x111 /* increment VSID */262262- addis r4,r4,0x1000 /* address of next segment */263263- bdnz 3b264264- sync265265- isync266266-267267- subi r1,r1,SL_PC268268-269269- /* Restore various CPU config stuffs */270270- bl __restore_cpu_setup271271-272272- /* Make sure all FPRs have been initialized */273273- bl reloc_offset274274- bl __init_fpu_registers275275-276276- /* Invalidate & enable L1 cache, we don't care about277277- * whatever the ROM may have tried to write to memory278278- */279279- bl __inval_enable_L1280280-281281- /* Restore the BATs, and SDR1. Then we can turn on the MMU. */282282- lwz r4,SL_SDR1(r1)283283- mtsdr1 r4284284- lwz r4,SL_SPRG0(r1)285285- mtsprg 0,r4286286- lwz r4,SL_SPRG0+4(r1)287287- mtsprg 1,r4288288- lwz r4,SL_SPRG0+8(r1)289289- mtsprg 2,r4290290- lwz r4,SL_SPRG0+12(r1)291291- mtsprg 3,r4292292-293293- lwz r4,SL_DBAT0(r1)294294- mtdbatu 0,r4295295- lwz r4,SL_DBAT0+4(r1)296296- mtdbatl 0,r4297297- lwz r4,SL_DBAT1(r1)298298- mtdbatu 1,r4299299- lwz r4,SL_DBAT1+4(r1)300300- mtdbatl 1,r4301301- lwz r4,SL_DBAT2(r1)302302- mtdbatu 2,r4303303- lwz r4,SL_DBAT2+4(r1)304304- mtdbatl 2,r4305305- lwz r4,SL_DBAT3(r1)306306- mtdbatu 3,r4307307- lwz r4,SL_DBAT3+4(r1)308308- mtdbatl 3,r4309309- lwz r4,SL_IBAT0(r1)310310- mtibatu 0,r4311311- lwz r4,SL_IBAT0+4(r1)312312- mtibatl 0,r4313313- lwz r4,SL_IBAT1(r1)314314- mtibatu 1,r4315315- lwz r4,SL_IBAT1+4(r1)316316- mtibatl 1,r4317317- lwz r4,SL_IBAT2(r1)318318- mtibatu 2,r4319319- lwz r4,SL_IBAT2+4(r1)320320- mtibatl 2,r4321321- lwz r4,SL_IBAT3(r1)322322- mtibatu 3,r4323323- lwz r4,SL_IBAT3+4(r1)324324- mtibatl 3,r4325325-326326-BEGIN_FTR_SECTION327327- li r4,0328328- mtspr SPRN_DBAT4U,r4329329- mtspr SPRN_DBAT4L,r4330330- mtspr SPRN_DBAT5U,r4331331- mtspr SPRN_DBAT5L,r4332332- mtspr SPRN_DBAT6U,r4333333- mtspr SPRN_DBAT6L,r4334334- mtspr SPRN_DBAT7U,r4335335- mtspr SPRN_DBAT7L,r4336336- mtspr SPRN_IBAT4U,r4337337- mtspr SPRN_IBAT4L,r4338338- mtspr SPRN_IBAT5U,r4339339- mtspr SPRN_IBAT5L,r4340340- mtspr SPRN_IBAT6U,r4341341- mtspr SPRN_IBAT6L,r4342342- mtspr SPRN_IBAT7U,r4343343- mtspr SPRN_IBAT7L,r4344344-END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS)345345-346346- /* Flush all TLBs */347347- lis r4,0x1000348348-1: addic. r4,r4,-0x1000349349- tlbie r4350350- blt 1b351351- sync352352-353353- /* restore the MSR and turn on the MMU */354354- lwz r3,SL_MSR(r1)355355- bl turn_on_mmu356356-357357- /* get back the stack pointer */358358- tovirt(r1,r1)359359-360360- /* Restore TB */361361- li r3,0362362- mttbl r3363363- lwz r3,SL_TB(r1)364364- lwz r4,SL_TB+4(r1)365365- mttbu r3366366- mttbl r4367367-368368- /* Restore the callee-saved registers and return */369369- lwz r0,SL_CR(r1)370370- mtcr r0371371- lwz r2,SL_R2(r1)372372- lmw r12,SL_R12(r1)373373- addi r1,r1,SL_SIZE374374- lwz r0,4(r1)375375- mtlr r0376376- blr377377-378378-turn_on_mmu:379379- mflr r4380380- tovirt(r4,r4)381381- mtsrr0 r4382382- mtsrr1 r3383383- sync384384- isync385385- rfi386386-387387-#endif /* defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ) */388388-389389- .section .data390390- .balign L1_CACHE_BYTES391391-sleep_storage:392392- .long 0393393- .balign L1_CACHE_BYTES, 0394394-395395-#endif /* CONFIG_6xx */396396- .section .text
-692
arch/ppc/platforms/pmac_smp.c
···11-/*22- * SMP support for power macintosh.33- *44- * We support both the old "powersurge" SMP architecture55- * and the current Core99 (G4 PowerMac) machines.66- *77- * Note that we don't support the very first rev. of88- * Apple/DayStar 2 CPUs board, the one with the funky99- * watchdog. Hopefully, none of these should be there except1010- * maybe internally to Apple. I should probably still add some1111- * code to detect this card though and disable SMP. --BenH.1212- *1313- * Support Macintosh G4 SMP by Troy Benjegerdes (hozer@drgw.net)1414- * and Ben Herrenschmidt <benh@kernel.crashing.org>.1515- *1616- * Support for DayStar quad CPU cards1717- * Copyright (C) XLR8, Inc. 1994-20001818- *1919- * This program is free software; you can redistribute it and/or2020- * modify it under the terms of the GNU General Public License2121- * as published by the Free Software Foundation; either version2222- * 2 of the License, or (at your option) any later version.2323- */2424-#include <linux/config.h>2525-#include <linux/kernel.h>2626-#include <linux/sched.h>2727-#include <linux/smp.h>2828-#include <linux/smp_lock.h>2929-#include <linux/interrupt.h>3030-#include <linux/kernel_stat.h>3131-#include <linux/delay.h>3232-#include <linux/init.h>3333-#include <linux/spinlock.h>3434-#include <linux/errno.h>3535-#include <linux/hardirq.h>3636-#include <linux/cpu.h>3737-3838-#include <asm/ptrace.h>3939-#include <asm/atomic.h>4040-#include <asm/irq.h>4141-#include <asm/page.h>4242-#include <asm/pgtable.h>4343-#include <asm/sections.h>4444-#include <asm/io.h>4545-#include <asm/prom.h>4646-#include <asm/smp.h>4747-#include <asm/residual.h>4848-#include <asm/machdep.h>4949-#include <asm/pmac_feature.h>5050-#include <asm/time.h>5151-#include <asm/open_pic.h>5252-#include <asm/cacheflush.h>5353-#include <asm/keylargo.h>5454-5555-/*5656- * Powersurge (old powermac SMP) support.5757- */5858-5959-extern void __secondary_start_pmac_0(void);6060-6161-/* Addresses for powersurge registers */6262-#define HAMMERHEAD_BASE 0xf80000006363-#define HHEAD_CONFIG 0x906464-#define HHEAD_SEC_INTR 0xc06565-6666-/* register for interrupting the primary processor on the powersurge */6767-/* N.B. this is actually the ethernet ROM! */6868-#define PSURGE_PRI_INTR 0xf30190006969-7070-/* register for storing the start address for the secondary processor */7171-/* N.B. this is the PCI config space address register for the 1st bridge */7272-#define PSURGE_START 0xf28000007373-7474-/* Daystar/XLR8 4-CPU card */7575-#define PSURGE_QUAD_REG_ADDR 0xf88000007676-7777-#define PSURGE_QUAD_IRQ_SET 07878-#define PSURGE_QUAD_IRQ_CLR 17979-#define PSURGE_QUAD_IRQ_PRIMARY 28080-#define PSURGE_QUAD_CKSTOP_CTL 38181-#define PSURGE_QUAD_PRIMARY_ARB 48282-#define PSURGE_QUAD_BOARD_ID 68383-#define PSURGE_QUAD_WHICH_CPU 78484-#define PSURGE_QUAD_CKSTOP_RDBK 88585-#define PSURGE_QUAD_RESET_CTL 118686-8787-#define PSURGE_QUAD_OUT(r, v) (out_8(quad_base + ((r) << 4) + 4, (v)))8888-#define PSURGE_QUAD_IN(r) (in_8(quad_base + ((r) << 4) + 4) & 0x0f)8989-#define PSURGE_QUAD_BIS(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) | (v)))9090-#define PSURGE_QUAD_BIC(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v)))9191-9292-/* virtual addresses for the above */9393-static volatile u8 __iomem *hhead_base;9494-static volatile u8 __iomem *quad_base;9595-static volatile u32 __iomem *psurge_pri_intr;9696-static volatile u8 __iomem *psurge_sec_intr;9797-static volatile u32 __iomem *psurge_start;9898-9999-/* values for psurge_type */100100-#define PSURGE_NONE -1101101-#define PSURGE_DUAL 0102102-#define PSURGE_QUAD_OKEE 1103103-#define PSURGE_QUAD_COTTON 2104104-#define PSURGE_QUAD_ICEGRASS 3105105-106106-/* what sort of powersurge board we have */107107-static int psurge_type = PSURGE_NONE;108108-109109-/* L2 and L3 cache settings to pass from CPU0 to CPU1 */110110-volatile static long int core99_l2_cache;111111-volatile static long int core99_l3_cache;112112-113113-/* Timebase freeze GPIO */114114-static unsigned int core99_tb_gpio;115115-116116-/* Sync flag for HW tb sync */117117-static volatile int sec_tb_reset = 0;118118-static unsigned int pri_tb_hi, pri_tb_lo;119119-static unsigned int pri_tb_stamp;120120-121121-static void __devinit core99_init_caches(int cpu)122122-{123123- if (!cpu_has_feature(CPU_FTR_L2CR))124124- return;125125-126126- if (cpu == 0) {127127- core99_l2_cache = _get_L2CR();128128- printk("CPU0: L2CR is %lx\n", core99_l2_cache);129129- } else {130130- printk("CPU%d: L2CR was %lx\n", cpu, _get_L2CR());131131- _set_L2CR(0);132132- _set_L2CR(core99_l2_cache);133133- printk("CPU%d: L2CR set to %lx\n", cpu, core99_l2_cache);134134- }135135-136136- if (!cpu_has_feature(CPU_FTR_L3CR))137137- return;138138-139139- if (cpu == 0){140140- core99_l3_cache = _get_L3CR();141141- printk("CPU0: L3CR is %lx\n", core99_l3_cache);142142- } else {143143- printk("CPU%d: L3CR was %lx\n", cpu, _get_L3CR());144144- _set_L3CR(0);145145- _set_L3CR(core99_l3_cache);146146- printk("CPU%d: L3CR set to %lx\n", cpu, core99_l3_cache);147147- }148148-}149149-150150-/*151151- * Set and clear IPIs for powersurge.152152- */153153-static inline void psurge_set_ipi(int cpu)154154-{155155- if (psurge_type == PSURGE_NONE)156156- return;157157- if (cpu == 0)158158- in_be32(psurge_pri_intr);159159- else if (psurge_type == PSURGE_DUAL)160160- out_8(psurge_sec_intr, 0);161161- else162162- PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_SET, 1 << cpu);163163-}164164-165165-static inline void psurge_clr_ipi(int cpu)166166-{167167- if (cpu > 0) {168168- switch(psurge_type) {169169- case PSURGE_DUAL:170170- out_8(psurge_sec_intr, ~0);171171- case PSURGE_NONE:172172- break;173173- default:174174- PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu);175175- }176176- }177177-}178178-179179-/*180180- * On powersurge (old SMP powermac architecture) we don't have181181- * separate IPIs for separate messages like openpic does. Instead182182- * we have a bitmap for each processor, where a 1 bit means that183183- * the corresponding message is pending for that processor.184184- * Ideally each cpu's entry would be in a different cache line.185185- * -- paulus.186186- */187187-static unsigned long psurge_smp_message[NR_CPUS];188188-189189-void psurge_smp_message_recv(struct pt_regs *regs)190190-{191191- int cpu = smp_processor_id();192192- int msg;193193-194194- /* clear interrupt */195195- psurge_clr_ipi(cpu);196196-197197- if (num_online_cpus() < 2)198198- return;199199-200200- /* make sure there is a message there */201201- for (msg = 0; msg < 4; msg++)202202- if (test_and_clear_bit(msg, &psurge_smp_message[cpu]))203203- smp_message_recv(msg, regs);204204-}205205-206206-irqreturn_t psurge_primary_intr(int irq, void *d, struct pt_regs *regs)207207-{208208- psurge_smp_message_recv(regs);209209- return IRQ_HANDLED;210210-}211211-212212-static void smp_psurge_message_pass(int target, int msg)213213-{214214- int i;215215-216216- if (num_online_cpus() < 2)217217- return;218218-219219- for (i = 0; i < NR_CPUS; i++) {220220- if (!cpu_online(i))221221- continue;222222- if (target == MSG_ALL223223- || (target == MSG_ALL_BUT_SELF && i != smp_processor_id())224224- || target == i) {225225- set_bit(msg, &psurge_smp_message[i]);226226- psurge_set_ipi(i);227227- }228228- }229229-}230230-231231-/*232232- * Determine a quad card presence. We read the board ID register, we233233- * force the data bus to change to something else, and we read it again.234234- * It it's stable, then the register probably exist (ugh !)235235- */236236-static int __init psurge_quad_probe(void)237237-{238238- int type;239239- unsigned int i;240240-241241- type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID);242242- if (type < PSURGE_QUAD_OKEE || type > PSURGE_QUAD_ICEGRASS243243- || type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))244244- return PSURGE_DUAL;245245-246246- /* looks OK, try a slightly more rigorous test */247247- /* bogus is not necessarily cacheline-aligned,248248- though I don't suppose that really matters. -- paulus */249249- for (i = 0; i < 100; i++) {250250- volatile u32 bogus[8];251251- bogus[(0+i)%8] = 0x00000000;252252- bogus[(1+i)%8] = 0x55555555;253253- bogus[(2+i)%8] = 0xFFFFFFFF;254254- bogus[(3+i)%8] = 0xAAAAAAAA;255255- bogus[(4+i)%8] = 0x33333333;256256- bogus[(5+i)%8] = 0xCCCCCCCC;257257- bogus[(6+i)%8] = 0xCCCCCCCC;258258- bogus[(7+i)%8] = 0x33333333;259259- wmb();260260- asm volatile("dcbf 0,%0" : : "r" (bogus) : "memory");261261- mb();262262- if (type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))263263- return PSURGE_DUAL;264264- }265265- return type;266266-}267267-268268-static void __init psurge_quad_init(void)269269-{270270- int procbits;271271-272272- if (ppc_md.progress) ppc_md.progress("psurge_quad_init", 0x351);273273- procbits = ~PSURGE_QUAD_IN(PSURGE_QUAD_WHICH_CPU);274274- if (psurge_type == PSURGE_QUAD_ICEGRASS)275275- PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);276276- else277277- PSURGE_QUAD_BIC(PSURGE_QUAD_CKSTOP_CTL, procbits);278278- mdelay(33);279279- out_8(psurge_sec_intr, ~0);280280- PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, procbits);281281- PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);282282- if (psurge_type != PSURGE_QUAD_ICEGRASS)283283- PSURGE_QUAD_BIS(PSURGE_QUAD_CKSTOP_CTL, procbits);284284- PSURGE_QUAD_BIC(PSURGE_QUAD_PRIMARY_ARB, procbits);285285- mdelay(33);286286- PSURGE_QUAD_BIC(PSURGE_QUAD_RESET_CTL, procbits);287287- mdelay(33);288288- PSURGE_QUAD_BIS(PSURGE_QUAD_PRIMARY_ARB, procbits);289289- mdelay(33);290290-}291291-292292-static int __init smp_psurge_probe(void)293293-{294294- int i, ncpus;295295-296296- /* We don't do SMP on the PPC601 -- paulus */297297- if (PVR_VER(mfspr(SPRN_PVR)) == 1)298298- return 1;299299-300300- /*301301- * The powersurge cpu board can be used in the generation302302- * of powermacs that have a socket for an upgradeable cpu card,303303- * including the 7500, 8500, 9500, 9600.304304- * The device tree doesn't tell you if you have 2 cpus because305305- * OF doesn't know anything about the 2nd processor.306306- * Instead we look for magic bits in magic registers,307307- * in the hammerhead memory controller in the case of the308308- * dual-cpu powersurge board. -- paulus.309309- */310310- if (find_devices("hammerhead") == NULL)311311- return 1;312312-313313- hhead_base = ioremap(HAMMERHEAD_BASE, 0x800);314314- quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024);315315- psurge_sec_intr = hhead_base + HHEAD_SEC_INTR;316316-317317- psurge_type = psurge_quad_probe();318318- if (psurge_type != PSURGE_DUAL) {319319- psurge_quad_init();320320- /* All released cards using this HW design have 4 CPUs */321321- ncpus = 4;322322- } else {323323- iounmap(quad_base);324324- if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) {325325- /* not a dual-cpu card */326326- iounmap(hhead_base);327327- psurge_type = PSURGE_NONE;328328- return 1;329329- }330330- ncpus = 2;331331- }332332-333333- psurge_start = ioremap(PSURGE_START, 4);334334- psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4);335335-336336- /* this is not actually strictly necessary -- paulus. */337337- for (i = 1; i < ncpus; ++i)338338- smp_hw_index[i] = i;339339-340340- if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352);341341-342342- return ncpus;343343-}344344-345345-static void __init smp_psurge_kick_cpu(int nr)346346-{347347- unsigned long start = __pa(__secondary_start_pmac_0) + nr * 8;348348- unsigned long a;349349-350350- /* may need to flush here if secondary bats aren't setup */351351- for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32)352352- asm volatile("dcbf 0,%0" : : "r" (a) : "memory");353353- asm volatile("sync");354354-355355- if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353);356356-357357- out_be32(psurge_start, start);358358- mb();359359-360360- psurge_set_ipi(nr);361361- udelay(10);362362- psurge_clr_ipi(nr);363363-364364- if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354);365365-}366366-367367-/*368368- * With the dual-cpu powersurge board, the decrementers and timebases369369- * of both cpus are frozen after the secondary cpu is started up,370370- * until we give the secondary cpu another interrupt. This routine371371- * uses this to get the timebases synchronized.372372- * -- paulus.373373- */374374-static void __init psurge_dual_sync_tb(int cpu_nr)375375-{376376- int t;377377-378378- set_dec(tb_ticks_per_jiffy);379379- set_tb(0, 0);380380- last_jiffy_stamp(cpu_nr) = 0;381381-382382- if (cpu_nr > 0) {383383- mb();384384- sec_tb_reset = 1;385385- return;386386- }387387-388388- /* wait for the secondary to have reset its TB before proceeding */389389- for (t = 10000000; t > 0 && !sec_tb_reset; --t)390390- ;391391-392392- /* now interrupt the secondary, starting both TBs */393393- psurge_set_ipi(1);394394-395395- smp_tb_synchronized = 1;396396-}397397-398398-static struct irqaction psurge_irqaction = {399399- .handler = psurge_primary_intr,400400- .flags = SA_INTERRUPT,401401- .mask = CPU_MASK_NONE,402402- .name = "primary IPI",403403-};404404-405405-static void __init smp_psurge_setup_cpu(int cpu_nr)406406-{407407-408408- if (cpu_nr == 0) {409409- /* If we failed to start the second CPU, we should still410410- * send it an IPI to start the timebase & DEC or we might411411- * have them stuck.412412- */413413- if (num_online_cpus() < 2) {414414- if (psurge_type == PSURGE_DUAL)415415- psurge_set_ipi(1);416416- return;417417- }418418- /* reset the entry point so if we get another intr we won't419419- * try to startup again */420420- out_be32(psurge_start, 0x100);421421- if (setup_irq(30, &psurge_irqaction))422422- printk(KERN_ERR "Couldn't get primary IPI interrupt");423423- }424424-425425- if (psurge_type == PSURGE_DUAL)426426- psurge_dual_sync_tb(cpu_nr);427427-}428428-429429-void __init smp_psurge_take_timebase(void)430430-{431431- /* Dummy implementation */432432-}433433-434434-void __init smp_psurge_give_timebase(void)435435-{436436- /* Dummy implementation */437437-}438438-439439-static int __init smp_core99_probe(void)440440-{441441-#ifdef CONFIG_6xx442442- extern int powersave_nap;443443-#endif444444- struct device_node *cpus, *firstcpu;445445- int i, ncpus = 0, boot_cpu = -1;446446- u32 *tbprop = NULL;447447-448448- if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345);449449- cpus = firstcpu = find_type_devices("cpu");450450- while(cpus != NULL) {451451- u32 *regprop = (u32 *)get_property(cpus, "reg", NULL);452452- char *stateprop = (char *)get_property(cpus, "state", NULL);453453- if (regprop != NULL && stateprop != NULL &&454454- !strncmp(stateprop, "running", 7))455455- boot_cpu = *regprop;456456- ++ncpus;457457- cpus = cpus->next;458458- }459459- if (boot_cpu == -1)460460- printk(KERN_WARNING "Couldn't detect boot CPU !\n");461461- if (boot_cpu != 0)462462- printk(KERN_WARNING "Boot CPU is %d, unsupported setup !\n", boot_cpu);463463-464464- if (machine_is_compatible("MacRISC4")) {465465- extern struct smp_ops_t core99_smp_ops;466466-467467- core99_smp_ops.take_timebase = smp_generic_take_timebase;468468- core99_smp_ops.give_timebase = smp_generic_give_timebase;469469- } else {470470- if (firstcpu != NULL)471471- tbprop = (u32 *)get_property(firstcpu, "timebase-enable", NULL);472472- if (tbprop)473473- core99_tb_gpio = *tbprop;474474- else475475- core99_tb_gpio = KL_GPIO_TB_ENABLE;476476- }477477-478478- if (ncpus > 1) {479479- openpic_request_IPIs();480480- for (i = 1; i < ncpus; ++i)481481- smp_hw_index[i] = i;482482-#ifdef CONFIG_6xx483483- powersave_nap = 0;484484-#endif485485- core99_init_caches(0);486486- }487487-488488- return ncpus;489489-}490490-491491-static void __devinit smp_core99_kick_cpu(int nr)492492-{493493- unsigned long save_vector, new_vector;494494- unsigned long flags;495495-496496- volatile unsigned long *vector497497- = ((volatile unsigned long *)(KERNELBASE+0x100));498498- if (nr < 0 || nr > 3)499499- return;500500- if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346);501501-502502- local_irq_save(flags);503503- local_irq_disable();504504-505505- /* Save reset vector */506506- save_vector = *vector;507507-508508- /* Setup fake reset vector that does 509509- * b __secondary_start_pmac_0 + nr*8 - KERNELBASE510510- */511511- new_vector = (unsigned long) __secondary_start_pmac_0 + nr * 8;512512- *vector = 0x48000002 + new_vector - KERNELBASE;513513-514514- /* flush data cache and inval instruction cache */515515- flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);516516-517517- /* Put some life in our friend */518518- pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0);519519-520520- /* FIXME: We wait a bit for the CPU to take the exception, I should521521- * instead wait for the entry code to set something for me. Well,522522- * ideally, all that crap will be done in prom.c and the CPU left523523- * in a RAM-based wait loop like CHRP.524524- */525525- mdelay(1);526526-527527- /* Restore our exception vector */528528- *vector = save_vector;529529- flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);530530-531531- local_irq_restore(flags);532532- if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347);533533-}534534-535535-static void __devinit smp_core99_setup_cpu(int cpu_nr)536536-{537537- /* Setup L2/L3 */538538- if (cpu_nr != 0)539539- core99_init_caches(cpu_nr);540540-541541- /* Setup openpic */542542- do_openpic_setup_cpu();543543-544544- if (cpu_nr == 0) {545545-#ifdef CONFIG_POWER4546546- extern void g5_phy_disable_cpu1(void);547547-548548- /* If we didn't start the second CPU, we must take549549- * it off the bus550550- */551551- if (machine_is_compatible("MacRISC4") &&552552- num_online_cpus() < 2) 553553- g5_phy_disable_cpu1();554554-#endif /* CONFIG_POWER4 */555555- if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349);556556- }557557-}558558-559559-/* not __init, called in sleep/wakeup code */560560-void smp_core99_take_timebase(void)561561-{562562- unsigned long flags;563563-564564- /* tell the primary we're here */565565- sec_tb_reset = 1;566566- mb();567567-568568- /* wait for the primary to set pri_tb_hi/lo */569569- while (sec_tb_reset < 2)570570- mb();571571-572572- /* set our stuff the same as the primary */573573- local_irq_save(flags);574574- set_dec(1);575575- set_tb(pri_tb_hi, pri_tb_lo);576576- last_jiffy_stamp(smp_processor_id()) = pri_tb_stamp;577577- mb();578578-579579- /* tell the primary we're done */580580- sec_tb_reset = 0;581581- mb();582582- local_irq_restore(flags);583583-}584584-585585-/* not __init, called in sleep/wakeup code */586586-void smp_core99_give_timebase(void)587587-{588588- unsigned long flags;589589- unsigned int t;590590-591591- /* wait for the secondary to be in take_timebase */592592- for (t = 100000; t > 0 && !sec_tb_reset; --t)593593- udelay(10);594594- if (!sec_tb_reset) {595595- printk(KERN_WARNING "Timeout waiting sync on second CPU\n");596596- return;597597- }598598-599599- /* freeze the timebase and read it */600600- /* disable interrupts so the timebase is disabled for the601601- shortest possible time */602602- local_irq_save(flags);603603- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 4);604604- pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);605605- mb();606606- pri_tb_hi = get_tbu();607607- pri_tb_lo = get_tbl();608608- pri_tb_stamp = last_jiffy_stamp(smp_processor_id());609609- mb();610610-611611- /* tell the secondary we're ready */612612- sec_tb_reset = 2;613613- mb();614614-615615- /* wait for the secondary to have taken it */616616- for (t = 100000; t > 0 && sec_tb_reset; --t)617617- udelay(10);618618- if (sec_tb_reset)619619- printk(KERN_WARNING "Timeout waiting sync(2) on second CPU\n");620620- else621621- smp_tb_synchronized = 1;622622-623623- /* Now, restart the timebase by leaving the GPIO to an open collector */624624- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0);625625- pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);626626- local_irq_restore(flags);627627-}628628-629629-630630-/* PowerSurge-style Macs */631631-struct smp_ops_t psurge_smp_ops = {632632- .message_pass = smp_psurge_message_pass,633633- .probe = smp_psurge_probe,634634- .kick_cpu = smp_psurge_kick_cpu,635635- .setup_cpu = smp_psurge_setup_cpu,636636- .give_timebase = smp_psurge_give_timebase,637637- .take_timebase = smp_psurge_take_timebase,638638-};639639-640640-/* Core99 Macs (dual G4s) */641641-struct smp_ops_t core99_smp_ops = {642642- .message_pass = smp_openpic_message_pass,643643- .probe = smp_core99_probe,644644- .kick_cpu = smp_core99_kick_cpu,645645- .setup_cpu = smp_core99_setup_cpu,646646- .give_timebase = smp_core99_give_timebase,647647- .take_timebase = smp_core99_take_timebase,648648-};649649-650650-#ifdef CONFIG_HOTPLUG_CPU651651-652652-int __cpu_disable(void)653653-{654654- cpu_clear(smp_processor_id(), cpu_online_map);655655-656656- /* XXX reset cpu affinity here */657657- openpic_set_priority(0xf);658658- asm volatile("mtdec %0" : : "r" (0x7fffffff));659659- mb();660660- udelay(20);661661- asm volatile("mtdec %0" : : "r" (0x7fffffff));662662- return 0;663663-}664664-665665-extern void low_cpu_die(void) __attribute__((noreturn)); /* in pmac_sleep.S */666666-static int cpu_dead[NR_CPUS];667667-668668-void cpu_die(void)669669-{670670- local_irq_disable();671671- cpu_dead[smp_processor_id()] = 1;672672- mb();673673- low_cpu_die();674674-}675675-676676-void __cpu_die(unsigned int cpu)677677-{678678- int timeout;679679-680680- timeout = 1000;681681- while (!cpu_dead[cpu]) {682682- if (--timeout == 0) {683683- printk("CPU %u refused to die!\n", cpu);684684- break;685685- }686686- msleep(1);687687- }688688- cpu_callin_map[cpu] = 0;689689- cpu_dead[cpu] = 0;690690-}691691-692692-#endif
-291
arch/ppc/platforms/pmac_time.c
···11-/*22- * Support for periodic interrupts (100 per second) and for getting33- * the current time from the RTC on Power Macintoshes.44- *55- * We use the decrementer register for our periodic interrupts.66- *77- * Paul Mackerras August 1996.88- * Copyright (C) 1996 Paul Mackerras.99- */1010-#include <linux/config.h>1111-#include <linux/errno.h>1212-#include <linux/sched.h>1313-#include <linux/kernel.h>1414-#include <linux/param.h>1515-#include <linux/string.h>1616-#include <linux/mm.h>1717-#include <linux/init.h>1818-#include <linux/time.h>1919-#include <linux/adb.h>2020-#include <linux/cuda.h>2121-#include <linux/pmu.h>2222-#include <linux/hardirq.h>2323-2424-#include <asm/sections.h>2525-#include <asm/prom.h>2626-#include <asm/system.h>2727-#include <asm/io.h>2828-#include <asm/pgtable.h>2929-#include <asm/machdep.h>3030-#include <asm/time.h>3131-#include <asm/nvram.h>3232-3333-/* Apparently the RTC stores seconds since 1 Jan 1904 */3434-#define RTC_OFFSET 20828448003535-3636-/*3737- * Calibrate the decrementer frequency with the VIA timer 1.3838- */3939-#define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */4040-4141-/* VIA registers */4242-#define RS 0x200 /* skip between registers */4343-#define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */4444-#define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */4545-#define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */4646-#define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */4747-#define ACR (11*RS) /* Auxiliary control register */4848-#define IFR (13*RS) /* Interrupt flag register */4949-5050-/* Bits in ACR */5151-#define T1MODE 0xc0 /* Timer 1 mode */5252-#define T1MODE_CONT 0x40 /* continuous interrupts */5353-5454-/* Bits in IFR and IER */5555-#define T1_INT 0x40 /* Timer 1 interrupt */5656-5757-extern struct timezone sys_tz;5858-5959-long __init6060-pmac_time_init(void)6161-{6262-#ifdef CONFIG_NVRAM6363- s32 delta = 0;6464- int dst;6565-6666- delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16;6767- delta |= ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xa)) << 8;6868- delta |= pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xb);6969- if (delta & 0x00800000UL)7070- delta |= 0xFF000000UL;7171- dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0);7272- printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60,7373- dst ? "on" : "off");7474- return delta;7575-#else7676- return 0;7777-#endif7878-}7979-8080-unsigned long8181-pmac_get_rtc_time(void)8282-{8383-#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)8484- struct adb_request req;8585- unsigned long now;8686-#endif8787-8888- /* Get the time from the RTC */8989- switch (sys_ctrler) {9090-#ifdef CONFIG_ADB_CUDA9191- case SYS_CTRLER_CUDA:9292- if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)9393- return 0;9494- while (!req.complete)9595- cuda_poll();9696- if (req.reply_len != 7)9797- printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",9898- req.reply_len);9999- now = (req.reply[3] << 24) + (req.reply[4] << 16)100100- + (req.reply[5] << 8) + req.reply[6];101101- return now - RTC_OFFSET;102102-#endif /* CONFIG_ADB_CUDA */103103-#ifdef CONFIG_ADB_PMU104104- case SYS_CTRLER_PMU:105105- if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)106106- return 0;107107- while (!req.complete)108108- pmu_poll();109109- if (req.reply_len != 4)110110- printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",111111- req.reply_len);112112- now = (req.reply[0] << 24) + (req.reply[1] << 16)113113- + (req.reply[2] << 8) + req.reply[3];114114- return now - RTC_OFFSET;115115-#endif /* CONFIG_ADB_PMU */116116- default: ;117117- }118118- return 0;119119-}120120-121121-int122122-pmac_set_rtc_time(unsigned long nowtime)123123-{124124-#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)125125- struct adb_request req;126126-#endif127127-128128- nowtime += RTC_OFFSET;129129-130130- switch (sys_ctrler) {131131-#ifdef CONFIG_ADB_CUDA132132- case SYS_CTRLER_CUDA:133133- if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,134134- nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)135135- return 0;136136- while (!req.complete)137137- cuda_poll();138138- if ((req.reply_len != 3) && (req.reply_len != 7))139139- printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",140140- req.reply_len);141141- return 1;142142-#endif /* CONFIG_ADB_CUDA */143143-#ifdef CONFIG_ADB_PMU144144- case SYS_CTRLER_PMU:145145- if (pmu_request(&req, NULL, 5, PMU_SET_RTC,146146- nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)147147- return 0;148148- while (!req.complete)149149- pmu_poll();150150- if (req.reply_len != 0)151151- printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",152152- req.reply_len);153153- return 1;154154-#endif /* CONFIG_ADB_PMU */155155- default:156156- return 0;157157- }158158-}159159-160160-/*161161- * Calibrate the decrementer register using VIA timer 1.162162- * This is used both on powermacs and CHRP machines.163163- */164164-int __init165165-via_calibrate_decr(void)166166-{167167- struct device_node *vias;168168- volatile unsigned char __iomem *via;169169- int count = VIA_TIMER_FREQ_6 / 100;170170- unsigned int dstart, dend;171171-172172- vias = find_devices("via-cuda");173173- if (vias == 0)174174- vias = find_devices("via-pmu");175175- if (vias == 0)176176- vias = find_devices("via");177177- if (vias == 0 || vias->n_addrs == 0)178178- return 0;179179- via = ioremap(vias->addrs[0].address, vias->addrs[0].size);180180-181181- /* set timer 1 for continuous interrupts */182182- out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT);183183- /* set the counter to a small value */184184- out_8(&via[T1CH], 2);185185- /* set the latch to `count' */186186- out_8(&via[T1LL], count);187187- out_8(&via[T1LH], count >> 8);188188- /* wait until it hits 0 */189189- while ((in_8(&via[IFR]) & T1_INT) == 0)190190- ;191191- dstart = get_dec();192192- /* clear the interrupt & wait until it hits 0 again */193193- in_8(&via[T1CL]);194194- while ((in_8(&via[IFR]) & T1_INT) == 0)195195- ;196196- dend = get_dec();197197-198198- tb_ticks_per_jiffy = (dstart - dend) / ((6 * HZ)/100);199199- tb_to_us = mulhwu_scale_factor(dstart - dend, 60000);200200-201201- printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n",202202- tb_ticks_per_jiffy, dstart - dend);203203-204204- iounmap(via);205205-206206- return 1;207207-}208208-209209-#ifdef CONFIG_PM210210-/*211211- * Reset the time after a sleep.212212- */213213-static int214214-time_sleep_notify(struct pmu_sleep_notifier *self, int when)215215-{216216- static unsigned long time_diff;217217- unsigned long flags;218218- unsigned long seq;219219-220220- switch (when) {221221- case PBOOK_SLEEP_NOW:222222- do {223223- seq = read_seqbegin_irqsave(&xtime_lock, flags);224224- time_diff = xtime.tv_sec - pmac_get_rtc_time();225225- } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));226226- break;227227- case PBOOK_WAKE:228228- write_seqlock_irqsave(&xtime_lock, flags);229229- xtime.tv_sec = pmac_get_rtc_time() + time_diff;230230- xtime.tv_nsec = 0;231231- last_rtc_update = xtime.tv_sec;232232- write_sequnlock_irqrestore(&xtime_lock, flags);233233- break;234234- }235235- return PBOOK_SLEEP_OK;236236-}237237-238238-static struct pmu_sleep_notifier time_sleep_notifier = {239239- time_sleep_notify, SLEEP_LEVEL_MISC,240240-};241241-#endif /* CONFIG_PM */242242-243243-/*244244- * Query the OF and get the decr frequency.245245- * This was taken from the pmac time_init() when merging the prep/pmac246246- * time functions.247247- */248248-void __init249249-pmac_calibrate_decr(void)250250-{251251- struct device_node *cpu;252252- unsigned int freq, *fp;253253-254254-#ifdef CONFIG_PM255255- pmu_register_sleep_notifier(&time_sleep_notifier);256256-#endif /* CONFIG_PM */257257-258258- /* We assume MacRISC2 machines have correct device-tree259259- * calibration. That's better since the VIA itself seems260260- * to be slightly off. --BenH261261- */262262- if (!machine_is_compatible("MacRISC2") &&263263- !machine_is_compatible("MacRISC3") &&264264- !machine_is_compatible("MacRISC4"))265265- if (via_calibrate_decr())266266- return;267267-268268- /* Special case: QuickSilver G4s seem to have a badly calibrated269269- * timebase-frequency in OF, VIA is much better on these. We should270270- * probably implement calibration based on the KL timer on these271271- * machines anyway... -BenH272272- */273273- if (machine_is_compatible("PowerMac3,5"))274274- if (via_calibrate_decr())275275- return;276276- /*277277- * The cpu node should have a timebase-frequency property278278- * to tell us the rate at which the decrementer counts.279279- */280280- cpu = find_type_devices("cpu");281281- if (cpu == 0)282282- panic("can't find cpu node in time_init");283283- fp = (unsigned int *) get_property(cpu, "timebase-frequency", NULL);284284- if (fp == 0)285285- panic("can't get cpu timebase frequency");286286- freq = *fp;287287- printk("time_init: decrementer frequency = %u.%.6u MHz\n",288288- freq/1000000, freq%1000000);289289- tb_ticks_per_jiffy = freq / HZ;290290- tb_to_us = mulhwu_scale_factor(freq, 1000000);291291-}
···7070struct device_node *dflt_interrupt_controller;7171int num_interrupt_controllers;72727373-int pmac_newworld;7474-7573extern unsigned int rtas_entry; /* physical pointer */76747775extern struct device_node *allnodes;···121123 unsigned long mem = (unsigned long) klimit;122124 struct device_node *np;123125124124- /* All newworld pmac machines and CHRPs now use the interrupt tree */126126+ /* All CHRPs now use the interrupt tree */125127 for (np = allnodes; np != NULL; np = np->allnext) {126128 if (get_property(np, "interrupt-parent", NULL)) {127129 use_of_interrupt_tree = 1;128130 break;129131 }130132 }131131- if (_machine == _MACH_Pmac && use_of_interrupt_tree)132132- pmac_newworld = 1;133133-134134-#ifdef CONFIG_BOOTX_TEXT135135- if (boot_infos && pmac_newworld) {136136- prom_print("WARNING ! BootX/miBoot booting is not supported on this machine\n");137137- prom_print(" You should use an Open Firmware bootloader\n");138138- }139139-#endif /* CONFIG_BOOTX_TEXT */140133141134 if (use_of_interrupt_tree) {142135 /*···423434 * those machines, we want to offset interrupts from the424435 * second openpic by 128 -- BenH425436 */426426- if (_machine != _MACH_Pmac && num_interrupt_controllers > 1437437+ if (num_interrupt_controllers > 1427438 && ic != NULL428439 && get_property(ic, "interrupt-parent", NULL) == NULL)429440 offset = 16;430430- else if (_machine == _MACH_Pmac && num_interrupt_controllers > 1431431- && ic != NULL && ic->parent != NULL) {432432- char *name = get_property(ic->parent, "name", NULL);433433- if (name && !strcmp(name, "u3"))434434- offset = 128;435435- }436441437442 np->intrs[i].line = irq[0] + offset;438443 if (n > 1)
+12-147
arch/ppc/xmon/start.c
···1818#include <asm/bootx.h>1919#include <asm/machdep.h>2020#include <asm/errno.h>2121-#include <asm/pmac_feature.h>2221#include <asm/processor.h>2322#include <asm/delay.h>2423#include <asm/btext.h>···2627unsigned int TXRDY, RXRDY, DLAB;2728static int xmon_expect(const char *str, unsigned int timeout);28292929-static int use_serial;3030static int use_screen;3131static int via_modem;3232static int xmon_use_sccb;3333-static struct device_node *channel_node;34333534#define TB_SPEED 250000003635···109112#ifdef CONFIG_PPC_MULTIPLATFORM110113 volatile unsigned char *base;111114112112- if (_machine == _MACH_Pmac) {113113- struct device_node *np;114114- unsigned long addr;115115-#ifdef CONFIG_BOOTX_TEXT116116- if (!use_screen && !use_serial117117- && !machine_is_compatible("iMac")) {118118- /* see if there is a keyboard in the device tree119119- with a parent of type "adb" */120120- for (np = find_devices("keyboard"); np; np = np->next)121121- if (np->parent && np->parent->type122122- && strcmp(np->parent->type, "adb") == 0)123123- break;124124-125125- /* needs to be hacked if xmon_printk is to be used126126- from within find_via_pmu() */127127-#ifdef CONFIG_ADB_PMU128128- if (np != NULL && boot_text_mapped && find_via_pmu())129129- use_screen = 1;130130-#endif131131-#ifdef CONFIG_ADB_CUDA132132- if (np != NULL && boot_text_mapped && find_via_cuda())133133- use_screen = 1;134134-#endif135135- }136136- if (!use_screen && (np = find_devices("escc")) != NULL) {137137- /*138138- * look for the device node for the serial port139139- * we're using and see if it says it has a modem140140- */141141- char *name = xmon_use_sccb? "ch-b": "ch-a";142142- char *slots;143143- int l;144144-145145- np = np->child;146146- while (np != NULL && strcmp(np->name, name) != 0)147147- np = np->sibling;148148- if (np != NULL) {149149- /* XXX should parse this properly */150150- channel_node = np;151151- slots = get_property(np, "slot-names", &l);152152- if (slots != NULL && l >= 10153153- && strcmp(slots+4, "Modem") == 0)154154- via_modem = 1;155155- }156156- }157157- btext_drawstring("xmon uses ");158158- if (use_screen)159159- btext_drawstring("screen and keyboard\n");160160- else {161161- if (via_modem)162162- btext_drawstring("modem on ");163163- btext_drawstring(xmon_use_sccb? "printer": "modem");164164- btext_drawstring(" port\n");165165- }166166-167167-#endif /* CONFIG_BOOTX_TEXT */168168-169169-#ifdef CHRP_ESCC170170- addr = 0xc1013020;171171-#else172172- addr = 0xf3013020;173173-#endif174174- TXRDY = 4;175175- RXRDY = 1;176176-177177- np = find_devices("mac-io");178178- if (np && np->n_addrs)179179- addr = np->addrs[0].address + 0x13020;180180- base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE);181181- sccc = base + (addr & ~PAGE_MASK);182182- sccd = sccc + 0x10;183183-184184- }185115#ifdef CONFIG_PPC_CHRP186186- else {187187- base = (volatile unsigned char *) isa_io_base;188188- if (_machine == _MACH_chrp)189189- base = (volatile unsigned char *)190190- ioremap(chrp_find_phys_io_base(), 0x1000);116116+ base = (volatile unsigned char *) isa_io_base;117117+ if (_machine == _MACH_chrp)118118+ base = (volatile unsigned char *)119119+ ioremap(chrp_find_phys_io_base(), 0x1000);191120192192- sccc = base + 0x3fd;193193- sccd = base + 0x3f8;194194- if (xmon_use_sccb) {195195- sccc -= 0x100;196196- sccd -= 0x100;197197- }198198- TXRDY = 0x20;199199- RXRDY = 1;200200- DLAB = 0x80;121121+ sccc = base + 0x3fd;122122+ sccd = base + 0x3f8;123123+ if (xmon_use_sccb) {124124+ sccc -= 0x100;125125+ sccd -= 0x100;201126 }127127+ TXRDY = 0x20;128128+ RXRDY = 1;129129+ DLAB = 0x80;202130#endif /* CONFIG_PPC_CHRP */203131#elif defined(CONFIG_GEMINI)204132 /* should already be mapped by the kernel boot */···307385 return *sccd;308386}309387310310-static unsigned char scc_inittab[] = {311311- 13, 0, /* set baud rate divisor */312312- 12, 1,313313- 14, 1, /* baud rate gen enable, src=rtxc */314314- 11, 0x50, /* clocks = br gen */315315- 5, 0xea, /* tx 8 bits, assert DTR & RTS */316316- 4, 0x46, /* x16 clock, 1 stop */317317- 3, 0xc1, /* rx enable, 8 bits */318318-};319319-320388void321389xmon_init_scc(void)322390{···318406 sccd[2] = 0; eieio(); /* FCR = 0 */319407 sccd[3] = 3; eieio(); /* LCR = 8N1 */320408 sccd[1] = 0; eieio(); /* IER = 0 */321321- }322322- else if ( _machine == _MACH_Pmac )323323- {324324- int i, x;325325-326326- if (channel_node != 0)327327- pmac_call_feature(328328- PMAC_FTR_SCC_ENABLE,329329- channel_node,330330- PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);331331- printk(KERN_INFO "Serial port locked ON by debugger !\n");332332- if (via_modem && channel_node != 0) {333333- unsigned int t0;334334-335335- pmac_call_feature(336336- PMAC_FTR_MODEM_ENABLE,337337- channel_node, 0, 1);338338- printk(KERN_INFO "Modem powered up by debugger !\n");339339- t0 = readtb();340340- while (readtb() - t0 < 3*TB_SPEED)341341- eieio();342342- }343343- /* use the B channel if requested */344344- if (xmon_use_sccb) {345345- sccc = (volatile unsigned char *)346346- ((unsigned long)sccc & ~0x20);347347- sccd = sccc + 0x10;348348- }349349- for (i = 20000; i != 0; --i) {350350- x = *sccc; eieio();351351- }352352- *sccc = 9; eieio(); /* reset A or B side */353353- *sccc = ((unsigned long)sccc & 0x20)? 0x80: 0x40; eieio();354354- for (i = 0; i < sizeof(scc_inittab); ++i) {355355- *sccc = scc_inittab[i];356356- eieio();357357- }358409 }359410 scc_initialized = 1;360411 if (via_modem) {···507632void508633xmon_enter(void)509634{510510-#ifdef CONFIG_ADB_PMU511511- if (_machine == _MACH_Pmac) {512512- pmu_suspend();513513- }514514-#endif515635}516636517637void518638xmon_leave(void)519639{520520-#ifdef CONFIG_ADB_PMU521521- if (_machine == _MACH_Pmac) {522522- pmu_resume();523523- }524524-#endif525640}
···27342734 * BIOS does tho. Right now, all this PM stuff is pmac-only for that27352735 * reason. --BenH27362736 */27372737-#if defined(CONFIG_PM) && defined(CONFIG_PPC_OF)27372737+#if defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC)27382738 if (_machine == _MACH_Pmac && rinfo->of_node) {27392739 if (rinfo->is_mobility && rinfo->pm_reg &&27402740 rinfo->family <= CHIP_FAMILY_RV250)···27782778 OUTREG(TV_DAC_CNTL, INREG(TV_DAC_CNTL) | 0x07000000);27792779#endif27802780 }27812781-#endif /* defined(CONFIG_PM) && defined(CONFIG_PPC_OF) */27812781+#endif /* defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC) */27822782}2783278327842784void radeonfb_pm_exit(struct radeonfb_info *rinfo)27852785{27862786-#if defined(CONFIG_PM) && defined(CONFIG_PPC_OF)27862786+#if defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC)27872787 if (rinfo->pm_mode != radeon_pm_none)27882788 pmac_set_early_video_resume(NULL, NULL);27892789#endif
+73-12
include/asm-powerpc/kexec.h
···3131#define KEXEC_ARCH KEXEC_ARCH_PPC3232#endif33333434-#define HAVE_ARCH_COPY_OLDMEM_PAGE3535-3636-#ifndef __ASSEMBLY__3737-3834#ifdef CONFIG_KEXEC39353636+#ifdef __powerpc64__3737+/*3838+ * This function is responsible for capturing register states if coming3939+ * via panic or invoking dump using sysrq-trigger.4040+ */4141+static inline void crash_setup_regs(struct pt_regs *newregs,4242+ struct pt_regs *oldregs)4343+{4444+ if (oldregs)4545+ memcpy(newregs, oldregs, sizeof(*newregs));4646+ else {4747+ /* FIXME Merge this with xmon_save_regs ?? */4848+ unsigned long tmp1, tmp2;4949+ __asm__ __volatile__ (5050+ "std 0,0(%2)\n"5151+ "std 1,8(%2)\n"5252+ "std 2,16(%2)\n"5353+ "std 3,24(%2)\n"5454+ "std 4,32(%2)\n"5555+ "std 5,40(%2)\n"5656+ "std 6,48(%2)\n"5757+ "std 7,56(%2)\n"5858+ "std 8,64(%2)\n"5959+ "std 9,72(%2)\n"6060+ "std 10,80(%2)\n"6161+ "std 11,88(%2)\n"6262+ "std 12,96(%2)\n"6363+ "std 13,104(%2)\n"6464+ "std 14,112(%2)\n"6565+ "std 15,120(%2)\n"6666+ "std 16,128(%2)\n"6767+ "std 17,136(%2)\n"6868+ "std 18,144(%2)\n"6969+ "std 19,152(%2)\n"7070+ "std 20,160(%2)\n"7171+ "std 21,168(%2)\n"7272+ "std 22,176(%2)\n"7373+ "std 23,184(%2)\n"7474+ "std 24,192(%2)\n"7575+ "std 25,200(%2)\n"7676+ "std 26,208(%2)\n"7777+ "std 27,216(%2)\n"7878+ "std 28,224(%2)\n"7979+ "std 29,232(%2)\n"8080+ "std 30,240(%2)\n"8181+ "std 31,248(%2)\n"8282+ "mfmsr %0\n"8383+ "std %0, 264(%2)\n"8484+ "mfctr %0\n"8585+ "std %0, 280(%2)\n"8686+ "mflr %0\n"8787+ "std %0, 288(%2)\n"8888+ "bl 1f\n"8989+ "1: mflr %1\n"9090+ "std %1, 256(%2)\n"9191+ "mtlr %0\n"9292+ "mfxer %0\n"9393+ "std %0, 296(%2)\n"9494+ : "=&r" (tmp1), "=&r" (tmp2)9595+ : "b" (newregs));9696+ }9797+}9898+#else9999+/*100100+ * Provide a dummy definition to avoid build failures. Will remain101101+ * empty till crash dump support is enabled.102102+ */103103+static inline void crash_setup_regs(struct pt_regs *newregs,104104+ struct pt_regs *oldregs) { }105105+#endif /* !__powerpc64 __ */106106+107107+#ifndef __ASSEMBLY__40108#define MAX_NOTE_BYTES 10244110942110#ifdef __powerpc64__···12153extern int default_machine_kexec_prepare(struct kimage *image);12254extern void default_machine_crash_shutdown(struct pt_regs *regs);12355124124-#endif /* !CONFIG_KEXEC */125125-126126-/*127127- * Provide a dummy definition to avoid build failures. Will remain128128- * empty till crash dump support is enabled.129129- */130130-static inline void crash_setup_regs(struct pt_regs *newregs,131131- struct pt_regs *oldregs) { }13256#endif /* ! __ASSEMBLY__ */5757+#endif /* CONFIG_KEXEC */13358#endif /* __KERNEL__ */13459#endif /* _ASM_POWERPC_KEXEC_H */
+8
include/asm-ppc/prom.h
···167167extern int of_pci_address_to_resource(struct device_node *dev, int bar,168168 struct resource *r);169169170170+#ifndef CONFIG_PPC_OF171171+/*172172+ * Fallback definitions for builds where we don't have prom.c included.173173+ */174174+#define machine_is_compatible(x) 0175175+#define of_find_compatible_node(f, t, c) NULL176176+#define get_property(p, n, l) NULL177177+#endif170178171179#endif /* _PPC_PROM_H */172180#endif /* __KERNEL__ */