162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au) 462306a36Sopenharmony_ci * Ben. Herrenschmidt (benh@kernel.crashing.org) 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * TODO: 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * - Replace mdelay with some schedule loop if possible 962306a36Sopenharmony_ci * - Shorten some obfuscated delays on some routines (like modem 1062306a36Sopenharmony_ci * power) 1162306a36Sopenharmony_ci * - Refcount some clocks (see darwin) 1262306a36Sopenharmony_ci * - Split split split... 1362306a36Sopenharmony_ci */ 1462306a36Sopenharmony_ci#include <linux/types.h> 1562306a36Sopenharmony_ci#include <linux/init.h> 1662306a36Sopenharmony_ci#include <linux/delay.h> 1762306a36Sopenharmony_ci#include <linux/kernel.h> 1862306a36Sopenharmony_ci#include <linux/sched.h> 1962306a36Sopenharmony_ci#include <linux/of.h> 2062306a36Sopenharmony_ci#include <linux/of_address.h> 2162306a36Sopenharmony_ci#include <linux/spinlock.h> 2262306a36Sopenharmony_ci#include <linux/adb.h> 2362306a36Sopenharmony_ci#include <linux/pmu.h> 2462306a36Sopenharmony_ci#include <linux/ioport.h> 2562306a36Sopenharmony_ci#include <linux/export.h> 2662306a36Sopenharmony_ci#include <linux/pci.h> 2762306a36Sopenharmony_ci#include <asm/sections.h> 2862306a36Sopenharmony_ci#include <asm/errno.h> 2962306a36Sopenharmony_ci#include <asm/ohare.h> 3062306a36Sopenharmony_ci#include <asm/heathrow.h> 3162306a36Sopenharmony_ci#include <asm/keylargo.h> 3262306a36Sopenharmony_ci#include <asm/uninorth.h> 3362306a36Sopenharmony_ci#include <asm/io.h> 3462306a36Sopenharmony_ci#include <asm/machdep.h> 3562306a36Sopenharmony_ci#include <asm/pmac_feature.h> 3662306a36Sopenharmony_ci#include <asm/dbdma.h> 3762306a36Sopenharmony_ci#include <asm/pci-bridge.h> 3862306a36Sopenharmony_ci#include <asm/pmac_low_i2c.h> 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#include "pmac.h" 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#undef DEBUG_FEATURE 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#ifdef DEBUG_FEATURE 4562306a36Sopenharmony_ci#define DBG(fmt...) printk(KERN_DEBUG fmt) 4662306a36Sopenharmony_ci#else 4762306a36Sopenharmony_ci#define DBG(fmt...) 4862306a36Sopenharmony_ci#endif 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S_32 5162306a36Sopenharmony_ciextern int powersave_lowspeed; 5262306a36Sopenharmony_ci#endif 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ciextern int powersave_nap; 5562306a36Sopenharmony_ciextern struct device_node *k2_skiplist[2]; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci/* 5862306a36Sopenharmony_ci * We use a single global lock to protect accesses. Each driver has 5962306a36Sopenharmony_ci * to take care of its own locking 6062306a36Sopenharmony_ci */ 6162306a36Sopenharmony_ciDEFINE_RAW_SPINLOCK(feature_lock); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci#define LOCK(flags) raw_spin_lock_irqsave(&feature_lock, flags); 6462306a36Sopenharmony_ci#define UNLOCK(flags) raw_spin_unlock_irqrestore(&feature_lock, flags); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci/* 6862306a36Sopenharmony_ci * Instance of some macio stuffs 6962306a36Sopenharmony_ci */ 7062306a36Sopenharmony_cistruct macio_chip macio_chips[MAX_MACIO_CHIPS]; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_cistruct macio_chip *macio_find(struct device_node *child, int type) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci while(child) { 7562306a36Sopenharmony_ci int i; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci for (i=0; i < MAX_MACIO_CHIPS && macio_chips[i].of_node; i++) 7862306a36Sopenharmony_ci if (child == macio_chips[i].of_node && 7962306a36Sopenharmony_ci (!type || macio_chips[i].type == type)) 8062306a36Sopenharmony_ci return &macio_chips[i]; 8162306a36Sopenharmony_ci child = child->parent; 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci return NULL; 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(macio_find); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistatic const char *macio_names[] = 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci "Unknown", 9062306a36Sopenharmony_ci "Grand Central", 9162306a36Sopenharmony_ci "OHare", 9262306a36Sopenharmony_ci "OHareII", 9362306a36Sopenharmony_ci "Heathrow", 9462306a36Sopenharmony_ci "Gatwick", 9562306a36Sopenharmony_ci "Paddington", 9662306a36Sopenharmony_ci "Keylargo", 9762306a36Sopenharmony_ci "Pangea", 9862306a36Sopenharmony_ci "Intrepid", 9962306a36Sopenharmony_ci "K2", 10062306a36Sopenharmony_ci "Shasta", 10162306a36Sopenharmony_ci}; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistruct device_node *uninorth_node; 10562306a36Sopenharmony_ciu32 __iomem *uninorth_base; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistatic u32 uninorth_rev; 10862306a36Sopenharmony_cistatic int uninorth_maj; 10962306a36Sopenharmony_cistatic void __iomem *u3_ht_base; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci/* 11262306a36Sopenharmony_ci * For each motherboard family, we have a table of functions pointers 11362306a36Sopenharmony_ci * that handle the various features. 11462306a36Sopenharmony_ci */ 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_citypedef long (*feature_call)(struct device_node *node, long param, long value); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_cistruct feature_table_entry { 11962306a36Sopenharmony_ci unsigned int selector; 12062306a36Sopenharmony_ci feature_call function; 12162306a36Sopenharmony_ci}; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistruct pmac_mb_def 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci const char* model_string; 12662306a36Sopenharmony_ci const char* model_name; 12762306a36Sopenharmony_ci int model_id; 12862306a36Sopenharmony_ci struct feature_table_entry* features; 12962306a36Sopenharmony_ci unsigned long board_flags; 13062306a36Sopenharmony_ci}; 13162306a36Sopenharmony_cistatic struct pmac_mb_def pmac_mb; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci/* 13462306a36Sopenharmony_ci * Here are the chip specific feature functions 13562306a36Sopenharmony_ci */ 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci#ifndef CONFIG_PPC64 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_cistatic int simple_feature_tweak(struct device_node *node, int type, int reg, 14062306a36Sopenharmony_ci u32 mask, int value) 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci struct macio_chip* macio; 14362306a36Sopenharmony_ci unsigned long flags; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci macio = macio_find(node, type); 14662306a36Sopenharmony_ci if (!macio) 14762306a36Sopenharmony_ci return -ENODEV; 14862306a36Sopenharmony_ci LOCK(flags); 14962306a36Sopenharmony_ci if (value) 15062306a36Sopenharmony_ci MACIO_BIS(reg, mask); 15162306a36Sopenharmony_ci else 15262306a36Sopenharmony_ci MACIO_BIC(reg, mask); 15362306a36Sopenharmony_ci (void)MACIO_IN32(reg); 15462306a36Sopenharmony_ci UNLOCK(flags); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci return 0; 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic long ohare_htw_scc_enable(struct device_node *node, long param, 16062306a36Sopenharmony_ci long value) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci struct macio_chip* macio; 16362306a36Sopenharmony_ci unsigned long chan_mask; 16462306a36Sopenharmony_ci unsigned long fcr; 16562306a36Sopenharmony_ci unsigned long flags; 16662306a36Sopenharmony_ci int htw, trans; 16762306a36Sopenharmony_ci unsigned long rmask; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci macio = macio_find(node, 0); 17062306a36Sopenharmony_ci if (!macio) 17162306a36Sopenharmony_ci return -ENODEV; 17262306a36Sopenharmony_ci if (of_node_name_eq(node, "ch-a")) 17362306a36Sopenharmony_ci chan_mask = MACIO_FLAG_SCCA_ON; 17462306a36Sopenharmony_ci else if (of_node_name_eq(node, "ch-b")) 17562306a36Sopenharmony_ci chan_mask = MACIO_FLAG_SCCB_ON; 17662306a36Sopenharmony_ci else 17762306a36Sopenharmony_ci return -ENODEV; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci htw = (macio->type == macio_heathrow || macio->type == macio_paddington 18062306a36Sopenharmony_ci || macio->type == macio_gatwick); 18162306a36Sopenharmony_ci /* On these machines, the HRW_SCC_TRANS_EN_N bit mustn't be touched */ 18262306a36Sopenharmony_ci trans = (pmac_mb.model_id != PMAC_TYPE_YOSEMITE && 18362306a36Sopenharmony_ci pmac_mb.model_id != PMAC_TYPE_YIKES); 18462306a36Sopenharmony_ci if (value) { 18562306a36Sopenharmony_ci#ifdef CONFIG_ADB_PMU 18662306a36Sopenharmony_ci if ((param & 0xfff) == PMAC_SCC_IRDA) 18762306a36Sopenharmony_ci pmu_enable_irled(1); 18862306a36Sopenharmony_ci#endif /* CONFIG_ADB_PMU */ 18962306a36Sopenharmony_ci LOCK(flags); 19062306a36Sopenharmony_ci fcr = MACIO_IN32(OHARE_FCR); 19162306a36Sopenharmony_ci /* Check if scc cell need enabling */ 19262306a36Sopenharmony_ci if (!(fcr & OH_SCC_ENABLE)) { 19362306a36Sopenharmony_ci fcr |= OH_SCC_ENABLE; 19462306a36Sopenharmony_ci if (htw) { 19562306a36Sopenharmony_ci /* Side effect: this will also power up the 19662306a36Sopenharmony_ci * modem, but it's too messy to figure out on which 19762306a36Sopenharmony_ci * ports this controls the transceiver and on which 19862306a36Sopenharmony_ci * it controls the modem 19962306a36Sopenharmony_ci */ 20062306a36Sopenharmony_ci if (trans) 20162306a36Sopenharmony_ci fcr &= ~HRW_SCC_TRANS_EN_N; 20262306a36Sopenharmony_ci MACIO_OUT32(OHARE_FCR, fcr); 20362306a36Sopenharmony_ci fcr |= (rmask = HRW_RESET_SCC); 20462306a36Sopenharmony_ci MACIO_OUT32(OHARE_FCR, fcr); 20562306a36Sopenharmony_ci } else { 20662306a36Sopenharmony_ci fcr |= (rmask = OH_SCC_RESET); 20762306a36Sopenharmony_ci MACIO_OUT32(OHARE_FCR, fcr); 20862306a36Sopenharmony_ci } 20962306a36Sopenharmony_ci UNLOCK(flags); 21062306a36Sopenharmony_ci (void)MACIO_IN32(OHARE_FCR); 21162306a36Sopenharmony_ci mdelay(15); 21262306a36Sopenharmony_ci LOCK(flags); 21362306a36Sopenharmony_ci fcr &= ~rmask; 21462306a36Sopenharmony_ci MACIO_OUT32(OHARE_FCR, fcr); 21562306a36Sopenharmony_ci } 21662306a36Sopenharmony_ci if (chan_mask & MACIO_FLAG_SCCA_ON) 21762306a36Sopenharmony_ci fcr |= OH_SCCA_IO; 21862306a36Sopenharmony_ci if (chan_mask & MACIO_FLAG_SCCB_ON) 21962306a36Sopenharmony_ci fcr |= OH_SCCB_IO; 22062306a36Sopenharmony_ci MACIO_OUT32(OHARE_FCR, fcr); 22162306a36Sopenharmony_ci macio->flags |= chan_mask; 22262306a36Sopenharmony_ci UNLOCK(flags); 22362306a36Sopenharmony_ci if (param & PMAC_SCC_FLAG_XMON) 22462306a36Sopenharmony_ci macio->flags |= MACIO_FLAG_SCC_LOCKED; 22562306a36Sopenharmony_ci } else { 22662306a36Sopenharmony_ci if (macio->flags & MACIO_FLAG_SCC_LOCKED) 22762306a36Sopenharmony_ci return -EPERM; 22862306a36Sopenharmony_ci LOCK(flags); 22962306a36Sopenharmony_ci fcr = MACIO_IN32(OHARE_FCR); 23062306a36Sopenharmony_ci if (chan_mask & MACIO_FLAG_SCCA_ON) 23162306a36Sopenharmony_ci fcr &= ~OH_SCCA_IO; 23262306a36Sopenharmony_ci if (chan_mask & MACIO_FLAG_SCCB_ON) 23362306a36Sopenharmony_ci fcr &= ~OH_SCCB_IO; 23462306a36Sopenharmony_ci MACIO_OUT32(OHARE_FCR, fcr); 23562306a36Sopenharmony_ci if ((fcr & (OH_SCCA_IO | OH_SCCB_IO)) == 0) { 23662306a36Sopenharmony_ci fcr &= ~OH_SCC_ENABLE; 23762306a36Sopenharmony_ci if (htw && trans) 23862306a36Sopenharmony_ci fcr |= HRW_SCC_TRANS_EN_N; 23962306a36Sopenharmony_ci MACIO_OUT32(OHARE_FCR, fcr); 24062306a36Sopenharmony_ci } 24162306a36Sopenharmony_ci macio->flags &= ~(chan_mask); 24262306a36Sopenharmony_ci UNLOCK(flags); 24362306a36Sopenharmony_ci mdelay(10); 24462306a36Sopenharmony_ci#ifdef CONFIG_ADB_PMU 24562306a36Sopenharmony_ci if ((param & 0xfff) == PMAC_SCC_IRDA) 24662306a36Sopenharmony_ci pmu_enable_irled(0); 24762306a36Sopenharmony_ci#endif /* CONFIG_ADB_PMU */ 24862306a36Sopenharmony_ci } 24962306a36Sopenharmony_ci return 0; 25062306a36Sopenharmony_ci} 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_cistatic long ohare_floppy_enable(struct device_node *node, long param, 25362306a36Sopenharmony_ci long value) 25462306a36Sopenharmony_ci{ 25562306a36Sopenharmony_ci return simple_feature_tweak(node, macio_ohare, 25662306a36Sopenharmony_ci OHARE_FCR, OH_FLOPPY_ENABLE, value); 25762306a36Sopenharmony_ci} 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_cistatic long ohare_mesh_enable(struct device_node *node, long param, long value) 26062306a36Sopenharmony_ci{ 26162306a36Sopenharmony_ci return simple_feature_tweak(node, macio_ohare, 26262306a36Sopenharmony_ci OHARE_FCR, OH_MESH_ENABLE, value); 26362306a36Sopenharmony_ci} 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_cistatic long ohare_ide_enable(struct device_node *node, long param, long value) 26662306a36Sopenharmony_ci{ 26762306a36Sopenharmony_ci switch(param) { 26862306a36Sopenharmony_ci case 0: 26962306a36Sopenharmony_ci /* For some reason, setting the bit in set_initial_features() 27062306a36Sopenharmony_ci * doesn't stick. I'm still investigating... --BenH. 27162306a36Sopenharmony_ci */ 27262306a36Sopenharmony_ci if (value) 27362306a36Sopenharmony_ci simple_feature_tweak(node, macio_ohare, 27462306a36Sopenharmony_ci OHARE_FCR, OH_IOBUS_ENABLE, 1); 27562306a36Sopenharmony_ci return simple_feature_tweak(node, macio_ohare, 27662306a36Sopenharmony_ci OHARE_FCR, OH_IDE0_ENABLE, value); 27762306a36Sopenharmony_ci case 1: 27862306a36Sopenharmony_ci return simple_feature_tweak(node, macio_ohare, 27962306a36Sopenharmony_ci OHARE_FCR, OH_BAY_IDE_ENABLE, value); 28062306a36Sopenharmony_ci default: 28162306a36Sopenharmony_ci return -ENODEV; 28262306a36Sopenharmony_ci } 28362306a36Sopenharmony_ci} 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_cistatic long ohare_ide_reset(struct device_node *node, long param, long value) 28662306a36Sopenharmony_ci{ 28762306a36Sopenharmony_ci switch(param) { 28862306a36Sopenharmony_ci case 0: 28962306a36Sopenharmony_ci return simple_feature_tweak(node, macio_ohare, 29062306a36Sopenharmony_ci OHARE_FCR, OH_IDE0_RESET_N, !value); 29162306a36Sopenharmony_ci case 1: 29262306a36Sopenharmony_ci return simple_feature_tweak(node, macio_ohare, 29362306a36Sopenharmony_ci OHARE_FCR, OH_IDE1_RESET_N, !value); 29462306a36Sopenharmony_ci default: 29562306a36Sopenharmony_ci return -ENODEV; 29662306a36Sopenharmony_ci } 29762306a36Sopenharmony_ci} 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_cistatic long ohare_sleep_state(struct device_node *node, long param, long value) 30062306a36Sopenharmony_ci{ 30162306a36Sopenharmony_ci struct macio_chip* macio = &macio_chips[0]; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0) 30462306a36Sopenharmony_ci return -EPERM; 30562306a36Sopenharmony_ci if (value == 1) { 30662306a36Sopenharmony_ci MACIO_BIC(OHARE_FCR, OH_IOBUS_ENABLE); 30762306a36Sopenharmony_ci } else if (value == 0) { 30862306a36Sopenharmony_ci MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); 30962306a36Sopenharmony_ci } 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci return 0; 31262306a36Sopenharmony_ci} 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_cistatic long heathrow_modem_enable(struct device_node *node, long param, 31562306a36Sopenharmony_ci long value) 31662306a36Sopenharmony_ci{ 31762306a36Sopenharmony_ci struct macio_chip* macio; 31862306a36Sopenharmony_ci u8 gpio; 31962306a36Sopenharmony_ci unsigned long flags; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci macio = macio_find(node, macio_unknown); 32262306a36Sopenharmony_ci if (!macio) 32362306a36Sopenharmony_ci return -ENODEV; 32462306a36Sopenharmony_ci gpio = MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1; 32562306a36Sopenharmony_ci if (!value) { 32662306a36Sopenharmony_ci LOCK(flags); 32762306a36Sopenharmony_ci MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio); 32862306a36Sopenharmony_ci UNLOCK(flags); 32962306a36Sopenharmony_ci (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); 33062306a36Sopenharmony_ci mdelay(250); 33162306a36Sopenharmony_ci } 33262306a36Sopenharmony_ci if (pmac_mb.model_id != PMAC_TYPE_YOSEMITE && 33362306a36Sopenharmony_ci pmac_mb.model_id != PMAC_TYPE_YIKES) { 33462306a36Sopenharmony_ci LOCK(flags); 33562306a36Sopenharmony_ci if (value) 33662306a36Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_SCC_TRANS_EN_N); 33762306a36Sopenharmony_ci else 33862306a36Sopenharmony_ci MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N); 33962306a36Sopenharmony_ci UNLOCK(flags); 34062306a36Sopenharmony_ci (void)MACIO_IN32(HEATHROW_FCR); 34162306a36Sopenharmony_ci mdelay(250); 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci if (value) { 34462306a36Sopenharmony_ci LOCK(flags); 34562306a36Sopenharmony_ci MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1); 34662306a36Sopenharmony_ci (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); 34762306a36Sopenharmony_ci UNLOCK(flags); mdelay(250); LOCK(flags); 34862306a36Sopenharmony_ci MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio); 34962306a36Sopenharmony_ci (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); 35062306a36Sopenharmony_ci UNLOCK(flags); mdelay(250); LOCK(flags); 35162306a36Sopenharmony_ci MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1); 35262306a36Sopenharmony_ci (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); 35362306a36Sopenharmony_ci UNLOCK(flags); mdelay(250); 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci return 0; 35662306a36Sopenharmony_ci} 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_cistatic long heathrow_floppy_enable(struct device_node *node, long param, 35962306a36Sopenharmony_ci long value) 36062306a36Sopenharmony_ci{ 36162306a36Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 36262306a36Sopenharmony_ci HEATHROW_FCR, 36362306a36Sopenharmony_ci HRW_SWIM_ENABLE|HRW_BAY_FLOPPY_ENABLE, 36462306a36Sopenharmony_ci value); 36562306a36Sopenharmony_ci} 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_cistatic long heathrow_mesh_enable(struct device_node *node, long param, 36862306a36Sopenharmony_ci long value) 36962306a36Sopenharmony_ci{ 37062306a36Sopenharmony_ci struct macio_chip* macio; 37162306a36Sopenharmony_ci unsigned long flags; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci macio = macio_find(node, macio_unknown); 37462306a36Sopenharmony_ci if (!macio) 37562306a36Sopenharmony_ci return -ENODEV; 37662306a36Sopenharmony_ci LOCK(flags); 37762306a36Sopenharmony_ci /* Set clear mesh cell enable */ 37862306a36Sopenharmony_ci if (value) 37962306a36Sopenharmony_ci MACIO_BIS(HEATHROW_FCR, HRW_MESH_ENABLE); 38062306a36Sopenharmony_ci else 38162306a36Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_MESH_ENABLE); 38262306a36Sopenharmony_ci (void)MACIO_IN32(HEATHROW_FCR); 38362306a36Sopenharmony_ci udelay(10); 38462306a36Sopenharmony_ci /* Set/Clear termination power */ 38562306a36Sopenharmony_ci if (value) 38662306a36Sopenharmony_ci MACIO_BIC(HEATHROW_MBCR, 0x04000000); 38762306a36Sopenharmony_ci else 38862306a36Sopenharmony_ci MACIO_BIS(HEATHROW_MBCR, 0x04000000); 38962306a36Sopenharmony_ci (void)MACIO_IN32(HEATHROW_MBCR); 39062306a36Sopenharmony_ci udelay(10); 39162306a36Sopenharmony_ci UNLOCK(flags); 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci return 0; 39462306a36Sopenharmony_ci} 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_cistatic long heathrow_ide_enable(struct device_node *node, long param, 39762306a36Sopenharmony_ci long value) 39862306a36Sopenharmony_ci{ 39962306a36Sopenharmony_ci switch(param) { 40062306a36Sopenharmony_ci case 0: 40162306a36Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 40262306a36Sopenharmony_ci HEATHROW_FCR, HRW_IDE0_ENABLE, value); 40362306a36Sopenharmony_ci case 1: 40462306a36Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 40562306a36Sopenharmony_ci HEATHROW_FCR, HRW_BAY_IDE_ENABLE, value); 40662306a36Sopenharmony_ci default: 40762306a36Sopenharmony_ci return -ENODEV; 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci} 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_cistatic long heathrow_ide_reset(struct device_node *node, long param, 41262306a36Sopenharmony_ci long value) 41362306a36Sopenharmony_ci{ 41462306a36Sopenharmony_ci switch(param) { 41562306a36Sopenharmony_ci case 0: 41662306a36Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 41762306a36Sopenharmony_ci HEATHROW_FCR, HRW_IDE0_RESET_N, !value); 41862306a36Sopenharmony_ci case 1: 41962306a36Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 42062306a36Sopenharmony_ci HEATHROW_FCR, HRW_IDE1_RESET_N, !value); 42162306a36Sopenharmony_ci default: 42262306a36Sopenharmony_ci return -ENODEV; 42362306a36Sopenharmony_ci } 42462306a36Sopenharmony_ci} 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_cistatic long heathrow_bmac_enable(struct device_node *node, long param, 42762306a36Sopenharmony_ci long value) 42862306a36Sopenharmony_ci{ 42962306a36Sopenharmony_ci struct macio_chip* macio; 43062306a36Sopenharmony_ci unsigned long flags; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci macio = macio_find(node, 0); 43362306a36Sopenharmony_ci if (!macio) 43462306a36Sopenharmony_ci return -ENODEV; 43562306a36Sopenharmony_ci if (value) { 43662306a36Sopenharmony_ci LOCK(flags); 43762306a36Sopenharmony_ci MACIO_BIS(HEATHROW_FCR, HRW_BMAC_IO_ENABLE); 43862306a36Sopenharmony_ci MACIO_BIS(HEATHROW_FCR, HRW_BMAC_RESET); 43962306a36Sopenharmony_ci UNLOCK(flags); 44062306a36Sopenharmony_ci (void)MACIO_IN32(HEATHROW_FCR); 44162306a36Sopenharmony_ci mdelay(10); 44262306a36Sopenharmony_ci LOCK(flags); 44362306a36Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_BMAC_RESET); 44462306a36Sopenharmony_ci UNLOCK(flags); 44562306a36Sopenharmony_ci (void)MACIO_IN32(HEATHROW_FCR); 44662306a36Sopenharmony_ci mdelay(10); 44762306a36Sopenharmony_ci } else { 44862306a36Sopenharmony_ci LOCK(flags); 44962306a36Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE); 45062306a36Sopenharmony_ci UNLOCK(flags); 45162306a36Sopenharmony_ci } 45262306a36Sopenharmony_ci return 0; 45362306a36Sopenharmony_ci} 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_cistatic long heathrow_sound_enable(struct device_node *node, long param, 45662306a36Sopenharmony_ci long value) 45762306a36Sopenharmony_ci{ 45862306a36Sopenharmony_ci struct macio_chip* macio; 45962306a36Sopenharmony_ci unsigned long flags; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci /* B&W G3 and Yikes don't support that properly (the 46262306a36Sopenharmony_ci * sound appear to never come back after being shut down). 46362306a36Sopenharmony_ci */ 46462306a36Sopenharmony_ci if (pmac_mb.model_id == PMAC_TYPE_YOSEMITE || 46562306a36Sopenharmony_ci pmac_mb.model_id == PMAC_TYPE_YIKES) 46662306a36Sopenharmony_ci return 0; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci macio = macio_find(node, 0); 46962306a36Sopenharmony_ci if (!macio) 47062306a36Sopenharmony_ci return -ENODEV; 47162306a36Sopenharmony_ci if (value) { 47262306a36Sopenharmony_ci LOCK(flags); 47362306a36Sopenharmony_ci MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); 47462306a36Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N); 47562306a36Sopenharmony_ci UNLOCK(flags); 47662306a36Sopenharmony_ci (void)MACIO_IN32(HEATHROW_FCR); 47762306a36Sopenharmony_ci } else { 47862306a36Sopenharmony_ci LOCK(flags); 47962306a36Sopenharmony_ci MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N); 48062306a36Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); 48162306a36Sopenharmony_ci UNLOCK(flags); 48262306a36Sopenharmony_ci } 48362306a36Sopenharmony_ci return 0; 48462306a36Sopenharmony_ci} 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_cistatic u32 save_fcr[6]; 48762306a36Sopenharmony_cistatic u32 save_mbcr; 48862306a36Sopenharmony_cistatic struct dbdma_regs save_dbdma[13]; 48962306a36Sopenharmony_cistatic struct dbdma_regs save_alt_dbdma[13]; 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_cistatic void dbdma_save(struct macio_chip *macio, struct dbdma_regs *save) 49262306a36Sopenharmony_ci{ 49362306a36Sopenharmony_ci int i; 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci /* Save state & config of DBDMA channels */ 49662306a36Sopenharmony_ci for (i = 0; i < 13; i++) { 49762306a36Sopenharmony_ci volatile struct dbdma_regs __iomem * chan = (void __iomem *) 49862306a36Sopenharmony_ci (macio->base + ((0x8000+i*0x100)>>2)); 49962306a36Sopenharmony_ci save[i].cmdptr_hi = in_le32(&chan->cmdptr_hi); 50062306a36Sopenharmony_ci save[i].cmdptr = in_le32(&chan->cmdptr); 50162306a36Sopenharmony_ci save[i].intr_sel = in_le32(&chan->intr_sel); 50262306a36Sopenharmony_ci save[i].br_sel = in_le32(&chan->br_sel); 50362306a36Sopenharmony_ci save[i].wait_sel = in_le32(&chan->wait_sel); 50462306a36Sopenharmony_ci } 50562306a36Sopenharmony_ci} 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_cistatic void dbdma_restore(struct macio_chip *macio, struct dbdma_regs *save) 50862306a36Sopenharmony_ci{ 50962306a36Sopenharmony_ci int i; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci /* Save state & config of DBDMA channels */ 51262306a36Sopenharmony_ci for (i = 0; i < 13; i++) { 51362306a36Sopenharmony_ci volatile struct dbdma_regs __iomem * chan = (void __iomem *) 51462306a36Sopenharmony_ci (macio->base + ((0x8000+i*0x100)>>2)); 51562306a36Sopenharmony_ci out_le32(&chan->control, (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16); 51662306a36Sopenharmony_ci while (in_le32(&chan->status) & ACTIVE) 51762306a36Sopenharmony_ci mb(); 51862306a36Sopenharmony_ci out_le32(&chan->cmdptr_hi, save[i].cmdptr_hi); 51962306a36Sopenharmony_ci out_le32(&chan->cmdptr, save[i].cmdptr); 52062306a36Sopenharmony_ci out_le32(&chan->intr_sel, save[i].intr_sel); 52162306a36Sopenharmony_ci out_le32(&chan->br_sel, save[i].br_sel); 52262306a36Sopenharmony_ci out_le32(&chan->wait_sel, save[i].wait_sel); 52362306a36Sopenharmony_ci } 52462306a36Sopenharmony_ci} 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_cistatic void heathrow_sleep(struct macio_chip *macio, int secondary) 52762306a36Sopenharmony_ci{ 52862306a36Sopenharmony_ci if (secondary) { 52962306a36Sopenharmony_ci dbdma_save(macio, save_alt_dbdma); 53062306a36Sopenharmony_ci save_fcr[2] = MACIO_IN32(0x38); 53162306a36Sopenharmony_ci save_fcr[3] = MACIO_IN32(0x3c); 53262306a36Sopenharmony_ci } else { 53362306a36Sopenharmony_ci dbdma_save(macio, save_dbdma); 53462306a36Sopenharmony_ci save_fcr[0] = MACIO_IN32(0x38); 53562306a36Sopenharmony_ci save_fcr[1] = MACIO_IN32(0x3c); 53662306a36Sopenharmony_ci save_mbcr = MACIO_IN32(0x34); 53762306a36Sopenharmony_ci /* Make sure sound is shut down */ 53862306a36Sopenharmony_ci MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N); 53962306a36Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); 54062306a36Sopenharmony_ci /* This seems to be necessary as well or the fan 54162306a36Sopenharmony_ci * keeps coming up and battery drains fast */ 54262306a36Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_IOBUS_ENABLE); 54362306a36Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_IDE0_RESET_N); 54462306a36Sopenharmony_ci /* Make sure eth is down even if module or sleep 54562306a36Sopenharmony_ci * won't work properly */ 54662306a36Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE | HRW_BMAC_RESET); 54762306a36Sopenharmony_ci } 54862306a36Sopenharmony_ci /* Make sure modem is shut down */ 54962306a36Sopenharmony_ci MACIO_OUT8(HRW_GPIO_MODEM_RESET, 55062306a36Sopenharmony_ci MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1); 55162306a36Sopenharmony_ci MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N); 55262306a36Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, OH_SCCA_IO|OH_SCCB_IO|HRW_SCC_ENABLE); 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci /* Let things settle */ 55562306a36Sopenharmony_ci (void)MACIO_IN32(HEATHROW_FCR); 55662306a36Sopenharmony_ci} 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_cistatic void heathrow_wakeup(struct macio_chip *macio, int secondary) 55962306a36Sopenharmony_ci{ 56062306a36Sopenharmony_ci if (secondary) { 56162306a36Sopenharmony_ci MACIO_OUT32(0x38, save_fcr[2]); 56262306a36Sopenharmony_ci (void)MACIO_IN32(0x38); 56362306a36Sopenharmony_ci mdelay(1); 56462306a36Sopenharmony_ci MACIO_OUT32(0x3c, save_fcr[3]); 56562306a36Sopenharmony_ci (void)MACIO_IN32(0x38); 56662306a36Sopenharmony_ci mdelay(10); 56762306a36Sopenharmony_ci dbdma_restore(macio, save_alt_dbdma); 56862306a36Sopenharmony_ci } else { 56962306a36Sopenharmony_ci MACIO_OUT32(0x38, save_fcr[0] | HRW_IOBUS_ENABLE); 57062306a36Sopenharmony_ci (void)MACIO_IN32(0x38); 57162306a36Sopenharmony_ci mdelay(1); 57262306a36Sopenharmony_ci MACIO_OUT32(0x3c, save_fcr[1]); 57362306a36Sopenharmony_ci (void)MACIO_IN32(0x38); 57462306a36Sopenharmony_ci mdelay(1); 57562306a36Sopenharmony_ci MACIO_OUT32(0x34, save_mbcr); 57662306a36Sopenharmony_ci (void)MACIO_IN32(0x38); 57762306a36Sopenharmony_ci mdelay(10); 57862306a36Sopenharmony_ci dbdma_restore(macio, save_dbdma); 57962306a36Sopenharmony_ci } 58062306a36Sopenharmony_ci} 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_cistatic long heathrow_sleep_state(struct device_node *node, long param, 58362306a36Sopenharmony_ci long value) 58462306a36Sopenharmony_ci{ 58562306a36Sopenharmony_ci if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0) 58662306a36Sopenharmony_ci return -EPERM; 58762306a36Sopenharmony_ci if (value == 1) { 58862306a36Sopenharmony_ci if (macio_chips[1].type == macio_gatwick) 58962306a36Sopenharmony_ci heathrow_sleep(&macio_chips[0], 1); 59062306a36Sopenharmony_ci heathrow_sleep(&macio_chips[0], 0); 59162306a36Sopenharmony_ci } else if (value == 0) { 59262306a36Sopenharmony_ci heathrow_wakeup(&macio_chips[0], 0); 59362306a36Sopenharmony_ci if (macio_chips[1].type == macio_gatwick) 59462306a36Sopenharmony_ci heathrow_wakeup(&macio_chips[0], 1); 59562306a36Sopenharmony_ci } 59662306a36Sopenharmony_ci return 0; 59762306a36Sopenharmony_ci} 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_cistatic long core99_scc_enable(struct device_node *node, long param, long value) 60062306a36Sopenharmony_ci{ 60162306a36Sopenharmony_ci struct macio_chip* macio; 60262306a36Sopenharmony_ci unsigned long flags; 60362306a36Sopenharmony_ci unsigned long chan_mask; 60462306a36Sopenharmony_ci u32 fcr; 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci macio = macio_find(node, 0); 60762306a36Sopenharmony_ci if (!macio) 60862306a36Sopenharmony_ci return -ENODEV; 60962306a36Sopenharmony_ci if (of_node_name_eq(node, "ch-a")) 61062306a36Sopenharmony_ci chan_mask = MACIO_FLAG_SCCA_ON; 61162306a36Sopenharmony_ci else if (of_node_name_eq(node, "ch-b")) 61262306a36Sopenharmony_ci chan_mask = MACIO_FLAG_SCCB_ON; 61362306a36Sopenharmony_ci else 61462306a36Sopenharmony_ci return -ENODEV; 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci if (value) { 61762306a36Sopenharmony_ci int need_reset_scc = 0; 61862306a36Sopenharmony_ci int need_reset_irda = 0; 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci LOCK(flags); 62162306a36Sopenharmony_ci fcr = MACIO_IN32(KEYLARGO_FCR0); 62262306a36Sopenharmony_ci /* Check if scc cell need enabling */ 62362306a36Sopenharmony_ci if (!(fcr & KL0_SCC_CELL_ENABLE)) { 62462306a36Sopenharmony_ci fcr |= KL0_SCC_CELL_ENABLE; 62562306a36Sopenharmony_ci need_reset_scc = 1; 62662306a36Sopenharmony_ci } 62762306a36Sopenharmony_ci if (chan_mask & MACIO_FLAG_SCCA_ON) { 62862306a36Sopenharmony_ci fcr |= KL0_SCCA_ENABLE; 62962306a36Sopenharmony_ci /* Don't enable line drivers for I2S modem */ 63062306a36Sopenharmony_ci if ((param & 0xfff) == PMAC_SCC_I2S1) 63162306a36Sopenharmony_ci fcr &= ~KL0_SCC_A_INTF_ENABLE; 63262306a36Sopenharmony_ci else 63362306a36Sopenharmony_ci fcr |= KL0_SCC_A_INTF_ENABLE; 63462306a36Sopenharmony_ci } 63562306a36Sopenharmony_ci if (chan_mask & MACIO_FLAG_SCCB_ON) { 63662306a36Sopenharmony_ci fcr |= KL0_SCCB_ENABLE; 63762306a36Sopenharmony_ci /* Perform irda specific inits */ 63862306a36Sopenharmony_ci if ((param & 0xfff) == PMAC_SCC_IRDA) { 63962306a36Sopenharmony_ci fcr &= ~KL0_SCC_B_INTF_ENABLE; 64062306a36Sopenharmony_ci fcr |= KL0_IRDA_ENABLE; 64162306a36Sopenharmony_ci fcr |= KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE; 64262306a36Sopenharmony_ci fcr |= KL0_IRDA_SOURCE1_SEL; 64362306a36Sopenharmony_ci fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0); 64462306a36Sopenharmony_ci fcr &= ~(KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND); 64562306a36Sopenharmony_ci need_reset_irda = 1; 64662306a36Sopenharmony_ci } else 64762306a36Sopenharmony_ci fcr |= KL0_SCC_B_INTF_ENABLE; 64862306a36Sopenharmony_ci } 64962306a36Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR0, fcr); 65062306a36Sopenharmony_ci macio->flags |= chan_mask; 65162306a36Sopenharmony_ci if (need_reset_scc) { 65262306a36Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR0, KL0_SCC_RESET); 65362306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); 65462306a36Sopenharmony_ci UNLOCK(flags); 65562306a36Sopenharmony_ci mdelay(15); 65662306a36Sopenharmony_ci LOCK(flags); 65762306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR0, KL0_SCC_RESET); 65862306a36Sopenharmony_ci } 65962306a36Sopenharmony_ci if (need_reset_irda) { 66062306a36Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR0, KL0_IRDA_RESET); 66162306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); 66262306a36Sopenharmony_ci UNLOCK(flags); 66362306a36Sopenharmony_ci mdelay(15); 66462306a36Sopenharmony_ci LOCK(flags); 66562306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR0, KL0_IRDA_RESET); 66662306a36Sopenharmony_ci } 66762306a36Sopenharmony_ci UNLOCK(flags); 66862306a36Sopenharmony_ci if (param & PMAC_SCC_FLAG_XMON) 66962306a36Sopenharmony_ci macio->flags |= MACIO_FLAG_SCC_LOCKED; 67062306a36Sopenharmony_ci } else { 67162306a36Sopenharmony_ci if (macio->flags & MACIO_FLAG_SCC_LOCKED) 67262306a36Sopenharmony_ci return -EPERM; 67362306a36Sopenharmony_ci LOCK(flags); 67462306a36Sopenharmony_ci fcr = MACIO_IN32(KEYLARGO_FCR0); 67562306a36Sopenharmony_ci if (chan_mask & MACIO_FLAG_SCCA_ON) 67662306a36Sopenharmony_ci fcr &= ~KL0_SCCA_ENABLE; 67762306a36Sopenharmony_ci if (chan_mask & MACIO_FLAG_SCCB_ON) { 67862306a36Sopenharmony_ci fcr &= ~KL0_SCCB_ENABLE; 67962306a36Sopenharmony_ci /* Perform irda specific clears */ 68062306a36Sopenharmony_ci if ((param & 0xfff) == PMAC_SCC_IRDA) { 68162306a36Sopenharmony_ci fcr &= ~KL0_IRDA_ENABLE; 68262306a36Sopenharmony_ci fcr &= ~(KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE); 68362306a36Sopenharmony_ci fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0); 68462306a36Sopenharmony_ci fcr &= ~(KL0_IRDA_SOURCE1_SEL|KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND); 68562306a36Sopenharmony_ci } 68662306a36Sopenharmony_ci } 68762306a36Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR0, fcr); 68862306a36Sopenharmony_ci if ((fcr & (KL0_SCCA_ENABLE | KL0_SCCB_ENABLE)) == 0) { 68962306a36Sopenharmony_ci fcr &= ~KL0_SCC_CELL_ENABLE; 69062306a36Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR0, fcr); 69162306a36Sopenharmony_ci } 69262306a36Sopenharmony_ci macio->flags &= ~(chan_mask); 69362306a36Sopenharmony_ci UNLOCK(flags); 69462306a36Sopenharmony_ci mdelay(10); 69562306a36Sopenharmony_ci } 69662306a36Sopenharmony_ci return 0; 69762306a36Sopenharmony_ci} 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_cistatic long 70062306a36Sopenharmony_cicore99_modem_enable(struct device_node *node, long param, long value) 70162306a36Sopenharmony_ci{ 70262306a36Sopenharmony_ci struct macio_chip* macio; 70362306a36Sopenharmony_ci u8 gpio; 70462306a36Sopenharmony_ci unsigned long flags; 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci /* Hack for internal USB modem */ 70762306a36Sopenharmony_ci if (node == NULL) { 70862306a36Sopenharmony_ci if (macio_chips[0].type != macio_keylargo) 70962306a36Sopenharmony_ci return -ENODEV; 71062306a36Sopenharmony_ci node = macio_chips[0].of_node; 71162306a36Sopenharmony_ci } 71262306a36Sopenharmony_ci macio = macio_find(node, 0); 71362306a36Sopenharmony_ci if (!macio) 71462306a36Sopenharmony_ci return -ENODEV; 71562306a36Sopenharmony_ci gpio = MACIO_IN8(KL_GPIO_MODEM_RESET); 71662306a36Sopenharmony_ci gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE; 71762306a36Sopenharmony_ci gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA; 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci if (!value) { 72062306a36Sopenharmony_ci LOCK(flags); 72162306a36Sopenharmony_ci MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); 72262306a36Sopenharmony_ci UNLOCK(flags); 72362306a36Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_MODEM_RESET); 72462306a36Sopenharmony_ci mdelay(250); 72562306a36Sopenharmony_ci } 72662306a36Sopenharmony_ci LOCK(flags); 72762306a36Sopenharmony_ci if (value) { 72862306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); 72962306a36Sopenharmony_ci UNLOCK(flags); 73062306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR2); 73162306a36Sopenharmony_ci mdelay(250); 73262306a36Sopenharmony_ci } else { 73362306a36Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); 73462306a36Sopenharmony_ci UNLOCK(flags); 73562306a36Sopenharmony_ci } 73662306a36Sopenharmony_ci if (value) { 73762306a36Sopenharmony_ci LOCK(flags); 73862306a36Sopenharmony_ci MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); 73962306a36Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_MODEM_RESET); 74062306a36Sopenharmony_ci UNLOCK(flags); mdelay(250); LOCK(flags); 74162306a36Sopenharmony_ci MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); 74262306a36Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_MODEM_RESET); 74362306a36Sopenharmony_ci UNLOCK(flags); mdelay(250); LOCK(flags); 74462306a36Sopenharmony_ci MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); 74562306a36Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_MODEM_RESET); 74662306a36Sopenharmony_ci UNLOCK(flags); mdelay(250); 74762306a36Sopenharmony_ci } 74862306a36Sopenharmony_ci return 0; 74962306a36Sopenharmony_ci} 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_cistatic long 75262306a36Sopenharmony_cipangea_modem_enable(struct device_node *node, long param, long value) 75362306a36Sopenharmony_ci{ 75462306a36Sopenharmony_ci struct macio_chip* macio; 75562306a36Sopenharmony_ci u8 gpio; 75662306a36Sopenharmony_ci unsigned long flags; 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci /* Hack for internal USB modem */ 75962306a36Sopenharmony_ci if (node == NULL) { 76062306a36Sopenharmony_ci if (macio_chips[0].type != macio_pangea && 76162306a36Sopenharmony_ci macio_chips[0].type != macio_intrepid) 76262306a36Sopenharmony_ci return -ENODEV; 76362306a36Sopenharmony_ci node = macio_chips[0].of_node; 76462306a36Sopenharmony_ci } 76562306a36Sopenharmony_ci macio = macio_find(node, 0); 76662306a36Sopenharmony_ci if (!macio) 76762306a36Sopenharmony_ci return -ENODEV; 76862306a36Sopenharmony_ci gpio = MACIO_IN8(KL_GPIO_MODEM_RESET); 76962306a36Sopenharmony_ci gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE; 77062306a36Sopenharmony_ci gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA; 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci if (!value) { 77362306a36Sopenharmony_ci LOCK(flags); 77462306a36Sopenharmony_ci MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); 77562306a36Sopenharmony_ci UNLOCK(flags); 77662306a36Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_MODEM_RESET); 77762306a36Sopenharmony_ci mdelay(250); 77862306a36Sopenharmony_ci } 77962306a36Sopenharmony_ci LOCK(flags); 78062306a36Sopenharmony_ci if (value) { 78162306a36Sopenharmony_ci MACIO_OUT8(KL_GPIO_MODEM_POWER, 78262306a36Sopenharmony_ci KEYLARGO_GPIO_OUTPUT_ENABLE); 78362306a36Sopenharmony_ci UNLOCK(flags); 78462306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR2); 78562306a36Sopenharmony_ci mdelay(250); 78662306a36Sopenharmony_ci } else { 78762306a36Sopenharmony_ci MACIO_OUT8(KL_GPIO_MODEM_POWER, 78862306a36Sopenharmony_ci KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); 78962306a36Sopenharmony_ci UNLOCK(flags); 79062306a36Sopenharmony_ci } 79162306a36Sopenharmony_ci if (value) { 79262306a36Sopenharmony_ci LOCK(flags); 79362306a36Sopenharmony_ci MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); 79462306a36Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_MODEM_RESET); 79562306a36Sopenharmony_ci UNLOCK(flags); mdelay(250); LOCK(flags); 79662306a36Sopenharmony_ci MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); 79762306a36Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_MODEM_RESET); 79862306a36Sopenharmony_ci UNLOCK(flags); mdelay(250); LOCK(flags); 79962306a36Sopenharmony_ci MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); 80062306a36Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_MODEM_RESET); 80162306a36Sopenharmony_ci UNLOCK(flags); mdelay(250); 80262306a36Sopenharmony_ci } 80362306a36Sopenharmony_ci return 0; 80462306a36Sopenharmony_ci} 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_cistatic long 80762306a36Sopenharmony_cicore99_ata100_enable(struct device_node *node, long value) 80862306a36Sopenharmony_ci{ 80962306a36Sopenharmony_ci unsigned long flags; 81062306a36Sopenharmony_ci struct pci_dev *pdev = NULL; 81162306a36Sopenharmony_ci u8 pbus, pid; 81262306a36Sopenharmony_ci int rc; 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci if (uninorth_rev < 0x24) 81562306a36Sopenharmony_ci return -ENODEV; 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci LOCK(flags); 81862306a36Sopenharmony_ci if (value) 81962306a36Sopenharmony_ci UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100); 82062306a36Sopenharmony_ci else 82162306a36Sopenharmony_ci UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100); 82262306a36Sopenharmony_ci (void)UN_IN(UNI_N_CLOCK_CNTL); 82362306a36Sopenharmony_ci UNLOCK(flags); 82462306a36Sopenharmony_ci udelay(20); 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci if (value) { 82762306a36Sopenharmony_ci if (pci_device_from_OF_node(node, &pbus, &pid) == 0) 82862306a36Sopenharmony_ci pdev = pci_get_domain_bus_and_slot(0, pbus, pid); 82962306a36Sopenharmony_ci if (pdev == NULL) 83062306a36Sopenharmony_ci return 0; 83162306a36Sopenharmony_ci rc = pci_enable_device(pdev); 83262306a36Sopenharmony_ci if (rc == 0) 83362306a36Sopenharmony_ci pci_set_master(pdev); 83462306a36Sopenharmony_ci pci_dev_put(pdev); 83562306a36Sopenharmony_ci if (rc) 83662306a36Sopenharmony_ci return rc; 83762306a36Sopenharmony_ci } 83862306a36Sopenharmony_ci return 0; 83962306a36Sopenharmony_ci} 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_cistatic long 84262306a36Sopenharmony_cicore99_ide_enable(struct device_node *node, long param, long value) 84362306a36Sopenharmony_ci{ 84462306a36Sopenharmony_ci /* Bus ID 0 to 2 are KeyLargo based IDE, busID 3 is U2 84562306a36Sopenharmony_ci * based ata-100 84662306a36Sopenharmony_ci */ 84762306a36Sopenharmony_ci switch(param) { 84862306a36Sopenharmony_ci case 0: 84962306a36Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 85062306a36Sopenharmony_ci KEYLARGO_FCR1, KL1_EIDE0_ENABLE, value); 85162306a36Sopenharmony_ci case 1: 85262306a36Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 85362306a36Sopenharmony_ci KEYLARGO_FCR1, KL1_EIDE1_ENABLE, value); 85462306a36Sopenharmony_ci case 2: 85562306a36Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 85662306a36Sopenharmony_ci KEYLARGO_FCR1, KL1_UIDE_ENABLE, value); 85762306a36Sopenharmony_ci case 3: 85862306a36Sopenharmony_ci return core99_ata100_enable(node, value); 85962306a36Sopenharmony_ci default: 86062306a36Sopenharmony_ci return -ENODEV; 86162306a36Sopenharmony_ci } 86262306a36Sopenharmony_ci} 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_cistatic long 86562306a36Sopenharmony_cicore99_ide_reset(struct device_node *node, long param, long value) 86662306a36Sopenharmony_ci{ 86762306a36Sopenharmony_ci switch(param) { 86862306a36Sopenharmony_ci case 0: 86962306a36Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 87062306a36Sopenharmony_ci KEYLARGO_FCR1, KL1_EIDE0_RESET_N, !value); 87162306a36Sopenharmony_ci case 1: 87262306a36Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 87362306a36Sopenharmony_ci KEYLARGO_FCR1, KL1_EIDE1_RESET_N, !value); 87462306a36Sopenharmony_ci case 2: 87562306a36Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 87662306a36Sopenharmony_ci KEYLARGO_FCR1, KL1_UIDE_RESET_N, !value); 87762306a36Sopenharmony_ci default: 87862306a36Sopenharmony_ci return -ENODEV; 87962306a36Sopenharmony_ci } 88062306a36Sopenharmony_ci} 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_cistatic long 88362306a36Sopenharmony_cicore99_gmac_enable(struct device_node *node, long param, long value) 88462306a36Sopenharmony_ci{ 88562306a36Sopenharmony_ci unsigned long flags; 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci LOCK(flags); 88862306a36Sopenharmony_ci if (value) 88962306a36Sopenharmony_ci UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC); 89062306a36Sopenharmony_ci else 89162306a36Sopenharmony_ci UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC); 89262306a36Sopenharmony_ci (void)UN_IN(UNI_N_CLOCK_CNTL); 89362306a36Sopenharmony_ci UNLOCK(flags); 89462306a36Sopenharmony_ci udelay(20); 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci return 0; 89762306a36Sopenharmony_ci} 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_cistatic long 90062306a36Sopenharmony_cicore99_gmac_phy_reset(struct device_node *node, long param, long value) 90162306a36Sopenharmony_ci{ 90262306a36Sopenharmony_ci unsigned long flags; 90362306a36Sopenharmony_ci struct macio_chip *macio; 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci macio = &macio_chips[0]; 90662306a36Sopenharmony_ci if (macio->type != macio_keylargo && macio->type != macio_pangea && 90762306a36Sopenharmony_ci macio->type != macio_intrepid) 90862306a36Sopenharmony_ci return -ENODEV; 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci LOCK(flags); 91162306a36Sopenharmony_ci MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE); 91262306a36Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_ETH_PHY_RESET); 91362306a36Sopenharmony_ci UNLOCK(flags); 91462306a36Sopenharmony_ci mdelay(10); 91562306a36Sopenharmony_ci LOCK(flags); 91662306a36Sopenharmony_ci MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, /*KEYLARGO_GPIO_OUTPUT_ENABLE | */ 91762306a36Sopenharmony_ci KEYLARGO_GPIO_OUTOUT_DATA); 91862306a36Sopenharmony_ci UNLOCK(flags); 91962306a36Sopenharmony_ci mdelay(10); 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci return 0; 92262306a36Sopenharmony_ci} 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_cistatic long 92562306a36Sopenharmony_cicore99_sound_chip_enable(struct device_node *node, long param, long value) 92662306a36Sopenharmony_ci{ 92762306a36Sopenharmony_ci struct macio_chip* macio; 92862306a36Sopenharmony_ci unsigned long flags; 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci macio = macio_find(node, 0); 93162306a36Sopenharmony_ci if (!macio) 93262306a36Sopenharmony_ci return -ENODEV; 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci /* Do a better probe code, screamer G4 desktops & 93562306a36Sopenharmony_ci * iMacs can do that too, add a recalibrate in 93662306a36Sopenharmony_ci * the driver as well 93762306a36Sopenharmony_ci */ 93862306a36Sopenharmony_ci if (pmac_mb.model_id == PMAC_TYPE_PISMO || 93962306a36Sopenharmony_ci pmac_mb.model_id == PMAC_TYPE_TITANIUM) { 94062306a36Sopenharmony_ci LOCK(flags); 94162306a36Sopenharmony_ci if (value) 94262306a36Sopenharmony_ci MACIO_OUT8(KL_GPIO_SOUND_POWER, 94362306a36Sopenharmony_ci KEYLARGO_GPIO_OUTPUT_ENABLE | 94462306a36Sopenharmony_ci KEYLARGO_GPIO_OUTOUT_DATA); 94562306a36Sopenharmony_ci else 94662306a36Sopenharmony_ci MACIO_OUT8(KL_GPIO_SOUND_POWER, 94762306a36Sopenharmony_ci KEYLARGO_GPIO_OUTPUT_ENABLE); 94862306a36Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_SOUND_POWER); 94962306a36Sopenharmony_ci UNLOCK(flags); 95062306a36Sopenharmony_ci } 95162306a36Sopenharmony_ci return 0; 95262306a36Sopenharmony_ci} 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_cistatic long 95562306a36Sopenharmony_cicore99_airport_enable(struct device_node *node, long param, long value) 95662306a36Sopenharmony_ci{ 95762306a36Sopenharmony_ci struct macio_chip* macio; 95862306a36Sopenharmony_ci unsigned long flags; 95962306a36Sopenharmony_ci int state; 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ci macio = macio_find(node, 0); 96262306a36Sopenharmony_ci if (!macio) 96362306a36Sopenharmony_ci return -ENODEV; 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci /* Hint: we allow passing of macio itself for the sake of the 96662306a36Sopenharmony_ci * sleep code 96762306a36Sopenharmony_ci */ 96862306a36Sopenharmony_ci if (node != macio->of_node && 96962306a36Sopenharmony_ci (!node->parent || node->parent != macio->of_node)) 97062306a36Sopenharmony_ci return -ENODEV; 97162306a36Sopenharmony_ci state = (macio->flags & MACIO_FLAG_AIRPORT_ON) != 0; 97262306a36Sopenharmony_ci if (value == state) 97362306a36Sopenharmony_ci return 0; 97462306a36Sopenharmony_ci if (value) { 97562306a36Sopenharmony_ci /* This code is a reproduction of OF enable-cardslot 97662306a36Sopenharmony_ci * and init-wireless methods, slightly hacked until 97762306a36Sopenharmony_ci * I got it working. 97862306a36Sopenharmony_ci */ 97962306a36Sopenharmony_ci LOCK(flags); 98062306a36Sopenharmony_ci MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 5); 98162306a36Sopenharmony_ci (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf); 98262306a36Sopenharmony_ci UNLOCK(flags); 98362306a36Sopenharmony_ci mdelay(10); 98462306a36Sopenharmony_ci LOCK(flags); 98562306a36Sopenharmony_ci MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 4); 98662306a36Sopenharmony_ci (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf); 98762306a36Sopenharmony_ci UNLOCK(flags); 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_ci mdelay(10); 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci LOCK(flags); 99262306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16); 99362306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR2); 99462306a36Sopenharmony_ci udelay(10); 99562306a36Sopenharmony_ci MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xb, 0); 99662306a36Sopenharmony_ci (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xb); 99762306a36Sopenharmony_ci udelay(10); 99862306a36Sopenharmony_ci MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xa, 0x28); 99962306a36Sopenharmony_ci (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xa); 100062306a36Sopenharmony_ci udelay(10); 100162306a36Sopenharmony_ci MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xd, 0x28); 100262306a36Sopenharmony_ci (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xd); 100362306a36Sopenharmony_ci udelay(10); 100462306a36Sopenharmony_ci MACIO_OUT8(KEYLARGO_GPIO_0+0xd, 0x28); 100562306a36Sopenharmony_ci (void)MACIO_IN8(KEYLARGO_GPIO_0+0xd); 100662306a36Sopenharmony_ci udelay(10); 100762306a36Sopenharmony_ci MACIO_OUT8(KEYLARGO_GPIO_0+0xe, 0x28); 100862306a36Sopenharmony_ci (void)MACIO_IN8(KEYLARGO_GPIO_0+0xe); 100962306a36Sopenharmony_ci UNLOCK(flags); 101062306a36Sopenharmony_ci udelay(10); 101162306a36Sopenharmony_ci MACIO_OUT32(0x1c000, 0); 101262306a36Sopenharmony_ci mdelay(1); 101362306a36Sopenharmony_ci MACIO_OUT8(0x1a3e0, 0x41); 101462306a36Sopenharmony_ci (void)MACIO_IN8(0x1a3e0); 101562306a36Sopenharmony_ci udelay(10); 101662306a36Sopenharmony_ci LOCK(flags); 101762306a36Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR2, KL2_CARDSEL_16); 101862306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR2); 101962306a36Sopenharmony_ci UNLOCK(flags); 102062306a36Sopenharmony_ci mdelay(100); 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci macio->flags |= MACIO_FLAG_AIRPORT_ON; 102362306a36Sopenharmony_ci } else { 102462306a36Sopenharmony_ci LOCK(flags); 102562306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16); 102662306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR2); 102762306a36Sopenharmony_ci MACIO_OUT8(KL_GPIO_AIRPORT_0, 0); 102862306a36Sopenharmony_ci MACIO_OUT8(KL_GPIO_AIRPORT_1, 0); 102962306a36Sopenharmony_ci MACIO_OUT8(KL_GPIO_AIRPORT_2, 0); 103062306a36Sopenharmony_ci MACIO_OUT8(KL_GPIO_AIRPORT_3, 0); 103162306a36Sopenharmony_ci MACIO_OUT8(KL_GPIO_AIRPORT_4, 0); 103262306a36Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_AIRPORT_4); 103362306a36Sopenharmony_ci UNLOCK(flags); 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci macio->flags &= ~MACIO_FLAG_AIRPORT_ON; 103662306a36Sopenharmony_ci } 103762306a36Sopenharmony_ci return 0; 103862306a36Sopenharmony_ci} 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_ci#ifdef CONFIG_SMP 104162306a36Sopenharmony_cistatic long 104262306a36Sopenharmony_cicore99_reset_cpu(struct device_node *node, long param, long value) 104362306a36Sopenharmony_ci{ 104462306a36Sopenharmony_ci unsigned int reset_io = 0; 104562306a36Sopenharmony_ci unsigned long flags; 104662306a36Sopenharmony_ci struct macio_chip *macio; 104762306a36Sopenharmony_ci struct device_node *np; 104862306a36Sopenharmony_ci const int dflt_reset_lines[] = { KL_GPIO_RESET_CPU0, 104962306a36Sopenharmony_ci KL_GPIO_RESET_CPU1, 105062306a36Sopenharmony_ci KL_GPIO_RESET_CPU2, 105162306a36Sopenharmony_ci KL_GPIO_RESET_CPU3 }; 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci macio = &macio_chips[0]; 105462306a36Sopenharmony_ci if (macio->type != macio_keylargo) 105562306a36Sopenharmony_ci return -ENODEV; 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ci for_each_of_cpu_node(np) { 105862306a36Sopenharmony_ci const u32 *rst = of_get_property(np, "soft-reset", NULL); 105962306a36Sopenharmony_ci if (!rst) 106062306a36Sopenharmony_ci continue; 106162306a36Sopenharmony_ci if (param == of_get_cpu_hwid(np, 0)) { 106262306a36Sopenharmony_ci of_node_put(np); 106362306a36Sopenharmony_ci reset_io = *rst; 106462306a36Sopenharmony_ci break; 106562306a36Sopenharmony_ci } 106662306a36Sopenharmony_ci } 106762306a36Sopenharmony_ci if (np == NULL || reset_io == 0) 106862306a36Sopenharmony_ci reset_io = dflt_reset_lines[param]; 106962306a36Sopenharmony_ci 107062306a36Sopenharmony_ci LOCK(flags); 107162306a36Sopenharmony_ci MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE); 107262306a36Sopenharmony_ci (void)MACIO_IN8(reset_io); 107362306a36Sopenharmony_ci udelay(1); 107462306a36Sopenharmony_ci MACIO_OUT8(reset_io, 0); 107562306a36Sopenharmony_ci (void)MACIO_IN8(reset_io); 107662306a36Sopenharmony_ci UNLOCK(flags); 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci return 0; 107962306a36Sopenharmony_ci} 108062306a36Sopenharmony_ci#endif /* CONFIG_SMP */ 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_cistatic long 108362306a36Sopenharmony_cicore99_usb_enable(struct device_node *node, long param, long value) 108462306a36Sopenharmony_ci{ 108562306a36Sopenharmony_ci struct macio_chip *macio; 108662306a36Sopenharmony_ci unsigned long flags; 108762306a36Sopenharmony_ci const char *prop; 108862306a36Sopenharmony_ci int number; 108962306a36Sopenharmony_ci u32 reg; 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_ci macio = &macio_chips[0]; 109262306a36Sopenharmony_ci if (macio->type != macio_keylargo && macio->type != macio_pangea && 109362306a36Sopenharmony_ci macio->type != macio_intrepid) 109462306a36Sopenharmony_ci return -ENODEV; 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_ci prop = of_get_property(node, "AAPL,clock-id", NULL); 109762306a36Sopenharmony_ci if (!prop) 109862306a36Sopenharmony_ci return -ENODEV; 109962306a36Sopenharmony_ci if (strncmp(prop, "usb0u048", 8) == 0) 110062306a36Sopenharmony_ci number = 0; 110162306a36Sopenharmony_ci else if (strncmp(prop, "usb1u148", 8) == 0) 110262306a36Sopenharmony_ci number = 2; 110362306a36Sopenharmony_ci else if (strncmp(prop, "usb2u248", 8) == 0) 110462306a36Sopenharmony_ci number = 4; 110562306a36Sopenharmony_ci else 110662306a36Sopenharmony_ci return -ENODEV; 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci /* Sorry for the brute-force locking, but this is only used during 110962306a36Sopenharmony_ci * sleep and the timing seem to be critical 111062306a36Sopenharmony_ci */ 111162306a36Sopenharmony_ci LOCK(flags); 111262306a36Sopenharmony_ci if (value) { 111362306a36Sopenharmony_ci /* Turn ON */ 111462306a36Sopenharmony_ci if (number == 0) { 111562306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1)); 111662306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); 111762306a36Sopenharmony_ci UNLOCK(flags); 111862306a36Sopenharmony_ci mdelay(1); 111962306a36Sopenharmony_ci LOCK(flags); 112062306a36Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE); 112162306a36Sopenharmony_ci } else if (number == 2) { 112262306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1)); 112362306a36Sopenharmony_ci UNLOCK(flags); 112462306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); 112562306a36Sopenharmony_ci mdelay(1); 112662306a36Sopenharmony_ci LOCK(flags); 112762306a36Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE); 112862306a36Sopenharmony_ci } else if (number == 4) { 112962306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1)); 113062306a36Sopenharmony_ci UNLOCK(flags); 113162306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR1); 113262306a36Sopenharmony_ci mdelay(1); 113362306a36Sopenharmony_ci LOCK(flags); 113462306a36Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR1, KL1_USB2_CELL_ENABLE); 113562306a36Sopenharmony_ci } 113662306a36Sopenharmony_ci if (number < 4) { 113762306a36Sopenharmony_ci reg = MACIO_IN32(KEYLARGO_FCR4); 113862306a36Sopenharmony_ci reg &= ~(KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) | 113962306a36Sopenharmony_ci KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number)); 114062306a36Sopenharmony_ci reg &= ~(KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) | 114162306a36Sopenharmony_ci KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1)); 114262306a36Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR4, reg); 114362306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR4); 114462306a36Sopenharmony_ci udelay(10); 114562306a36Sopenharmony_ci } else { 114662306a36Sopenharmony_ci reg = MACIO_IN32(KEYLARGO_FCR3); 114762306a36Sopenharmony_ci reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) | 114862306a36Sopenharmony_ci KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0)); 114962306a36Sopenharmony_ci reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) | 115062306a36Sopenharmony_ci KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1)); 115162306a36Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR3, reg); 115262306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR3); 115362306a36Sopenharmony_ci udelay(10); 115462306a36Sopenharmony_ci } 115562306a36Sopenharmony_ci if (macio->type == macio_intrepid) { 115662306a36Sopenharmony_ci /* wait for clock stopped bits to clear */ 115762306a36Sopenharmony_ci u32 test0 = 0, test1 = 0; 115862306a36Sopenharmony_ci u32 status0, status1; 115962306a36Sopenharmony_ci int timeout = 1000; 116062306a36Sopenharmony_ci 116162306a36Sopenharmony_ci UNLOCK(flags); 116262306a36Sopenharmony_ci switch (number) { 116362306a36Sopenharmony_ci case 0: 116462306a36Sopenharmony_ci test0 = UNI_N_CLOCK_STOPPED_USB0; 116562306a36Sopenharmony_ci test1 = UNI_N_CLOCK_STOPPED_USB0PCI; 116662306a36Sopenharmony_ci break; 116762306a36Sopenharmony_ci case 2: 116862306a36Sopenharmony_ci test0 = UNI_N_CLOCK_STOPPED_USB1; 116962306a36Sopenharmony_ci test1 = UNI_N_CLOCK_STOPPED_USB1PCI; 117062306a36Sopenharmony_ci break; 117162306a36Sopenharmony_ci case 4: 117262306a36Sopenharmony_ci test0 = UNI_N_CLOCK_STOPPED_USB2; 117362306a36Sopenharmony_ci test1 = UNI_N_CLOCK_STOPPED_USB2PCI; 117462306a36Sopenharmony_ci break; 117562306a36Sopenharmony_ci } 117662306a36Sopenharmony_ci do { 117762306a36Sopenharmony_ci if (--timeout <= 0) { 117862306a36Sopenharmony_ci printk(KERN_ERR "core99_usb_enable: " 117962306a36Sopenharmony_ci "Timeout waiting for clocks\n"); 118062306a36Sopenharmony_ci break; 118162306a36Sopenharmony_ci } 118262306a36Sopenharmony_ci mdelay(1); 118362306a36Sopenharmony_ci status0 = UN_IN(UNI_N_CLOCK_STOP_STATUS0); 118462306a36Sopenharmony_ci status1 = UN_IN(UNI_N_CLOCK_STOP_STATUS1); 118562306a36Sopenharmony_ci } while ((status0 & test0) | (status1 & test1)); 118662306a36Sopenharmony_ci LOCK(flags); 118762306a36Sopenharmony_ci } 118862306a36Sopenharmony_ci } else { 118962306a36Sopenharmony_ci /* Turn OFF */ 119062306a36Sopenharmony_ci if (number < 4) { 119162306a36Sopenharmony_ci reg = MACIO_IN32(KEYLARGO_FCR4); 119262306a36Sopenharmony_ci reg |= KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) | 119362306a36Sopenharmony_ci KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number); 119462306a36Sopenharmony_ci reg |= KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) | 119562306a36Sopenharmony_ci KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1); 119662306a36Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR4, reg); 119762306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR4); 119862306a36Sopenharmony_ci udelay(1); 119962306a36Sopenharmony_ci } else { 120062306a36Sopenharmony_ci reg = MACIO_IN32(KEYLARGO_FCR3); 120162306a36Sopenharmony_ci reg |= KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) | 120262306a36Sopenharmony_ci KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0); 120362306a36Sopenharmony_ci reg |= KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) | 120462306a36Sopenharmony_ci KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1); 120562306a36Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR3, reg); 120662306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR3); 120762306a36Sopenharmony_ci udelay(1); 120862306a36Sopenharmony_ci } 120962306a36Sopenharmony_ci if (number == 0) { 121062306a36Sopenharmony_ci if (macio->type != macio_intrepid) 121162306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE); 121262306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); 121362306a36Sopenharmony_ci udelay(1); 121462306a36Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1)); 121562306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); 121662306a36Sopenharmony_ci } else if (number == 2) { 121762306a36Sopenharmony_ci if (macio->type != macio_intrepid) 121862306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE); 121962306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); 122062306a36Sopenharmony_ci udelay(1); 122162306a36Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1)); 122262306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); 122362306a36Sopenharmony_ci } else if (number == 4) { 122462306a36Sopenharmony_ci udelay(1); 122562306a36Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1)); 122662306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR1); 122762306a36Sopenharmony_ci } 122862306a36Sopenharmony_ci udelay(1); 122962306a36Sopenharmony_ci } 123062306a36Sopenharmony_ci UNLOCK(flags); 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_ci return 0; 123362306a36Sopenharmony_ci} 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_cistatic long 123662306a36Sopenharmony_cicore99_firewire_enable(struct device_node *node, long param, long value) 123762306a36Sopenharmony_ci{ 123862306a36Sopenharmony_ci unsigned long flags; 123962306a36Sopenharmony_ci struct macio_chip *macio; 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci macio = &macio_chips[0]; 124262306a36Sopenharmony_ci if (macio->type != macio_keylargo && macio->type != macio_pangea && 124362306a36Sopenharmony_ci macio->type != macio_intrepid) 124462306a36Sopenharmony_ci return -ENODEV; 124562306a36Sopenharmony_ci if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED)) 124662306a36Sopenharmony_ci return -ENODEV; 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci LOCK(flags); 124962306a36Sopenharmony_ci if (value) { 125062306a36Sopenharmony_ci UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW); 125162306a36Sopenharmony_ci (void)UN_IN(UNI_N_CLOCK_CNTL); 125262306a36Sopenharmony_ci } else { 125362306a36Sopenharmony_ci UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW); 125462306a36Sopenharmony_ci (void)UN_IN(UNI_N_CLOCK_CNTL); 125562306a36Sopenharmony_ci } 125662306a36Sopenharmony_ci UNLOCK(flags); 125762306a36Sopenharmony_ci mdelay(1); 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_ci return 0; 126062306a36Sopenharmony_ci} 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_cistatic long 126362306a36Sopenharmony_cicore99_firewire_cable_power(struct device_node *node, long param, long value) 126462306a36Sopenharmony_ci{ 126562306a36Sopenharmony_ci unsigned long flags; 126662306a36Sopenharmony_ci struct macio_chip *macio; 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci /* Trick: we allow NULL node */ 126962306a36Sopenharmony_ci if ((pmac_mb.board_flags & PMAC_MB_HAS_FW_POWER) == 0) 127062306a36Sopenharmony_ci return -ENODEV; 127162306a36Sopenharmony_ci macio = &macio_chips[0]; 127262306a36Sopenharmony_ci if (macio->type != macio_keylargo && macio->type != macio_pangea && 127362306a36Sopenharmony_ci macio->type != macio_intrepid) 127462306a36Sopenharmony_ci return -ENODEV; 127562306a36Sopenharmony_ci if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED)) 127662306a36Sopenharmony_ci return -ENODEV; 127762306a36Sopenharmony_ci 127862306a36Sopenharmony_ci LOCK(flags); 127962306a36Sopenharmony_ci if (value) { 128062306a36Sopenharmony_ci MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 0); 128162306a36Sopenharmony_ci MACIO_IN8(KL_GPIO_FW_CABLE_POWER); 128262306a36Sopenharmony_ci udelay(10); 128362306a36Sopenharmony_ci } else { 128462306a36Sopenharmony_ci MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 4); 128562306a36Sopenharmony_ci MACIO_IN8(KL_GPIO_FW_CABLE_POWER); udelay(10); 128662306a36Sopenharmony_ci } 128762306a36Sopenharmony_ci UNLOCK(flags); 128862306a36Sopenharmony_ci mdelay(1); 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_ci return 0; 129162306a36Sopenharmony_ci} 129262306a36Sopenharmony_ci 129362306a36Sopenharmony_cistatic long 129462306a36Sopenharmony_ciintrepid_aack_delay_enable(struct device_node *node, long param, long value) 129562306a36Sopenharmony_ci{ 129662306a36Sopenharmony_ci unsigned long flags; 129762306a36Sopenharmony_ci 129862306a36Sopenharmony_ci if (uninorth_rev < 0xd2) 129962306a36Sopenharmony_ci return -ENODEV; 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci LOCK(flags); 130262306a36Sopenharmony_ci if (param) 130362306a36Sopenharmony_ci UN_BIS(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE); 130462306a36Sopenharmony_ci else 130562306a36Sopenharmony_ci UN_BIC(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE); 130662306a36Sopenharmony_ci UNLOCK(flags); 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci return 0; 130962306a36Sopenharmony_ci} 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci#endif /* CONFIG_PPC64 */ 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_cistatic long 131562306a36Sopenharmony_cicore99_read_gpio(struct device_node *node, long param, long value) 131662306a36Sopenharmony_ci{ 131762306a36Sopenharmony_ci struct macio_chip *macio = &macio_chips[0]; 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci return MACIO_IN8(param); 132062306a36Sopenharmony_ci} 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci 132362306a36Sopenharmony_cistatic long 132462306a36Sopenharmony_cicore99_write_gpio(struct device_node *node, long param, long value) 132562306a36Sopenharmony_ci{ 132662306a36Sopenharmony_ci struct macio_chip *macio = &macio_chips[0]; 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci MACIO_OUT8(param, (u8)(value & 0xff)); 132962306a36Sopenharmony_ci return 0; 133062306a36Sopenharmony_ci} 133162306a36Sopenharmony_ci 133262306a36Sopenharmony_ci#ifdef CONFIG_PPC64 133362306a36Sopenharmony_cistatic long g5_gmac_enable(struct device_node *node, long param, long value) 133462306a36Sopenharmony_ci{ 133562306a36Sopenharmony_ci struct macio_chip *macio = &macio_chips[0]; 133662306a36Sopenharmony_ci unsigned long flags; 133762306a36Sopenharmony_ci 133862306a36Sopenharmony_ci if (node == NULL) 133962306a36Sopenharmony_ci return -ENODEV; 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci LOCK(flags); 134262306a36Sopenharmony_ci if (value) { 134362306a36Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE); 134462306a36Sopenharmony_ci mb(); 134562306a36Sopenharmony_ci k2_skiplist[0] = NULL; 134662306a36Sopenharmony_ci } else { 134762306a36Sopenharmony_ci k2_skiplist[0] = node; 134862306a36Sopenharmony_ci mb(); 134962306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE); 135062306a36Sopenharmony_ci } 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_ci UNLOCK(flags); 135362306a36Sopenharmony_ci mdelay(1); 135462306a36Sopenharmony_ci 135562306a36Sopenharmony_ci return 0; 135662306a36Sopenharmony_ci} 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_cistatic long g5_fw_enable(struct device_node *node, long param, long value) 135962306a36Sopenharmony_ci{ 136062306a36Sopenharmony_ci struct macio_chip *macio = &macio_chips[0]; 136162306a36Sopenharmony_ci unsigned long flags; 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_ci if (node == NULL) 136462306a36Sopenharmony_ci return -ENODEV; 136562306a36Sopenharmony_ci 136662306a36Sopenharmony_ci LOCK(flags); 136762306a36Sopenharmony_ci if (value) { 136862306a36Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE); 136962306a36Sopenharmony_ci mb(); 137062306a36Sopenharmony_ci k2_skiplist[1] = NULL; 137162306a36Sopenharmony_ci } else { 137262306a36Sopenharmony_ci k2_skiplist[1] = node; 137362306a36Sopenharmony_ci mb(); 137462306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE); 137562306a36Sopenharmony_ci } 137662306a36Sopenharmony_ci 137762306a36Sopenharmony_ci UNLOCK(flags); 137862306a36Sopenharmony_ci mdelay(1); 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_ci return 0; 138162306a36Sopenharmony_ci} 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_cistatic long g5_mpic_enable(struct device_node *node, long param, long value) 138462306a36Sopenharmony_ci{ 138562306a36Sopenharmony_ci unsigned long flags; 138662306a36Sopenharmony_ci struct device_node *parent = of_get_parent(node); 138762306a36Sopenharmony_ci int is_u3; 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci if (parent == NULL) 139062306a36Sopenharmony_ci return 0; 139162306a36Sopenharmony_ci is_u3 = of_node_name_eq(parent, "u3") || of_node_name_eq(parent, "u4"); 139262306a36Sopenharmony_ci of_node_put(parent); 139362306a36Sopenharmony_ci if (!is_u3) 139462306a36Sopenharmony_ci return 0; 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_ci LOCK(flags); 139762306a36Sopenharmony_ci UN_BIS(U3_TOGGLE_REG, U3_MPIC_RESET | U3_MPIC_OUTPUT_ENABLE); 139862306a36Sopenharmony_ci UNLOCK(flags); 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_ci return 0; 140162306a36Sopenharmony_ci} 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_cistatic long g5_eth_phy_reset(struct device_node *node, long param, long value) 140462306a36Sopenharmony_ci{ 140562306a36Sopenharmony_ci struct macio_chip *macio = &macio_chips[0]; 140662306a36Sopenharmony_ci struct device_node *phy; 140762306a36Sopenharmony_ci int need_reset; 140862306a36Sopenharmony_ci 140962306a36Sopenharmony_ci /* 141062306a36Sopenharmony_ci * We must not reset the combo PHYs, only the BCM5221 found in 141162306a36Sopenharmony_ci * the iMac G5. 141262306a36Sopenharmony_ci */ 141362306a36Sopenharmony_ci phy = of_get_next_child(node, NULL); 141462306a36Sopenharmony_ci if (!phy) 141562306a36Sopenharmony_ci return -ENODEV; 141662306a36Sopenharmony_ci need_reset = of_device_is_compatible(phy, "B5221"); 141762306a36Sopenharmony_ci of_node_put(phy); 141862306a36Sopenharmony_ci if (!need_reset) 141962306a36Sopenharmony_ci return 0; 142062306a36Sopenharmony_ci 142162306a36Sopenharmony_ci /* PHY reset is GPIO 29, not in device-tree unfortunately */ 142262306a36Sopenharmony_ci MACIO_OUT8(K2_GPIO_EXTINT_0 + 29, 142362306a36Sopenharmony_ci KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); 142462306a36Sopenharmony_ci /* Thankfully, this is now always called at a time when we can 142562306a36Sopenharmony_ci * schedule by sungem. 142662306a36Sopenharmony_ci */ 142762306a36Sopenharmony_ci msleep(10); 142862306a36Sopenharmony_ci MACIO_OUT8(K2_GPIO_EXTINT_0 + 29, 0); 142962306a36Sopenharmony_ci 143062306a36Sopenharmony_ci return 0; 143162306a36Sopenharmony_ci} 143262306a36Sopenharmony_ci 143362306a36Sopenharmony_cistatic long g5_i2s_enable(struct device_node *node, long param, long value) 143462306a36Sopenharmony_ci{ 143562306a36Sopenharmony_ci /* Very crude implementation for now */ 143662306a36Sopenharmony_ci struct macio_chip *macio = &macio_chips[0]; 143762306a36Sopenharmony_ci unsigned long flags; 143862306a36Sopenharmony_ci int cell; 143962306a36Sopenharmony_ci u32 fcrs[3][3] = { 144062306a36Sopenharmony_ci { 0, 144162306a36Sopenharmony_ci K2_FCR1_I2S0_CELL_ENABLE | 144262306a36Sopenharmony_ci K2_FCR1_I2S0_CLK_ENABLE_BIT | K2_FCR1_I2S0_ENABLE, 144362306a36Sopenharmony_ci KL3_I2S0_CLK18_ENABLE 144462306a36Sopenharmony_ci }, 144562306a36Sopenharmony_ci { KL0_SCC_A_INTF_ENABLE, 144662306a36Sopenharmony_ci K2_FCR1_I2S1_CELL_ENABLE | 144762306a36Sopenharmony_ci K2_FCR1_I2S1_CLK_ENABLE_BIT | K2_FCR1_I2S1_ENABLE, 144862306a36Sopenharmony_ci KL3_I2S1_CLK18_ENABLE 144962306a36Sopenharmony_ci }, 145062306a36Sopenharmony_ci { KL0_SCC_B_INTF_ENABLE, 145162306a36Sopenharmony_ci SH_FCR1_I2S2_CELL_ENABLE | 145262306a36Sopenharmony_ci SH_FCR1_I2S2_CLK_ENABLE_BIT | SH_FCR1_I2S2_ENABLE, 145362306a36Sopenharmony_ci SH_FCR3_I2S2_CLK18_ENABLE 145462306a36Sopenharmony_ci }, 145562306a36Sopenharmony_ci }; 145662306a36Sopenharmony_ci 145762306a36Sopenharmony_ci if (macio->type != macio_keylargo2 && macio->type != macio_shasta) 145862306a36Sopenharmony_ci return -ENODEV; 145962306a36Sopenharmony_ci if (strncmp(node->name, "i2s-", 4)) 146062306a36Sopenharmony_ci return -ENODEV; 146162306a36Sopenharmony_ci cell = node->name[4] - 'a'; 146262306a36Sopenharmony_ci switch(cell) { 146362306a36Sopenharmony_ci case 0: 146462306a36Sopenharmony_ci case 1: 146562306a36Sopenharmony_ci break; 146662306a36Sopenharmony_ci case 2: 146762306a36Sopenharmony_ci if (macio->type == macio_shasta) 146862306a36Sopenharmony_ci break; 146962306a36Sopenharmony_ci fallthrough; 147062306a36Sopenharmony_ci default: 147162306a36Sopenharmony_ci return -ENODEV; 147262306a36Sopenharmony_ci } 147362306a36Sopenharmony_ci 147462306a36Sopenharmony_ci LOCK(flags); 147562306a36Sopenharmony_ci if (value) { 147662306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR0, fcrs[cell][0]); 147762306a36Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR1, fcrs[cell][1]); 147862306a36Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR3, fcrs[cell][2]); 147962306a36Sopenharmony_ci } else { 148062306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR3, fcrs[cell][2]); 148162306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR1, fcrs[cell][1]); 148262306a36Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR0, fcrs[cell][0]); 148362306a36Sopenharmony_ci } 148462306a36Sopenharmony_ci udelay(10); 148562306a36Sopenharmony_ci UNLOCK(flags); 148662306a36Sopenharmony_ci 148762306a36Sopenharmony_ci return 0; 148862306a36Sopenharmony_ci} 148962306a36Sopenharmony_ci 149062306a36Sopenharmony_ci 149162306a36Sopenharmony_ci#ifdef CONFIG_SMP 149262306a36Sopenharmony_cistatic long g5_reset_cpu(struct device_node *node, long param, long value) 149362306a36Sopenharmony_ci{ 149462306a36Sopenharmony_ci unsigned int reset_io = 0; 149562306a36Sopenharmony_ci unsigned long flags; 149662306a36Sopenharmony_ci struct macio_chip *macio; 149762306a36Sopenharmony_ci struct device_node *np; 149862306a36Sopenharmony_ci 149962306a36Sopenharmony_ci macio = &macio_chips[0]; 150062306a36Sopenharmony_ci if (macio->type != macio_keylargo2 && macio->type != macio_shasta) 150162306a36Sopenharmony_ci return -ENODEV; 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_ci for_each_of_cpu_node(np) { 150462306a36Sopenharmony_ci const u32 *rst = of_get_property(np, "soft-reset", NULL); 150562306a36Sopenharmony_ci if (!rst) 150662306a36Sopenharmony_ci continue; 150762306a36Sopenharmony_ci if (param == of_get_cpu_hwid(np, 0)) { 150862306a36Sopenharmony_ci of_node_put(np); 150962306a36Sopenharmony_ci reset_io = *rst; 151062306a36Sopenharmony_ci break; 151162306a36Sopenharmony_ci } 151262306a36Sopenharmony_ci } 151362306a36Sopenharmony_ci if (np == NULL || reset_io == 0) 151462306a36Sopenharmony_ci return -ENODEV; 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ci LOCK(flags); 151762306a36Sopenharmony_ci MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE); 151862306a36Sopenharmony_ci (void)MACIO_IN8(reset_io); 151962306a36Sopenharmony_ci udelay(1); 152062306a36Sopenharmony_ci MACIO_OUT8(reset_io, 0); 152162306a36Sopenharmony_ci (void)MACIO_IN8(reset_io); 152262306a36Sopenharmony_ci UNLOCK(flags); 152362306a36Sopenharmony_ci 152462306a36Sopenharmony_ci return 0; 152562306a36Sopenharmony_ci} 152662306a36Sopenharmony_ci#endif /* CONFIG_SMP */ 152762306a36Sopenharmony_ci 152862306a36Sopenharmony_ci/* 152962306a36Sopenharmony_ci * This can be called from pmac_smp so isn't static 153062306a36Sopenharmony_ci * 153162306a36Sopenharmony_ci * This takes the second CPU off the bus on dual CPU machines 153262306a36Sopenharmony_ci * running UP 153362306a36Sopenharmony_ci */ 153462306a36Sopenharmony_civoid __init g5_phy_disable_cpu1(void) 153562306a36Sopenharmony_ci{ 153662306a36Sopenharmony_ci if (uninorth_maj == 3) 153762306a36Sopenharmony_ci UN_OUT(U3_API_PHY_CONFIG_1, 0); 153862306a36Sopenharmony_ci} 153962306a36Sopenharmony_ci#endif /* CONFIG_PPC64 */ 154062306a36Sopenharmony_ci 154162306a36Sopenharmony_ci#ifndef CONFIG_PPC64 154262306a36Sopenharmony_ci 154362306a36Sopenharmony_ci 154462306a36Sopenharmony_ci#ifdef CONFIG_PM 154562306a36Sopenharmony_cistatic u32 save_gpio_levels[2]; 154662306a36Sopenharmony_cistatic u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT]; 154762306a36Sopenharmony_cistatic u8 save_gpio_normal[KEYLARGO_GPIO_CNT]; 154862306a36Sopenharmony_cistatic u32 save_unin_clock_ctl; 154962306a36Sopenharmony_ci 155062306a36Sopenharmony_cistatic void keylargo_shutdown(struct macio_chip *macio, int sleep_mode) 155162306a36Sopenharmony_ci{ 155262306a36Sopenharmony_ci u32 temp; 155362306a36Sopenharmony_ci 155462306a36Sopenharmony_ci if (sleep_mode) { 155562306a36Sopenharmony_ci mdelay(1); 155662306a36Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND); 155762306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); 155862306a36Sopenharmony_ci mdelay(1); 155962306a36Sopenharmony_ci } 156062306a36Sopenharmony_ci 156162306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | 156262306a36Sopenharmony_ci KL0_SCC_CELL_ENABLE | 156362306a36Sopenharmony_ci KL0_IRDA_ENABLE | KL0_IRDA_CLK32_ENABLE | 156462306a36Sopenharmony_ci KL0_IRDA_CLK19_ENABLE); 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK); 156762306a36Sopenharmony_ci MACIO_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_IDE_ENABLE); 156862306a36Sopenharmony_ci 156962306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR1, 157062306a36Sopenharmony_ci KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT | 157162306a36Sopenharmony_ci KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE | 157262306a36Sopenharmony_ci KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT | 157362306a36Sopenharmony_ci KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE | 157462306a36Sopenharmony_ci KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE | 157562306a36Sopenharmony_ci KL1_EIDE0_ENABLE | KL1_EIDE0_RESET_N | 157662306a36Sopenharmony_ci KL1_EIDE1_ENABLE | KL1_EIDE1_RESET_N | 157762306a36Sopenharmony_ci KL1_UIDE_ENABLE); 157862306a36Sopenharmony_ci 157962306a36Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); 158062306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR2, KL2_IOBUS_ENABLE); 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_ci temp = MACIO_IN32(KEYLARGO_FCR3); 158362306a36Sopenharmony_ci if (macio->rev >= 2) { 158462306a36Sopenharmony_ci temp |= KL3_SHUTDOWN_PLL2X; 158562306a36Sopenharmony_ci if (sleep_mode) 158662306a36Sopenharmony_ci temp |= KL3_SHUTDOWN_PLL_TOTAL; 158762306a36Sopenharmony_ci } 158862306a36Sopenharmony_ci 158962306a36Sopenharmony_ci temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 | 159062306a36Sopenharmony_ci KL3_SHUTDOWN_PLLKW35; 159162306a36Sopenharmony_ci if (sleep_mode) 159262306a36Sopenharmony_ci temp |= KL3_SHUTDOWN_PLLKW12; 159362306a36Sopenharmony_ci temp &= ~(KL3_CLK66_ENABLE | KL3_CLK49_ENABLE | KL3_CLK45_ENABLE 159462306a36Sopenharmony_ci | KL3_CLK31_ENABLE | KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE); 159562306a36Sopenharmony_ci if (sleep_mode) 159662306a36Sopenharmony_ci temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE); 159762306a36Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR3, temp); 159862306a36Sopenharmony_ci 159962306a36Sopenharmony_ci /* Flush posted writes & wait a bit */ 160062306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1); 160162306a36Sopenharmony_ci} 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_cistatic void pangea_shutdown(struct macio_chip *macio, int sleep_mode) 160462306a36Sopenharmony_ci{ 160562306a36Sopenharmony_ci u32 temp; 160662306a36Sopenharmony_ci 160762306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | 160862306a36Sopenharmony_ci KL0_SCC_CELL_ENABLE | 160962306a36Sopenharmony_ci KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE); 161062306a36Sopenharmony_ci 161162306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR1, 161262306a36Sopenharmony_ci KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT | 161362306a36Sopenharmony_ci KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE | 161462306a36Sopenharmony_ci KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT | 161562306a36Sopenharmony_ci KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE | 161662306a36Sopenharmony_ci KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE | 161762306a36Sopenharmony_ci KL1_UIDE_ENABLE); 161862306a36Sopenharmony_ci if (pmac_mb.board_flags & PMAC_MB_MOBILE) 161962306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N); 162062306a36Sopenharmony_ci 162162306a36Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); 162262306a36Sopenharmony_ci 162362306a36Sopenharmony_ci temp = MACIO_IN32(KEYLARGO_FCR3); 162462306a36Sopenharmony_ci temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 | 162562306a36Sopenharmony_ci KL3_SHUTDOWN_PLLKW35; 162662306a36Sopenharmony_ci temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | KL3_CLK31_ENABLE 162762306a36Sopenharmony_ci | KL3_I2S0_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE); 162862306a36Sopenharmony_ci if (sleep_mode) 162962306a36Sopenharmony_ci temp &= ~(KL3_VIA_CLK16_ENABLE | KL3_TIMER_CLK18_ENABLE); 163062306a36Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR3, temp); 163162306a36Sopenharmony_ci 163262306a36Sopenharmony_ci /* Flush posted writes & wait a bit */ 163362306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1); 163462306a36Sopenharmony_ci} 163562306a36Sopenharmony_ci 163662306a36Sopenharmony_cistatic void intrepid_shutdown(struct macio_chip *macio, int sleep_mode) 163762306a36Sopenharmony_ci{ 163862306a36Sopenharmony_ci u32 temp; 163962306a36Sopenharmony_ci 164062306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | 164162306a36Sopenharmony_ci KL0_SCC_CELL_ENABLE); 164262306a36Sopenharmony_ci 164362306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR1, 164462306a36Sopenharmony_ci KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT | 164562306a36Sopenharmony_ci KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE | 164662306a36Sopenharmony_ci KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE | 164762306a36Sopenharmony_ci KL1_EIDE0_ENABLE); 164862306a36Sopenharmony_ci if (pmac_mb.board_flags & PMAC_MB_MOBILE) 164962306a36Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N); 165062306a36Sopenharmony_ci 165162306a36Sopenharmony_ci temp = MACIO_IN32(KEYLARGO_FCR3); 165262306a36Sopenharmony_ci temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | 165362306a36Sopenharmony_ci KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE); 165462306a36Sopenharmony_ci if (sleep_mode) 165562306a36Sopenharmony_ci temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_IT_VIA_CLK32_ENABLE); 165662306a36Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR3, temp); 165762306a36Sopenharmony_ci 165862306a36Sopenharmony_ci /* Flush posted writes & wait a bit */ 165962306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); 166062306a36Sopenharmony_ci mdelay(10); 166162306a36Sopenharmony_ci} 166262306a36Sopenharmony_ci 166362306a36Sopenharmony_ci 166462306a36Sopenharmony_cistatic int 166562306a36Sopenharmony_cicore99_sleep(void) 166662306a36Sopenharmony_ci{ 166762306a36Sopenharmony_ci struct macio_chip *macio; 166862306a36Sopenharmony_ci int i; 166962306a36Sopenharmony_ci 167062306a36Sopenharmony_ci macio = &macio_chips[0]; 167162306a36Sopenharmony_ci if (macio->type != macio_keylargo && macio->type != macio_pangea && 167262306a36Sopenharmony_ci macio->type != macio_intrepid) 167362306a36Sopenharmony_ci return -ENODEV; 167462306a36Sopenharmony_ci 167562306a36Sopenharmony_ci /* We power off the wireless slot in case it was not done 167662306a36Sopenharmony_ci * by the driver. We don't power it on automatically however 167762306a36Sopenharmony_ci */ 167862306a36Sopenharmony_ci if (macio->flags & MACIO_FLAG_AIRPORT_ON) 167962306a36Sopenharmony_ci core99_airport_enable(macio->of_node, 0, 0); 168062306a36Sopenharmony_ci 168162306a36Sopenharmony_ci /* We power off the FW cable. Should be done by the driver... */ 168262306a36Sopenharmony_ci if (macio->flags & MACIO_FLAG_FW_SUPPORTED) { 168362306a36Sopenharmony_ci core99_firewire_enable(NULL, 0, 0); 168462306a36Sopenharmony_ci core99_firewire_cable_power(NULL, 0, 0); 168562306a36Sopenharmony_ci } 168662306a36Sopenharmony_ci 168762306a36Sopenharmony_ci /* We make sure int. modem is off (in case driver lost it) */ 168862306a36Sopenharmony_ci if (macio->type == macio_keylargo) 168962306a36Sopenharmony_ci core99_modem_enable(macio->of_node, 0, 0); 169062306a36Sopenharmony_ci else 169162306a36Sopenharmony_ci pangea_modem_enable(macio->of_node, 0, 0); 169262306a36Sopenharmony_ci 169362306a36Sopenharmony_ci /* We make sure the sound is off as well */ 169462306a36Sopenharmony_ci core99_sound_chip_enable(macio->of_node, 0, 0); 169562306a36Sopenharmony_ci 169662306a36Sopenharmony_ci /* 169762306a36Sopenharmony_ci * Save various bits of KeyLargo 169862306a36Sopenharmony_ci */ 169962306a36Sopenharmony_ci 170062306a36Sopenharmony_ci /* Save the state of the various GPIOs */ 170162306a36Sopenharmony_ci save_gpio_levels[0] = MACIO_IN32(KEYLARGO_GPIO_LEVELS0); 170262306a36Sopenharmony_ci save_gpio_levels[1] = MACIO_IN32(KEYLARGO_GPIO_LEVELS1); 170362306a36Sopenharmony_ci for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++) 170462306a36Sopenharmony_ci save_gpio_extint[i] = MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+i); 170562306a36Sopenharmony_ci for (i=0; i<KEYLARGO_GPIO_CNT; i++) 170662306a36Sopenharmony_ci save_gpio_normal[i] = MACIO_IN8(KEYLARGO_GPIO_0+i); 170762306a36Sopenharmony_ci 170862306a36Sopenharmony_ci /* Save the FCRs */ 170962306a36Sopenharmony_ci if (macio->type == macio_keylargo) 171062306a36Sopenharmony_ci save_mbcr = MACIO_IN32(KEYLARGO_MBCR); 171162306a36Sopenharmony_ci save_fcr[0] = MACIO_IN32(KEYLARGO_FCR0); 171262306a36Sopenharmony_ci save_fcr[1] = MACIO_IN32(KEYLARGO_FCR1); 171362306a36Sopenharmony_ci save_fcr[2] = MACIO_IN32(KEYLARGO_FCR2); 171462306a36Sopenharmony_ci save_fcr[3] = MACIO_IN32(KEYLARGO_FCR3); 171562306a36Sopenharmony_ci save_fcr[4] = MACIO_IN32(KEYLARGO_FCR4); 171662306a36Sopenharmony_ci if (macio->type == macio_pangea || macio->type == macio_intrepid) 171762306a36Sopenharmony_ci save_fcr[5] = MACIO_IN32(KEYLARGO_FCR5); 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_ci /* Save state & config of DBDMA channels */ 172062306a36Sopenharmony_ci dbdma_save(macio, save_dbdma); 172162306a36Sopenharmony_ci 172262306a36Sopenharmony_ci /* 172362306a36Sopenharmony_ci * Turn off as much as we can 172462306a36Sopenharmony_ci */ 172562306a36Sopenharmony_ci if (macio->type == macio_pangea) 172662306a36Sopenharmony_ci pangea_shutdown(macio, 1); 172762306a36Sopenharmony_ci else if (macio->type == macio_intrepid) 172862306a36Sopenharmony_ci intrepid_shutdown(macio, 1); 172962306a36Sopenharmony_ci else if (macio->type == macio_keylargo) 173062306a36Sopenharmony_ci keylargo_shutdown(macio, 1); 173162306a36Sopenharmony_ci 173262306a36Sopenharmony_ci /* 173362306a36Sopenharmony_ci * Put the host bridge to sleep 173462306a36Sopenharmony_ci */ 173562306a36Sopenharmony_ci 173662306a36Sopenharmony_ci save_unin_clock_ctl = UN_IN(UNI_N_CLOCK_CNTL); 173762306a36Sopenharmony_ci /* Note: do not switch GMAC off, driver does it when necessary, WOL must keep it 173862306a36Sopenharmony_ci * enabled ! 173962306a36Sopenharmony_ci */ 174062306a36Sopenharmony_ci UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl & 174162306a36Sopenharmony_ci ~(/*UNI_N_CLOCK_CNTL_GMAC|*/UNI_N_CLOCK_CNTL_FW/*|UNI_N_CLOCK_CNTL_PCI*/)); 174262306a36Sopenharmony_ci udelay(100); 174362306a36Sopenharmony_ci UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING); 174462306a36Sopenharmony_ci UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_SLEEP); 174562306a36Sopenharmony_ci mdelay(10); 174662306a36Sopenharmony_ci 174762306a36Sopenharmony_ci /* 174862306a36Sopenharmony_ci * FIXME: A bit of black magic with OpenPIC (don't ask me why) 174962306a36Sopenharmony_ci */ 175062306a36Sopenharmony_ci if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) { 175162306a36Sopenharmony_ci MACIO_BIS(0x506e0, 0x00400000); 175262306a36Sopenharmony_ci MACIO_BIS(0x506e0, 0x80000000); 175362306a36Sopenharmony_ci } 175462306a36Sopenharmony_ci return 0; 175562306a36Sopenharmony_ci} 175662306a36Sopenharmony_ci 175762306a36Sopenharmony_cistatic int 175862306a36Sopenharmony_cicore99_wake_up(void) 175962306a36Sopenharmony_ci{ 176062306a36Sopenharmony_ci struct macio_chip *macio; 176162306a36Sopenharmony_ci int i; 176262306a36Sopenharmony_ci 176362306a36Sopenharmony_ci macio = &macio_chips[0]; 176462306a36Sopenharmony_ci if (macio->type != macio_keylargo && macio->type != macio_pangea && 176562306a36Sopenharmony_ci macio->type != macio_intrepid) 176662306a36Sopenharmony_ci return -ENODEV; 176762306a36Sopenharmony_ci 176862306a36Sopenharmony_ci /* 176962306a36Sopenharmony_ci * Wakeup the host bridge 177062306a36Sopenharmony_ci */ 177162306a36Sopenharmony_ci UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL); 177262306a36Sopenharmony_ci udelay(10); 177362306a36Sopenharmony_ci UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING); 177462306a36Sopenharmony_ci udelay(10); 177562306a36Sopenharmony_ci 177662306a36Sopenharmony_ci /* 177762306a36Sopenharmony_ci * Restore KeyLargo 177862306a36Sopenharmony_ci */ 177962306a36Sopenharmony_ci 178062306a36Sopenharmony_ci if (macio->type == macio_keylargo) { 178162306a36Sopenharmony_ci MACIO_OUT32(KEYLARGO_MBCR, save_mbcr); 178262306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_MBCR); udelay(10); 178362306a36Sopenharmony_ci } 178462306a36Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR0, save_fcr[0]); 178562306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); udelay(10); 178662306a36Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR1, save_fcr[1]); 178762306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR1); udelay(10); 178862306a36Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR2, save_fcr[2]); 178962306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR2); udelay(10); 179062306a36Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR3, save_fcr[3]); 179162306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR3); udelay(10); 179262306a36Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR4, save_fcr[4]); 179362306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR4); udelay(10); 179462306a36Sopenharmony_ci if (macio->type == macio_pangea || macio->type == macio_intrepid) { 179562306a36Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR5, save_fcr[5]); 179662306a36Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR5); udelay(10); 179762306a36Sopenharmony_ci } 179862306a36Sopenharmony_ci 179962306a36Sopenharmony_ci dbdma_restore(macio, save_dbdma); 180062306a36Sopenharmony_ci 180162306a36Sopenharmony_ci MACIO_OUT32(KEYLARGO_GPIO_LEVELS0, save_gpio_levels[0]); 180262306a36Sopenharmony_ci MACIO_OUT32(KEYLARGO_GPIO_LEVELS1, save_gpio_levels[1]); 180362306a36Sopenharmony_ci for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++) 180462306a36Sopenharmony_ci MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+i, save_gpio_extint[i]); 180562306a36Sopenharmony_ci for (i=0; i<KEYLARGO_GPIO_CNT; i++) 180662306a36Sopenharmony_ci MACIO_OUT8(KEYLARGO_GPIO_0+i, save_gpio_normal[i]); 180762306a36Sopenharmony_ci 180862306a36Sopenharmony_ci /* FIXME more black magic with OpenPIC ... */ 180962306a36Sopenharmony_ci if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) { 181062306a36Sopenharmony_ci MACIO_BIC(0x506e0, 0x00400000); 181162306a36Sopenharmony_ci MACIO_BIC(0x506e0, 0x80000000); 181262306a36Sopenharmony_ci } 181362306a36Sopenharmony_ci 181462306a36Sopenharmony_ci UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl); 181562306a36Sopenharmony_ci udelay(100); 181662306a36Sopenharmony_ci 181762306a36Sopenharmony_ci return 0; 181862306a36Sopenharmony_ci} 181962306a36Sopenharmony_ci 182062306a36Sopenharmony_ci#endif /* CONFIG_PM */ 182162306a36Sopenharmony_ci 182262306a36Sopenharmony_cistatic long 182362306a36Sopenharmony_cicore99_sleep_state(struct device_node *node, long param, long value) 182462306a36Sopenharmony_ci{ 182562306a36Sopenharmony_ci /* Param == 1 means to enter the "fake sleep" mode that is 182662306a36Sopenharmony_ci * used for CPU speed switch 182762306a36Sopenharmony_ci */ 182862306a36Sopenharmony_ci if (param == 1) { 182962306a36Sopenharmony_ci if (value == 1) { 183062306a36Sopenharmony_ci UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING); 183162306a36Sopenharmony_ci UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_IDLE2); 183262306a36Sopenharmony_ci } else { 183362306a36Sopenharmony_ci UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL); 183462306a36Sopenharmony_ci udelay(10); 183562306a36Sopenharmony_ci UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING); 183662306a36Sopenharmony_ci udelay(10); 183762306a36Sopenharmony_ci } 183862306a36Sopenharmony_ci return 0; 183962306a36Sopenharmony_ci } 184062306a36Sopenharmony_ci if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0) 184162306a36Sopenharmony_ci return -EPERM; 184262306a36Sopenharmony_ci 184362306a36Sopenharmony_ci#ifdef CONFIG_PM 184462306a36Sopenharmony_ci if (value == 1) 184562306a36Sopenharmony_ci return core99_sleep(); 184662306a36Sopenharmony_ci else if (value == 0) 184762306a36Sopenharmony_ci return core99_wake_up(); 184862306a36Sopenharmony_ci 184962306a36Sopenharmony_ci#endif /* CONFIG_PM */ 185062306a36Sopenharmony_ci return 0; 185162306a36Sopenharmony_ci} 185262306a36Sopenharmony_ci 185362306a36Sopenharmony_ci#endif /* CONFIG_PPC64 */ 185462306a36Sopenharmony_ci 185562306a36Sopenharmony_cistatic long 185662306a36Sopenharmony_cigeneric_dev_can_wake(struct device_node *node, long param, long value) 185762306a36Sopenharmony_ci{ 185862306a36Sopenharmony_ci /* Todo: eventually check we are really dealing with on-board 185962306a36Sopenharmony_ci * video device ... 186062306a36Sopenharmony_ci */ 186162306a36Sopenharmony_ci 186262306a36Sopenharmony_ci if (pmac_mb.board_flags & PMAC_MB_MAY_SLEEP) 186362306a36Sopenharmony_ci pmac_mb.board_flags |= PMAC_MB_CAN_SLEEP; 186462306a36Sopenharmony_ci return 0; 186562306a36Sopenharmony_ci} 186662306a36Sopenharmony_ci 186762306a36Sopenharmony_cistatic long generic_get_mb_info(struct device_node *node, long param, long value) 186862306a36Sopenharmony_ci{ 186962306a36Sopenharmony_ci switch(param) { 187062306a36Sopenharmony_ci case PMAC_MB_INFO_MODEL: 187162306a36Sopenharmony_ci return pmac_mb.model_id; 187262306a36Sopenharmony_ci case PMAC_MB_INFO_FLAGS: 187362306a36Sopenharmony_ci return pmac_mb.board_flags; 187462306a36Sopenharmony_ci case PMAC_MB_INFO_NAME: 187562306a36Sopenharmony_ci /* hack hack hack... but should work */ 187662306a36Sopenharmony_ci *((const char **)value) = pmac_mb.model_name; 187762306a36Sopenharmony_ci return 0; 187862306a36Sopenharmony_ci } 187962306a36Sopenharmony_ci return -EINVAL; 188062306a36Sopenharmony_ci} 188162306a36Sopenharmony_ci 188262306a36Sopenharmony_ci 188362306a36Sopenharmony_ci/* 188462306a36Sopenharmony_ci * Table definitions 188562306a36Sopenharmony_ci */ 188662306a36Sopenharmony_ci 188762306a36Sopenharmony_ci/* Used on any machine 188862306a36Sopenharmony_ci */ 188962306a36Sopenharmony_cistatic struct feature_table_entry any_features[] = { 189062306a36Sopenharmony_ci { PMAC_FTR_GET_MB_INFO, generic_get_mb_info }, 189162306a36Sopenharmony_ci { PMAC_FTR_DEVICE_CAN_WAKE, generic_dev_can_wake }, 189262306a36Sopenharmony_ci { 0, NULL } 189362306a36Sopenharmony_ci}; 189462306a36Sopenharmony_ci 189562306a36Sopenharmony_ci#ifndef CONFIG_PPC64 189662306a36Sopenharmony_ci 189762306a36Sopenharmony_ci/* OHare based motherboards. Currently, we only use these on the 189862306a36Sopenharmony_ci * 2400,3400 and 3500 series powerbooks. Some older desktops seem 189962306a36Sopenharmony_ci * to have issues with turning on/off those asic cells 190062306a36Sopenharmony_ci */ 190162306a36Sopenharmony_cistatic struct feature_table_entry ohare_features[] = { 190262306a36Sopenharmony_ci { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable }, 190362306a36Sopenharmony_ci { PMAC_FTR_SWIM3_ENABLE, ohare_floppy_enable }, 190462306a36Sopenharmony_ci { PMAC_FTR_MESH_ENABLE, ohare_mesh_enable }, 190562306a36Sopenharmony_ci { PMAC_FTR_IDE_ENABLE, ohare_ide_enable}, 190662306a36Sopenharmony_ci { PMAC_FTR_IDE_RESET, ohare_ide_reset}, 190762306a36Sopenharmony_ci { PMAC_FTR_SLEEP_STATE, ohare_sleep_state }, 190862306a36Sopenharmony_ci { 0, NULL } 190962306a36Sopenharmony_ci}; 191062306a36Sopenharmony_ci 191162306a36Sopenharmony_ci/* Heathrow desktop machines (Beige G3). 191262306a36Sopenharmony_ci * Separated as some features couldn't be properly tested 191362306a36Sopenharmony_ci * and the serial port control bits appear to confuse it. 191462306a36Sopenharmony_ci */ 191562306a36Sopenharmony_cistatic struct feature_table_entry heathrow_desktop_features[] = { 191662306a36Sopenharmony_ci { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable }, 191762306a36Sopenharmony_ci { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable }, 191862306a36Sopenharmony_ci { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable }, 191962306a36Sopenharmony_ci { PMAC_FTR_IDE_RESET, heathrow_ide_reset }, 192062306a36Sopenharmony_ci { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable }, 192162306a36Sopenharmony_ci { 0, NULL } 192262306a36Sopenharmony_ci}; 192362306a36Sopenharmony_ci 192462306a36Sopenharmony_ci/* Heathrow based laptop, that is the Wallstreet and mainstreet 192562306a36Sopenharmony_ci * powerbooks. 192662306a36Sopenharmony_ci */ 192762306a36Sopenharmony_cistatic struct feature_table_entry heathrow_laptop_features[] = { 192862306a36Sopenharmony_ci { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable }, 192962306a36Sopenharmony_ci { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable }, 193062306a36Sopenharmony_ci { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable }, 193162306a36Sopenharmony_ci { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable }, 193262306a36Sopenharmony_ci { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable }, 193362306a36Sopenharmony_ci { PMAC_FTR_IDE_RESET, heathrow_ide_reset }, 193462306a36Sopenharmony_ci { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable }, 193562306a36Sopenharmony_ci { PMAC_FTR_SOUND_CHIP_ENABLE, heathrow_sound_enable }, 193662306a36Sopenharmony_ci { PMAC_FTR_SLEEP_STATE, heathrow_sleep_state }, 193762306a36Sopenharmony_ci { 0, NULL } 193862306a36Sopenharmony_ci}; 193962306a36Sopenharmony_ci 194062306a36Sopenharmony_ci/* Paddington based machines 194162306a36Sopenharmony_ci * The lombard (101) powerbook, first iMac models, B&W G3 and Yikes G4. 194262306a36Sopenharmony_ci */ 194362306a36Sopenharmony_cistatic struct feature_table_entry paddington_features[] = { 194462306a36Sopenharmony_ci { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable }, 194562306a36Sopenharmony_ci { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable }, 194662306a36Sopenharmony_ci { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable }, 194762306a36Sopenharmony_ci { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable }, 194862306a36Sopenharmony_ci { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable }, 194962306a36Sopenharmony_ci { PMAC_FTR_IDE_RESET, heathrow_ide_reset }, 195062306a36Sopenharmony_ci { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable }, 195162306a36Sopenharmony_ci { PMAC_FTR_SOUND_CHIP_ENABLE, heathrow_sound_enable }, 195262306a36Sopenharmony_ci { PMAC_FTR_SLEEP_STATE, heathrow_sleep_state }, 195362306a36Sopenharmony_ci { 0, NULL } 195462306a36Sopenharmony_ci}; 195562306a36Sopenharmony_ci 195662306a36Sopenharmony_ci/* Core99 & MacRISC 2 machines (all machines released since the 195762306a36Sopenharmony_ci * iBook (included), that is all AGP machines, except pangea 195862306a36Sopenharmony_ci * chipset. The pangea chipset is the "combo" UniNorth/KeyLargo 195962306a36Sopenharmony_ci * used on iBook2 & iMac "flow power". 196062306a36Sopenharmony_ci */ 196162306a36Sopenharmony_cistatic struct feature_table_entry core99_features[] = { 196262306a36Sopenharmony_ci { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, 196362306a36Sopenharmony_ci { PMAC_FTR_MODEM_ENABLE, core99_modem_enable }, 196462306a36Sopenharmony_ci { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, 196562306a36Sopenharmony_ci { PMAC_FTR_IDE_RESET, core99_ide_reset }, 196662306a36Sopenharmony_ci { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable }, 196762306a36Sopenharmony_ci { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset }, 196862306a36Sopenharmony_ci { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable }, 196962306a36Sopenharmony_ci { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable }, 197062306a36Sopenharmony_ci { PMAC_FTR_USB_ENABLE, core99_usb_enable }, 197162306a36Sopenharmony_ci { PMAC_FTR_1394_ENABLE, core99_firewire_enable }, 197262306a36Sopenharmony_ci { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power }, 197362306a36Sopenharmony_ci#ifdef CONFIG_PM 197462306a36Sopenharmony_ci { PMAC_FTR_SLEEP_STATE, core99_sleep_state }, 197562306a36Sopenharmony_ci#endif 197662306a36Sopenharmony_ci#ifdef CONFIG_SMP 197762306a36Sopenharmony_ci { PMAC_FTR_RESET_CPU, core99_reset_cpu }, 197862306a36Sopenharmony_ci#endif /* CONFIG_SMP */ 197962306a36Sopenharmony_ci { PMAC_FTR_READ_GPIO, core99_read_gpio }, 198062306a36Sopenharmony_ci { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, 198162306a36Sopenharmony_ci { 0, NULL } 198262306a36Sopenharmony_ci}; 198362306a36Sopenharmony_ci 198462306a36Sopenharmony_ci/* RackMac 198562306a36Sopenharmony_ci */ 198662306a36Sopenharmony_cistatic struct feature_table_entry rackmac_features[] = { 198762306a36Sopenharmony_ci { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, 198862306a36Sopenharmony_ci { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, 198962306a36Sopenharmony_ci { PMAC_FTR_IDE_RESET, core99_ide_reset }, 199062306a36Sopenharmony_ci { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable }, 199162306a36Sopenharmony_ci { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset }, 199262306a36Sopenharmony_ci { PMAC_FTR_USB_ENABLE, core99_usb_enable }, 199362306a36Sopenharmony_ci { PMAC_FTR_1394_ENABLE, core99_firewire_enable }, 199462306a36Sopenharmony_ci { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power }, 199562306a36Sopenharmony_ci { PMAC_FTR_SLEEP_STATE, core99_sleep_state }, 199662306a36Sopenharmony_ci#ifdef CONFIG_SMP 199762306a36Sopenharmony_ci { PMAC_FTR_RESET_CPU, core99_reset_cpu }, 199862306a36Sopenharmony_ci#endif /* CONFIG_SMP */ 199962306a36Sopenharmony_ci { PMAC_FTR_READ_GPIO, core99_read_gpio }, 200062306a36Sopenharmony_ci { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, 200162306a36Sopenharmony_ci { 0, NULL } 200262306a36Sopenharmony_ci}; 200362306a36Sopenharmony_ci 200462306a36Sopenharmony_ci/* Pangea features 200562306a36Sopenharmony_ci */ 200662306a36Sopenharmony_cistatic struct feature_table_entry pangea_features[] = { 200762306a36Sopenharmony_ci { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, 200862306a36Sopenharmony_ci { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable }, 200962306a36Sopenharmony_ci { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, 201062306a36Sopenharmony_ci { PMAC_FTR_IDE_RESET, core99_ide_reset }, 201162306a36Sopenharmony_ci { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable }, 201262306a36Sopenharmony_ci { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset }, 201362306a36Sopenharmony_ci { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable }, 201462306a36Sopenharmony_ci { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable }, 201562306a36Sopenharmony_ci { PMAC_FTR_USB_ENABLE, core99_usb_enable }, 201662306a36Sopenharmony_ci { PMAC_FTR_1394_ENABLE, core99_firewire_enable }, 201762306a36Sopenharmony_ci { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power }, 201862306a36Sopenharmony_ci { PMAC_FTR_SLEEP_STATE, core99_sleep_state }, 201962306a36Sopenharmony_ci { PMAC_FTR_READ_GPIO, core99_read_gpio }, 202062306a36Sopenharmony_ci { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, 202162306a36Sopenharmony_ci { 0, NULL } 202262306a36Sopenharmony_ci}; 202362306a36Sopenharmony_ci 202462306a36Sopenharmony_ci/* Intrepid features 202562306a36Sopenharmony_ci */ 202662306a36Sopenharmony_cistatic struct feature_table_entry intrepid_features[] = { 202762306a36Sopenharmony_ci { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, 202862306a36Sopenharmony_ci { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable }, 202962306a36Sopenharmony_ci { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, 203062306a36Sopenharmony_ci { PMAC_FTR_IDE_RESET, core99_ide_reset }, 203162306a36Sopenharmony_ci { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable }, 203262306a36Sopenharmony_ci { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset }, 203362306a36Sopenharmony_ci { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable }, 203462306a36Sopenharmony_ci { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable }, 203562306a36Sopenharmony_ci { PMAC_FTR_USB_ENABLE, core99_usb_enable }, 203662306a36Sopenharmony_ci { PMAC_FTR_1394_ENABLE, core99_firewire_enable }, 203762306a36Sopenharmony_ci { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power }, 203862306a36Sopenharmony_ci { PMAC_FTR_SLEEP_STATE, core99_sleep_state }, 203962306a36Sopenharmony_ci { PMAC_FTR_READ_GPIO, core99_read_gpio }, 204062306a36Sopenharmony_ci { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, 204162306a36Sopenharmony_ci { PMAC_FTR_AACK_DELAY_ENABLE, intrepid_aack_delay_enable }, 204262306a36Sopenharmony_ci { 0, NULL } 204362306a36Sopenharmony_ci}; 204462306a36Sopenharmony_ci 204562306a36Sopenharmony_ci#else /* CONFIG_PPC64 */ 204662306a36Sopenharmony_ci 204762306a36Sopenharmony_ci/* G5 features 204862306a36Sopenharmony_ci */ 204962306a36Sopenharmony_cistatic struct feature_table_entry g5_features[] = { 205062306a36Sopenharmony_ci { PMAC_FTR_GMAC_ENABLE, g5_gmac_enable }, 205162306a36Sopenharmony_ci { PMAC_FTR_1394_ENABLE, g5_fw_enable }, 205262306a36Sopenharmony_ci { PMAC_FTR_ENABLE_MPIC, g5_mpic_enable }, 205362306a36Sopenharmony_ci { PMAC_FTR_GMAC_PHY_RESET, g5_eth_phy_reset }, 205462306a36Sopenharmony_ci { PMAC_FTR_SOUND_CHIP_ENABLE, g5_i2s_enable }, 205562306a36Sopenharmony_ci#ifdef CONFIG_SMP 205662306a36Sopenharmony_ci { PMAC_FTR_RESET_CPU, g5_reset_cpu }, 205762306a36Sopenharmony_ci#endif /* CONFIG_SMP */ 205862306a36Sopenharmony_ci { PMAC_FTR_READ_GPIO, core99_read_gpio }, 205962306a36Sopenharmony_ci { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, 206062306a36Sopenharmony_ci { 0, NULL } 206162306a36Sopenharmony_ci}; 206262306a36Sopenharmony_ci 206362306a36Sopenharmony_ci#endif /* CONFIG_PPC64 */ 206462306a36Sopenharmony_ci 206562306a36Sopenharmony_cistatic struct pmac_mb_def pmac_mb_defs[] = { 206662306a36Sopenharmony_ci#ifndef CONFIG_PPC64 206762306a36Sopenharmony_ci /* 206862306a36Sopenharmony_ci * Desktops 206962306a36Sopenharmony_ci */ 207062306a36Sopenharmony_ci 207162306a36Sopenharmony_ci { "AAPL,8500", "PowerMac 8500/8600", 207262306a36Sopenharmony_ci PMAC_TYPE_PSURGE, NULL, 207362306a36Sopenharmony_ci 0 207462306a36Sopenharmony_ci }, 207562306a36Sopenharmony_ci { "AAPL,9500", "PowerMac 9500/9600", 207662306a36Sopenharmony_ci PMAC_TYPE_PSURGE, NULL, 207762306a36Sopenharmony_ci 0 207862306a36Sopenharmony_ci }, 207962306a36Sopenharmony_ci { "AAPL,7200", "PowerMac 7200", 208062306a36Sopenharmony_ci PMAC_TYPE_PSURGE, NULL, 208162306a36Sopenharmony_ci 0 208262306a36Sopenharmony_ci }, 208362306a36Sopenharmony_ci { "AAPL,7300", "PowerMac 7200/7300", 208462306a36Sopenharmony_ci PMAC_TYPE_PSURGE, NULL, 208562306a36Sopenharmony_ci 0 208662306a36Sopenharmony_ci }, 208762306a36Sopenharmony_ci { "AAPL,7500", "PowerMac 7500", 208862306a36Sopenharmony_ci PMAC_TYPE_PSURGE, NULL, 208962306a36Sopenharmony_ci 0 209062306a36Sopenharmony_ci }, 209162306a36Sopenharmony_ci { "AAPL,ShinerESB", "Apple Network Server", 209262306a36Sopenharmony_ci PMAC_TYPE_ANS, NULL, 209362306a36Sopenharmony_ci 0 209462306a36Sopenharmony_ci }, 209562306a36Sopenharmony_ci { "AAPL,e407", "Alchemy", 209662306a36Sopenharmony_ci PMAC_TYPE_ALCHEMY, NULL, 209762306a36Sopenharmony_ci 0 209862306a36Sopenharmony_ci }, 209962306a36Sopenharmony_ci { "AAPL,e411", "Gazelle", 210062306a36Sopenharmony_ci PMAC_TYPE_GAZELLE, NULL, 210162306a36Sopenharmony_ci 0 210262306a36Sopenharmony_ci }, 210362306a36Sopenharmony_ci { "AAPL,Gossamer", "PowerMac G3 (Gossamer)", 210462306a36Sopenharmony_ci PMAC_TYPE_GOSSAMER, heathrow_desktop_features, 210562306a36Sopenharmony_ci 0 210662306a36Sopenharmony_ci }, 210762306a36Sopenharmony_ci { "AAPL,PowerMac G3", "PowerMac G3 (Silk)", 210862306a36Sopenharmony_ci PMAC_TYPE_SILK, heathrow_desktop_features, 210962306a36Sopenharmony_ci 0 211062306a36Sopenharmony_ci }, 211162306a36Sopenharmony_ci { "PowerMac1,1", "Blue&White G3", 211262306a36Sopenharmony_ci PMAC_TYPE_YOSEMITE, paddington_features, 211362306a36Sopenharmony_ci 0 211462306a36Sopenharmony_ci }, 211562306a36Sopenharmony_ci { "PowerMac1,2", "PowerMac G4 PCI Graphics", 211662306a36Sopenharmony_ci PMAC_TYPE_YIKES, paddington_features, 211762306a36Sopenharmony_ci 0 211862306a36Sopenharmony_ci }, 211962306a36Sopenharmony_ci { "PowerMac2,1", "iMac FireWire", 212062306a36Sopenharmony_ci PMAC_TYPE_FW_IMAC, core99_features, 212162306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99 212262306a36Sopenharmony_ci }, 212362306a36Sopenharmony_ci { "PowerMac2,2", "iMac FireWire", 212462306a36Sopenharmony_ci PMAC_TYPE_FW_IMAC, core99_features, 212562306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99 212662306a36Sopenharmony_ci }, 212762306a36Sopenharmony_ci { "PowerMac3,1", "PowerMac G4 AGP Graphics", 212862306a36Sopenharmony_ci PMAC_TYPE_SAWTOOTH, core99_features, 212962306a36Sopenharmony_ci PMAC_MB_OLD_CORE99 213062306a36Sopenharmony_ci }, 213162306a36Sopenharmony_ci { "PowerMac3,2", "PowerMac G4 AGP Graphics", 213262306a36Sopenharmony_ci PMAC_TYPE_SAWTOOTH, core99_features, 213362306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99 213462306a36Sopenharmony_ci }, 213562306a36Sopenharmony_ci { "PowerMac3,3", "PowerMac G4 AGP Graphics", 213662306a36Sopenharmony_ci PMAC_TYPE_SAWTOOTH, core99_features, 213762306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99 213862306a36Sopenharmony_ci }, 213962306a36Sopenharmony_ci { "PowerMac3,4", "PowerMac G4 Silver", 214062306a36Sopenharmony_ci PMAC_TYPE_QUICKSILVER, core99_features, 214162306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP 214262306a36Sopenharmony_ci }, 214362306a36Sopenharmony_ci { "PowerMac3,5", "PowerMac G4 Silver", 214462306a36Sopenharmony_ci PMAC_TYPE_QUICKSILVER, core99_features, 214562306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP 214662306a36Sopenharmony_ci }, 214762306a36Sopenharmony_ci { "PowerMac3,6", "PowerMac G4 Windtunnel", 214862306a36Sopenharmony_ci PMAC_TYPE_WINDTUNNEL, core99_features, 214962306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP, 215062306a36Sopenharmony_ci }, 215162306a36Sopenharmony_ci { "PowerMac4,1", "iMac \"Flower Power\"", 215262306a36Sopenharmony_ci PMAC_TYPE_PANGEA_IMAC, pangea_features, 215362306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP 215462306a36Sopenharmony_ci }, 215562306a36Sopenharmony_ci { "PowerMac4,2", "Flat panel iMac", 215662306a36Sopenharmony_ci PMAC_TYPE_FLAT_PANEL_IMAC, pangea_features, 215762306a36Sopenharmony_ci PMAC_MB_CAN_SLEEP 215862306a36Sopenharmony_ci }, 215962306a36Sopenharmony_ci { "PowerMac4,4", "eMac", 216062306a36Sopenharmony_ci PMAC_TYPE_EMAC, core99_features, 216162306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP 216262306a36Sopenharmony_ci }, 216362306a36Sopenharmony_ci { "PowerMac5,1", "PowerMac G4 Cube", 216462306a36Sopenharmony_ci PMAC_TYPE_CUBE, core99_features, 216562306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99 216662306a36Sopenharmony_ci }, 216762306a36Sopenharmony_ci { "PowerMac6,1", "Flat panel iMac", 216862306a36Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 216962306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP, 217062306a36Sopenharmony_ci }, 217162306a36Sopenharmony_ci { "PowerMac6,3", "Flat panel iMac", 217262306a36Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 217362306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP, 217462306a36Sopenharmony_ci }, 217562306a36Sopenharmony_ci { "PowerMac6,4", "eMac", 217662306a36Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 217762306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP, 217862306a36Sopenharmony_ci }, 217962306a36Sopenharmony_ci { "PowerMac10,1", "Mac mini", 218062306a36Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 218162306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP, 218262306a36Sopenharmony_ci }, 218362306a36Sopenharmony_ci { "PowerMac10,2", "Mac mini (Late 2005)", 218462306a36Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 218562306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP, 218662306a36Sopenharmony_ci }, 218762306a36Sopenharmony_ci { "iMac,1", "iMac (first generation)", 218862306a36Sopenharmony_ci PMAC_TYPE_ORIG_IMAC, paddington_features, 218962306a36Sopenharmony_ci 0 219062306a36Sopenharmony_ci }, 219162306a36Sopenharmony_ci 219262306a36Sopenharmony_ci /* 219362306a36Sopenharmony_ci * Xserve's 219462306a36Sopenharmony_ci */ 219562306a36Sopenharmony_ci 219662306a36Sopenharmony_ci { "RackMac1,1", "XServe", 219762306a36Sopenharmony_ci PMAC_TYPE_RACKMAC, rackmac_features, 219862306a36Sopenharmony_ci 0, 219962306a36Sopenharmony_ci }, 220062306a36Sopenharmony_ci { "RackMac1,2", "XServe rev. 2", 220162306a36Sopenharmony_ci PMAC_TYPE_RACKMAC, rackmac_features, 220262306a36Sopenharmony_ci 0, 220362306a36Sopenharmony_ci }, 220462306a36Sopenharmony_ci 220562306a36Sopenharmony_ci /* 220662306a36Sopenharmony_ci * Laptops 220762306a36Sopenharmony_ci */ 220862306a36Sopenharmony_ci 220962306a36Sopenharmony_ci { "AAPL,3400/2400", "PowerBook 3400", 221062306a36Sopenharmony_ci PMAC_TYPE_HOOPER, ohare_features, 221162306a36Sopenharmony_ci PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE 221262306a36Sopenharmony_ci }, 221362306a36Sopenharmony_ci { "AAPL,3500", "PowerBook 3500", 221462306a36Sopenharmony_ci PMAC_TYPE_KANGA, ohare_features, 221562306a36Sopenharmony_ci PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE 221662306a36Sopenharmony_ci }, 221762306a36Sopenharmony_ci { "AAPL,PowerBook1998", "PowerBook Wallstreet", 221862306a36Sopenharmony_ci PMAC_TYPE_WALLSTREET, heathrow_laptop_features, 221962306a36Sopenharmony_ci PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE 222062306a36Sopenharmony_ci }, 222162306a36Sopenharmony_ci { "PowerBook1,1", "PowerBook 101 (Lombard)", 222262306a36Sopenharmony_ci PMAC_TYPE_101_PBOOK, paddington_features, 222362306a36Sopenharmony_ci PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE 222462306a36Sopenharmony_ci }, 222562306a36Sopenharmony_ci { "PowerBook2,1", "iBook (first generation)", 222662306a36Sopenharmony_ci PMAC_TYPE_ORIG_IBOOK, core99_features, 222762306a36Sopenharmony_ci PMAC_MB_CAN_SLEEP | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE 222862306a36Sopenharmony_ci }, 222962306a36Sopenharmony_ci { "PowerBook2,2", "iBook FireWire", 223062306a36Sopenharmony_ci PMAC_TYPE_FW_IBOOK, core99_features, 223162306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | 223262306a36Sopenharmony_ci PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE 223362306a36Sopenharmony_ci }, 223462306a36Sopenharmony_ci { "PowerBook3,1", "PowerBook Pismo", 223562306a36Sopenharmony_ci PMAC_TYPE_PISMO, core99_features, 223662306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | 223762306a36Sopenharmony_ci PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE 223862306a36Sopenharmony_ci }, 223962306a36Sopenharmony_ci { "PowerBook3,2", "PowerBook Titanium", 224062306a36Sopenharmony_ci PMAC_TYPE_TITANIUM, core99_features, 224162306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE 224262306a36Sopenharmony_ci }, 224362306a36Sopenharmony_ci { "PowerBook3,3", "PowerBook Titanium II", 224462306a36Sopenharmony_ci PMAC_TYPE_TITANIUM2, core99_features, 224562306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE 224662306a36Sopenharmony_ci }, 224762306a36Sopenharmony_ci { "PowerBook3,4", "PowerBook Titanium III", 224862306a36Sopenharmony_ci PMAC_TYPE_TITANIUM3, core99_features, 224962306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE 225062306a36Sopenharmony_ci }, 225162306a36Sopenharmony_ci { "PowerBook3,5", "PowerBook Titanium IV", 225262306a36Sopenharmony_ci PMAC_TYPE_TITANIUM4, core99_features, 225362306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE 225462306a36Sopenharmony_ci }, 225562306a36Sopenharmony_ci { "PowerBook4,1", "iBook 2", 225662306a36Sopenharmony_ci PMAC_TYPE_IBOOK2, pangea_features, 225762306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE 225862306a36Sopenharmony_ci }, 225962306a36Sopenharmony_ci { "PowerBook4,2", "iBook 2", 226062306a36Sopenharmony_ci PMAC_TYPE_IBOOK2, pangea_features, 226162306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE 226262306a36Sopenharmony_ci }, 226362306a36Sopenharmony_ci { "PowerBook4,3", "iBook 2 rev. 2", 226462306a36Sopenharmony_ci PMAC_TYPE_IBOOK2, pangea_features, 226562306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE 226662306a36Sopenharmony_ci }, 226762306a36Sopenharmony_ci { "PowerBook5,1", "PowerBook G4 17\"", 226862306a36Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 226962306a36Sopenharmony_ci PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 227062306a36Sopenharmony_ci }, 227162306a36Sopenharmony_ci { "PowerBook5,2", "PowerBook G4 15\"", 227262306a36Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 227362306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 227462306a36Sopenharmony_ci }, 227562306a36Sopenharmony_ci { "PowerBook5,3", "PowerBook G4 17\"", 227662306a36Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 227762306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 227862306a36Sopenharmony_ci }, 227962306a36Sopenharmony_ci { "PowerBook5,4", "PowerBook G4 15\"", 228062306a36Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 228162306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 228262306a36Sopenharmony_ci }, 228362306a36Sopenharmony_ci { "PowerBook5,5", "PowerBook G4 17\"", 228462306a36Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 228562306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 228662306a36Sopenharmony_ci }, 228762306a36Sopenharmony_ci { "PowerBook5,6", "PowerBook G4 15\"", 228862306a36Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 228962306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 229062306a36Sopenharmony_ci }, 229162306a36Sopenharmony_ci { "PowerBook5,7", "PowerBook G4 17\"", 229262306a36Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 229362306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 229462306a36Sopenharmony_ci }, 229562306a36Sopenharmony_ci { "PowerBook5,8", "PowerBook G4 15\"", 229662306a36Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 229762306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_MOBILE, 229862306a36Sopenharmony_ci }, 229962306a36Sopenharmony_ci { "PowerBook5,9", "PowerBook G4 17\"", 230062306a36Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 230162306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_MOBILE, 230262306a36Sopenharmony_ci }, 230362306a36Sopenharmony_ci { "PowerBook6,1", "PowerBook G4 12\"", 230462306a36Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 230562306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 230662306a36Sopenharmony_ci }, 230762306a36Sopenharmony_ci { "PowerBook6,2", "PowerBook G4", 230862306a36Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 230962306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 231062306a36Sopenharmony_ci }, 231162306a36Sopenharmony_ci { "PowerBook6,3", "iBook G4", 231262306a36Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 231362306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 231462306a36Sopenharmony_ci }, 231562306a36Sopenharmony_ci { "PowerBook6,4", "PowerBook G4 12\"", 231662306a36Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 231762306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 231862306a36Sopenharmony_ci }, 231962306a36Sopenharmony_ci { "PowerBook6,5", "iBook G4", 232062306a36Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 232162306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 232262306a36Sopenharmony_ci }, 232362306a36Sopenharmony_ci { "PowerBook6,7", "iBook G4", 232462306a36Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 232562306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 232662306a36Sopenharmony_ci }, 232762306a36Sopenharmony_ci { "PowerBook6,8", "PowerBook G4 12\"", 232862306a36Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 232962306a36Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 233062306a36Sopenharmony_ci }, 233162306a36Sopenharmony_ci#else /* CONFIG_PPC64 */ 233262306a36Sopenharmony_ci { "PowerMac7,2", "PowerMac G5", 233362306a36Sopenharmony_ci PMAC_TYPE_POWERMAC_G5, g5_features, 233462306a36Sopenharmony_ci 0, 233562306a36Sopenharmony_ci }, 233662306a36Sopenharmony_ci#ifdef CONFIG_PPC64 233762306a36Sopenharmony_ci { "PowerMac7,3", "PowerMac G5", 233862306a36Sopenharmony_ci PMAC_TYPE_POWERMAC_G5, g5_features, 233962306a36Sopenharmony_ci 0, 234062306a36Sopenharmony_ci }, 234162306a36Sopenharmony_ci { "PowerMac8,1", "iMac G5", 234262306a36Sopenharmony_ci PMAC_TYPE_IMAC_G5, g5_features, 234362306a36Sopenharmony_ci 0, 234462306a36Sopenharmony_ci }, 234562306a36Sopenharmony_ci { "PowerMac9,1", "PowerMac G5", 234662306a36Sopenharmony_ci PMAC_TYPE_POWERMAC_G5_U3L, g5_features, 234762306a36Sopenharmony_ci 0, 234862306a36Sopenharmony_ci }, 234962306a36Sopenharmony_ci { "PowerMac11,2", "PowerMac G5 Dual Core", 235062306a36Sopenharmony_ci PMAC_TYPE_POWERMAC_G5_U3L, g5_features, 235162306a36Sopenharmony_ci 0, 235262306a36Sopenharmony_ci }, 235362306a36Sopenharmony_ci { "PowerMac12,1", "iMac G5 (iSight)", 235462306a36Sopenharmony_ci PMAC_TYPE_POWERMAC_G5_U3L, g5_features, 235562306a36Sopenharmony_ci 0, 235662306a36Sopenharmony_ci }, 235762306a36Sopenharmony_ci { "RackMac3,1", "XServe G5", 235862306a36Sopenharmony_ci PMAC_TYPE_XSERVE_G5, g5_features, 235962306a36Sopenharmony_ci 0, 236062306a36Sopenharmony_ci }, 236162306a36Sopenharmony_ci#endif /* CONFIG_PPC64 */ 236262306a36Sopenharmony_ci#endif /* CONFIG_PPC64 */ 236362306a36Sopenharmony_ci}; 236462306a36Sopenharmony_ci 236562306a36Sopenharmony_ci/* 236662306a36Sopenharmony_ci * The toplevel feature_call callback 236762306a36Sopenharmony_ci */ 236862306a36Sopenharmony_cilong pmac_do_feature_call(unsigned int selector, ...) 236962306a36Sopenharmony_ci{ 237062306a36Sopenharmony_ci struct device_node *node; 237162306a36Sopenharmony_ci long param, value; 237262306a36Sopenharmony_ci int i; 237362306a36Sopenharmony_ci feature_call func = NULL; 237462306a36Sopenharmony_ci va_list args; 237562306a36Sopenharmony_ci 237662306a36Sopenharmony_ci if (pmac_mb.features) 237762306a36Sopenharmony_ci for (i=0; pmac_mb.features[i].function; i++) 237862306a36Sopenharmony_ci if (pmac_mb.features[i].selector == selector) { 237962306a36Sopenharmony_ci func = pmac_mb.features[i].function; 238062306a36Sopenharmony_ci break; 238162306a36Sopenharmony_ci } 238262306a36Sopenharmony_ci if (!func) 238362306a36Sopenharmony_ci for (i=0; any_features[i].function; i++) 238462306a36Sopenharmony_ci if (any_features[i].selector == selector) { 238562306a36Sopenharmony_ci func = any_features[i].function; 238662306a36Sopenharmony_ci break; 238762306a36Sopenharmony_ci } 238862306a36Sopenharmony_ci if (!func) 238962306a36Sopenharmony_ci return -ENODEV; 239062306a36Sopenharmony_ci 239162306a36Sopenharmony_ci va_start(args, selector); 239262306a36Sopenharmony_ci node = (struct device_node*)va_arg(args, void*); 239362306a36Sopenharmony_ci param = va_arg(args, long); 239462306a36Sopenharmony_ci value = va_arg(args, long); 239562306a36Sopenharmony_ci va_end(args); 239662306a36Sopenharmony_ci 239762306a36Sopenharmony_ci return func(node, param, value); 239862306a36Sopenharmony_ci} 239962306a36Sopenharmony_ci 240062306a36Sopenharmony_cistatic int __init probe_motherboard(void) 240162306a36Sopenharmony_ci{ 240262306a36Sopenharmony_ci int i; 240362306a36Sopenharmony_ci struct macio_chip *macio = &macio_chips[0]; 240462306a36Sopenharmony_ci const char *model = NULL; 240562306a36Sopenharmony_ci struct device_node *dt; 240662306a36Sopenharmony_ci int ret = 0; 240762306a36Sopenharmony_ci 240862306a36Sopenharmony_ci /* Lookup known motherboard type in device-tree. First try an 240962306a36Sopenharmony_ci * exact match on the "model" property, then try a "compatible" 241062306a36Sopenharmony_ci * match is none is found. 241162306a36Sopenharmony_ci */ 241262306a36Sopenharmony_ci dt = of_find_node_by_name(NULL, "device-tree"); 241362306a36Sopenharmony_ci if (dt != NULL) 241462306a36Sopenharmony_ci model = of_get_property(dt, "model", NULL); 241562306a36Sopenharmony_ci for(i=0; model && i<ARRAY_SIZE(pmac_mb_defs); i++) { 241662306a36Sopenharmony_ci if (strcmp(model, pmac_mb_defs[i].model_string) == 0) { 241762306a36Sopenharmony_ci pmac_mb = pmac_mb_defs[i]; 241862306a36Sopenharmony_ci goto found; 241962306a36Sopenharmony_ci } 242062306a36Sopenharmony_ci } 242162306a36Sopenharmony_ci for(i=0; i<ARRAY_SIZE(pmac_mb_defs); i++) { 242262306a36Sopenharmony_ci if (of_machine_is_compatible(pmac_mb_defs[i].model_string)) { 242362306a36Sopenharmony_ci pmac_mb = pmac_mb_defs[i]; 242462306a36Sopenharmony_ci goto found; 242562306a36Sopenharmony_ci } 242662306a36Sopenharmony_ci } 242762306a36Sopenharmony_ci 242862306a36Sopenharmony_ci /* Fallback to selection depending on mac-io chip type */ 242962306a36Sopenharmony_ci switch(macio->type) { 243062306a36Sopenharmony_ci#ifndef CONFIG_PPC64 243162306a36Sopenharmony_ci case macio_grand_central: 243262306a36Sopenharmony_ci pmac_mb.model_id = PMAC_TYPE_PSURGE; 243362306a36Sopenharmony_ci pmac_mb.model_name = "Unknown PowerSurge"; 243462306a36Sopenharmony_ci break; 243562306a36Sopenharmony_ci case macio_ohare: 243662306a36Sopenharmony_ci pmac_mb.model_id = PMAC_TYPE_UNKNOWN_OHARE; 243762306a36Sopenharmony_ci pmac_mb.model_name = "Unknown OHare-based"; 243862306a36Sopenharmony_ci break; 243962306a36Sopenharmony_ci case macio_heathrow: 244062306a36Sopenharmony_ci pmac_mb.model_id = PMAC_TYPE_UNKNOWN_HEATHROW; 244162306a36Sopenharmony_ci pmac_mb.model_name = "Unknown Heathrow-based"; 244262306a36Sopenharmony_ci pmac_mb.features = heathrow_desktop_features; 244362306a36Sopenharmony_ci break; 244462306a36Sopenharmony_ci case macio_paddington: 244562306a36Sopenharmony_ci pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PADDINGTON; 244662306a36Sopenharmony_ci pmac_mb.model_name = "Unknown Paddington-based"; 244762306a36Sopenharmony_ci pmac_mb.features = paddington_features; 244862306a36Sopenharmony_ci break; 244962306a36Sopenharmony_ci case macio_keylargo: 245062306a36Sopenharmony_ci pmac_mb.model_id = PMAC_TYPE_UNKNOWN_CORE99; 245162306a36Sopenharmony_ci pmac_mb.model_name = "Unknown Keylargo-based"; 245262306a36Sopenharmony_ci pmac_mb.features = core99_features; 245362306a36Sopenharmony_ci break; 245462306a36Sopenharmony_ci case macio_pangea: 245562306a36Sopenharmony_ci pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PANGEA; 245662306a36Sopenharmony_ci pmac_mb.model_name = "Unknown Pangea-based"; 245762306a36Sopenharmony_ci pmac_mb.features = pangea_features; 245862306a36Sopenharmony_ci break; 245962306a36Sopenharmony_ci case macio_intrepid: 246062306a36Sopenharmony_ci pmac_mb.model_id = PMAC_TYPE_UNKNOWN_INTREPID; 246162306a36Sopenharmony_ci pmac_mb.model_name = "Unknown Intrepid-based"; 246262306a36Sopenharmony_ci pmac_mb.features = intrepid_features; 246362306a36Sopenharmony_ci break; 246462306a36Sopenharmony_ci#else /* CONFIG_PPC64 */ 246562306a36Sopenharmony_ci case macio_keylargo2: 246662306a36Sopenharmony_ci pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2; 246762306a36Sopenharmony_ci pmac_mb.model_name = "Unknown K2-based"; 246862306a36Sopenharmony_ci pmac_mb.features = g5_features; 246962306a36Sopenharmony_ci break; 247062306a36Sopenharmony_ci case macio_shasta: 247162306a36Sopenharmony_ci pmac_mb.model_id = PMAC_TYPE_UNKNOWN_SHASTA; 247262306a36Sopenharmony_ci pmac_mb.model_name = "Unknown Shasta-based"; 247362306a36Sopenharmony_ci pmac_mb.features = g5_features; 247462306a36Sopenharmony_ci break; 247562306a36Sopenharmony_ci#endif /* CONFIG_PPC64 */ 247662306a36Sopenharmony_ci default: 247762306a36Sopenharmony_ci ret = -ENODEV; 247862306a36Sopenharmony_ci goto done; 247962306a36Sopenharmony_ci } 248062306a36Sopenharmony_cifound: 248162306a36Sopenharmony_ci#ifndef CONFIG_PPC64 248262306a36Sopenharmony_ci /* Fixup Hooper vs. Comet */ 248362306a36Sopenharmony_ci if (pmac_mb.model_id == PMAC_TYPE_HOOPER) { 248462306a36Sopenharmony_ci u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4); 248562306a36Sopenharmony_ci if (!mach_id_ptr) { 248662306a36Sopenharmony_ci ret = -ENODEV; 248762306a36Sopenharmony_ci goto done; 248862306a36Sopenharmony_ci } 248962306a36Sopenharmony_ci /* Here, I used to disable the media-bay on comet. It 249062306a36Sopenharmony_ci * appears this is wrong, the floppy connector is actually 249162306a36Sopenharmony_ci * a kind of media-bay and works with the current driver. 249262306a36Sopenharmony_ci */ 249362306a36Sopenharmony_ci if (__raw_readl(mach_id_ptr) & 0x20000000UL) 249462306a36Sopenharmony_ci pmac_mb.model_id = PMAC_TYPE_COMET; 249562306a36Sopenharmony_ci iounmap(mach_id_ptr); 249662306a36Sopenharmony_ci } 249762306a36Sopenharmony_ci 249862306a36Sopenharmony_ci /* Set default value of powersave_nap on machines that support it. 249962306a36Sopenharmony_ci * It appears that uninorth rev 3 has a problem with it, we don't 250062306a36Sopenharmony_ci * enable it on those. In theory, the flush-on-lock property is 250162306a36Sopenharmony_ci * supposed to be set when not supported, but I'm not very confident 250262306a36Sopenharmony_ci * that all Apple OF revs did it properly, I do it the paranoid way. 250362306a36Sopenharmony_ci */ 250462306a36Sopenharmony_ci if (uninorth_base && uninorth_rev > 3) { 250562306a36Sopenharmony_ci struct device_node *np; 250662306a36Sopenharmony_ci 250762306a36Sopenharmony_ci for_each_of_cpu_node(np) { 250862306a36Sopenharmony_ci int cpu_count = 1; 250962306a36Sopenharmony_ci 251062306a36Sopenharmony_ci /* Nap mode not supported on SMP */ 251162306a36Sopenharmony_ci if (of_property_read_bool(np, "flush-on-lock") || 251262306a36Sopenharmony_ci (cpu_count > 1)) { 251362306a36Sopenharmony_ci powersave_nap = 0; 251462306a36Sopenharmony_ci of_node_put(np); 251562306a36Sopenharmony_ci break; 251662306a36Sopenharmony_ci } 251762306a36Sopenharmony_ci 251862306a36Sopenharmony_ci cpu_count++; 251962306a36Sopenharmony_ci powersave_nap = 1; 252062306a36Sopenharmony_ci } 252162306a36Sopenharmony_ci } 252262306a36Sopenharmony_ci if (powersave_nap) 252362306a36Sopenharmony_ci printk(KERN_DEBUG "Processor NAP mode on idle enabled.\n"); 252462306a36Sopenharmony_ci 252562306a36Sopenharmony_ci /* On CPUs that support it (750FX), lowspeed by default during 252662306a36Sopenharmony_ci * NAP mode 252762306a36Sopenharmony_ci */ 252862306a36Sopenharmony_ci powersave_lowspeed = 1; 252962306a36Sopenharmony_ci 253062306a36Sopenharmony_ci#else /* CONFIG_PPC64 */ 253162306a36Sopenharmony_ci powersave_nap = 1; 253262306a36Sopenharmony_ci#endif /* CONFIG_PPC64 */ 253362306a36Sopenharmony_ci 253462306a36Sopenharmony_ci /* Check for "mobile" machine */ 253562306a36Sopenharmony_ci if (model && (strncmp(model, "PowerBook", 9) == 0 253662306a36Sopenharmony_ci || strncmp(model, "iBook", 5) == 0)) 253762306a36Sopenharmony_ci pmac_mb.board_flags |= PMAC_MB_MOBILE; 253862306a36Sopenharmony_ci 253962306a36Sopenharmony_ci 254062306a36Sopenharmony_ci printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name); 254162306a36Sopenharmony_cidone: 254262306a36Sopenharmony_ci of_node_put(dt); 254362306a36Sopenharmony_ci return ret; 254462306a36Sopenharmony_ci} 254562306a36Sopenharmony_ci 254662306a36Sopenharmony_ci/* Initialize the Core99 UniNorth host bridge and memory controller 254762306a36Sopenharmony_ci */ 254862306a36Sopenharmony_cistatic void __init probe_uninorth(void) 254962306a36Sopenharmony_ci{ 255062306a36Sopenharmony_ci struct resource res; 255162306a36Sopenharmony_ci unsigned long actrl; 255262306a36Sopenharmony_ci 255362306a36Sopenharmony_ci /* Locate core99 Uni-N */ 255462306a36Sopenharmony_ci uninorth_node = of_find_node_by_name(NULL, "uni-n"); 255562306a36Sopenharmony_ci uninorth_maj = 1; 255662306a36Sopenharmony_ci 255762306a36Sopenharmony_ci /* Locate G5 u3 */ 255862306a36Sopenharmony_ci if (uninorth_node == NULL) { 255962306a36Sopenharmony_ci uninorth_node = of_find_node_by_name(NULL, "u3"); 256062306a36Sopenharmony_ci uninorth_maj = 3; 256162306a36Sopenharmony_ci } 256262306a36Sopenharmony_ci /* Locate G5 u4 */ 256362306a36Sopenharmony_ci if (uninorth_node == NULL) { 256462306a36Sopenharmony_ci uninorth_node = of_find_node_by_name(NULL, "u4"); 256562306a36Sopenharmony_ci uninorth_maj = 4; 256662306a36Sopenharmony_ci } 256762306a36Sopenharmony_ci if (uninorth_node == NULL) { 256862306a36Sopenharmony_ci uninorth_maj = 0; 256962306a36Sopenharmony_ci return; 257062306a36Sopenharmony_ci } 257162306a36Sopenharmony_ci 257262306a36Sopenharmony_ci if (of_address_to_resource(uninorth_node, 0, &res)) 257362306a36Sopenharmony_ci return; 257462306a36Sopenharmony_ci 257562306a36Sopenharmony_ci uninorth_base = ioremap(res.start, 0x40000); 257662306a36Sopenharmony_ci if (uninorth_base == NULL) 257762306a36Sopenharmony_ci return; 257862306a36Sopenharmony_ci uninorth_rev = in_be32(UN_REG(UNI_N_VERSION)); 257962306a36Sopenharmony_ci if (uninorth_maj == 3 || uninorth_maj == 4) { 258062306a36Sopenharmony_ci u3_ht_base = ioremap(res.start + U3_HT_CONFIG_BASE, 0x1000); 258162306a36Sopenharmony_ci if (u3_ht_base == NULL) { 258262306a36Sopenharmony_ci iounmap(uninorth_base); 258362306a36Sopenharmony_ci return; 258462306a36Sopenharmony_ci } 258562306a36Sopenharmony_ci } 258662306a36Sopenharmony_ci 258762306a36Sopenharmony_ci printk(KERN_INFO "Found %s memory controller & host bridge" 258862306a36Sopenharmony_ci " @ 0x%08x revision: 0x%02x\n", uninorth_maj == 3 ? "U3" : 258962306a36Sopenharmony_ci uninorth_maj == 4 ? "U4" : "UniNorth", 259062306a36Sopenharmony_ci (unsigned int)res.start, uninorth_rev); 259162306a36Sopenharmony_ci printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base); 259262306a36Sopenharmony_ci 259362306a36Sopenharmony_ci /* Set the arbitrer QAck delay according to what Apple does 259462306a36Sopenharmony_ci */ 259562306a36Sopenharmony_ci if (uninorth_rev < 0x11) { 259662306a36Sopenharmony_ci actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK; 259762306a36Sopenharmony_ci actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 : 259862306a36Sopenharmony_ci UNI_N_ARB_CTRL_QACK_DELAY) << 259962306a36Sopenharmony_ci UNI_N_ARB_CTRL_QACK_DELAY_SHIFT; 260062306a36Sopenharmony_ci UN_OUT(UNI_N_ARB_CTRL, actrl); 260162306a36Sopenharmony_ci } 260262306a36Sopenharmony_ci 260362306a36Sopenharmony_ci /* Some more magic as done by them in recent MacOS X on UniNorth 260462306a36Sopenharmony_ci * revs 1.5 to 2.O and Pangea. Seem to toggle the UniN Maxbus/PCI 260562306a36Sopenharmony_ci * memory timeout 260662306a36Sopenharmony_ci */ 260762306a36Sopenharmony_ci if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) || 260862306a36Sopenharmony_ci uninorth_rev == 0xc0) 260962306a36Sopenharmony_ci UN_OUT(0x2160, UN_IN(0x2160) & 0x00ffffff); 261062306a36Sopenharmony_ci} 261162306a36Sopenharmony_ci 261262306a36Sopenharmony_cistatic void __init probe_one_macio(const char *name, const char *compat, int type) 261362306a36Sopenharmony_ci{ 261462306a36Sopenharmony_ci struct device_node* node; 261562306a36Sopenharmony_ci int i; 261662306a36Sopenharmony_ci volatile u32 __iomem *base; 261762306a36Sopenharmony_ci const u32 *addrp, *revp; 261862306a36Sopenharmony_ci phys_addr_t addr; 261962306a36Sopenharmony_ci u64 size; 262062306a36Sopenharmony_ci 262162306a36Sopenharmony_ci for_each_node_by_name(node, name) { 262262306a36Sopenharmony_ci if (!compat) 262362306a36Sopenharmony_ci break; 262462306a36Sopenharmony_ci if (of_device_is_compatible(node, compat)) 262562306a36Sopenharmony_ci break; 262662306a36Sopenharmony_ci } 262762306a36Sopenharmony_ci if (!node) 262862306a36Sopenharmony_ci return; 262962306a36Sopenharmony_ci for(i=0; i<MAX_MACIO_CHIPS; i++) { 263062306a36Sopenharmony_ci if (!macio_chips[i].of_node) 263162306a36Sopenharmony_ci break; 263262306a36Sopenharmony_ci if (macio_chips[i].of_node == node) 263362306a36Sopenharmony_ci goto out_put; 263462306a36Sopenharmony_ci } 263562306a36Sopenharmony_ci 263662306a36Sopenharmony_ci if (i >= MAX_MACIO_CHIPS) { 263762306a36Sopenharmony_ci printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n"); 263862306a36Sopenharmony_ci printk(KERN_ERR "pmac_feature: %pOF skipped\n", node); 263962306a36Sopenharmony_ci goto out_put; 264062306a36Sopenharmony_ci } 264162306a36Sopenharmony_ci addrp = of_get_pci_address(node, 0, &size, NULL); 264262306a36Sopenharmony_ci if (addrp == NULL) { 264362306a36Sopenharmony_ci printk(KERN_ERR "pmac_feature: %pOF: can't find base !\n", 264462306a36Sopenharmony_ci node); 264562306a36Sopenharmony_ci goto out_put; 264662306a36Sopenharmony_ci } 264762306a36Sopenharmony_ci addr = of_translate_address(node, addrp); 264862306a36Sopenharmony_ci if (addr == 0) { 264962306a36Sopenharmony_ci printk(KERN_ERR "pmac_feature: %pOF, can't translate base !\n", 265062306a36Sopenharmony_ci node); 265162306a36Sopenharmony_ci goto out_put; 265262306a36Sopenharmony_ci } 265362306a36Sopenharmony_ci base = ioremap(addr, (unsigned long)size); 265462306a36Sopenharmony_ci if (!base) { 265562306a36Sopenharmony_ci printk(KERN_ERR "pmac_feature: %pOF, can't map mac-io chip !\n", 265662306a36Sopenharmony_ci node); 265762306a36Sopenharmony_ci goto out_put; 265862306a36Sopenharmony_ci } 265962306a36Sopenharmony_ci if (type == macio_keylargo || type == macio_keylargo2) { 266062306a36Sopenharmony_ci const u32 *did = of_get_property(node, "device-id", NULL); 266162306a36Sopenharmony_ci if (*did == 0x00000025) 266262306a36Sopenharmony_ci type = macio_pangea; 266362306a36Sopenharmony_ci if (*did == 0x0000003e) 266462306a36Sopenharmony_ci type = macio_intrepid; 266562306a36Sopenharmony_ci if (*did == 0x0000004f) 266662306a36Sopenharmony_ci type = macio_shasta; 266762306a36Sopenharmony_ci } 266862306a36Sopenharmony_ci macio_chips[i].of_node = node; 266962306a36Sopenharmony_ci macio_chips[i].type = type; 267062306a36Sopenharmony_ci macio_chips[i].base = base; 267162306a36Sopenharmony_ci macio_chips[i].flags = MACIO_FLAG_SCCA_ON | MACIO_FLAG_SCCB_ON; 267262306a36Sopenharmony_ci macio_chips[i].name = macio_names[type]; 267362306a36Sopenharmony_ci revp = of_get_property(node, "revision-id", NULL); 267462306a36Sopenharmony_ci if (revp) 267562306a36Sopenharmony_ci macio_chips[i].rev = *revp; 267662306a36Sopenharmony_ci printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n", 267762306a36Sopenharmony_ci macio_names[type], macio_chips[i].rev, macio_chips[i].base); 267862306a36Sopenharmony_ci 267962306a36Sopenharmony_ci return; 268062306a36Sopenharmony_ci 268162306a36Sopenharmony_ciout_put: 268262306a36Sopenharmony_ci of_node_put(node); 268362306a36Sopenharmony_ci} 268462306a36Sopenharmony_ci 268562306a36Sopenharmony_cistatic int __init 268662306a36Sopenharmony_ciprobe_macios(void) 268762306a36Sopenharmony_ci{ 268862306a36Sopenharmony_ci /* Warning, ordering is important */ 268962306a36Sopenharmony_ci probe_one_macio("gc", NULL, macio_grand_central); 269062306a36Sopenharmony_ci probe_one_macio("ohare", NULL, macio_ohare); 269162306a36Sopenharmony_ci probe_one_macio("pci106b,7", NULL, macio_ohareII); 269262306a36Sopenharmony_ci probe_one_macio("mac-io", "keylargo", macio_keylargo); 269362306a36Sopenharmony_ci probe_one_macio("mac-io", "paddington", macio_paddington); 269462306a36Sopenharmony_ci probe_one_macio("mac-io", "gatwick", macio_gatwick); 269562306a36Sopenharmony_ci probe_one_macio("mac-io", "heathrow", macio_heathrow); 269662306a36Sopenharmony_ci probe_one_macio("mac-io", "K2-Keylargo", macio_keylargo2); 269762306a36Sopenharmony_ci 269862306a36Sopenharmony_ci /* Make sure the "main" macio chip appear first */ 269962306a36Sopenharmony_ci if (macio_chips[0].type == macio_gatwick 270062306a36Sopenharmony_ci && macio_chips[1].type == macio_heathrow) { 270162306a36Sopenharmony_ci struct macio_chip temp = macio_chips[0]; 270262306a36Sopenharmony_ci macio_chips[0] = macio_chips[1]; 270362306a36Sopenharmony_ci macio_chips[1] = temp; 270462306a36Sopenharmony_ci } 270562306a36Sopenharmony_ci if (macio_chips[0].type == macio_ohareII 270662306a36Sopenharmony_ci && macio_chips[1].type == macio_ohare) { 270762306a36Sopenharmony_ci struct macio_chip temp = macio_chips[0]; 270862306a36Sopenharmony_ci macio_chips[0] = macio_chips[1]; 270962306a36Sopenharmony_ci macio_chips[1] = temp; 271062306a36Sopenharmony_ci } 271162306a36Sopenharmony_ci macio_chips[0].lbus.index = 0; 271262306a36Sopenharmony_ci macio_chips[1].lbus.index = 1; 271362306a36Sopenharmony_ci 271462306a36Sopenharmony_ci return (macio_chips[0].of_node == NULL) ? -ENODEV : 0; 271562306a36Sopenharmony_ci} 271662306a36Sopenharmony_ci 271762306a36Sopenharmony_cistatic void __init 271862306a36Sopenharmony_ciinitial_serial_shutdown(struct device_node *np) 271962306a36Sopenharmony_ci{ 272062306a36Sopenharmony_ci int len; 272162306a36Sopenharmony_ci const struct slot_names_prop { 272262306a36Sopenharmony_ci int count; 272362306a36Sopenharmony_ci char name[1]; 272462306a36Sopenharmony_ci } *slots; 272562306a36Sopenharmony_ci const char *conn; 272662306a36Sopenharmony_ci int port_type = PMAC_SCC_ASYNC; 272762306a36Sopenharmony_ci int modem = 0; 272862306a36Sopenharmony_ci 272962306a36Sopenharmony_ci slots = of_get_property(np, "slot-names", &len); 273062306a36Sopenharmony_ci conn = of_get_property(np, "AAPL,connector", &len); 273162306a36Sopenharmony_ci if (conn && (strcmp(conn, "infrared") == 0)) 273262306a36Sopenharmony_ci port_type = PMAC_SCC_IRDA; 273362306a36Sopenharmony_ci else if (of_device_is_compatible(np, "cobalt")) 273462306a36Sopenharmony_ci modem = 1; 273562306a36Sopenharmony_ci else if (slots && slots->count > 0) { 273662306a36Sopenharmony_ci if (strcmp(slots->name, "IrDA") == 0) 273762306a36Sopenharmony_ci port_type = PMAC_SCC_IRDA; 273862306a36Sopenharmony_ci else if (strcmp(slots->name, "Modem") == 0) 273962306a36Sopenharmony_ci modem = 1; 274062306a36Sopenharmony_ci } 274162306a36Sopenharmony_ci if (modem) 274262306a36Sopenharmony_ci pmac_call_feature(PMAC_FTR_MODEM_ENABLE, np, 0, 0); 274362306a36Sopenharmony_ci pmac_call_feature(PMAC_FTR_SCC_ENABLE, np, port_type, 0); 274462306a36Sopenharmony_ci} 274562306a36Sopenharmony_ci 274662306a36Sopenharmony_cistatic void __init 274762306a36Sopenharmony_ciset_initial_features(void) 274862306a36Sopenharmony_ci{ 274962306a36Sopenharmony_ci struct device_node *np; 275062306a36Sopenharmony_ci 275162306a36Sopenharmony_ci /* That hack appears to be necessary for some StarMax motherboards 275262306a36Sopenharmony_ci * but I'm not too sure it was audited for side-effects on other 275362306a36Sopenharmony_ci * ohare based machines... 275462306a36Sopenharmony_ci * Since I still have difficulties figuring the right way to 275562306a36Sopenharmony_ci * differentiate them all and since that hack was there for a long 275662306a36Sopenharmony_ci * time, I'll keep it around 275762306a36Sopenharmony_ci */ 275862306a36Sopenharmony_ci if (macio_chips[0].type == macio_ohare) { 275962306a36Sopenharmony_ci struct macio_chip *macio = &macio_chips[0]; 276062306a36Sopenharmony_ci np = of_find_node_by_name(NULL, "via-pmu"); 276162306a36Sopenharmony_ci if (np) 276262306a36Sopenharmony_ci MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); 276362306a36Sopenharmony_ci else 276462306a36Sopenharmony_ci MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES); 276562306a36Sopenharmony_ci of_node_put(np); 276662306a36Sopenharmony_ci } else if (macio_chips[1].type == macio_ohare) { 276762306a36Sopenharmony_ci struct macio_chip *macio = &macio_chips[1]; 276862306a36Sopenharmony_ci MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); 276962306a36Sopenharmony_ci } 277062306a36Sopenharmony_ci 277162306a36Sopenharmony_ci#ifdef CONFIG_PPC64 277262306a36Sopenharmony_ci if (macio_chips[0].type == macio_keylargo2 || 277362306a36Sopenharmony_ci macio_chips[0].type == macio_shasta) { 277462306a36Sopenharmony_ci#ifndef CONFIG_SMP 277562306a36Sopenharmony_ci /* On SMP machines running UP, we have the second CPU eating 277662306a36Sopenharmony_ci * bus cycles. We need to take it off the bus. This is done 277762306a36Sopenharmony_ci * from pmac_smp for SMP kernels running on one CPU 277862306a36Sopenharmony_ci */ 277962306a36Sopenharmony_ci np = of_find_node_by_type(NULL, "cpu"); 278062306a36Sopenharmony_ci if (np != NULL) 278162306a36Sopenharmony_ci np = of_find_node_by_type(np, "cpu"); 278262306a36Sopenharmony_ci if (np != NULL) { 278362306a36Sopenharmony_ci g5_phy_disable_cpu1(); 278462306a36Sopenharmony_ci of_node_put(np); 278562306a36Sopenharmony_ci } 278662306a36Sopenharmony_ci#endif /* CONFIG_SMP */ 278762306a36Sopenharmony_ci /* Enable GMAC for now for PCI probing. It will be disabled 278862306a36Sopenharmony_ci * later on after PCI probe 278962306a36Sopenharmony_ci */ 279062306a36Sopenharmony_ci for_each_node_by_name(np, "ethernet") 279162306a36Sopenharmony_ci if (of_device_is_compatible(np, "K2-GMAC")) 279262306a36Sopenharmony_ci g5_gmac_enable(np, 0, 1); 279362306a36Sopenharmony_ci 279462306a36Sopenharmony_ci /* Enable FW before PCI probe. Will be disabled later on 279562306a36Sopenharmony_ci * Note: We should have a batter way to check that we are 279662306a36Sopenharmony_ci * dealing with uninorth internal cell and not a PCI cell 279762306a36Sopenharmony_ci * on the external PCI. The code below works though. 279862306a36Sopenharmony_ci */ 279962306a36Sopenharmony_ci for_each_node_by_name(np, "firewire") { 280062306a36Sopenharmony_ci if (of_device_is_compatible(np, "pci106b,5811")) { 280162306a36Sopenharmony_ci macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; 280262306a36Sopenharmony_ci g5_fw_enable(np, 0, 1); 280362306a36Sopenharmony_ci } 280462306a36Sopenharmony_ci } 280562306a36Sopenharmony_ci } 280662306a36Sopenharmony_ci#else /* CONFIG_PPC64 */ 280762306a36Sopenharmony_ci 280862306a36Sopenharmony_ci if (macio_chips[0].type == macio_keylargo || 280962306a36Sopenharmony_ci macio_chips[0].type == macio_pangea || 281062306a36Sopenharmony_ci macio_chips[0].type == macio_intrepid) { 281162306a36Sopenharmony_ci /* Enable GMAC for now for PCI probing. It will be disabled 281262306a36Sopenharmony_ci * later on after PCI probe 281362306a36Sopenharmony_ci */ 281462306a36Sopenharmony_ci for_each_node_by_name(np, "ethernet") { 281562306a36Sopenharmony_ci if (np->parent 281662306a36Sopenharmony_ci && of_device_is_compatible(np->parent, "uni-north") 281762306a36Sopenharmony_ci && of_device_is_compatible(np, "gmac")) 281862306a36Sopenharmony_ci core99_gmac_enable(np, 0, 1); 281962306a36Sopenharmony_ci } 282062306a36Sopenharmony_ci 282162306a36Sopenharmony_ci /* Enable FW before PCI probe. Will be disabled later on 282262306a36Sopenharmony_ci * Note: We should have a batter way to check that we are 282362306a36Sopenharmony_ci * dealing with uninorth internal cell and not a PCI cell 282462306a36Sopenharmony_ci * on the external PCI. The code below works though. 282562306a36Sopenharmony_ci */ 282662306a36Sopenharmony_ci for_each_node_by_name(np, "firewire") { 282762306a36Sopenharmony_ci if (np->parent 282862306a36Sopenharmony_ci && of_device_is_compatible(np->parent, "uni-north") 282962306a36Sopenharmony_ci && (of_device_is_compatible(np, "pci106b,18") || 283062306a36Sopenharmony_ci of_device_is_compatible(np, "pci106b,30") || 283162306a36Sopenharmony_ci of_device_is_compatible(np, "pci11c1,5811"))) { 283262306a36Sopenharmony_ci macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; 283362306a36Sopenharmony_ci core99_firewire_enable(np, 0, 1); 283462306a36Sopenharmony_ci } 283562306a36Sopenharmony_ci } 283662306a36Sopenharmony_ci 283762306a36Sopenharmony_ci /* Enable ATA-100 before PCI probe. */ 283862306a36Sopenharmony_ci for_each_node_by_name(np, "ata-6") { 283962306a36Sopenharmony_ci if (np->parent 284062306a36Sopenharmony_ci && of_device_is_compatible(np->parent, "uni-north") 284162306a36Sopenharmony_ci && of_device_is_compatible(np, "kauai-ata")) { 284262306a36Sopenharmony_ci core99_ata100_enable(np, 1); 284362306a36Sopenharmony_ci } 284462306a36Sopenharmony_ci } 284562306a36Sopenharmony_ci 284662306a36Sopenharmony_ci /* Switch airport off */ 284762306a36Sopenharmony_ci for_each_node_by_name(np, "radio") { 284862306a36Sopenharmony_ci if (np->parent == macio_chips[0].of_node) { 284962306a36Sopenharmony_ci macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON; 285062306a36Sopenharmony_ci core99_airport_enable(np, 0, 0); 285162306a36Sopenharmony_ci } 285262306a36Sopenharmony_ci } 285362306a36Sopenharmony_ci } 285462306a36Sopenharmony_ci 285562306a36Sopenharmony_ci /* On all machines that support sound PM, switch sound off */ 285662306a36Sopenharmony_ci if (macio_chips[0].of_node) 285762306a36Sopenharmony_ci pmac_do_feature_call(PMAC_FTR_SOUND_CHIP_ENABLE, 285862306a36Sopenharmony_ci macio_chips[0].of_node, 0, 0); 285962306a36Sopenharmony_ci 286062306a36Sopenharmony_ci /* While on some desktop G3s, we turn it back on */ 286162306a36Sopenharmony_ci if (macio_chips[0].of_node && macio_chips[0].type == macio_heathrow 286262306a36Sopenharmony_ci && (pmac_mb.model_id == PMAC_TYPE_GOSSAMER || 286362306a36Sopenharmony_ci pmac_mb.model_id == PMAC_TYPE_SILK)) { 286462306a36Sopenharmony_ci struct macio_chip *macio = &macio_chips[0]; 286562306a36Sopenharmony_ci MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); 286662306a36Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N); 286762306a36Sopenharmony_ci } 286862306a36Sopenharmony_ci 286962306a36Sopenharmony_ci#endif /* CONFIG_PPC64 */ 287062306a36Sopenharmony_ci 287162306a36Sopenharmony_ci /* On all machines, switch modem & serial ports off */ 287262306a36Sopenharmony_ci for_each_node_by_name(np, "ch-a") 287362306a36Sopenharmony_ci initial_serial_shutdown(np); 287462306a36Sopenharmony_ci for_each_node_by_name(np, "ch-b") 287562306a36Sopenharmony_ci initial_serial_shutdown(np); 287662306a36Sopenharmony_ci} 287762306a36Sopenharmony_ci 287862306a36Sopenharmony_civoid __init 287962306a36Sopenharmony_cipmac_feature_init(void) 288062306a36Sopenharmony_ci{ 288162306a36Sopenharmony_ci /* Detect the UniNorth memory controller */ 288262306a36Sopenharmony_ci probe_uninorth(); 288362306a36Sopenharmony_ci 288462306a36Sopenharmony_ci /* Probe mac-io controllers */ 288562306a36Sopenharmony_ci if (probe_macios()) { 288662306a36Sopenharmony_ci printk(KERN_WARNING "No mac-io chip found\n"); 288762306a36Sopenharmony_ci return; 288862306a36Sopenharmony_ci } 288962306a36Sopenharmony_ci 289062306a36Sopenharmony_ci /* Probe machine type */ 289162306a36Sopenharmony_ci if (probe_motherboard()) 289262306a36Sopenharmony_ci printk(KERN_WARNING "Unknown PowerMac !\n"); 289362306a36Sopenharmony_ci 289462306a36Sopenharmony_ci /* Set some initial features (turn off some chips that will 289562306a36Sopenharmony_ci * be later turned on) 289662306a36Sopenharmony_ci */ 289762306a36Sopenharmony_ci set_initial_features(); 289862306a36Sopenharmony_ci} 289962306a36Sopenharmony_ci 290062306a36Sopenharmony_ci#if 0 290162306a36Sopenharmony_cistatic void dump_HT_speeds(char *name, u32 cfg, u32 frq) 290262306a36Sopenharmony_ci{ 290362306a36Sopenharmony_ci int freqs[16] = { 200,300,400,500,600,800,1000,0,0,0,0,0,0,0,0,0 }; 290462306a36Sopenharmony_ci int bits[8] = { 8,16,0,32,2,4,0,0 }; 290562306a36Sopenharmony_ci int freq = (frq >> 8) & 0xf; 290662306a36Sopenharmony_ci 290762306a36Sopenharmony_ci if (freqs[freq] == 0) 290862306a36Sopenharmony_ci printk("%s: Unknown HT link frequency %x\n", name, freq); 290962306a36Sopenharmony_ci else 291062306a36Sopenharmony_ci printk("%s: %d MHz on main link, (%d in / %d out) bits width\n", 291162306a36Sopenharmony_ci name, freqs[freq], 291262306a36Sopenharmony_ci bits[(cfg >> 28) & 0x7], bits[(cfg >> 24) & 0x7]); 291362306a36Sopenharmony_ci} 291462306a36Sopenharmony_ci 291562306a36Sopenharmony_civoid __init pmac_check_ht_link(void) 291662306a36Sopenharmony_ci{ 291762306a36Sopenharmony_ci u32 ufreq, freq, ucfg, cfg; 291862306a36Sopenharmony_ci struct device_node *pcix_node; 291962306a36Sopenharmony_ci u8 px_bus, px_devfn; 292062306a36Sopenharmony_ci struct pci_controller *px_hose; 292162306a36Sopenharmony_ci 292262306a36Sopenharmony_ci (void)in_be32(u3_ht_base + U3_HT_LINK_COMMAND); 292362306a36Sopenharmony_ci ucfg = cfg = in_be32(u3_ht_base + U3_HT_LINK_CONFIG); 292462306a36Sopenharmony_ci ufreq = freq = in_be32(u3_ht_base + U3_HT_LINK_FREQ); 292562306a36Sopenharmony_ci dump_HT_speeds("U3 HyperTransport", cfg, freq); 292662306a36Sopenharmony_ci 292762306a36Sopenharmony_ci pcix_node = of_find_compatible_node(NULL, "pci", "pci-x"); 292862306a36Sopenharmony_ci if (pcix_node == NULL) { 292962306a36Sopenharmony_ci printk("No PCI-X bridge found\n"); 293062306a36Sopenharmony_ci return; 293162306a36Sopenharmony_ci } 293262306a36Sopenharmony_ci if (pci_device_from_OF_node(pcix_node, &px_bus, &px_devfn) != 0) { 293362306a36Sopenharmony_ci printk("PCI-X bridge found but not matched to pci\n"); 293462306a36Sopenharmony_ci return; 293562306a36Sopenharmony_ci } 293662306a36Sopenharmony_ci px_hose = pci_find_hose_for_OF_device(pcix_node); 293762306a36Sopenharmony_ci if (px_hose == NULL) { 293862306a36Sopenharmony_ci printk("PCI-X bridge found but not matched to host\n"); 293962306a36Sopenharmony_ci return; 294062306a36Sopenharmony_ci } 294162306a36Sopenharmony_ci early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg); 294262306a36Sopenharmony_ci early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq); 294362306a36Sopenharmony_ci dump_HT_speeds("PCI-X HT Uplink", cfg, freq); 294462306a36Sopenharmony_ci early_read_config_dword(px_hose, px_bus, px_devfn, 0xc8, &cfg); 294562306a36Sopenharmony_ci early_read_config_dword(px_hose, px_bus, px_devfn, 0xd0, &freq); 294662306a36Sopenharmony_ci dump_HT_speeds("PCI-X HT Downlink", cfg, freq); 294762306a36Sopenharmony_ci} 294862306a36Sopenharmony_ci#endif /* 0 */ 294962306a36Sopenharmony_ci 295062306a36Sopenharmony_ci/* 295162306a36Sopenharmony_ci * Early video resume hook 295262306a36Sopenharmony_ci */ 295362306a36Sopenharmony_ci 295462306a36Sopenharmony_cistatic void (*pmac_early_vresume_proc)(void *data); 295562306a36Sopenharmony_cistatic void *pmac_early_vresume_data; 295662306a36Sopenharmony_ci 295762306a36Sopenharmony_civoid pmac_set_early_video_resume(void (*proc)(void *data), void *data) 295862306a36Sopenharmony_ci{ 295962306a36Sopenharmony_ci if (!machine_is(powermac)) 296062306a36Sopenharmony_ci return; 296162306a36Sopenharmony_ci preempt_disable(); 296262306a36Sopenharmony_ci pmac_early_vresume_proc = proc; 296362306a36Sopenharmony_ci pmac_early_vresume_data = data; 296462306a36Sopenharmony_ci preempt_enable(); 296562306a36Sopenharmony_ci} 296662306a36Sopenharmony_ciEXPORT_SYMBOL(pmac_set_early_video_resume); 296762306a36Sopenharmony_ci 296862306a36Sopenharmony_civoid pmac_call_early_video_resume(void) 296962306a36Sopenharmony_ci{ 297062306a36Sopenharmony_ci if (pmac_early_vresume_proc) 297162306a36Sopenharmony_ci pmac_early_vresume_proc(pmac_early_vresume_data); 297262306a36Sopenharmony_ci} 297362306a36Sopenharmony_ci 297462306a36Sopenharmony_ci/* 297562306a36Sopenharmony_ci * AGP related suspend/resume code 297662306a36Sopenharmony_ci */ 297762306a36Sopenharmony_ci 297862306a36Sopenharmony_cistatic struct pci_dev *pmac_agp_bridge; 297962306a36Sopenharmony_cistatic int (*pmac_agp_suspend)(struct pci_dev *bridge); 298062306a36Sopenharmony_cistatic int (*pmac_agp_resume)(struct pci_dev *bridge); 298162306a36Sopenharmony_ci 298262306a36Sopenharmony_civoid pmac_register_agp_pm(struct pci_dev *bridge, 298362306a36Sopenharmony_ci int (*suspend)(struct pci_dev *bridge), 298462306a36Sopenharmony_ci int (*resume)(struct pci_dev *bridge)) 298562306a36Sopenharmony_ci{ 298662306a36Sopenharmony_ci if (suspend || resume) { 298762306a36Sopenharmony_ci pmac_agp_bridge = bridge; 298862306a36Sopenharmony_ci pmac_agp_suspend = suspend; 298962306a36Sopenharmony_ci pmac_agp_resume = resume; 299062306a36Sopenharmony_ci return; 299162306a36Sopenharmony_ci } 299262306a36Sopenharmony_ci if (bridge != pmac_agp_bridge) 299362306a36Sopenharmony_ci return; 299462306a36Sopenharmony_ci pmac_agp_suspend = pmac_agp_resume = NULL; 299562306a36Sopenharmony_ci return; 299662306a36Sopenharmony_ci} 299762306a36Sopenharmony_ciEXPORT_SYMBOL(pmac_register_agp_pm); 299862306a36Sopenharmony_ci 299962306a36Sopenharmony_civoid pmac_suspend_agp_for_card(struct pci_dev *dev) 300062306a36Sopenharmony_ci{ 300162306a36Sopenharmony_ci if (pmac_agp_bridge == NULL || pmac_agp_suspend == NULL) 300262306a36Sopenharmony_ci return; 300362306a36Sopenharmony_ci if (pmac_agp_bridge->bus != dev->bus) 300462306a36Sopenharmony_ci return; 300562306a36Sopenharmony_ci pmac_agp_suspend(pmac_agp_bridge); 300662306a36Sopenharmony_ci} 300762306a36Sopenharmony_ciEXPORT_SYMBOL(pmac_suspend_agp_for_card); 300862306a36Sopenharmony_ci 300962306a36Sopenharmony_civoid pmac_resume_agp_for_card(struct pci_dev *dev) 301062306a36Sopenharmony_ci{ 301162306a36Sopenharmony_ci if (pmac_agp_bridge == NULL || pmac_agp_resume == NULL) 301262306a36Sopenharmony_ci return; 301362306a36Sopenharmony_ci if (pmac_agp_bridge->bus != dev->bus) 301462306a36Sopenharmony_ci return; 301562306a36Sopenharmony_ci pmac_agp_resume(pmac_agp_bridge); 301662306a36Sopenharmony_ci} 301762306a36Sopenharmony_ciEXPORT_SYMBOL(pmac_resume_agp_for_card); 301862306a36Sopenharmony_ci 301962306a36Sopenharmony_ciint pmac_get_uninorth_variant(void) 302062306a36Sopenharmony_ci{ 302162306a36Sopenharmony_ci return uninorth_maj; 302262306a36Sopenharmony_ci} 3023