18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au) 48c2ecf20Sopenharmony_ci * Ben. Herrenschmidt (benh@kernel.crashing.org) 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * TODO: 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * - Replace mdelay with some schedule loop if possible 98c2ecf20Sopenharmony_ci * - Shorten some obfuscated delays on some routines (like modem 108c2ecf20Sopenharmony_ci * power) 118c2ecf20Sopenharmony_ci * - Refcount some clocks (see darwin) 128c2ecf20Sopenharmony_ci * - Split split split... 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci#include <linux/types.h> 158c2ecf20Sopenharmony_ci#include <linux/init.h> 168c2ecf20Sopenharmony_ci#include <linux/delay.h> 178c2ecf20Sopenharmony_ci#include <linux/kernel.h> 188c2ecf20Sopenharmony_ci#include <linux/sched.h> 198c2ecf20Sopenharmony_ci#include <linux/of.h> 208c2ecf20Sopenharmony_ci#include <linux/of_address.h> 218c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 228c2ecf20Sopenharmony_ci#include <linux/adb.h> 238c2ecf20Sopenharmony_ci#include <linux/pmu.h> 248c2ecf20Sopenharmony_ci#include <linux/ioport.h> 258c2ecf20Sopenharmony_ci#include <linux/export.h> 268c2ecf20Sopenharmony_ci#include <linux/pci.h> 278c2ecf20Sopenharmony_ci#include <asm/sections.h> 288c2ecf20Sopenharmony_ci#include <asm/errno.h> 298c2ecf20Sopenharmony_ci#include <asm/ohare.h> 308c2ecf20Sopenharmony_ci#include <asm/heathrow.h> 318c2ecf20Sopenharmony_ci#include <asm/keylargo.h> 328c2ecf20Sopenharmony_ci#include <asm/uninorth.h> 338c2ecf20Sopenharmony_ci#include <asm/io.h> 348c2ecf20Sopenharmony_ci#include <asm/prom.h> 358c2ecf20Sopenharmony_ci#include <asm/machdep.h> 368c2ecf20Sopenharmony_ci#include <asm/pmac_feature.h> 378c2ecf20Sopenharmony_ci#include <asm/dbdma.h> 388c2ecf20Sopenharmony_ci#include <asm/pci-bridge.h> 398c2ecf20Sopenharmony_ci#include <asm/pmac_low_i2c.h> 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#undef DEBUG_FEATURE 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#ifdef DEBUG_FEATURE 448c2ecf20Sopenharmony_ci#define DBG(fmt...) printk(KERN_DEBUG fmt) 458c2ecf20Sopenharmony_ci#else 468c2ecf20Sopenharmony_ci#define DBG(fmt...) 478c2ecf20Sopenharmony_ci#endif 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S_32 508c2ecf20Sopenharmony_ciextern int powersave_lowspeed; 518c2ecf20Sopenharmony_ci#endif 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ciextern int powersave_nap; 548c2ecf20Sopenharmony_ciextern struct device_node *k2_skiplist[2]; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci/* 578c2ecf20Sopenharmony_ci * We use a single global lock to protect accesses. Each driver has 588c2ecf20Sopenharmony_ci * to take care of its own locking 598c2ecf20Sopenharmony_ci */ 608c2ecf20Sopenharmony_ciDEFINE_RAW_SPINLOCK(feature_lock); 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci#define LOCK(flags) raw_spin_lock_irqsave(&feature_lock, flags); 638c2ecf20Sopenharmony_ci#define UNLOCK(flags) raw_spin_unlock_irqrestore(&feature_lock, flags); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci/* 678c2ecf20Sopenharmony_ci * Instance of some macio stuffs 688c2ecf20Sopenharmony_ci */ 698c2ecf20Sopenharmony_cistruct macio_chip macio_chips[MAX_MACIO_CHIPS]; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_cistruct macio_chip *macio_find(struct device_node *child, int type) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci while(child) { 748c2ecf20Sopenharmony_ci int i; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci for (i=0; i < MAX_MACIO_CHIPS && macio_chips[i].of_node; i++) 778c2ecf20Sopenharmony_ci if (child == macio_chips[i].of_node && 788c2ecf20Sopenharmony_ci (!type || macio_chips[i].type == type)) 798c2ecf20Sopenharmony_ci return &macio_chips[i]; 808c2ecf20Sopenharmony_ci child = child->parent; 818c2ecf20Sopenharmony_ci } 828c2ecf20Sopenharmony_ci return NULL; 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(macio_find); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistatic const char *macio_names[] = 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci "Unknown", 898c2ecf20Sopenharmony_ci "Grand Central", 908c2ecf20Sopenharmony_ci "OHare", 918c2ecf20Sopenharmony_ci "OHareII", 928c2ecf20Sopenharmony_ci "Heathrow", 938c2ecf20Sopenharmony_ci "Gatwick", 948c2ecf20Sopenharmony_ci "Paddington", 958c2ecf20Sopenharmony_ci "Keylargo", 968c2ecf20Sopenharmony_ci "Pangea", 978c2ecf20Sopenharmony_ci "Intrepid", 988c2ecf20Sopenharmony_ci "K2", 998c2ecf20Sopenharmony_ci "Shasta", 1008c2ecf20Sopenharmony_ci}; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistruct device_node *uninorth_node; 1048c2ecf20Sopenharmony_ciu32 __iomem *uninorth_base; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cistatic u32 uninorth_rev; 1078c2ecf20Sopenharmony_cistatic int uninorth_maj; 1088c2ecf20Sopenharmony_cistatic void __iomem *u3_ht_base; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci/* 1118c2ecf20Sopenharmony_ci * For each motherboard family, we have a table of functions pointers 1128c2ecf20Sopenharmony_ci * that handle the various features. 1138c2ecf20Sopenharmony_ci */ 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_citypedef long (*feature_call)(struct device_node *node, long param, long value); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistruct feature_table_entry { 1188c2ecf20Sopenharmony_ci unsigned int selector; 1198c2ecf20Sopenharmony_ci feature_call function; 1208c2ecf20Sopenharmony_ci}; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_cistruct pmac_mb_def 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci const char* model_string; 1258c2ecf20Sopenharmony_ci const char* model_name; 1268c2ecf20Sopenharmony_ci int model_id; 1278c2ecf20Sopenharmony_ci struct feature_table_entry* features; 1288c2ecf20Sopenharmony_ci unsigned long board_flags; 1298c2ecf20Sopenharmony_ci}; 1308c2ecf20Sopenharmony_cistatic struct pmac_mb_def pmac_mb; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci/* 1338c2ecf20Sopenharmony_ci * Here are the chip specific feature functions 1348c2ecf20Sopenharmony_ci */ 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic inline int simple_feature_tweak(struct device_node *node, int type, 1378c2ecf20Sopenharmony_ci int reg, u32 mask, int value) 1388c2ecf20Sopenharmony_ci{ 1398c2ecf20Sopenharmony_ci struct macio_chip* macio; 1408c2ecf20Sopenharmony_ci unsigned long flags; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci macio = macio_find(node, type); 1438c2ecf20Sopenharmony_ci if (!macio) 1448c2ecf20Sopenharmony_ci return -ENODEV; 1458c2ecf20Sopenharmony_ci LOCK(flags); 1468c2ecf20Sopenharmony_ci if (value) 1478c2ecf20Sopenharmony_ci MACIO_BIS(reg, mask); 1488c2ecf20Sopenharmony_ci else 1498c2ecf20Sopenharmony_ci MACIO_BIC(reg, mask); 1508c2ecf20Sopenharmony_ci (void)MACIO_IN32(reg); 1518c2ecf20Sopenharmony_ci UNLOCK(flags); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci return 0; 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci#ifndef CONFIG_PPC64 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cistatic long ohare_htw_scc_enable(struct device_node *node, long param, 1598c2ecf20Sopenharmony_ci long value) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci struct macio_chip* macio; 1628c2ecf20Sopenharmony_ci unsigned long chan_mask; 1638c2ecf20Sopenharmony_ci unsigned long fcr; 1648c2ecf20Sopenharmony_ci unsigned long flags; 1658c2ecf20Sopenharmony_ci int htw, trans; 1668c2ecf20Sopenharmony_ci unsigned long rmask; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci macio = macio_find(node, 0); 1698c2ecf20Sopenharmony_ci if (!macio) 1708c2ecf20Sopenharmony_ci return -ENODEV; 1718c2ecf20Sopenharmony_ci if (of_node_name_eq(node, "ch-a")) 1728c2ecf20Sopenharmony_ci chan_mask = MACIO_FLAG_SCCA_ON; 1738c2ecf20Sopenharmony_ci else if (of_node_name_eq(node, "ch-b")) 1748c2ecf20Sopenharmony_ci chan_mask = MACIO_FLAG_SCCB_ON; 1758c2ecf20Sopenharmony_ci else 1768c2ecf20Sopenharmony_ci return -ENODEV; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci htw = (macio->type == macio_heathrow || macio->type == macio_paddington 1798c2ecf20Sopenharmony_ci || macio->type == macio_gatwick); 1808c2ecf20Sopenharmony_ci /* On these machines, the HRW_SCC_TRANS_EN_N bit mustn't be touched */ 1818c2ecf20Sopenharmony_ci trans = (pmac_mb.model_id != PMAC_TYPE_YOSEMITE && 1828c2ecf20Sopenharmony_ci pmac_mb.model_id != PMAC_TYPE_YIKES); 1838c2ecf20Sopenharmony_ci if (value) { 1848c2ecf20Sopenharmony_ci#ifdef CONFIG_ADB_PMU 1858c2ecf20Sopenharmony_ci if ((param & 0xfff) == PMAC_SCC_IRDA) 1868c2ecf20Sopenharmony_ci pmu_enable_irled(1); 1878c2ecf20Sopenharmony_ci#endif /* CONFIG_ADB_PMU */ 1888c2ecf20Sopenharmony_ci LOCK(flags); 1898c2ecf20Sopenharmony_ci fcr = MACIO_IN32(OHARE_FCR); 1908c2ecf20Sopenharmony_ci /* Check if scc cell need enabling */ 1918c2ecf20Sopenharmony_ci if (!(fcr & OH_SCC_ENABLE)) { 1928c2ecf20Sopenharmony_ci fcr |= OH_SCC_ENABLE; 1938c2ecf20Sopenharmony_ci if (htw) { 1948c2ecf20Sopenharmony_ci /* Side effect: this will also power up the 1958c2ecf20Sopenharmony_ci * modem, but it's too messy to figure out on which 1968c2ecf20Sopenharmony_ci * ports this controls the transceiver and on which 1978c2ecf20Sopenharmony_ci * it controls the modem 1988c2ecf20Sopenharmony_ci */ 1998c2ecf20Sopenharmony_ci if (trans) 2008c2ecf20Sopenharmony_ci fcr &= ~HRW_SCC_TRANS_EN_N; 2018c2ecf20Sopenharmony_ci MACIO_OUT32(OHARE_FCR, fcr); 2028c2ecf20Sopenharmony_ci fcr |= (rmask = HRW_RESET_SCC); 2038c2ecf20Sopenharmony_ci MACIO_OUT32(OHARE_FCR, fcr); 2048c2ecf20Sopenharmony_ci } else { 2058c2ecf20Sopenharmony_ci fcr |= (rmask = OH_SCC_RESET); 2068c2ecf20Sopenharmony_ci MACIO_OUT32(OHARE_FCR, fcr); 2078c2ecf20Sopenharmony_ci } 2088c2ecf20Sopenharmony_ci UNLOCK(flags); 2098c2ecf20Sopenharmony_ci (void)MACIO_IN32(OHARE_FCR); 2108c2ecf20Sopenharmony_ci mdelay(15); 2118c2ecf20Sopenharmony_ci LOCK(flags); 2128c2ecf20Sopenharmony_ci fcr &= ~rmask; 2138c2ecf20Sopenharmony_ci MACIO_OUT32(OHARE_FCR, fcr); 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci if (chan_mask & MACIO_FLAG_SCCA_ON) 2168c2ecf20Sopenharmony_ci fcr |= OH_SCCA_IO; 2178c2ecf20Sopenharmony_ci if (chan_mask & MACIO_FLAG_SCCB_ON) 2188c2ecf20Sopenharmony_ci fcr |= OH_SCCB_IO; 2198c2ecf20Sopenharmony_ci MACIO_OUT32(OHARE_FCR, fcr); 2208c2ecf20Sopenharmony_ci macio->flags |= chan_mask; 2218c2ecf20Sopenharmony_ci UNLOCK(flags); 2228c2ecf20Sopenharmony_ci if (param & PMAC_SCC_FLAG_XMON) 2238c2ecf20Sopenharmony_ci macio->flags |= MACIO_FLAG_SCC_LOCKED; 2248c2ecf20Sopenharmony_ci } else { 2258c2ecf20Sopenharmony_ci if (macio->flags & MACIO_FLAG_SCC_LOCKED) 2268c2ecf20Sopenharmony_ci return -EPERM; 2278c2ecf20Sopenharmony_ci LOCK(flags); 2288c2ecf20Sopenharmony_ci fcr = MACIO_IN32(OHARE_FCR); 2298c2ecf20Sopenharmony_ci if (chan_mask & MACIO_FLAG_SCCA_ON) 2308c2ecf20Sopenharmony_ci fcr &= ~OH_SCCA_IO; 2318c2ecf20Sopenharmony_ci if (chan_mask & MACIO_FLAG_SCCB_ON) 2328c2ecf20Sopenharmony_ci fcr &= ~OH_SCCB_IO; 2338c2ecf20Sopenharmony_ci MACIO_OUT32(OHARE_FCR, fcr); 2348c2ecf20Sopenharmony_ci if ((fcr & (OH_SCCA_IO | OH_SCCB_IO)) == 0) { 2358c2ecf20Sopenharmony_ci fcr &= ~OH_SCC_ENABLE; 2368c2ecf20Sopenharmony_ci if (htw && trans) 2378c2ecf20Sopenharmony_ci fcr |= HRW_SCC_TRANS_EN_N; 2388c2ecf20Sopenharmony_ci MACIO_OUT32(OHARE_FCR, fcr); 2398c2ecf20Sopenharmony_ci } 2408c2ecf20Sopenharmony_ci macio->flags &= ~(chan_mask); 2418c2ecf20Sopenharmony_ci UNLOCK(flags); 2428c2ecf20Sopenharmony_ci mdelay(10); 2438c2ecf20Sopenharmony_ci#ifdef CONFIG_ADB_PMU 2448c2ecf20Sopenharmony_ci if ((param & 0xfff) == PMAC_SCC_IRDA) 2458c2ecf20Sopenharmony_ci pmu_enable_irled(0); 2468c2ecf20Sopenharmony_ci#endif /* CONFIG_ADB_PMU */ 2478c2ecf20Sopenharmony_ci } 2488c2ecf20Sopenharmony_ci return 0; 2498c2ecf20Sopenharmony_ci} 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_cistatic long ohare_floppy_enable(struct device_node *node, long param, 2528c2ecf20Sopenharmony_ci long value) 2538c2ecf20Sopenharmony_ci{ 2548c2ecf20Sopenharmony_ci return simple_feature_tweak(node, macio_ohare, 2558c2ecf20Sopenharmony_ci OHARE_FCR, OH_FLOPPY_ENABLE, value); 2568c2ecf20Sopenharmony_ci} 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_cistatic long ohare_mesh_enable(struct device_node *node, long param, long value) 2598c2ecf20Sopenharmony_ci{ 2608c2ecf20Sopenharmony_ci return simple_feature_tweak(node, macio_ohare, 2618c2ecf20Sopenharmony_ci OHARE_FCR, OH_MESH_ENABLE, value); 2628c2ecf20Sopenharmony_ci} 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_cistatic long ohare_ide_enable(struct device_node *node, long param, long value) 2658c2ecf20Sopenharmony_ci{ 2668c2ecf20Sopenharmony_ci switch(param) { 2678c2ecf20Sopenharmony_ci case 0: 2688c2ecf20Sopenharmony_ci /* For some reason, setting the bit in set_initial_features() 2698c2ecf20Sopenharmony_ci * doesn't stick. I'm still investigating... --BenH. 2708c2ecf20Sopenharmony_ci */ 2718c2ecf20Sopenharmony_ci if (value) 2728c2ecf20Sopenharmony_ci simple_feature_tweak(node, macio_ohare, 2738c2ecf20Sopenharmony_ci OHARE_FCR, OH_IOBUS_ENABLE, 1); 2748c2ecf20Sopenharmony_ci return simple_feature_tweak(node, macio_ohare, 2758c2ecf20Sopenharmony_ci OHARE_FCR, OH_IDE0_ENABLE, value); 2768c2ecf20Sopenharmony_ci case 1: 2778c2ecf20Sopenharmony_ci return simple_feature_tweak(node, macio_ohare, 2788c2ecf20Sopenharmony_ci OHARE_FCR, OH_BAY_IDE_ENABLE, value); 2798c2ecf20Sopenharmony_ci default: 2808c2ecf20Sopenharmony_ci return -ENODEV; 2818c2ecf20Sopenharmony_ci } 2828c2ecf20Sopenharmony_ci} 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_cistatic long ohare_ide_reset(struct device_node *node, long param, long value) 2858c2ecf20Sopenharmony_ci{ 2868c2ecf20Sopenharmony_ci switch(param) { 2878c2ecf20Sopenharmony_ci case 0: 2888c2ecf20Sopenharmony_ci return simple_feature_tweak(node, macio_ohare, 2898c2ecf20Sopenharmony_ci OHARE_FCR, OH_IDE0_RESET_N, !value); 2908c2ecf20Sopenharmony_ci case 1: 2918c2ecf20Sopenharmony_ci return simple_feature_tweak(node, macio_ohare, 2928c2ecf20Sopenharmony_ci OHARE_FCR, OH_IDE1_RESET_N, !value); 2938c2ecf20Sopenharmony_ci default: 2948c2ecf20Sopenharmony_ci return -ENODEV; 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci} 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic long ohare_sleep_state(struct device_node *node, long param, long value) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci struct macio_chip* macio = &macio_chips[0]; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0) 3038c2ecf20Sopenharmony_ci return -EPERM; 3048c2ecf20Sopenharmony_ci if (value == 1) { 3058c2ecf20Sopenharmony_ci MACIO_BIC(OHARE_FCR, OH_IOBUS_ENABLE); 3068c2ecf20Sopenharmony_ci } else if (value == 0) { 3078c2ecf20Sopenharmony_ci MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); 3088c2ecf20Sopenharmony_ci } 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci return 0; 3118c2ecf20Sopenharmony_ci} 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_cistatic long heathrow_modem_enable(struct device_node *node, long param, 3148c2ecf20Sopenharmony_ci long value) 3158c2ecf20Sopenharmony_ci{ 3168c2ecf20Sopenharmony_ci struct macio_chip* macio; 3178c2ecf20Sopenharmony_ci u8 gpio; 3188c2ecf20Sopenharmony_ci unsigned long flags; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci macio = macio_find(node, macio_unknown); 3218c2ecf20Sopenharmony_ci if (!macio) 3228c2ecf20Sopenharmony_ci return -ENODEV; 3238c2ecf20Sopenharmony_ci gpio = MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1; 3248c2ecf20Sopenharmony_ci if (!value) { 3258c2ecf20Sopenharmony_ci LOCK(flags); 3268c2ecf20Sopenharmony_ci MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio); 3278c2ecf20Sopenharmony_ci UNLOCK(flags); 3288c2ecf20Sopenharmony_ci (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); 3298c2ecf20Sopenharmony_ci mdelay(250); 3308c2ecf20Sopenharmony_ci } 3318c2ecf20Sopenharmony_ci if (pmac_mb.model_id != PMAC_TYPE_YOSEMITE && 3328c2ecf20Sopenharmony_ci pmac_mb.model_id != PMAC_TYPE_YIKES) { 3338c2ecf20Sopenharmony_ci LOCK(flags); 3348c2ecf20Sopenharmony_ci if (value) 3358c2ecf20Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_SCC_TRANS_EN_N); 3368c2ecf20Sopenharmony_ci else 3378c2ecf20Sopenharmony_ci MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N); 3388c2ecf20Sopenharmony_ci UNLOCK(flags); 3398c2ecf20Sopenharmony_ci (void)MACIO_IN32(HEATHROW_FCR); 3408c2ecf20Sopenharmony_ci mdelay(250); 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci if (value) { 3438c2ecf20Sopenharmony_ci LOCK(flags); 3448c2ecf20Sopenharmony_ci MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1); 3458c2ecf20Sopenharmony_ci (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); 3468c2ecf20Sopenharmony_ci UNLOCK(flags); mdelay(250); LOCK(flags); 3478c2ecf20Sopenharmony_ci MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio); 3488c2ecf20Sopenharmony_ci (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); 3498c2ecf20Sopenharmony_ci UNLOCK(flags); mdelay(250); LOCK(flags); 3508c2ecf20Sopenharmony_ci MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1); 3518c2ecf20Sopenharmony_ci (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); 3528c2ecf20Sopenharmony_ci UNLOCK(flags); mdelay(250); 3538c2ecf20Sopenharmony_ci } 3548c2ecf20Sopenharmony_ci return 0; 3558c2ecf20Sopenharmony_ci} 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_cistatic long heathrow_floppy_enable(struct device_node *node, long param, 3588c2ecf20Sopenharmony_ci long value) 3598c2ecf20Sopenharmony_ci{ 3608c2ecf20Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 3618c2ecf20Sopenharmony_ci HEATHROW_FCR, 3628c2ecf20Sopenharmony_ci HRW_SWIM_ENABLE|HRW_BAY_FLOPPY_ENABLE, 3638c2ecf20Sopenharmony_ci value); 3648c2ecf20Sopenharmony_ci} 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_cistatic long heathrow_mesh_enable(struct device_node *node, long param, 3678c2ecf20Sopenharmony_ci long value) 3688c2ecf20Sopenharmony_ci{ 3698c2ecf20Sopenharmony_ci struct macio_chip* macio; 3708c2ecf20Sopenharmony_ci unsigned long flags; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci macio = macio_find(node, macio_unknown); 3738c2ecf20Sopenharmony_ci if (!macio) 3748c2ecf20Sopenharmony_ci return -ENODEV; 3758c2ecf20Sopenharmony_ci LOCK(flags); 3768c2ecf20Sopenharmony_ci /* Set clear mesh cell enable */ 3778c2ecf20Sopenharmony_ci if (value) 3788c2ecf20Sopenharmony_ci MACIO_BIS(HEATHROW_FCR, HRW_MESH_ENABLE); 3798c2ecf20Sopenharmony_ci else 3808c2ecf20Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_MESH_ENABLE); 3818c2ecf20Sopenharmony_ci (void)MACIO_IN32(HEATHROW_FCR); 3828c2ecf20Sopenharmony_ci udelay(10); 3838c2ecf20Sopenharmony_ci /* Set/Clear termination power */ 3848c2ecf20Sopenharmony_ci if (value) 3858c2ecf20Sopenharmony_ci MACIO_BIC(HEATHROW_MBCR, 0x04000000); 3868c2ecf20Sopenharmony_ci else 3878c2ecf20Sopenharmony_ci MACIO_BIS(HEATHROW_MBCR, 0x04000000); 3888c2ecf20Sopenharmony_ci (void)MACIO_IN32(HEATHROW_MBCR); 3898c2ecf20Sopenharmony_ci udelay(10); 3908c2ecf20Sopenharmony_ci UNLOCK(flags); 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci return 0; 3938c2ecf20Sopenharmony_ci} 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_cistatic long heathrow_ide_enable(struct device_node *node, long param, 3968c2ecf20Sopenharmony_ci long value) 3978c2ecf20Sopenharmony_ci{ 3988c2ecf20Sopenharmony_ci switch(param) { 3998c2ecf20Sopenharmony_ci case 0: 4008c2ecf20Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 4018c2ecf20Sopenharmony_ci HEATHROW_FCR, HRW_IDE0_ENABLE, value); 4028c2ecf20Sopenharmony_ci case 1: 4038c2ecf20Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 4048c2ecf20Sopenharmony_ci HEATHROW_FCR, HRW_BAY_IDE_ENABLE, value); 4058c2ecf20Sopenharmony_ci default: 4068c2ecf20Sopenharmony_ci return -ENODEV; 4078c2ecf20Sopenharmony_ci } 4088c2ecf20Sopenharmony_ci} 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_cistatic long heathrow_ide_reset(struct device_node *node, long param, 4118c2ecf20Sopenharmony_ci long value) 4128c2ecf20Sopenharmony_ci{ 4138c2ecf20Sopenharmony_ci switch(param) { 4148c2ecf20Sopenharmony_ci case 0: 4158c2ecf20Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 4168c2ecf20Sopenharmony_ci HEATHROW_FCR, HRW_IDE0_RESET_N, !value); 4178c2ecf20Sopenharmony_ci case 1: 4188c2ecf20Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 4198c2ecf20Sopenharmony_ci HEATHROW_FCR, HRW_IDE1_RESET_N, !value); 4208c2ecf20Sopenharmony_ci default: 4218c2ecf20Sopenharmony_ci return -ENODEV; 4228c2ecf20Sopenharmony_ci } 4238c2ecf20Sopenharmony_ci} 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_cistatic long heathrow_bmac_enable(struct device_node *node, long param, 4268c2ecf20Sopenharmony_ci long value) 4278c2ecf20Sopenharmony_ci{ 4288c2ecf20Sopenharmony_ci struct macio_chip* macio; 4298c2ecf20Sopenharmony_ci unsigned long flags; 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci macio = macio_find(node, 0); 4328c2ecf20Sopenharmony_ci if (!macio) 4338c2ecf20Sopenharmony_ci return -ENODEV; 4348c2ecf20Sopenharmony_ci if (value) { 4358c2ecf20Sopenharmony_ci LOCK(flags); 4368c2ecf20Sopenharmony_ci MACIO_BIS(HEATHROW_FCR, HRW_BMAC_IO_ENABLE); 4378c2ecf20Sopenharmony_ci MACIO_BIS(HEATHROW_FCR, HRW_BMAC_RESET); 4388c2ecf20Sopenharmony_ci UNLOCK(flags); 4398c2ecf20Sopenharmony_ci (void)MACIO_IN32(HEATHROW_FCR); 4408c2ecf20Sopenharmony_ci mdelay(10); 4418c2ecf20Sopenharmony_ci LOCK(flags); 4428c2ecf20Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_BMAC_RESET); 4438c2ecf20Sopenharmony_ci UNLOCK(flags); 4448c2ecf20Sopenharmony_ci (void)MACIO_IN32(HEATHROW_FCR); 4458c2ecf20Sopenharmony_ci mdelay(10); 4468c2ecf20Sopenharmony_ci } else { 4478c2ecf20Sopenharmony_ci LOCK(flags); 4488c2ecf20Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE); 4498c2ecf20Sopenharmony_ci UNLOCK(flags); 4508c2ecf20Sopenharmony_ci } 4518c2ecf20Sopenharmony_ci return 0; 4528c2ecf20Sopenharmony_ci} 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_cistatic long heathrow_sound_enable(struct device_node *node, long param, 4558c2ecf20Sopenharmony_ci long value) 4568c2ecf20Sopenharmony_ci{ 4578c2ecf20Sopenharmony_ci struct macio_chip* macio; 4588c2ecf20Sopenharmony_ci unsigned long flags; 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci /* B&W G3 and Yikes don't support that properly (the 4618c2ecf20Sopenharmony_ci * sound appear to never come back after being shut down). 4628c2ecf20Sopenharmony_ci */ 4638c2ecf20Sopenharmony_ci if (pmac_mb.model_id == PMAC_TYPE_YOSEMITE || 4648c2ecf20Sopenharmony_ci pmac_mb.model_id == PMAC_TYPE_YIKES) 4658c2ecf20Sopenharmony_ci return 0; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci macio = macio_find(node, 0); 4688c2ecf20Sopenharmony_ci if (!macio) 4698c2ecf20Sopenharmony_ci return -ENODEV; 4708c2ecf20Sopenharmony_ci if (value) { 4718c2ecf20Sopenharmony_ci LOCK(flags); 4728c2ecf20Sopenharmony_ci MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); 4738c2ecf20Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N); 4748c2ecf20Sopenharmony_ci UNLOCK(flags); 4758c2ecf20Sopenharmony_ci (void)MACIO_IN32(HEATHROW_FCR); 4768c2ecf20Sopenharmony_ci } else { 4778c2ecf20Sopenharmony_ci LOCK(flags); 4788c2ecf20Sopenharmony_ci MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N); 4798c2ecf20Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); 4808c2ecf20Sopenharmony_ci UNLOCK(flags); 4818c2ecf20Sopenharmony_ci } 4828c2ecf20Sopenharmony_ci return 0; 4838c2ecf20Sopenharmony_ci} 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_cistatic u32 save_fcr[6]; 4868c2ecf20Sopenharmony_cistatic u32 save_mbcr; 4878c2ecf20Sopenharmony_cistatic struct dbdma_regs save_dbdma[13]; 4888c2ecf20Sopenharmony_cistatic struct dbdma_regs save_alt_dbdma[13]; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_cistatic void dbdma_save(struct macio_chip *macio, struct dbdma_regs *save) 4918c2ecf20Sopenharmony_ci{ 4928c2ecf20Sopenharmony_ci int i; 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci /* Save state & config of DBDMA channels */ 4958c2ecf20Sopenharmony_ci for (i = 0; i < 13; i++) { 4968c2ecf20Sopenharmony_ci volatile struct dbdma_regs __iomem * chan = (void __iomem *) 4978c2ecf20Sopenharmony_ci (macio->base + ((0x8000+i*0x100)>>2)); 4988c2ecf20Sopenharmony_ci save[i].cmdptr_hi = in_le32(&chan->cmdptr_hi); 4998c2ecf20Sopenharmony_ci save[i].cmdptr = in_le32(&chan->cmdptr); 5008c2ecf20Sopenharmony_ci save[i].intr_sel = in_le32(&chan->intr_sel); 5018c2ecf20Sopenharmony_ci save[i].br_sel = in_le32(&chan->br_sel); 5028c2ecf20Sopenharmony_ci save[i].wait_sel = in_le32(&chan->wait_sel); 5038c2ecf20Sopenharmony_ci } 5048c2ecf20Sopenharmony_ci} 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_cistatic void dbdma_restore(struct macio_chip *macio, struct dbdma_regs *save) 5078c2ecf20Sopenharmony_ci{ 5088c2ecf20Sopenharmony_ci int i; 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci /* Save state & config of DBDMA channels */ 5118c2ecf20Sopenharmony_ci for (i = 0; i < 13; i++) { 5128c2ecf20Sopenharmony_ci volatile struct dbdma_regs __iomem * chan = (void __iomem *) 5138c2ecf20Sopenharmony_ci (macio->base + ((0x8000+i*0x100)>>2)); 5148c2ecf20Sopenharmony_ci out_le32(&chan->control, (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16); 5158c2ecf20Sopenharmony_ci while (in_le32(&chan->status) & ACTIVE) 5168c2ecf20Sopenharmony_ci mb(); 5178c2ecf20Sopenharmony_ci out_le32(&chan->cmdptr_hi, save[i].cmdptr_hi); 5188c2ecf20Sopenharmony_ci out_le32(&chan->cmdptr, save[i].cmdptr); 5198c2ecf20Sopenharmony_ci out_le32(&chan->intr_sel, save[i].intr_sel); 5208c2ecf20Sopenharmony_ci out_le32(&chan->br_sel, save[i].br_sel); 5218c2ecf20Sopenharmony_ci out_le32(&chan->wait_sel, save[i].wait_sel); 5228c2ecf20Sopenharmony_ci } 5238c2ecf20Sopenharmony_ci} 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_cistatic void heathrow_sleep(struct macio_chip *macio, int secondary) 5268c2ecf20Sopenharmony_ci{ 5278c2ecf20Sopenharmony_ci if (secondary) { 5288c2ecf20Sopenharmony_ci dbdma_save(macio, save_alt_dbdma); 5298c2ecf20Sopenharmony_ci save_fcr[2] = MACIO_IN32(0x38); 5308c2ecf20Sopenharmony_ci save_fcr[3] = MACIO_IN32(0x3c); 5318c2ecf20Sopenharmony_ci } else { 5328c2ecf20Sopenharmony_ci dbdma_save(macio, save_dbdma); 5338c2ecf20Sopenharmony_ci save_fcr[0] = MACIO_IN32(0x38); 5348c2ecf20Sopenharmony_ci save_fcr[1] = MACIO_IN32(0x3c); 5358c2ecf20Sopenharmony_ci save_mbcr = MACIO_IN32(0x34); 5368c2ecf20Sopenharmony_ci /* Make sure sound is shut down */ 5378c2ecf20Sopenharmony_ci MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N); 5388c2ecf20Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); 5398c2ecf20Sopenharmony_ci /* This seems to be necessary as well or the fan 5408c2ecf20Sopenharmony_ci * keeps coming up and battery drains fast */ 5418c2ecf20Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_IOBUS_ENABLE); 5428c2ecf20Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_IDE0_RESET_N); 5438c2ecf20Sopenharmony_ci /* Make sure eth is down even if module or sleep 5448c2ecf20Sopenharmony_ci * won't work properly */ 5458c2ecf20Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE | HRW_BMAC_RESET); 5468c2ecf20Sopenharmony_ci } 5478c2ecf20Sopenharmony_ci /* Make sure modem is shut down */ 5488c2ecf20Sopenharmony_ci MACIO_OUT8(HRW_GPIO_MODEM_RESET, 5498c2ecf20Sopenharmony_ci MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1); 5508c2ecf20Sopenharmony_ci MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N); 5518c2ecf20Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, OH_SCCA_IO|OH_SCCB_IO|HRW_SCC_ENABLE); 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci /* Let things settle */ 5548c2ecf20Sopenharmony_ci (void)MACIO_IN32(HEATHROW_FCR); 5558c2ecf20Sopenharmony_ci} 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_cistatic void heathrow_wakeup(struct macio_chip *macio, int secondary) 5588c2ecf20Sopenharmony_ci{ 5598c2ecf20Sopenharmony_ci if (secondary) { 5608c2ecf20Sopenharmony_ci MACIO_OUT32(0x38, save_fcr[2]); 5618c2ecf20Sopenharmony_ci (void)MACIO_IN32(0x38); 5628c2ecf20Sopenharmony_ci mdelay(1); 5638c2ecf20Sopenharmony_ci MACIO_OUT32(0x3c, save_fcr[3]); 5648c2ecf20Sopenharmony_ci (void)MACIO_IN32(0x38); 5658c2ecf20Sopenharmony_ci mdelay(10); 5668c2ecf20Sopenharmony_ci dbdma_restore(macio, save_alt_dbdma); 5678c2ecf20Sopenharmony_ci } else { 5688c2ecf20Sopenharmony_ci MACIO_OUT32(0x38, save_fcr[0] | HRW_IOBUS_ENABLE); 5698c2ecf20Sopenharmony_ci (void)MACIO_IN32(0x38); 5708c2ecf20Sopenharmony_ci mdelay(1); 5718c2ecf20Sopenharmony_ci MACIO_OUT32(0x3c, save_fcr[1]); 5728c2ecf20Sopenharmony_ci (void)MACIO_IN32(0x38); 5738c2ecf20Sopenharmony_ci mdelay(1); 5748c2ecf20Sopenharmony_ci MACIO_OUT32(0x34, save_mbcr); 5758c2ecf20Sopenharmony_ci (void)MACIO_IN32(0x38); 5768c2ecf20Sopenharmony_ci mdelay(10); 5778c2ecf20Sopenharmony_ci dbdma_restore(macio, save_dbdma); 5788c2ecf20Sopenharmony_ci } 5798c2ecf20Sopenharmony_ci} 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_cistatic long heathrow_sleep_state(struct device_node *node, long param, 5828c2ecf20Sopenharmony_ci long value) 5838c2ecf20Sopenharmony_ci{ 5848c2ecf20Sopenharmony_ci if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0) 5858c2ecf20Sopenharmony_ci return -EPERM; 5868c2ecf20Sopenharmony_ci if (value == 1) { 5878c2ecf20Sopenharmony_ci if (macio_chips[1].type == macio_gatwick) 5888c2ecf20Sopenharmony_ci heathrow_sleep(&macio_chips[0], 1); 5898c2ecf20Sopenharmony_ci heathrow_sleep(&macio_chips[0], 0); 5908c2ecf20Sopenharmony_ci } else if (value == 0) { 5918c2ecf20Sopenharmony_ci heathrow_wakeup(&macio_chips[0], 0); 5928c2ecf20Sopenharmony_ci if (macio_chips[1].type == macio_gatwick) 5938c2ecf20Sopenharmony_ci heathrow_wakeup(&macio_chips[0], 1); 5948c2ecf20Sopenharmony_ci } 5958c2ecf20Sopenharmony_ci return 0; 5968c2ecf20Sopenharmony_ci} 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_cistatic long core99_scc_enable(struct device_node *node, long param, long value) 5998c2ecf20Sopenharmony_ci{ 6008c2ecf20Sopenharmony_ci struct macio_chip* macio; 6018c2ecf20Sopenharmony_ci unsigned long flags; 6028c2ecf20Sopenharmony_ci unsigned long chan_mask; 6038c2ecf20Sopenharmony_ci u32 fcr; 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci macio = macio_find(node, 0); 6068c2ecf20Sopenharmony_ci if (!macio) 6078c2ecf20Sopenharmony_ci return -ENODEV; 6088c2ecf20Sopenharmony_ci if (of_node_name_eq(node, "ch-a")) 6098c2ecf20Sopenharmony_ci chan_mask = MACIO_FLAG_SCCA_ON; 6108c2ecf20Sopenharmony_ci else if (of_node_name_eq(node, "ch-b")) 6118c2ecf20Sopenharmony_ci chan_mask = MACIO_FLAG_SCCB_ON; 6128c2ecf20Sopenharmony_ci else 6138c2ecf20Sopenharmony_ci return -ENODEV; 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci if (value) { 6168c2ecf20Sopenharmony_ci int need_reset_scc = 0; 6178c2ecf20Sopenharmony_ci int need_reset_irda = 0; 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci LOCK(flags); 6208c2ecf20Sopenharmony_ci fcr = MACIO_IN32(KEYLARGO_FCR0); 6218c2ecf20Sopenharmony_ci /* Check if scc cell need enabling */ 6228c2ecf20Sopenharmony_ci if (!(fcr & KL0_SCC_CELL_ENABLE)) { 6238c2ecf20Sopenharmony_ci fcr |= KL0_SCC_CELL_ENABLE; 6248c2ecf20Sopenharmony_ci need_reset_scc = 1; 6258c2ecf20Sopenharmony_ci } 6268c2ecf20Sopenharmony_ci if (chan_mask & MACIO_FLAG_SCCA_ON) { 6278c2ecf20Sopenharmony_ci fcr |= KL0_SCCA_ENABLE; 6288c2ecf20Sopenharmony_ci /* Don't enable line drivers for I2S modem */ 6298c2ecf20Sopenharmony_ci if ((param & 0xfff) == PMAC_SCC_I2S1) 6308c2ecf20Sopenharmony_ci fcr &= ~KL0_SCC_A_INTF_ENABLE; 6318c2ecf20Sopenharmony_ci else 6328c2ecf20Sopenharmony_ci fcr |= KL0_SCC_A_INTF_ENABLE; 6338c2ecf20Sopenharmony_ci } 6348c2ecf20Sopenharmony_ci if (chan_mask & MACIO_FLAG_SCCB_ON) { 6358c2ecf20Sopenharmony_ci fcr |= KL0_SCCB_ENABLE; 6368c2ecf20Sopenharmony_ci /* Perform irda specific inits */ 6378c2ecf20Sopenharmony_ci if ((param & 0xfff) == PMAC_SCC_IRDA) { 6388c2ecf20Sopenharmony_ci fcr &= ~KL0_SCC_B_INTF_ENABLE; 6398c2ecf20Sopenharmony_ci fcr |= KL0_IRDA_ENABLE; 6408c2ecf20Sopenharmony_ci fcr |= KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE; 6418c2ecf20Sopenharmony_ci fcr |= KL0_IRDA_SOURCE1_SEL; 6428c2ecf20Sopenharmony_ci fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0); 6438c2ecf20Sopenharmony_ci fcr &= ~(KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND); 6448c2ecf20Sopenharmony_ci need_reset_irda = 1; 6458c2ecf20Sopenharmony_ci } else 6468c2ecf20Sopenharmony_ci fcr |= KL0_SCC_B_INTF_ENABLE; 6478c2ecf20Sopenharmony_ci } 6488c2ecf20Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR0, fcr); 6498c2ecf20Sopenharmony_ci macio->flags |= chan_mask; 6508c2ecf20Sopenharmony_ci if (need_reset_scc) { 6518c2ecf20Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR0, KL0_SCC_RESET); 6528c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); 6538c2ecf20Sopenharmony_ci UNLOCK(flags); 6548c2ecf20Sopenharmony_ci mdelay(15); 6558c2ecf20Sopenharmony_ci LOCK(flags); 6568c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR0, KL0_SCC_RESET); 6578c2ecf20Sopenharmony_ci } 6588c2ecf20Sopenharmony_ci if (need_reset_irda) { 6598c2ecf20Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR0, KL0_IRDA_RESET); 6608c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); 6618c2ecf20Sopenharmony_ci UNLOCK(flags); 6628c2ecf20Sopenharmony_ci mdelay(15); 6638c2ecf20Sopenharmony_ci LOCK(flags); 6648c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR0, KL0_IRDA_RESET); 6658c2ecf20Sopenharmony_ci } 6668c2ecf20Sopenharmony_ci UNLOCK(flags); 6678c2ecf20Sopenharmony_ci if (param & PMAC_SCC_FLAG_XMON) 6688c2ecf20Sopenharmony_ci macio->flags |= MACIO_FLAG_SCC_LOCKED; 6698c2ecf20Sopenharmony_ci } else { 6708c2ecf20Sopenharmony_ci if (macio->flags & MACIO_FLAG_SCC_LOCKED) 6718c2ecf20Sopenharmony_ci return -EPERM; 6728c2ecf20Sopenharmony_ci LOCK(flags); 6738c2ecf20Sopenharmony_ci fcr = MACIO_IN32(KEYLARGO_FCR0); 6748c2ecf20Sopenharmony_ci if (chan_mask & MACIO_FLAG_SCCA_ON) 6758c2ecf20Sopenharmony_ci fcr &= ~KL0_SCCA_ENABLE; 6768c2ecf20Sopenharmony_ci if (chan_mask & MACIO_FLAG_SCCB_ON) { 6778c2ecf20Sopenharmony_ci fcr &= ~KL0_SCCB_ENABLE; 6788c2ecf20Sopenharmony_ci /* Perform irda specific clears */ 6798c2ecf20Sopenharmony_ci if ((param & 0xfff) == PMAC_SCC_IRDA) { 6808c2ecf20Sopenharmony_ci fcr &= ~KL0_IRDA_ENABLE; 6818c2ecf20Sopenharmony_ci fcr &= ~(KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE); 6828c2ecf20Sopenharmony_ci fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0); 6838c2ecf20Sopenharmony_ci fcr &= ~(KL0_IRDA_SOURCE1_SEL|KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND); 6848c2ecf20Sopenharmony_ci } 6858c2ecf20Sopenharmony_ci } 6868c2ecf20Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR0, fcr); 6878c2ecf20Sopenharmony_ci if ((fcr & (KL0_SCCA_ENABLE | KL0_SCCB_ENABLE)) == 0) { 6888c2ecf20Sopenharmony_ci fcr &= ~KL0_SCC_CELL_ENABLE; 6898c2ecf20Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR0, fcr); 6908c2ecf20Sopenharmony_ci } 6918c2ecf20Sopenharmony_ci macio->flags &= ~(chan_mask); 6928c2ecf20Sopenharmony_ci UNLOCK(flags); 6938c2ecf20Sopenharmony_ci mdelay(10); 6948c2ecf20Sopenharmony_ci } 6958c2ecf20Sopenharmony_ci return 0; 6968c2ecf20Sopenharmony_ci} 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_cistatic long 6998c2ecf20Sopenharmony_cicore99_modem_enable(struct device_node *node, long param, long value) 7008c2ecf20Sopenharmony_ci{ 7018c2ecf20Sopenharmony_ci struct macio_chip* macio; 7028c2ecf20Sopenharmony_ci u8 gpio; 7038c2ecf20Sopenharmony_ci unsigned long flags; 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci /* Hack for internal USB modem */ 7068c2ecf20Sopenharmony_ci if (node == NULL) { 7078c2ecf20Sopenharmony_ci if (macio_chips[0].type != macio_keylargo) 7088c2ecf20Sopenharmony_ci return -ENODEV; 7098c2ecf20Sopenharmony_ci node = macio_chips[0].of_node; 7108c2ecf20Sopenharmony_ci } 7118c2ecf20Sopenharmony_ci macio = macio_find(node, 0); 7128c2ecf20Sopenharmony_ci if (!macio) 7138c2ecf20Sopenharmony_ci return -ENODEV; 7148c2ecf20Sopenharmony_ci gpio = MACIO_IN8(KL_GPIO_MODEM_RESET); 7158c2ecf20Sopenharmony_ci gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE; 7168c2ecf20Sopenharmony_ci gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA; 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci if (!value) { 7198c2ecf20Sopenharmony_ci LOCK(flags); 7208c2ecf20Sopenharmony_ci MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); 7218c2ecf20Sopenharmony_ci UNLOCK(flags); 7228c2ecf20Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_MODEM_RESET); 7238c2ecf20Sopenharmony_ci mdelay(250); 7248c2ecf20Sopenharmony_ci } 7258c2ecf20Sopenharmony_ci LOCK(flags); 7268c2ecf20Sopenharmony_ci if (value) { 7278c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); 7288c2ecf20Sopenharmony_ci UNLOCK(flags); 7298c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR2); 7308c2ecf20Sopenharmony_ci mdelay(250); 7318c2ecf20Sopenharmony_ci } else { 7328c2ecf20Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); 7338c2ecf20Sopenharmony_ci UNLOCK(flags); 7348c2ecf20Sopenharmony_ci } 7358c2ecf20Sopenharmony_ci if (value) { 7368c2ecf20Sopenharmony_ci LOCK(flags); 7378c2ecf20Sopenharmony_ci MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); 7388c2ecf20Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_MODEM_RESET); 7398c2ecf20Sopenharmony_ci UNLOCK(flags); mdelay(250); LOCK(flags); 7408c2ecf20Sopenharmony_ci MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); 7418c2ecf20Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_MODEM_RESET); 7428c2ecf20Sopenharmony_ci UNLOCK(flags); mdelay(250); LOCK(flags); 7438c2ecf20Sopenharmony_ci MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); 7448c2ecf20Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_MODEM_RESET); 7458c2ecf20Sopenharmony_ci UNLOCK(flags); mdelay(250); 7468c2ecf20Sopenharmony_ci } 7478c2ecf20Sopenharmony_ci return 0; 7488c2ecf20Sopenharmony_ci} 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_cistatic long 7518c2ecf20Sopenharmony_cipangea_modem_enable(struct device_node *node, long param, long value) 7528c2ecf20Sopenharmony_ci{ 7538c2ecf20Sopenharmony_ci struct macio_chip* macio; 7548c2ecf20Sopenharmony_ci u8 gpio; 7558c2ecf20Sopenharmony_ci unsigned long flags; 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci /* Hack for internal USB modem */ 7588c2ecf20Sopenharmony_ci if (node == NULL) { 7598c2ecf20Sopenharmony_ci if (macio_chips[0].type != macio_pangea && 7608c2ecf20Sopenharmony_ci macio_chips[0].type != macio_intrepid) 7618c2ecf20Sopenharmony_ci return -ENODEV; 7628c2ecf20Sopenharmony_ci node = macio_chips[0].of_node; 7638c2ecf20Sopenharmony_ci } 7648c2ecf20Sopenharmony_ci macio = macio_find(node, 0); 7658c2ecf20Sopenharmony_ci if (!macio) 7668c2ecf20Sopenharmony_ci return -ENODEV; 7678c2ecf20Sopenharmony_ci gpio = MACIO_IN8(KL_GPIO_MODEM_RESET); 7688c2ecf20Sopenharmony_ci gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE; 7698c2ecf20Sopenharmony_ci gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA; 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci if (!value) { 7728c2ecf20Sopenharmony_ci LOCK(flags); 7738c2ecf20Sopenharmony_ci MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); 7748c2ecf20Sopenharmony_ci UNLOCK(flags); 7758c2ecf20Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_MODEM_RESET); 7768c2ecf20Sopenharmony_ci mdelay(250); 7778c2ecf20Sopenharmony_ci } 7788c2ecf20Sopenharmony_ci LOCK(flags); 7798c2ecf20Sopenharmony_ci if (value) { 7808c2ecf20Sopenharmony_ci MACIO_OUT8(KL_GPIO_MODEM_POWER, 7818c2ecf20Sopenharmony_ci KEYLARGO_GPIO_OUTPUT_ENABLE); 7828c2ecf20Sopenharmony_ci UNLOCK(flags); 7838c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR2); 7848c2ecf20Sopenharmony_ci mdelay(250); 7858c2ecf20Sopenharmony_ci } else { 7868c2ecf20Sopenharmony_ci MACIO_OUT8(KL_GPIO_MODEM_POWER, 7878c2ecf20Sopenharmony_ci KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); 7888c2ecf20Sopenharmony_ci UNLOCK(flags); 7898c2ecf20Sopenharmony_ci } 7908c2ecf20Sopenharmony_ci if (value) { 7918c2ecf20Sopenharmony_ci LOCK(flags); 7928c2ecf20Sopenharmony_ci MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); 7938c2ecf20Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_MODEM_RESET); 7948c2ecf20Sopenharmony_ci UNLOCK(flags); mdelay(250); LOCK(flags); 7958c2ecf20Sopenharmony_ci MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); 7968c2ecf20Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_MODEM_RESET); 7978c2ecf20Sopenharmony_ci UNLOCK(flags); mdelay(250); LOCK(flags); 7988c2ecf20Sopenharmony_ci MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); 7998c2ecf20Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_MODEM_RESET); 8008c2ecf20Sopenharmony_ci UNLOCK(flags); mdelay(250); 8018c2ecf20Sopenharmony_ci } 8028c2ecf20Sopenharmony_ci return 0; 8038c2ecf20Sopenharmony_ci} 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_cistatic long 8068c2ecf20Sopenharmony_cicore99_ata100_enable(struct device_node *node, long value) 8078c2ecf20Sopenharmony_ci{ 8088c2ecf20Sopenharmony_ci unsigned long flags; 8098c2ecf20Sopenharmony_ci struct pci_dev *pdev = NULL; 8108c2ecf20Sopenharmony_ci u8 pbus, pid; 8118c2ecf20Sopenharmony_ci int rc; 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci if (uninorth_rev < 0x24) 8148c2ecf20Sopenharmony_ci return -ENODEV; 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci LOCK(flags); 8178c2ecf20Sopenharmony_ci if (value) 8188c2ecf20Sopenharmony_ci UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100); 8198c2ecf20Sopenharmony_ci else 8208c2ecf20Sopenharmony_ci UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100); 8218c2ecf20Sopenharmony_ci (void)UN_IN(UNI_N_CLOCK_CNTL); 8228c2ecf20Sopenharmony_ci UNLOCK(flags); 8238c2ecf20Sopenharmony_ci udelay(20); 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci if (value) { 8268c2ecf20Sopenharmony_ci if (pci_device_from_OF_node(node, &pbus, &pid) == 0) 8278c2ecf20Sopenharmony_ci pdev = pci_get_domain_bus_and_slot(0, pbus, pid); 8288c2ecf20Sopenharmony_ci if (pdev == NULL) 8298c2ecf20Sopenharmony_ci return 0; 8308c2ecf20Sopenharmony_ci rc = pci_enable_device(pdev); 8318c2ecf20Sopenharmony_ci if (rc == 0) 8328c2ecf20Sopenharmony_ci pci_set_master(pdev); 8338c2ecf20Sopenharmony_ci pci_dev_put(pdev); 8348c2ecf20Sopenharmony_ci if (rc) 8358c2ecf20Sopenharmony_ci return rc; 8368c2ecf20Sopenharmony_ci } 8378c2ecf20Sopenharmony_ci return 0; 8388c2ecf20Sopenharmony_ci} 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_cistatic long 8418c2ecf20Sopenharmony_cicore99_ide_enable(struct device_node *node, long param, long value) 8428c2ecf20Sopenharmony_ci{ 8438c2ecf20Sopenharmony_ci /* Bus ID 0 to 2 are KeyLargo based IDE, busID 3 is U2 8448c2ecf20Sopenharmony_ci * based ata-100 8458c2ecf20Sopenharmony_ci */ 8468c2ecf20Sopenharmony_ci switch(param) { 8478c2ecf20Sopenharmony_ci case 0: 8488c2ecf20Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 8498c2ecf20Sopenharmony_ci KEYLARGO_FCR1, KL1_EIDE0_ENABLE, value); 8508c2ecf20Sopenharmony_ci case 1: 8518c2ecf20Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 8528c2ecf20Sopenharmony_ci KEYLARGO_FCR1, KL1_EIDE1_ENABLE, value); 8538c2ecf20Sopenharmony_ci case 2: 8548c2ecf20Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 8558c2ecf20Sopenharmony_ci KEYLARGO_FCR1, KL1_UIDE_ENABLE, value); 8568c2ecf20Sopenharmony_ci case 3: 8578c2ecf20Sopenharmony_ci return core99_ata100_enable(node, value); 8588c2ecf20Sopenharmony_ci default: 8598c2ecf20Sopenharmony_ci return -ENODEV; 8608c2ecf20Sopenharmony_ci } 8618c2ecf20Sopenharmony_ci} 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_cistatic long 8648c2ecf20Sopenharmony_cicore99_ide_reset(struct device_node *node, long param, long value) 8658c2ecf20Sopenharmony_ci{ 8668c2ecf20Sopenharmony_ci switch(param) { 8678c2ecf20Sopenharmony_ci case 0: 8688c2ecf20Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 8698c2ecf20Sopenharmony_ci KEYLARGO_FCR1, KL1_EIDE0_RESET_N, !value); 8708c2ecf20Sopenharmony_ci case 1: 8718c2ecf20Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 8728c2ecf20Sopenharmony_ci KEYLARGO_FCR1, KL1_EIDE1_RESET_N, !value); 8738c2ecf20Sopenharmony_ci case 2: 8748c2ecf20Sopenharmony_ci return simple_feature_tweak(node, macio_unknown, 8758c2ecf20Sopenharmony_ci KEYLARGO_FCR1, KL1_UIDE_RESET_N, !value); 8768c2ecf20Sopenharmony_ci default: 8778c2ecf20Sopenharmony_ci return -ENODEV; 8788c2ecf20Sopenharmony_ci } 8798c2ecf20Sopenharmony_ci} 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_cistatic long 8828c2ecf20Sopenharmony_cicore99_gmac_enable(struct device_node *node, long param, long value) 8838c2ecf20Sopenharmony_ci{ 8848c2ecf20Sopenharmony_ci unsigned long flags; 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci LOCK(flags); 8878c2ecf20Sopenharmony_ci if (value) 8888c2ecf20Sopenharmony_ci UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC); 8898c2ecf20Sopenharmony_ci else 8908c2ecf20Sopenharmony_ci UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC); 8918c2ecf20Sopenharmony_ci (void)UN_IN(UNI_N_CLOCK_CNTL); 8928c2ecf20Sopenharmony_ci UNLOCK(flags); 8938c2ecf20Sopenharmony_ci udelay(20); 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci return 0; 8968c2ecf20Sopenharmony_ci} 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_cistatic long 8998c2ecf20Sopenharmony_cicore99_gmac_phy_reset(struct device_node *node, long param, long value) 9008c2ecf20Sopenharmony_ci{ 9018c2ecf20Sopenharmony_ci unsigned long flags; 9028c2ecf20Sopenharmony_ci struct macio_chip *macio; 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci macio = &macio_chips[0]; 9058c2ecf20Sopenharmony_ci if (macio->type != macio_keylargo && macio->type != macio_pangea && 9068c2ecf20Sopenharmony_ci macio->type != macio_intrepid) 9078c2ecf20Sopenharmony_ci return -ENODEV; 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci LOCK(flags); 9108c2ecf20Sopenharmony_ci MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE); 9118c2ecf20Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_ETH_PHY_RESET); 9128c2ecf20Sopenharmony_ci UNLOCK(flags); 9138c2ecf20Sopenharmony_ci mdelay(10); 9148c2ecf20Sopenharmony_ci LOCK(flags); 9158c2ecf20Sopenharmony_ci MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, /*KEYLARGO_GPIO_OUTPUT_ENABLE | */ 9168c2ecf20Sopenharmony_ci KEYLARGO_GPIO_OUTOUT_DATA); 9178c2ecf20Sopenharmony_ci UNLOCK(flags); 9188c2ecf20Sopenharmony_ci mdelay(10); 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci return 0; 9218c2ecf20Sopenharmony_ci} 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_cistatic long 9248c2ecf20Sopenharmony_cicore99_sound_chip_enable(struct device_node *node, long param, long value) 9258c2ecf20Sopenharmony_ci{ 9268c2ecf20Sopenharmony_ci struct macio_chip* macio; 9278c2ecf20Sopenharmony_ci unsigned long flags; 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci macio = macio_find(node, 0); 9308c2ecf20Sopenharmony_ci if (!macio) 9318c2ecf20Sopenharmony_ci return -ENODEV; 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci /* Do a better probe code, screamer G4 desktops & 9348c2ecf20Sopenharmony_ci * iMacs can do that too, add a recalibrate in 9358c2ecf20Sopenharmony_ci * the driver as well 9368c2ecf20Sopenharmony_ci */ 9378c2ecf20Sopenharmony_ci if (pmac_mb.model_id == PMAC_TYPE_PISMO || 9388c2ecf20Sopenharmony_ci pmac_mb.model_id == PMAC_TYPE_TITANIUM) { 9398c2ecf20Sopenharmony_ci LOCK(flags); 9408c2ecf20Sopenharmony_ci if (value) 9418c2ecf20Sopenharmony_ci MACIO_OUT8(KL_GPIO_SOUND_POWER, 9428c2ecf20Sopenharmony_ci KEYLARGO_GPIO_OUTPUT_ENABLE | 9438c2ecf20Sopenharmony_ci KEYLARGO_GPIO_OUTOUT_DATA); 9448c2ecf20Sopenharmony_ci else 9458c2ecf20Sopenharmony_ci MACIO_OUT8(KL_GPIO_SOUND_POWER, 9468c2ecf20Sopenharmony_ci KEYLARGO_GPIO_OUTPUT_ENABLE); 9478c2ecf20Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_SOUND_POWER); 9488c2ecf20Sopenharmony_ci UNLOCK(flags); 9498c2ecf20Sopenharmony_ci } 9508c2ecf20Sopenharmony_ci return 0; 9518c2ecf20Sopenharmony_ci} 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_cistatic long 9548c2ecf20Sopenharmony_cicore99_airport_enable(struct device_node *node, long param, long value) 9558c2ecf20Sopenharmony_ci{ 9568c2ecf20Sopenharmony_ci struct macio_chip* macio; 9578c2ecf20Sopenharmony_ci unsigned long flags; 9588c2ecf20Sopenharmony_ci int state; 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci macio = macio_find(node, 0); 9618c2ecf20Sopenharmony_ci if (!macio) 9628c2ecf20Sopenharmony_ci return -ENODEV; 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci /* Hint: we allow passing of macio itself for the sake of the 9658c2ecf20Sopenharmony_ci * sleep code 9668c2ecf20Sopenharmony_ci */ 9678c2ecf20Sopenharmony_ci if (node != macio->of_node && 9688c2ecf20Sopenharmony_ci (!node->parent || node->parent != macio->of_node)) 9698c2ecf20Sopenharmony_ci return -ENODEV; 9708c2ecf20Sopenharmony_ci state = (macio->flags & MACIO_FLAG_AIRPORT_ON) != 0; 9718c2ecf20Sopenharmony_ci if (value == state) 9728c2ecf20Sopenharmony_ci return 0; 9738c2ecf20Sopenharmony_ci if (value) { 9748c2ecf20Sopenharmony_ci /* This code is a reproduction of OF enable-cardslot 9758c2ecf20Sopenharmony_ci * and init-wireless methods, slightly hacked until 9768c2ecf20Sopenharmony_ci * I got it working. 9778c2ecf20Sopenharmony_ci */ 9788c2ecf20Sopenharmony_ci LOCK(flags); 9798c2ecf20Sopenharmony_ci MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 5); 9808c2ecf20Sopenharmony_ci (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf); 9818c2ecf20Sopenharmony_ci UNLOCK(flags); 9828c2ecf20Sopenharmony_ci mdelay(10); 9838c2ecf20Sopenharmony_ci LOCK(flags); 9848c2ecf20Sopenharmony_ci MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 4); 9858c2ecf20Sopenharmony_ci (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf); 9868c2ecf20Sopenharmony_ci UNLOCK(flags); 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci mdelay(10); 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci LOCK(flags); 9918c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16); 9928c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR2); 9938c2ecf20Sopenharmony_ci udelay(10); 9948c2ecf20Sopenharmony_ci MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xb, 0); 9958c2ecf20Sopenharmony_ci (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xb); 9968c2ecf20Sopenharmony_ci udelay(10); 9978c2ecf20Sopenharmony_ci MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xa, 0x28); 9988c2ecf20Sopenharmony_ci (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xa); 9998c2ecf20Sopenharmony_ci udelay(10); 10008c2ecf20Sopenharmony_ci MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xd, 0x28); 10018c2ecf20Sopenharmony_ci (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xd); 10028c2ecf20Sopenharmony_ci udelay(10); 10038c2ecf20Sopenharmony_ci MACIO_OUT8(KEYLARGO_GPIO_0+0xd, 0x28); 10048c2ecf20Sopenharmony_ci (void)MACIO_IN8(KEYLARGO_GPIO_0+0xd); 10058c2ecf20Sopenharmony_ci udelay(10); 10068c2ecf20Sopenharmony_ci MACIO_OUT8(KEYLARGO_GPIO_0+0xe, 0x28); 10078c2ecf20Sopenharmony_ci (void)MACIO_IN8(KEYLARGO_GPIO_0+0xe); 10088c2ecf20Sopenharmony_ci UNLOCK(flags); 10098c2ecf20Sopenharmony_ci udelay(10); 10108c2ecf20Sopenharmony_ci MACIO_OUT32(0x1c000, 0); 10118c2ecf20Sopenharmony_ci mdelay(1); 10128c2ecf20Sopenharmony_ci MACIO_OUT8(0x1a3e0, 0x41); 10138c2ecf20Sopenharmony_ci (void)MACIO_IN8(0x1a3e0); 10148c2ecf20Sopenharmony_ci udelay(10); 10158c2ecf20Sopenharmony_ci LOCK(flags); 10168c2ecf20Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR2, KL2_CARDSEL_16); 10178c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR2); 10188c2ecf20Sopenharmony_ci UNLOCK(flags); 10198c2ecf20Sopenharmony_ci mdelay(100); 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci macio->flags |= MACIO_FLAG_AIRPORT_ON; 10228c2ecf20Sopenharmony_ci } else { 10238c2ecf20Sopenharmony_ci LOCK(flags); 10248c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16); 10258c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR2); 10268c2ecf20Sopenharmony_ci MACIO_OUT8(KL_GPIO_AIRPORT_0, 0); 10278c2ecf20Sopenharmony_ci MACIO_OUT8(KL_GPIO_AIRPORT_1, 0); 10288c2ecf20Sopenharmony_ci MACIO_OUT8(KL_GPIO_AIRPORT_2, 0); 10298c2ecf20Sopenharmony_ci MACIO_OUT8(KL_GPIO_AIRPORT_3, 0); 10308c2ecf20Sopenharmony_ci MACIO_OUT8(KL_GPIO_AIRPORT_4, 0); 10318c2ecf20Sopenharmony_ci (void)MACIO_IN8(KL_GPIO_AIRPORT_4); 10328c2ecf20Sopenharmony_ci UNLOCK(flags); 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci macio->flags &= ~MACIO_FLAG_AIRPORT_ON; 10358c2ecf20Sopenharmony_ci } 10368c2ecf20Sopenharmony_ci return 0; 10378c2ecf20Sopenharmony_ci} 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 10408c2ecf20Sopenharmony_cistatic long 10418c2ecf20Sopenharmony_cicore99_reset_cpu(struct device_node *node, long param, long value) 10428c2ecf20Sopenharmony_ci{ 10438c2ecf20Sopenharmony_ci unsigned int reset_io = 0; 10448c2ecf20Sopenharmony_ci unsigned long flags; 10458c2ecf20Sopenharmony_ci struct macio_chip *macio; 10468c2ecf20Sopenharmony_ci struct device_node *np; 10478c2ecf20Sopenharmony_ci const int dflt_reset_lines[] = { KL_GPIO_RESET_CPU0, 10488c2ecf20Sopenharmony_ci KL_GPIO_RESET_CPU1, 10498c2ecf20Sopenharmony_ci KL_GPIO_RESET_CPU2, 10508c2ecf20Sopenharmony_ci KL_GPIO_RESET_CPU3 }; 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci macio = &macio_chips[0]; 10538c2ecf20Sopenharmony_ci if (macio->type != macio_keylargo) 10548c2ecf20Sopenharmony_ci return -ENODEV; 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci for_each_of_cpu_node(np) { 10578c2ecf20Sopenharmony_ci const u32 *num = of_get_property(np, "reg", NULL); 10588c2ecf20Sopenharmony_ci const u32 *rst = of_get_property(np, "soft-reset", NULL); 10598c2ecf20Sopenharmony_ci if (num == NULL || rst == NULL) 10608c2ecf20Sopenharmony_ci continue; 10618c2ecf20Sopenharmony_ci if (param == *num) { 10628c2ecf20Sopenharmony_ci reset_io = *rst; 10638c2ecf20Sopenharmony_ci break; 10648c2ecf20Sopenharmony_ci } 10658c2ecf20Sopenharmony_ci } 10668c2ecf20Sopenharmony_ci if (np == NULL || reset_io == 0) 10678c2ecf20Sopenharmony_ci reset_io = dflt_reset_lines[param]; 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_ci LOCK(flags); 10708c2ecf20Sopenharmony_ci MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE); 10718c2ecf20Sopenharmony_ci (void)MACIO_IN8(reset_io); 10728c2ecf20Sopenharmony_ci udelay(1); 10738c2ecf20Sopenharmony_ci MACIO_OUT8(reset_io, 0); 10748c2ecf20Sopenharmony_ci (void)MACIO_IN8(reset_io); 10758c2ecf20Sopenharmony_ci UNLOCK(flags); 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci return 0; 10788c2ecf20Sopenharmony_ci} 10798c2ecf20Sopenharmony_ci#endif /* CONFIG_SMP */ 10808c2ecf20Sopenharmony_ci 10818c2ecf20Sopenharmony_cistatic long 10828c2ecf20Sopenharmony_cicore99_usb_enable(struct device_node *node, long param, long value) 10838c2ecf20Sopenharmony_ci{ 10848c2ecf20Sopenharmony_ci struct macio_chip *macio; 10858c2ecf20Sopenharmony_ci unsigned long flags; 10868c2ecf20Sopenharmony_ci const char *prop; 10878c2ecf20Sopenharmony_ci int number; 10888c2ecf20Sopenharmony_ci u32 reg; 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci macio = &macio_chips[0]; 10918c2ecf20Sopenharmony_ci if (macio->type != macio_keylargo && macio->type != macio_pangea && 10928c2ecf20Sopenharmony_ci macio->type != macio_intrepid) 10938c2ecf20Sopenharmony_ci return -ENODEV; 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci prop = of_get_property(node, "AAPL,clock-id", NULL); 10968c2ecf20Sopenharmony_ci if (!prop) 10978c2ecf20Sopenharmony_ci return -ENODEV; 10988c2ecf20Sopenharmony_ci if (strncmp(prop, "usb0u048", 8) == 0) 10998c2ecf20Sopenharmony_ci number = 0; 11008c2ecf20Sopenharmony_ci else if (strncmp(prop, "usb1u148", 8) == 0) 11018c2ecf20Sopenharmony_ci number = 2; 11028c2ecf20Sopenharmony_ci else if (strncmp(prop, "usb2u248", 8) == 0) 11038c2ecf20Sopenharmony_ci number = 4; 11048c2ecf20Sopenharmony_ci else 11058c2ecf20Sopenharmony_ci return -ENODEV; 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci /* Sorry for the brute-force locking, but this is only used during 11088c2ecf20Sopenharmony_ci * sleep and the timing seem to be critical 11098c2ecf20Sopenharmony_ci */ 11108c2ecf20Sopenharmony_ci LOCK(flags); 11118c2ecf20Sopenharmony_ci if (value) { 11128c2ecf20Sopenharmony_ci /* Turn ON */ 11138c2ecf20Sopenharmony_ci if (number == 0) { 11148c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1)); 11158c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); 11168c2ecf20Sopenharmony_ci UNLOCK(flags); 11178c2ecf20Sopenharmony_ci mdelay(1); 11188c2ecf20Sopenharmony_ci LOCK(flags); 11198c2ecf20Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE); 11208c2ecf20Sopenharmony_ci } else if (number == 2) { 11218c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1)); 11228c2ecf20Sopenharmony_ci UNLOCK(flags); 11238c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); 11248c2ecf20Sopenharmony_ci mdelay(1); 11258c2ecf20Sopenharmony_ci LOCK(flags); 11268c2ecf20Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE); 11278c2ecf20Sopenharmony_ci } else if (number == 4) { 11288c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1)); 11298c2ecf20Sopenharmony_ci UNLOCK(flags); 11308c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR1); 11318c2ecf20Sopenharmony_ci mdelay(1); 11328c2ecf20Sopenharmony_ci LOCK(flags); 11338c2ecf20Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR1, KL1_USB2_CELL_ENABLE); 11348c2ecf20Sopenharmony_ci } 11358c2ecf20Sopenharmony_ci if (number < 4) { 11368c2ecf20Sopenharmony_ci reg = MACIO_IN32(KEYLARGO_FCR4); 11378c2ecf20Sopenharmony_ci reg &= ~(KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) | 11388c2ecf20Sopenharmony_ci KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number)); 11398c2ecf20Sopenharmony_ci reg &= ~(KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) | 11408c2ecf20Sopenharmony_ci KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1)); 11418c2ecf20Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR4, reg); 11428c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR4); 11438c2ecf20Sopenharmony_ci udelay(10); 11448c2ecf20Sopenharmony_ci } else { 11458c2ecf20Sopenharmony_ci reg = MACIO_IN32(KEYLARGO_FCR3); 11468c2ecf20Sopenharmony_ci reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) | 11478c2ecf20Sopenharmony_ci KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0)); 11488c2ecf20Sopenharmony_ci reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) | 11498c2ecf20Sopenharmony_ci KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1)); 11508c2ecf20Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR3, reg); 11518c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR3); 11528c2ecf20Sopenharmony_ci udelay(10); 11538c2ecf20Sopenharmony_ci } 11548c2ecf20Sopenharmony_ci if (macio->type == macio_intrepid) { 11558c2ecf20Sopenharmony_ci /* wait for clock stopped bits to clear */ 11568c2ecf20Sopenharmony_ci u32 test0 = 0, test1 = 0; 11578c2ecf20Sopenharmony_ci u32 status0, status1; 11588c2ecf20Sopenharmony_ci int timeout = 1000; 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci UNLOCK(flags); 11618c2ecf20Sopenharmony_ci switch (number) { 11628c2ecf20Sopenharmony_ci case 0: 11638c2ecf20Sopenharmony_ci test0 = UNI_N_CLOCK_STOPPED_USB0; 11648c2ecf20Sopenharmony_ci test1 = UNI_N_CLOCK_STOPPED_USB0PCI; 11658c2ecf20Sopenharmony_ci break; 11668c2ecf20Sopenharmony_ci case 2: 11678c2ecf20Sopenharmony_ci test0 = UNI_N_CLOCK_STOPPED_USB1; 11688c2ecf20Sopenharmony_ci test1 = UNI_N_CLOCK_STOPPED_USB1PCI; 11698c2ecf20Sopenharmony_ci break; 11708c2ecf20Sopenharmony_ci case 4: 11718c2ecf20Sopenharmony_ci test0 = UNI_N_CLOCK_STOPPED_USB2; 11728c2ecf20Sopenharmony_ci test1 = UNI_N_CLOCK_STOPPED_USB2PCI; 11738c2ecf20Sopenharmony_ci break; 11748c2ecf20Sopenharmony_ci } 11758c2ecf20Sopenharmony_ci do { 11768c2ecf20Sopenharmony_ci if (--timeout <= 0) { 11778c2ecf20Sopenharmony_ci printk(KERN_ERR "core99_usb_enable: " 11788c2ecf20Sopenharmony_ci "Timeout waiting for clocks\n"); 11798c2ecf20Sopenharmony_ci break; 11808c2ecf20Sopenharmony_ci } 11818c2ecf20Sopenharmony_ci mdelay(1); 11828c2ecf20Sopenharmony_ci status0 = UN_IN(UNI_N_CLOCK_STOP_STATUS0); 11838c2ecf20Sopenharmony_ci status1 = UN_IN(UNI_N_CLOCK_STOP_STATUS1); 11848c2ecf20Sopenharmony_ci } while ((status0 & test0) | (status1 & test1)); 11858c2ecf20Sopenharmony_ci LOCK(flags); 11868c2ecf20Sopenharmony_ci } 11878c2ecf20Sopenharmony_ci } else { 11888c2ecf20Sopenharmony_ci /* Turn OFF */ 11898c2ecf20Sopenharmony_ci if (number < 4) { 11908c2ecf20Sopenharmony_ci reg = MACIO_IN32(KEYLARGO_FCR4); 11918c2ecf20Sopenharmony_ci reg |= KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) | 11928c2ecf20Sopenharmony_ci KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number); 11938c2ecf20Sopenharmony_ci reg |= KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) | 11948c2ecf20Sopenharmony_ci KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1); 11958c2ecf20Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR4, reg); 11968c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR4); 11978c2ecf20Sopenharmony_ci udelay(1); 11988c2ecf20Sopenharmony_ci } else { 11998c2ecf20Sopenharmony_ci reg = MACIO_IN32(KEYLARGO_FCR3); 12008c2ecf20Sopenharmony_ci reg |= KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) | 12018c2ecf20Sopenharmony_ci KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0); 12028c2ecf20Sopenharmony_ci reg |= KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) | 12038c2ecf20Sopenharmony_ci KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1); 12048c2ecf20Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR3, reg); 12058c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR3); 12068c2ecf20Sopenharmony_ci udelay(1); 12078c2ecf20Sopenharmony_ci } 12088c2ecf20Sopenharmony_ci if (number == 0) { 12098c2ecf20Sopenharmony_ci if (macio->type != macio_intrepid) 12108c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE); 12118c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); 12128c2ecf20Sopenharmony_ci udelay(1); 12138c2ecf20Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1)); 12148c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); 12158c2ecf20Sopenharmony_ci } else if (number == 2) { 12168c2ecf20Sopenharmony_ci if (macio->type != macio_intrepid) 12178c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE); 12188c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); 12198c2ecf20Sopenharmony_ci udelay(1); 12208c2ecf20Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1)); 12218c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); 12228c2ecf20Sopenharmony_ci } else if (number == 4) { 12238c2ecf20Sopenharmony_ci udelay(1); 12248c2ecf20Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1)); 12258c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR1); 12268c2ecf20Sopenharmony_ci } 12278c2ecf20Sopenharmony_ci udelay(1); 12288c2ecf20Sopenharmony_ci } 12298c2ecf20Sopenharmony_ci UNLOCK(flags); 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci return 0; 12328c2ecf20Sopenharmony_ci} 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_cistatic long 12358c2ecf20Sopenharmony_cicore99_firewire_enable(struct device_node *node, long param, long value) 12368c2ecf20Sopenharmony_ci{ 12378c2ecf20Sopenharmony_ci unsigned long flags; 12388c2ecf20Sopenharmony_ci struct macio_chip *macio; 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_ci macio = &macio_chips[0]; 12418c2ecf20Sopenharmony_ci if (macio->type != macio_keylargo && macio->type != macio_pangea && 12428c2ecf20Sopenharmony_ci macio->type != macio_intrepid) 12438c2ecf20Sopenharmony_ci return -ENODEV; 12448c2ecf20Sopenharmony_ci if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED)) 12458c2ecf20Sopenharmony_ci return -ENODEV; 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_ci LOCK(flags); 12488c2ecf20Sopenharmony_ci if (value) { 12498c2ecf20Sopenharmony_ci UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW); 12508c2ecf20Sopenharmony_ci (void)UN_IN(UNI_N_CLOCK_CNTL); 12518c2ecf20Sopenharmony_ci } else { 12528c2ecf20Sopenharmony_ci UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW); 12538c2ecf20Sopenharmony_ci (void)UN_IN(UNI_N_CLOCK_CNTL); 12548c2ecf20Sopenharmony_ci } 12558c2ecf20Sopenharmony_ci UNLOCK(flags); 12568c2ecf20Sopenharmony_ci mdelay(1); 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ci return 0; 12598c2ecf20Sopenharmony_ci} 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_cistatic long 12628c2ecf20Sopenharmony_cicore99_firewire_cable_power(struct device_node *node, long param, long value) 12638c2ecf20Sopenharmony_ci{ 12648c2ecf20Sopenharmony_ci unsigned long flags; 12658c2ecf20Sopenharmony_ci struct macio_chip *macio; 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_ci /* Trick: we allow NULL node */ 12688c2ecf20Sopenharmony_ci if ((pmac_mb.board_flags & PMAC_MB_HAS_FW_POWER) == 0) 12698c2ecf20Sopenharmony_ci return -ENODEV; 12708c2ecf20Sopenharmony_ci macio = &macio_chips[0]; 12718c2ecf20Sopenharmony_ci if (macio->type != macio_keylargo && macio->type != macio_pangea && 12728c2ecf20Sopenharmony_ci macio->type != macio_intrepid) 12738c2ecf20Sopenharmony_ci return -ENODEV; 12748c2ecf20Sopenharmony_ci if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED)) 12758c2ecf20Sopenharmony_ci return -ENODEV; 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ci LOCK(flags); 12788c2ecf20Sopenharmony_ci if (value) { 12798c2ecf20Sopenharmony_ci MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 0); 12808c2ecf20Sopenharmony_ci MACIO_IN8(KL_GPIO_FW_CABLE_POWER); 12818c2ecf20Sopenharmony_ci udelay(10); 12828c2ecf20Sopenharmony_ci } else { 12838c2ecf20Sopenharmony_ci MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 4); 12848c2ecf20Sopenharmony_ci MACIO_IN8(KL_GPIO_FW_CABLE_POWER); udelay(10); 12858c2ecf20Sopenharmony_ci } 12868c2ecf20Sopenharmony_ci UNLOCK(flags); 12878c2ecf20Sopenharmony_ci mdelay(1); 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ci return 0; 12908c2ecf20Sopenharmony_ci} 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_cistatic long 12938c2ecf20Sopenharmony_ciintrepid_aack_delay_enable(struct device_node *node, long param, long value) 12948c2ecf20Sopenharmony_ci{ 12958c2ecf20Sopenharmony_ci unsigned long flags; 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci if (uninorth_rev < 0xd2) 12988c2ecf20Sopenharmony_ci return -ENODEV; 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_ci LOCK(flags); 13018c2ecf20Sopenharmony_ci if (param) 13028c2ecf20Sopenharmony_ci UN_BIS(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE); 13038c2ecf20Sopenharmony_ci else 13048c2ecf20Sopenharmony_ci UN_BIC(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE); 13058c2ecf20Sopenharmony_ci UNLOCK(flags); 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci return 0; 13088c2ecf20Sopenharmony_ci} 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC64 */ 13128c2ecf20Sopenharmony_ci 13138c2ecf20Sopenharmony_cistatic long 13148c2ecf20Sopenharmony_cicore99_read_gpio(struct device_node *node, long param, long value) 13158c2ecf20Sopenharmony_ci{ 13168c2ecf20Sopenharmony_ci struct macio_chip *macio = &macio_chips[0]; 13178c2ecf20Sopenharmony_ci 13188c2ecf20Sopenharmony_ci return MACIO_IN8(param); 13198c2ecf20Sopenharmony_ci} 13208c2ecf20Sopenharmony_ci 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_cistatic long 13238c2ecf20Sopenharmony_cicore99_write_gpio(struct device_node *node, long param, long value) 13248c2ecf20Sopenharmony_ci{ 13258c2ecf20Sopenharmony_ci struct macio_chip *macio = &macio_chips[0]; 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_ci MACIO_OUT8(param, (u8)(value & 0xff)); 13288c2ecf20Sopenharmony_ci return 0; 13298c2ecf20Sopenharmony_ci} 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC64 13328c2ecf20Sopenharmony_cistatic long g5_gmac_enable(struct device_node *node, long param, long value) 13338c2ecf20Sopenharmony_ci{ 13348c2ecf20Sopenharmony_ci struct macio_chip *macio = &macio_chips[0]; 13358c2ecf20Sopenharmony_ci unsigned long flags; 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci if (node == NULL) 13388c2ecf20Sopenharmony_ci return -ENODEV; 13398c2ecf20Sopenharmony_ci 13408c2ecf20Sopenharmony_ci LOCK(flags); 13418c2ecf20Sopenharmony_ci if (value) { 13428c2ecf20Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE); 13438c2ecf20Sopenharmony_ci mb(); 13448c2ecf20Sopenharmony_ci k2_skiplist[0] = NULL; 13458c2ecf20Sopenharmony_ci } else { 13468c2ecf20Sopenharmony_ci k2_skiplist[0] = node; 13478c2ecf20Sopenharmony_ci mb(); 13488c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE); 13498c2ecf20Sopenharmony_ci } 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci UNLOCK(flags); 13528c2ecf20Sopenharmony_ci mdelay(1); 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci return 0; 13558c2ecf20Sopenharmony_ci} 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_cistatic long g5_fw_enable(struct device_node *node, long param, long value) 13588c2ecf20Sopenharmony_ci{ 13598c2ecf20Sopenharmony_ci struct macio_chip *macio = &macio_chips[0]; 13608c2ecf20Sopenharmony_ci unsigned long flags; 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ci if (node == NULL) 13638c2ecf20Sopenharmony_ci return -ENODEV; 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_ci LOCK(flags); 13668c2ecf20Sopenharmony_ci if (value) { 13678c2ecf20Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE); 13688c2ecf20Sopenharmony_ci mb(); 13698c2ecf20Sopenharmony_ci k2_skiplist[1] = NULL; 13708c2ecf20Sopenharmony_ci } else { 13718c2ecf20Sopenharmony_ci k2_skiplist[1] = node; 13728c2ecf20Sopenharmony_ci mb(); 13738c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE); 13748c2ecf20Sopenharmony_ci } 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_ci UNLOCK(flags); 13778c2ecf20Sopenharmony_ci mdelay(1); 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_ci return 0; 13808c2ecf20Sopenharmony_ci} 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_cistatic long g5_mpic_enable(struct device_node *node, long param, long value) 13838c2ecf20Sopenharmony_ci{ 13848c2ecf20Sopenharmony_ci unsigned long flags; 13858c2ecf20Sopenharmony_ci struct device_node *parent = of_get_parent(node); 13868c2ecf20Sopenharmony_ci int is_u3; 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_ci if (parent == NULL) 13898c2ecf20Sopenharmony_ci return 0; 13908c2ecf20Sopenharmony_ci is_u3 = of_node_name_eq(parent, "u3") || of_node_name_eq(parent, "u4"); 13918c2ecf20Sopenharmony_ci of_node_put(parent); 13928c2ecf20Sopenharmony_ci if (!is_u3) 13938c2ecf20Sopenharmony_ci return 0; 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci LOCK(flags); 13968c2ecf20Sopenharmony_ci UN_BIS(U3_TOGGLE_REG, U3_MPIC_RESET | U3_MPIC_OUTPUT_ENABLE); 13978c2ecf20Sopenharmony_ci UNLOCK(flags); 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci return 0; 14008c2ecf20Sopenharmony_ci} 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_cistatic long g5_eth_phy_reset(struct device_node *node, long param, long value) 14038c2ecf20Sopenharmony_ci{ 14048c2ecf20Sopenharmony_ci struct macio_chip *macio = &macio_chips[0]; 14058c2ecf20Sopenharmony_ci struct device_node *phy; 14068c2ecf20Sopenharmony_ci int need_reset; 14078c2ecf20Sopenharmony_ci 14088c2ecf20Sopenharmony_ci /* 14098c2ecf20Sopenharmony_ci * We must not reset the combo PHYs, only the BCM5221 found in 14108c2ecf20Sopenharmony_ci * the iMac G5. 14118c2ecf20Sopenharmony_ci */ 14128c2ecf20Sopenharmony_ci phy = of_get_next_child(node, NULL); 14138c2ecf20Sopenharmony_ci if (!phy) 14148c2ecf20Sopenharmony_ci return -ENODEV; 14158c2ecf20Sopenharmony_ci need_reset = of_device_is_compatible(phy, "B5221"); 14168c2ecf20Sopenharmony_ci of_node_put(phy); 14178c2ecf20Sopenharmony_ci if (!need_reset) 14188c2ecf20Sopenharmony_ci return 0; 14198c2ecf20Sopenharmony_ci 14208c2ecf20Sopenharmony_ci /* PHY reset is GPIO 29, not in device-tree unfortunately */ 14218c2ecf20Sopenharmony_ci MACIO_OUT8(K2_GPIO_EXTINT_0 + 29, 14228c2ecf20Sopenharmony_ci KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); 14238c2ecf20Sopenharmony_ci /* Thankfully, this is now always called at a time when we can 14248c2ecf20Sopenharmony_ci * schedule by sungem. 14258c2ecf20Sopenharmony_ci */ 14268c2ecf20Sopenharmony_ci msleep(10); 14278c2ecf20Sopenharmony_ci MACIO_OUT8(K2_GPIO_EXTINT_0 + 29, 0); 14288c2ecf20Sopenharmony_ci 14298c2ecf20Sopenharmony_ci return 0; 14308c2ecf20Sopenharmony_ci} 14318c2ecf20Sopenharmony_ci 14328c2ecf20Sopenharmony_cistatic long g5_i2s_enable(struct device_node *node, long param, long value) 14338c2ecf20Sopenharmony_ci{ 14348c2ecf20Sopenharmony_ci /* Very crude implementation for now */ 14358c2ecf20Sopenharmony_ci struct macio_chip *macio = &macio_chips[0]; 14368c2ecf20Sopenharmony_ci unsigned long flags; 14378c2ecf20Sopenharmony_ci int cell; 14388c2ecf20Sopenharmony_ci u32 fcrs[3][3] = { 14398c2ecf20Sopenharmony_ci { 0, 14408c2ecf20Sopenharmony_ci K2_FCR1_I2S0_CELL_ENABLE | 14418c2ecf20Sopenharmony_ci K2_FCR1_I2S0_CLK_ENABLE_BIT | K2_FCR1_I2S0_ENABLE, 14428c2ecf20Sopenharmony_ci KL3_I2S0_CLK18_ENABLE 14438c2ecf20Sopenharmony_ci }, 14448c2ecf20Sopenharmony_ci { KL0_SCC_A_INTF_ENABLE, 14458c2ecf20Sopenharmony_ci K2_FCR1_I2S1_CELL_ENABLE | 14468c2ecf20Sopenharmony_ci K2_FCR1_I2S1_CLK_ENABLE_BIT | K2_FCR1_I2S1_ENABLE, 14478c2ecf20Sopenharmony_ci KL3_I2S1_CLK18_ENABLE 14488c2ecf20Sopenharmony_ci }, 14498c2ecf20Sopenharmony_ci { KL0_SCC_B_INTF_ENABLE, 14508c2ecf20Sopenharmony_ci SH_FCR1_I2S2_CELL_ENABLE | 14518c2ecf20Sopenharmony_ci SH_FCR1_I2S2_CLK_ENABLE_BIT | SH_FCR1_I2S2_ENABLE, 14528c2ecf20Sopenharmony_ci SH_FCR3_I2S2_CLK18_ENABLE 14538c2ecf20Sopenharmony_ci }, 14548c2ecf20Sopenharmony_ci }; 14558c2ecf20Sopenharmony_ci 14568c2ecf20Sopenharmony_ci if (macio->type != macio_keylargo2 && macio->type != macio_shasta) 14578c2ecf20Sopenharmony_ci return -ENODEV; 14588c2ecf20Sopenharmony_ci if (strncmp(node->name, "i2s-", 4)) 14598c2ecf20Sopenharmony_ci return -ENODEV; 14608c2ecf20Sopenharmony_ci cell = node->name[4] - 'a'; 14618c2ecf20Sopenharmony_ci switch(cell) { 14628c2ecf20Sopenharmony_ci case 0: 14638c2ecf20Sopenharmony_ci case 1: 14648c2ecf20Sopenharmony_ci break; 14658c2ecf20Sopenharmony_ci case 2: 14668c2ecf20Sopenharmony_ci if (macio->type == macio_shasta) 14678c2ecf20Sopenharmony_ci break; 14688c2ecf20Sopenharmony_ci fallthrough; 14698c2ecf20Sopenharmony_ci default: 14708c2ecf20Sopenharmony_ci return -ENODEV; 14718c2ecf20Sopenharmony_ci } 14728c2ecf20Sopenharmony_ci 14738c2ecf20Sopenharmony_ci LOCK(flags); 14748c2ecf20Sopenharmony_ci if (value) { 14758c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR0, fcrs[cell][0]); 14768c2ecf20Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR1, fcrs[cell][1]); 14778c2ecf20Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR3, fcrs[cell][2]); 14788c2ecf20Sopenharmony_ci } else { 14798c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR3, fcrs[cell][2]); 14808c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR1, fcrs[cell][1]); 14818c2ecf20Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR0, fcrs[cell][0]); 14828c2ecf20Sopenharmony_ci } 14838c2ecf20Sopenharmony_ci udelay(10); 14848c2ecf20Sopenharmony_ci UNLOCK(flags); 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_ci return 0; 14878c2ecf20Sopenharmony_ci} 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_ci 14908c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 14918c2ecf20Sopenharmony_cistatic long g5_reset_cpu(struct device_node *node, long param, long value) 14928c2ecf20Sopenharmony_ci{ 14938c2ecf20Sopenharmony_ci unsigned int reset_io = 0; 14948c2ecf20Sopenharmony_ci unsigned long flags; 14958c2ecf20Sopenharmony_ci struct macio_chip *macio; 14968c2ecf20Sopenharmony_ci struct device_node *np; 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci macio = &macio_chips[0]; 14998c2ecf20Sopenharmony_ci if (macio->type != macio_keylargo2 && macio->type != macio_shasta) 15008c2ecf20Sopenharmony_ci return -ENODEV; 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci for_each_of_cpu_node(np) { 15038c2ecf20Sopenharmony_ci const u32 *num = of_get_property(np, "reg", NULL); 15048c2ecf20Sopenharmony_ci const u32 *rst = of_get_property(np, "soft-reset", NULL); 15058c2ecf20Sopenharmony_ci if (num == NULL || rst == NULL) 15068c2ecf20Sopenharmony_ci continue; 15078c2ecf20Sopenharmony_ci if (param == *num) { 15088c2ecf20Sopenharmony_ci reset_io = *rst; 15098c2ecf20Sopenharmony_ci break; 15108c2ecf20Sopenharmony_ci } 15118c2ecf20Sopenharmony_ci } 15128c2ecf20Sopenharmony_ci if (np == NULL || reset_io == 0) 15138c2ecf20Sopenharmony_ci return -ENODEV; 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_ci LOCK(flags); 15168c2ecf20Sopenharmony_ci MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE); 15178c2ecf20Sopenharmony_ci (void)MACIO_IN8(reset_io); 15188c2ecf20Sopenharmony_ci udelay(1); 15198c2ecf20Sopenharmony_ci MACIO_OUT8(reset_io, 0); 15208c2ecf20Sopenharmony_ci (void)MACIO_IN8(reset_io); 15218c2ecf20Sopenharmony_ci UNLOCK(flags); 15228c2ecf20Sopenharmony_ci 15238c2ecf20Sopenharmony_ci return 0; 15248c2ecf20Sopenharmony_ci} 15258c2ecf20Sopenharmony_ci#endif /* CONFIG_SMP */ 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_ci/* 15288c2ecf20Sopenharmony_ci * This can be called from pmac_smp so isn't static 15298c2ecf20Sopenharmony_ci * 15308c2ecf20Sopenharmony_ci * This takes the second CPU off the bus on dual CPU machines 15318c2ecf20Sopenharmony_ci * running UP 15328c2ecf20Sopenharmony_ci */ 15338c2ecf20Sopenharmony_civoid g5_phy_disable_cpu1(void) 15348c2ecf20Sopenharmony_ci{ 15358c2ecf20Sopenharmony_ci if (uninorth_maj == 3) 15368c2ecf20Sopenharmony_ci UN_OUT(U3_API_PHY_CONFIG_1, 0); 15378c2ecf20Sopenharmony_ci} 15388c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC64 */ 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_ci#ifndef CONFIG_PPC64 15418c2ecf20Sopenharmony_ci 15428c2ecf20Sopenharmony_ci 15438c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 15448c2ecf20Sopenharmony_cistatic u32 save_gpio_levels[2]; 15458c2ecf20Sopenharmony_cistatic u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT]; 15468c2ecf20Sopenharmony_cistatic u8 save_gpio_normal[KEYLARGO_GPIO_CNT]; 15478c2ecf20Sopenharmony_cistatic u32 save_unin_clock_ctl; 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_cistatic void keylargo_shutdown(struct macio_chip *macio, int sleep_mode) 15508c2ecf20Sopenharmony_ci{ 15518c2ecf20Sopenharmony_ci u32 temp; 15528c2ecf20Sopenharmony_ci 15538c2ecf20Sopenharmony_ci if (sleep_mode) { 15548c2ecf20Sopenharmony_ci mdelay(1); 15558c2ecf20Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND); 15568c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); 15578c2ecf20Sopenharmony_ci mdelay(1); 15588c2ecf20Sopenharmony_ci } 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | 15618c2ecf20Sopenharmony_ci KL0_SCC_CELL_ENABLE | 15628c2ecf20Sopenharmony_ci KL0_IRDA_ENABLE | KL0_IRDA_CLK32_ENABLE | 15638c2ecf20Sopenharmony_ci KL0_IRDA_CLK19_ENABLE); 15648c2ecf20Sopenharmony_ci 15658c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK); 15668c2ecf20Sopenharmony_ci MACIO_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_IDE_ENABLE); 15678c2ecf20Sopenharmony_ci 15688c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR1, 15698c2ecf20Sopenharmony_ci KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT | 15708c2ecf20Sopenharmony_ci KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE | 15718c2ecf20Sopenharmony_ci KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT | 15728c2ecf20Sopenharmony_ci KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE | 15738c2ecf20Sopenharmony_ci KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE | 15748c2ecf20Sopenharmony_ci KL1_EIDE0_ENABLE | KL1_EIDE0_RESET_N | 15758c2ecf20Sopenharmony_ci KL1_EIDE1_ENABLE | KL1_EIDE1_RESET_N | 15768c2ecf20Sopenharmony_ci KL1_UIDE_ENABLE); 15778c2ecf20Sopenharmony_ci 15788c2ecf20Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); 15798c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR2, KL2_IOBUS_ENABLE); 15808c2ecf20Sopenharmony_ci 15818c2ecf20Sopenharmony_ci temp = MACIO_IN32(KEYLARGO_FCR3); 15828c2ecf20Sopenharmony_ci if (macio->rev >= 2) { 15838c2ecf20Sopenharmony_ci temp |= KL3_SHUTDOWN_PLL2X; 15848c2ecf20Sopenharmony_ci if (sleep_mode) 15858c2ecf20Sopenharmony_ci temp |= KL3_SHUTDOWN_PLL_TOTAL; 15868c2ecf20Sopenharmony_ci } 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 | 15898c2ecf20Sopenharmony_ci KL3_SHUTDOWN_PLLKW35; 15908c2ecf20Sopenharmony_ci if (sleep_mode) 15918c2ecf20Sopenharmony_ci temp |= KL3_SHUTDOWN_PLLKW12; 15928c2ecf20Sopenharmony_ci temp &= ~(KL3_CLK66_ENABLE | KL3_CLK49_ENABLE | KL3_CLK45_ENABLE 15938c2ecf20Sopenharmony_ci | KL3_CLK31_ENABLE | KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE); 15948c2ecf20Sopenharmony_ci if (sleep_mode) 15958c2ecf20Sopenharmony_ci temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE); 15968c2ecf20Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR3, temp); 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_ci /* Flush posted writes & wait a bit */ 15998c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1); 16008c2ecf20Sopenharmony_ci} 16018c2ecf20Sopenharmony_ci 16028c2ecf20Sopenharmony_cistatic void pangea_shutdown(struct macio_chip *macio, int sleep_mode) 16038c2ecf20Sopenharmony_ci{ 16048c2ecf20Sopenharmony_ci u32 temp; 16058c2ecf20Sopenharmony_ci 16068c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | 16078c2ecf20Sopenharmony_ci KL0_SCC_CELL_ENABLE | 16088c2ecf20Sopenharmony_ci KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE); 16098c2ecf20Sopenharmony_ci 16108c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR1, 16118c2ecf20Sopenharmony_ci KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT | 16128c2ecf20Sopenharmony_ci KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE | 16138c2ecf20Sopenharmony_ci KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT | 16148c2ecf20Sopenharmony_ci KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE | 16158c2ecf20Sopenharmony_ci KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE | 16168c2ecf20Sopenharmony_ci KL1_UIDE_ENABLE); 16178c2ecf20Sopenharmony_ci if (pmac_mb.board_flags & PMAC_MB_MOBILE) 16188c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N); 16198c2ecf20Sopenharmony_ci 16208c2ecf20Sopenharmony_ci MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); 16218c2ecf20Sopenharmony_ci 16228c2ecf20Sopenharmony_ci temp = MACIO_IN32(KEYLARGO_FCR3); 16238c2ecf20Sopenharmony_ci temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 | 16248c2ecf20Sopenharmony_ci KL3_SHUTDOWN_PLLKW35; 16258c2ecf20Sopenharmony_ci temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | KL3_CLK31_ENABLE 16268c2ecf20Sopenharmony_ci | KL3_I2S0_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE); 16278c2ecf20Sopenharmony_ci if (sleep_mode) 16288c2ecf20Sopenharmony_ci temp &= ~(KL3_VIA_CLK16_ENABLE | KL3_TIMER_CLK18_ENABLE); 16298c2ecf20Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR3, temp); 16308c2ecf20Sopenharmony_ci 16318c2ecf20Sopenharmony_ci /* Flush posted writes & wait a bit */ 16328c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1); 16338c2ecf20Sopenharmony_ci} 16348c2ecf20Sopenharmony_ci 16358c2ecf20Sopenharmony_cistatic void intrepid_shutdown(struct macio_chip *macio, int sleep_mode) 16368c2ecf20Sopenharmony_ci{ 16378c2ecf20Sopenharmony_ci u32 temp; 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | 16408c2ecf20Sopenharmony_ci KL0_SCC_CELL_ENABLE); 16418c2ecf20Sopenharmony_ci 16428c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR1, 16438c2ecf20Sopenharmony_ci KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT | 16448c2ecf20Sopenharmony_ci KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE | 16458c2ecf20Sopenharmony_ci KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE | 16468c2ecf20Sopenharmony_ci KL1_EIDE0_ENABLE); 16478c2ecf20Sopenharmony_ci if (pmac_mb.board_flags & PMAC_MB_MOBILE) 16488c2ecf20Sopenharmony_ci MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N); 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_ci temp = MACIO_IN32(KEYLARGO_FCR3); 16518c2ecf20Sopenharmony_ci temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | 16528c2ecf20Sopenharmony_ci KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE); 16538c2ecf20Sopenharmony_ci if (sleep_mode) 16548c2ecf20Sopenharmony_ci temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_IT_VIA_CLK32_ENABLE); 16558c2ecf20Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR3, temp); 16568c2ecf20Sopenharmony_ci 16578c2ecf20Sopenharmony_ci /* Flush posted writes & wait a bit */ 16588c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); 16598c2ecf20Sopenharmony_ci mdelay(10); 16608c2ecf20Sopenharmony_ci} 16618c2ecf20Sopenharmony_ci 16628c2ecf20Sopenharmony_ci 16638c2ecf20Sopenharmony_cistatic int 16648c2ecf20Sopenharmony_cicore99_sleep(void) 16658c2ecf20Sopenharmony_ci{ 16668c2ecf20Sopenharmony_ci struct macio_chip *macio; 16678c2ecf20Sopenharmony_ci int i; 16688c2ecf20Sopenharmony_ci 16698c2ecf20Sopenharmony_ci macio = &macio_chips[0]; 16708c2ecf20Sopenharmony_ci if (macio->type != macio_keylargo && macio->type != macio_pangea && 16718c2ecf20Sopenharmony_ci macio->type != macio_intrepid) 16728c2ecf20Sopenharmony_ci return -ENODEV; 16738c2ecf20Sopenharmony_ci 16748c2ecf20Sopenharmony_ci /* We power off the wireless slot in case it was not done 16758c2ecf20Sopenharmony_ci * by the driver. We don't power it on automatically however 16768c2ecf20Sopenharmony_ci */ 16778c2ecf20Sopenharmony_ci if (macio->flags & MACIO_FLAG_AIRPORT_ON) 16788c2ecf20Sopenharmony_ci core99_airport_enable(macio->of_node, 0, 0); 16798c2ecf20Sopenharmony_ci 16808c2ecf20Sopenharmony_ci /* We power off the FW cable. Should be done by the driver... */ 16818c2ecf20Sopenharmony_ci if (macio->flags & MACIO_FLAG_FW_SUPPORTED) { 16828c2ecf20Sopenharmony_ci core99_firewire_enable(NULL, 0, 0); 16838c2ecf20Sopenharmony_ci core99_firewire_cable_power(NULL, 0, 0); 16848c2ecf20Sopenharmony_ci } 16858c2ecf20Sopenharmony_ci 16868c2ecf20Sopenharmony_ci /* We make sure int. modem is off (in case driver lost it) */ 16878c2ecf20Sopenharmony_ci if (macio->type == macio_keylargo) 16888c2ecf20Sopenharmony_ci core99_modem_enable(macio->of_node, 0, 0); 16898c2ecf20Sopenharmony_ci else 16908c2ecf20Sopenharmony_ci pangea_modem_enable(macio->of_node, 0, 0); 16918c2ecf20Sopenharmony_ci 16928c2ecf20Sopenharmony_ci /* We make sure the sound is off as well */ 16938c2ecf20Sopenharmony_ci core99_sound_chip_enable(macio->of_node, 0, 0); 16948c2ecf20Sopenharmony_ci 16958c2ecf20Sopenharmony_ci /* 16968c2ecf20Sopenharmony_ci * Save various bits of KeyLargo 16978c2ecf20Sopenharmony_ci */ 16988c2ecf20Sopenharmony_ci 16998c2ecf20Sopenharmony_ci /* Save the state of the various GPIOs */ 17008c2ecf20Sopenharmony_ci save_gpio_levels[0] = MACIO_IN32(KEYLARGO_GPIO_LEVELS0); 17018c2ecf20Sopenharmony_ci save_gpio_levels[1] = MACIO_IN32(KEYLARGO_GPIO_LEVELS1); 17028c2ecf20Sopenharmony_ci for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++) 17038c2ecf20Sopenharmony_ci save_gpio_extint[i] = MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+i); 17048c2ecf20Sopenharmony_ci for (i=0; i<KEYLARGO_GPIO_CNT; i++) 17058c2ecf20Sopenharmony_ci save_gpio_normal[i] = MACIO_IN8(KEYLARGO_GPIO_0+i); 17068c2ecf20Sopenharmony_ci 17078c2ecf20Sopenharmony_ci /* Save the FCRs */ 17088c2ecf20Sopenharmony_ci if (macio->type == macio_keylargo) 17098c2ecf20Sopenharmony_ci save_mbcr = MACIO_IN32(KEYLARGO_MBCR); 17108c2ecf20Sopenharmony_ci save_fcr[0] = MACIO_IN32(KEYLARGO_FCR0); 17118c2ecf20Sopenharmony_ci save_fcr[1] = MACIO_IN32(KEYLARGO_FCR1); 17128c2ecf20Sopenharmony_ci save_fcr[2] = MACIO_IN32(KEYLARGO_FCR2); 17138c2ecf20Sopenharmony_ci save_fcr[3] = MACIO_IN32(KEYLARGO_FCR3); 17148c2ecf20Sopenharmony_ci save_fcr[4] = MACIO_IN32(KEYLARGO_FCR4); 17158c2ecf20Sopenharmony_ci if (macio->type == macio_pangea || macio->type == macio_intrepid) 17168c2ecf20Sopenharmony_ci save_fcr[5] = MACIO_IN32(KEYLARGO_FCR5); 17178c2ecf20Sopenharmony_ci 17188c2ecf20Sopenharmony_ci /* Save state & config of DBDMA channels */ 17198c2ecf20Sopenharmony_ci dbdma_save(macio, save_dbdma); 17208c2ecf20Sopenharmony_ci 17218c2ecf20Sopenharmony_ci /* 17228c2ecf20Sopenharmony_ci * Turn off as much as we can 17238c2ecf20Sopenharmony_ci */ 17248c2ecf20Sopenharmony_ci if (macio->type == macio_pangea) 17258c2ecf20Sopenharmony_ci pangea_shutdown(macio, 1); 17268c2ecf20Sopenharmony_ci else if (macio->type == macio_intrepid) 17278c2ecf20Sopenharmony_ci intrepid_shutdown(macio, 1); 17288c2ecf20Sopenharmony_ci else if (macio->type == macio_keylargo) 17298c2ecf20Sopenharmony_ci keylargo_shutdown(macio, 1); 17308c2ecf20Sopenharmony_ci 17318c2ecf20Sopenharmony_ci /* 17328c2ecf20Sopenharmony_ci * Put the host bridge to sleep 17338c2ecf20Sopenharmony_ci */ 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_ci save_unin_clock_ctl = UN_IN(UNI_N_CLOCK_CNTL); 17368c2ecf20Sopenharmony_ci /* Note: do not switch GMAC off, driver does it when necessary, WOL must keep it 17378c2ecf20Sopenharmony_ci * enabled ! 17388c2ecf20Sopenharmony_ci */ 17398c2ecf20Sopenharmony_ci UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl & 17408c2ecf20Sopenharmony_ci ~(/*UNI_N_CLOCK_CNTL_GMAC|*/UNI_N_CLOCK_CNTL_FW/*|UNI_N_CLOCK_CNTL_PCI*/)); 17418c2ecf20Sopenharmony_ci udelay(100); 17428c2ecf20Sopenharmony_ci UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING); 17438c2ecf20Sopenharmony_ci UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_SLEEP); 17448c2ecf20Sopenharmony_ci mdelay(10); 17458c2ecf20Sopenharmony_ci 17468c2ecf20Sopenharmony_ci /* 17478c2ecf20Sopenharmony_ci * FIXME: A bit of black magic with OpenPIC (don't ask me why) 17488c2ecf20Sopenharmony_ci */ 17498c2ecf20Sopenharmony_ci if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) { 17508c2ecf20Sopenharmony_ci MACIO_BIS(0x506e0, 0x00400000); 17518c2ecf20Sopenharmony_ci MACIO_BIS(0x506e0, 0x80000000); 17528c2ecf20Sopenharmony_ci } 17538c2ecf20Sopenharmony_ci return 0; 17548c2ecf20Sopenharmony_ci} 17558c2ecf20Sopenharmony_ci 17568c2ecf20Sopenharmony_cistatic int 17578c2ecf20Sopenharmony_cicore99_wake_up(void) 17588c2ecf20Sopenharmony_ci{ 17598c2ecf20Sopenharmony_ci struct macio_chip *macio; 17608c2ecf20Sopenharmony_ci int i; 17618c2ecf20Sopenharmony_ci 17628c2ecf20Sopenharmony_ci macio = &macio_chips[0]; 17638c2ecf20Sopenharmony_ci if (macio->type != macio_keylargo && macio->type != macio_pangea && 17648c2ecf20Sopenharmony_ci macio->type != macio_intrepid) 17658c2ecf20Sopenharmony_ci return -ENODEV; 17668c2ecf20Sopenharmony_ci 17678c2ecf20Sopenharmony_ci /* 17688c2ecf20Sopenharmony_ci * Wakeup the host bridge 17698c2ecf20Sopenharmony_ci */ 17708c2ecf20Sopenharmony_ci UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL); 17718c2ecf20Sopenharmony_ci udelay(10); 17728c2ecf20Sopenharmony_ci UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING); 17738c2ecf20Sopenharmony_ci udelay(10); 17748c2ecf20Sopenharmony_ci 17758c2ecf20Sopenharmony_ci /* 17768c2ecf20Sopenharmony_ci * Restore KeyLargo 17778c2ecf20Sopenharmony_ci */ 17788c2ecf20Sopenharmony_ci 17798c2ecf20Sopenharmony_ci if (macio->type == macio_keylargo) { 17808c2ecf20Sopenharmony_ci MACIO_OUT32(KEYLARGO_MBCR, save_mbcr); 17818c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_MBCR); udelay(10); 17828c2ecf20Sopenharmony_ci } 17838c2ecf20Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR0, save_fcr[0]); 17848c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR0); udelay(10); 17858c2ecf20Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR1, save_fcr[1]); 17868c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR1); udelay(10); 17878c2ecf20Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR2, save_fcr[2]); 17888c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR2); udelay(10); 17898c2ecf20Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR3, save_fcr[3]); 17908c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR3); udelay(10); 17918c2ecf20Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR4, save_fcr[4]); 17928c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR4); udelay(10); 17938c2ecf20Sopenharmony_ci if (macio->type == macio_pangea || macio->type == macio_intrepid) { 17948c2ecf20Sopenharmony_ci MACIO_OUT32(KEYLARGO_FCR5, save_fcr[5]); 17958c2ecf20Sopenharmony_ci (void)MACIO_IN32(KEYLARGO_FCR5); udelay(10); 17968c2ecf20Sopenharmony_ci } 17978c2ecf20Sopenharmony_ci 17988c2ecf20Sopenharmony_ci dbdma_restore(macio, save_dbdma); 17998c2ecf20Sopenharmony_ci 18008c2ecf20Sopenharmony_ci MACIO_OUT32(KEYLARGO_GPIO_LEVELS0, save_gpio_levels[0]); 18018c2ecf20Sopenharmony_ci MACIO_OUT32(KEYLARGO_GPIO_LEVELS1, save_gpio_levels[1]); 18028c2ecf20Sopenharmony_ci for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++) 18038c2ecf20Sopenharmony_ci MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+i, save_gpio_extint[i]); 18048c2ecf20Sopenharmony_ci for (i=0; i<KEYLARGO_GPIO_CNT; i++) 18058c2ecf20Sopenharmony_ci MACIO_OUT8(KEYLARGO_GPIO_0+i, save_gpio_normal[i]); 18068c2ecf20Sopenharmony_ci 18078c2ecf20Sopenharmony_ci /* FIXME more black magic with OpenPIC ... */ 18088c2ecf20Sopenharmony_ci if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) { 18098c2ecf20Sopenharmony_ci MACIO_BIC(0x506e0, 0x00400000); 18108c2ecf20Sopenharmony_ci MACIO_BIC(0x506e0, 0x80000000); 18118c2ecf20Sopenharmony_ci } 18128c2ecf20Sopenharmony_ci 18138c2ecf20Sopenharmony_ci UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl); 18148c2ecf20Sopenharmony_ci udelay(100); 18158c2ecf20Sopenharmony_ci 18168c2ecf20Sopenharmony_ci return 0; 18178c2ecf20Sopenharmony_ci} 18188c2ecf20Sopenharmony_ci 18198c2ecf20Sopenharmony_ci#endif /* CONFIG_PM */ 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_cistatic long 18228c2ecf20Sopenharmony_cicore99_sleep_state(struct device_node *node, long param, long value) 18238c2ecf20Sopenharmony_ci{ 18248c2ecf20Sopenharmony_ci /* Param == 1 means to enter the "fake sleep" mode that is 18258c2ecf20Sopenharmony_ci * used for CPU speed switch 18268c2ecf20Sopenharmony_ci */ 18278c2ecf20Sopenharmony_ci if (param == 1) { 18288c2ecf20Sopenharmony_ci if (value == 1) { 18298c2ecf20Sopenharmony_ci UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING); 18308c2ecf20Sopenharmony_ci UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_IDLE2); 18318c2ecf20Sopenharmony_ci } else { 18328c2ecf20Sopenharmony_ci UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL); 18338c2ecf20Sopenharmony_ci udelay(10); 18348c2ecf20Sopenharmony_ci UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING); 18358c2ecf20Sopenharmony_ci udelay(10); 18368c2ecf20Sopenharmony_ci } 18378c2ecf20Sopenharmony_ci return 0; 18388c2ecf20Sopenharmony_ci } 18398c2ecf20Sopenharmony_ci if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0) 18408c2ecf20Sopenharmony_ci return -EPERM; 18418c2ecf20Sopenharmony_ci 18428c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 18438c2ecf20Sopenharmony_ci if (value == 1) 18448c2ecf20Sopenharmony_ci return core99_sleep(); 18458c2ecf20Sopenharmony_ci else if (value == 0) 18468c2ecf20Sopenharmony_ci return core99_wake_up(); 18478c2ecf20Sopenharmony_ci 18488c2ecf20Sopenharmony_ci#endif /* CONFIG_PM */ 18498c2ecf20Sopenharmony_ci return 0; 18508c2ecf20Sopenharmony_ci} 18518c2ecf20Sopenharmony_ci 18528c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC64 */ 18538c2ecf20Sopenharmony_ci 18548c2ecf20Sopenharmony_cistatic long 18558c2ecf20Sopenharmony_cigeneric_dev_can_wake(struct device_node *node, long param, long value) 18568c2ecf20Sopenharmony_ci{ 18578c2ecf20Sopenharmony_ci /* Todo: eventually check we are really dealing with on-board 18588c2ecf20Sopenharmony_ci * video device ... 18598c2ecf20Sopenharmony_ci */ 18608c2ecf20Sopenharmony_ci 18618c2ecf20Sopenharmony_ci if (pmac_mb.board_flags & PMAC_MB_MAY_SLEEP) 18628c2ecf20Sopenharmony_ci pmac_mb.board_flags |= PMAC_MB_CAN_SLEEP; 18638c2ecf20Sopenharmony_ci return 0; 18648c2ecf20Sopenharmony_ci} 18658c2ecf20Sopenharmony_ci 18668c2ecf20Sopenharmony_cistatic long generic_get_mb_info(struct device_node *node, long param, long value) 18678c2ecf20Sopenharmony_ci{ 18688c2ecf20Sopenharmony_ci switch(param) { 18698c2ecf20Sopenharmony_ci case PMAC_MB_INFO_MODEL: 18708c2ecf20Sopenharmony_ci return pmac_mb.model_id; 18718c2ecf20Sopenharmony_ci case PMAC_MB_INFO_FLAGS: 18728c2ecf20Sopenharmony_ci return pmac_mb.board_flags; 18738c2ecf20Sopenharmony_ci case PMAC_MB_INFO_NAME: 18748c2ecf20Sopenharmony_ci /* hack hack hack... but should work */ 18758c2ecf20Sopenharmony_ci *((const char **)value) = pmac_mb.model_name; 18768c2ecf20Sopenharmony_ci return 0; 18778c2ecf20Sopenharmony_ci } 18788c2ecf20Sopenharmony_ci return -EINVAL; 18798c2ecf20Sopenharmony_ci} 18808c2ecf20Sopenharmony_ci 18818c2ecf20Sopenharmony_ci 18828c2ecf20Sopenharmony_ci/* 18838c2ecf20Sopenharmony_ci * Table definitions 18848c2ecf20Sopenharmony_ci */ 18858c2ecf20Sopenharmony_ci 18868c2ecf20Sopenharmony_ci/* Used on any machine 18878c2ecf20Sopenharmony_ci */ 18888c2ecf20Sopenharmony_cistatic struct feature_table_entry any_features[] = { 18898c2ecf20Sopenharmony_ci { PMAC_FTR_GET_MB_INFO, generic_get_mb_info }, 18908c2ecf20Sopenharmony_ci { PMAC_FTR_DEVICE_CAN_WAKE, generic_dev_can_wake }, 18918c2ecf20Sopenharmony_ci { 0, NULL } 18928c2ecf20Sopenharmony_ci}; 18938c2ecf20Sopenharmony_ci 18948c2ecf20Sopenharmony_ci#ifndef CONFIG_PPC64 18958c2ecf20Sopenharmony_ci 18968c2ecf20Sopenharmony_ci/* OHare based motherboards. Currently, we only use these on the 18978c2ecf20Sopenharmony_ci * 2400,3400 and 3500 series powerbooks. Some older desktops seem 18988c2ecf20Sopenharmony_ci * to have issues with turning on/off those asic cells 18998c2ecf20Sopenharmony_ci */ 19008c2ecf20Sopenharmony_cistatic struct feature_table_entry ohare_features[] = { 19018c2ecf20Sopenharmony_ci { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable }, 19028c2ecf20Sopenharmony_ci { PMAC_FTR_SWIM3_ENABLE, ohare_floppy_enable }, 19038c2ecf20Sopenharmony_ci { PMAC_FTR_MESH_ENABLE, ohare_mesh_enable }, 19048c2ecf20Sopenharmony_ci { PMAC_FTR_IDE_ENABLE, ohare_ide_enable}, 19058c2ecf20Sopenharmony_ci { PMAC_FTR_IDE_RESET, ohare_ide_reset}, 19068c2ecf20Sopenharmony_ci { PMAC_FTR_SLEEP_STATE, ohare_sleep_state }, 19078c2ecf20Sopenharmony_ci { 0, NULL } 19088c2ecf20Sopenharmony_ci}; 19098c2ecf20Sopenharmony_ci 19108c2ecf20Sopenharmony_ci/* Heathrow desktop machines (Beige G3). 19118c2ecf20Sopenharmony_ci * Separated as some features couldn't be properly tested 19128c2ecf20Sopenharmony_ci * and the serial port control bits appear to confuse it. 19138c2ecf20Sopenharmony_ci */ 19148c2ecf20Sopenharmony_cistatic struct feature_table_entry heathrow_desktop_features[] = { 19158c2ecf20Sopenharmony_ci { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable }, 19168c2ecf20Sopenharmony_ci { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable }, 19178c2ecf20Sopenharmony_ci { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable }, 19188c2ecf20Sopenharmony_ci { PMAC_FTR_IDE_RESET, heathrow_ide_reset }, 19198c2ecf20Sopenharmony_ci { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable }, 19208c2ecf20Sopenharmony_ci { 0, NULL } 19218c2ecf20Sopenharmony_ci}; 19228c2ecf20Sopenharmony_ci 19238c2ecf20Sopenharmony_ci/* Heathrow based laptop, that is the Wallstreet and mainstreet 19248c2ecf20Sopenharmony_ci * powerbooks. 19258c2ecf20Sopenharmony_ci */ 19268c2ecf20Sopenharmony_cistatic struct feature_table_entry heathrow_laptop_features[] = { 19278c2ecf20Sopenharmony_ci { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable }, 19288c2ecf20Sopenharmony_ci { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable }, 19298c2ecf20Sopenharmony_ci { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable }, 19308c2ecf20Sopenharmony_ci { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable }, 19318c2ecf20Sopenharmony_ci { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable }, 19328c2ecf20Sopenharmony_ci { PMAC_FTR_IDE_RESET, heathrow_ide_reset }, 19338c2ecf20Sopenharmony_ci { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable }, 19348c2ecf20Sopenharmony_ci { PMAC_FTR_SOUND_CHIP_ENABLE, heathrow_sound_enable }, 19358c2ecf20Sopenharmony_ci { PMAC_FTR_SLEEP_STATE, heathrow_sleep_state }, 19368c2ecf20Sopenharmony_ci { 0, NULL } 19378c2ecf20Sopenharmony_ci}; 19388c2ecf20Sopenharmony_ci 19398c2ecf20Sopenharmony_ci/* Paddington based machines 19408c2ecf20Sopenharmony_ci * The lombard (101) powerbook, first iMac models, B&W G3 and Yikes G4. 19418c2ecf20Sopenharmony_ci */ 19428c2ecf20Sopenharmony_cistatic struct feature_table_entry paddington_features[] = { 19438c2ecf20Sopenharmony_ci { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable }, 19448c2ecf20Sopenharmony_ci { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable }, 19458c2ecf20Sopenharmony_ci { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable }, 19468c2ecf20Sopenharmony_ci { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable }, 19478c2ecf20Sopenharmony_ci { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable }, 19488c2ecf20Sopenharmony_ci { PMAC_FTR_IDE_RESET, heathrow_ide_reset }, 19498c2ecf20Sopenharmony_ci { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable }, 19508c2ecf20Sopenharmony_ci { PMAC_FTR_SOUND_CHIP_ENABLE, heathrow_sound_enable }, 19518c2ecf20Sopenharmony_ci { PMAC_FTR_SLEEP_STATE, heathrow_sleep_state }, 19528c2ecf20Sopenharmony_ci { 0, NULL } 19538c2ecf20Sopenharmony_ci}; 19548c2ecf20Sopenharmony_ci 19558c2ecf20Sopenharmony_ci/* Core99 & MacRISC 2 machines (all machines released since the 19568c2ecf20Sopenharmony_ci * iBook (included), that is all AGP machines, except pangea 19578c2ecf20Sopenharmony_ci * chipset. The pangea chipset is the "combo" UniNorth/KeyLargo 19588c2ecf20Sopenharmony_ci * used on iBook2 & iMac "flow power". 19598c2ecf20Sopenharmony_ci */ 19608c2ecf20Sopenharmony_cistatic struct feature_table_entry core99_features[] = { 19618c2ecf20Sopenharmony_ci { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, 19628c2ecf20Sopenharmony_ci { PMAC_FTR_MODEM_ENABLE, core99_modem_enable }, 19638c2ecf20Sopenharmony_ci { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, 19648c2ecf20Sopenharmony_ci { PMAC_FTR_IDE_RESET, core99_ide_reset }, 19658c2ecf20Sopenharmony_ci { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable }, 19668c2ecf20Sopenharmony_ci { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset }, 19678c2ecf20Sopenharmony_ci { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable }, 19688c2ecf20Sopenharmony_ci { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable }, 19698c2ecf20Sopenharmony_ci { PMAC_FTR_USB_ENABLE, core99_usb_enable }, 19708c2ecf20Sopenharmony_ci { PMAC_FTR_1394_ENABLE, core99_firewire_enable }, 19718c2ecf20Sopenharmony_ci { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power }, 19728c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 19738c2ecf20Sopenharmony_ci { PMAC_FTR_SLEEP_STATE, core99_sleep_state }, 19748c2ecf20Sopenharmony_ci#endif 19758c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 19768c2ecf20Sopenharmony_ci { PMAC_FTR_RESET_CPU, core99_reset_cpu }, 19778c2ecf20Sopenharmony_ci#endif /* CONFIG_SMP */ 19788c2ecf20Sopenharmony_ci { PMAC_FTR_READ_GPIO, core99_read_gpio }, 19798c2ecf20Sopenharmony_ci { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, 19808c2ecf20Sopenharmony_ci { 0, NULL } 19818c2ecf20Sopenharmony_ci}; 19828c2ecf20Sopenharmony_ci 19838c2ecf20Sopenharmony_ci/* RackMac 19848c2ecf20Sopenharmony_ci */ 19858c2ecf20Sopenharmony_cistatic struct feature_table_entry rackmac_features[] = { 19868c2ecf20Sopenharmony_ci { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, 19878c2ecf20Sopenharmony_ci { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, 19888c2ecf20Sopenharmony_ci { PMAC_FTR_IDE_RESET, core99_ide_reset }, 19898c2ecf20Sopenharmony_ci { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable }, 19908c2ecf20Sopenharmony_ci { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset }, 19918c2ecf20Sopenharmony_ci { PMAC_FTR_USB_ENABLE, core99_usb_enable }, 19928c2ecf20Sopenharmony_ci { PMAC_FTR_1394_ENABLE, core99_firewire_enable }, 19938c2ecf20Sopenharmony_ci { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power }, 19948c2ecf20Sopenharmony_ci { PMAC_FTR_SLEEP_STATE, core99_sleep_state }, 19958c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 19968c2ecf20Sopenharmony_ci { PMAC_FTR_RESET_CPU, core99_reset_cpu }, 19978c2ecf20Sopenharmony_ci#endif /* CONFIG_SMP */ 19988c2ecf20Sopenharmony_ci { PMAC_FTR_READ_GPIO, core99_read_gpio }, 19998c2ecf20Sopenharmony_ci { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, 20008c2ecf20Sopenharmony_ci { 0, NULL } 20018c2ecf20Sopenharmony_ci}; 20028c2ecf20Sopenharmony_ci 20038c2ecf20Sopenharmony_ci/* Pangea features 20048c2ecf20Sopenharmony_ci */ 20058c2ecf20Sopenharmony_cistatic struct feature_table_entry pangea_features[] = { 20068c2ecf20Sopenharmony_ci { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, 20078c2ecf20Sopenharmony_ci { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable }, 20088c2ecf20Sopenharmony_ci { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, 20098c2ecf20Sopenharmony_ci { PMAC_FTR_IDE_RESET, core99_ide_reset }, 20108c2ecf20Sopenharmony_ci { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable }, 20118c2ecf20Sopenharmony_ci { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset }, 20128c2ecf20Sopenharmony_ci { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable }, 20138c2ecf20Sopenharmony_ci { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable }, 20148c2ecf20Sopenharmony_ci { PMAC_FTR_USB_ENABLE, core99_usb_enable }, 20158c2ecf20Sopenharmony_ci { PMAC_FTR_1394_ENABLE, core99_firewire_enable }, 20168c2ecf20Sopenharmony_ci { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power }, 20178c2ecf20Sopenharmony_ci { PMAC_FTR_SLEEP_STATE, core99_sleep_state }, 20188c2ecf20Sopenharmony_ci { PMAC_FTR_READ_GPIO, core99_read_gpio }, 20198c2ecf20Sopenharmony_ci { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, 20208c2ecf20Sopenharmony_ci { 0, NULL } 20218c2ecf20Sopenharmony_ci}; 20228c2ecf20Sopenharmony_ci 20238c2ecf20Sopenharmony_ci/* Intrepid features 20248c2ecf20Sopenharmony_ci */ 20258c2ecf20Sopenharmony_cistatic struct feature_table_entry intrepid_features[] = { 20268c2ecf20Sopenharmony_ci { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, 20278c2ecf20Sopenharmony_ci { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable }, 20288c2ecf20Sopenharmony_ci { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, 20298c2ecf20Sopenharmony_ci { PMAC_FTR_IDE_RESET, core99_ide_reset }, 20308c2ecf20Sopenharmony_ci { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable }, 20318c2ecf20Sopenharmony_ci { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset }, 20328c2ecf20Sopenharmony_ci { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable }, 20338c2ecf20Sopenharmony_ci { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable }, 20348c2ecf20Sopenharmony_ci { PMAC_FTR_USB_ENABLE, core99_usb_enable }, 20358c2ecf20Sopenharmony_ci { PMAC_FTR_1394_ENABLE, core99_firewire_enable }, 20368c2ecf20Sopenharmony_ci { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power }, 20378c2ecf20Sopenharmony_ci { PMAC_FTR_SLEEP_STATE, core99_sleep_state }, 20388c2ecf20Sopenharmony_ci { PMAC_FTR_READ_GPIO, core99_read_gpio }, 20398c2ecf20Sopenharmony_ci { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, 20408c2ecf20Sopenharmony_ci { PMAC_FTR_AACK_DELAY_ENABLE, intrepid_aack_delay_enable }, 20418c2ecf20Sopenharmony_ci { 0, NULL } 20428c2ecf20Sopenharmony_ci}; 20438c2ecf20Sopenharmony_ci 20448c2ecf20Sopenharmony_ci#else /* CONFIG_PPC64 */ 20458c2ecf20Sopenharmony_ci 20468c2ecf20Sopenharmony_ci/* G5 features 20478c2ecf20Sopenharmony_ci */ 20488c2ecf20Sopenharmony_cistatic struct feature_table_entry g5_features[] = { 20498c2ecf20Sopenharmony_ci { PMAC_FTR_GMAC_ENABLE, g5_gmac_enable }, 20508c2ecf20Sopenharmony_ci { PMAC_FTR_1394_ENABLE, g5_fw_enable }, 20518c2ecf20Sopenharmony_ci { PMAC_FTR_ENABLE_MPIC, g5_mpic_enable }, 20528c2ecf20Sopenharmony_ci { PMAC_FTR_GMAC_PHY_RESET, g5_eth_phy_reset }, 20538c2ecf20Sopenharmony_ci { PMAC_FTR_SOUND_CHIP_ENABLE, g5_i2s_enable }, 20548c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 20558c2ecf20Sopenharmony_ci { PMAC_FTR_RESET_CPU, g5_reset_cpu }, 20568c2ecf20Sopenharmony_ci#endif /* CONFIG_SMP */ 20578c2ecf20Sopenharmony_ci { PMAC_FTR_READ_GPIO, core99_read_gpio }, 20588c2ecf20Sopenharmony_ci { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, 20598c2ecf20Sopenharmony_ci { 0, NULL } 20608c2ecf20Sopenharmony_ci}; 20618c2ecf20Sopenharmony_ci 20628c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC64 */ 20638c2ecf20Sopenharmony_ci 20648c2ecf20Sopenharmony_cistatic struct pmac_mb_def pmac_mb_defs[] = { 20658c2ecf20Sopenharmony_ci#ifndef CONFIG_PPC64 20668c2ecf20Sopenharmony_ci /* 20678c2ecf20Sopenharmony_ci * Desktops 20688c2ecf20Sopenharmony_ci */ 20698c2ecf20Sopenharmony_ci 20708c2ecf20Sopenharmony_ci { "AAPL,8500", "PowerMac 8500/8600", 20718c2ecf20Sopenharmony_ci PMAC_TYPE_PSURGE, NULL, 20728c2ecf20Sopenharmony_ci 0 20738c2ecf20Sopenharmony_ci }, 20748c2ecf20Sopenharmony_ci { "AAPL,9500", "PowerMac 9500/9600", 20758c2ecf20Sopenharmony_ci PMAC_TYPE_PSURGE, NULL, 20768c2ecf20Sopenharmony_ci 0 20778c2ecf20Sopenharmony_ci }, 20788c2ecf20Sopenharmony_ci { "AAPL,7200", "PowerMac 7200", 20798c2ecf20Sopenharmony_ci PMAC_TYPE_PSURGE, NULL, 20808c2ecf20Sopenharmony_ci 0 20818c2ecf20Sopenharmony_ci }, 20828c2ecf20Sopenharmony_ci { "AAPL,7300", "PowerMac 7200/7300", 20838c2ecf20Sopenharmony_ci PMAC_TYPE_PSURGE, NULL, 20848c2ecf20Sopenharmony_ci 0 20858c2ecf20Sopenharmony_ci }, 20868c2ecf20Sopenharmony_ci { "AAPL,7500", "PowerMac 7500", 20878c2ecf20Sopenharmony_ci PMAC_TYPE_PSURGE, NULL, 20888c2ecf20Sopenharmony_ci 0 20898c2ecf20Sopenharmony_ci }, 20908c2ecf20Sopenharmony_ci { "AAPL,ShinerESB", "Apple Network Server", 20918c2ecf20Sopenharmony_ci PMAC_TYPE_ANS, NULL, 20928c2ecf20Sopenharmony_ci 0 20938c2ecf20Sopenharmony_ci }, 20948c2ecf20Sopenharmony_ci { "AAPL,e407", "Alchemy", 20958c2ecf20Sopenharmony_ci PMAC_TYPE_ALCHEMY, NULL, 20968c2ecf20Sopenharmony_ci 0 20978c2ecf20Sopenharmony_ci }, 20988c2ecf20Sopenharmony_ci { "AAPL,e411", "Gazelle", 20998c2ecf20Sopenharmony_ci PMAC_TYPE_GAZELLE, NULL, 21008c2ecf20Sopenharmony_ci 0 21018c2ecf20Sopenharmony_ci }, 21028c2ecf20Sopenharmony_ci { "AAPL,Gossamer", "PowerMac G3 (Gossamer)", 21038c2ecf20Sopenharmony_ci PMAC_TYPE_GOSSAMER, heathrow_desktop_features, 21048c2ecf20Sopenharmony_ci 0 21058c2ecf20Sopenharmony_ci }, 21068c2ecf20Sopenharmony_ci { "AAPL,PowerMac G3", "PowerMac G3 (Silk)", 21078c2ecf20Sopenharmony_ci PMAC_TYPE_SILK, heathrow_desktop_features, 21088c2ecf20Sopenharmony_ci 0 21098c2ecf20Sopenharmony_ci }, 21108c2ecf20Sopenharmony_ci { "PowerMac1,1", "Blue&White G3", 21118c2ecf20Sopenharmony_ci PMAC_TYPE_YOSEMITE, paddington_features, 21128c2ecf20Sopenharmony_ci 0 21138c2ecf20Sopenharmony_ci }, 21148c2ecf20Sopenharmony_ci { "PowerMac1,2", "PowerMac G4 PCI Graphics", 21158c2ecf20Sopenharmony_ci PMAC_TYPE_YIKES, paddington_features, 21168c2ecf20Sopenharmony_ci 0 21178c2ecf20Sopenharmony_ci }, 21188c2ecf20Sopenharmony_ci { "PowerMac2,1", "iMac FireWire", 21198c2ecf20Sopenharmony_ci PMAC_TYPE_FW_IMAC, core99_features, 21208c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99 21218c2ecf20Sopenharmony_ci }, 21228c2ecf20Sopenharmony_ci { "PowerMac2,2", "iMac FireWire", 21238c2ecf20Sopenharmony_ci PMAC_TYPE_FW_IMAC, core99_features, 21248c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99 21258c2ecf20Sopenharmony_ci }, 21268c2ecf20Sopenharmony_ci { "PowerMac3,1", "PowerMac G4 AGP Graphics", 21278c2ecf20Sopenharmony_ci PMAC_TYPE_SAWTOOTH, core99_features, 21288c2ecf20Sopenharmony_ci PMAC_MB_OLD_CORE99 21298c2ecf20Sopenharmony_ci }, 21308c2ecf20Sopenharmony_ci { "PowerMac3,2", "PowerMac G4 AGP Graphics", 21318c2ecf20Sopenharmony_ci PMAC_TYPE_SAWTOOTH, core99_features, 21328c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99 21338c2ecf20Sopenharmony_ci }, 21348c2ecf20Sopenharmony_ci { "PowerMac3,3", "PowerMac G4 AGP Graphics", 21358c2ecf20Sopenharmony_ci PMAC_TYPE_SAWTOOTH, core99_features, 21368c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99 21378c2ecf20Sopenharmony_ci }, 21388c2ecf20Sopenharmony_ci { "PowerMac3,4", "PowerMac G4 Silver", 21398c2ecf20Sopenharmony_ci PMAC_TYPE_QUICKSILVER, core99_features, 21408c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP 21418c2ecf20Sopenharmony_ci }, 21428c2ecf20Sopenharmony_ci { "PowerMac3,5", "PowerMac G4 Silver", 21438c2ecf20Sopenharmony_ci PMAC_TYPE_QUICKSILVER, core99_features, 21448c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP 21458c2ecf20Sopenharmony_ci }, 21468c2ecf20Sopenharmony_ci { "PowerMac3,6", "PowerMac G4 Windtunnel", 21478c2ecf20Sopenharmony_ci PMAC_TYPE_WINDTUNNEL, core99_features, 21488c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP, 21498c2ecf20Sopenharmony_ci }, 21508c2ecf20Sopenharmony_ci { "PowerMac4,1", "iMac \"Flower Power\"", 21518c2ecf20Sopenharmony_ci PMAC_TYPE_PANGEA_IMAC, pangea_features, 21528c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP 21538c2ecf20Sopenharmony_ci }, 21548c2ecf20Sopenharmony_ci { "PowerMac4,2", "Flat panel iMac", 21558c2ecf20Sopenharmony_ci PMAC_TYPE_FLAT_PANEL_IMAC, pangea_features, 21568c2ecf20Sopenharmony_ci PMAC_MB_CAN_SLEEP 21578c2ecf20Sopenharmony_ci }, 21588c2ecf20Sopenharmony_ci { "PowerMac4,4", "eMac", 21598c2ecf20Sopenharmony_ci PMAC_TYPE_EMAC, core99_features, 21608c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP 21618c2ecf20Sopenharmony_ci }, 21628c2ecf20Sopenharmony_ci { "PowerMac5,1", "PowerMac G4 Cube", 21638c2ecf20Sopenharmony_ci PMAC_TYPE_CUBE, core99_features, 21648c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99 21658c2ecf20Sopenharmony_ci }, 21668c2ecf20Sopenharmony_ci { "PowerMac6,1", "Flat panel iMac", 21678c2ecf20Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 21688c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP, 21698c2ecf20Sopenharmony_ci }, 21708c2ecf20Sopenharmony_ci { "PowerMac6,3", "Flat panel iMac", 21718c2ecf20Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 21728c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP, 21738c2ecf20Sopenharmony_ci }, 21748c2ecf20Sopenharmony_ci { "PowerMac6,4", "eMac", 21758c2ecf20Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 21768c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP, 21778c2ecf20Sopenharmony_ci }, 21788c2ecf20Sopenharmony_ci { "PowerMac10,1", "Mac mini", 21798c2ecf20Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 21808c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP, 21818c2ecf20Sopenharmony_ci }, 21828c2ecf20Sopenharmony_ci { "PowerMac10,2", "Mac mini (Late 2005)", 21838c2ecf20Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 21848c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP, 21858c2ecf20Sopenharmony_ci }, 21868c2ecf20Sopenharmony_ci { "iMac,1", "iMac (first generation)", 21878c2ecf20Sopenharmony_ci PMAC_TYPE_ORIG_IMAC, paddington_features, 21888c2ecf20Sopenharmony_ci 0 21898c2ecf20Sopenharmony_ci }, 21908c2ecf20Sopenharmony_ci 21918c2ecf20Sopenharmony_ci /* 21928c2ecf20Sopenharmony_ci * Xserve's 21938c2ecf20Sopenharmony_ci */ 21948c2ecf20Sopenharmony_ci 21958c2ecf20Sopenharmony_ci { "RackMac1,1", "XServe", 21968c2ecf20Sopenharmony_ci PMAC_TYPE_RACKMAC, rackmac_features, 21978c2ecf20Sopenharmony_ci 0, 21988c2ecf20Sopenharmony_ci }, 21998c2ecf20Sopenharmony_ci { "RackMac1,2", "XServe rev. 2", 22008c2ecf20Sopenharmony_ci PMAC_TYPE_RACKMAC, rackmac_features, 22018c2ecf20Sopenharmony_ci 0, 22028c2ecf20Sopenharmony_ci }, 22038c2ecf20Sopenharmony_ci 22048c2ecf20Sopenharmony_ci /* 22058c2ecf20Sopenharmony_ci * Laptops 22068c2ecf20Sopenharmony_ci */ 22078c2ecf20Sopenharmony_ci 22088c2ecf20Sopenharmony_ci { "AAPL,3400/2400", "PowerBook 3400", 22098c2ecf20Sopenharmony_ci PMAC_TYPE_HOOPER, ohare_features, 22108c2ecf20Sopenharmony_ci PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE 22118c2ecf20Sopenharmony_ci }, 22128c2ecf20Sopenharmony_ci { "AAPL,3500", "PowerBook 3500", 22138c2ecf20Sopenharmony_ci PMAC_TYPE_KANGA, ohare_features, 22148c2ecf20Sopenharmony_ci PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE 22158c2ecf20Sopenharmony_ci }, 22168c2ecf20Sopenharmony_ci { "AAPL,PowerBook1998", "PowerBook Wallstreet", 22178c2ecf20Sopenharmony_ci PMAC_TYPE_WALLSTREET, heathrow_laptop_features, 22188c2ecf20Sopenharmony_ci PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE 22198c2ecf20Sopenharmony_ci }, 22208c2ecf20Sopenharmony_ci { "PowerBook1,1", "PowerBook 101 (Lombard)", 22218c2ecf20Sopenharmony_ci PMAC_TYPE_101_PBOOK, paddington_features, 22228c2ecf20Sopenharmony_ci PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE 22238c2ecf20Sopenharmony_ci }, 22248c2ecf20Sopenharmony_ci { "PowerBook2,1", "iBook (first generation)", 22258c2ecf20Sopenharmony_ci PMAC_TYPE_ORIG_IBOOK, core99_features, 22268c2ecf20Sopenharmony_ci PMAC_MB_CAN_SLEEP | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE 22278c2ecf20Sopenharmony_ci }, 22288c2ecf20Sopenharmony_ci { "PowerBook2,2", "iBook FireWire", 22298c2ecf20Sopenharmony_ci PMAC_TYPE_FW_IBOOK, core99_features, 22308c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | 22318c2ecf20Sopenharmony_ci PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE 22328c2ecf20Sopenharmony_ci }, 22338c2ecf20Sopenharmony_ci { "PowerBook3,1", "PowerBook Pismo", 22348c2ecf20Sopenharmony_ci PMAC_TYPE_PISMO, core99_features, 22358c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | 22368c2ecf20Sopenharmony_ci PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE 22378c2ecf20Sopenharmony_ci }, 22388c2ecf20Sopenharmony_ci { "PowerBook3,2", "PowerBook Titanium", 22398c2ecf20Sopenharmony_ci PMAC_TYPE_TITANIUM, core99_features, 22408c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE 22418c2ecf20Sopenharmony_ci }, 22428c2ecf20Sopenharmony_ci { "PowerBook3,3", "PowerBook Titanium II", 22438c2ecf20Sopenharmony_ci PMAC_TYPE_TITANIUM2, core99_features, 22448c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE 22458c2ecf20Sopenharmony_ci }, 22468c2ecf20Sopenharmony_ci { "PowerBook3,4", "PowerBook Titanium III", 22478c2ecf20Sopenharmony_ci PMAC_TYPE_TITANIUM3, core99_features, 22488c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE 22498c2ecf20Sopenharmony_ci }, 22508c2ecf20Sopenharmony_ci { "PowerBook3,5", "PowerBook Titanium IV", 22518c2ecf20Sopenharmony_ci PMAC_TYPE_TITANIUM4, core99_features, 22528c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE 22538c2ecf20Sopenharmony_ci }, 22548c2ecf20Sopenharmony_ci { "PowerBook4,1", "iBook 2", 22558c2ecf20Sopenharmony_ci PMAC_TYPE_IBOOK2, pangea_features, 22568c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE 22578c2ecf20Sopenharmony_ci }, 22588c2ecf20Sopenharmony_ci { "PowerBook4,2", "iBook 2", 22598c2ecf20Sopenharmony_ci PMAC_TYPE_IBOOK2, pangea_features, 22608c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE 22618c2ecf20Sopenharmony_ci }, 22628c2ecf20Sopenharmony_ci { "PowerBook4,3", "iBook 2 rev. 2", 22638c2ecf20Sopenharmony_ci PMAC_TYPE_IBOOK2, pangea_features, 22648c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE 22658c2ecf20Sopenharmony_ci }, 22668c2ecf20Sopenharmony_ci { "PowerBook5,1", "PowerBook G4 17\"", 22678c2ecf20Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 22688c2ecf20Sopenharmony_ci PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 22698c2ecf20Sopenharmony_ci }, 22708c2ecf20Sopenharmony_ci { "PowerBook5,2", "PowerBook G4 15\"", 22718c2ecf20Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 22728c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 22738c2ecf20Sopenharmony_ci }, 22748c2ecf20Sopenharmony_ci { "PowerBook5,3", "PowerBook G4 17\"", 22758c2ecf20Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 22768c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 22778c2ecf20Sopenharmony_ci }, 22788c2ecf20Sopenharmony_ci { "PowerBook5,4", "PowerBook G4 15\"", 22798c2ecf20Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 22808c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 22818c2ecf20Sopenharmony_ci }, 22828c2ecf20Sopenharmony_ci { "PowerBook5,5", "PowerBook G4 17\"", 22838c2ecf20Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 22848c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 22858c2ecf20Sopenharmony_ci }, 22868c2ecf20Sopenharmony_ci { "PowerBook5,6", "PowerBook G4 15\"", 22878c2ecf20Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 22888c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 22898c2ecf20Sopenharmony_ci }, 22908c2ecf20Sopenharmony_ci { "PowerBook5,7", "PowerBook G4 17\"", 22918c2ecf20Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 22928c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 22938c2ecf20Sopenharmony_ci }, 22948c2ecf20Sopenharmony_ci { "PowerBook5,8", "PowerBook G4 15\"", 22958c2ecf20Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 22968c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_MOBILE, 22978c2ecf20Sopenharmony_ci }, 22988c2ecf20Sopenharmony_ci { "PowerBook5,9", "PowerBook G4 17\"", 22998c2ecf20Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 23008c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_MOBILE, 23018c2ecf20Sopenharmony_ci }, 23028c2ecf20Sopenharmony_ci { "PowerBook6,1", "PowerBook G4 12\"", 23038c2ecf20Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 23048c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 23058c2ecf20Sopenharmony_ci }, 23068c2ecf20Sopenharmony_ci { "PowerBook6,2", "PowerBook G4", 23078c2ecf20Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 23088c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 23098c2ecf20Sopenharmony_ci }, 23108c2ecf20Sopenharmony_ci { "PowerBook6,3", "iBook G4", 23118c2ecf20Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 23128c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 23138c2ecf20Sopenharmony_ci }, 23148c2ecf20Sopenharmony_ci { "PowerBook6,4", "PowerBook G4 12\"", 23158c2ecf20Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 23168c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 23178c2ecf20Sopenharmony_ci }, 23188c2ecf20Sopenharmony_ci { "PowerBook6,5", "iBook G4", 23198c2ecf20Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 23208c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 23218c2ecf20Sopenharmony_ci }, 23228c2ecf20Sopenharmony_ci { "PowerBook6,7", "iBook G4", 23238c2ecf20Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 23248c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 23258c2ecf20Sopenharmony_ci }, 23268c2ecf20Sopenharmony_ci { "PowerBook6,8", "PowerBook G4 12\"", 23278c2ecf20Sopenharmony_ci PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, 23288c2ecf20Sopenharmony_ci PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, 23298c2ecf20Sopenharmony_ci }, 23308c2ecf20Sopenharmony_ci#else /* CONFIG_PPC64 */ 23318c2ecf20Sopenharmony_ci { "PowerMac7,2", "PowerMac G5", 23328c2ecf20Sopenharmony_ci PMAC_TYPE_POWERMAC_G5, g5_features, 23338c2ecf20Sopenharmony_ci 0, 23348c2ecf20Sopenharmony_ci }, 23358c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC64 23368c2ecf20Sopenharmony_ci { "PowerMac7,3", "PowerMac G5", 23378c2ecf20Sopenharmony_ci PMAC_TYPE_POWERMAC_G5, g5_features, 23388c2ecf20Sopenharmony_ci 0, 23398c2ecf20Sopenharmony_ci }, 23408c2ecf20Sopenharmony_ci { "PowerMac8,1", "iMac G5", 23418c2ecf20Sopenharmony_ci PMAC_TYPE_IMAC_G5, g5_features, 23428c2ecf20Sopenharmony_ci 0, 23438c2ecf20Sopenharmony_ci }, 23448c2ecf20Sopenharmony_ci { "PowerMac9,1", "PowerMac G5", 23458c2ecf20Sopenharmony_ci PMAC_TYPE_POWERMAC_G5_U3L, g5_features, 23468c2ecf20Sopenharmony_ci 0, 23478c2ecf20Sopenharmony_ci }, 23488c2ecf20Sopenharmony_ci { "PowerMac11,2", "PowerMac G5 Dual Core", 23498c2ecf20Sopenharmony_ci PMAC_TYPE_POWERMAC_G5_U3L, g5_features, 23508c2ecf20Sopenharmony_ci 0, 23518c2ecf20Sopenharmony_ci }, 23528c2ecf20Sopenharmony_ci { "PowerMac12,1", "iMac G5 (iSight)", 23538c2ecf20Sopenharmony_ci PMAC_TYPE_POWERMAC_G5_U3L, g5_features, 23548c2ecf20Sopenharmony_ci 0, 23558c2ecf20Sopenharmony_ci }, 23568c2ecf20Sopenharmony_ci { "RackMac3,1", "XServe G5", 23578c2ecf20Sopenharmony_ci PMAC_TYPE_XSERVE_G5, g5_features, 23588c2ecf20Sopenharmony_ci 0, 23598c2ecf20Sopenharmony_ci }, 23608c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC64 */ 23618c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC64 */ 23628c2ecf20Sopenharmony_ci}; 23638c2ecf20Sopenharmony_ci 23648c2ecf20Sopenharmony_ci/* 23658c2ecf20Sopenharmony_ci * The toplevel feature_call callback 23668c2ecf20Sopenharmony_ci */ 23678c2ecf20Sopenharmony_cilong pmac_do_feature_call(unsigned int selector, ...) 23688c2ecf20Sopenharmony_ci{ 23698c2ecf20Sopenharmony_ci struct device_node *node; 23708c2ecf20Sopenharmony_ci long param, value; 23718c2ecf20Sopenharmony_ci int i; 23728c2ecf20Sopenharmony_ci feature_call func = NULL; 23738c2ecf20Sopenharmony_ci va_list args; 23748c2ecf20Sopenharmony_ci 23758c2ecf20Sopenharmony_ci if (pmac_mb.features) 23768c2ecf20Sopenharmony_ci for (i=0; pmac_mb.features[i].function; i++) 23778c2ecf20Sopenharmony_ci if (pmac_mb.features[i].selector == selector) { 23788c2ecf20Sopenharmony_ci func = pmac_mb.features[i].function; 23798c2ecf20Sopenharmony_ci break; 23808c2ecf20Sopenharmony_ci } 23818c2ecf20Sopenharmony_ci if (!func) 23828c2ecf20Sopenharmony_ci for (i=0; any_features[i].function; i++) 23838c2ecf20Sopenharmony_ci if (any_features[i].selector == selector) { 23848c2ecf20Sopenharmony_ci func = any_features[i].function; 23858c2ecf20Sopenharmony_ci break; 23868c2ecf20Sopenharmony_ci } 23878c2ecf20Sopenharmony_ci if (!func) 23888c2ecf20Sopenharmony_ci return -ENODEV; 23898c2ecf20Sopenharmony_ci 23908c2ecf20Sopenharmony_ci va_start(args, selector); 23918c2ecf20Sopenharmony_ci node = (struct device_node*)va_arg(args, void*); 23928c2ecf20Sopenharmony_ci param = va_arg(args, long); 23938c2ecf20Sopenharmony_ci value = va_arg(args, long); 23948c2ecf20Sopenharmony_ci va_end(args); 23958c2ecf20Sopenharmony_ci 23968c2ecf20Sopenharmony_ci return func(node, param, value); 23978c2ecf20Sopenharmony_ci} 23988c2ecf20Sopenharmony_ci 23998c2ecf20Sopenharmony_cistatic int __init probe_motherboard(void) 24008c2ecf20Sopenharmony_ci{ 24018c2ecf20Sopenharmony_ci int i; 24028c2ecf20Sopenharmony_ci struct macio_chip *macio = &macio_chips[0]; 24038c2ecf20Sopenharmony_ci const char *model = NULL; 24048c2ecf20Sopenharmony_ci struct device_node *dt; 24058c2ecf20Sopenharmony_ci int ret = 0; 24068c2ecf20Sopenharmony_ci 24078c2ecf20Sopenharmony_ci /* Lookup known motherboard type in device-tree. First try an 24088c2ecf20Sopenharmony_ci * exact match on the "model" property, then try a "compatible" 24098c2ecf20Sopenharmony_ci * match is none is found. 24108c2ecf20Sopenharmony_ci */ 24118c2ecf20Sopenharmony_ci dt = of_find_node_by_name(NULL, "device-tree"); 24128c2ecf20Sopenharmony_ci if (dt != NULL) 24138c2ecf20Sopenharmony_ci model = of_get_property(dt, "model", NULL); 24148c2ecf20Sopenharmony_ci for(i=0; model && i<ARRAY_SIZE(pmac_mb_defs); i++) { 24158c2ecf20Sopenharmony_ci if (strcmp(model, pmac_mb_defs[i].model_string) == 0) { 24168c2ecf20Sopenharmony_ci pmac_mb = pmac_mb_defs[i]; 24178c2ecf20Sopenharmony_ci goto found; 24188c2ecf20Sopenharmony_ci } 24198c2ecf20Sopenharmony_ci } 24208c2ecf20Sopenharmony_ci for(i=0; i<ARRAY_SIZE(pmac_mb_defs); i++) { 24218c2ecf20Sopenharmony_ci if (of_machine_is_compatible(pmac_mb_defs[i].model_string)) { 24228c2ecf20Sopenharmony_ci pmac_mb = pmac_mb_defs[i]; 24238c2ecf20Sopenharmony_ci goto found; 24248c2ecf20Sopenharmony_ci } 24258c2ecf20Sopenharmony_ci } 24268c2ecf20Sopenharmony_ci 24278c2ecf20Sopenharmony_ci /* Fallback to selection depending on mac-io chip type */ 24288c2ecf20Sopenharmony_ci switch(macio->type) { 24298c2ecf20Sopenharmony_ci#ifndef CONFIG_PPC64 24308c2ecf20Sopenharmony_ci case macio_grand_central: 24318c2ecf20Sopenharmony_ci pmac_mb.model_id = PMAC_TYPE_PSURGE; 24328c2ecf20Sopenharmony_ci pmac_mb.model_name = "Unknown PowerSurge"; 24338c2ecf20Sopenharmony_ci break; 24348c2ecf20Sopenharmony_ci case macio_ohare: 24358c2ecf20Sopenharmony_ci pmac_mb.model_id = PMAC_TYPE_UNKNOWN_OHARE; 24368c2ecf20Sopenharmony_ci pmac_mb.model_name = "Unknown OHare-based"; 24378c2ecf20Sopenharmony_ci break; 24388c2ecf20Sopenharmony_ci case macio_heathrow: 24398c2ecf20Sopenharmony_ci pmac_mb.model_id = PMAC_TYPE_UNKNOWN_HEATHROW; 24408c2ecf20Sopenharmony_ci pmac_mb.model_name = "Unknown Heathrow-based"; 24418c2ecf20Sopenharmony_ci pmac_mb.features = heathrow_desktop_features; 24428c2ecf20Sopenharmony_ci break; 24438c2ecf20Sopenharmony_ci case macio_paddington: 24448c2ecf20Sopenharmony_ci pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PADDINGTON; 24458c2ecf20Sopenharmony_ci pmac_mb.model_name = "Unknown Paddington-based"; 24468c2ecf20Sopenharmony_ci pmac_mb.features = paddington_features; 24478c2ecf20Sopenharmony_ci break; 24488c2ecf20Sopenharmony_ci case macio_keylargo: 24498c2ecf20Sopenharmony_ci pmac_mb.model_id = PMAC_TYPE_UNKNOWN_CORE99; 24508c2ecf20Sopenharmony_ci pmac_mb.model_name = "Unknown Keylargo-based"; 24518c2ecf20Sopenharmony_ci pmac_mb.features = core99_features; 24528c2ecf20Sopenharmony_ci break; 24538c2ecf20Sopenharmony_ci case macio_pangea: 24548c2ecf20Sopenharmony_ci pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PANGEA; 24558c2ecf20Sopenharmony_ci pmac_mb.model_name = "Unknown Pangea-based"; 24568c2ecf20Sopenharmony_ci pmac_mb.features = pangea_features; 24578c2ecf20Sopenharmony_ci break; 24588c2ecf20Sopenharmony_ci case macio_intrepid: 24598c2ecf20Sopenharmony_ci pmac_mb.model_id = PMAC_TYPE_UNKNOWN_INTREPID; 24608c2ecf20Sopenharmony_ci pmac_mb.model_name = "Unknown Intrepid-based"; 24618c2ecf20Sopenharmony_ci pmac_mb.features = intrepid_features; 24628c2ecf20Sopenharmony_ci break; 24638c2ecf20Sopenharmony_ci#else /* CONFIG_PPC64 */ 24648c2ecf20Sopenharmony_ci case macio_keylargo2: 24658c2ecf20Sopenharmony_ci pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2; 24668c2ecf20Sopenharmony_ci pmac_mb.model_name = "Unknown K2-based"; 24678c2ecf20Sopenharmony_ci pmac_mb.features = g5_features; 24688c2ecf20Sopenharmony_ci break; 24698c2ecf20Sopenharmony_ci case macio_shasta: 24708c2ecf20Sopenharmony_ci pmac_mb.model_id = PMAC_TYPE_UNKNOWN_SHASTA; 24718c2ecf20Sopenharmony_ci pmac_mb.model_name = "Unknown Shasta-based"; 24728c2ecf20Sopenharmony_ci pmac_mb.features = g5_features; 24738c2ecf20Sopenharmony_ci break; 24748c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC64 */ 24758c2ecf20Sopenharmony_ci default: 24768c2ecf20Sopenharmony_ci ret = -ENODEV; 24778c2ecf20Sopenharmony_ci goto done; 24788c2ecf20Sopenharmony_ci } 24798c2ecf20Sopenharmony_cifound: 24808c2ecf20Sopenharmony_ci#ifndef CONFIG_PPC64 24818c2ecf20Sopenharmony_ci /* Fixup Hooper vs. Comet */ 24828c2ecf20Sopenharmony_ci if (pmac_mb.model_id == PMAC_TYPE_HOOPER) { 24838c2ecf20Sopenharmony_ci u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4); 24848c2ecf20Sopenharmony_ci if (!mach_id_ptr) { 24858c2ecf20Sopenharmony_ci ret = -ENODEV; 24868c2ecf20Sopenharmony_ci goto done; 24878c2ecf20Sopenharmony_ci } 24888c2ecf20Sopenharmony_ci /* Here, I used to disable the media-bay on comet. It 24898c2ecf20Sopenharmony_ci * appears this is wrong, the floppy connector is actually 24908c2ecf20Sopenharmony_ci * a kind of media-bay and works with the current driver. 24918c2ecf20Sopenharmony_ci */ 24928c2ecf20Sopenharmony_ci if (__raw_readl(mach_id_ptr) & 0x20000000UL) 24938c2ecf20Sopenharmony_ci pmac_mb.model_id = PMAC_TYPE_COMET; 24948c2ecf20Sopenharmony_ci iounmap(mach_id_ptr); 24958c2ecf20Sopenharmony_ci } 24968c2ecf20Sopenharmony_ci 24978c2ecf20Sopenharmony_ci /* Set default value of powersave_nap on machines that support it. 24988c2ecf20Sopenharmony_ci * It appears that uninorth rev 3 has a problem with it, we don't 24998c2ecf20Sopenharmony_ci * enable it on those. In theory, the flush-on-lock property is 25008c2ecf20Sopenharmony_ci * supposed to be set when not supported, but I'm not very confident 25018c2ecf20Sopenharmony_ci * that all Apple OF revs did it properly, I do it the paranoid way. 25028c2ecf20Sopenharmony_ci */ 25038c2ecf20Sopenharmony_ci if (uninorth_base && uninorth_rev > 3) { 25048c2ecf20Sopenharmony_ci struct device_node *np; 25058c2ecf20Sopenharmony_ci 25068c2ecf20Sopenharmony_ci for_each_of_cpu_node(np) { 25078c2ecf20Sopenharmony_ci int cpu_count = 1; 25088c2ecf20Sopenharmony_ci 25098c2ecf20Sopenharmony_ci /* Nap mode not supported on SMP */ 25108c2ecf20Sopenharmony_ci if (of_get_property(np, "flush-on-lock", NULL) || 25118c2ecf20Sopenharmony_ci (cpu_count > 1)) { 25128c2ecf20Sopenharmony_ci powersave_nap = 0; 25138c2ecf20Sopenharmony_ci of_node_put(np); 25148c2ecf20Sopenharmony_ci break; 25158c2ecf20Sopenharmony_ci } 25168c2ecf20Sopenharmony_ci 25178c2ecf20Sopenharmony_ci cpu_count++; 25188c2ecf20Sopenharmony_ci powersave_nap = 1; 25198c2ecf20Sopenharmony_ci } 25208c2ecf20Sopenharmony_ci } 25218c2ecf20Sopenharmony_ci if (powersave_nap) 25228c2ecf20Sopenharmony_ci printk(KERN_DEBUG "Processor NAP mode on idle enabled.\n"); 25238c2ecf20Sopenharmony_ci 25248c2ecf20Sopenharmony_ci /* On CPUs that support it (750FX), lowspeed by default during 25258c2ecf20Sopenharmony_ci * NAP mode 25268c2ecf20Sopenharmony_ci */ 25278c2ecf20Sopenharmony_ci powersave_lowspeed = 1; 25288c2ecf20Sopenharmony_ci 25298c2ecf20Sopenharmony_ci#else /* CONFIG_PPC64 */ 25308c2ecf20Sopenharmony_ci powersave_nap = 1; 25318c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC64 */ 25328c2ecf20Sopenharmony_ci 25338c2ecf20Sopenharmony_ci /* Check for "mobile" machine */ 25348c2ecf20Sopenharmony_ci if (model && (strncmp(model, "PowerBook", 9) == 0 25358c2ecf20Sopenharmony_ci || strncmp(model, "iBook", 5) == 0)) 25368c2ecf20Sopenharmony_ci pmac_mb.board_flags |= PMAC_MB_MOBILE; 25378c2ecf20Sopenharmony_ci 25388c2ecf20Sopenharmony_ci 25398c2ecf20Sopenharmony_ci printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name); 25408c2ecf20Sopenharmony_cidone: 25418c2ecf20Sopenharmony_ci of_node_put(dt); 25428c2ecf20Sopenharmony_ci return ret; 25438c2ecf20Sopenharmony_ci} 25448c2ecf20Sopenharmony_ci 25458c2ecf20Sopenharmony_ci/* Initialize the Core99 UniNorth host bridge and memory controller 25468c2ecf20Sopenharmony_ci */ 25478c2ecf20Sopenharmony_cistatic void __init probe_uninorth(void) 25488c2ecf20Sopenharmony_ci{ 25498c2ecf20Sopenharmony_ci const u32 *addrp; 25508c2ecf20Sopenharmony_ci phys_addr_t address; 25518c2ecf20Sopenharmony_ci unsigned long actrl; 25528c2ecf20Sopenharmony_ci 25538c2ecf20Sopenharmony_ci /* Locate core99 Uni-N */ 25548c2ecf20Sopenharmony_ci uninorth_node = of_find_node_by_name(NULL, "uni-n"); 25558c2ecf20Sopenharmony_ci uninorth_maj = 1; 25568c2ecf20Sopenharmony_ci 25578c2ecf20Sopenharmony_ci /* Locate G5 u3 */ 25588c2ecf20Sopenharmony_ci if (uninorth_node == NULL) { 25598c2ecf20Sopenharmony_ci uninorth_node = of_find_node_by_name(NULL, "u3"); 25608c2ecf20Sopenharmony_ci uninorth_maj = 3; 25618c2ecf20Sopenharmony_ci } 25628c2ecf20Sopenharmony_ci /* Locate G5 u4 */ 25638c2ecf20Sopenharmony_ci if (uninorth_node == NULL) { 25648c2ecf20Sopenharmony_ci uninorth_node = of_find_node_by_name(NULL, "u4"); 25658c2ecf20Sopenharmony_ci uninorth_maj = 4; 25668c2ecf20Sopenharmony_ci } 25678c2ecf20Sopenharmony_ci if (uninorth_node == NULL) { 25688c2ecf20Sopenharmony_ci uninorth_maj = 0; 25698c2ecf20Sopenharmony_ci return; 25708c2ecf20Sopenharmony_ci } 25718c2ecf20Sopenharmony_ci 25728c2ecf20Sopenharmony_ci addrp = of_get_property(uninorth_node, "reg", NULL); 25738c2ecf20Sopenharmony_ci if (addrp == NULL) 25748c2ecf20Sopenharmony_ci return; 25758c2ecf20Sopenharmony_ci address = of_translate_address(uninorth_node, addrp); 25768c2ecf20Sopenharmony_ci if (address == 0) 25778c2ecf20Sopenharmony_ci return; 25788c2ecf20Sopenharmony_ci uninorth_base = ioremap(address, 0x40000); 25798c2ecf20Sopenharmony_ci if (uninorth_base == NULL) 25808c2ecf20Sopenharmony_ci return; 25818c2ecf20Sopenharmony_ci uninorth_rev = in_be32(UN_REG(UNI_N_VERSION)); 25828c2ecf20Sopenharmony_ci if (uninorth_maj == 3 || uninorth_maj == 4) { 25838c2ecf20Sopenharmony_ci u3_ht_base = ioremap(address + U3_HT_CONFIG_BASE, 0x1000); 25848c2ecf20Sopenharmony_ci if (u3_ht_base == NULL) { 25858c2ecf20Sopenharmony_ci iounmap(uninorth_base); 25868c2ecf20Sopenharmony_ci return; 25878c2ecf20Sopenharmony_ci } 25888c2ecf20Sopenharmony_ci } 25898c2ecf20Sopenharmony_ci 25908c2ecf20Sopenharmony_ci printk(KERN_INFO "Found %s memory controller & host bridge" 25918c2ecf20Sopenharmony_ci " @ 0x%08x revision: 0x%02x\n", uninorth_maj == 3 ? "U3" : 25928c2ecf20Sopenharmony_ci uninorth_maj == 4 ? "U4" : "UniNorth", 25938c2ecf20Sopenharmony_ci (unsigned int)address, uninorth_rev); 25948c2ecf20Sopenharmony_ci printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base); 25958c2ecf20Sopenharmony_ci 25968c2ecf20Sopenharmony_ci /* Set the arbitrer QAck delay according to what Apple does 25978c2ecf20Sopenharmony_ci */ 25988c2ecf20Sopenharmony_ci if (uninorth_rev < 0x11) { 25998c2ecf20Sopenharmony_ci actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK; 26008c2ecf20Sopenharmony_ci actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 : 26018c2ecf20Sopenharmony_ci UNI_N_ARB_CTRL_QACK_DELAY) << 26028c2ecf20Sopenharmony_ci UNI_N_ARB_CTRL_QACK_DELAY_SHIFT; 26038c2ecf20Sopenharmony_ci UN_OUT(UNI_N_ARB_CTRL, actrl); 26048c2ecf20Sopenharmony_ci } 26058c2ecf20Sopenharmony_ci 26068c2ecf20Sopenharmony_ci /* Some more magic as done by them in recent MacOS X on UniNorth 26078c2ecf20Sopenharmony_ci * revs 1.5 to 2.O and Pangea. Seem to toggle the UniN Maxbus/PCI 26088c2ecf20Sopenharmony_ci * memory timeout 26098c2ecf20Sopenharmony_ci */ 26108c2ecf20Sopenharmony_ci if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) || 26118c2ecf20Sopenharmony_ci uninorth_rev == 0xc0) 26128c2ecf20Sopenharmony_ci UN_OUT(0x2160, UN_IN(0x2160) & 0x00ffffff); 26138c2ecf20Sopenharmony_ci} 26148c2ecf20Sopenharmony_ci 26158c2ecf20Sopenharmony_cistatic void __init probe_one_macio(const char *name, const char *compat, int type) 26168c2ecf20Sopenharmony_ci{ 26178c2ecf20Sopenharmony_ci struct device_node* node; 26188c2ecf20Sopenharmony_ci int i; 26198c2ecf20Sopenharmony_ci volatile u32 __iomem *base; 26208c2ecf20Sopenharmony_ci const u32 *addrp, *revp; 26218c2ecf20Sopenharmony_ci phys_addr_t addr; 26228c2ecf20Sopenharmony_ci u64 size; 26238c2ecf20Sopenharmony_ci 26248c2ecf20Sopenharmony_ci for_each_node_by_name(node, name) { 26258c2ecf20Sopenharmony_ci if (!compat) 26268c2ecf20Sopenharmony_ci break; 26278c2ecf20Sopenharmony_ci if (of_device_is_compatible(node, compat)) 26288c2ecf20Sopenharmony_ci break; 26298c2ecf20Sopenharmony_ci } 26308c2ecf20Sopenharmony_ci if (!node) 26318c2ecf20Sopenharmony_ci return; 26328c2ecf20Sopenharmony_ci for(i=0; i<MAX_MACIO_CHIPS; i++) { 26338c2ecf20Sopenharmony_ci if (!macio_chips[i].of_node) 26348c2ecf20Sopenharmony_ci break; 26358c2ecf20Sopenharmony_ci if (macio_chips[i].of_node == node) 26368c2ecf20Sopenharmony_ci return; 26378c2ecf20Sopenharmony_ci } 26388c2ecf20Sopenharmony_ci 26398c2ecf20Sopenharmony_ci if (i >= MAX_MACIO_CHIPS) { 26408c2ecf20Sopenharmony_ci printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n"); 26418c2ecf20Sopenharmony_ci printk(KERN_ERR "pmac_feature: %pOF skipped\n", node); 26428c2ecf20Sopenharmony_ci return; 26438c2ecf20Sopenharmony_ci } 26448c2ecf20Sopenharmony_ci addrp = of_get_pci_address(node, 0, &size, NULL); 26458c2ecf20Sopenharmony_ci if (addrp == NULL) { 26468c2ecf20Sopenharmony_ci printk(KERN_ERR "pmac_feature: %pOF: can't find base !\n", 26478c2ecf20Sopenharmony_ci node); 26488c2ecf20Sopenharmony_ci return; 26498c2ecf20Sopenharmony_ci } 26508c2ecf20Sopenharmony_ci addr = of_translate_address(node, addrp); 26518c2ecf20Sopenharmony_ci if (addr == 0) { 26528c2ecf20Sopenharmony_ci printk(KERN_ERR "pmac_feature: %pOF, can't translate base !\n", 26538c2ecf20Sopenharmony_ci node); 26548c2ecf20Sopenharmony_ci return; 26558c2ecf20Sopenharmony_ci } 26568c2ecf20Sopenharmony_ci base = ioremap(addr, (unsigned long)size); 26578c2ecf20Sopenharmony_ci if (!base) { 26588c2ecf20Sopenharmony_ci printk(KERN_ERR "pmac_feature: %pOF, can't map mac-io chip !\n", 26598c2ecf20Sopenharmony_ci node); 26608c2ecf20Sopenharmony_ci return; 26618c2ecf20Sopenharmony_ci } 26628c2ecf20Sopenharmony_ci if (type == macio_keylargo || type == macio_keylargo2) { 26638c2ecf20Sopenharmony_ci const u32 *did = of_get_property(node, "device-id", NULL); 26648c2ecf20Sopenharmony_ci if (*did == 0x00000025) 26658c2ecf20Sopenharmony_ci type = macio_pangea; 26668c2ecf20Sopenharmony_ci if (*did == 0x0000003e) 26678c2ecf20Sopenharmony_ci type = macio_intrepid; 26688c2ecf20Sopenharmony_ci if (*did == 0x0000004f) 26698c2ecf20Sopenharmony_ci type = macio_shasta; 26708c2ecf20Sopenharmony_ci } 26718c2ecf20Sopenharmony_ci macio_chips[i].of_node = node; 26728c2ecf20Sopenharmony_ci macio_chips[i].type = type; 26738c2ecf20Sopenharmony_ci macio_chips[i].base = base; 26748c2ecf20Sopenharmony_ci macio_chips[i].flags = MACIO_FLAG_SCCA_ON | MACIO_FLAG_SCCB_ON; 26758c2ecf20Sopenharmony_ci macio_chips[i].name = macio_names[type]; 26768c2ecf20Sopenharmony_ci revp = of_get_property(node, "revision-id", NULL); 26778c2ecf20Sopenharmony_ci if (revp) 26788c2ecf20Sopenharmony_ci macio_chips[i].rev = *revp; 26798c2ecf20Sopenharmony_ci printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n", 26808c2ecf20Sopenharmony_ci macio_names[type], macio_chips[i].rev, macio_chips[i].base); 26818c2ecf20Sopenharmony_ci} 26828c2ecf20Sopenharmony_ci 26838c2ecf20Sopenharmony_cistatic int __init 26848c2ecf20Sopenharmony_ciprobe_macios(void) 26858c2ecf20Sopenharmony_ci{ 26868c2ecf20Sopenharmony_ci /* Warning, ordering is important */ 26878c2ecf20Sopenharmony_ci probe_one_macio("gc", NULL, macio_grand_central); 26888c2ecf20Sopenharmony_ci probe_one_macio("ohare", NULL, macio_ohare); 26898c2ecf20Sopenharmony_ci probe_one_macio("pci106b,7", NULL, macio_ohareII); 26908c2ecf20Sopenharmony_ci probe_one_macio("mac-io", "keylargo", macio_keylargo); 26918c2ecf20Sopenharmony_ci probe_one_macio("mac-io", "paddington", macio_paddington); 26928c2ecf20Sopenharmony_ci probe_one_macio("mac-io", "gatwick", macio_gatwick); 26938c2ecf20Sopenharmony_ci probe_one_macio("mac-io", "heathrow", macio_heathrow); 26948c2ecf20Sopenharmony_ci probe_one_macio("mac-io", "K2-Keylargo", macio_keylargo2); 26958c2ecf20Sopenharmony_ci 26968c2ecf20Sopenharmony_ci /* Make sure the "main" macio chip appear first */ 26978c2ecf20Sopenharmony_ci if (macio_chips[0].type == macio_gatwick 26988c2ecf20Sopenharmony_ci && macio_chips[1].type == macio_heathrow) { 26998c2ecf20Sopenharmony_ci struct macio_chip temp = macio_chips[0]; 27008c2ecf20Sopenharmony_ci macio_chips[0] = macio_chips[1]; 27018c2ecf20Sopenharmony_ci macio_chips[1] = temp; 27028c2ecf20Sopenharmony_ci } 27038c2ecf20Sopenharmony_ci if (macio_chips[0].type == macio_ohareII 27048c2ecf20Sopenharmony_ci && macio_chips[1].type == macio_ohare) { 27058c2ecf20Sopenharmony_ci struct macio_chip temp = macio_chips[0]; 27068c2ecf20Sopenharmony_ci macio_chips[0] = macio_chips[1]; 27078c2ecf20Sopenharmony_ci macio_chips[1] = temp; 27088c2ecf20Sopenharmony_ci } 27098c2ecf20Sopenharmony_ci macio_chips[0].lbus.index = 0; 27108c2ecf20Sopenharmony_ci macio_chips[1].lbus.index = 1; 27118c2ecf20Sopenharmony_ci 27128c2ecf20Sopenharmony_ci return (macio_chips[0].of_node == NULL) ? -ENODEV : 0; 27138c2ecf20Sopenharmony_ci} 27148c2ecf20Sopenharmony_ci 27158c2ecf20Sopenharmony_cistatic void __init 27168c2ecf20Sopenharmony_ciinitial_serial_shutdown(struct device_node *np) 27178c2ecf20Sopenharmony_ci{ 27188c2ecf20Sopenharmony_ci int len; 27198c2ecf20Sopenharmony_ci const struct slot_names_prop { 27208c2ecf20Sopenharmony_ci int count; 27218c2ecf20Sopenharmony_ci char name[1]; 27228c2ecf20Sopenharmony_ci } *slots; 27238c2ecf20Sopenharmony_ci const char *conn; 27248c2ecf20Sopenharmony_ci int port_type = PMAC_SCC_ASYNC; 27258c2ecf20Sopenharmony_ci int modem = 0; 27268c2ecf20Sopenharmony_ci 27278c2ecf20Sopenharmony_ci slots = of_get_property(np, "slot-names", &len); 27288c2ecf20Sopenharmony_ci conn = of_get_property(np, "AAPL,connector", &len); 27298c2ecf20Sopenharmony_ci if (conn && (strcmp(conn, "infrared") == 0)) 27308c2ecf20Sopenharmony_ci port_type = PMAC_SCC_IRDA; 27318c2ecf20Sopenharmony_ci else if (of_device_is_compatible(np, "cobalt")) 27328c2ecf20Sopenharmony_ci modem = 1; 27338c2ecf20Sopenharmony_ci else if (slots && slots->count > 0) { 27348c2ecf20Sopenharmony_ci if (strcmp(slots->name, "IrDA") == 0) 27358c2ecf20Sopenharmony_ci port_type = PMAC_SCC_IRDA; 27368c2ecf20Sopenharmony_ci else if (strcmp(slots->name, "Modem") == 0) 27378c2ecf20Sopenharmony_ci modem = 1; 27388c2ecf20Sopenharmony_ci } 27398c2ecf20Sopenharmony_ci if (modem) 27408c2ecf20Sopenharmony_ci pmac_call_feature(PMAC_FTR_MODEM_ENABLE, np, 0, 0); 27418c2ecf20Sopenharmony_ci pmac_call_feature(PMAC_FTR_SCC_ENABLE, np, port_type, 0); 27428c2ecf20Sopenharmony_ci} 27438c2ecf20Sopenharmony_ci 27448c2ecf20Sopenharmony_cistatic void __init 27458c2ecf20Sopenharmony_ciset_initial_features(void) 27468c2ecf20Sopenharmony_ci{ 27478c2ecf20Sopenharmony_ci struct device_node *np; 27488c2ecf20Sopenharmony_ci 27498c2ecf20Sopenharmony_ci /* That hack appears to be necessary for some StarMax motherboards 27508c2ecf20Sopenharmony_ci * but I'm not too sure it was audited for side-effects on other 27518c2ecf20Sopenharmony_ci * ohare based machines... 27528c2ecf20Sopenharmony_ci * Since I still have difficulties figuring the right way to 27538c2ecf20Sopenharmony_ci * differentiate them all and since that hack was there for a long 27548c2ecf20Sopenharmony_ci * time, I'll keep it around 27558c2ecf20Sopenharmony_ci */ 27568c2ecf20Sopenharmony_ci if (macio_chips[0].type == macio_ohare) { 27578c2ecf20Sopenharmony_ci struct macio_chip *macio = &macio_chips[0]; 27588c2ecf20Sopenharmony_ci np = of_find_node_by_name(NULL, "via-pmu"); 27598c2ecf20Sopenharmony_ci if (np) 27608c2ecf20Sopenharmony_ci MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); 27618c2ecf20Sopenharmony_ci else 27628c2ecf20Sopenharmony_ci MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES); 27638c2ecf20Sopenharmony_ci of_node_put(np); 27648c2ecf20Sopenharmony_ci } else if (macio_chips[1].type == macio_ohare) { 27658c2ecf20Sopenharmony_ci struct macio_chip *macio = &macio_chips[1]; 27668c2ecf20Sopenharmony_ci MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); 27678c2ecf20Sopenharmony_ci } 27688c2ecf20Sopenharmony_ci 27698c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC64 27708c2ecf20Sopenharmony_ci if (macio_chips[0].type == macio_keylargo2 || 27718c2ecf20Sopenharmony_ci macio_chips[0].type == macio_shasta) { 27728c2ecf20Sopenharmony_ci#ifndef CONFIG_SMP 27738c2ecf20Sopenharmony_ci /* On SMP machines running UP, we have the second CPU eating 27748c2ecf20Sopenharmony_ci * bus cycles. We need to take it off the bus. This is done 27758c2ecf20Sopenharmony_ci * from pmac_smp for SMP kernels running on one CPU 27768c2ecf20Sopenharmony_ci */ 27778c2ecf20Sopenharmony_ci np = of_find_node_by_type(NULL, "cpu"); 27788c2ecf20Sopenharmony_ci if (np != NULL) 27798c2ecf20Sopenharmony_ci np = of_find_node_by_type(np, "cpu"); 27808c2ecf20Sopenharmony_ci if (np != NULL) { 27818c2ecf20Sopenharmony_ci g5_phy_disable_cpu1(); 27828c2ecf20Sopenharmony_ci of_node_put(np); 27838c2ecf20Sopenharmony_ci } 27848c2ecf20Sopenharmony_ci#endif /* CONFIG_SMP */ 27858c2ecf20Sopenharmony_ci /* Enable GMAC for now for PCI probing. It will be disabled 27868c2ecf20Sopenharmony_ci * later on after PCI probe 27878c2ecf20Sopenharmony_ci */ 27888c2ecf20Sopenharmony_ci for_each_node_by_name(np, "ethernet") 27898c2ecf20Sopenharmony_ci if (of_device_is_compatible(np, "K2-GMAC")) 27908c2ecf20Sopenharmony_ci g5_gmac_enable(np, 0, 1); 27918c2ecf20Sopenharmony_ci 27928c2ecf20Sopenharmony_ci /* Enable FW before PCI probe. Will be disabled later on 27938c2ecf20Sopenharmony_ci * Note: We should have a batter way to check that we are 27948c2ecf20Sopenharmony_ci * dealing with uninorth internal cell and not a PCI cell 27958c2ecf20Sopenharmony_ci * on the external PCI. The code below works though. 27968c2ecf20Sopenharmony_ci */ 27978c2ecf20Sopenharmony_ci for_each_node_by_name(np, "firewire") { 27988c2ecf20Sopenharmony_ci if (of_device_is_compatible(np, "pci106b,5811")) { 27998c2ecf20Sopenharmony_ci macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; 28008c2ecf20Sopenharmony_ci g5_fw_enable(np, 0, 1); 28018c2ecf20Sopenharmony_ci } 28028c2ecf20Sopenharmony_ci } 28038c2ecf20Sopenharmony_ci } 28048c2ecf20Sopenharmony_ci#else /* CONFIG_PPC64 */ 28058c2ecf20Sopenharmony_ci 28068c2ecf20Sopenharmony_ci if (macio_chips[0].type == macio_keylargo || 28078c2ecf20Sopenharmony_ci macio_chips[0].type == macio_pangea || 28088c2ecf20Sopenharmony_ci macio_chips[0].type == macio_intrepid) { 28098c2ecf20Sopenharmony_ci /* Enable GMAC for now for PCI probing. It will be disabled 28108c2ecf20Sopenharmony_ci * later on after PCI probe 28118c2ecf20Sopenharmony_ci */ 28128c2ecf20Sopenharmony_ci for_each_node_by_name(np, "ethernet") { 28138c2ecf20Sopenharmony_ci if (np->parent 28148c2ecf20Sopenharmony_ci && of_device_is_compatible(np->parent, "uni-north") 28158c2ecf20Sopenharmony_ci && of_device_is_compatible(np, "gmac")) 28168c2ecf20Sopenharmony_ci core99_gmac_enable(np, 0, 1); 28178c2ecf20Sopenharmony_ci } 28188c2ecf20Sopenharmony_ci 28198c2ecf20Sopenharmony_ci /* Enable FW before PCI probe. Will be disabled later on 28208c2ecf20Sopenharmony_ci * Note: We should have a batter way to check that we are 28218c2ecf20Sopenharmony_ci * dealing with uninorth internal cell and not a PCI cell 28228c2ecf20Sopenharmony_ci * on the external PCI. The code below works though. 28238c2ecf20Sopenharmony_ci */ 28248c2ecf20Sopenharmony_ci for_each_node_by_name(np, "firewire") { 28258c2ecf20Sopenharmony_ci if (np->parent 28268c2ecf20Sopenharmony_ci && of_device_is_compatible(np->parent, "uni-north") 28278c2ecf20Sopenharmony_ci && (of_device_is_compatible(np, "pci106b,18") || 28288c2ecf20Sopenharmony_ci of_device_is_compatible(np, "pci106b,30") || 28298c2ecf20Sopenharmony_ci of_device_is_compatible(np, "pci11c1,5811"))) { 28308c2ecf20Sopenharmony_ci macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; 28318c2ecf20Sopenharmony_ci core99_firewire_enable(np, 0, 1); 28328c2ecf20Sopenharmony_ci } 28338c2ecf20Sopenharmony_ci } 28348c2ecf20Sopenharmony_ci 28358c2ecf20Sopenharmony_ci /* Enable ATA-100 before PCI probe. */ 28368c2ecf20Sopenharmony_ci for_each_node_by_name(np, "ata-6") { 28378c2ecf20Sopenharmony_ci if (np->parent 28388c2ecf20Sopenharmony_ci && of_device_is_compatible(np->parent, "uni-north") 28398c2ecf20Sopenharmony_ci && of_device_is_compatible(np, "kauai-ata")) { 28408c2ecf20Sopenharmony_ci core99_ata100_enable(np, 1); 28418c2ecf20Sopenharmony_ci } 28428c2ecf20Sopenharmony_ci } 28438c2ecf20Sopenharmony_ci 28448c2ecf20Sopenharmony_ci /* Switch airport off */ 28458c2ecf20Sopenharmony_ci for_each_node_by_name(np, "radio") { 28468c2ecf20Sopenharmony_ci if (np->parent == macio_chips[0].of_node) { 28478c2ecf20Sopenharmony_ci macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON; 28488c2ecf20Sopenharmony_ci core99_airport_enable(np, 0, 0); 28498c2ecf20Sopenharmony_ci } 28508c2ecf20Sopenharmony_ci } 28518c2ecf20Sopenharmony_ci } 28528c2ecf20Sopenharmony_ci 28538c2ecf20Sopenharmony_ci /* On all machines that support sound PM, switch sound off */ 28548c2ecf20Sopenharmony_ci if (macio_chips[0].of_node) 28558c2ecf20Sopenharmony_ci pmac_do_feature_call(PMAC_FTR_SOUND_CHIP_ENABLE, 28568c2ecf20Sopenharmony_ci macio_chips[0].of_node, 0, 0); 28578c2ecf20Sopenharmony_ci 28588c2ecf20Sopenharmony_ci /* While on some desktop G3s, we turn it back on */ 28598c2ecf20Sopenharmony_ci if (macio_chips[0].of_node && macio_chips[0].type == macio_heathrow 28608c2ecf20Sopenharmony_ci && (pmac_mb.model_id == PMAC_TYPE_GOSSAMER || 28618c2ecf20Sopenharmony_ci pmac_mb.model_id == PMAC_TYPE_SILK)) { 28628c2ecf20Sopenharmony_ci struct macio_chip *macio = &macio_chips[0]; 28638c2ecf20Sopenharmony_ci MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); 28648c2ecf20Sopenharmony_ci MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N); 28658c2ecf20Sopenharmony_ci } 28668c2ecf20Sopenharmony_ci 28678c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC64 */ 28688c2ecf20Sopenharmony_ci 28698c2ecf20Sopenharmony_ci /* On all machines, switch modem & serial ports off */ 28708c2ecf20Sopenharmony_ci for_each_node_by_name(np, "ch-a") 28718c2ecf20Sopenharmony_ci initial_serial_shutdown(np); 28728c2ecf20Sopenharmony_ci for_each_node_by_name(np, "ch-b") 28738c2ecf20Sopenharmony_ci initial_serial_shutdown(np); 28748c2ecf20Sopenharmony_ci} 28758c2ecf20Sopenharmony_ci 28768c2ecf20Sopenharmony_civoid __init 28778c2ecf20Sopenharmony_cipmac_feature_init(void) 28788c2ecf20Sopenharmony_ci{ 28798c2ecf20Sopenharmony_ci /* Detect the UniNorth memory controller */ 28808c2ecf20Sopenharmony_ci probe_uninorth(); 28818c2ecf20Sopenharmony_ci 28828c2ecf20Sopenharmony_ci /* Probe mac-io controllers */ 28838c2ecf20Sopenharmony_ci if (probe_macios()) { 28848c2ecf20Sopenharmony_ci printk(KERN_WARNING "No mac-io chip found\n"); 28858c2ecf20Sopenharmony_ci return; 28868c2ecf20Sopenharmony_ci } 28878c2ecf20Sopenharmony_ci 28888c2ecf20Sopenharmony_ci /* Probe machine type */ 28898c2ecf20Sopenharmony_ci if (probe_motherboard()) 28908c2ecf20Sopenharmony_ci printk(KERN_WARNING "Unknown PowerMac !\n"); 28918c2ecf20Sopenharmony_ci 28928c2ecf20Sopenharmony_ci /* Set some initial features (turn off some chips that will 28938c2ecf20Sopenharmony_ci * be later turned on) 28948c2ecf20Sopenharmony_ci */ 28958c2ecf20Sopenharmony_ci set_initial_features(); 28968c2ecf20Sopenharmony_ci} 28978c2ecf20Sopenharmony_ci 28988c2ecf20Sopenharmony_ci#if 0 28998c2ecf20Sopenharmony_cistatic void dump_HT_speeds(char *name, u32 cfg, u32 frq) 29008c2ecf20Sopenharmony_ci{ 29018c2ecf20Sopenharmony_ci int freqs[16] = { 200,300,400,500,600,800,1000,0,0,0,0,0,0,0,0,0 }; 29028c2ecf20Sopenharmony_ci int bits[8] = { 8,16,0,32,2,4,0,0 }; 29038c2ecf20Sopenharmony_ci int freq = (frq >> 8) & 0xf; 29048c2ecf20Sopenharmony_ci 29058c2ecf20Sopenharmony_ci if (freqs[freq] == 0) 29068c2ecf20Sopenharmony_ci printk("%s: Unknown HT link frequency %x\n", name, freq); 29078c2ecf20Sopenharmony_ci else 29088c2ecf20Sopenharmony_ci printk("%s: %d MHz on main link, (%d in / %d out) bits width\n", 29098c2ecf20Sopenharmony_ci name, freqs[freq], 29108c2ecf20Sopenharmony_ci bits[(cfg >> 28) & 0x7], bits[(cfg >> 24) & 0x7]); 29118c2ecf20Sopenharmony_ci} 29128c2ecf20Sopenharmony_ci 29138c2ecf20Sopenharmony_civoid __init pmac_check_ht_link(void) 29148c2ecf20Sopenharmony_ci{ 29158c2ecf20Sopenharmony_ci u32 ufreq, freq, ucfg, cfg; 29168c2ecf20Sopenharmony_ci struct device_node *pcix_node; 29178c2ecf20Sopenharmony_ci u8 px_bus, px_devfn; 29188c2ecf20Sopenharmony_ci struct pci_controller *px_hose; 29198c2ecf20Sopenharmony_ci 29208c2ecf20Sopenharmony_ci (void)in_be32(u3_ht_base + U3_HT_LINK_COMMAND); 29218c2ecf20Sopenharmony_ci ucfg = cfg = in_be32(u3_ht_base + U3_HT_LINK_CONFIG); 29228c2ecf20Sopenharmony_ci ufreq = freq = in_be32(u3_ht_base + U3_HT_LINK_FREQ); 29238c2ecf20Sopenharmony_ci dump_HT_speeds("U3 HyperTransport", cfg, freq); 29248c2ecf20Sopenharmony_ci 29258c2ecf20Sopenharmony_ci pcix_node = of_find_compatible_node(NULL, "pci", "pci-x"); 29268c2ecf20Sopenharmony_ci if (pcix_node == NULL) { 29278c2ecf20Sopenharmony_ci printk("No PCI-X bridge found\n"); 29288c2ecf20Sopenharmony_ci return; 29298c2ecf20Sopenharmony_ci } 29308c2ecf20Sopenharmony_ci if (pci_device_from_OF_node(pcix_node, &px_bus, &px_devfn) != 0) { 29318c2ecf20Sopenharmony_ci printk("PCI-X bridge found but not matched to pci\n"); 29328c2ecf20Sopenharmony_ci return; 29338c2ecf20Sopenharmony_ci } 29348c2ecf20Sopenharmony_ci px_hose = pci_find_hose_for_OF_device(pcix_node); 29358c2ecf20Sopenharmony_ci if (px_hose == NULL) { 29368c2ecf20Sopenharmony_ci printk("PCI-X bridge found but not matched to host\n"); 29378c2ecf20Sopenharmony_ci return; 29388c2ecf20Sopenharmony_ci } 29398c2ecf20Sopenharmony_ci early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg); 29408c2ecf20Sopenharmony_ci early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq); 29418c2ecf20Sopenharmony_ci dump_HT_speeds("PCI-X HT Uplink", cfg, freq); 29428c2ecf20Sopenharmony_ci early_read_config_dword(px_hose, px_bus, px_devfn, 0xc8, &cfg); 29438c2ecf20Sopenharmony_ci early_read_config_dword(px_hose, px_bus, px_devfn, 0xd0, &freq); 29448c2ecf20Sopenharmony_ci dump_HT_speeds("PCI-X HT Downlink", cfg, freq); 29458c2ecf20Sopenharmony_ci} 29468c2ecf20Sopenharmony_ci#endif /* 0 */ 29478c2ecf20Sopenharmony_ci 29488c2ecf20Sopenharmony_ci/* 29498c2ecf20Sopenharmony_ci * Early video resume hook 29508c2ecf20Sopenharmony_ci */ 29518c2ecf20Sopenharmony_ci 29528c2ecf20Sopenharmony_cistatic void (*pmac_early_vresume_proc)(void *data); 29538c2ecf20Sopenharmony_cistatic void *pmac_early_vresume_data; 29548c2ecf20Sopenharmony_ci 29558c2ecf20Sopenharmony_civoid pmac_set_early_video_resume(void (*proc)(void *data), void *data) 29568c2ecf20Sopenharmony_ci{ 29578c2ecf20Sopenharmony_ci if (!machine_is(powermac)) 29588c2ecf20Sopenharmony_ci return; 29598c2ecf20Sopenharmony_ci preempt_disable(); 29608c2ecf20Sopenharmony_ci pmac_early_vresume_proc = proc; 29618c2ecf20Sopenharmony_ci pmac_early_vresume_data = data; 29628c2ecf20Sopenharmony_ci preempt_enable(); 29638c2ecf20Sopenharmony_ci} 29648c2ecf20Sopenharmony_ciEXPORT_SYMBOL(pmac_set_early_video_resume); 29658c2ecf20Sopenharmony_ci 29668c2ecf20Sopenharmony_civoid pmac_call_early_video_resume(void) 29678c2ecf20Sopenharmony_ci{ 29688c2ecf20Sopenharmony_ci if (pmac_early_vresume_proc) 29698c2ecf20Sopenharmony_ci pmac_early_vresume_proc(pmac_early_vresume_data); 29708c2ecf20Sopenharmony_ci} 29718c2ecf20Sopenharmony_ci 29728c2ecf20Sopenharmony_ci/* 29738c2ecf20Sopenharmony_ci * AGP related suspend/resume code 29748c2ecf20Sopenharmony_ci */ 29758c2ecf20Sopenharmony_ci 29768c2ecf20Sopenharmony_cistatic struct pci_dev *pmac_agp_bridge; 29778c2ecf20Sopenharmony_cistatic int (*pmac_agp_suspend)(struct pci_dev *bridge); 29788c2ecf20Sopenharmony_cistatic int (*pmac_agp_resume)(struct pci_dev *bridge); 29798c2ecf20Sopenharmony_ci 29808c2ecf20Sopenharmony_civoid pmac_register_agp_pm(struct pci_dev *bridge, 29818c2ecf20Sopenharmony_ci int (*suspend)(struct pci_dev *bridge), 29828c2ecf20Sopenharmony_ci int (*resume)(struct pci_dev *bridge)) 29838c2ecf20Sopenharmony_ci{ 29848c2ecf20Sopenharmony_ci if (suspend || resume) { 29858c2ecf20Sopenharmony_ci pmac_agp_bridge = bridge; 29868c2ecf20Sopenharmony_ci pmac_agp_suspend = suspend; 29878c2ecf20Sopenharmony_ci pmac_agp_resume = resume; 29888c2ecf20Sopenharmony_ci return; 29898c2ecf20Sopenharmony_ci } 29908c2ecf20Sopenharmony_ci if (bridge != pmac_agp_bridge) 29918c2ecf20Sopenharmony_ci return; 29928c2ecf20Sopenharmony_ci pmac_agp_suspend = pmac_agp_resume = NULL; 29938c2ecf20Sopenharmony_ci return; 29948c2ecf20Sopenharmony_ci} 29958c2ecf20Sopenharmony_ciEXPORT_SYMBOL(pmac_register_agp_pm); 29968c2ecf20Sopenharmony_ci 29978c2ecf20Sopenharmony_civoid pmac_suspend_agp_for_card(struct pci_dev *dev) 29988c2ecf20Sopenharmony_ci{ 29998c2ecf20Sopenharmony_ci if (pmac_agp_bridge == NULL || pmac_agp_suspend == NULL) 30008c2ecf20Sopenharmony_ci return; 30018c2ecf20Sopenharmony_ci if (pmac_agp_bridge->bus != dev->bus) 30028c2ecf20Sopenharmony_ci return; 30038c2ecf20Sopenharmony_ci pmac_agp_suspend(pmac_agp_bridge); 30048c2ecf20Sopenharmony_ci} 30058c2ecf20Sopenharmony_ciEXPORT_SYMBOL(pmac_suspend_agp_for_card); 30068c2ecf20Sopenharmony_ci 30078c2ecf20Sopenharmony_civoid pmac_resume_agp_for_card(struct pci_dev *dev) 30088c2ecf20Sopenharmony_ci{ 30098c2ecf20Sopenharmony_ci if (pmac_agp_bridge == NULL || pmac_agp_resume == NULL) 30108c2ecf20Sopenharmony_ci return; 30118c2ecf20Sopenharmony_ci if (pmac_agp_bridge->bus != dev->bus) 30128c2ecf20Sopenharmony_ci return; 30138c2ecf20Sopenharmony_ci pmac_agp_resume(pmac_agp_bridge); 30148c2ecf20Sopenharmony_ci} 30158c2ecf20Sopenharmony_ciEXPORT_SYMBOL(pmac_resume_agp_for_card); 30168c2ecf20Sopenharmony_ci 30178c2ecf20Sopenharmony_ciint pmac_get_uninorth_variant(void) 30188c2ecf20Sopenharmony_ci{ 30198c2ecf20Sopenharmony_ci return uninorth_maj; 30208c2ecf20Sopenharmony_ci} 3021