patch-2.4.0-test4 linux/arch/ppc/kernel/feature.c
Next file: linux/arch/ppc/kernel/gemini_setup.c
Previous file: linux/arch/ppc/kernel/entry.S
Back to the patch index
Back to the overall index
- Lines: 285
- Date:
Thu Jul 13 09:42:50 2000
- Orig file:
v2.4.0-test3/linux/arch/ppc/kernel/feature.c
- Orig date:
Thu May 11 15:30:06 2000
diff -u --recursive --new-file v2.4.0-test3/linux/arch/ppc/kernel/feature.c linux/arch/ppc/kernel/feature.c
@@ -2,6 +2,7 @@
* arch/ppc/kernel/feature.c
*
* Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
+ * Ben. Herrenschmidt (bh40@calva.net)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -30,7 +31,7 @@
#undef DEBUG_FEATURE
#define MAX_FEATURE_CONTROLLERS 2
-#define MAX_FEATURE_OFFSET 0x50
+#define MAX_FEATURE_OFFSET 0x100
#define FREG(c,r) (&(((c)->reg)[(r)>>2]))
typedef struct feature_bit {
@@ -70,6 +71,7 @@
{0x38,0,0}, /* FEATURE_IDE2_reset */
{0x38,0,0}, /* FEATURE_Mediabay_IDE_switch */
{0x38,0,0}, /* FEATURE_Mediabay_content */
+ {0x38,0,0}, /* FEATURE_Airport_reset */
};
/* Those bits are from a PowerBook. It's possible that desktop machines
@@ -102,6 +104,7 @@
{0x38,0,0}, /* FEATURE_IDE2_reset */
{0x38,0,0}, /* FEATURE_Mediabay_IDE_switch */
{0x38,0,0}, /* FEATURE_Mediabay_content */
+ {0x38,0,0}, /* FEATURE_Airport_reset */
};
/*
@@ -135,6 +138,7 @@
{0x38,0,0}, /* FEATURE_IDE2_reset */
{0x38,0,0}, /* FEATURE_Mediabay_IDE_switch */
{0x38,0,0}, /* FEATURE_Mediabay_content */
+ {0x38,0,0}, /* FEATURE_Airport_reset */
};
/* Those bits are for Core99 machines (iBook,G4,iMacSL/DV,Pismo,...).
@@ -166,6 +170,7 @@
{0x3c,1,0x40000000}, /* FEATURE_IDE2_reset */
{0x34,0,0x00001000}, /* FEATURE_Mediabay_IDE_switch */
{0x34,0,0x00000100}, /* FEATURE_Mediabay_content */
+ {0x40,1,0x08000000}, /* FEATURE_Airport_reset */
};
/* definition of a feature controller object */
@@ -177,22 +182,33 @@
};
/* static functions */
-static void
+static struct feature_controller*
feature_add_controller(struct device_node *controller_device, fbit* bits);
static struct feature_controller*
feature_lookup_controller(struct device_node *device);
-/* static varialbles */
+static void heathrow_prepare_for_sleep(struct feature_controller* ctrler);
+static void heathrow_wakeup(struct feature_controller* ctrler);
+static void core99_prepare_for_sleep(struct feature_controller* ctrler);
+static void core99_wake_up(struct feature_controller* ctrler);
+
+/* static variables */
static struct feature_controller controllers[MAX_FEATURE_CONTROLLERS];
static int controller_count = 0;
+/* Core99 stuffs */
+static volatile u32* uninorth_base = NULL;
+static volatile u32* keylargo_base = NULL;
+static int uninorth_rev;
+static int keylargo_rev;
void
feature_init(void)
{
struct device_node *np;
-
+ u32 *rev;
+
if (_machine != _MACH_Pmac)
return;
@@ -202,7 +218,14 @@
* plus some gpio's which could eventually be handled here.
*/
if (device_is_compatible(np, "Keylargo")) {
- feature_add_controller(np, feature_bits_keylargo);
+ struct feature_controller* ctrler =
+ feature_add_controller(np, feature_bits_keylargo);
+ if (ctrler) {
+ keylargo_base = ctrler->reg;
+ rev = (u32 *)get_property(ctrler->device, "revision-id", NULL);
+ if (rev)
+ keylargo_rev = *rev;
+ }
} else if (device_is_compatible(np, "paddington")) {
feature_add_controller(np, feature_bits_paddington);
} else {
@@ -222,6 +245,18 @@
}
}
+ /* Handle core99 Uni-N */
+ np = find_devices("uni-n");
+ if (np && np->n_addrs > 0) {
+ uninorth_base = ioremap(np->addrs[0].address, 0x1000);
+ rev = (u32 *)get_property(np, "device-rev", NULL);
+ if (rev)
+ uninorth_rev = *rev;
+ }
+ if (uninorth_base && keylargo_base)
+ printk("Uni-N revision: %d, KeyLargo revision: %d\n",
+ uninorth_rev, keylargo_rev);
+
if (controller_count)
printk(KERN_INFO "Registered %d feature controller(s)\n", controller_count);
@@ -236,7 +271,7 @@
#endif
}
-static void
+static struct feature_controller*
feature_add_controller(struct device_node *controller_device, fbit* bits)
{
struct feature_controller* controller;
@@ -244,7 +279,7 @@
if (controller_count >= MAX_FEATURE_CONTROLLERS) {
printk(KERN_INFO "Feature controller %s skipped(MAX:%d)\n",
controller_device->full_name, MAX_FEATURE_CONTROLLERS);
- return;
+ return NULL;
}
controller = &controllers[controller_count];
@@ -253,7 +288,7 @@
if (controller_device->n_addrs == 0) {
printk(KERN_ERR "No addresses for %s\n",
controller_device->full_name);
- return;
+ return NULL;
}
controller->reg = (volatile u32 *)ioremap(
@@ -262,12 +297,14 @@
if (bits == NULL) {
printk(KERN_INFO "Twiddling the magic ohare bits\n");
out_le32(FREG(controller,OHARE_FEATURE_REG), STARMAX_FEATURES);
- return;
+ return NULL;
}
spin_lock_init(&controller->lock);
controller_count++;
+
+ return controller;
}
static struct feature_controller*
@@ -387,5 +424,120 @@
*/
value = (in_le32(FREG(controller, bit->reg)) & bit->mask);
return bit->polarity ? (value == 0) : (value == bit->mask);
+}
+
+/*
+ * Core99 functions
+ *
+ * Note: We currently assume there is _one_ UniN chip and _one_ KeyLargo
+ * chip, which is the case on all Core99 machines so far
+ */
+
+/* Only one GMAC is assumed */
+void
+feature_set_gmac_power(struct device_node* device, int power)
+{
+ if (!uninorth_base)
+ return;
+ if (power)
+ out_le32(uninorth_base + 0x20/4,
+ in_le32(uninorth_base + 0x20/4) | 0x02000000);
+ else
+ out_le32(uninorth_base + 0x20/4,
+ in_le32(uninorth_base + 0x20/4) & ~0x02000000);
+ udelay(20);
+}
+
+/* Pass the node of the correct controller, please */
+void
+feature_set_usb_power(struct device_node* device, int power)
+{
+}
+
+/* Not yet implemented */
+void
+feature_set_firewire_power(struct device_node* device, int power)
+{
+}
+
+void
+feature_prepare_for_sleep(void)
+{
+ /* We assume gatwick is second */
+ struct feature_controller* ctrler = &controllers[0];
+
+ if (!ctrler)
+ return;
+ if (controller_count > 1 &&
+ device_is_compatible(ctrler->device, "gatwick"))
+ ctrler = &controllers[1];
+
+ if (ctrler->bits == feature_bits_heathrow ||
+ ctrler->bits == feature_bits_paddington) {
+ heathrow_prepare_for_sleep(ctrler);
+ return;
+ }
+ if (ctrler->bits == feature_bits_keylargo) {
+ core99_prepare_for_sleep(ctrler);
+ return;
+ }
+}
+
+
+void
+feature_wake_up(void)
+{
+ struct feature_controller* ctrler = &controllers[0];
+
+ if (!ctrler)
+ return;
+ if (controller_count > 1 &&
+ device_is_compatible(ctrler->device, "gatwick"))
+ ctrler = &controllers[1];
+
+ if (ctrler->bits == feature_bits_heathrow ||
+ ctrler->bits == feature_bits_paddington) {
+ heathrow_wakeup(ctrler);
+ return;
+ }
+ if (ctrler->bits == feature_bits_keylargo) {
+ core99_wake_up(ctrler);
+ return;
+ }
+}
+
+static u32 save_fcr0;
+//static u32 save_fcr1;
+//static u32 save_fcr2;
+static u32 save_mbcr;
+
+static void
+heathrow_prepare_for_sleep(struct feature_controller* ctrler)
+{
+ save_mbcr = in_le32(FREG(ctrler, 0x34));
+ save_fcr0 = in_le32(FREG(ctrler, 0x38));
+
+ out_le32(FREG(ctrler, 0x38), save_fcr0 & ~HRW_IOBUS_ENABLE);
+}
+
+static void
+heathrow_wakeup(struct feature_controller* ctrler)
+{
+ out_le32(FREG(ctrler, 0x38), save_fcr0);
+ out_le32(FREG(ctrler, 0x34), save_mbcr);
+
+ out_le32(FREG(ctrler, 0x38), save_fcr0 | HRW_IOBUS_ENABLE);
+}
+
+static void
+core99_prepare_for_sleep(struct feature_controller* ctrler)
+{
+ /* Not yet implemented */
+}
+
+static void
+core99_wake_up(struct feature_controller* ctrler)
+{
+ /* Not yet implemented */
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)