ppc64: Simplify secondary CPU startup on powermacs
[linux-2.6/x86.git] / arch / ppc64 / kernel / pmac_feature.c
blob26075f11db77caa63ec73eef2c2cc8e293be5978
1 /*
2 * arch/ppc/platforms/pmac_feature.c
4 * Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au)
5 * Ben. Herrenschmidt (benh@kernel.crashing.org)
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
12 * TODO:
14 * - Replace mdelay with some schedule loop if possible
15 * - Shorten some obfuscated delays on some routines (like modem
16 * power)
17 * - Refcount some clocks (see darwin)
18 * - Split split split...
21 #include <linux/config.h>
22 #include <linux/types.h>
23 #include <linux/init.h>
24 #include <linux/delay.h>
25 #include <linux/kernel.h>
26 #include <linux/sched.h>
27 #include <linux/spinlock.h>
28 #include <linux/adb.h>
29 #include <linux/pmu.h>
30 #include <linux/ioport.h>
31 #include <linux/pci.h>
32 #include <asm/sections.h>
33 #include <asm/errno.h>
34 #include <asm/keylargo.h>
35 #include <asm/uninorth.h>
36 #include <asm/io.h>
37 #include <asm/prom.h>
38 #include <asm/machdep.h>
39 #include <asm/pmac_feature.h>
40 #include <asm/dbdma.h>
41 #include <asm/pci-bridge.h>
42 #include <asm/pmac_low_i2c.h>
44 #undef DEBUG_FEATURE
46 #ifdef DEBUG_FEATURE
47 #define DBG(fmt...) printk(KERN_DEBUG fmt)
48 #else
49 #define DBG(fmt...)
50 #endif
53 * We use a single global lock to protect accesses. Each driver has
54 * to take care of its own locking
56 static DEFINE_SPINLOCK(feature_lock);
58 #define LOCK(flags) spin_lock_irqsave(&feature_lock, flags);
59 #define UNLOCK(flags) spin_unlock_irqrestore(&feature_lock, flags);
63 * Instance of some macio stuffs
65 struct macio_chip macio_chips[MAX_MACIO_CHIPS] ;
67 struct macio_chip* macio_find(struct device_node* child, int type)
69 while(child) {
70 int i;
72 for (i=0; i < MAX_MACIO_CHIPS && macio_chips[i].of_node; i++)
73 if (child == macio_chips[i].of_node &&
74 (!type || macio_chips[i].type == type))
75 return &macio_chips[i];
76 child = child->parent;
78 return NULL;
80 EXPORT_SYMBOL_GPL(macio_find);
82 static const char* macio_names[] =
84 "Unknown",
85 "Grand Central",
86 "OHare",
87 "OHareII",
88 "Heathrow",
89 "Gatwick",
90 "Paddington",
91 "Keylargo",
92 "Pangea",
93 "Intrepid",
94 "K2"
100 * Uninorth reg. access. Note that Uni-N regs are big endian
103 #define UN_REG(r) (uninorth_base + ((r) >> 2))
104 #define UN_IN(r) (in_be32(UN_REG(r)))
105 #define UN_OUT(r,v) (out_be32(UN_REG(r), (v)))
106 #define UN_BIS(r,v) (UN_OUT((r), UN_IN(r) | (v)))
107 #define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v)))
109 static struct device_node* uninorth_node;
110 static u32* uninorth_base;
111 static u32 uninorth_rev;
112 static void *u3_ht;
114 extern struct device_node *k2_skiplist[2];
117 * For each motherboard family, we have a table of functions pointers
118 * that handle the various features.
121 typedef long (*feature_call)(struct device_node* node, long param, long value);
123 struct feature_table_entry {
124 unsigned int selector;
125 feature_call function;
128 struct pmac_mb_def
130 const char* model_string;
131 const char* model_name;
132 int model_id;
133 struct feature_table_entry* features;
134 unsigned long board_flags;
136 static struct pmac_mb_def pmac_mb;
139 * Here are the chip specific feature functions
143 static long g5_read_gpio(struct device_node* node, long param, long value)
145 struct macio_chip* macio = &macio_chips[0];
147 return MACIO_IN8(param);
151 static long g5_write_gpio(struct device_node* node, long param, long value)
153 struct macio_chip* macio = &macio_chips[0];
155 MACIO_OUT8(param, (u8)(value & 0xff));
156 return 0;
159 static long g5_gmac_enable(struct device_node* node, long param, long value)
161 struct macio_chip* macio = &macio_chips[0];
162 unsigned long flags;
164 if (node == NULL)
165 return -ENODEV;
167 LOCK(flags);
168 if (value) {
169 MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE);
170 mb();
171 k2_skiplist[0] = NULL;
172 } else {
173 k2_skiplist[0] = node;
174 mb();
175 MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE);
178 UNLOCK(flags);
179 mdelay(1);
181 return 0;
184 static long g5_fw_enable(struct device_node* node, long param, long value)
186 struct macio_chip* macio = &macio_chips[0];
187 unsigned long flags;
189 if (node == NULL)
190 return -ENODEV;
192 LOCK(flags);
193 if (value) {
194 MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE);
195 mb();
196 k2_skiplist[1] = NULL;
197 } else {
198 k2_skiplist[1] = node;
199 mb();
200 MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE);
203 UNLOCK(flags);
204 mdelay(1);
206 return 0;
209 static long g5_mpic_enable(struct device_node* node, long param, long value)
211 unsigned long flags;
213 if (node->parent == NULL || strcmp(node->parent->name, "u3"))
214 return 0;
216 LOCK(flags);
217 UN_BIS(U3_TOGGLE_REG, U3_MPIC_RESET | U3_MPIC_OUTPUT_ENABLE);
218 UNLOCK(flags);
220 return 0;
223 static long g5_eth_phy_reset(struct device_node* node, long param, long value)
225 struct macio_chip* macio = &macio_chips[0];
226 struct device_node *phy;
227 int need_reset;
230 * We must not reset the combo PHYs, only the BCM5221 found in
231 * the iMac G5.
233 phy = of_get_next_child(node, NULL);
234 if (!phy)
235 return -ENODEV;
236 need_reset = device_is_compatible(phy, "B5221");
237 of_node_put(phy);
238 if (!need_reset)
239 return 0;
241 /* PHY reset is GPIO 29, not in device-tree unfortunately */
242 MACIO_OUT8(K2_GPIO_EXTINT_0 + 29,
243 KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
244 /* Thankfully, this is now always called at a time when we can
245 * schedule by sungem.
247 msleep(10);
248 MACIO_OUT8(K2_GPIO_EXTINT_0 + 29, 0);
250 return 0;
253 static long g5_i2s_enable(struct device_node *node, long param, long value)
255 /* Very crude implementation for now */
256 struct macio_chip* macio = &macio_chips[0];
257 unsigned long flags;
259 if (value == 0)
260 return 0; /* don't disable yet */
262 LOCK(flags);
263 MACIO_BIS(KEYLARGO_FCR3, KL3_CLK45_ENABLE | KL3_CLK49_ENABLE |
264 KL3_I2S0_CLK18_ENABLE);
265 udelay(10);
266 MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_I2S0_CELL_ENABLE |
267 K2_FCR1_I2S0_CLK_ENABLE_BIT | K2_FCR1_I2S0_ENABLE);
268 udelay(10);
269 MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_I2S0_RESET);
270 UNLOCK(flags);
271 udelay(10);
273 return 0;
277 #ifdef CONFIG_SMP
278 static long g5_reset_cpu(struct device_node* node, long param, long value)
280 unsigned int reset_io = 0;
281 unsigned long flags;
282 struct macio_chip* macio;
283 struct device_node* np;
285 macio = &macio_chips[0];
286 if (macio->type != macio_keylargo2)
287 return -ENODEV;
289 np = find_path_device("/cpus");
290 if (np == NULL)
291 return -ENODEV;
292 for (np = np->child; np != NULL; np = np->sibling) {
293 u32* num = (u32 *)get_property(np, "reg", NULL);
294 u32* rst = (u32 *)get_property(np, "soft-reset", NULL);
295 if (num == NULL || rst == NULL)
296 continue;
297 if (param == *num) {
298 reset_io = *rst;
299 break;
302 if (np == NULL || reset_io == 0)
303 return -ENODEV;
305 LOCK(flags);
306 MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);
307 (void)MACIO_IN8(reset_io);
308 udelay(1);
309 MACIO_OUT8(reset_io, 0);
310 (void)MACIO_IN8(reset_io);
311 UNLOCK(flags);
313 return 0;
315 #endif /* CONFIG_SMP */
318 * This can be called from pmac_smp so isn't static
320 * This takes the second CPU off the bus on dual CPU machines
321 * running UP
323 void g5_phy_disable_cpu1(void)
325 UN_OUT(U3_API_PHY_CONFIG_1, 0);
328 static long generic_get_mb_info(struct device_node* node, long param, long value)
330 switch(param) {
331 case PMAC_MB_INFO_MODEL:
332 return pmac_mb.model_id;
333 case PMAC_MB_INFO_FLAGS:
334 return pmac_mb.board_flags;
335 case PMAC_MB_INFO_NAME:
336 /* hack hack hack... but should work */
337 *((const char **)value) = pmac_mb.model_name;
338 return 0;
340 return -EINVAL;
345 * Table definitions
348 /* Used on any machine
350 static struct feature_table_entry any_features[] = {
351 { PMAC_FTR_GET_MB_INFO, generic_get_mb_info },
352 { 0, NULL }
355 /* G5 features
357 static struct feature_table_entry g5_features[] = {
358 { PMAC_FTR_GMAC_ENABLE, g5_gmac_enable },
359 { PMAC_FTR_1394_ENABLE, g5_fw_enable },
360 { PMAC_FTR_ENABLE_MPIC, g5_mpic_enable },
361 { PMAC_FTR_READ_GPIO, g5_read_gpio },
362 { PMAC_FTR_WRITE_GPIO, g5_write_gpio },
363 { PMAC_FTR_GMAC_PHY_RESET, g5_eth_phy_reset },
364 { PMAC_FTR_SOUND_CHIP_ENABLE, g5_i2s_enable },
365 #ifdef CONFIG_SMP
366 { PMAC_FTR_RESET_CPU, g5_reset_cpu },
367 #endif /* CONFIG_SMP */
368 { 0, NULL }
371 static struct pmac_mb_def pmac_mb_defs[] = {
372 { "PowerMac7,2", "PowerMac G5",
373 PMAC_TYPE_POWERMAC_G5, g5_features,
376 { "PowerMac7,3", "PowerMac G5",
377 PMAC_TYPE_POWERMAC_G5, g5_features,
380 { "PowerMac8,1", "iMac G5",
381 PMAC_TYPE_IMAC_G5, g5_features,
384 { "PowerMac9,1", "PowerMac G5",
385 PMAC_TYPE_POWERMAC_G5_U3L, g5_features,
388 { "RackMac3,1", "XServe G5",
389 PMAC_TYPE_XSERVE_G5, g5_features,
395 * The toplevel feature_call callback
397 long pmac_do_feature_call(unsigned int selector, ...)
399 struct device_node* node;
400 long param, value;
401 int i;
402 feature_call func = NULL;
403 va_list args;
405 if (pmac_mb.features)
406 for (i=0; pmac_mb.features[i].function; i++)
407 if (pmac_mb.features[i].selector == selector) {
408 func = pmac_mb.features[i].function;
409 break;
411 if (!func)
412 for (i=0; any_features[i].function; i++)
413 if (any_features[i].selector == selector) {
414 func = any_features[i].function;
415 break;
417 if (!func)
418 return -ENODEV;
420 va_start(args, selector);
421 node = (struct device_node*)va_arg(args, void*);
422 param = va_arg(args, long);
423 value = va_arg(args, long);
424 va_end(args);
426 return func(node, param, value);
429 static int __init probe_motherboard(void)
431 int i;
432 struct macio_chip* macio = &macio_chips[0];
433 const char* model = NULL;
434 struct device_node *dt;
436 /* Lookup known motherboard type in device-tree. First try an
437 * exact match on the "model" property, then try a "compatible"
438 * match is none is found.
440 dt = find_devices("device-tree");
441 if (dt != NULL)
442 model = (const char *) get_property(dt, "model", NULL);
443 for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
444 if (strcmp(model, pmac_mb_defs[i].model_string) == 0) {
445 pmac_mb = pmac_mb_defs[i];
446 goto found;
449 for(i=0; i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
450 if (machine_is_compatible(pmac_mb_defs[i].model_string)) {
451 pmac_mb = pmac_mb_defs[i];
452 goto found;
456 /* Fallback to selection depending on mac-io chip type */
457 switch(macio->type) {
458 case macio_keylargo2:
459 pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2;
460 pmac_mb.model_name = "Unknown K2-based";
461 pmac_mb.features = g5_features;
463 default:
464 return -ENODEV;
466 found:
467 /* Check for "mobile" machine */
468 if (model && (strncmp(model, "PowerBook", 9) == 0
469 || strncmp(model, "iBook", 5) == 0))
470 pmac_mb.board_flags |= PMAC_MB_MOBILE;
473 printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name);
474 return 0;
477 /* Initialize the Core99 UniNorth host bridge and memory controller
479 static void __init probe_uninorth(void)
481 uninorth_node = of_find_node_by_name(NULL, "u3");
482 if (uninorth_node && uninorth_node->n_addrs > 0) {
483 /* Small hack until I figure out if parsing in prom.c is correct. I should
484 * get rid of those pre-parsed junk anyway
486 unsigned long address = uninorth_node->addrs[0].address;
487 uninorth_base = ioremap(address, 0x40000);
488 uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
489 u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000);
490 } else
491 uninorth_node = NULL;
493 if (!uninorth_node)
494 return;
496 printk(KERN_INFO "Found U3 memory controller & host bridge, revision: %d\n",
497 uninorth_rev);
498 printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base);
502 static void __init probe_one_macio(const char* name, const char* compat, int type)
504 struct device_node* node;
505 int i;
506 volatile u32* base;
507 u32* revp;
509 node = find_devices(name);
510 if (!node || !node->n_addrs)
511 return;
512 if (compat)
513 do {
514 if (device_is_compatible(node, compat))
515 break;
516 node = node->next;
517 } while (node);
518 if (!node)
519 return;
520 for(i=0; i<MAX_MACIO_CHIPS; i++) {
521 if (!macio_chips[i].of_node)
522 break;
523 if (macio_chips[i].of_node == node)
524 return;
526 if (i >= MAX_MACIO_CHIPS) {
527 printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n");
528 printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name);
529 return;
531 base = (volatile u32*)ioremap(node->addrs[0].address, node->addrs[0].size);
532 if (!base) {
533 printk(KERN_ERR "pmac_feature: Can't map mac-io chip !\n");
534 return;
536 if (type == macio_keylargo) {
537 u32* did = (u32 *)get_property(node, "device-id", NULL);
538 if (*did == 0x00000025)
539 type = macio_pangea;
540 if (*did == 0x0000003e)
541 type = macio_intrepid;
543 macio_chips[i].of_node = node;
544 macio_chips[i].type = type;
545 macio_chips[i].base = base;
546 macio_chips[i].flags = MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON;
547 macio_chips[i].name = macio_names[type];
548 revp = (u32 *)get_property(node, "revision-id", NULL);
549 if (revp)
550 macio_chips[i].rev = *revp;
551 printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n",
552 macio_names[type], macio_chips[i].rev, macio_chips[i].base);
555 static int __init
556 probe_macios(void)
558 probe_one_macio("mac-io", "K2-Keylargo", macio_keylargo2);
560 macio_chips[0].lbus.index = 0;
561 macio_chips[1].lbus.index = 1;
563 return (macio_chips[0].of_node == NULL) ? -ENODEV : 0;
566 static void __init
567 set_initial_features(void)
569 struct device_node *np;
571 if (macio_chips[0].type == macio_keylargo2) {
572 #ifndef CONFIG_SMP
573 /* On SMP machines running UP, we have the second CPU eating
574 * bus cycles. We need to take it off the bus. This is done
575 * from pmac_smp for SMP kernels running on one CPU
577 np = of_find_node_by_type(NULL, "cpu");
578 if (np != NULL)
579 np = of_find_node_by_type(np, "cpu");
580 if (np != NULL) {
581 g5_phy_disable_cpu1();
582 of_node_put(np);
584 #endif /* CONFIG_SMP */
585 /* Enable GMAC for now for PCI probing. It will be disabled
586 * later on after PCI probe
588 np = of_find_node_by_name(NULL, "ethernet");
589 while(np) {
590 if (device_is_compatible(np, "K2-GMAC"))
591 g5_gmac_enable(np, 0, 1);
592 np = of_find_node_by_name(np, "ethernet");
595 /* Enable FW before PCI probe. Will be disabled later on
596 * Note: We should have a batter way to check that we are
597 * dealing with uninorth internal cell and not a PCI cell
598 * on the external PCI. The code below works though.
600 np = of_find_node_by_name(NULL, "firewire");
601 while(np) {
602 if (device_is_compatible(np, "pci106b,5811")) {
603 macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
604 g5_fw_enable(np, 0, 1);
606 np = of_find_node_by_name(np, "firewire");
611 void __init
612 pmac_feature_init(void)
614 /* Detect the UniNorth memory controller */
615 probe_uninorth();
617 /* Probe mac-io controllers */
618 if (probe_macios()) {
619 printk(KERN_WARNING "No mac-io chip found\n");
620 return;
623 /* Setup low-level i2c stuffs */
624 pmac_init_low_i2c();
626 /* Probe machine type */
627 if (probe_motherboard())
628 printk(KERN_WARNING "Unknown PowerMac !\n");
630 /* Set some initial features (turn off some chips that will
631 * be later turned on)
633 set_initial_features();
636 int __init pmac_feature_late_init(void)
638 #if 0
639 struct device_node* np;
641 /* Request some resources late */
642 if (uninorth_node)
643 request_OF_resource(uninorth_node, 0, NULL);
644 np = find_devices("hammerhead");
645 if (np)
646 request_OF_resource(np, 0, NULL);
647 np = find_devices("interrupt-controller");
648 if (np)
649 request_OF_resource(np, 0, NULL);
650 #endif
651 return 0;
654 device_initcall(pmac_feature_late_init);
656 #if 0
657 static void dump_HT_speeds(char *name, u32 cfg, u32 frq)
659 int freqs[16] = { 200,300,400,500,600,800,1000,0,0,0,0,0,0,0,0,0 };
660 int bits[8] = { 8,16,0,32,2,4,0,0 };
661 int freq = (frq >> 8) & 0xf;
663 if (freqs[freq] == 0)
664 printk("%s: Unknown HT link frequency %x\n", name, freq);
665 else
666 printk("%s: %d MHz on main link, (%d in / %d out) bits width\n",
667 name, freqs[freq],
668 bits[(cfg >> 28) & 0x7], bits[(cfg >> 24) & 0x7]);
670 #endif
672 void __init pmac_check_ht_link(void)
674 #if 0 /* Disabled for now */
675 u32 ufreq, freq, ucfg, cfg;
676 struct device_node *pcix_node;
677 struct pci_dn *pdn;
678 u8 px_bus, px_devfn;
679 struct pci_controller *px_hose;
681 (void)in_be32(u3_ht + U3_HT_LINK_COMMAND);
682 ucfg = cfg = in_be32(u3_ht + U3_HT_LINK_CONFIG);
683 ufreq = freq = in_be32(u3_ht + U3_HT_LINK_FREQ);
684 dump_HT_speeds("U3 HyperTransport", cfg, freq);
686 pcix_node = of_find_compatible_node(NULL, "pci", "pci-x");
687 if (pcix_node == NULL) {
688 printk("No PCI-X bridge found\n");
689 return;
691 pdn = pcix_node->data;
692 px_hose = pdn->phb;
693 px_bus = pdn->busno;
694 px_devfn = pdn->devfn;
696 early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg);
697 early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq);
698 dump_HT_speeds("PCI-X HT Uplink", cfg, freq);
699 early_read_config_dword(px_hose, px_bus, px_devfn, 0xc8, &cfg);
700 early_read_config_dword(px_hose, px_bus, px_devfn, 0xd0, &freq);
701 dump_HT_speeds("PCI-X HT Downlink", cfg, freq);
702 #endif
706 * Early video resume hook
709 static void (*pmac_early_vresume_proc)(void *data);
710 static void *pmac_early_vresume_data;
712 void pmac_set_early_video_resume(void (*proc)(void *data), void *data)
714 if (_machine != _MACH_Pmac)
715 return;
716 preempt_disable();
717 pmac_early_vresume_proc = proc;
718 pmac_early_vresume_data = data;
719 preempt_enable();
721 EXPORT_SYMBOL(pmac_set_early_video_resume);
725 * AGP related suspend/resume code
728 static struct pci_dev *pmac_agp_bridge;
729 static int (*pmac_agp_suspend)(struct pci_dev *bridge);
730 static int (*pmac_agp_resume)(struct pci_dev *bridge);
732 void pmac_register_agp_pm(struct pci_dev *bridge,
733 int (*suspend)(struct pci_dev *bridge),
734 int (*resume)(struct pci_dev *bridge))
736 if (suspend || resume) {
737 pmac_agp_bridge = bridge;
738 pmac_agp_suspend = suspend;
739 pmac_agp_resume = resume;
740 return;
742 if (bridge != pmac_agp_bridge)
743 return;
744 pmac_agp_suspend = pmac_agp_resume = NULL;
745 return;
747 EXPORT_SYMBOL(pmac_register_agp_pm);
749 void pmac_suspend_agp_for_card(struct pci_dev *dev)
751 if (pmac_agp_bridge == NULL || pmac_agp_suspend == NULL)
752 return;
753 if (pmac_agp_bridge->bus != dev->bus)
754 return;
755 pmac_agp_suspend(pmac_agp_bridge);
757 EXPORT_SYMBOL(pmac_suspend_agp_for_card);
759 void pmac_resume_agp_for_card(struct pci_dev *dev)
761 if (pmac_agp_bridge == NULL || pmac_agp_resume == NULL)
762 return;
763 if (pmac_agp_bridge->bus != dev->bus)
764 return;
765 pmac_agp_resume(pmac_agp_bridge);
767 EXPORT_SYMBOL(pmac_resume_agp_for_card);