12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2f6d57916SPaul Mackerras /*
3f6d57916SPaul Mackerras * Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au)
4f6d57916SPaul Mackerras * Ben. Herrenschmidt (benh@kernel.crashing.org)
5f6d57916SPaul Mackerras *
6f6d57916SPaul Mackerras * TODO:
7f6d57916SPaul Mackerras *
8f6d57916SPaul Mackerras * - Replace mdelay with some schedule loop if possible
9f6d57916SPaul Mackerras * - Shorten some obfuscated delays on some routines (like modem
10f6d57916SPaul Mackerras * power)
11f6d57916SPaul Mackerras * - Refcount some clocks (see darwin)
12f6d57916SPaul Mackerras * - Split split split...
13f6d57916SPaul Mackerras */
14f6d57916SPaul Mackerras #include <linux/types.h>
15f6d57916SPaul Mackerras #include <linux/init.h>
16f6d57916SPaul Mackerras #include <linux/delay.h>
17f6d57916SPaul Mackerras #include <linux/kernel.h>
18f6d57916SPaul Mackerras #include <linux/sched.h>
1922ae782fSGrant Likely #include <linux/of.h>
2022ae782fSGrant Likely #include <linux/of_address.h>
21f6d57916SPaul Mackerras #include <linux/spinlock.h>
22f6d57916SPaul Mackerras #include <linux/adb.h>
23f6d57916SPaul Mackerras #include <linux/pmu.h>
24f6d57916SPaul Mackerras #include <linux/ioport.h>
2566b15db6SPaul Gortmaker #include <linux/export.h>
26f6d57916SPaul Mackerras #include <linux/pci.h>
27f6d57916SPaul Mackerras #include <asm/sections.h>
28f6d57916SPaul Mackerras #include <asm/errno.h>
29f6d57916SPaul Mackerras #include <asm/ohare.h>
30f6d57916SPaul Mackerras #include <asm/heathrow.h>
31f6d57916SPaul Mackerras #include <asm/keylargo.h>
32f6d57916SPaul Mackerras #include <asm/uninorth.h>
33f6d57916SPaul Mackerras #include <asm/io.h>
34f6d57916SPaul Mackerras #include <asm/machdep.h>
35f6d57916SPaul Mackerras #include <asm/pmac_feature.h>
36f6d57916SPaul Mackerras #include <asm/dbdma.h>
37f6d57916SPaul Mackerras #include <asm/pci-bridge.h>
38f6d57916SPaul Mackerras #include <asm/pmac_low_i2c.h>
39f6d57916SPaul Mackerras
4054f30b83SArnd Bergmann #include "pmac.h"
4154f30b83SArnd Bergmann
42f6d57916SPaul Mackerras #undef DEBUG_FEATURE
43f6d57916SPaul Mackerras
44f6d57916SPaul Mackerras #ifdef DEBUG_FEATURE
45f6d57916SPaul Mackerras #define DBG(fmt...) printk(KERN_DEBUG fmt)
46f6d57916SPaul Mackerras #else
47f6d57916SPaul Mackerras #define DBG(fmt...)
48f6d57916SPaul Mackerras #endif
49f6d57916SPaul Mackerras
50d7cceda9SChristophe Leroy #ifdef CONFIG_PPC_BOOK3S_32
51f6d57916SPaul Mackerras extern int powersave_lowspeed;
52f6d57916SPaul Mackerras #endif
53f6d57916SPaul Mackerras
54f6d57916SPaul Mackerras extern int powersave_nap;
55f6d57916SPaul Mackerras extern struct device_node *k2_skiplist[2];
56f6d57916SPaul Mackerras
57f6d57916SPaul Mackerras /*
58f6d57916SPaul Mackerras * We use a single global lock to protect accesses. Each driver has
59f6d57916SPaul Mackerras * to take care of its own locking
60f6d57916SPaul Mackerras */
61087d8c7dSThomas Gleixner DEFINE_RAW_SPINLOCK(feature_lock);
62f6d57916SPaul Mackerras
63087d8c7dSThomas Gleixner #define LOCK(flags) raw_spin_lock_irqsave(&feature_lock, flags);
64087d8c7dSThomas Gleixner #define UNLOCK(flags) raw_spin_unlock_irqrestore(&feature_lock, flags);
65f6d57916SPaul Mackerras
66f6d57916SPaul Mackerras
67f6d57916SPaul Mackerras /*
68f6d57916SPaul Mackerras * Instance of some macio stuffs
69f6d57916SPaul Mackerras */
70f6d57916SPaul Mackerras struct macio_chip macio_chips[MAX_MACIO_CHIPS];
71f6d57916SPaul Mackerras
macio_find(struct device_node * child,int type)72f6d57916SPaul Mackerras struct macio_chip *macio_find(struct device_node *child, int type)
73f6d57916SPaul Mackerras {
74f6d57916SPaul Mackerras while(child) {
75f6d57916SPaul Mackerras int i;
76f6d57916SPaul Mackerras
77f6d57916SPaul Mackerras for (i=0; i < MAX_MACIO_CHIPS && macio_chips[i].of_node; i++)
78f6d57916SPaul Mackerras if (child == macio_chips[i].of_node &&
79f6d57916SPaul Mackerras (!type || macio_chips[i].type == type))
80f6d57916SPaul Mackerras return &macio_chips[i];
81f6d57916SPaul Mackerras child = child->parent;
82f6d57916SPaul Mackerras }
83f6d57916SPaul Mackerras return NULL;
84f6d57916SPaul Mackerras }
85f6d57916SPaul Mackerras EXPORT_SYMBOL_GPL(macio_find);
86f6d57916SPaul Mackerras
87f6d57916SPaul Mackerras static const char *macio_names[] =
88f6d57916SPaul Mackerras {
89f6d57916SPaul Mackerras "Unknown",
90f6d57916SPaul Mackerras "Grand Central",
91f6d57916SPaul Mackerras "OHare",
92f6d57916SPaul Mackerras "OHareII",
93f6d57916SPaul Mackerras "Heathrow",
94f6d57916SPaul Mackerras "Gatwick",
95f6d57916SPaul Mackerras "Paddington",
96f6d57916SPaul Mackerras "Keylargo",
97f6d57916SPaul Mackerras "Pangea",
98f6d57916SPaul Mackerras "Intrepid",
991beb6a7dSBenjamin Herrenschmidt "K2",
1001beb6a7dSBenjamin Herrenschmidt "Shasta",
101f6d57916SPaul Mackerras };
102f6d57916SPaul Mackerras
103f6d57916SPaul Mackerras
1045b9ca526SBenjamin Herrenschmidt struct device_node *uninorth_node;
1055b9ca526SBenjamin Herrenschmidt u32 __iomem *uninorth_base;
106f6d57916SPaul Mackerras
107f6d57916SPaul Mackerras static u32 uninorth_rev;
1081beb6a7dSBenjamin Herrenschmidt static int uninorth_maj;
1095b9ca526SBenjamin Herrenschmidt static void __iomem *u3_ht_base;
110f6d57916SPaul Mackerras
111f6d57916SPaul Mackerras /*
112f6d57916SPaul Mackerras * For each motherboard family, we have a table of functions pointers
113f6d57916SPaul Mackerras * that handle the various features.
114f6d57916SPaul Mackerras */
115f6d57916SPaul Mackerras
116f6d57916SPaul Mackerras typedef long (*feature_call)(struct device_node *node, long param, long value);
117f6d57916SPaul Mackerras
118f6d57916SPaul Mackerras struct feature_table_entry {
119f6d57916SPaul Mackerras unsigned int selector;
120f6d57916SPaul Mackerras feature_call function;
121f6d57916SPaul Mackerras };
122f6d57916SPaul Mackerras
123f6d57916SPaul Mackerras struct pmac_mb_def
124f6d57916SPaul Mackerras {
125f6d57916SPaul Mackerras const char* model_string;
126f6d57916SPaul Mackerras const char* model_name;
127f6d57916SPaul Mackerras int model_id;
128f6d57916SPaul Mackerras struct feature_table_entry* features;
129f6d57916SPaul Mackerras unsigned long board_flags;
130f6d57916SPaul Mackerras };
131f6d57916SPaul Mackerras static struct pmac_mb_def pmac_mb;
132f6d57916SPaul Mackerras
133f6d57916SPaul Mackerras /*
134f6d57916SPaul Mackerras * Here are the chip specific feature functions
135f6d57916SPaul Mackerras */
136f6d57916SPaul Mackerras
137*1eafbd87SMichael Ellerman #ifndef CONFIG_PPC64
138*1eafbd87SMichael Ellerman
simple_feature_tweak(struct device_node * node,int type,int reg,u32 mask,int value)139*1eafbd87SMichael Ellerman static int simple_feature_tweak(struct device_node *node, int type, int reg,
140*1eafbd87SMichael Ellerman u32 mask, int value)
141f6d57916SPaul Mackerras {
142f6d57916SPaul Mackerras struct macio_chip* macio;
143f6d57916SPaul Mackerras unsigned long flags;
144f6d57916SPaul Mackerras
145f6d57916SPaul Mackerras macio = macio_find(node, type);
146f6d57916SPaul Mackerras if (!macio)
147f6d57916SPaul Mackerras return -ENODEV;
148f6d57916SPaul Mackerras LOCK(flags);
149f6d57916SPaul Mackerras if (value)
150f6d57916SPaul Mackerras MACIO_BIS(reg, mask);
151f6d57916SPaul Mackerras else
152f6d57916SPaul Mackerras MACIO_BIC(reg, mask);
153f6d57916SPaul Mackerras (void)MACIO_IN32(reg);
154f6d57916SPaul Mackerras UNLOCK(flags);
155f6d57916SPaul Mackerras
156f6d57916SPaul Mackerras return 0;
157f6d57916SPaul Mackerras }
158f6d57916SPaul Mackerras
ohare_htw_scc_enable(struct device_node * node,long param,long value)159f6d57916SPaul Mackerras static long ohare_htw_scc_enable(struct device_node *node, long param,
160f6d57916SPaul Mackerras long value)
161f6d57916SPaul Mackerras {
162f6d57916SPaul Mackerras struct macio_chip* macio;
163f6d57916SPaul Mackerras unsigned long chan_mask;
164f6d57916SPaul Mackerras unsigned long fcr;
165f6d57916SPaul Mackerras unsigned long flags;
166f6d57916SPaul Mackerras int htw, trans;
167f6d57916SPaul Mackerras unsigned long rmask;
168f6d57916SPaul Mackerras
169f6d57916SPaul Mackerras macio = macio_find(node, 0);
170f6d57916SPaul Mackerras if (!macio)
171f6d57916SPaul Mackerras return -ENODEV;
1722c8e65b5SRob Herring if (of_node_name_eq(node, "ch-a"))
173f6d57916SPaul Mackerras chan_mask = MACIO_FLAG_SCCA_ON;
1742c8e65b5SRob Herring else if (of_node_name_eq(node, "ch-b"))
175f6d57916SPaul Mackerras chan_mask = MACIO_FLAG_SCCB_ON;
176f6d57916SPaul Mackerras else
177f6d57916SPaul Mackerras return -ENODEV;
178f6d57916SPaul Mackerras
179f6d57916SPaul Mackerras htw = (macio->type == macio_heathrow || macio->type == macio_paddington
180f6d57916SPaul Mackerras || macio->type == macio_gatwick);
181f6d57916SPaul Mackerras /* On these machines, the HRW_SCC_TRANS_EN_N bit mustn't be touched */
182f6d57916SPaul Mackerras trans = (pmac_mb.model_id != PMAC_TYPE_YOSEMITE &&
183f6d57916SPaul Mackerras pmac_mb.model_id != PMAC_TYPE_YIKES);
184f6d57916SPaul Mackerras if (value) {
185f6d57916SPaul Mackerras #ifdef CONFIG_ADB_PMU
186f6d57916SPaul Mackerras if ((param & 0xfff) == PMAC_SCC_IRDA)
187f6d57916SPaul Mackerras pmu_enable_irled(1);
188f6d57916SPaul Mackerras #endif /* CONFIG_ADB_PMU */
189f6d57916SPaul Mackerras LOCK(flags);
190f6d57916SPaul Mackerras fcr = MACIO_IN32(OHARE_FCR);
191f6d57916SPaul Mackerras /* Check if scc cell need enabling */
192f6d57916SPaul Mackerras if (!(fcr & OH_SCC_ENABLE)) {
193f6d57916SPaul Mackerras fcr |= OH_SCC_ENABLE;
194f6d57916SPaul Mackerras if (htw) {
195f6d57916SPaul Mackerras /* Side effect: this will also power up the
196f6d57916SPaul Mackerras * modem, but it's too messy to figure out on which
197446957baSAdam Buchbinder * ports this controls the transceiver and on which
198f6d57916SPaul Mackerras * it controls the modem
199f6d57916SPaul Mackerras */
200f6d57916SPaul Mackerras if (trans)
201f6d57916SPaul Mackerras fcr &= ~HRW_SCC_TRANS_EN_N;
202f6d57916SPaul Mackerras MACIO_OUT32(OHARE_FCR, fcr);
203f6d57916SPaul Mackerras fcr |= (rmask = HRW_RESET_SCC);
204f6d57916SPaul Mackerras MACIO_OUT32(OHARE_FCR, fcr);
205f6d57916SPaul Mackerras } else {
206f6d57916SPaul Mackerras fcr |= (rmask = OH_SCC_RESET);
207f6d57916SPaul Mackerras MACIO_OUT32(OHARE_FCR, fcr);
208f6d57916SPaul Mackerras }
209f6d57916SPaul Mackerras UNLOCK(flags);
210f6d57916SPaul Mackerras (void)MACIO_IN32(OHARE_FCR);
211f6d57916SPaul Mackerras mdelay(15);
212f6d57916SPaul Mackerras LOCK(flags);
213f6d57916SPaul Mackerras fcr &= ~rmask;
214f6d57916SPaul Mackerras MACIO_OUT32(OHARE_FCR, fcr);
215f6d57916SPaul Mackerras }
216f6d57916SPaul Mackerras if (chan_mask & MACIO_FLAG_SCCA_ON)
217f6d57916SPaul Mackerras fcr |= OH_SCCA_IO;
218f6d57916SPaul Mackerras if (chan_mask & MACIO_FLAG_SCCB_ON)
219f6d57916SPaul Mackerras fcr |= OH_SCCB_IO;
220f6d57916SPaul Mackerras MACIO_OUT32(OHARE_FCR, fcr);
221f6d57916SPaul Mackerras macio->flags |= chan_mask;
222f6d57916SPaul Mackerras UNLOCK(flags);
223f6d57916SPaul Mackerras if (param & PMAC_SCC_FLAG_XMON)
224f6d57916SPaul Mackerras macio->flags |= MACIO_FLAG_SCC_LOCKED;
225f6d57916SPaul Mackerras } else {
226f6d57916SPaul Mackerras if (macio->flags & MACIO_FLAG_SCC_LOCKED)
227f6d57916SPaul Mackerras return -EPERM;
228f6d57916SPaul Mackerras LOCK(flags);
229f6d57916SPaul Mackerras fcr = MACIO_IN32(OHARE_FCR);
230f6d57916SPaul Mackerras if (chan_mask & MACIO_FLAG_SCCA_ON)
231f6d57916SPaul Mackerras fcr &= ~OH_SCCA_IO;
232f6d57916SPaul Mackerras if (chan_mask & MACIO_FLAG_SCCB_ON)
233f6d57916SPaul Mackerras fcr &= ~OH_SCCB_IO;
234f6d57916SPaul Mackerras MACIO_OUT32(OHARE_FCR, fcr);
235f6d57916SPaul Mackerras if ((fcr & (OH_SCCA_IO | OH_SCCB_IO)) == 0) {
236f6d57916SPaul Mackerras fcr &= ~OH_SCC_ENABLE;
237f6d57916SPaul Mackerras if (htw && trans)
238f6d57916SPaul Mackerras fcr |= HRW_SCC_TRANS_EN_N;
239f6d57916SPaul Mackerras MACIO_OUT32(OHARE_FCR, fcr);
240f6d57916SPaul Mackerras }
241f6d57916SPaul Mackerras macio->flags &= ~(chan_mask);
242f6d57916SPaul Mackerras UNLOCK(flags);
243f6d57916SPaul Mackerras mdelay(10);
244f6d57916SPaul Mackerras #ifdef CONFIG_ADB_PMU
245f6d57916SPaul Mackerras if ((param & 0xfff) == PMAC_SCC_IRDA)
246f6d57916SPaul Mackerras pmu_enable_irled(0);
247f6d57916SPaul Mackerras #endif /* CONFIG_ADB_PMU */
248f6d57916SPaul Mackerras }
249f6d57916SPaul Mackerras return 0;
250f6d57916SPaul Mackerras }
251f6d57916SPaul Mackerras
ohare_floppy_enable(struct device_node * node,long param,long value)252f6d57916SPaul Mackerras static long ohare_floppy_enable(struct device_node *node, long param,
253f6d57916SPaul Mackerras long value)
254f6d57916SPaul Mackerras {
255f6d57916SPaul Mackerras return simple_feature_tweak(node, macio_ohare,
256f6d57916SPaul Mackerras OHARE_FCR, OH_FLOPPY_ENABLE, value);
257f6d57916SPaul Mackerras }
258f6d57916SPaul Mackerras
ohare_mesh_enable(struct device_node * node,long param,long value)259f6d57916SPaul Mackerras static long ohare_mesh_enable(struct device_node *node, long param, long value)
260f6d57916SPaul Mackerras {
261f6d57916SPaul Mackerras return simple_feature_tweak(node, macio_ohare,
262f6d57916SPaul Mackerras OHARE_FCR, OH_MESH_ENABLE, value);
263f6d57916SPaul Mackerras }
264f6d57916SPaul Mackerras
ohare_ide_enable(struct device_node * node,long param,long value)265f6d57916SPaul Mackerras static long ohare_ide_enable(struct device_node *node, long param, long value)
266f6d57916SPaul Mackerras {
267f6d57916SPaul Mackerras switch(param) {
268f6d57916SPaul Mackerras case 0:
269f6d57916SPaul Mackerras /* For some reason, setting the bit in set_initial_features()
270f6d57916SPaul Mackerras * doesn't stick. I'm still investigating... --BenH.
271f6d57916SPaul Mackerras */
272f6d57916SPaul Mackerras if (value)
273f6d57916SPaul Mackerras simple_feature_tweak(node, macio_ohare,
274f6d57916SPaul Mackerras OHARE_FCR, OH_IOBUS_ENABLE, 1);
275f6d57916SPaul Mackerras return simple_feature_tweak(node, macio_ohare,
276f6d57916SPaul Mackerras OHARE_FCR, OH_IDE0_ENABLE, value);
277f6d57916SPaul Mackerras case 1:
278f6d57916SPaul Mackerras return simple_feature_tweak(node, macio_ohare,
279f6d57916SPaul Mackerras OHARE_FCR, OH_BAY_IDE_ENABLE, value);
280f6d57916SPaul Mackerras default:
281f6d57916SPaul Mackerras return -ENODEV;
282f6d57916SPaul Mackerras }
283f6d57916SPaul Mackerras }
284f6d57916SPaul Mackerras
ohare_ide_reset(struct device_node * node,long param,long value)285f6d57916SPaul Mackerras static long ohare_ide_reset(struct device_node *node, long param, long value)
286f6d57916SPaul Mackerras {
287f6d57916SPaul Mackerras switch(param) {
288f6d57916SPaul Mackerras case 0:
289f6d57916SPaul Mackerras return simple_feature_tweak(node, macio_ohare,
290f6d57916SPaul Mackerras OHARE_FCR, OH_IDE0_RESET_N, !value);
291f6d57916SPaul Mackerras case 1:
292f6d57916SPaul Mackerras return simple_feature_tweak(node, macio_ohare,
293f6d57916SPaul Mackerras OHARE_FCR, OH_IDE1_RESET_N, !value);
294f6d57916SPaul Mackerras default:
295f6d57916SPaul Mackerras return -ENODEV;
296f6d57916SPaul Mackerras }
297f6d57916SPaul Mackerras }
298f6d57916SPaul Mackerras
ohare_sleep_state(struct device_node * node,long param,long value)299f6d57916SPaul Mackerras static long ohare_sleep_state(struct device_node *node, long param, long value)
300f6d57916SPaul Mackerras {
301f6d57916SPaul Mackerras struct macio_chip* macio = &macio_chips[0];
302f6d57916SPaul Mackerras
303f6d57916SPaul Mackerras if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
304f6d57916SPaul Mackerras return -EPERM;
305f6d57916SPaul Mackerras if (value == 1) {
306f6d57916SPaul Mackerras MACIO_BIC(OHARE_FCR, OH_IOBUS_ENABLE);
307f6d57916SPaul Mackerras } else if (value == 0) {
308f6d57916SPaul Mackerras MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
309f6d57916SPaul Mackerras }
310f6d57916SPaul Mackerras
311f6d57916SPaul Mackerras return 0;
312f6d57916SPaul Mackerras }
313f6d57916SPaul Mackerras
heathrow_modem_enable(struct device_node * node,long param,long value)314f6d57916SPaul Mackerras static long heathrow_modem_enable(struct device_node *node, long param,
315f6d57916SPaul Mackerras long value)
316f6d57916SPaul Mackerras {
317f6d57916SPaul Mackerras struct macio_chip* macio;
318f6d57916SPaul Mackerras u8 gpio;
319f6d57916SPaul Mackerras unsigned long flags;
320f6d57916SPaul Mackerras
321f6d57916SPaul Mackerras macio = macio_find(node, macio_unknown);
322f6d57916SPaul Mackerras if (!macio)
323f6d57916SPaul Mackerras return -ENODEV;
324f6d57916SPaul Mackerras gpio = MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1;
325f6d57916SPaul Mackerras if (!value) {
326f6d57916SPaul Mackerras LOCK(flags);
327f6d57916SPaul Mackerras MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio);
328f6d57916SPaul Mackerras UNLOCK(flags);
329f6d57916SPaul Mackerras (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
330f6d57916SPaul Mackerras mdelay(250);
331f6d57916SPaul Mackerras }
332f6d57916SPaul Mackerras if (pmac_mb.model_id != PMAC_TYPE_YOSEMITE &&
333f6d57916SPaul Mackerras pmac_mb.model_id != PMAC_TYPE_YIKES) {
334f6d57916SPaul Mackerras LOCK(flags);
335f6d57916SPaul Mackerras if (value)
336f6d57916SPaul Mackerras MACIO_BIC(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
337f6d57916SPaul Mackerras else
338f6d57916SPaul Mackerras MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
339f6d57916SPaul Mackerras UNLOCK(flags);
340f6d57916SPaul Mackerras (void)MACIO_IN32(HEATHROW_FCR);
341f6d57916SPaul Mackerras mdelay(250);
342f6d57916SPaul Mackerras }
343f6d57916SPaul Mackerras if (value) {
344f6d57916SPaul Mackerras LOCK(flags);
345f6d57916SPaul Mackerras MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);
346f6d57916SPaul Mackerras (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
347f6d57916SPaul Mackerras UNLOCK(flags); mdelay(250); LOCK(flags);
348f6d57916SPaul Mackerras MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio);
349f6d57916SPaul Mackerras (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
350f6d57916SPaul Mackerras UNLOCK(flags); mdelay(250); LOCK(flags);
351f6d57916SPaul Mackerras MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);
352f6d57916SPaul Mackerras (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
353f6d57916SPaul Mackerras UNLOCK(flags); mdelay(250);
354f6d57916SPaul Mackerras }
355f6d57916SPaul Mackerras return 0;
356f6d57916SPaul Mackerras }
357f6d57916SPaul Mackerras
heathrow_floppy_enable(struct device_node * node,long param,long value)358f6d57916SPaul Mackerras static long heathrow_floppy_enable(struct device_node *node, long param,
359f6d57916SPaul Mackerras long value)
360f6d57916SPaul Mackerras {
361f6d57916SPaul Mackerras return simple_feature_tweak(node, macio_unknown,
362f6d57916SPaul Mackerras HEATHROW_FCR,
363f6d57916SPaul Mackerras HRW_SWIM_ENABLE|HRW_BAY_FLOPPY_ENABLE,
364f6d57916SPaul Mackerras value);
365f6d57916SPaul Mackerras }
366f6d57916SPaul Mackerras
heathrow_mesh_enable(struct device_node * node,long param,long value)367f6d57916SPaul Mackerras static long heathrow_mesh_enable(struct device_node *node, long param,
368f6d57916SPaul Mackerras long value)
369f6d57916SPaul Mackerras {
370f6d57916SPaul Mackerras struct macio_chip* macio;
371f6d57916SPaul Mackerras unsigned long flags;
372f6d57916SPaul Mackerras
373f6d57916SPaul Mackerras macio = macio_find(node, macio_unknown);
374f6d57916SPaul Mackerras if (!macio)
375f6d57916SPaul Mackerras return -ENODEV;
376f6d57916SPaul Mackerras LOCK(flags);
377f6d57916SPaul Mackerras /* Set clear mesh cell enable */
378f6d57916SPaul Mackerras if (value)
379f6d57916SPaul Mackerras MACIO_BIS(HEATHROW_FCR, HRW_MESH_ENABLE);
380f6d57916SPaul Mackerras else
381f6d57916SPaul Mackerras MACIO_BIC(HEATHROW_FCR, HRW_MESH_ENABLE);
382f6d57916SPaul Mackerras (void)MACIO_IN32(HEATHROW_FCR);
383f6d57916SPaul Mackerras udelay(10);
384f6d57916SPaul Mackerras /* Set/Clear termination power */
385f6d57916SPaul Mackerras if (value)
386f6d57916SPaul Mackerras MACIO_BIC(HEATHROW_MBCR, 0x04000000);
387f6d57916SPaul Mackerras else
388f6d57916SPaul Mackerras MACIO_BIS(HEATHROW_MBCR, 0x04000000);
389f6d57916SPaul Mackerras (void)MACIO_IN32(HEATHROW_MBCR);
390f6d57916SPaul Mackerras udelay(10);
391f6d57916SPaul Mackerras UNLOCK(flags);
392f6d57916SPaul Mackerras
393f6d57916SPaul Mackerras return 0;
394f6d57916SPaul Mackerras }
395f6d57916SPaul Mackerras
heathrow_ide_enable(struct device_node * node,long param,long value)396f6d57916SPaul Mackerras static long heathrow_ide_enable(struct device_node *node, long param,
397f6d57916SPaul Mackerras long value)
398f6d57916SPaul Mackerras {
399f6d57916SPaul Mackerras switch(param) {
400f6d57916SPaul Mackerras case 0:
401f6d57916SPaul Mackerras return simple_feature_tweak(node, macio_unknown,
402f6d57916SPaul Mackerras HEATHROW_FCR, HRW_IDE0_ENABLE, value);
403f6d57916SPaul Mackerras case 1:
404f6d57916SPaul Mackerras return simple_feature_tweak(node, macio_unknown,
405f6d57916SPaul Mackerras HEATHROW_FCR, HRW_BAY_IDE_ENABLE, value);
406f6d57916SPaul Mackerras default:
407f6d57916SPaul Mackerras return -ENODEV;
408f6d57916SPaul Mackerras }
409f6d57916SPaul Mackerras }
410f6d57916SPaul Mackerras
heathrow_ide_reset(struct device_node * node,long param,long value)411f6d57916SPaul Mackerras static long heathrow_ide_reset(struct device_node *node, long param,
412f6d57916SPaul Mackerras long value)
413f6d57916SPaul Mackerras {
414f6d57916SPaul Mackerras switch(param) {
415f6d57916SPaul Mackerras case 0:
416f6d57916SPaul Mackerras return simple_feature_tweak(node, macio_unknown,
417f6d57916SPaul Mackerras HEATHROW_FCR, HRW_IDE0_RESET_N, !value);
418f6d57916SPaul Mackerras case 1:
419f6d57916SPaul Mackerras return simple_feature_tweak(node, macio_unknown,
420f6d57916SPaul Mackerras HEATHROW_FCR, HRW_IDE1_RESET_N, !value);
421f6d57916SPaul Mackerras default:
422f6d57916SPaul Mackerras return -ENODEV;
423f6d57916SPaul Mackerras }
424f6d57916SPaul Mackerras }
425f6d57916SPaul Mackerras
heathrow_bmac_enable(struct device_node * node,long param,long value)426f6d57916SPaul Mackerras static long heathrow_bmac_enable(struct device_node *node, long param,
427f6d57916SPaul Mackerras long value)
428f6d57916SPaul Mackerras {
429f6d57916SPaul Mackerras struct macio_chip* macio;
430f6d57916SPaul Mackerras unsigned long flags;
431f6d57916SPaul Mackerras
432f6d57916SPaul Mackerras macio = macio_find(node, 0);
433f6d57916SPaul Mackerras if (!macio)
434f6d57916SPaul Mackerras return -ENODEV;
435f6d57916SPaul Mackerras if (value) {
436f6d57916SPaul Mackerras LOCK(flags);
437f6d57916SPaul Mackerras MACIO_BIS(HEATHROW_FCR, HRW_BMAC_IO_ENABLE);
438f6d57916SPaul Mackerras MACIO_BIS(HEATHROW_FCR, HRW_BMAC_RESET);
439f6d57916SPaul Mackerras UNLOCK(flags);
440f6d57916SPaul Mackerras (void)MACIO_IN32(HEATHROW_FCR);
441f6d57916SPaul Mackerras mdelay(10);
442f6d57916SPaul Mackerras LOCK(flags);
443f6d57916SPaul Mackerras MACIO_BIC(HEATHROW_FCR, HRW_BMAC_RESET);
444f6d57916SPaul Mackerras UNLOCK(flags);
445f6d57916SPaul Mackerras (void)MACIO_IN32(HEATHROW_FCR);
446f6d57916SPaul Mackerras mdelay(10);
447f6d57916SPaul Mackerras } else {
448f6d57916SPaul Mackerras LOCK(flags);
449f6d57916SPaul Mackerras MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE);
450f6d57916SPaul Mackerras UNLOCK(flags);
451f6d57916SPaul Mackerras }
452f6d57916SPaul Mackerras return 0;
453f6d57916SPaul Mackerras }
454f6d57916SPaul Mackerras
heathrow_sound_enable(struct device_node * node,long param,long value)455f6d57916SPaul Mackerras static long heathrow_sound_enable(struct device_node *node, long param,
456f6d57916SPaul Mackerras long value)
457f6d57916SPaul Mackerras {
458f6d57916SPaul Mackerras struct macio_chip* macio;
459f6d57916SPaul Mackerras unsigned long flags;
460f6d57916SPaul Mackerras
461f6d57916SPaul Mackerras /* B&W G3 and Yikes don't support that properly (the
462446957baSAdam Buchbinder * sound appear to never come back after being shut down).
463f6d57916SPaul Mackerras */
464f6d57916SPaul Mackerras if (pmac_mb.model_id == PMAC_TYPE_YOSEMITE ||
465f6d57916SPaul Mackerras pmac_mb.model_id == PMAC_TYPE_YIKES)
466f6d57916SPaul Mackerras return 0;
467f6d57916SPaul Mackerras
468f6d57916SPaul Mackerras macio = macio_find(node, 0);
469f6d57916SPaul Mackerras if (!macio)
470f6d57916SPaul Mackerras return -ENODEV;
471f6d57916SPaul Mackerras if (value) {
472f6d57916SPaul Mackerras LOCK(flags);
473f6d57916SPaul Mackerras MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
474f6d57916SPaul Mackerras MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
475f6d57916SPaul Mackerras UNLOCK(flags);
476f6d57916SPaul Mackerras (void)MACIO_IN32(HEATHROW_FCR);
477f6d57916SPaul Mackerras } else {
478f6d57916SPaul Mackerras LOCK(flags);
479f6d57916SPaul Mackerras MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N);
480f6d57916SPaul Mackerras MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
481f6d57916SPaul Mackerras UNLOCK(flags);
482f6d57916SPaul Mackerras }
483f6d57916SPaul Mackerras return 0;
484f6d57916SPaul Mackerras }
485f6d57916SPaul Mackerras
486f6d57916SPaul Mackerras static u32 save_fcr[6];
487f6d57916SPaul Mackerras static u32 save_mbcr;
488f6d57916SPaul Mackerras static struct dbdma_regs save_dbdma[13];
489f6d57916SPaul Mackerras static struct dbdma_regs save_alt_dbdma[13];
490f6d57916SPaul Mackerras
dbdma_save(struct macio_chip * macio,struct dbdma_regs * save)491f6d57916SPaul Mackerras static void dbdma_save(struct macio_chip *macio, struct dbdma_regs *save)
492f6d57916SPaul Mackerras {
493f6d57916SPaul Mackerras int i;
494f6d57916SPaul Mackerras
495f6d57916SPaul Mackerras /* Save state & config of DBDMA channels */
496f6d57916SPaul Mackerras for (i = 0; i < 13; i++) {
497f6d57916SPaul Mackerras volatile struct dbdma_regs __iomem * chan = (void __iomem *)
498f6d57916SPaul Mackerras (macio->base + ((0x8000+i*0x100)>>2));
499f6d57916SPaul Mackerras save[i].cmdptr_hi = in_le32(&chan->cmdptr_hi);
500f6d57916SPaul Mackerras save[i].cmdptr = in_le32(&chan->cmdptr);
501f6d57916SPaul Mackerras save[i].intr_sel = in_le32(&chan->intr_sel);
502f6d57916SPaul Mackerras save[i].br_sel = in_le32(&chan->br_sel);
503f6d57916SPaul Mackerras save[i].wait_sel = in_le32(&chan->wait_sel);
504f6d57916SPaul Mackerras }
505f6d57916SPaul Mackerras }
506f6d57916SPaul Mackerras
dbdma_restore(struct macio_chip * macio,struct dbdma_regs * save)507f6d57916SPaul Mackerras static void dbdma_restore(struct macio_chip *macio, struct dbdma_regs *save)
508f6d57916SPaul Mackerras {
509f6d57916SPaul Mackerras int i;
510f6d57916SPaul Mackerras
511f6d57916SPaul Mackerras /* Save state & config of DBDMA channels */
512f6d57916SPaul Mackerras for (i = 0; i < 13; i++) {
513f6d57916SPaul Mackerras volatile struct dbdma_regs __iomem * chan = (void __iomem *)
514f6d57916SPaul Mackerras (macio->base + ((0x8000+i*0x100)>>2));
515f6d57916SPaul Mackerras out_le32(&chan->control, (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16);
516f6d57916SPaul Mackerras while (in_le32(&chan->status) & ACTIVE)
517f6d57916SPaul Mackerras mb();
518f6d57916SPaul Mackerras out_le32(&chan->cmdptr_hi, save[i].cmdptr_hi);
519f6d57916SPaul Mackerras out_le32(&chan->cmdptr, save[i].cmdptr);
520f6d57916SPaul Mackerras out_le32(&chan->intr_sel, save[i].intr_sel);
521f6d57916SPaul Mackerras out_le32(&chan->br_sel, save[i].br_sel);
522f6d57916SPaul Mackerras out_le32(&chan->wait_sel, save[i].wait_sel);
523f6d57916SPaul Mackerras }
524f6d57916SPaul Mackerras }
525f6d57916SPaul Mackerras
heathrow_sleep(struct macio_chip * macio,int secondary)526f6d57916SPaul Mackerras static void heathrow_sleep(struct macio_chip *macio, int secondary)
527f6d57916SPaul Mackerras {
528f6d57916SPaul Mackerras if (secondary) {
529f6d57916SPaul Mackerras dbdma_save(macio, save_alt_dbdma);
530f6d57916SPaul Mackerras save_fcr[2] = MACIO_IN32(0x38);
531f6d57916SPaul Mackerras save_fcr[3] = MACIO_IN32(0x3c);
532f6d57916SPaul Mackerras } else {
533f6d57916SPaul Mackerras dbdma_save(macio, save_dbdma);
534f6d57916SPaul Mackerras save_fcr[0] = MACIO_IN32(0x38);
535f6d57916SPaul Mackerras save_fcr[1] = MACIO_IN32(0x3c);
536f6d57916SPaul Mackerras save_mbcr = MACIO_IN32(0x34);
537f6d57916SPaul Mackerras /* Make sure sound is shut down */
538f6d57916SPaul Mackerras MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N);
539f6d57916SPaul Mackerras MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
540f6d57916SPaul Mackerras /* This seems to be necessary as well or the fan
541f6d57916SPaul Mackerras * keeps coming up and battery drains fast */
542f6d57916SPaul Mackerras MACIO_BIC(HEATHROW_FCR, HRW_IOBUS_ENABLE);
543f6d57916SPaul Mackerras MACIO_BIC(HEATHROW_FCR, HRW_IDE0_RESET_N);
544f6d57916SPaul Mackerras /* Make sure eth is down even if module or sleep
545f6d57916SPaul Mackerras * won't work properly */
546f6d57916SPaul Mackerras MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE | HRW_BMAC_RESET);
547f6d57916SPaul Mackerras }
548f6d57916SPaul Mackerras /* Make sure modem is shut down */
549f6d57916SPaul Mackerras MACIO_OUT8(HRW_GPIO_MODEM_RESET,
550f6d57916SPaul Mackerras MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1);
551f6d57916SPaul Mackerras MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
552f6d57916SPaul Mackerras MACIO_BIC(HEATHROW_FCR, OH_SCCA_IO|OH_SCCB_IO|HRW_SCC_ENABLE);
553f6d57916SPaul Mackerras
554f6d57916SPaul Mackerras /* Let things settle */
555f6d57916SPaul Mackerras (void)MACIO_IN32(HEATHROW_FCR);
556f6d57916SPaul Mackerras }
557f6d57916SPaul Mackerras
heathrow_wakeup(struct macio_chip * macio,int secondary)558f6d57916SPaul Mackerras static void heathrow_wakeup(struct macio_chip *macio, int secondary)
559f6d57916SPaul Mackerras {
560f6d57916SPaul Mackerras if (secondary) {
561f6d57916SPaul Mackerras MACIO_OUT32(0x38, save_fcr[2]);
562f6d57916SPaul Mackerras (void)MACIO_IN32(0x38);
563f6d57916SPaul Mackerras mdelay(1);
564f6d57916SPaul Mackerras MACIO_OUT32(0x3c, save_fcr[3]);
565f6d57916SPaul Mackerras (void)MACIO_IN32(0x38);
566f6d57916SPaul Mackerras mdelay(10);
567f6d57916SPaul Mackerras dbdma_restore(macio, save_alt_dbdma);
568f6d57916SPaul Mackerras } else {
569f6d57916SPaul Mackerras MACIO_OUT32(0x38, save_fcr[0] | HRW_IOBUS_ENABLE);
570f6d57916SPaul Mackerras (void)MACIO_IN32(0x38);
571f6d57916SPaul Mackerras mdelay(1);
572f6d57916SPaul Mackerras MACIO_OUT32(0x3c, save_fcr[1]);
573f6d57916SPaul Mackerras (void)MACIO_IN32(0x38);
574f6d57916SPaul Mackerras mdelay(1);
575f6d57916SPaul Mackerras MACIO_OUT32(0x34, save_mbcr);
576f6d57916SPaul Mackerras (void)MACIO_IN32(0x38);
577f6d57916SPaul Mackerras mdelay(10);
578f6d57916SPaul Mackerras dbdma_restore(macio, save_dbdma);
579f6d57916SPaul Mackerras }
580f6d57916SPaul Mackerras }
581f6d57916SPaul Mackerras
heathrow_sleep_state(struct device_node * node,long param,long value)582f6d57916SPaul Mackerras static long heathrow_sleep_state(struct device_node *node, long param,
583f6d57916SPaul Mackerras long value)
584f6d57916SPaul Mackerras {
585f6d57916SPaul Mackerras if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
586f6d57916SPaul Mackerras return -EPERM;
587f6d57916SPaul Mackerras if (value == 1) {
588f6d57916SPaul Mackerras if (macio_chips[1].type == macio_gatwick)
589f6d57916SPaul Mackerras heathrow_sleep(&macio_chips[0], 1);
590f6d57916SPaul Mackerras heathrow_sleep(&macio_chips[0], 0);
591f6d57916SPaul Mackerras } else if (value == 0) {
592f6d57916SPaul Mackerras heathrow_wakeup(&macio_chips[0], 0);
593f6d57916SPaul Mackerras if (macio_chips[1].type == macio_gatwick)
594f6d57916SPaul Mackerras heathrow_wakeup(&macio_chips[0], 1);
595f6d57916SPaul Mackerras }
596f6d57916SPaul Mackerras return 0;
597f6d57916SPaul Mackerras }
598f6d57916SPaul Mackerras
core99_scc_enable(struct device_node * node,long param,long value)599f6d57916SPaul Mackerras static long core99_scc_enable(struct device_node *node, long param, long value)
600f6d57916SPaul Mackerras {
601f6d57916SPaul Mackerras struct macio_chip* macio;
602f6d57916SPaul Mackerras unsigned long flags;
603f6d57916SPaul Mackerras unsigned long chan_mask;
604f6d57916SPaul Mackerras u32 fcr;
605f6d57916SPaul Mackerras
606f6d57916SPaul Mackerras macio = macio_find(node, 0);
607f6d57916SPaul Mackerras if (!macio)
608f6d57916SPaul Mackerras return -ENODEV;
6092c8e65b5SRob Herring if (of_node_name_eq(node, "ch-a"))
610f6d57916SPaul Mackerras chan_mask = MACIO_FLAG_SCCA_ON;
6112c8e65b5SRob Herring else if (of_node_name_eq(node, "ch-b"))
612f6d57916SPaul Mackerras chan_mask = MACIO_FLAG_SCCB_ON;
613f6d57916SPaul Mackerras else
614f6d57916SPaul Mackerras return -ENODEV;
615f6d57916SPaul Mackerras
616f6d57916SPaul Mackerras if (value) {
617f6d57916SPaul Mackerras int need_reset_scc = 0;
618f6d57916SPaul Mackerras int need_reset_irda = 0;
619f6d57916SPaul Mackerras
620f6d57916SPaul Mackerras LOCK(flags);
621f6d57916SPaul Mackerras fcr = MACIO_IN32(KEYLARGO_FCR0);
622f6d57916SPaul Mackerras /* Check if scc cell need enabling */
623f6d57916SPaul Mackerras if (!(fcr & KL0_SCC_CELL_ENABLE)) {
624f6d57916SPaul Mackerras fcr |= KL0_SCC_CELL_ENABLE;
625f6d57916SPaul Mackerras need_reset_scc = 1;
626f6d57916SPaul Mackerras }
627f6d57916SPaul Mackerras if (chan_mask & MACIO_FLAG_SCCA_ON) {
628f6d57916SPaul Mackerras fcr |= KL0_SCCA_ENABLE;
629f6d57916SPaul Mackerras /* Don't enable line drivers for I2S modem */
630f6d57916SPaul Mackerras if ((param & 0xfff) == PMAC_SCC_I2S1)
631f6d57916SPaul Mackerras fcr &= ~KL0_SCC_A_INTF_ENABLE;
632f6d57916SPaul Mackerras else
633f6d57916SPaul Mackerras fcr |= KL0_SCC_A_INTF_ENABLE;
634f6d57916SPaul Mackerras }
635f6d57916SPaul Mackerras if (chan_mask & MACIO_FLAG_SCCB_ON) {
636f6d57916SPaul Mackerras fcr |= KL0_SCCB_ENABLE;
637f6d57916SPaul Mackerras /* Perform irda specific inits */
638f6d57916SPaul Mackerras if ((param & 0xfff) == PMAC_SCC_IRDA) {
639f6d57916SPaul Mackerras fcr &= ~KL0_SCC_B_INTF_ENABLE;
640f6d57916SPaul Mackerras fcr |= KL0_IRDA_ENABLE;
641f6d57916SPaul Mackerras fcr |= KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE;
642f6d57916SPaul Mackerras fcr |= KL0_IRDA_SOURCE1_SEL;
643f6d57916SPaul Mackerras fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0);
644f6d57916SPaul Mackerras fcr &= ~(KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND);
645f6d57916SPaul Mackerras need_reset_irda = 1;
646f6d57916SPaul Mackerras } else
647f6d57916SPaul Mackerras fcr |= KL0_SCC_B_INTF_ENABLE;
648f6d57916SPaul Mackerras }
649f6d57916SPaul Mackerras MACIO_OUT32(KEYLARGO_FCR0, fcr);
650f6d57916SPaul Mackerras macio->flags |= chan_mask;
651f6d57916SPaul Mackerras if (need_reset_scc) {
652f6d57916SPaul Mackerras MACIO_BIS(KEYLARGO_FCR0, KL0_SCC_RESET);
653f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR0);
654f6d57916SPaul Mackerras UNLOCK(flags);
655f6d57916SPaul Mackerras mdelay(15);
656f6d57916SPaul Mackerras LOCK(flags);
657f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_FCR0, KL0_SCC_RESET);
658f6d57916SPaul Mackerras }
659f6d57916SPaul Mackerras if (need_reset_irda) {
660f6d57916SPaul Mackerras MACIO_BIS(KEYLARGO_FCR0, KL0_IRDA_RESET);
661f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR0);
662f6d57916SPaul Mackerras UNLOCK(flags);
663f6d57916SPaul Mackerras mdelay(15);
664f6d57916SPaul Mackerras LOCK(flags);
665f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_FCR0, KL0_IRDA_RESET);
666f6d57916SPaul Mackerras }
667f6d57916SPaul Mackerras UNLOCK(flags);
668f6d57916SPaul Mackerras if (param & PMAC_SCC_FLAG_XMON)
669f6d57916SPaul Mackerras macio->flags |= MACIO_FLAG_SCC_LOCKED;
670f6d57916SPaul Mackerras } else {
671f6d57916SPaul Mackerras if (macio->flags & MACIO_FLAG_SCC_LOCKED)
672f6d57916SPaul Mackerras return -EPERM;
673f6d57916SPaul Mackerras LOCK(flags);
674f6d57916SPaul Mackerras fcr = MACIO_IN32(KEYLARGO_FCR0);
675f6d57916SPaul Mackerras if (chan_mask & MACIO_FLAG_SCCA_ON)
676f6d57916SPaul Mackerras fcr &= ~KL0_SCCA_ENABLE;
677f6d57916SPaul Mackerras if (chan_mask & MACIO_FLAG_SCCB_ON) {
678f6d57916SPaul Mackerras fcr &= ~KL0_SCCB_ENABLE;
679f6d57916SPaul Mackerras /* Perform irda specific clears */
680f6d57916SPaul Mackerras if ((param & 0xfff) == PMAC_SCC_IRDA) {
681f6d57916SPaul Mackerras fcr &= ~KL0_IRDA_ENABLE;
682f6d57916SPaul Mackerras fcr &= ~(KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE);
683f6d57916SPaul Mackerras fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0);
684f6d57916SPaul Mackerras fcr &= ~(KL0_IRDA_SOURCE1_SEL|KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND);
685f6d57916SPaul Mackerras }
686f6d57916SPaul Mackerras }
687f6d57916SPaul Mackerras MACIO_OUT32(KEYLARGO_FCR0, fcr);
688f6d57916SPaul Mackerras if ((fcr & (KL0_SCCA_ENABLE | KL0_SCCB_ENABLE)) == 0) {
689f6d57916SPaul Mackerras fcr &= ~KL0_SCC_CELL_ENABLE;
690f6d57916SPaul Mackerras MACIO_OUT32(KEYLARGO_FCR0, fcr);
691f6d57916SPaul Mackerras }
692f6d57916SPaul Mackerras macio->flags &= ~(chan_mask);
693f6d57916SPaul Mackerras UNLOCK(flags);
694f6d57916SPaul Mackerras mdelay(10);
695f6d57916SPaul Mackerras }
696f6d57916SPaul Mackerras return 0;
697f6d57916SPaul Mackerras }
698f6d57916SPaul Mackerras
699f6d57916SPaul Mackerras static long
core99_modem_enable(struct device_node * node,long param,long value)700f6d57916SPaul Mackerras core99_modem_enable(struct device_node *node, long param, long value)
701f6d57916SPaul Mackerras {
702f6d57916SPaul Mackerras struct macio_chip* macio;
703f6d57916SPaul Mackerras u8 gpio;
704f6d57916SPaul Mackerras unsigned long flags;
705f6d57916SPaul Mackerras
706f6d57916SPaul Mackerras /* Hack for internal USB modem */
707f6d57916SPaul Mackerras if (node == NULL) {
708f6d57916SPaul Mackerras if (macio_chips[0].type != macio_keylargo)
709f6d57916SPaul Mackerras return -ENODEV;
710f6d57916SPaul Mackerras node = macio_chips[0].of_node;
711f6d57916SPaul Mackerras }
712f6d57916SPaul Mackerras macio = macio_find(node, 0);
713f6d57916SPaul Mackerras if (!macio)
714f6d57916SPaul Mackerras return -ENODEV;
715f6d57916SPaul Mackerras gpio = MACIO_IN8(KL_GPIO_MODEM_RESET);
716f6d57916SPaul Mackerras gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE;
717f6d57916SPaul Mackerras gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA;
718f6d57916SPaul Mackerras
719f6d57916SPaul Mackerras if (!value) {
720f6d57916SPaul Mackerras LOCK(flags);
721f6d57916SPaul Mackerras MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
722f6d57916SPaul Mackerras UNLOCK(flags);
723f6d57916SPaul Mackerras (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
724f6d57916SPaul Mackerras mdelay(250);
725f6d57916SPaul Mackerras }
726f6d57916SPaul Mackerras LOCK(flags);
727f6d57916SPaul Mackerras if (value) {
728f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
729f6d57916SPaul Mackerras UNLOCK(flags);
730f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR2);
731f6d57916SPaul Mackerras mdelay(250);
732f6d57916SPaul Mackerras } else {
733f6d57916SPaul Mackerras MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
734f6d57916SPaul Mackerras UNLOCK(flags);
735f6d57916SPaul Mackerras }
736f6d57916SPaul Mackerras if (value) {
737f6d57916SPaul Mackerras LOCK(flags);
738f6d57916SPaul Mackerras MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
739f6d57916SPaul Mackerras (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
740f6d57916SPaul Mackerras UNLOCK(flags); mdelay(250); LOCK(flags);
741f6d57916SPaul Mackerras MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
742f6d57916SPaul Mackerras (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
743f6d57916SPaul Mackerras UNLOCK(flags); mdelay(250); LOCK(flags);
744f6d57916SPaul Mackerras MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
745f6d57916SPaul Mackerras (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
746f6d57916SPaul Mackerras UNLOCK(flags); mdelay(250);
747f6d57916SPaul Mackerras }
748f6d57916SPaul Mackerras return 0;
749f6d57916SPaul Mackerras }
750f6d57916SPaul Mackerras
751f6d57916SPaul Mackerras static long
pangea_modem_enable(struct device_node * node,long param,long value)752f6d57916SPaul Mackerras pangea_modem_enable(struct device_node *node, long param, long value)
753f6d57916SPaul Mackerras {
754f6d57916SPaul Mackerras struct macio_chip* macio;
755f6d57916SPaul Mackerras u8 gpio;
756f6d57916SPaul Mackerras unsigned long flags;
757f6d57916SPaul Mackerras
758f6d57916SPaul Mackerras /* Hack for internal USB modem */
759f6d57916SPaul Mackerras if (node == NULL) {
760f6d57916SPaul Mackerras if (macio_chips[0].type != macio_pangea &&
761f6d57916SPaul Mackerras macio_chips[0].type != macio_intrepid)
762f6d57916SPaul Mackerras return -ENODEV;
763f6d57916SPaul Mackerras node = macio_chips[0].of_node;
764f6d57916SPaul Mackerras }
765f6d57916SPaul Mackerras macio = macio_find(node, 0);
766f6d57916SPaul Mackerras if (!macio)
767f6d57916SPaul Mackerras return -ENODEV;
768f6d57916SPaul Mackerras gpio = MACIO_IN8(KL_GPIO_MODEM_RESET);
769f6d57916SPaul Mackerras gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE;
770f6d57916SPaul Mackerras gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA;
771f6d57916SPaul Mackerras
772f6d57916SPaul Mackerras if (!value) {
773f6d57916SPaul Mackerras LOCK(flags);
774f6d57916SPaul Mackerras MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
775f6d57916SPaul Mackerras UNLOCK(flags);
776f6d57916SPaul Mackerras (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
777f6d57916SPaul Mackerras mdelay(250);
778f6d57916SPaul Mackerras }
779f6d57916SPaul Mackerras LOCK(flags);
780f6d57916SPaul Mackerras if (value) {
781f6d57916SPaul Mackerras MACIO_OUT8(KL_GPIO_MODEM_POWER,
782f6d57916SPaul Mackerras KEYLARGO_GPIO_OUTPUT_ENABLE);
783f6d57916SPaul Mackerras UNLOCK(flags);
784f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR2);
785f6d57916SPaul Mackerras mdelay(250);
786f6d57916SPaul Mackerras } else {
787f6d57916SPaul Mackerras MACIO_OUT8(KL_GPIO_MODEM_POWER,
788f6d57916SPaul Mackerras KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
789f6d57916SPaul Mackerras UNLOCK(flags);
790f6d57916SPaul Mackerras }
791f6d57916SPaul Mackerras if (value) {
792f6d57916SPaul Mackerras LOCK(flags);
793f6d57916SPaul Mackerras MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
794f6d57916SPaul Mackerras (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
795f6d57916SPaul Mackerras UNLOCK(flags); mdelay(250); LOCK(flags);
796f6d57916SPaul Mackerras MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
797f6d57916SPaul Mackerras (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
798f6d57916SPaul Mackerras UNLOCK(flags); mdelay(250); LOCK(flags);
799f6d57916SPaul Mackerras MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
800f6d57916SPaul Mackerras (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
801f6d57916SPaul Mackerras UNLOCK(flags); mdelay(250);
802f6d57916SPaul Mackerras }
803f6d57916SPaul Mackerras return 0;
804f6d57916SPaul Mackerras }
805f6d57916SPaul Mackerras
806f6d57916SPaul Mackerras static long
core99_ata100_enable(struct device_node * node,long value)807f6d57916SPaul Mackerras core99_ata100_enable(struct device_node *node, long value)
808f6d57916SPaul Mackerras {
809f6d57916SPaul Mackerras unsigned long flags;
810f6d57916SPaul Mackerras struct pci_dev *pdev = NULL;
811f6d57916SPaul Mackerras u8 pbus, pid;
812e71c5c38SBenjamin Herrenschmidt int rc;
813f6d57916SPaul Mackerras
814f6d57916SPaul Mackerras if (uninorth_rev < 0x24)
815f6d57916SPaul Mackerras return -ENODEV;
816f6d57916SPaul Mackerras
817f6d57916SPaul Mackerras LOCK(flags);
818f6d57916SPaul Mackerras if (value)
819f6d57916SPaul Mackerras UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100);
820f6d57916SPaul Mackerras else
821f6d57916SPaul Mackerras UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100);
822f6d57916SPaul Mackerras (void)UN_IN(UNI_N_CLOCK_CNTL);
823f6d57916SPaul Mackerras UNLOCK(flags);
824f6d57916SPaul Mackerras udelay(20);
825f6d57916SPaul Mackerras
826f6d57916SPaul Mackerras if (value) {
827f6d57916SPaul Mackerras if (pci_device_from_OF_node(node, &pbus, &pid) == 0)
82850ed5780SSinan Kaya pdev = pci_get_domain_bus_and_slot(0, pbus, pid);
829f6d57916SPaul Mackerras if (pdev == NULL)
830f6d57916SPaul Mackerras return 0;
831e71c5c38SBenjamin Herrenschmidt rc = pci_enable_device(pdev);
83256282440SSegher Boessenkool if (rc == 0)
83356282440SSegher Boessenkool pci_set_master(pdev);
83456282440SSegher Boessenkool pci_dev_put(pdev);
835e71c5c38SBenjamin Herrenschmidt if (rc)
836e71c5c38SBenjamin Herrenschmidt return rc;
837f6d57916SPaul Mackerras }
838f6d57916SPaul Mackerras return 0;
839f6d57916SPaul Mackerras }
840f6d57916SPaul Mackerras
841f6d57916SPaul Mackerras static long
core99_ide_enable(struct device_node * node,long param,long value)842f6d57916SPaul Mackerras core99_ide_enable(struct device_node *node, long param, long value)
843f6d57916SPaul Mackerras {
844f6d57916SPaul Mackerras /* Bus ID 0 to 2 are KeyLargo based IDE, busID 3 is U2
845f6d57916SPaul Mackerras * based ata-100
846f6d57916SPaul Mackerras */
847f6d57916SPaul Mackerras switch(param) {
848f6d57916SPaul Mackerras case 0:
849f6d57916SPaul Mackerras return simple_feature_tweak(node, macio_unknown,
850f6d57916SPaul Mackerras KEYLARGO_FCR1, KL1_EIDE0_ENABLE, value);
851f6d57916SPaul Mackerras case 1:
852f6d57916SPaul Mackerras return simple_feature_tweak(node, macio_unknown,
853f6d57916SPaul Mackerras KEYLARGO_FCR1, KL1_EIDE1_ENABLE, value);
854f6d57916SPaul Mackerras case 2:
855f6d57916SPaul Mackerras return simple_feature_tweak(node, macio_unknown,
856f6d57916SPaul Mackerras KEYLARGO_FCR1, KL1_UIDE_ENABLE, value);
857f6d57916SPaul Mackerras case 3:
858f6d57916SPaul Mackerras return core99_ata100_enable(node, value);
859f6d57916SPaul Mackerras default:
860f6d57916SPaul Mackerras return -ENODEV;
861f6d57916SPaul Mackerras }
862f6d57916SPaul Mackerras }
863f6d57916SPaul Mackerras
864f6d57916SPaul Mackerras static long
core99_ide_reset(struct device_node * node,long param,long value)865f6d57916SPaul Mackerras core99_ide_reset(struct device_node *node, long param, long value)
866f6d57916SPaul Mackerras {
867f6d57916SPaul Mackerras switch(param) {
868f6d57916SPaul Mackerras case 0:
869f6d57916SPaul Mackerras return simple_feature_tweak(node, macio_unknown,
870f6d57916SPaul Mackerras KEYLARGO_FCR1, KL1_EIDE0_RESET_N, !value);
871f6d57916SPaul Mackerras case 1:
872f6d57916SPaul Mackerras return simple_feature_tweak(node, macio_unknown,
873f6d57916SPaul Mackerras KEYLARGO_FCR1, KL1_EIDE1_RESET_N, !value);
874f6d57916SPaul Mackerras case 2:
875f6d57916SPaul Mackerras return simple_feature_tweak(node, macio_unknown,
876f6d57916SPaul Mackerras KEYLARGO_FCR1, KL1_UIDE_RESET_N, !value);
877f6d57916SPaul Mackerras default:
878f6d57916SPaul Mackerras return -ENODEV;
879f6d57916SPaul Mackerras }
880f6d57916SPaul Mackerras }
881f6d57916SPaul Mackerras
882f6d57916SPaul Mackerras static long
core99_gmac_enable(struct device_node * node,long param,long value)883f6d57916SPaul Mackerras core99_gmac_enable(struct device_node *node, long param, long value)
884f6d57916SPaul Mackerras {
885f6d57916SPaul Mackerras unsigned long flags;
886f6d57916SPaul Mackerras
887f6d57916SPaul Mackerras LOCK(flags);
888f6d57916SPaul Mackerras if (value)
889f6d57916SPaul Mackerras UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
890f6d57916SPaul Mackerras else
891f6d57916SPaul Mackerras UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
892f6d57916SPaul Mackerras (void)UN_IN(UNI_N_CLOCK_CNTL);
893f6d57916SPaul Mackerras UNLOCK(flags);
894f6d57916SPaul Mackerras udelay(20);
895f6d57916SPaul Mackerras
896f6d57916SPaul Mackerras return 0;
897f6d57916SPaul Mackerras }
898f6d57916SPaul Mackerras
899f6d57916SPaul Mackerras static long
core99_gmac_phy_reset(struct device_node * node,long param,long value)900f6d57916SPaul Mackerras core99_gmac_phy_reset(struct device_node *node, long param, long value)
901f6d57916SPaul Mackerras {
902f6d57916SPaul Mackerras unsigned long flags;
903f6d57916SPaul Mackerras struct macio_chip *macio;
904f6d57916SPaul Mackerras
905f6d57916SPaul Mackerras macio = &macio_chips[0];
906f6d57916SPaul Mackerras if (macio->type != macio_keylargo && macio->type != macio_pangea &&
907f6d57916SPaul Mackerras macio->type != macio_intrepid)
908f6d57916SPaul Mackerras return -ENODEV;
909f6d57916SPaul Mackerras
910f6d57916SPaul Mackerras LOCK(flags);
911f6d57916SPaul Mackerras MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE);
912f6d57916SPaul Mackerras (void)MACIO_IN8(KL_GPIO_ETH_PHY_RESET);
913f6d57916SPaul Mackerras UNLOCK(flags);
914f6d57916SPaul Mackerras mdelay(10);
915f6d57916SPaul Mackerras LOCK(flags);
916f6d57916SPaul Mackerras MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, /*KEYLARGO_GPIO_OUTPUT_ENABLE | */
917f6d57916SPaul Mackerras KEYLARGO_GPIO_OUTOUT_DATA);
918f6d57916SPaul Mackerras UNLOCK(flags);
919f6d57916SPaul Mackerras mdelay(10);
920f6d57916SPaul Mackerras
921f6d57916SPaul Mackerras return 0;
922f6d57916SPaul Mackerras }
923f6d57916SPaul Mackerras
924f6d57916SPaul Mackerras static long
core99_sound_chip_enable(struct device_node * node,long param,long value)925f6d57916SPaul Mackerras core99_sound_chip_enable(struct device_node *node, long param, long value)
926f6d57916SPaul Mackerras {
927f6d57916SPaul Mackerras struct macio_chip* macio;
928f6d57916SPaul Mackerras unsigned long flags;
929f6d57916SPaul Mackerras
930f6d57916SPaul Mackerras macio = macio_find(node, 0);
931f6d57916SPaul Mackerras if (!macio)
932f6d57916SPaul Mackerras return -ENODEV;
933f6d57916SPaul Mackerras
934f6d57916SPaul Mackerras /* Do a better probe code, screamer G4 desktops &
935f6d57916SPaul Mackerras * iMacs can do that too, add a recalibrate in
936f6d57916SPaul Mackerras * the driver as well
937f6d57916SPaul Mackerras */
938f6d57916SPaul Mackerras if (pmac_mb.model_id == PMAC_TYPE_PISMO ||
939f6d57916SPaul Mackerras pmac_mb.model_id == PMAC_TYPE_TITANIUM) {
940f6d57916SPaul Mackerras LOCK(flags);
941f6d57916SPaul Mackerras if (value)
942f6d57916SPaul Mackerras MACIO_OUT8(KL_GPIO_SOUND_POWER,
943f6d57916SPaul Mackerras KEYLARGO_GPIO_OUTPUT_ENABLE |
944f6d57916SPaul Mackerras KEYLARGO_GPIO_OUTOUT_DATA);
945f6d57916SPaul Mackerras else
946f6d57916SPaul Mackerras MACIO_OUT8(KL_GPIO_SOUND_POWER,
947f6d57916SPaul Mackerras KEYLARGO_GPIO_OUTPUT_ENABLE);
948f6d57916SPaul Mackerras (void)MACIO_IN8(KL_GPIO_SOUND_POWER);
949f6d57916SPaul Mackerras UNLOCK(flags);
950f6d57916SPaul Mackerras }
951f6d57916SPaul Mackerras return 0;
952f6d57916SPaul Mackerras }
953f6d57916SPaul Mackerras
954f6d57916SPaul Mackerras static long
core99_airport_enable(struct device_node * node,long param,long value)955f6d57916SPaul Mackerras core99_airport_enable(struct device_node *node, long param, long value)
956f6d57916SPaul Mackerras {
957f6d57916SPaul Mackerras struct macio_chip* macio;
958f6d57916SPaul Mackerras unsigned long flags;
959f6d57916SPaul Mackerras int state;
960f6d57916SPaul Mackerras
961f6d57916SPaul Mackerras macio = macio_find(node, 0);
962f6d57916SPaul Mackerras if (!macio)
963f6d57916SPaul Mackerras return -ENODEV;
964f6d57916SPaul Mackerras
965f6d57916SPaul Mackerras /* Hint: we allow passing of macio itself for the sake of the
966f6d57916SPaul Mackerras * sleep code
967f6d57916SPaul Mackerras */
968f6d57916SPaul Mackerras if (node != macio->of_node &&
969f6d57916SPaul Mackerras (!node->parent || node->parent != macio->of_node))
970f6d57916SPaul Mackerras return -ENODEV;
971f6d57916SPaul Mackerras state = (macio->flags & MACIO_FLAG_AIRPORT_ON) != 0;
972f6d57916SPaul Mackerras if (value == state)
973f6d57916SPaul Mackerras return 0;
974f6d57916SPaul Mackerras if (value) {
975f6d57916SPaul Mackerras /* This code is a reproduction of OF enable-cardslot
976f6d57916SPaul Mackerras * and init-wireless methods, slightly hacked until
977f6d57916SPaul Mackerras * I got it working.
978f6d57916SPaul Mackerras */
979f6d57916SPaul Mackerras LOCK(flags);
980f6d57916SPaul Mackerras MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 5);
981f6d57916SPaul Mackerras (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf);
982f6d57916SPaul Mackerras UNLOCK(flags);
983f6d57916SPaul Mackerras mdelay(10);
984f6d57916SPaul Mackerras LOCK(flags);
985f6d57916SPaul Mackerras MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 4);
986f6d57916SPaul Mackerras (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf);
987f6d57916SPaul Mackerras UNLOCK(flags);
988f6d57916SPaul Mackerras
989f6d57916SPaul Mackerras mdelay(10);
990f6d57916SPaul Mackerras
991f6d57916SPaul Mackerras LOCK(flags);
992f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16);
993f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR2);
994f6d57916SPaul Mackerras udelay(10);
995f6d57916SPaul Mackerras MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xb, 0);
996f6d57916SPaul Mackerras (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xb);
997f6d57916SPaul Mackerras udelay(10);
998f6d57916SPaul Mackerras MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xa, 0x28);
999f6d57916SPaul Mackerras (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xa);
1000f6d57916SPaul Mackerras udelay(10);
1001f6d57916SPaul Mackerras MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xd, 0x28);
1002f6d57916SPaul Mackerras (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xd);
1003f6d57916SPaul Mackerras udelay(10);
1004f6d57916SPaul Mackerras MACIO_OUT8(KEYLARGO_GPIO_0+0xd, 0x28);
1005f6d57916SPaul Mackerras (void)MACIO_IN8(KEYLARGO_GPIO_0+0xd);
1006f6d57916SPaul Mackerras udelay(10);
1007f6d57916SPaul Mackerras MACIO_OUT8(KEYLARGO_GPIO_0+0xe, 0x28);
1008f6d57916SPaul Mackerras (void)MACIO_IN8(KEYLARGO_GPIO_0+0xe);
1009f6d57916SPaul Mackerras UNLOCK(flags);
1010f6d57916SPaul Mackerras udelay(10);
1011f6d57916SPaul Mackerras MACIO_OUT32(0x1c000, 0);
1012f6d57916SPaul Mackerras mdelay(1);
1013f6d57916SPaul Mackerras MACIO_OUT8(0x1a3e0, 0x41);
1014f6d57916SPaul Mackerras (void)MACIO_IN8(0x1a3e0);
1015f6d57916SPaul Mackerras udelay(10);
1016f6d57916SPaul Mackerras LOCK(flags);
1017f6d57916SPaul Mackerras MACIO_BIS(KEYLARGO_FCR2, KL2_CARDSEL_16);
1018f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR2);
1019f6d57916SPaul Mackerras UNLOCK(flags);
1020f6d57916SPaul Mackerras mdelay(100);
1021f6d57916SPaul Mackerras
1022f6d57916SPaul Mackerras macio->flags |= MACIO_FLAG_AIRPORT_ON;
1023f6d57916SPaul Mackerras } else {
1024f6d57916SPaul Mackerras LOCK(flags);
1025f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16);
1026f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR2);
1027f6d57916SPaul Mackerras MACIO_OUT8(KL_GPIO_AIRPORT_0, 0);
1028f6d57916SPaul Mackerras MACIO_OUT8(KL_GPIO_AIRPORT_1, 0);
1029f6d57916SPaul Mackerras MACIO_OUT8(KL_GPIO_AIRPORT_2, 0);
1030f6d57916SPaul Mackerras MACIO_OUT8(KL_GPIO_AIRPORT_3, 0);
1031f6d57916SPaul Mackerras MACIO_OUT8(KL_GPIO_AIRPORT_4, 0);
1032f6d57916SPaul Mackerras (void)MACIO_IN8(KL_GPIO_AIRPORT_4);
1033f6d57916SPaul Mackerras UNLOCK(flags);
1034f6d57916SPaul Mackerras
1035f6d57916SPaul Mackerras macio->flags &= ~MACIO_FLAG_AIRPORT_ON;
1036f6d57916SPaul Mackerras }
1037f6d57916SPaul Mackerras return 0;
1038f6d57916SPaul Mackerras }
1039f6d57916SPaul Mackerras
1040f6d57916SPaul Mackerras #ifdef CONFIG_SMP
1041f6d57916SPaul Mackerras static long
core99_reset_cpu(struct device_node * node,long param,long value)1042f6d57916SPaul Mackerras core99_reset_cpu(struct device_node *node, long param, long value)
1043f6d57916SPaul Mackerras {
1044f6d57916SPaul Mackerras unsigned int reset_io = 0;
1045f6d57916SPaul Mackerras unsigned long flags;
1046f6d57916SPaul Mackerras struct macio_chip *macio;
1047f6d57916SPaul Mackerras struct device_node *np;
1048f6d57916SPaul Mackerras const int dflt_reset_lines[] = { KL_GPIO_RESET_CPU0,
1049f6d57916SPaul Mackerras KL_GPIO_RESET_CPU1,
1050f6d57916SPaul Mackerras KL_GPIO_RESET_CPU2,
1051f6d57916SPaul Mackerras KL_GPIO_RESET_CPU3 };
1052f6d57916SPaul Mackerras
1053f6d57916SPaul Mackerras macio = &macio_chips[0];
1054f6d57916SPaul Mackerras if (macio->type != macio_keylargo)
1055f6d57916SPaul Mackerras return -ENODEV;
1056f6d57916SPaul Mackerras
1057a94fe366SRob Herring for_each_of_cpu_node(np) {
1058e2eb6392SStephen Rothwell const u32 *rst = of_get_property(np, "soft-reset", NULL);
1059bc1cf750SRob Herring if (!rst)
1060f6d57916SPaul Mackerras continue;
1061bc1cf750SRob Herring if (param == of_get_cpu_hwid(np, 0)) {
1062bc1cf750SRob Herring of_node_put(np);
1063f6d57916SPaul Mackerras reset_io = *rst;
1064f6d57916SPaul Mackerras break;
1065f6d57916SPaul Mackerras }
1066f6d57916SPaul Mackerras }
1067f6d57916SPaul Mackerras if (np == NULL || reset_io == 0)
1068f6d57916SPaul Mackerras reset_io = dflt_reset_lines[param];
1069f6d57916SPaul Mackerras
1070f6d57916SPaul Mackerras LOCK(flags);
1071f6d57916SPaul Mackerras MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);
1072f6d57916SPaul Mackerras (void)MACIO_IN8(reset_io);
1073f6d57916SPaul Mackerras udelay(1);
1074f6d57916SPaul Mackerras MACIO_OUT8(reset_io, 0);
1075f6d57916SPaul Mackerras (void)MACIO_IN8(reset_io);
1076f6d57916SPaul Mackerras UNLOCK(flags);
1077f6d57916SPaul Mackerras
1078f6d57916SPaul Mackerras return 0;
1079f6d57916SPaul Mackerras }
1080f6d57916SPaul Mackerras #endif /* CONFIG_SMP */
1081f6d57916SPaul Mackerras
1082f6d57916SPaul Mackerras static long
core99_usb_enable(struct device_node * node,long param,long value)1083f6d57916SPaul Mackerras core99_usb_enable(struct device_node *node, long param, long value)
1084f6d57916SPaul Mackerras {
1085f6d57916SPaul Mackerras struct macio_chip *macio;
1086f6d57916SPaul Mackerras unsigned long flags;
1087018a3d1dSJeremy Kerr const char *prop;
1088f6d57916SPaul Mackerras int number;
1089f6d57916SPaul Mackerras u32 reg;
1090f6d57916SPaul Mackerras
1091f6d57916SPaul Mackerras macio = &macio_chips[0];
1092f6d57916SPaul Mackerras if (macio->type != macio_keylargo && macio->type != macio_pangea &&
1093f6d57916SPaul Mackerras macio->type != macio_intrepid)
1094f6d57916SPaul Mackerras return -ENODEV;
1095f6d57916SPaul Mackerras
1096e2eb6392SStephen Rothwell prop = of_get_property(node, "AAPL,clock-id", NULL);
1097f6d57916SPaul Mackerras if (!prop)
1098f6d57916SPaul Mackerras return -ENODEV;
1099f6d57916SPaul Mackerras if (strncmp(prop, "usb0u048", 8) == 0)
1100f6d57916SPaul Mackerras number = 0;
1101f6d57916SPaul Mackerras else if (strncmp(prop, "usb1u148", 8) == 0)
1102f6d57916SPaul Mackerras number = 2;
1103f6d57916SPaul Mackerras else if (strncmp(prop, "usb2u248", 8) == 0)
1104f6d57916SPaul Mackerras number = 4;
1105f6d57916SPaul Mackerras else
1106f6d57916SPaul Mackerras return -ENODEV;
1107f6d57916SPaul Mackerras
1108f6d57916SPaul Mackerras /* Sorry for the brute-force locking, but this is only used during
1109f6d57916SPaul Mackerras * sleep and the timing seem to be critical
1110f6d57916SPaul Mackerras */
1111f6d57916SPaul Mackerras LOCK(flags);
1112f6d57916SPaul Mackerras if (value) {
1113f6d57916SPaul Mackerras /* Turn ON */
1114f6d57916SPaul Mackerras if (number == 0) {
1115f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
1116f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR0);
1117f6d57916SPaul Mackerras UNLOCK(flags);
1118f6d57916SPaul Mackerras mdelay(1);
1119f6d57916SPaul Mackerras LOCK(flags);
1120f6d57916SPaul Mackerras MACIO_BIS(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
1121f6d57916SPaul Mackerras } else if (number == 2) {
1122f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
1123f6d57916SPaul Mackerras UNLOCK(flags);
1124f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR0);
1125f6d57916SPaul Mackerras mdelay(1);
1126f6d57916SPaul Mackerras LOCK(flags);
1127f6d57916SPaul Mackerras MACIO_BIS(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
1128f6d57916SPaul Mackerras } else if (number == 4) {
1129f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1));
1130f6d57916SPaul Mackerras UNLOCK(flags);
1131f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR1);
1132f6d57916SPaul Mackerras mdelay(1);
1133f6d57916SPaul Mackerras LOCK(flags);
1134f6d57916SPaul Mackerras MACIO_BIS(KEYLARGO_FCR1, KL1_USB2_CELL_ENABLE);
1135f6d57916SPaul Mackerras }
1136f6d57916SPaul Mackerras if (number < 4) {
1137f6d57916SPaul Mackerras reg = MACIO_IN32(KEYLARGO_FCR4);
1138f6d57916SPaul Mackerras reg &= ~(KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) |
1139f6d57916SPaul Mackerras KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number));
1140f6d57916SPaul Mackerras reg &= ~(KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) |
1141f6d57916SPaul Mackerras KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1));
1142f6d57916SPaul Mackerras MACIO_OUT32(KEYLARGO_FCR4, reg);
1143f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR4);
1144f6d57916SPaul Mackerras udelay(10);
1145f6d57916SPaul Mackerras } else {
1146f6d57916SPaul Mackerras reg = MACIO_IN32(KEYLARGO_FCR3);
1147f6d57916SPaul Mackerras reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) |
1148f6d57916SPaul Mackerras KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0));
1149f6d57916SPaul Mackerras reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) |
1150f6d57916SPaul Mackerras KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1));
1151f6d57916SPaul Mackerras MACIO_OUT32(KEYLARGO_FCR3, reg);
1152f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR3);
1153f6d57916SPaul Mackerras udelay(10);
1154f6d57916SPaul Mackerras }
1155f6d57916SPaul Mackerras if (macio->type == macio_intrepid) {
1156f6d57916SPaul Mackerras /* wait for clock stopped bits to clear */
1157f6d57916SPaul Mackerras u32 test0 = 0, test1 = 0;
1158f6d57916SPaul Mackerras u32 status0, status1;
1159f6d57916SPaul Mackerras int timeout = 1000;
1160f6d57916SPaul Mackerras
1161f6d57916SPaul Mackerras UNLOCK(flags);
1162f6d57916SPaul Mackerras switch (number) {
1163f6d57916SPaul Mackerras case 0:
1164f6d57916SPaul Mackerras test0 = UNI_N_CLOCK_STOPPED_USB0;
1165f6d57916SPaul Mackerras test1 = UNI_N_CLOCK_STOPPED_USB0PCI;
1166f6d57916SPaul Mackerras break;
1167f6d57916SPaul Mackerras case 2:
1168f6d57916SPaul Mackerras test0 = UNI_N_CLOCK_STOPPED_USB1;
1169f6d57916SPaul Mackerras test1 = UNI_N_CLOCK_STOPPED_USB1PCI;
1170f6d57916SPaul Mackerras break;
1171f6d57916SPaul Mackerras case 4:
1172f6d57916SPaul Mackerras test0 = UNI_N_CLOCK_STOPPED_USB2;
1173f6d57916SPaul Mackerras test1 = UNI_N_CLOCK_STOPPED_USB2PCI;
1174f6d57916SPaul Mackerras break;
1175f6d57916SPaul Mackerras }
1176f6d57916SPaul Mackerras do {
1177f6d57916SPaul Mackerras if (--timeout <= 0) {
1178f6d57916SPaul Mackerras printk(KERN_ERR "core99_usb_enable: "
1179f6d57916SPaul Mackerras "Timeout waiting for clocks\n");
1180f6d57916SPaul Mackerras break;
1181f6d57916SPaul Mackerras }
1182f6d57916SPaul Mackerras mdelay(1);
1183f6d57916SPaul Mackerras status0 = UN_IN(UNI_N_CLOCK_STOP_STATUS0);
1184f6d57916SPaul Mackerras status1 = UN_IN(UNI_N_CLOCK_STOP_STATUS1);
1185f6d57916SPaul Mackerras } while ((status0 & test0) | (status1 & test1));
1186f6d57916SPaul Mackerras LOCK(flags);
1187f6d57916SPaul Mackerras }
1188f6d57916SPaul Mackerras } else {
1189f6d57916SPaul Mackerras /* Turn OFF */
1190f6d57916SPaul Mackerras if (number < 4) {
1191f6d57916SPaul Mackerras reg = MACIO_IN32(KEYLARGO_FCR4);
1192f6d57916SPaul Mackerras reg |= KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) |
1193f6d57916SPaul Mackerras KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number);
1194f6d57916SPaul Mackerras reg |= KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) |
1195f6d57916SPaul Mackerras KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1);
1196f6d57916SPaul Mackerras MACIO_OUT32(KEYLARGO_FCR4, reg);
1197f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR4);
1198f6d57916SPaul Mackerras udelay(1);
1199f6d57916SPaul Mackerras } else {
1200f6d57916SPaul Mackerras reg = MACIO_IN32(KEYLARGO_FCR3);
1201f6d57916SPaul Mackerras reg |= KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) |
1202f6d57916SPaul Mackerras KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0);
1203f6d57916SPaul Mackerras reg |= KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) |
1204f6d57916SPaul Mackerras KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1);
1205f6d57916SPaul Mackerras MACIO_OUT32(KEYLARGO_FCR3, reg);
1206f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR3);
1207f6d57916SPaul Mackerras udelay(1);
1208f6d57916SPaul Mackerras }
1209f6d57916SPaul Mackerras if (number == 0) {
1210f6d57916SPaul Mackerras if (macio->type != macio_intrepid)
1211f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
1212f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR0);
1213f6d57916SPaul Mackerras udelay(1);
1214f6d57916SPaul Mackerras MACIO_BIS(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
1215f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR0);
1216f6d57916SPaul Mackerras } else if (number == 2) {
1217f6d57916SPaul Mackerras if (macio->type != macio_intrepid)
1218f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
1219f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR0);
1220f6d57916SPaul Mackerras udelay(1);
1221f6d57916SPaul Mackerras MACIO_BIS(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
1222f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR0);
1223f6d57916SPaul Mackerras } else if (number == 4) {
1224f6d57916SPaul Mackerras udelay(1);
1225f6d57916SPaul Mackerras MACIO_BIS(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1));
1226f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR1);
1227f6d57916SPaul Mackerras }
1228f6d57916SPaul Mackerras udelay(1);
1229f6d57916SPaul Mackerras }
1230f6d57916SPaul Mackerras UNLOCK(flags);
1231f6d57916SPaul Mackerras
1232f6d57916SPaul Mackerras return 0;
1233f6d57916SPaul Mackerras }
1234f6d57916SPaul Mackerras
1235f6d57916SPaul Mackerras static long
core99_firewire_enable(struct device_node * node,long param,long value)1236f6d57916SPaul Mackerras core99_firewire_enable(struct device_node *node, long param, long value)
1237f6d57916SPaul Mackerras {
1238f6d57916SPaul Mackerras unsigned long flags;
1239f6d57916SPaul Mackerras struct macio_chip *macio;
1240f6d57916SPaul Mackerras
1241f6d57916SPaul Mackerras macio = &macio_chips[0];
1242f6d57916SPaul Mackerras if (macio->type != macio_keylargo && macio->type != macio_pangea &&
1243f6d57916SPaul Mackerras macio->type != macio_intrepid)
1244f6d57916SPaul Mackerras return -ENODEV;
1245f6d57916SPaul Mackerras if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED))
1246f6d57916SPaul Mackerras return -ENODEV;
1247f6d57916SPaul Mackerras
1248f6d57916SPaul Mackerras LOCK(flags);
1249f6d57916SPaul Mackerras if (value) {
1250f6d57916SPaul Mackerras UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
1251f6d57916SPaul Mackerras (void)UN_IN(UNI_N_CLOCK_CNTL);
1252f6d57916SPaul Mackerras } else {
1253f6d57916SPaul Mackerras UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
1254f6d57916SPaul Mackerras (void)UN_IN(UNI_N_CLOCK_CNTL);
1255f6d57916SPaul Mackerras }
1256f6d57916SPaul Mackerras UNLOCK(flags);
1257f6d57916SPaul Mackerras mdelay(1);
1258f6d57916SPaul Mackerras
1259f6d57916SPaul Mackerras return 0;
1260f6d57916SPaul Mackerras }
1261f6d57916SPaul Mackerras
1262f6d57916SPaul Mackerras static long
core99_firewire_cable_power(struct device_node * node,long param,long value)1263f6d57916SPaul Mackerras core99_firewire_cable_power(struct device_node *node, long param, long value)
1264f6d57916SPaul Mackerras {
1265f6d57916SPaul Mackerras unsigned long flags;
1266f6d57916SPaul Mackerras struct macio_chip *macio;
1267f6d57916SPaul Mackerras
1268f6d57916SPaul Mackerras /* Trick: we allow NULL node */
1269f6d57916SPaul Mackerras if ((pmac_mb.board_flags & PMAC_MB_HAS_FW_POWER) == 0)
1270f6d57916SPaul Mackerras return -ENODEV;
1271f6d57916SPaul Mackerras macio = &macio_chips[0];
1272f6d57916SPaul Mackerras if (macio->type != macio_keylargo && macio->type != macio_pangea &&
1273f6d57916SPaul Mackerras macio->type != macio_intrepid)
1274f6d57916SPaul Mackerras return -ENODEV;
1275f6d57916SPaul Mackerras if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED))
1276f6d57916SPaul Mackerras return -ENODEV;
1277f6d57916SPaul Mackerras
1278f6d57916SPaul Mackerras LOCK(flags);
1279f6d57916SPaul Mackerras if (value) {
1280f6d57916SPaul Mackerras MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 0);
1281f6d57916SPaul Mackerras MACIO_IN8(KL_GPIO_FW_CABLE_POWER);
1282f6d57916SPaul Mackerras udelay(10);
1283f6d57916SPaul Mackerras } else {
1284f6d57916SPaul Mackerras MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 4);
1285f6d57916SPaul Mackerras MACIO_IN8(KL_GPIO_FW_CABLE_POWER); udelay(10);
1286f6d57916SPaul Mackerras }
1287f6d57916SPaul Mackerras UNLOCK(flags);
1288f6d57916SPaul Mackerras mdelay(1);
1289f6d57916SPaul Mackerras
1290f6d57916SPaul Mackerras return 0;
1291f6d57916SPaul Mackerras }
1292f6d57916SPaul Mackerras
1293f6d57916SPaul Mackerras static long
intrepid_aack_delay_enable(struct device_node * node,long param,long value)1294f6d57916SPaul Mackerras intrepid_aack_delay_enable(struct device_node *node, long param, long value)
1295f6d57916SPaul Mackerras {
1296f6d57916SPaul Mackerras unsigned long flags;
1297f6d57916SPaul Mackerras
1298f6d57916SPaul Mackerras if (uninorth_rev < 0xd2)
1299f6d57916SPaul Mackerras return -ENODEV;
1300f6d57916SPaul Mackerras
1301f6d57916SPaul Mackerras LOCK(flags);
1302f6d57916SPaul Mackerras if (param)
1303f6d57916SPaul Mackerras UN_BIS(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE);
1304f6d57916SPaul Mackerras else
1305f6d57916SPaul Mackerras UN_BIC(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE);
1306f6d57916SPaul Mackerras UNLOCK(flags);
1307f6d57916SPaul Mackerras
1308f6d57916SPaul Mackerras return 0;
1309f6d57916SPaul Mackerras }
1310f6d57916SPaul Mackerras
1311f6d57916SPaul Mackerras
1312804ece07SMichael Ellerman #endif /* CONFIG_PPC64 */
1313f6d57916SPaul Mackerras
1314f6d57916SPaul Mackerras static long
core99_read_gpio(struct device_node * node,long param,long value)1315f6d57916SPaul Mackerras core99_read_gpio(struct device_node *node, long param, long value)
1316f6d57916SPaul Mackerras {
1317f6d57916SPaul Mackerras struct macio_chip *macio = &macio_chips[0];
1318f6d57916SPaul Mackerras
1319f6d57916SPaul Mackerras return MACIO_IN8(param);
1320f6d57916SPaul Mackerras }
1321f6d57916SPaul Mackerras
1322f6d57916SPaul Mackerras
1323f6d57916SPaul Mackerras static long
core99_write_gpio(struct device_node * node,long param,long value)1324f6d57916SPaul Mackerras core99_write_gpio(struct device_node *node, long param, long value)
1325f6d57916SPaul Mackerras {
1326f6d57916SPaul Mackerras struct macio_chip *macio = &macio_chips[0];
1327f6d57916SPaul Mackerras
1328f6d57916SPaul Mackerras MACIO_OUT8(param, (u8)(value & 0xff));
1329f6d57916SPaul Mackerras return 0;
1330f6d57916SPaul Mackerras }
1331f6d57916SPaul Mackerras
1332804ece07SMichael Ellerman #ifdef CONFIG_PPC64
g5_gmac_enable(struct device_node * node,long param,long value)1333f6d57916SPaul Mackerras static long g5_gmac_enable(struct device_node *node, long param, long value)
1334f6d57916SPaul Mackerras {
1335f6d57916SPaul Mackerras struct macio_chip *macio = &macio_chips[0];
1336f6d57916SPaul Mackerras unsigned long flags;
1337f6d57916SPaul Mackerras
1338f6d57916SPaul Mackerras if (node == NULL)
1339f6d57916SPaul Mackerras return -ENODEV;
1340f6d57916SPaul Mackerras
1341f6d57916SPaul Mackerras LOCK(flags);
1342f6d57916SPaul Mackerras if (value) {
1343f6d57916SPaul Mackerras MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE);
1344f6d57916SPaul Mackerras mb();
1345f6d57916SPaul Mackerras k2_skiplist[0] = NULL;
1346f6d57916SPaul Mackerras } else {
1347f6d57916SPaul Mackerras k2_skiplist[0] = node;
1348f6d57916SPaul Mackerras mb();
1349f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE);
1350f6d57916SPaul Mackerras }
1351f6d57916SPaul Mackerras
1352f6d57916SPaul Mackerras UNLOCK(flags);
1353f6d57916SPaul Mackerras mdelay(1);
1354f6d57916SPaul Mackerras
1355f6d57916SPaul Mackerras return 0;
1356f6d57916SPaul Mackerras }
1357f6d57916SPaul Mackerras
g5_fw_enable(struct device_node * node,long param,long value)1358f6d57916SPaul Mackerras static long g5_fw_enable(struct device_node *node, long param, long value)
1359f6d57916SPaul Mackerras {
1360f6d57916SPaul Mackerras struct macio_chip *macio = &macio_chips[0];
1361f6d57916SPaul Mackerras unsigned long flags;
1362f6d57916SPaul Mackerras
1363f6d57916SPaul Mackerras if (node == NULL)
1364f6d57916SPaul Mackerras return -ENODEV;
1365f6d57916SPaul Mackerras
1366f6d57916SPaul Mackerras LOCK(flags);
1367f6d57916SPaul Mackerras if (value) {
1368f6d57916SPaul Mackerras MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE);
1369f6d57916SPaul Mackerras mb();
1370f6d57916SPaul Mackerras k2_skiplist[1] = NULL;
1371f6d57916SPaul Mackerras } else {
1372f6d57916SPaul Mackerras k2_skiplist[1] = node;
1373f6d57916SPaul Mackerras mb();
1374f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE);
1375f6d57916SPaul Mackerras }
1376f6d57916SPaul Mackerras
1377f6d57916SPaul Mackerras UNLOCK(flags);
1378f6d57916SPaul Mackerras mdelay(1);
1379f6d57916SPaul Mackerras
1380f6d57916SPaul Mackerras return 0;
1381f6d57916SPaul Mackerras }
1382f6d57916SPaul Mackerras
g5_mpic_enable(struct device_node * node,long param,long value)1383f6d57916SPaul Mackerras static long g5_mpic_enable(struct device_node *node, long param, long value)
1384f6d57916SPaul Mackerras {
1385f6d57916SPaul Mackerras unsigned long flags;
13861beb6a7dSBenjamin Herrenschmidt struct device_node *parent = of_get_parent(node);
13871beb6a7dSBenjamin Herrenschmidt int is_u3;
1388f6d57916SPaul Mackerras
13891beb6a7dSBenjamin Herrenschmidt if (parent == NULL)
13901beb6a7dSBenjamin Herrenschmidt return 0;
13912c8e65b5SRob Herring is_u3 = of_node_name_eq(parent, "u3") || of_node_name_eq(parent, "u4");
13921beb6a7dSBenjamin Herrenschmidt of_node_put(parent);
13931beb6a7dSBenjamin Herrenschmidt if (!is_u3)
1394f6d57916SPaul Mackerras return 0;
1395f6d57916SPaul Mackerras
1396f6d57916SPaul Mackerras LOCK(flags);
1397f6d57916SPaul Mackerras UN_BIS(U3_TOGGLE_REG, U3_MPIC_RESET | U3_MPIC_OUTPUT_ENABLE);
1398f6d57916SPaul Mackerras UNLOCK(flags);
1399f6d57916SPaul Mackerras
1400f6d57916SPaul Mackerras return 0;
1401f6d57916SPaul Mackerras }
1402f6d57916SPaul Mackerras
g5_eth_phy_reset(struct device_node * node,long param,long value)1403f6d57916SPaul Mackerras static long g5_eth_phy_reset(struct device_node *node, long param, long value)
1404f6d57916SPaul Mackerras {
1405f6d57916SPaul Mackerras struct macio_chip *macio = &macio_chips[0];
1406f6d57916SPaul Mackerras struct device_node *phy;
1407f6d57916SPaul Mackerras int need_reset;
1408f6d57916SPaul Mackerras
1409f6d57916SPaul Mackerras /*
1410f6d57916SPaul Mackerras * We must not reset the combo PHYs, only the BCM5221 found in
1411f6d57916SPaul Mackerras * the iMac G5.
1412f6d57916SPaul Mackerras */
1413f6d57916SPaul Mackerras phy = of_get_next_child(node, NULL);
1414f6d57916SPaul Mackerras if (!phy)
1415f6d57916SPaul Mackerras return -ENODEV;
141655b61fecSStephen Rothwell need_reset = of_device_is_compatible(phy, "B5221");
1417f6d57916SPaul Mackerras of_node_put(phy);
1418f6d57916SPaul Mackerras if (!need_reset)
1419f6d57916SPaul Mackerras return 0;
1420f6d57916SPaul Mackerras
1421f6d57916SPaul Mackerras /* PHY reset is GPIO 29, not in device-tree unfortunately */
1422f6d57916SPaul Mackerras MACIO_OUT8(K2_GPIO_EXTINT_0 + 29,
1423f6d57916SPaul Mackerras KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
1424f6d57916SPaul Mackerras /* Thankfully, this is now always called at a time when we can
1425f6d57916SPaul Mackerras * schedule by sungem.
1426f6d57916SPaul Mackerras */
1427f6d57916SPaul Mackerras msleep(10);
1428f6d57916SPaul Mackerras MACIO_OUT8(K2_GPIO_EXTINT_0 + 29, 0);
1429f6d57916SPaul Mackerras
1430f6d57916SPaul Mackerras return 0;
1431f6d57916SPaul Mackerras }
1432f6d57916SPaul Mackerras
g5_i2s_enable(struct device_node * node,long param,long value)1433f6d57916SPaul Mackerras static long g5_i2s_enable(struct device_node *node, long param, long value)
1434f6d57916SPaul Mackerras {
1435f6d57916SPaul Mackerras /* Very crude implementation for now */
1436f6d57916SPaul Mackerras struct macio_chip *macio = &macio_chips[0];
1437f6d57916SPaul Mackerras unsigned long flags;
1438cc5d0189SBenjamin Herrenschmidt int cell;
1439cc5d0189SBenjamin Herrenschmidt u32 fcrs[3][3] = {
1440cc5d0189SBenjamin Herrenschmidt { 0,
1441cc5d0189SBenjamin Herrenschmidt K2_FCR1_I2S0_CELL_ENABLE |
1442cc5d0189SBenjamin Herrenschmidt K2_FCR1_I2S0_CLK_ENABLE_BIT | K2_FCR1_I2S0_ENABLE,
1443cc5d0189SBenjamin Herrenschmidt KL3_I2S0_CLK18_ENABLE
1444cc5d0189SBenjamin Herrenschmidt },
1445cc5d0189SBenjamin Herrenschmidt { KL0_SCC_A_INTF_ENABLE,
1446cc5d0189SBenjamin Herrenschmidt K2_FCR1_I2S1_CELL_ENABLE |
1447cc5d0189SBenjamin Herrenschmidt K2_FCR1_I2S1_CLK_ENABLE_BIT | K2_FCR1_I2S1_ENABLE,
1448cc5d0189SBenjamin Herrenschmidt KL3_I2S1_CLK18_ENABLE
1449cc5d0189SBenjamin Herrenschmidt },
1450cc5d0189SBenjamin Herrenschmidt { KL0_SCC_B_INTF_ENABLE,
1451cc5d0189SBenjamin Herrenschmidt SH_FCR1_I2S2_CELL_ENABLE |
1452cc5d0189SBenjamin Herrenschmidt SH_FCR1_I2S2_CLK_ENABLE_BIT | SH_FCR1_I2S2_ENABLE,
1453cc5d0189SBenjamin Herrenschmidt SH_FCR3_I2S2_CLK18_ENABLE
1454cc5d0189SBenjamin Herrenschmidt },
1455cc5d0189SBenjamin Herrenschmidt };
1456f6d57916SPaul Mackerras
14571beb6a7dSBenjamin Herrenschmidt if (macio->type != macio_keylargo2 && macio->type != macio_shasta)
1458cc5d0189SBenjamin Herrenschmidt return -ENODEV;
1459cc5d0189SBenjamin Herrenschmidt if (strncmp(node->name, "i2s-", 4))
1460cc5d0189SBenjamin Herrenschmidt return -ENODEV;
1461cc5d0189SBenjamin Herrenschmidt cell = node->name[4] - 'a';
1462cc5d0189SBenjamin Herrenschmidt switch(cell) {
1463cc5d0189SBenjamin Herrenschmidt case 0:
1464cc5d0189SBenjamin Herrenschmidt case 1:
1465cc5d0189SBenjamin Herrenschmidt break;
1466cc5d0189SBenjamin Herrenschmidt case 2:
1467cc5d0189SBenjamin Herrenschmidt if (macio->type == macio_shasta)
1468cc5d0189SBenjamin Herrenschmidt break;
14695e66a0cbSGustavo A. R. Silva fallthrough;
1470cc5d0189SBenjamin Herrenschmidt default:
1471cc5d0189SBenjamin Herrenschmidt return -ENODEV;
1472cc5d0189SBenjamin Herrenschmidt }
1473f6d57916SPaul Mackerras
1474f6d57916SPaul Mackerras LOCK(flags);
1475cc5d0189SBenjamin Herrenschmidt if (value) {
1476cc5d0189SBenjamin Herrenschmidt MACIO_BIC(KEYLARGO_FCR0, fcrs[cell][0]);
1477cc5d0189SBenjamin Herrenschmidt MACIO_BIS(KEYLARGO_FCR1, fcrs[cell][1]);
1478cc5d0189SBenjamin Herrenschmidt MACIO_BIS(KEYLARGO_FCR3, fcrs[cell][2]);
1479cc5d0189SBenjamin Herrenschmidt } else {
1480cc5d0189SBenjamin Herrenschmidt MACIO_BIC(KEYLARGO_FCR3, fcrs[cell][2]);
1481cc5d0189SBenjamin Herrenschmidt MACIO_BIC(KEYLARGO_FCR1, fcrs[cell][1]);
1482cc5d0189SBenjamin Herrenschmidt MACIO_BIS(KEYLARGO_FCR0, fcrs[cell][0]);
1483cc5d0189SBenjamin Herrenschmidt }
1484f6d57916SPaul Mackerras udelay(10);
1485f6d57916SPaul Mackerras UNLOCK(flags);
1486f6d57916SPaul Mackerras
1487f6d57916SPaul Mackerras return 0;
1488f6d57916SPaul Mackerras }
1489f6d57916SPaul Mackerras
1490f6d57916SPaul Mackerras
1491f6d57916SPaul Mackerras #ifdef CONFIG_SMP
g5_reset_cpu(struct device_node * node,long param,long value)1492f6d57916SPaul Mackerras static long g5_reset_cpu(struct device_node *node, long param, long value)
1493f6d57916SPaul Mackerras {
1494f6d57916SPaul Mackerras unsigned int reset_io = 0;
1495f6d57916SPaul Mackerras unsigned long flags;
1496f6d57916SPaul Mackerras struct macio_chip *macio;
1497f6d57916SPaul Mackerras struct device_node *np;
1498f6d57916SPaul Mackerras
1499f6d57916SPaul Mackerras macio = &macio_chips[0];
15001beb6a7dSBenjamin Herrenschmidt if (macio->type != macio_keylargo2 && macio->type != macio_shasta)
1501f6d57916SPaul Mackerras return -ENODEV;
1502f6d57916SPaul Mackerras
1503a94fe366SRob Herring for_each_of_cpu_node(np) {
1504e2eb6392SStephen Rothwell const u32 *rst = of_get_property(np, "soft-reset", NULL);
1505bc1cf750SRob Herring if (!rst)
1506f6d57916SPaul Mackerras continue;
1507bc1cf750SRob Herring if (param == of_get_cpu_hwid(np, 0)) {
1508bc1cf750SRob Herring of_node_put(np);
1509f6d57916SPaul Mackerras reset_io = *rst;
1510f6d57916SPaul Mackerras break;
1511f6d57916SPaul Mackerras }
1512f6d57916SPaul Mackerras }
1513f6d57916SPaul Mackerras if (np == NULL || reset_io == 0)
1514f6d57916SPaul Mackerras return -ENODEV;
1515f6d57916SPaul Mackerras
1516f6d57916SPaul Mackerras LOCK(flags);
1517f6d57916SPaul Mackerras MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);
1518f6d57916SPaul Mackerras (void)MACIO_IN8(reset_io);
1519f6d57916SPaul Mackerras udelay(1);
1520f6d57916SPaul Mackerras MACIO_OUT8(reset_io, 0);
1521f6d57916SPaul Mackerras (void)MACIO_IN8(reset_io);
1522f6d57916SPaul Mackerras UNLOCK(flags);
1523f6d57916SPaul Mackerras
1524f6d57916SPaul Mackerras return 0;
1525f6d57916SPaul Mackerras }
1526f6d57916SPaul Mackerras #endif /* CONFIG_SMP */
1527f6d57916SPaul Mackerras
1528f6d57916SPaul Mackerras /*
1529f6d57916SPaul Mackerras * This can be called from pmac_smp so isn't static
1530f6d57916SPaul Mackerras *
1531f6d57916SPaul Mackerras * This takes the second CPU off the bus on dual CPU machines
1532f6d57916SPaul Mackerras * running UP
1533f6d57916SPaul Mackerras */
g5_phy_disable_cpu1(void)1534b346f571SNick Child void __init g5_phy_disable_cpu1(void)
1535f6d57916SPaul Mackerras {
15361beb6a7dSBenjamin Herrenschmidt if (uninorth_maj == 3)
1537f6d57916SPaul Mackerras UN_OUT(U3_API_PHY_CONFIG_1, 0);
1538f6d57916SPaul Mackerras }
1539804ece07SMichael Ellerman #endif /* CONFIG_PPC64 */
1540f6d57916SPaul Mackerras
1541804ece07SMichael Ellerman #ifndef CONFIG_PPC64
1542f6d57916SPaul Mackerras
15435b9ca526SBenjamin Herrenschmidt
15445b9ca526SBenjamin Herrenschmidt #ifdef CONFIG_PM
15450613ffbfSOlaf Hering static u32 save_gpio_levels[2];
15460613ffbfSOlaf Hering static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT];
15470613ffbfSOlaf Hering static u8 save_gpio_normal[KEYLARGO_GPIO_CNT];
15480613ffbfSOlaf Hering static u32 save_unin_clock_ctl;
15495b9ca526SBenjamin Herrenschmidt
keylargo_shutdown(struct macio_chip * macio,int sleep_mode)15505b9ca526SBenjamin Herrenschmidt static void keylargo_shutdown(struct macio_chip *macio, int sleep_mode)
1551f6d57916SPaul Mackerras {
1552f6d57916SPaul Mackerras u32 temp;
1553f6d57916SPaul Mackerras
1554f6d57916SPaul Mackerras if (sleep_mode) {
1555f6d57916SPaul Mackerras mdelay(1);
1556f6d57916SPaul Mackerras MACIO_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND);
1557f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR0);
1558f6d57916SPaul Mackerras mdelay(1);
1559f6d57916SPaul Mackerras }
1560f6d57916SPaul Mackerras
1561f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
1562f6d57916SPaul Mackerras KL0_SCC_CELL_ENABLE |
1563f6d57916SPaul Mackerras KL0_IRDA_ENABLE | KL0_IRDA_CLK32_ENABLE |
1564f6d57916SPaul Mackerras KL0_IRDA_CLK19_ENABLE);
1565f6d57916SPaul Mackerras
1566f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK);
1567f6d57916SPaul Mackerras MACIO_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_IDE_ENABLE);
1568f6d57916SPaul Mackerras
1569f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_FCR1,
1570f6d57916SPaul Mackerras KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
1571f6d57916SPaul Mackerras KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
1572f6d57916SPaul Mackerras KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
1573f6d57916SPaul Mackerras KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
1574f6d57916SPaul Mackerras KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
1575f6d57916SPaul Mackerras KL1_EIDE0_ENABLE | KL1_EIDE0_RESET_N |
1576f6d57916SPaul Mackerras KL1_EIDE1_ENABLE | KL1_EIDE1_RESET_N |
1577f6d57916SPaul Mackerras KL1_UIDE_ENABLE);
1578f6d57916SPaul Mackerras
1579f6d57916SPaul Mackerras MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
1580f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_FCR2, KL2_IOBUS_ENABLE);
1581f6d57916SPaul Mackerras
1582f6d57916SPaul Mackerras temp = MACIO_IN32(KEYLARGO_FCR3);
1583f6d57916SPaul Mackerras if (macio->rev >= 2) {
1584f6d57916SPaul Mackerras temp |= KL3_SHUTDOWN_PLL2X;
1585f6d57916SPaul Mackerras if (sleep_mode)
1586f6d57916SPaul Mackerras temp |= KL3_SHUTDOWN_PLL_TOTAL;
1587f6d57916SPaul Mackerras }
1588f6d57916SPaul Mackerras
1589f6d57916SPaul Mackerras temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
1590f6d57916SPaul Mackerras KL3_SHUTDOWN_PLLKW35;
1591f6d57916SPaul Mackerras if (sleep_mode)
1592f6d57916SPaul Mackerras temp |= KL3_SHUTDOWN_PLLKW12;
1593f6d57916SPaul Mackerras temp &= ~(KL3_CLK66_ENABLE | KL3_CLK49_ENABLE | KL3_CLK45_ENABLE
1594f6d57916SPaul Mackerras | KL3_CLK31_ENABLE | KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE);
1595f6d57916SPaul Mackerras if (sleep_mode)
1596f6d57916SPaul Mackerras temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
1597f6d57916SPaul Mackerras MACIO_OUT32(KEYLARGO_FCR3, temp);
1598f6d57916SPaul Mackerras
1599f6d57916SPaul Mackerras /* Flush posted writes & wait a bit */
1600f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
1601f6d57916SPaul Mackerras }
1602f6d57916SPaul Mackerras
pangea_shutdown(struct macio_chip * macio,int sleep_mode)16035b9ca526SBenjamin Herrenschmidt static void pangea_shutdown(struct macio_chip *macio, int sleep_mode)
1604f6d57916SPaul Mackerras {
1605f6d57916SPaul Mackerras u32 temp;
1606f6d57916SPaul Mackerras
1607f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
1608f6d57916SPaul Mackerras KL0_SCC_CELL_ENABLE |
1609f6d57916SPaul Mackerras KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE);
1610f6d57916SPaul Mackerras
1611f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_FCR1,
1612f6d57916SPaul Mackerras KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
1613f6d57916SPaul Mackerras KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
1614f6d57916SPaul Mackerras KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
1615f6d57916SPaul Mackerras KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
1616f6d57916SPaul Mackerras KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
1617f6d57916SPaul Mackerras KL1_UIDE_ENABLE);
1618f6d57916SPaul Mackerras if (pmac_mb.board_flags & PMAC_MB_MOBILE)
1619f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N);
1620f6d57916SPaul Mackerras
1621f6d57916SPaul Mackerras MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
1622f6d57916SPaul Mackerras
1623f6d57916SPaul Mackerras temp = MACIO_IN32(KEYLARGO_FCR3);
1624f6d57916SPaul Mackerras temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
1625f6d57916SPaul Mackerras KL3_SHUTDOWN_PLLKW35;
1626f6d57916SPaul Mackerras temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | KL3_CLK31_ENABLE
1627f6d57916SPaul Mackerras | KL3_I2S0_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE);
1628f6d57916SPaul Mackerras if (sleep_mode)
1629f6d57916SPaul Mackerras temp &= ~(KL3_VIA_CLK16_ENABLE | KL3_TIMER_CLK18_ENABLE);
1630f6d57916SPaul Mackerras MACIO_OUT32(KEYLARGO_FCR3, temp);
1631f6d57916SPaul Mackerras
1632f6d57916SPaul Mackerras /* Flush posted writes & wait a bit */
1633f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
1634f6d57916SPaul Mackerras }
1635f6d57916SPaul Mackerras
intrepid_shutdown(struct macio_chip * macio,int sleep_mode)16365b9ca526SBenjamin Herrenschmidt static void intrepid_shutdown(struct macio_chip *macio, int sleep_mode)
1637f6d57916SPaul Mackerras {
1638f6d57916SPaul Mackerras u32 temp;
1639f6d57916SPaul Mackerras
1640f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
1641f6d57916SPaul Mackerras KL0_SCC_CELL_ENABLE);
1642f6d57916SPaul Mackerras
1643f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_FCR1,
1644f6d57916SPaul Mackerras KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
1645f6d57916SPaul Mackerras KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
1646c8b8b1f2SBenjamin Herrenschmidt KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
1647c8b8b1f2SBenjamin Herrenschmidt KL1_EIDE0_ENABLE);
1648f6d57916SPaul Mackerras if (pmac_mb.board_flags & PMAC_MB_MOBILE)
1649f6d57916SPaul Mackerras MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N);
1650f6d57916SPaul Mackerras
1651f6d57916SPaul Mackerras temp = MACIO_IN32(KEYLARGO_FCR3);
1652f6d57916SPaul Mackerras temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE |
1653f6d57916SPaul Mackerras KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE);
1654f6d57916SPaul Mackerras if (sleep_mode)
1655f6d57916SPaul Mackerras temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_IT_VIA_CLK32_ENABLE);
1656f6d57916SPaul Mackerras MACIO_OUT32(KEYLARGO_FCR3, temp);
1657f6d57916SPaul Mackerras
1658f6d57916SPaul Mackerras /* Flush posted writes & wait a bit */
1659f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR0);
1660f6d57916SPaul Mackerras mdelay(10);
1661f6d57916SPaul Mackerras }
1662f6d57916SPaul Mackerras
1663f6d57916SPaul Mackerras
1664f6d57916SPaul Mackerras static int
core99_sleep(void)1665f6d57916SPaul Mackerras core99_sleep(void)
1666f6d57916SPaul Mackerras {
1667f6d57916SPaul Mackerras struct macio_chip *macio;
1668f6d57916SPaul Mackerras int i;
1669f6d57916SPaul Mackerras
1670f6d57916SPaul Mackerras macio = &macio_chips[0];
1671f6d57916SPaul Mackerras if (macio->type != macio_keylargo && macio->type != macio_pangea &&
1672f6d57916SPaul Mackerras macio->type != macio_intrepid)
1673f6d57916SPaul Mackerras return -ENODEV;
1674f6d57916SPaul Mackerras
1675f6d57916SPaul Mackerras /* We power off the wireless slot in case it was not done
1676f6d57916SPaul Mackerras * by the driver. We don't power it on automatically however
1677f6d57916SPaul Mackerras */
1678f6d57916SPaul Mackerras if (macio->flags & MACIO_FLAG_AIRPORT_ON)
1679f6d57916SPaul Mackerras core99_airport_enable(macio->of_node, 0, 0);
1680f6d57916SPaul Mackerras
1681f6d57916SPaul Mackerras /* We power off the FW cable. Should be done by the driver... */
1682f6d57916SPaul Mackerras if (macio->flags & MACIO_FLAG_FW_SUPPORTED) {
1683f6d57916SPaul Mackerras core99_firewire_enable(NULL, 0, 0);
1684f6d57916SPaul Mackerras core99_firewire_cable_power(NULL, 0, 0);
1685f6d57916SPaul Mackerras }
1686f6d57916SPaul Mackerras
1687f6d57916SPaul Mackerras /* We make sure int. modem is off (in case driver lost it) */
1688f6d57916SPaul Mackerras if (macio->type == macio_keylargo)
1689f6d57916SPaul Mackerras core99_modem_enable(macio->of_node, 0, 0);
1690f6d57916SPaul Mackerras else
1691f6d57916SPaul Mackerras pangea_modem_enable(macio->of_node, 0, 0);
1692f6d57916SPaul Mackerras
1693f6d57916SPaul Mackerras /* We make sure the sound is off as well */
1694f6d57916SPaul Mackerras core99_sound_chip_enable(macio->of_node, 0, 0);
1695f6d57916SPaul Mackerras
1696f6d57916SPaul Mackerras /*
1697f6d57916SPaul Mackerras * Save various bits of KeyLargo
1698f6d57916SPaul Mackerras */
1699f6d57916SPaul Mackerras
1700f6d57916SPaul Mackerras /* Save the state of the various GPIOs */
1701f6d57916SPaul Mackerras save_gpio_levels[0] = MACIO_IN32(KEYLARGO_GPIO_LEVELS0);
1702f6d57916SPaul Mackerras save_gpio_levels[1] = MACIO_IN32(KEYLARGO_GPIO_LEVELS1);
1703f6d57916SPaul Mackerras for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
1704f6d57916SPaul Mackerras save_gpio_extint[i] = MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+i);
1705f6d57916SPaul Mackerras for (i=0; i<KEYLARGO_GPIO_CNT; i++)
1706f6d57916SPaul Mackerras save_gpio_normal[i] = MACIO_IN8(KEYLARGO_GPIO_0+i);
1707f6d57916SPaul Mackerras
1708f6d57916SPaul Mackerras /* Save the FCRs */
1709f6d57916SPaul Mackerras if (macio->type == macio_keylargo)
1710f6d57916SPaul Mackerras save_mbcr = MACIO_IN32(KEYLARGO_MBCR);
1711f6d57916SPaul Mackerras save_fcr[0] = MACIO_IN32(KEYLARGO_FCR0);
1712f6d57916SPaul Mackerras save_fcr[1] = MACIO_IN32(KEYLARGO_FCR1);
1713f6d57916SPaul Mackerras save_fcr[2] = MACIO_IN32(KEYLARGO_FCR2);
1714f6d57916SPaul Mackerras save_fcr[3] = MACIO_IN32(KEYLARGO_FCR3);
1715f6d57916SPaul Mackerras save_fcr[4] = MACIO_IN32(KEYLARGO_FCR4);
1716f6d57916SPaul Mackerras if (macio->type == macio_pangea || macio->type == macio_intrepid)
1717f6d57916SPaul Mackerras save_fcr[5] = MACIO_IN32(KEYLARGO_FCR5);
1718f6d57916SPaul Mackerras
1719f6d57916SPaul Mackerras /* Save state & config of DBDMA channels */
1720f6d57916SPaul Mackerras dbdma_save(macio, save_dbdma);
1721f6d57916SPaul Mackerras
1722f6d57916SPaul Mackerras /*
1723f6d57916SPaul Mackerras * Turn off as much as we can
1724f6d57916SPaul Mackerras */
1725f6d57916SPaul Mackerras if (macio->type == macio_pangea)
1726f6d57916SPaul Mackerras pangea_shutdown(macio, 1);
1727f6d57916SPaul Mackerras else if (macio->type == macio_intrepid)
1728f6d57916SPaul Mackerras intrepid_shutdown(macio, 1);
1729f6d57916SPaul Mackerras else if (macio->type == macio_keylargo)
1730f6d57916SPaul Mackerras keylargo_shutdown(macio, 1);
1731f6d57916SPaul Mackerras
1732f6d57916SPaul Mackerras /*
1733f6d57916SPaul Mackerras * Put the host bridge to sleep
1734f6d57916SPaul Mackerras */
1735f6d57916SPaul Mackerras
1736f6d57916SPaul Mackerras save_unin_clock_ctl = UN_IN(UNI_N_CLOCK_CNTL);
1737f6d57916SPaul Mackerras /* Note: do not switch GMAC off, driver does it when necessary, WOL must keep it
1738f6d57916SPaul Mackerras * enabled !
1739f6d57916SPaul Mackerras */
1740f6d57916SPaul Mackerras UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl &
1741f6d57916SPaul Mackerras ~(/*UNI_N_CLOCK_CNTL_GMAC|*/UNI_N_CLOCK_CNTL_FW/*|UNI_N_CLOCK_CNTL_PCI*/));
1742f6d57916SPaul Mackerras udelay(100);
1743f6d57916SPaul Mackerras UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING);
1744f6d57916SPaul Mackerras UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_SLEEP);
1745f6d57916SPaul Mackerras mdelay(10);
1746f6d57916SPaul Mackerras
1747f6d57916SPaul Mackerras /*
1748f6d57916SPaul Mackerras * FIXME: A bit of black magic with OpenPIC (don't ask me why)
1749f6d57916SPaul Mackerras */
1750f6d57916SPaul Mackerras if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) {
1751f6d57916SPaul Mackerras MACIO_BIS(0x506e0, 0x00400000);
1752f6d57916SPaul Mackerras MACIO_BIS(0x506e0, 0x80000000);
1753f6d57916SPaul Mackerras }
1754f6d57916SPaul Mackerras return 0;
1755f6d57916SPaul Mackerras }
1756f6d57916SPaul Mackerras
1757f6d57916SPaul Mackerras static int
core99_wake_up(void)1758f6d57916SPaul Mackerras core99_wake_up(void)
1759f6d57916SPaul Mackerras {
1760f6d57916SPaul Mackerras struct macio_chip *macio;
1761f6d57916SPaul Mackerras int i;
1762f6d57916SPaul Mackerras
1763f6d57916SPaul Mackerras macio = &macio_chips[0];
1764f6d57916SPaul Mackerras if (macio->type != macio_keylargo && macio->type != macio_pangea &&
1765f6d57916SPaul Mackerras macio->type != macio_intrepid)
1766f6d57916SPaul Mackerras return -ENODEV;
1767f6d57916SPaul Mackerras
1768f6d57916SPaul Mackerras /*
1769f6d57916SPaul Mackerras * Wakeup the host bridge
1770f6d57916SPaul Mackerras */
1771f6d57916SPaul Mackerras UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL);
1772f6d57916SPaul Mackerras udelay(10);
1773f6d57916SPaul Mackerras UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING);
1774f6d57916SPaul Mackerras udelay(10);
1775f6d57916SPaul Mackerras
1776f6d57916SPaul Mackerras /*
1777f6d57916SPaul Mackerras * Restore KeyLargo
1778f6d57916SPaul Mackerras */
1779f6d57916SPaul Mackerras
1780f6d57916SPaul Mackerras if (macio->type == macio_keylargo) {
1781f6d57916SPaul Mackerras MACIO_OUT32(KEYLARGO_MBCR, save_mbcr);
1782f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_MBCR); udelay(10);
1783f6d57916SPaul Mackerras }
1784f6d57916SPaul Mackerras MACIO_OUT32(KEYLARGO_FCR0, save_fcr[0]);
1785f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR0); udelay(10);
1786f6d57916SPaul Mackerras MACIO_OUT32(KEYLARGO_FCR1, save_fcr[1]);
1787f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR1); udelay(10);
1788f6d57916SPaul Mackerras MACIO_OUT32(KEYLARGO_FCR2, save_fcr[2]);
1789f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR2); udelay(10);
1790f6d57916SPaul Mackerras MACIO_OUT32(KEYLARGO_FCR3, save_fcr[3]);
1791f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR3); udelay(10);
1792f6d57916SPaul Mackerras MACIO_OUT32(KEYLARGO_FCR4, save_fcr[4]);
1793f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR4); udelay(10);
1794f6d57916SPaul Mackerras if (macio->type == macio_pangea || macio->type == macio_intrepid) {
1795f6d57916SPaul Mackerras MACIO_OUT32(KEYLARGO_FCR5, save_fcr[5]);
1796f6d57916SPaul Mackerras (void)MACIO_IN32(KEYLARGO_FCR5); udelay(10);
1797f6d57916SPaul Mackerras }
1798f6d57916SPaul Mackerras
1799f6d57916SPaul Mackerras dbdma_restore(macio, save_dbdma);
1800f6d57916SPaul Mackerras
1801f6d57916SPaul Mackerras MACIO_OUT32(KEYLARGO_GPIO_LEVELS0, save_gpio_levels[0]);
1802f6d57916SPaul Mackerras MACIO_OUT32(KEYLARGO_GPIO_LEVELS1, save_gpio_levels[1]);
1803f6d57916SPaul Mackerras for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
1804f6d57916SPaul Mackerras MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+i, save_gpio_extint[i]);
1805f6d57916SPaul Mackerras for (i=0; i<KEYLARGO_GPIO_CNT; i++)
1806f6d57916SPaul Mackerras MACIO_OUT8(KEYLARGO_GPIO_0+i, save_gpio_normal[i]);
1807f6d57916SPaul Mackerras
1808f6d57916SPaul Mackerras /* FIXME more black magic with OpenPIC ... */
1809f6d57916SPaul Mackerras if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) {
1810f6d57916SPaul Mackerras MACIO_BIC(0x506e0, 0x00400000);
1811f6d57916SPaul Mackerras MACIO_BIC(0x506e0, 0x80000000);
1812f6d57916SPaul Mackerras }
1813f6d57916SPaul Mackerras
1814f6d57916SPaul Mackerras UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl);
1815f6d57916SPaul Mackerras udelay(100);
1816f6d57916SPaul Mackerras
1817f6d57916SPaul Mackerras return 0;
1818f6d57916SPaul Mackerras }
1819f6d57916SPaul Mackerras
18205b9ca526SBenjamin Herrenschmidt #endif /* CONFIG_PM */
18215b9ca526SBenjamin Herrenschmidt
1822f6d57916SPaul Mackerras static long
core99_sleep_state(struct device_node * node,long param,long value)1823f6d57916SPaul Mackerras core99_sleep_state(struct device_node *node, long param, long value)
1824f6d57916SPaul Mackerras {
1825f6d57916SPaul Mackerras /* Param == 1 means to enter the "fake sleep" mode that is
1826f6d57916SPaul Mackerras * used for CPU speed switch
1827f6d57916SPaul Mackerras */
1828f6d57916SPaul Mackerras if (param == 1) {
1829f6d57916SPaul Mackerras if (value == 1) {
1830f6d57916SPaul Mackerras UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING);
1831f6d57916SPaul Mackerras UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_IDLE2);
1832f6d57916SPaul Mackerras } else {
1833f6d57916SPaul Mackerras UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL);
1834f6d57916SPaul Mackerras udelay(10);
1835f6d57916SPaul Mackerras UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING);
1836f6d57916SPaul Mackerras udelay(10);
1837f6d57916SPaul Mackerras }
1838f6d57916SPaul Mackerras return 0;
1839f6d57916SPaul Mackerras }
1840f6d57916SPaul Mackerras if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
1841f6d57916SPaul Mackerras return -EPERM;
1842f6d57916SPaul Mackerras
18435b9ca526SBenjamin Herrenschmidt #ifdef CONFIG_PM
1844f6d57916SPaul Mackerras if (value == 1)
1845f6d57916SPaul Mackerras return core99_sleep();
1846f6d57916SPaul Mackerras else if (value == 0)
1847f6d57916SPaul Mackerras return core99_wake_up();
18485b9ca526SBenjamin Herrenschmidt
18495b9ca526SBenjamin Herrenschmidt #endif /* CONFIG_PM */
1850f6d57916SPaul Mackerras return 0;
1851f6d57916SPaul Mackerras }
1852f6d57916SPaul Mackerras
1853804ece07SMichael Ellerman #endif /* CONFIG_PPC64 */
1854f6d57916SPaul Mackerras
1855f6d57916SPaul Mackerras static long
generic_dev_can_wake(struct device_node * node,long param,long value)1856f6d57916SPaul Mackerras generic_dev_can_wake(struct device_node *node, long param, long value)
1857f6d57916SPaul Mackerras {
1858f6d57916SPaul Mackerras /* Todo: eventually check we are really dealing with on-board
1859f6d57916SPaul Mackerras * video device ...
1860f6d57916SPaul Mackerras */
1861f6d57916SPaul Mackerras
1862f6d57916SPaul Mackerras if (pmac_mb.board_flags & PMAC_MB_MAY_SLEEP)
1863f6d57916SPaul Mackerras pmac_mb.board_flags |= PMAC_MB_CAN_SLEEP;
1864f6d57916SPaul Mackerras return 0;
1865f6d57916SPaul Mackerras }
1866f6d57916SPaul Mackerras
generic_get_mb_info(struct device_node * node,long param,long value)1867f6d57916SPaul Mackerras static long generic_get_mb_info(struct device_node *node, long param, long value)
1868f6d57916SPaul Mackerras {
1869f6d57916SPaul Mackerras switch(param) {
1870f6d57916SPaul Mackerras case PMAC_MB_INFO_MODEL:
1871f6d57916SPaul Mackerras return pmac_mb.model_id;
1872f6d57916SPaul Mackerras case PMAC_MB_INFO_FLAGS:
1873f6d57916SPaul Mackerras return pmac_mb.board_flags;
1874f6d57916SPaul Mackerras case PMAC_MB_INFO_NAME:
1875f6d57916SPaul Mackerras /* hack hack hack... but should work */
1876f6d57916SPaul Mackerras *((const char **)value) = pmac_mb.model_name;
1877f6d57916SPaul Mackerras return 0;
1878f6d57916SPaul Mackerras }
1879f6d57916SPaul Mackerras return -EINVAL;
1880f6d57916SPaul Mackerras }
1881f6d57916SPaul Mackerras
1882f6d57916SPaul Mackerras
1883f6d57916SPaul Mackerras /*
1884f6d57916SPaul Mackerras * Table definitions
1885f6d57916SPaul Mackerras */
1886f6d57916SPaul Mackerras
1887f6d57916SPaul Mackerras /* Used on any machine
1888f6d57916SPaul Mackerras */
1889f6d57916SPaul Mackerras static struct feature_table_entry any_features[] = {
1890f6d57916SPaul Mackerras { PMAC_FTR_GET_MB_INFO, generic_get_mb_info },
1891f6d57916SPaul Mackerras { PMAC_FTR_DEVICE_CAN_WAKE, generic_dev_can_wake },
1892f6d57916SPaul Mackerras { 0, NULL }
1893f6d57916SPaul Mackerras };
1894f6d57916SPaul Mackerras
1895804ece07SMichael Ellerman #ifndef CONFIG_PPC64
1896f6d57916SPaul Mackerras
1897f6d57916SPaul Mackerras /* OHare based motherboards. Currently, we only use these on the
1898f6d57916SPaul Mackerras * 2400,3400 and 3500 series powerbooks. Some older desktops seem
1899f6d57916SPaul Mackerras * to have issues with turning on/off those asic cells
1900f6d57916SPaul Mackerras */
1901f6d57916SPaul Mackerras static struct feature_table_entry ohare_features[] = {
1902f6d57916SPaul Mackerras { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable },
1903f6d57916SPaul Mackerras { PMAC_FTR_SWIM3_ENABLE, ohare_floppy_enable },
1904f6d57916SPaul Mackerras { PMAC_FTR_MESH_ENABLE, ohare_mesh_enable },
1905f6d57916SPaul Mackerras { PMAC_FTR_IDE_ENABLE, ohare_ide_enable},
1906f6d57916SPaul Mackerras { PMAC_FTR_IDE_RESET, ohare_ide_reset},
1907f6d57916SPaul Mackerras { PMAC_FTR_SLEEP_STATE, ohare_sleep_state },
1908f6d57916SPaul Mackerras { 0, NULL }
1909f6d57916SPaul Mackerras };
1910f6d57916SPaul Mackerras
1911f6d57916SPaul Mackerras /* Heathrow desktop machines (Beige G3).
1912f6d57916SPaul Mackerras * Separated as some features couldn't be properly tested
1913f6d57916SPaul Mackerras * and the serial port control bits appear to confuse it.
1914f6d57916SPaul Mackerras */
1915f6d57916SPaul Mackerras static struct feature_table_entry heathrow_desktop_features[] = {
1916f6d57916SPaul Mackerras { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable },
1917f6d57916SPaul Mackerras { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable },
1918f6d57916SPaul Mackerras { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable },
1919f6d57916SPaul Mackerras { PMAC_FTR_IDE_RESET, heathrow_ide_reset },
1920f6d57916SPaul Mackerras { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable },
1921f6d57916SPaul Mackerras { 0, NULL }
1922f6d57916SPaul Mackerras };
1923f6d57916SPaul Mackerras
1924f6d57916SPaul Mackerras /* Heathrow based laptop, that is the Wallstreet and mainstreet
1925f6d57916SPaul Mackerras * powerbooks.
1926f6d57916SPaul Mackerras */
1927f6d57916SPaul Mackerras static struct feature_table_entry heathrow_laptop_features[] = {
1928f6d57916SPaul Mackerras { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable },
1929f6d57916SPaul Mackerras { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable },
1930f6d57916SPaul Mackerras { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable },
1931f6d57916SPaul Mackerras { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable },
1932f6d57916SPaul Mackerras { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable },
1933f6d57916SPaul Mackerras { PMAC_FTR_IDE_RESET, heathrow_ide_reset },
1934f6d57916SPaul Mackerras { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable },
1935f6d57916SPaul Mackerras { PMAC_FTR_SOUND_CHIP_ENABLE, heathrow_sound_enable },
1936f6d57916SPaul Mackerras { PMAC_FTR_SLEEP_STATE, heathrow_sleep_state },
1937f6d57916SPaul Mackerras { 0, NULL }
1938f6d57916SPaul Mackerras };
1939f6d57916SPaul Mackerras
1940f6d57916SPaul Mackerras /* Paddington based machines
1941f6d57916SPaul Mackerras * The lombard (101) powerbook, first iMac models, B&W G3 and Yikes G4.
1942f6d57916SPaul Mackerras */
1943f6d57916SPaul Mackerras static struct feature_table_entry paddington_features[] = {
1944f6d57916SPaul Mackerras { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable },
1945f6d57916SPaul Mackerras { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable },
1946f6d57916SPaul Mackerras { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable },
1947f6d57916SPaul Mackerras { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable },
1948f6d57916SPaul Mackerras { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable },
1949f6d57916SPaul Mackerras { PMAC_FTR_IDE_RESET, heathrow_ide_reset },
1950f6d57916SPaul Mackerras { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable },
1951f6d57916SPaul Mackerras { PMAC_FTR_SOUND_CHIP_ENABLE, heathrow_sound_enable },
1952f6d57916SPaul Mackerras { PMAC_FTR_SLEEP_STATE, heathrow_sleep_state },
1953f6d57916SPaul Mackerras { 0, NULL }
1954f6d57916SPaul Mackerras };
1955f6d57916SPaul Mackerras
1956f6d57916SPaul Mackerras /* Core99 & MacRISC 2 machines (all machines released since the
1957f6d57916SPaul Mackerras * iBook (included), that is all AGP machines, except pangea
1958f6d57916SPaul Mackerras * chipset. The pangea chipset is the "combo" UniNorth/KeyLargo
1959f6d57916SPaul Mackerras * used on iBook2 & iMac "flow power".
1960f6d57916SPaul Mackerras */
1961f6d57916SPaul Mackerras static struct feature_table_entry core99_features[] = {
1962f6d57916SPaul Mackerras { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
1963f6d57916SPaul Mackerras { PMAC_FTR_MODEM_ENABLE, core99_modem_enable },
1964f6d57916SPaul Mackerras { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
1965f6d57916SPaul Mackerras { PMAC_FTR_IDE_RESET, core99_ide_reset },
1966f6d57916SPaul Mackerras { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },
1967f6d57916SPaul Mackerras { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },
1968f6d57916SPaul Mackerras { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable },
1969f6d57916SPaul Mackerras { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable },
1970f6d57916SPaul Mackerras { PMAC_FTR_USB_ENABLE, core99_usb_enable },
1971f6d57916SPaul Mackerras { PMAC_FTR_1394_ENABLE, core99_firewire_enable },
1972f6d57916SPaul Mackerras { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },
19735b9ca526SBenjamin Herrenschmidt #ifdef CONFIG_PM
1974f6d57916SPaul Mackerras { PMAC_FTR_SLEEP_STATE, core99_sleep_state },
19755b9ca526SBenjamin Herrenschmidt #endif
1976f6d57916SPaul Mackerras #ifdef CONFIG_SMP
1977f6d57916SPaul Mackerras { PMAC_FTR_RESET_CPU, core99_reset_cpu },
1978f6d57916SPaul Mackerras #endif /* CONFIG_SMP */
1979f6d57916SPaul Mackerras { PMAC_FTR_READ_GPIO, core99_read_gpio },
1980f6d57916SPaul Mackerras { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
1981f6d57916SPaul Mackerras { 0, NULL }
1982f6d57916SPaul Mackerras };
1983f6d57916SPaul Mackerras
1984f6d57916SPaul Mackerras /* RackMac
1985f6d57916SPaul Mackerras */
1986f6d57916SPaul Mackerras static struct feature_table_entry rackmac_features[] = {
1987f6d57916SPaul Mackerras { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
1988f6d57916SPaul Mackerras { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
1989f6d57916SPaul Mackerras { PMAC_FTR_IDE_RESET, core99_ide_reset },
1990f6d57916SPaul Mackerras { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },
1991f6d57916SPaul Mackerras { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },
1992f6d57916SPaul Mackerras { PMAC_FTR_USB_ENABLE, core99_usb_enable },
1993f6d57916SPaul Mackerras { PMAC_FTR_1394_ENABLE, core99_firewire_enable },
1994f6d57916SPaul Mackerras { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },
1995f6d57916SPaul Mackerras { PMAC_FTR_SLEEP_STATE, core99_sleep_state },
1996f6d57916SPaul Mackerras #ifdef CONFIG_SMP
1997f6d57916SPaul Mackerras { PMAC_FTR_RESET_CPU, core99_reset_cpu },
1998f6d57916SPaul Mackerras #endif /* CONFIG_SMP */
1999f6d57916SPaul Mackerras { PMAC_FTR_READ_GPIO, core99_read_gpio },
2000f6d57916SPaul Mackerras { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
2001f6d57916SPaul Mackerras { 0, NULL }
2002f6d57916SPaul Mackerras };
2003f6d57916SPaul Mackerras
2004f6d57916SPaul Mackerras /* Pangea features
2005f6d57916SPaul Mackerras */
2006f6d57916SPaul Mackerras static struct feature_table_entry pangea_features[] = {
2007f6d57916SPaul Mackerras { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
2008f6d57916SPaul Mackerras { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable },
2009f6d57916SPaul Mackerras { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
2010f6d57916SPaul Mackerras { PMAC_FTR_IDE_RESET, core99_ide_reset },
2011f6d57916SPaul Mackerras { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },
2012f6d57916SPaul Mackerras { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },
2013f6d57916SPaul Mackerras { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable },
2014f6d57916SPaul Mackerras { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable },
2015f6d57916SPaul Mackerras { PMAC_FTR_USB_ENABLE, core99_usb_enable },
2016f6d57916SPaul Mackerras { PMAC_FTR_1394_ENABLE, core99_firewire_enable },
2017f6d57916SPaul Mackerras { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },
2018f6d57916SPaul Mackerras { PMAC_FTR_SLEEP_STATE, core99_sleep_state },
2019f6d57916SPaul Mackerras { PMAC_FTR_READ_GPIO, core99_read_gpio },
2020f6d57916SPaul Mackerras { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
2021f6d57916SPaul Mackerras { 0, NULL }
2022f6d57916SPaul Mackerras };
2023f6d57916SPaul Mackerras
2024f6d57916SPaul Mackerras /* Intrepid features
2025f6d57916SPaul Mackerras */
2026f6d57916SPaul Mackerras static struct feature_table_entry intrepid_features[] = {
2027f6d57916SPaul Mackerras { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
2028f6d57916SPaul Mackerras { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable },
2029f6d57916SPaul Mackerras { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
2030f6d57916SPaul Mackerras { PMAC_FTR_IDE_RESET, core99_ide_reset },
2031f6d57916SPaul Mackerras { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },
2032f6d57916SPaul Mackerras { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },
2033f6d57916SPaul Mackerras { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable },
2034f6d57916SPaul Mackerras { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable },
2035f6d57916SPaul Mackerras { PMAC_FTR_USB_ENABLE, core99_usb_enable },
2036f6d57916SPaul Mackerras { PMAC_FTR_1394_ENABLE, core99_firewire_enable },
2037f6d57916SPaul Mackerras { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },
2038f6d57916SPaul Mackerras { PMAC_FTR_SLEEP_STATE, core99_sleep_state },
2039f6d57916SPaul Mackerras { PMAC_FTR_READ_GPIO, core99_read_gpio },
2040f6d57916SPaul Mackerras { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
2041f6d57916SPaul Mackerras { PMAC_FTR_AACK_DELAY_ENABLE, intrepid_aack_delay_enable },
2042f6d57916SPaul Mackerras { 0, NULL }
2043f6d57916SPaul Mackerras };
2044f6d57916SPaul Mackerras
2045804ece07SMichael Ellerman #else /* CONFIG_PPC64 */
2046f6d57916SPaul Mackerras
2047f6d57916SPaul Mackerras /* G5 features
2048f6d57916SPaul Mackerras */
2049f6d57916SPaul Mackerras static struct feature_table_entry g5_features[] = {
2050f6d57916SPaul Mackerras { PMAC_FTR_GMAC_ENABLE, g5_gmac_enable },
2051f6d57916SPaul Mackerras { PMAC_FTR_1394_ENABLE, g5_fw_enable },
2052f6d57916SPaul Mackerras { PMAC_FTR_ENABLE_MPIC, g5_mpic_enable },
2053f6d57916SPaul Mackerras { PMAC_FTR_GMAC_PHY_RESET, g5_eth_phy_reset },
2054f6d57916SPaul Mackerras { PMAC_FTR_SOUND_CHIP_ENABLE, g5_i2s_enable },
2055f6d57916SPaul Mackerras #ifdef CONFIG_SMP
2056f6d57916SPaul Mackerras { PMAC_FTR_RESET_CPU, g5_reset_cpu },
2057f6d57916SPaul Mackerras #endif /* CONFIG_SMP */
2058f6d57916SPaul Mackerras { PMAC_FTR_READ_GPIO, core99_read_gpio },
2059f6d57916SPaul Mackerras { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
2060f6d57916SPaul Mackerras { 0, NULL }
2061f6d57916SPaul Mackerras };
2062f6d57916SPaul Mackerras
2063804ece07SMichael Ellerman #endif /* CONFIG_PPC64 */
2064f6d57916SPaul Mackerras
2065f6d57916SPaul Mackerras static struct pmac_mb_def pmac_mb_defs[] = {
2066804ece07SMichael Ellerman #ifndef CONFIG_PPC64
2067f6d57916SPaul Mackerras /*
2068f6d57916SPaul Mackerras * Desktops
2069f6d57916SPaul Mackerras */
2070f6d57916SPaul Mackerras
2071f6d57916SPaul Mackerras { "AAPL,8500", "PowerMac 8500/8600",
2072f6d57916SPaul Mackerras PMAC_TYPE_PSURGE, NULL,
2073f6d57916SPaul Mackerras 0
2074f6d57916SPaul Mackerras },
2075f6d57916SPaul Mackerras { "AAPL,9500", "PowerMac 9500/9600",
2076f6d57916SPaul Mackerras PMAC_TYPE_PSURGE, NULL,
2077f6d57916SPaul Mackerras 0
2078f6d57916SPaul Mackerras },
2079f6d57916SPaul Mackerras { "AAPL,7200", "PowerMac 7200",
2080f6d57916SPaul Mackerras PMAC_TYPE_PSURGE, NULL,
2081f6d57916SPaul Mackerras 0
2082f6d57916SPaul Mackerras },
2083f6d57916SPaul Mackerras { "AAPL,7300", "PowerMac 7200/7300",
2084f6d57916SPaul Mackerras PMAC_TYPE_PSURGE, NULL,
2085f6d57916SPaul Mackerras 0
2086f6d57916SPaul Mackerras },
2087f6d57916SPaul Mackerras { "AAPL,7500", "PowerMac 7500",
2088f6d57916SPaul Mackerras PMAC_TYPE_PSURGE, NULL,
2089f6d57916SPaul Mackerras 0
2090f6d57916SPaul Mackerras },
2091f6d57916SPaul Mackerras { "AAPL,ShinerESB", "Apple Network Server",
2092f6d57916SPaul Mackerras PMAC_TYPE_ANS, NULL,
2093f6d57916SPaul Mackerras 0
2094f6d57916SPaul Mackerras },
2095f6d57916SPaul Mackerras { "AAPL,e407", "Alchemy",
2096f6d57916SPaul Mackerras PMAC_TYPE_ALCHEMY, NULL,
2097f6d57916SPaul Mackerras 0
2098f6d57916SPaul Mackerras },
2099f6d57916SPaul Mackerras { "AAPL,e411", "Gazelle",
2100f6d57916SPaul Mackerras PMAC_TYPE_GAZELLE, NULL,
2101f6d57916SPaul Mackerras 0
2102f6d57916SPaul Mackerras },
2103f6d57916SPaul Mackerras { "AAPL,Gossamer", "PowerMac G3 (Gossamer)",
2104f6d57916SPaul Mackerras PMAC_TYPE_GOSSAMER, heathrow_desktop_features,
2105f6d57916SPaul Mackerras 0
2106f6d57916SPaul Mackerras },
2107f6d57916SPaul Mackerras { "AAPL,PowerMac G3", "PowerMac G3 (Silk)",
2108f6d57916SPaul Mackerras PMAC_TYPE_SILK, heathrow_desktop_features,
2109f6d57916SPaul Mackerras 0
2110f6d57916SPaul Mackerras },
2111f6d57916SPaul Mackerras { "PowerMac1,1", "Blue&White G3",
2112f6d57916SPaul Mackerras PMAC_TYPE_YOSEMITE, paddington_features,
2113f6d57916SPaul Mackerras 0
2114f6d57916SPaul Mackerras },
2115f6d57916SPaul Mackerras { "PowerMac1,2", "PowerMac G4 PCI Graphics",
2116f6d57916SPaul Mackerras PMAC_TYPE_YIKES, paddington_features,
2117f6d57916SPaul Mackerras 0
2118f6d57916SPaul Mackerras },
2119f6d57916SPaul Mackerras { "PowerMac2,1", "iMac FireWire",
2120f6d57916SPaul Mackerras PMAC_TYPE_FW_IMAC, core99_features,
2121f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
2122f6d57916SPaul Mackerras },
2123f6d57916SPaul Mackerras { "PowerMac2,2", "iMac FireWire",
2124f6d57916SPaul Mackerras PMAC_TYPE_FW_IMAC, core99_features,
2125f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
2126f6d57916SPaul Mackerras },
2127f6d57916SPaul Mackerras { "PowerMac3,1", "PowerMac G4 AGP Graphics",
2128f6d57916SPaul Mackerras PMAC_TYPE_SAWTOOTH, core99_features,
2129f6d57916SPaul Mackerras PMAC_MB_OLD_CORE99
2130f6d57916SPaul Mackerras },
2131f6d57916SPaul Mackerras { "PowerMac3,2", "PowerMac G4 AGP Graphics",
2132f6d57916SPaul Mackerras PMAC_TYPE_SAWTOOTH, core99_features,
2133f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
2134f6d57916SPaul Mackerras },
2135f6d57916SPaul Mackerras { "PowerMac3,3", "PowerMac G4 AGP Graphics",
2136f6d57916SPaul Mackerras PMAC_TYPE_SAWTOOTH, core99_features,
2137f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
2138f6d57916SPaul Mackerras },
2139f6d57916SPaul Mackerras { "PowerMac3,4", "PowerMac G4 Silver",
2140f6d57916SPaul Mackerras PMAC_TYPE_QUICKSILVER, core99_features,
2141f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP
2142f6d57916SPaul Mackerras },
2143f6d57916SPaul Mackerras { "PowerMac3,5", "PowerMac G4 Silver",
2144f6d57916SPaul Mackerras PMAC_TYPE_QUICKSILVER, core99_features,
2145f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP
2146f6d57916SPaul Mackerras },
2147f6d57916SPaul Mackerras { "PowerMac3,6", "PowerMac G4 Windtunnel",
2148f6d57916SPaul Mackerras PMAC_TYPE_WINDTUNNEL, core99_features,
2149f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP,
2150f6d57916SPaul Mackerras },
2151f6d57916SPaul Mackerras { "PowerMac4,1", "iMac \"Flower Power\"",
2152f6d57916SPaul Mackerras PMAC_TYPE_PANGEA_IMAC, pangea_features,
2153f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP
2154f6d57916SPaul Mackerras },
2155f6d57916SPaul Mackerras { "PowerMac4,2", "Flat panel iMac",
2156f6d57916SPaul Mackerras PMAC_TYPE_FLAT_PANEL_IMAC, pangea_features,
2157f6d57916SPaul Mackerras PMAC_MB_CAN_SLEEP
2158f6d57916SPaul Mackerras },
2159f6d57916SPaul Mackerras { "PowerMac4,4", "eMac",
2160f6d57916SPaul Mackerras PMAC_TYPE_EMAC, core99_features,
2161f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP
2162f6d57916SPaul Mackerras },
2163f6d57916SPaul Mackerras { "PowerMac5,1", "PowerMac G4 Cube",
2164f6d57916SPaul Mackerras PMAC_TYPE_CUBE, core99_features,
2165f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
2166f6d57916SPaul Mackerras },
2167f6d57916SPaul Mackerras { "PowerMac6,1", "Flat panel iMac",
2168f6d57916SPaul Mackerras PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2169f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP,
2170f6d57916SPaul Mackerras },
2171f6d57916SPaul Mackerras { "PowerMac6,3", "Flat panel iMac",
2172f6d57916SPaul Mackerras PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2173f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP,
2174f6d57916SPaul Mackerras },
2175f6d57916SPaul Mackerras { "PowerMac6,4", "eMac",
2176f6d57916SPaul Mackerras PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2177f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP,
2178f6d57916SPaul Mackerras },
2179f6d57916SPaul Mackerras { "PowerMac10,1", "Mac mini",
2180f6d57916SPaul Mackerras PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2181c8b8b1f2SBenjamin Herrenschmidt PMAC_MB_MAY_SLEEP,
2182f6d57916SPaul Mackerras },
2183ff4bb7cbSBenjamin Herrenschmidt { "PowerMac10,2", "Mac mini (Late 2005)",
2184ff4bb7cbSBenjamin Herrenschmidt PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2185ff4bb7cbSBenjamin Herrenschmidt PMAC_MB_MAY_SLEEP,
2186ff4bb7cbSBenjamin Herrenschmidt },
2187f6d57916SPaul Mackerras { "iMac,1", "iMac (first generation)",
2188f6d57916SPaul Mackerras PMAC_TYPE_ORIG_IMAC, paddington_features,
2189f6d57916SPaul Mackerras 0
2190f6d57916SPaul Mackerras },
2191f6d57916SPaul Mackerras
2192f6d57916SPaul Mackerras /*
2193f6d57916SPaul Mackerras * Xserve's
2194f6d57916SPaul Mackerras */
2195f6d57916SPaul Mackerras
2196f6d57916SPaul Mackerras { "RackMac1,1", "XServe",
2197f6d57916SPaul Mackerras PMAC_TYPE_RACKMAC, rackmac_features,
2198f6d57916SPaul Mackerras 0,
2199f6d57916SPaul Mackerras },
2200f6d57916SPaul Mackerras { "RackMac1,2", "XServe rev. 2",
2201f6d57916SPaul Mackerras PMAC_TYPE_RACKMAC, rackmac_features,
2202f6d57916SPaul Mackerras 0,
2203f6d57916SPaul Mackerras },
2204f6d57916SPaul Mackerras
2205f6d57916SPaul Mackerras /*
2206f6d57916SPaul Mackerras * Laptops
2207f6d57916SPaul Mackerras */
2208f6d57916SPaul Mackerras
2209f6d57916SPaul Mackerras { "AAPL,3400/2400", "PowerBook 3400",
2210f6d57916SPaul Mackerras PMAC_TYPE_HOOPER, ohare_features,
2211f6d57916SPaul Mackerras PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
2212f6d57916SPaul Mackerras },
2213f6d57916SPaul Mackerras { "AAPL,3500", "PowerBook 3500",
2214f6d57916SPaul Mackerras PMAC_TYPE_KANGA, ohare_features,
2215f6d57916SPaul Mackerras PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
2216f6d57916SPaul Mackerras },
2217f6d57916SPaul Mackerras { "AAPL,PowerBook1998", "PowerBook Wallstreet",
2218f6d57916SPaul Mackerras PMAC_TYPE_WALLSTREET, heathrow_laptop_features,
2219f6d57916SPaul Mackerras PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
2220f6d57916SPaul Mackerras },
2221f6d57916SPaul Mackerras { "PowerBook1,1", "PowerBook 101 (Lombard)",
2222f6d57916SPaul Mackerras PMAC_TYPE_101_PBOOK, paddington_features,
2223f6d57916SPaul Mackerras PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
2224f6d57916SPaul Mackerras },
2225f6d57916SPaul Mackerras { "PowerBook2,1", "iBook (first generation)",
2226f6d57916SPaul Mackerras PMAC_TYPE_ORIG_IBOOK, core99_features,
2227f6d57916SPaul Mackerras PMAC_MB_CAN_SLEEP | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
2228f6d57916SPaul Mackerras },
2229f6d57916SPaul Mackerras { "PowerBook2,2", "iBook FireWire",
2230f6d57916SPaul Mackerras PMAC_TYPE_FW_IBOOK, core99_features,
2231f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER |
2232f6d57916SPaul Mackerras PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
2233f6d57916SPaul Mackerras },
2234f6d57916SPaul Mackerras { "PowerBook3,1", "PowerBook Pismo",
2235f6d57916SPaul Mackerras PMAC_TYPE_PISMO, core99_features,
2236f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER |
2237f6d57916SPaul Mackerras PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
2238f6d57916SPaul Mackerras },
2239f6d57916SPaul Mackerras { "PowerBook3,2", "PowerBook Titanium",
2240f6d57916SPaul Mackerras PMAC_TYPE_TITANIUM, core99_features,
2241f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
2242f6d57916SPaul Mackerras },
2243f6d57916SPaul Mackerras { "PowerBook3,3", "PowerBook Titanium II",
2244f6d57916SPaul Mackerras PMAC_TYPE_TITANIUM2, core99_features,
2245f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
2246f6d57916SPaul Mackerras },
2247f6d57916SPaul Mackerras { "PowerBook3,4", "PowerBook Titanium III",
2248f6d57916SPaul Mackerras PMAC_TYPE_TITANIUM3, core99_features,
2249f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
2250f6d57916SPaul Mackerras },
2251f6d57916SPaul Mackerras { "PowerBook3,5", "PowerBook Titanium IV",
2252f6d57916SPaul Mackerras PMAC_TYPE_TITANIUM4, core99_features,
2253f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
2254f6d57916SPaul Mackerras },
2255f6d57916SPaul Mackerras { "PowerBook4,1", "iBook 2",
2256f6d57916SPaul Mackerras PMAC_TYPE_IBOOK2, pangea_features,
2257f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
2258f6d57916SPaul Mackerras },
2259f6d57916SPaul Mackerras { "PowerBook4,2", "iBook 2",
2260f6d57916SPaul Mackerras PMAC_TYPE_IBOOK2, pangea_features,
2261f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
2262f6d57916SPaul Mackerras },
2263f6d57916SPaul Mackerras { "PowerBook4,3", "iBook 2 rev. 2",
2264f6d57916SPaul Mackerras PMAC_TYPE_IBOOK2, pangea_features,
2265f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
2266f6d57916SPaul Mackerras },
2267f6d57916SPaul Mackerras { "PowerBook5,1", "PowerBook G4 17\"",
2268f6d57916SPaul Mackerras PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2269f6d57916SPaul Mackerras PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
2270f6d57916SPaul Mackerras },
2271f6d57916SPaul Mackerras { "PowerBook5,2", "PowerBook G4 15\"",
2272f6d57916SPaul Mackerras PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2273f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
2274f6d57916SPaul Mackerras },
2275f6d57916SPaul Mackerras { "PowerBook5,3", "PowerBook G4 17\"",
2276f6d57916SPaul Mackerras PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2277f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
2278f6d57916SPaul Mackerras },
2279f6d57916SPaul Mackerras { "PowerBook5,4", "PowerBook G4 15\"",
2280f6d57916SPaul Mackerras PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2281f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
2282f6d57916SPaul Mackerras },
2283f6d57916SPaul Mackerras { "PowerBook5,5", "PowerBook G4 17\"",
2284f6d57916SPaul Mackerras PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2285f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
2286f6d57916SPaul Mackerras },
2287f6d57916SPaul Mackerras { "PowerBook5,6", "PowerBook G4 15\"",
2288f6d57916SPaul Mackerras PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2289f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
2290f6d57916SPaul Mackerras },
2291f6d57916SPaul Mackerras { "PowerBook5,7", "PowerBook G4 17\"",
2292f6d57916SPaul Mackerras PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2293f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
2294f6d57916SPaul Mackerras },
2295950fc002SOlof Johansson { "PowerBook5,8", "PowerBook G4 15\"",
2296950fc002SOlof Johansson PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2297c8b8b1f2SBenjamin Herrenschmidt PMAC_MB_MAY_SLEEP | PMAC_MB_MOBILE,
2298950fc002SOlof Johansson },
2299950fc002SOlof Johansson { "PowerBook5,9", "PowerBook G4 17\"",
2300950fc002SOlof Johansson PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2301c8b8b1f2SBenjamin Herrenschmidt PMAC_MB_MAY_SLEEP | PMAC_MB_MOBILE,
2302950fc002SOlof Johansson },
2303f6d57916SPaul Mackerras { "PowerBook6,1", "PowerBook G4 12\"",
2304f6d57916SPaul Mackerras PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2305f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
2306f6d57916SPaul Mackerras },
2307f6d57916SPaul Mackerras { "PowerBook6,2", "PowerBook G4",
2308f6d57916SPaul Mackerras PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2309f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
2310f6d57916SPaul Mackerras },
2311f6d57916SPaul Mackerras { "PowerBook6,3", "iBook G4",
2312f6d57916SPaul Mackerras PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2313f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
2314f6d57916SPaul Mackerras },
2315f6d57916SPaul Mackerras { "PowerBook6,4", "PowerBook G4 12\"",
2316f6d57916SPaul Mackerras PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2317f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
2318f6d57916SPaul Mackerras },
2319f6d57916SPaul Mackerras { "PowerBook6,5", "iBook G4",
2320f6d57916SPaul Mackerras PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2321f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
2322f6d57916SPaul Mackerras },
23235629d41dSPaul Mackerras { "PowerBook6,7", "iBook G4",
23245629d41dSPaul Mackerras PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
23255629d41dSPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
23265629d41dSPaul Mackerras },
2327f6d57916SPaul Mackerras { "PowerBook6,8", "PowerBook G4 12\"",
2328f6d57916SPaul Mackerras PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
2329f6d57916SPaul Mackerras PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
2330f6d57916SPaul Mackerras },
2331804ece07SMichael Ellerman #else /* CONFIG_PPC64 */
2332f6d57916SPaul Mackerras { "PowerMac7,2", "PowerMac G5",
2333f6d57916SPaul Mackerras PMAC_TYPE_POWERMAC_G5, g5_features,
2334f6d57916SPaul Mackerras 0,
2335f6d57916SPaul Mackerras },
2336f6d57916SPaul Mackerras #ifdef CONFIG_PPC64
2337f6d57916SPaul Mackerras { "PowerMac7,3", "PowerMac G5",
2338f6d57916SPaul Mackerras PMAC_TYPE_POWERMAC_G5, g5_features,
2339f6d57916SPaul Mackerras 0,
2340f6d57916SPaul Mackerras },
2341f6d57916SPaul Mackerras { "PowerMac8,1", "iMac G5",
2342f6d57916SPaul Mackerras PMAC_TYPE_IMAC_G5, g5_features,
2343f6d57916SPaul Mackerras 0,
2344f6d57916SPaul Mackerras },
2345f6d57916SPaul Mackerras { "PowerMac9,1", "PowerMac G5",
2346f6d57916SPaul Mackerras PMAC_TYPE_POWERMAC_G5_U3L, g5_features,
2347f6d57916SPaul Mackerras 0,
2348f6d57916SPaul Mackerras },
23491beb6a7dSBenjamin Herrenschmidt { "PowerMac11,2", "PowerMac G5 Dual Core",
23501beb6a7dSBenjamin Herrenschmidt PMAC_TYPE_POWERMAC_G5_U3L, g5_features,
23511beb6a7dSBenjamin Herrenschmidt 0,
23521beb6a7dSBenjamin Herrenschmidt },
23531beb6a7dSBenjamin Herrenschmidt { "PowerMac12,1", "iMac G5 (iSight)",
23541beb6a7dSBenjamin Herrenschmidt PMAC_TYPE_POWERMAC_G5_U3L, g5_features,
23551beb6a7dSBenjamin Herrenschmidt 0,
23561beb6a7dSBenjamin Herrenschmidt },
2357f6d57916SPaul Mackerras { "RackMac3,1", "XServe G5",
2358f6d57916SPaul Mackerras PMAC_TYPE_XSERVE_G5, g5_features,
2359f6d57916SPaul Mackerras 0,
2360f6d57916SPaul Mackerras },
2361f6d57916SPaul Mackerras #endif /* CONFIG_PPC64 */
2362804ece07SMichael Ellerman #endif /* CONFIG_PPC64 */
2363f6d57916SPaul Mackerras };
2364f6d57916SPaul Mackerras
2365f6d57916SPaul Mackerras /*
2366f6d57916SPaul Mackerras * The toplevel feature_call callback
2367f6d57916SPaul Mackerras */
pmac_do_feature_call(unsigned int selector,...)2368f6d57916SPaul Mackerras long pmac_do_feature_call(unsigned int selector, ...)
2369f6d57916SPaul Mackerras {
2370f6d57916SPaul Mackerras struct device_node *node;
2371f6d57916SPaul Mackerras long param, value;
2372f6d57916SPaul Mackerras int i;
2373f6d57916SPaul Mackerras feature_call func = NULL;
2374f6d57916SPaul Mackerras va_list args;
2375f6d57916SPaul Mackerras
2376f6d57916SPaul Mackerras if (pmac_mb.features)
2377f6d57916SPaul Mackerras for (i=0; pmac_mb.features[i].function; i++)
2378f6d57916SPaul Mackerras if (pmac_mb.features[i].selector == selector) {
2379f6d57916SPaul Mackerras func = pmac_mb.features[i].function;
2380f6d57916SPaul Mackerras break;
2381f6d57916SPaul Mackerras }
2382f6d57916SPaul Mackerras if (!func)
2383f6d57916SPaul Mackerras for (i=0; any_features[i].function; i++)
2384f6d57916SPaul Mackerras if (any_features[i].selector == selector) {
2385f6d57916SPaul Mackerras func = any_features[i].function;
2386f6d57916SPaul Mackerras break;
2387f6d57916SPaul Mackerras }
2388f6d57916SPaul Mackerras if (!func)
2389f6d57916SPaul Mackerras return -ENODEV;
2390f6d57916SPaul Mackerras
2391f6d57916SPaul Mackerras va_start(args, selector);
2392f6d57916SPaul Mackerras node = (struct device_node*)va_arg(args, void*);
2393f6d57916SPaul Mackerras param = va_arg(args, long);
2394f6d57916SPaul Mackerras value = va_arg(args, long);
2395f6d57916SPaul Mackerras va_end(args);
2396f6d57916SPaul Mackerras
2397f6d57916SPaul Mackerras return func(node, param, value);
2398f6d57916SPaul Mackerras }
2399f6d57916SPaul Mackerras
probe_motherboard(void)2400f6d57916SPaul Mackerras static int __init probe_motherboard(void)
2401f6d57916SPaul Mackerras {
2402f6d57916SPaul Mackerras int i;
2403f6d57916SPaul Mackerras struct macio_chip *macio = &macio_chips[0];
2404f6d57916SPaul Mackerras const char *model = NULL;
2405f6d57916SPaul Mackerras struct device_node *dt;
240630686ba6SStephen Rothwell int ret = 0;
2407f6d57916SPaul Mackerras
2408f6d57916SPaul Mackerras /* Lookup known motherboard type in device-tree. First try an
2409f6d57916SPaul Mackerras * exact match on the "model" property, then try a "compatible"
2410f6d57916SPaul Mackerras * match is none is found.
2411f6d57916SPaul Mackerras */
241230686ba6SStephen Rothwell dt = of_find_node_by_name(NULL, "device-tree");
2413f6d57916SPaul Mackerras if (dt != NULL)
2414e2eb6392SStephen Rothwell model = of_get_property(dt, "model", NULL);
2415a888ad45SStoyan Gaydarov for(i=0; model && i<ARRAY_SIZE(pmac_mb_defs); i++) {
2416f6d57916SPaul Mackerras if (strcmp(model, pmac_mb_defs[i].model_string) == 0) {
2417f6d57916SPaul Mackerras pmac_mb = pmac_mb_defs[i];
2418f6d57916SPaul Mackerras goto found;
2419f6d57916SPaul Mackerras }
2420f6d57916SPaul Mackerras }
2421a888ad45SStoyan Gaydarov for(i=0; i<ARRAY_SIZE(pmac_mb_defs); i++) {
242271a157e8SGrant Likely if (of_machine_is_compatible(pmac_mb_defs[i].model_string)) {
2423f6d57916SPaul Mackerras pmac_mb = pmac_mb_defs[i];
2424f6d57916SPaul Mackerras goto found;
2425f6d57916SPaul Mackerras }
2426f6d57916SPaul Mackerras }
2427f6d57916SPaul Mackerras
2428f6d57916SPaul Mackerras /* Fallback to selection depending on mac-io chip type */
2429f6d57916SPaul Mackerras switch(macio->type) {
2430804ece07SMichael Ellerman #ifndef CONFIG_PPC64
2431f6d57916SPaul Mackerras case macio_grand_central:
2432f6d57916SPaul Mackerras pmac_mb.model_id = PMAC_TYPE_PSURGE;
2433f6d57916SPaul Mackerras pmac_mb.model_name = "Unknown PowerSurge";
2434f6d57916SPaul Mackerras break;
2435f6d57916SPaul Mackerras case macio_ohare:
2436f6d57916SPaul Mackerras pmac_mb.model_id = PMAC_TYPE_UNKNOWN_OHARE;
2437f6d57916SPaul Mackerras pmac_mb.model_name = "Unknown OHare-based";
2438f6d57916SPaul Mackerras break;
2439f6d57916SPaul Mackerras case macio_heathrow:
2440f6d57916SPaul Mackerras pmac_mb.model_id = PMAC_TYPE_UNKNOWN_HEATHROW;
2441f6d57916SPaul Mackerras pmac_mb.model_name = "Unknown Heathrow-based";
2442f6d57916SPaul Mackerras pmac_mb.features = heathrow_desktop_features;
2443f6d57916SPaul Mackerras break;
2444f6d57916SPaul Mackerras case macio_paddington:
2445f6d57916SPaul Mackerras pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PADDINGTON;
2446f6d57916SPaul Mackerras pmac_mb.model_name = "Unknown Paddington-based";
2447f6d57916SPaul Mackerras pmac_mb.features = paddington_features;
2448f6d57916SPaul Mackerras break;
2449f6d57916SPaul Mackerras case macio_keylargo:
2450f6d57916SPaul Mackerras pmac_mb.model_id = PMAC_TYPE_UNKNOWN_CORE99;
2451f6d57916SPaul Mackerras pmac_mb.model_name = "Unknown Keylargo-based";
2452f6d57916SPaul Mackerras pmac_mb.features = core99_features;
2453f6d57916SPaul Mackerras break;
2454f6d57916SPaul Mackerras case macio_pangea:
2455f6d57916SPaul Mackerras pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PANGEA;
2456f6d57916SPaul Mackerras pmac_mb.model_name = "Unknown Pangea-based";
2457f6d57916SPaul Mackerras pmac_mb.features = pangea_features;
2458f6d57916SPaul Mackerras break;
2459f6d57916SPaul Mackerras case macio_intrepid:
2460f6d57916SPaul Mackerras pmac_mb.model_id = PMAC_TYPE_UNKNOWN_INTREPID;
2461f6d57916SPaul Mackerras pmac_mb.model_name = "Unknown Intrepid-based";
2462f6d57916SPaul Mackerras pmac_mb.features = intrepid_features;
2463f6d57916SPaul Mackerras break;
2464804ece07SMichael Ellerman #else /* CONFIG_PPC64 */
2465f6d57916SPaul Mackerras case macio_keylargo2:
2466f6d57916SPaul Mackerras pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2;
2467f6d57916SPaul Mackerras pmac_mb.model_name = "Unknown K2-based";
2468f6d57916SPaul Mackerras pmac_mb.features = g5_features;
2469f6d57916SPaul Mackerras break;
24701beb6a7dSBenjamin Herrenschmidt case macio_shasta:
24711beb6a7dSBenjamin Herrenschmidt pmac_mb.model_id = PMAC_TYPE_UNKNOWN_SHASTA;
24721beb6a7dSBenjamin Herrenschmidt pmac_mb.model_name = "Unknown Shasta-based";
24731beb6a7dSBenjamin Herrenschmidt pmac_mb.features = g5_features;
24741beb6a7dSBenjamin Herrenschmidt break;
2475804ece07SMichael Ellerman #endif /* CONFIG_PPC64 */
2476f6d57916SPaul Mackerras default:
247730686ba6SStephen Rothwell ret = -ENODEV;
247830686ba6SStephen Rothwell goto done;
2479f6d57916SPaul Mackerras }
2480f6d57916SPaul Mackerras found:
2481804ece07SMichael Ellerman #ifndef CONFIG_PPC64
2482f6d57916SPaul Mackerras /* Fixup Hooper vs. Comet */
2483f6d57916SPaul Mackerras if (pmac_mb.model_id == PMAC_TYPE_HOOPER) {
2484f6d57916SPaul Mackerras u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4);
248530686ba6SStephen Rothwell if (!mach_id_ptr) {
248630686ba6SStephen Rothwell ret = -ENODEV;
248730686ba6SStephen Rothwell goto done;
248830686ba6SStephen Rothwell }
2489f6d57916SPaul Mackerras /* Here, I used to disable the media-bay on comet. It
2490f6d57916SPaul Mackerras * appears this is wrong, the floppy connector is actually
2491f6d57916SPaul Mackerras * a kind of media-bay and works with the current driver.
2492f6d57916SPaul Mackerras */
2493f6d57916SPaul Mackerras if (__raw_readl(mach_id_ptr) & 0x20000000UL)
2494f6d57916SPaul Mackerras pmac_mb.model_id = PMAC_TYPE_COMET;
2495f6d57916SPaul Mackerras iounmap(mach_id_ptr);
2496f6d57916SPaul Mackerras }
2497f6d57916SPaul Mackerras
2498f6d57916SPaul Mackerras /* Set default value of powersave_nap on machines that support it.
2499f6d57916SPaul Mackerras * It appears that uninorth rev 3 has a problem with it, we don't
2500f6d57916SPaul Mackerras * enable it on those. In theory, the flush-on-lock property is
2501f6d57916SPaul Mackerras * supposed to be set when not supported, but I'm not very confident
2502f6d57916SPaul Mackerras * that all Apple OF revs did it properly, I do it the paranoid way.
2503f6d57916SPaul Mackerras */
2504a94fe366SRob Herring if (uninorth_base && uninorth_rev > 3) {
25058c8dc322SStephen Rothwell struct device_node *np;
25068c8dc322SStephen Rothwell
2507a94fe366SRob Herring for_each_of_cpu_node(np) {
2508a94fe366SRob Herring int cpu_count = 1;
2509a94fe366SRob Herring
2510f6d57916SPaul Mackerras /* Nap mode not supported on SMP */
25114d57e351SRob Herring if (of_property_read_bool(np, "flush-on-lock") ||
2512a94fe366SRob Herring (cpu_count > 1)) {
2513a94fe366SRob Herring powersave_nap = 0;
2514a94fe366SRob Herring of_node_put(np);
2515f6d57916SPaul Mackerras break;
25168c8dc322SStephen Rothwell }
2517a94fe366SRob Herring
2518a94fe366SRob Herring cpu_count++;
2519f6d57916SPaul Mackerras powersave_nap = 1;
2520f6d57916SPaul Mackerras }
2521a94fe366SRob Herring }
2522a94fe366SRob Herring if (powersave_nap)
2523a94fe366SRob Herring printk(KERN_DEBUG "Processor NAP mode on idle enabled.\n");
2524f6d57916SPaul Mackerras
2525f6d57916SPaul Mackerras /* On CPUs that support it (750FX), lowspeed by default during
2526f6d57916SPaul Mackerras * NAP mode
2527f6d57916SPaul Mackerras */
2528f6d57916SPaul Mackerras powersave_lowspeed = 1;
2529c6cb3b5fSBenjamin Herrenschmidt
2530804ece07SMichael Ellerman #else /* CONFIG_PPC64 */
2531f6d57916SPaul Mackerras powersave_nap = 1;
2532804ece07SMichael Ellerman #endif /* CONFIG_PPC64 */
2533c6cb3b5fSBenjamin Herrenschmidt
2534f6d57916SPaul Mackerras /* Check for "mobile" machine */
2535f6d57916SPaul Mackerras if (model && (strncmp(model, "PowerBook", 9) == 0
2536f6d57916SPaul Mackerras || strncmp(model, "iBook", 5) == 0))
2537f6d57916SPaul Mackerras pmac_mb.board_flags |= PMAC_MB_MOBILE;
2538f6d57916SPaul Mackerras
2539f6d57916SPaul Mackerras
2540f6d57916SPaul Mackerras printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name);
254130686ba6SStephen Rothwell done:
254230686ba6SStephen Rothwell of_node_put(dt);
254330686ba6SStephen Rothwell return ret;
2544f6d57916SPaul Mackerras }
2545f6d57916SPaul Mackerras
2546f6d57916SPaul Mackerras /* Initialize the Core99 UniNorth host bridge and memory controller
2547f6d57916SPaul Mackerras */
probe_uninorth(void)2548f6d57916SPaul Mackerras static void __init probe_uninorth(void)
2549f6d57916SPaul Mackerras {
25502500763dSRob Herring struct resource res;
2551f6d57916SPaul Mackerras unsigned long actrl;
2552f6d57916SPaul Mackerras
2553f6d57916SPaul Mackerras /* Locate core99 Uni-N */
2554f6d57916SPaul Mackerras uninorth_node = of_find_node_by_name(NULL, "uni-n");
2555592a607bSBenjamin Herrenschmidt uninorth_maj = 1;
2556592a607bSBenjamin Herrenschmidt
2557f6d57916SPaul Mackerras /* Locate G5 u3 */
2558f6d57916SPaul Mackerras if (uninorth_node == NULL) {
2559f6d57916SPaul Mackerras uninorth_node = of_find_node_by_name(NULL, "u3");
25601beb6a7dSBenjamin Herrenschmidt uninorth_maj = 3;
25611beb6a7dSBenjamin Herrenschmidt }
25621beb6a7dSBenjamin Herrenschmidt /* Locate G5 u4 */
25631beb6a7dSBenjamin Herrenschmidt if (uninorth_node == NULL) {
25641beb6a7dSBenjamin Herrenschmidt uninorth_node = of_find_node_by_name(NULL, "u4");
25651beb6a7dSBenjamin Herrenschmidt uninorth_maj = 4;
2566f6d57916SPaul Mackerras }
2567592a607bSBenjamin Herrenschmidt if (uninorth_node == NULL) {
2568592a607bSBenjamin Herrenschmidt uninorth_maj = 0;
256951d3082fSBenjamin Herrenschmidt return;
2570592a607bSBenjamin Herrenschmidt }
257151d3082fSBenjamin Herrenschmidt
25722500763dSRob Herring if (of_address_to_resource(uninorth_node, 0, &res))
257351d3082fSBenjamin Herrenschmidt return;
25742500763dSRob Herring
25752500763dSRob Herring uninorth_base = ioremap(res.start, 0x40000);
257602a606c2Sroel kluin if (uninorth_base == NULL)
257702a606c2Sroel kluin return;
2578f6d57916SPaul Mackerras uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
257902a606c2Sroel kluin if (uninorth_maj == 3 || uninorth_maj == 4) {
25802500763dSRob Herring u3_ht_base = ioremap(res.start + U3_HT_CONFIG_BASE, 0x1000);
258102a606c2Sroel kluin if (u3_ht_base == NULL) {
258202a606c2Sroel kluin iounmap(uninorth_base);
258302a606c2Sroel kluin return;
258402a606c2Sroel kluin }
258502a606c2Sroel kluin }
2586f6d57916SPaul Mackerras
25871beb6a7dSBenjamin Herrenschmidt printk(KERN_INFO "Found %s memory controller & host bridge"
25881beb6a7dSBenjamin Herrenschmidt " @ 0x%08x revision: 0x%02x\n", uninorth_maj == 3 ? "U3" :
25891beb6a7dSBenjamin Herrenschmidt uninorth_maj == 4 ? "U4" : "UniNorth",
25902500763dSRob Herring (unsigned int)res.start, uninorth_rev);
2591f6d57916SPaul Mackerras printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base);
2592f6d57916SPaul Mackerras
2593f6d57916SPaul Mackerras /* Set the arbitrer QAck delay according to what Apple does
2594f6d57916SPaul Mackerras */
2595f6d57916SPaul Mackerras if (uninorth_rev < 0x11) {
2596f6d57916SPaul Mackerras actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK;
2597f6d57916SPaul Mackerras actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 :
25981beb6a7dSBenjamin Herrenschmidt UNI_N_ARB_CTRL_QACK_DELAY) <<
25991beb6a7dSBenjamin Herrenschmidt UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
2600f6d57916SPaul Mackerras UN_OUT(UNI_N_ARB_CTRL, actrl);
2601f6d57916SPaul Mackerras }
2602f6d57916SPaul Mackerras
2603f6d57916SPaul Mackerras /* Some more magic as done by them in recent MacOS X on UniNorth
2604f6d57916SPaul Mackerras * revs 1.5 to 2.O and Pangea. Seem to toggle the UniN Maxbus/PCI
2605f6d57916SPaul Mackerras * memory timeout
2606f6d57916SPaul Mackerras */
26071beb6a7dSBenjamin Herrenschmidt if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) ||
26081beb6a7dSBenjamin Herrenschmidt uninorth_rev == 0xc0)
2609f6d57916SPaul Mackerras UN_OUT(0x2160, UN_IN(0x2160) & 0x00ffffff);
2610f6d57916SPaul Mackerras }
2611f6d57916SPaul Mackerras
probe_one_macio(const char * name,const char * compat,int type)2612f6d57916SPaul Mackerras static void __init probe_one_macio(const char *name, const char *compat, int type)
2613f6d57916SPaul Mackerras {
2614f6d57916SPaul Mackerras struct device_node* node;
2615f6d57916SPaul Mackerras int i;
2616f6d57916SPaul Mackerras volatile u32 __iomem *base;
2617018a3d1dSJeremy Kerr const u32 *addrp, *revp;
261851d3082fSBenjamin Herrenschmidt phys_addr_t addr;
261951d3082fSBenjamin Herrenschmidt u64 size;
2620f6d57916SPaul Mackerras
26210aa8ff9bSDmitry Torokhov for_each_node_by_name(node, name) {
262251d3082fSBenjamin Herrenschmidt if (!compat)
262351d3082fSBenjamin Herrenschmidt break;
262455b61fecSStephen Rothwell if (of_device_is_compatible(node, compat))
2625f6d57916SPaul Mackerras break;
262651d3082fSBenjamin Herrenschmidt }
2627f6d57916SPaul Mackerras if (!node)
2628f6d57916SPaul Mackerras return;
2629f6d57916SPaul Mackerras for(i=0; i<MAX_MACIO_CHIPS; i++) {
2630f6d57916SPaul Mackerras if (!macio_chips[i].of_node)
2631f6d57916SPaul Mackerras break;
2632f6d57916SPaul Mackerras if (macio_chips[i].of_node == node)
2633d36337ceSLiang He goto out_put;
2634f6d57916SPaul Mackerras }
263551d3082fSBenjamin Herrenschmidt
2636f6d57916SPaul Mackerras if (i >= MAX_MACIO_CHIPS) {
2637f6d57916SPaul Mackerras printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n");
2638b7c670d6SRob Herring printk(KERN_ERR "pmac_feature: %pOF skipped\n", node);
2639d36337ceSLiang He goto out_put;
2640f6d57916SPaul Mackerras }
2641d2dd482bSBenjamin Herrenschmidt addrp = of_get_pci_address(node, 0, &size, NULL);
264251d3082fSBenjamin Herrenschmidt if (addrp == NULL) {
2643b7c670d6SRob Herring printk(KERN_ERR "pmac_feature: %pOF: can't find base !\n",
2644b7c670d6SRob Herring node);
2645d36337ceSLiang He goto out_put;
264651d3082fSBenjamin Herrenschmidt }
264751d3082fSBenjamin Herrenschmidt addr = of_translate_address(node, addrp);
264851d3082fSBenjamin Herrenschmidt if (addr == 0) {
2649b7c670d6SRob Herring printk(KERN_ERR "pmac_feature: %pOF, can't translate base !\n",
2650b7c670d6SRob Herring node);
2651d36337ceSLiang He goto out_put;
265251d3082fSBenjamin Herrenschmidt }
265351d3082fSBenjamin Herrenschmidt base = ioremap(addr, (unsigned long)size);
2654f6d57916SPaul Mackerras if (!base) {
2655b7c670d6SRob Herring printk(KERN_ERR "pmac_feature: %pOF, can't map mac-io chip !\n",
2656b7c670d6SRob Herring node);
2657d36337ceSLiang He goto out_put;
2658f6d57916SPaul Mackerras }
26591beb6a7dSBenjamin Herrenschmidt if (type == macio_keylargo || type == macio_keylargo2) {
2660e2eb6392SStephen Rothwell const u32 *did = of_get_property(node, "device-id", NULL);
2661f6d57916SPaul Mackerras if (*did == 0x00000025)
2662f6d57916SPaul Mackerras type = macio_pangea;
2663f6d57916SPaul Mackerras if (*did == 0x0000003e)
2664f6d57916SPaul Mackerras type = macio_intrepid;
26651beb6a7dSBenjamin Herrenschmidt if (*did == 0x0000004f)
26661beb6a7dSBenjamin Herrenschmidt type = macio_shasta;
2667f6d57916SPaul Mackerras }
2668f6d57916SPaul Mackerras macio_chips[i].of_node = node;
2669f6d57916SPaul Mackerras macio_chips[i].type = type;
2670f6d57916SPaul Mackerras macio_chips[i].base = base;
26711b3c83e6Sroel kluin macio_chips[i].flags = MACIO_FLAG_SCCA_ON | MACIO_FLAG_SCCB_ON;
2672f6d57916SPaul Mackerras macio_chips[i].name = macio_names[type];
2673e2eb6392SStephen Rothwell revp = of_get_property(node, "revision-id", NULL);
2674f6d57916SPaul Mackerras if (revp)
2675f6d57916SPaul Mackerras macio_chips[i].rev = *revp;
2676f6d57916SPaul Mackerras printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n",
2677f6d57916SPaul Mackerras macio_names[type], macio_chips[i].rev, macio_chips[i].base);
2678d36337ceSLiang He
2679d36337ceSLiang He return;
2680d36337ceSLiang He
2681d36337ceSLiang He out_put:
2682d36337ceSLiang He of_node_put(node);
2683f6d57916SPaul Mackerras }
2684f6d57916SPaul Mackerras
2685f6d57916SPaul Mackerras static int __init
probe_macios(void)2686f6d57916SPaul Mackerras probe_macios(void)
2687f6d57916SPaul Mackerras {
2688f6d57916SPaul Mackerras /* Warning, ordering is important */
2689f6d57916SPaul Mackerras probe_one_macio("gc", NULL, macio_grand_central);
2690f6d57916SPaul Mackerras probe_one_macio("ohare", NULL, macio_ohare);
2691f6d57916SPaul Mackerras probe_one_macio("pci106b,7", NULL, macio_ohareII);
2692f6d57916SPaul Mackerras probe_one_macio("mac-io", "keylargo", macio_keylargo);
2693f6d57916SPaul Mackerras probe_one_macio("mac-io", "paddington", macio_paddington);
2694f6d57916SPaul Mackerras probe_one_macio("mac-io", "gatwick", macio_gatwick);
2695f6d57916SPaul Mackerras probe_one_macio("mac-io", "heathrow", macio_heathrow);
2696f6d57916SPaul Mackerras probe_one_macio("mac-io", "K2-Keylargo", macio_keylargo2);
2697f6d57916SPaul Mackerras
2698f6d57916SPaul Mackerras /* Make sure the "main" macio chip appear first */
2699f6d57916SPaul Mackerras if (macio_chips[0].type == macio_gatwick
2700f6d57916SPaul Mackerras && macio_chips[1].type == macio_heathrow) {
2701f6d57916SPaul Mackerras struct macio_chip temp = macio_chips[0];
2702f6d57916SPaul Mackerras macio_chips[0] = macio_chips[1];
2703f6d57916SPaul Mackerras macio_chips[1] = temp;
2704f6d57916SPaul Mackerras }
2705f6d57916SPaul Mackerras if (macio_chips[0].type == macio_ohareII
2706f6d57916SPaul Mackerras && macio_chips[1].type == macio_ohare) {
2707f6d57916SPaul Mackerras struct macio_chip temp = macio_chips[0];
2708f6d57916SPaul Mackerras macio_chips[0] = macio_chips[1];
2709f6d57916SPaul Mackerras macio_chips[1] = temp;
2710f6d57916SPaul Mackerras }
2711f6d57916SPaul Mackerras macio_chips[0].lbus.index = 0;
2712f6d57916SPaul Mackerras macio_chips[1].lbus.index = 1;
2713f6d57916SPaul Mackerras
2714f6d57916SPaul Mackerras return (macio_chips[0].of_node == NULL) ? -ENODEV : 0;
2715f6d57916SPaul Mackerras }
2716f6d57916SPaul Mackerras
2717f6d57916SPaul Mackerras static void __init
initial_serial_shutdown(struct device_node * np)2718f6d57916SPaul Mackerras initial_serial_shutdown(struct device_node *np)
2719f6d57916SPaul Mackerras {
2720f6d57916SPaul Mackerras int len;
2721018a3d1dSJeremy Kerr const struct slot_names_prop {
2722f6d57916SPaul Mackerras int count;
2723f6d57916SPaul Mackerras char name[1];
2724f6d57916SPaul Mackerras } *slots;
2725018a3d1dSJeremy Kerr const char *conn;
2726f6d57916SPaul Mackerras int port_type = PMAC_SCC_ASYNC;
2727f6d57916SPaul Mackerras int modem = 0;
2728f6d57916SPaul Mackerras
2729e2eb6392SStephen Rothwell slots = of_get_property(np, "slot-names", &len);
2730e2eb6392SStephen Rothwell conn = of_get_property(np, "AAPL,connector", &len);
2731f6d57916SPaul Mackerras if (conn && (strcmp(conn, "infrared") == 0))
2732f6d57916SPaul Mackerras port_type = PMAC_SCC_IRDA;
273355b61fecSStephen Rothwell else if (of_device_is_compatible(np, "cobalt"))
2734f6d57916SPaul Mackerras modem = 1;
2735f6d57916SPaul Mackerras else if (slots && slots->count > 0) {
2736f6d57916SPaul Mackerras if (strcmp(slots->name, "IrDA") == 0)
2737f6d57916SPaul Mackerras port_type = PMAC_SCC_IRDA;
2738f6d57916SPaul Mackerras else if (strcmp(slots->name, "Modem") == 0)
2739f6d57916SPaul Mackerras modem = 1;
2740f6d57916SPaul Mackerras }
2741f6d57916SPaul Mackerras if (modem)
2742f6d57916SPaul Mackerras pmac_call_feature(PMAC_FTR_MODEM_ENABLE, np, 0, 0);
2743f6d57916SPaul Mackerras pmac_call_feature(PMAC_FTR_SCC_ENABLE, np, port_type, 0);
2744f6d57916SPaul Mackerras }
2745f6d57916SPaul Mackerras
2746f6d57916SPaul Mackerras static void __init
set_initial_features(void)2747f6d57916SPaul Mackerras set_initial_features(void)
2748f6d57916SPaul Mackerras {
2749f6d57916SPaul Mackerras struct device_node *np;
2750f6d57916SPaul Mackerras
2751f6d57916SPaul Mackerras /* That hack appears to be necessary for some StarMax motherboards
2752f6d57916SPaul Mackerras * but I'm not too sure it was audited for side-effects on other
2753f6d57916SPaul Mackerras * ohare based machines...
2754f6d57916SPaul Mackerras * Since I still have difficulties figuring the right way to
2755446957baSAdam Buchbinder * differentiate them all and since that hack was there for a long
2756f6d57916SPaul Mackerras * time, I'll keep it around
2757f6d57916SPaul Mackerras */
275830686ba6SStephen Rothwell if (macio_chips[0].type == macio_ohare) {
2759f6d57916SPaul Mackerras struct macio_chip *macio = &macio_chips[0];
276030686ba6SStephen Rothwell np = of_find_node_by_name(NULL, "via-pmu");
276130686ba6SStephen Rothwell if (np)
2762f6d57916SPaul Mackerras MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
276330686ba6SStephen Rothwell else
276430686ba6SStephen Rothwell MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES);
276530686ba6SStephen Rothwell of_node_put(np);
2766f6d57916SPaul Mackerras } else if (macio_chips[1].type == macio_ohare) {
2767f6d57916SPaul Mackerras struct macio_chip *macio = &macio_chips[1];
2768f6d57916SPaul Mackerras MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
2769f6d57916SPaul Mackerras }
2770f6d57916SPaul Mackerras
2771804ece07SMichael Ellerman #ifdef CONFIG_PPC64
27721beb6a7dSBenjamin Herrenschmidt if (macio_chips[0].type == macio_keylargo2 ||
27731beb6a7dSBenjamin Herrenschmidt macio_chips[0].type == macio_shasta) {
2774f6d57916SPaul Mackerras #ifndef CONFIG_SMP
2775f6d57916SPaul Mackerras /* On SMP machines running UP, we have the second CPU eating
2776f6d57916SPaul Mackerras * bus cycles. We need to take it off the bus. This is done
2777f6d57916SPaul Mackerras * from pmac_smp for SMP kernels running on one CPU
2778f6d57916SPaul Mackerras */
2779f6d57916SPaul Mackerras np = of_find_node_by_type(NULL, "cpu");
2780f6d57916SPaul Mackerras if (np != NULL)
2781f6d57916SPaul Mackerras np = of_find_node_by_type(np, "cpu");
2782f6d57916SPaul Mackerras if (np != NULL) {
2783f6d57916SPaul Mackerras g5_phy_disable_cpu1();
2784f6d57916SPaul Mackerras of_node_put(np);
2785f6d57916SPaul Mackerras }
2786f6d57916SPaul Mackerras #endif /* CONFIG_SMP */
2787f6d57916SPaul Mackerras /* Enable GMAC for now for PCI probing. It will be disabled
2788f6d57916SPaul Mackerras * later on after PCI probe
2789f6d57916SPaul Mackerras */
2790ccdb8ed3SGrant Likely for_each_node_by_name(np, "ethernet")
279155b61fecSStephen Rothwell if (of_device_is_compatible(np, "K2-GMAC"))
2792f6d57916SPaul Mackerras g5_gmac_enable(np, 0, 1);
2793f6d57916SPaul Mackerras
2794f6d57916SPaul Mackerras /* Enable FW before PCI probe. Will be disabled later on
2795f6d57916SPaul Mackerras * Note: We should have a batter way to check that we are
2796f6d57916SPaul Mackerras * dealing with uninorth internal cell and not a PCI cell
2797f6d57916SPaul Mackerras * on the external PCI. The code below works though.
2798f6d57916SPaul Mackerras */
2799ccdb8ed3SGrant Likely for_each_node_by_name(np, "firewire") {
280055b61fecSStephen Rothwell if (of_device_is_compatible(np, "pci106b,5811")) {
2801f6d57916SPaul Mackerras macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
2802f6d57916SPaul Mackerras g5_fw_enable(np, 0, 1);
2803f6d57916SPaul Mackerras }
2804f6d57916SPaul Mackerras }
2805f6d57916SPaul Mackerras }
2806804ece07SMichael Ellerman #else /* CONFIG_PPC64 */
2807f6d57916SPaul Mackerras
2808f6d57916SPaul Mackerras if (macio_chips[0].type == macio_keylargo ||
2809f6d57916SPaul Mackerras macio_chips[0].type == macio_pangea ||
2810f6d57916SPaul Mackerras macio_chips[0].type == macio_intrepid) {
2811f6d57916SPaul Mackerras /* Enable GMAC for now for PCI probing. It will be disabled
2812f6d57916SPaul Mackerras * later on after PCI probe
2813f6d57916SPaul Mackerras */
2814ccdb8ed3SGrant Likely for_each_node_by_name(np, "ethernet") {
2815f6d57916SPaul Mackerras if (np->parent
281655b61fecSStephen Rothwell && of_device_is_compatible(np->parent, "uni-north")
281755b61fecSStephen Rothwell && of_device_is_compatible(np, "gmac"))
2818f6d57916SPaul Mackerras core99_gmac_enable(np, 0, 1);
2819f6d57916SPaul Mackerras }
2820f6d57916SPaul Mackerras
2821f6d57916SPaul Mackerras /* Enable FW before PCI probe. Will be disabled later on
2822f6d57916SPaul Mackerras * Note: We should have a batter way to check that we are
2823f6d57916SPaul Mackerras * dealing with uninorth internal cell and not a PCI cell
2824f6d57916SPaul Mackerras * on the external PCI. The code below works though.
2825f6d57916SPaul Mackerras */
2826ccdb8ed3SGrant Likely for_each_node_by_name(np, "firewire") {
2827f6d57916SPaul Mackerras if (np->parent
282855b61fecSStephen Rothwell && of_device_is_compatible(np->parent, "uni-north")
282955b61fecSStephen Rothwell && (of_device_is_compatible(np, "pci106b,18") ||
283055b61fecSStephen Rothwell of_device_is_compatible(np, "pci106b,30") ||
283155b61fecSStephen Rothwell of_device_is_compatible(np, "pci11c1,5811"))) {
2832f6d57916SPaul Mackerras macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
2833f6d57916SPaul Mackerras core99_firewire_enable(np, 0, 1);
2834f6d57916SPaul Mackerras }
2835f6d57916SPaul Mackerras }
2836f6d57916SPaul Mackerras
2837f6d57916SPaul Mackerras /* Enable ATA-100 before PCI probe. */
2838ccdb8ed3SGrant Likely for_each_node_by_name(np, "ata-6") {
2839f6d57916SPaul Mackerras if (np->parent
284055b61fecSStephen Rothwell && of_device_is_compatible(np->parent, "uni-north")
284155b61fecSStephen Rothwell && of_device_is_compatible(np, "kauai-ata")) {
2842f6d57916SPaul Mackerras core99_ata100_enable(np, 1);
2843f6d57916SPaul Mackerras }
2844f6d57916SPaul Mackerras }
2845f6d57916SPaul Mackerras
2846f6d57916SPaul Mackerras /* Switch airport off */
284730686ba6SStephen Rothwell for_each_node_by_name(np, "radio") {
28485fba610eSJulia Lawall if (np->parent == macio_chips[0].of_node) {
2849f6d57916SPaul Mackerras macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON;
2850f6d57916SPaul Mackerras core99_airport_enable(np, 0, 0);
2851f6d57916SPaul Mackerras }
2852f6d57916SPaul Mackerras }
2853f6d57916SPaul Mackerras }
2854f6d57916SPaul Mackerras
2855f6d57916SPaul Mackerras /* On all machines that support sound PM, switch sound off */
2856f6d57916SPaul Mackerras if (macio_chips[0].of_node)
2857f6d57916SPaul Mackerras pmac_do_feature_call(PMAC_FTR_SOUND_CHIP_ENABLE,
2858f6d57916SPaul Mackerras macio_chips[0].of_node, 0, 0);
2859f6d57916SPaul Mackerras
2860f6d57916SPaul Mackerras /* While on some desktop G3s, we turn it back on */
2861f6d57916SPaul Mackerras if (macio_chips[0].of_node && macio_chips[0].type == macio_heathrow
2862f6d57916SPaul Mackerras && (pmac_mb.model_id == PMAC_TYPE_GOSSAMER ||
2863f6d57916SPaul Mackerras pmac_mb.model_id == PMAC_TYPE_SILK)) {
2864f6d57916SPaul Mackerras struct macio_chip *macio = &macio_chips[0];
2865f6d57916SPaul Mackerras MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
2866f6d57916SPaul Mackerras MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
2867f6d57916SPaul Mackerras }
2868f6d57916SPaul Mackerras
2869804ece07SMichael Ellerman #endif /* CONFIG_PPC64 */
2870f6d57916SPaul Mackerras
2871f6d57916SPaul Mackerras /* On all machines, switch modem & serial ports off */
287230686ba6SStephen Rothwell for_each_node_by_name(np, "ch-a")
2873f6d57916SPaul Mackerras initial_serial_shutdown(np);
287430686ba6SStephen Rothwell for_each_node_by_name(np, "ch-b")
2875f6d57916SPaul Mackerras initial_serial_shutdown(np);
2876f6d57916SPaul Mackerras }
2877f6d57916SPaul Mackerras
2878f6d57916SPaul Mackerras void __init
pmac_feature_init(void)2879f6d57916SPaul Mackerras pmac_feature_init(void)
2880f6d57916SPaul Mackerras {
2881f6d57916SPaul Mackerras /* Detect the UniNorth memory controller */
2882f6d57916SPaul Mackerras probe_uninorth();
2883f6d57916SPaul Mackerras
2884f6d57916SPaul Mackerras /* Probe mac-io controllers */
2885f6d57916SPaul Mackerras if (probe_macios()) {
2886f6d57916SPaul Mackerras printk(KERN_WARNING "No mac-io chip found\n");
2887f6d57916SPaul Mackerras return;
2888f6d57916SPaul Mackerras }
2889f6d57916SPaul Mackerras
2890f6d57916SPaul Mackerras /* Probe machine type */
2891f6d57916SPaul Mackerras if (probe_motherboard())
2892f6d57916SPaul Mackerras printk(KERN_WARNING "Unknown PowerMac !\n");
2893f6d57916SPaul Mackerras
2894f6d57916SPaul Mackerras /* Set some initial features (turn off some chips that will
2895f6d57916SPaul Mackerras * be later turned on)
2896f6d57916SPaul Mackerras */
2897f6d57916SPaul Mackerras set_initial_features();
2898f6d57916SPaul Mackerras }
2899f6d57916SPaul Mackerras
2900f6d57916SPaul Mackerras #if 0
2901f6d57916SPaul Mackerras static void dump_HT_speeds(char *name, u32 cfg, u32 frq)
2902f6d57916SPaul Mackerras {
2903f6d57916SPaul Mackerras int freqs[16] = { 200,300,400,500,600,800,1000,0,0,0,0,0,0,0,0,0 };
2904f6d57916SPaul Mackerras int bits[8] = { 8,16,0,32,2,4,0,0 };
2905f6d57916SPaul Mackerras int freq = (frq >> 8) & 0xf;
2906f6d57916SPaul Mackerras
2907f6d57916SPaul Mackerras if (freqs[freq] == 0)
2908f6d57916SPaul Mackerras printk("%s: Unknown HT link frequency %x\n", name, freq);
2909f6d57916SPaul Mackerras else
2910f6d57916SPaul Mackerras printk("%s: %d MHz on main link, (%d in / %d out) bits width\n",
2911f6d57916SPaul Mackerras name, freqs[freq],
2912f6d57916SPaul Mackerras bits[(cfg >> 28) & 0x7], bits[(cfg >> 24) & 0x7]);
2913f6d57916SPaul Mackerras }
2914f6d57916SPaul Mackerras
2915f6d57916SPaul Mackerras void __init pmac_check_ht_link(void)
2916f6d57916SPaul Mackerras {
2917f6d57916SPaul Mackerras u32 ufreq, freq, ucfg, cfg;
2918f6d57916SPaul Mackerras struct device_node *pcix_node;
2919f6d57916SPaul Mackerras u8 px_bus, px_devfn;
2920f6d57916SPaul Mackerras struct pci_controller *px_hose;
2921f6d57916SPaul Mackerras
29225b9ca526SBenjamin Herrenschmidt (void)in_be32(u3_ht_base + U3_HT_LINK_COMMAND);
29235b9ca526SBenjamin Herrenschmidt ucfg = cfg = in_be32(u3_ht_base + U3_HT_LINK_CONFIG);
29245b9ca526SBenjamin Herrenschmidt ufreq = freq = in_be32(u3_ht_base + U3_HT_LINK_FREQ);
2925f6d57916SPaul Mackerras dump_HT_speeds("U3 HyperTransport", cfg, freq);
2926f6d57916SPaul Mackerras
2927f6d57916SPaul Mackerras pcix_node = of_find_compatible_node(NULL, "pci", "pci-x");
2928f6d57916SPaul Mackerras if (pcix_node == NULL) {
2929f6d57916SPaul Mackerras printk("No PCI-X bridge found\n");
2930f6d57916SPaul Mackerras return;
2931f6d57916SPaul Mackerras }
2932f6d57916SPaul Mackerras if (pci_device_from_OF_node(pcix_node, &px_bus, &px_devfn) != 0) {
2933f6d57916SPaul Mackerras printk("PCI-X bridge found but not matched to pci\n");
2934f6d57916SPaul Mackerras return;
2935f6d57916SPaul Mackerras }
2936f6d57916SPaul Mackerras px_hose = pci_find_hose_for_OF_device(pcix_node);
2937f6d57916SPaul Mackerras if (px_hose == NULL) {
2938f6d57916SPaul Mackerras printk("PCI-X bridge found but not matched to host\n");
2939f6d57916SPaul Mackerras return;
2940f6d57916SPaul Mackerras }
2941f6d57916SPaul Mackerras early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg);
2942f6d57916SPaul Mackerras early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq);
2943f6d57916SPaul Mackerras dump_HT_speeds("PCI-X HT Uplink", cfg, freq);
2944f6d57916SPaul Mackerras early_read_config_dword(px_hose, px_bus, px_devfn, 0xc8, &cfg);
2945f6d57916SPaul Mackerras early_read_config_dword(px_hose, px_bus, px_devfn, 0xd0, &freq);
2946f6d57916SPaul Mackerras dump_HT_speeds("PCI-X HT Downlink", cfg, freq);
2947f6d57916SPaul Mackerras }
294835499c01SPaul Mackerras #endif /* 0 */
2949f6d57916SPaul Mackerras
2950f6d57916SPaul Mackerras /*
2951f6d57916SPaul Mackerras * Early video resume hook
2952f6d57916SPaul Mackerras */
2953f6d57916SPaul Mackerras
2954f6d57916SPaul Mackerras static void (*pmac_early_vresume_proc)(void *data);
2955f6d57916SPaul Mackerras static void *pmac_early_vresume_data;
2956f6d57916SPaul Mackerras
pmac_set_early_video_resume(void (* proc)(void * data),void * data)2957f6d57916SPaul Mackerras void pmac_set_early_video_resume(void (*proc)(void *data), void *data)
2958f6d57916SPaul Mackerras {
2959e8222502SBenjamin Herrenschmidt if (!machine_is(powermac))
2960f6d57916SPaul Mackerras return;
2961f6d57916SPaul Mackerras preempt_disable();
2962f6d57916SPaul Mackerras pmac_early_vresume_proc = proc;
2963f6d57916SPaul Mackerras pmac_early_vresume_data = data;
2964f6d57916SPaul Mackerras preempt_enable();
2965f6d57916SPaul Mackerras }
2966f6d57916SPaul Mackerras EXPORT_SYMBOL(pmac_set_early_video_resume);
2967f6d57916SPaul Mackerras
pmac_call_early_video_resume(void)2968f6d57916SPaul Mackerras void pmac_call_early_video_resume(void)
2969f6d57916SPaul Mackerras {
2970f6d57916SPaul Mackerras if (pmac_early_vresume_proc)
2971f6d57916SPaul Mackerras pmac_early_vresume_proc(pmac_early_vresume_data);
2972f6d57916SPaul Mackerras }
2973f6d57916SPaul Mackerras
2974f6d57916SPaul Mackerras /*
2975f6d57916SPaul Mackerras * AGP related suspend/resume code
2976f6d57916SPaul Mackerras */
2977f6d57916SPaul Mackerras
2978f6d57916SPaul Mackerras static struct pci_dev *pmac_agp_bridge;
2979f6d57916SPaul Mackerras static int (*pmac_agp_suspend)(struct pci_dev *bridge);
2980f6d57916SPaul Mackerras static int (*pmac_agp_resume)(struct pci_dev *bridge);
2981f6d57916SPaul Mackerras
pmac_register_agp_pm(struct pci_dev * bridge,int (* suspend)(struct pci_dev * bridge),int (* resume)(struct pci_dev * bridge))2982f6d57916SPaul Mackerras void pmac_register_agp_pm(struct pci_dev *bridge,
2983f6d57916SPaul Mackerras int (*suspend)(struct pci_dev *bridge),
2984f6d57916SPaul Mackerras int (*resume)(struct pci_dev *bridge))
2985f6d57916SPaul Mackerras {
2986f6d57916SPaul Mackerras if (suspend || resume) {
2987f6d57916SPaul Mackerras pmac_agp_bridge = bridge;
2988f6d57916SPaul Mackerras pmac_agp_suspend = suspend;
2989f6d57916SPaul Mackerras pmac_agp_resume = resume;
2990f6d57916SPaul Mackerras return;
2991f6d57916SPaul Mackerras }
2992f6d57916SPaul Mackerras if (bridge != pmac_agp_bridge)
2993f6d57916SPaul Mackerras return;
2994f6d57916SPaul Mackerras pmac_agp_suspend = pmac_agp_resume = NULL;
2995f6d57916SPaul Mackerras return;
2996f6d57916SPaul Mackerras }
2997f6d57916SPaul Mackerras EXPORT_SYMBOL(pmac_register_agp_pm);
2998f6d57916SPaul Mackerras
pmac_suspend_agp_for_card(struct pci_dev * dev)2999f6d57916SPaul Mackerras void pmac_suspend_agp_for_card(struct pci_dev *dev)
3000f6d57916SPaul Mackerras {
3001f6d57916SPaul Mackerras if (pmac_agp_bridge == NULL || pmac_agp_suspend == NULL)
3002f6d57916SPaul Mackerras return;
3003f6d57916SPaul Mackerras if (pmac_agp_bridge->bus != dev->bus)
3004f6d57916SPaul Mackerras return;
3005f6d57916SPaul Mackerras pmac_agp_suspend(pmac_agp_bridge);
3006f6d57916SPaul Mackerras }
3007f6d57916SPaul Mackerras EXPORT_SYMBOL(pmac_suspend_agp_for_card);
3008f6d57916SPaul Mackerras
pmac_resume_agp_for_card(struct pci_dev * dev)3009f6d57916SPaul Mackerras void pmac_resume_agp_for_card(struct pci_dev *dev)
3010f6d57916SPaul Mackerras {
3011f6d57916SPaul Mackerras if (pmac_agp_bridge == NULL || pmac_agp_resume == NULL)
3012f6d57916SPaul Mackerras return;
3013f6d57916SPaul Mackerras if (pmac_agp_bridge->bus != dev->bus)
3014f6d57916SPaul Mackerras return;
3015f6d57916SPaul Mackerras pmac_agp_resume(pmac_agp_bridge);
3016f6d57916SPaul Mackerras }
3017f6d57916SPaul Mackerras EXPORT_SYMBOL(pmac_resume_agp_for_card);
3018592a607bSBenjamin Herrenschmidt
pmac_get_uninorth_variant(void)3019592a607bSBenjamin Herrenschmidt int pmac_get_uninorth_variant(void)
3020592a607bSBenjamin Herrenschmidt {
3021592a607bSBenjamin Herrenschmidt return uninorth_maj;
3022592a607bSBenjamin Herrenschmidt }
3023