Commit 1a623a25 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Paul Mackerras

PPC32: Forward-port support for new powermacs from 2.4 tree.

parent f5a61e07
......@@ -14,6 +14,8 @@
* - Replace mdelay with some schedule loop if possible
* - Shorten some obfuscated delays on some routines (like modem
* power)
* - Refcount some clocks (see darwin)
* - Split split split...
*
*/
#include <linux/config.h>
......@@ -25,6 +27,8 @@
#include <linux/spinlock.h>
#include <linux/adb.h>
#include <linux/pmu.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <asm/sections.h>
#include <asm/errno.h>
#include <asm/ohare.h>
......@@ -34,8 +38,10 @@
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/macio_asic.h>
#include <asm/pmac_feature.h>
#include <asm/dbdma.h>
#include <asm/pci-bridge.h>
#undef DEBUG_FEATURE
......@@ -46,7 +52,8 @@
#endif
/* Exported from arch/ppc/kernel/idle.c */
extern unsigned long powersave_nap;
extern int powersave_nap;
extern int powersave_lowspeed;
/*
* We use a single global lock to protect accesses. Each driver has
......@@ -57,53 +64,13 @@ static spinlock_t feature_lock __pmacdata = SPIN_LOCK_UNLOCKED;
#define LOCK(flags) spin_lock_irqsave(&feature_lock, flags);
#define UNLOCK(flags) spin_unlock_irqrestore(&feature_lock, flags);
/*
* Helper functions regarding the various flavors of mac-io
* Instance of some macio stuffs
*/
struct macio_chip macio_chips[MAX_MACIO_CHIPS] __pmacdata;
#define MAX_MACIO_CHIPS 2
enum {
macio_unknown = 0,
macio_grand_central,
macio_ohare,
macio_ohareII,
macio_heathrow,
macio_gatwick,
macio_paddington,
macio_keylargo,
macio_pangea
};
static const char* macio_names[] __pmacdata =
{
"Unknown",
"Grand Central",
"OHare",
"OHareII",
"Heathrow",
"Gatwick",
"Paddington",
"Keylargo",
"Pangea"
};
static struct macio_chip
{
struct device_node* of_node;
int type;
int rev;
volatile u32* base;
unsigned long flags;
} macio_chips[MAX_MACIO_CHIPS] __pmacdata;
#define MACIO_FLAG_SCCA_ON 0x00000001
#define MACIO_FLAG_SCCB_ON 0x00000002
#define MACIO_FLAG_SCC_LOCKED 0x00000004
#define MACIO_FLAG_AIRPORT_ON 0x00000010
#define MACIO_FLAG_FW_SUPPORTED 0x00000020
static struct macio_chip* __pmac
struct macio_chip* __pmac
macio_find(struct device_node* child, int type)
{
while(child) {
......@@ -118,15 +85,21 @@ macio_find(struct device_node* child, int type)
return NULL;
}
#define MACIO_FCR32(macio, r) ((macio)->base + ((r) >> 2))
#define MACIO_FCR8(macio, r) (((volatile u8*)((macio)->base)) + (r))
static const char* macio_names[] __pmacdata =
{
"Unknown",
"Grand Central",
"OHare",
"OHareII",
"Heathrow",
"Gatwick",
"Paddington",
"Keylargo",
"Pangea",
"Intrepid"
};
#define MACIO_IN32(r) (in_le32(MACIO_FCR32(macio,r)))
#define MACIO_OUT32(r,v) (out_le32(MACIO_FCR32(macio,r), (v)))
#define MACIO_BIS(r,v) (MACIO_OUT32((r), MACIO_IN32(r) | (v)))
#define MACIO_BIC(r,v) (MACIO_OUT32((r), MACIO_IN32(r) & ~(v)))
#define MACIO_IN8(r) (in_8(MACIO_FCR8(macio,r)))
#define MACIO_OUT8(r,v) (out_8(MACIO_FCR8(macio,r), (v)))
/*
* Uninorth reg. access. Note that Uni-N regs are big endian
......@@ -196,7 +169,7 @@ ohare_htw_scc_enable(struct device_node* node, int param, int value)
unsigned long chan_mask;
unsigned long fcr;
unsigned long flags;
int htw;
int htw, trans;
unsigned long rmask;
macio = macio_find(node, 0);
......@@ -211,6 +184,9 @@ ohare_htw_scc_enable(struct device_node* node, int param, int value)
htw = (macio->type == macio_heathrow || macio->type == macio_paddington
|| macio->type == macio_gatwick);
/* On these machines, the HRW_SCC_TRANS_EN_N bit mustn't be touched */
trans = (pmac_mb.model_id != PMAC_TYPE_YOSEMITE &&
pmac_mb.model_id != PMAC_TYPE_YIKES);
if (value) {
#ifdef CONFIG_ADB_PMU
if ((param & 0xfff) == PMAC_SCC_IRDA)
......@@ -222,6 +198,12 @@ ohare_htw_scc_enable(struct device_node* node, int param, int value)
if (!(fcr & OH_SCC_ENABLE)) {
fcr |= OH_SCC_ENABLE;
if (htw) {
/* Side effect: this will also power up the
* modem, but it's too messy to figure out on which
* ports this controls the tranceiver and on which
* it controls the modem
*/
if (trans)
fcr &= ~HRW_SCC_TRANS_EN_N;
MACIO_OUT32(OHARE_FCR, fcr);
fcr |= (rmask = HRW_RESET_SCC);
......@@ -258,7 +240,7 @@ ohare_htw_scc_enable(struct device_node* node, int param, int value)
MACIO_OUT32(OHARE_FCR, fcr);
if ((fcr & (OH_SCCA_IO | OH_SCCB_IO)) == 0) {
fcr &= ~OH_SCC_ENABLE;
if (htw)
if (htw && trans)
fcr |= HRW_SCC_TRANS_EN_N;
MACIO_OUT32(OHARE_FCR, fcr);
}
......@@ -330,9 +312,9 @@ ohare_sleep_state(struct device_node* node, int param, int value)
if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
return -EPERM;
if (value) {
if (value == 1) {
MACIO_BIC(OHARE_FCR, OH_IOBUS_ENABLE);
} else {
} else if (value == 0) {
MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
}
......@@ -522,7 +504,7 @@ heathrow_sound_enable(struct device_node* node, int param, int value)
return 0;
}
static u32 save_fcr[5] __pmacdata;
static u32 save_fcr[6] __pmacdata;
static u32 save_mbcr __pmacdata;
static u32 save_gpio_levels[2] __pmacdata;
static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT] __pmacdata;
......@@ -586,6 +568,7 @@ heathrow_sleep(struct macio_chip* macio, int secondary)
/* This seems to be necessary as well or the fan
* keeps coming up and battery drains fast */
MACIO_BIC(HEATHROW_FCR, HRW_IOBUS_ENABLE);
MACIO_BIC(HEATHROW_FCR, HRW_IDE0_RESET_N);
/* Make sure eth is down even if module or sleep
* won't work properly */
MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE | HRW_BMAC_RESET);
......@@ -751,6 +734,12 @@ core99_modem_enable(struct device_node* node, int param, int value)
u8 gpio;
unsigned long flags;
/* Hack for internal USB modem */
if (node == NULL) {
if (macio_chips[0].type != macio_keylargo)
return -ENODEV;
node = macio_chips[0].of_node;
}
macio = macio_find(node, 0);
if (!macio)
return -ENODEV;
......@@ -790,9 +779,97 @@ core99_modem_enable(struct device_node* node, int param, int value)
return 0;
}
static int __pmac
pangea_modem_enable(struct device_node* node, int param, int value)
{
struct macio_chip* macio;
u8 gpio;
unsigned long flags;
/* Hack for internal USB modem */
if (node == NULL) {
if (macio_chips[0].type != macio_pangea &&
macio_chips[0].type != macio_intrepid)
return -ENODEV;
node = macio_chips[0].of_node;
}
macio = macio_find(node, 0);
if (!macio)
return -ENODEV;
gpio = MACIO_IN8(KL_GPIO_MODEM_RESET);
gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE;
gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA;
if (!value) {
LOCK(flags);
MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
UNLOCK(flags);
(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
mdelay(250);
}
LOCK(flags);
if (value) {
MACIO_OUT8(KL_GPIO_MODEM_POWER,
KEYLARGO_GPIO_OUTPUT_ENABLE);
UNLOCK(flags);
(void)MACIO_IN32(KEYLARGO_FCR2);
mdelay(250);
} else {
MACIO_OUT8(KL_GPIO_MODEM_POWER,
KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
UNLOCK(flags);
}
if (value) {
LOCK(flags);
MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
UNLOCK(flags); mdelay(250); LOCK(flags);
MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
UNLOCK(flags); mdelay(250); LOCK(flags);
MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
UNLOCK(flags); mdelay(250);
}
return 0;
}
static int __pmac
core99_ata100_enable(struct device_node* node, int value)
{
unsigned long flags;
struct pci_dev *pdev = NULL;
u8 pbus, pid;
if (uninorth_rev < 0x24)
return -ENODEV;
LOCK(flags);
if (value)
UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100);
else
UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100);
(void)UN_IN(UNI_N_CLOCK_CNTL);
UNLOCK(flags);
udelay(20);
if (value) {
if (pci_device_from_OF_node(node, &pbus, &pid) == 0)
pdev = pci_find_slot(pbus, pid);
if (pdev == NULL)
return 0;
pci_enable_device(pdev);
pci_set_master(pdev);
}
return 0;
}
static int __pmac
core99_ide_enable(struct device_node* node, int param, int value)
{
/* Bus ID 0 to 2 are KeyLargo based IDE, busID 3 is U2
* based ata-100
*/
switch(param) {
case 0:
return simple_feature_tweak(node, macio_unknown,
......@@ -803,6 +880,8 @@ core99_ide_enable(struct device_node* node, int param, int value)
case 2:
return simple_feature_tweak(node, macio_unknown,
KEYLARGO_FCR1, KL1_UIDE_ENABLE, value);
case 3:
return core99_ata100_enable(node, value);
default:
return -ENODEV;
}
......@@ -850,7 +929,8 @@ core99_gmac_phy_reset(struct device_node* node, int param, int value)
struct macio_chip* macio;
macio = &macio_chips[0];
if (macio->type != macio_keylargo && macio->type != macio_pangea)
if (macio->type != macio_keylargo && macio->type != macio_pangea &&
macio->type != macio_intrepid)
return -ENODEV;
LOCK(flags);
......@@ -987,27 +1067,40 @@ core99_airport_enable(struct device_node* node, int param, int value)
static int __pmac
core99_reset_cpu(struct device_node* node, int param, int value)
{
const int reset_lines[] = { KL_GPIO_RESET_CPU0,
unsigned int reset_io = 0;
unsigned long flags;
struct macio_chip* macio;
struct device_node* np;
const int dflt_reset_lines[] = { KL_GPIO_RESET_CPU0,
KL_GPIO_RESET_CPU1,
KL_GPIO_RESET_CPU2,
KL_GPIO_RESET_CPU3 };
int reset_io;
unsigned long flags;
struct macio_chip* macio;
macio = &macio_chips[0];
if (macio->type != macio_keylargo && macio->type != macio_pangea)
return -ENODEV;
if (param > 3 || param < 0)
if (macio->type != macio_keylargo)
return -ENODEV;
reset_io = reset_lines[param];
np = find_path_device("/cpus");
if (np == NULL)
return -ENODEV;
for (np = np->child; np != NULL; np = np->sibling) {
u32* num = (u32 *)get_property(np, "reg", NULL);
u32* rst = (u32 *)get_property(np, "soft-reset", NULL);
if (num == NULL || rst == NULL)
continue;
if (param == *num) {
reset_io = *rst;
break;
}
}
if (np == NULL || reset_io == 0)
reset_io = dflt_reset_lines[param];
LOCK(flags);
MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);
(void)MACIO_IN8(reset_io);
udelay(1);
MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTOUT_DATA | KEYLARGO_GPIO_OUTPUT_ENABLE);
(void)MACIO_IN8(reset_io);
UNLOCK(flags);
......@@ -1025,15 +1118,19 @@ core99_usb_enable(struct device_node* node, int param, int value)
u32 reg;
macio = &macio_chips[0];
if (macio->type != macio_keylargo && macio->type != macio_pangea)
if (macio->type != macio_keylargo && macio->type != macio_pangea &&
macio->type != macio_intrepid)
return -ENODEV;
/* XXX Fix handling of 3rd USB controller in Intrepid, move the
* port connect stuff (KL4_*) to the sleep code eventually
*/
prop = (char *)get_property(node, "AAPL,clock-id", NULL);
if (!prop)
return -ENODEV;
if (strncmp(prop, "usb0u048", strlen("usb0u048")) == 0)
if (strncmp(prop, "usb0u048", 8) == 0)
number = 0;
else if (strncmp(prop, "usb1u148", strlen("usb1u148")) == 0)
else if (strncmp(prop, "usb1u148", 8) == 0)
number = 2;
else
return -ENODEV;
......@@ -1104,7 +1201,8 @@ core99_firewire_enable(struct device_node* node, int param, int value)
struct macio_chip* macio;
macio = &macio_chips[0];
if (macio->type != macio_keylargo && macio->type != macio_pangea)
if (macio->type != macio_keylargo && macio->type != macio_pangea &&
macio->type != macio_intrepid)
return -ENODEV;
if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED))
return -ENODEV;
......@@ -1133,7 +1231,8 @@ core99_firewire_cable_power(struct device_node* node, int param, int value)
if ((pmac_mb.board_flags & PMAC_MB_HAS_FW_POWER) == 0)
return -ENODEV;
macio = &macio_chips[0];
if (macio->type != macio_keylargo && macio->type != macio_pangea)
if (macio->type != macio_keylargo && macio->type != macio_pangea &&
macio->type != macio_intrepid)
return -ENODEV;
if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED))
return -ENODEV;
......@@ -1172,23 +1271,24 @@ core99_write_gpio(struct device_node* node, int param, int value)
}
static void __pmac
keylargo_shutdown(struct macio_chip* macio, int restart)
keylargo_shutdown(struct macio_chip* macio, int sleep_mode)
{
u32 temp;
if (sleep_mode) {
mdelay(1);
MACIO_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND);
(void)MACIO_IN32(KEYLARGO_FCR0);
mdelay(100);
mdelay(1);
}
MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
KL0_SCC_CELL_ENABLE |
KL0_IRDA_ENABLE | KL0_IRDA_CLK32_ENABLE |
KL0_IRDA_CLK19_ENABLE);
(void)MACIO_IN32(KEYLARGO_FCR0); udelay(10);
MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK);
(void)MACIO_IN32(KEYLARGO_MBCR); udelay(10);
MACIO_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_IDE_ENABLE);
MACIO_BIC(KEYLARGO_FCR1,
KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
......@@ -1199,27 +1299,33 @@ keylargo_shutdown(struct macio_chip* macio, int restart)
KL1_EIDE0_ENABLE | KL1_EIDE0_RESET_N |
KL1_EIDE1_ENABLE | KL1_EIDE1_RESET_N |
KL1_UIDE_ENABLE);
(void)MACIO_IN32(KEYLARGO_FCR1); udelay(10);
MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
udelay(10);
MACIO_BIC(KEYLARGO_FCR2, KL2_IOBUS_ENABLE);
udelay(10);
temp = MACIO_IN32(KEYLARGO_FCR3);
if (macio->rev >= 2)
temp |= (KL3_SHUTDOWN_PLL2X | KL3_SHUTDOWN_PLL_TOTAL);
if (macio->rev >= 2) {
temp |= KL3_SHUTDOWN_PLL2X;
if (sleep_mode)
temp |= KL3_SHUTDOWN_PLL_TOTAL;
}
temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
KL3_SHUTDOWN_PLLKW35 | KL3_SHUTDOWN_PLLKW12;
KL3_SHUTDOWN_PLLKW35;
if (sleep_mode)
temp |= KL3_SHUTDOWN_PLLKW12;
temp &= ~(KL3_CLK66_ENABLE | KL3_CLK49_ENABLE | KL3_CLK45_ENABLE
| KL3_CLK31_ENABLE | KL3_TIMER_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE
| KL3_I2S0_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
| KL3_CLK31_ENABLE | KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE);
if (sleep_mode)
temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
MACIO_OUT32(KEYLARGO_FCR3, temp);
(void)MACIO_IN32(KEYLARGO_FCR3); udelay(10);
/* Flush posted writes & wait a bit */
(void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
}
static void __pmac
pangea_shutdown(struct macio_chip* macio, int restart)
pangea_shutdown(struct macio_chip* macio, int sleep_mode)
{
u32 temp;
......@@ -1227,10 +1333,6 @@ pangea_shutdown(struct macio_chip* macio, int restart)
KL0_SCC_CELL_ENABLE |
KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE);
(void)MACIO_IN32(KEYLARGO_FCR0); udelay(10);
MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK);
(void)MACIO_IN32(KEYLARGO_MBCR); udelay(10);
MACIO_BIC(KEYLARGO_FCR1,
KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
......@@ -1238,18 +1340,54 @@ pangea_shutdown(struct macio_chip* macio, int restart)
KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
KL1_UIDE_ENABLE);
(void)MACIO_IN32(KEYLARGO_FCR1); udelay(10);
if (pmac_mb.board_flags & PMAC_MB_MOBILE)
MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N);
MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
udelay(10);
temp = MACIO_IN32(KEYLARGO_FCR3);
temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
KL3_SHUTDOWN_PLLKW35;
temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE
| KL3_CLK31_ENABLE | KL3_TIMER_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE
| KL3_I2S0_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | KL3_CLK31_ENABLE
| KL3_I2S0_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE);
if (sleep_mode)
temp &= ~(KL3_VIA_CLK16_ENABLE | KL3_TIMER_CLK18_ENABLE);
MACIO_OUT32(KEYLARGO_FCR3, temp);
(void)MACIO_IN32(KEYLARGO_FCR3); udelay(10);
/* Flush posted writes & wait a bit */
(void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
}
static void __pmac
intrepid_shutdown(struct macio_chip* macio, int sleep_mode)
{
u32 temp;
MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
KL0_SCC_CELL_ENABLE |
KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE);
MACIO_BIC(KEYLARGO_FCR1,
KL1_USB2_CELL_ENABLE |
KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE);
if (pmac_mb.board_flags & PMAC_MB_MOBILE)
MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N);
MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
temp = MACIO_IN32(KEYLARGO_FCR3);
temp |= KL3_IT_SHUTDOWN_PLL1 | KL3_IT_SHUTDOWN_PLL2 |
KL3_IT_SHUTDOWN_PLL3;
temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE |
KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE);
if (sleep_mode)
temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_IT_VIA_CLK32_ENABLE);
MACIO_OUT32(KEYLARGO_FCR3, temp);
/* Flush posted writes & wait a bit */
(void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
}
static int __pmac
......@@ -1259,7 +1397,8 @@ core99_sleep(void)
int i;
macio = &macio_chips[0];
if (macio->type != macio_keylargo && macio->type != macio_pangea)
if (macio->type != macio_keylargo && macio->type != macio_pangea &&
macio->type != macio_intrepid)
return -ENODEV;
/* We power off the wireless slot in case it was not done
......@@ -1275,7 +1414,11 @@ core99_sleep(void)
}
/* We make sure int. modem is off (in case driver lost it) */
if (macio->type == macio_keylargo)
core99_modem_enable(macio->of_node, 0, 0);
else
pangea_modem_enable(macio->of_node, 0, 0);
/* We make sure the sound is off as well */
core99_sound_chip_enable(macio->of_node, 0, 0);
......@@ -1292,12 +1435,15 @@ core99_sleep(void)
save_gpio_normal[i] = MACIO_IN8(KEYLARGO_GPIO_0+i);
/* Save the FCRs */
if (macio->type == macio_keylargo)
save_mbcr = MACIO_IN32(KEYLARGO_MBCR);
save_fcr[0] = MACIO_IN32(KEYLARGO_FCR0);
save_fcr[1] = MACIO_IN32(KEYLARGO_FCR1);
save_fcr[2] = MACIO_IN32(KEYLARGO_FCR2);
save_fcr[3] = MACIO_IN32(KEYLARGO_FCR3);
save_fcr[4] = MACIO_IN32(KEYLARGO_FCR4);
if (macio->type == macio_pangea || macio->type == macio_intrepid)
save_fcr[5] = MACIO_IN32(KEYLARGO_FCR5);
/* Save state & config of DBDMA channels */
dbdma_save(macio, save_dbdma);
......@@ -1306,9 +1452,11 @@ core99_sleep(void)
* Turn off as much as we can
*/
if (macio->type == macio_pangea)
pangea_shutdown(macio, 0);
pangea_shutdown(macio, 1);
else if (macio->type == macio_intrepid)
intrepid_shutdown(macio, 1);
else if (macio->type == macio_keylargo)
keylargo_shutdown(macio, 0);
keylargo_shutdown(macio, 1);
/*
* Put the host bridge to sleep
......@@ -1338,7 +1486,8 @@ core99_wake_up(void)
int i;
macio = &macio_chips[0];
if (macio->type != macio_keylargo && macio->type != macio_pangea)
if (macio->type != macio_keylargo && macio->type != macio_pangea &&
macio->type != macio_intrepid)
return -ENODEV;
/*
......@@ -1353,8 +1502,10 @@ core99_wake_up(void)
* Restore KeyLargo
*/
if (macio->type == macio_keylargo) {
MACIO_OUT32(KEYLARGO_MBCR, save_mbcr);
(void)MACIO_IN32(KEYLARGO_MBCR); udelay(10);
}
MACIO_OUT32(KEYLARGO_FCR0, save_fcr[0]);
(void)MACIO_IN32(KEYLARGO_FCR0); udelay(10);
MACIO_OUT32(KEYLARGO_FCR1, save_fcr[1]);
......@@ -1365,6 +1516,10 @@ core99_wake_up(void)
(void)MACIO_IN32(KEYLARGO_FCR3); udelay(10);
MACIO_OUT32(KEYLARGO_FCR4, save_fcr[4]);
(void)MACIO_IN32(KEYLARGO_FCR4); udelay(10);
if (macio->type == macio_pangea || macio->type == macio_intrepid) {
MACIO_OUT32(KEYLARGO_FCR5, save_fcr[5]);
(void)MACIO_IN32(KEYLARGO_FCR5); udelay(10);
}
dbdma_restore(macio, save_dbdma);
......@@ -1390,6 +1545,21 @@ core99_wake_up(void)
static int __pmac
core99_sleep_state(struct device_node* node, int param, int value)
{
/* Param == 1 means to enter the "fake sleep" mode that is
* used for CPU speed switch
*/
if (param == 1) {
if (value == 1) {
UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING);
UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_IDLE2);
} else {
UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL);
udelay(10);
UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING);
udelay(10);
}
return 0;
}
if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
return -EPERM;
if (value == 1)
......@@ -1399,55 +1569,6 @@ core99_sleep_state(struct device_node* node, int param, int value)
return 0;
}
static int __pmac
pangea_modem_enable(struct device_node* node, int param, int value)
{
struct macio_chip* macio;
u8 gpio;
unsigned long flags;
macio = macio_find(node, 0);
if (!macio)
return -ENODEV;
gpio = MACIO_IN8(KL_GPIO_MODEM_RESET);
gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE;
gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA;
if (!value) {
LOCK(flags);
MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
UNLOCK(flags);
(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
mdelay(250);
}
LOCK(flags);
if (value) {
MACIO_OUT8(KL_GPIO_MODEM_POWER,
KEYLARGO_GPIO_OUTPUT_ENABLE);
UNLOCK(flags);
(void)MACIO_IN32(KEYLARGO_FCR2);
mdelay(250);
} else {
MACIO_OUT8(KL_GPIO_MODEM_POWER,
KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
UNLOCK(flags);
}
if (value) {
LOCK(flags);
MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
UNLOCK(flags); mdelay(250); LOCK(flags);
MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
UNLOCK(flags); mdelay(250); LOCK(flags);
MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
UNLOCK(flags); mdelay(250);
}
return 0;
}
static int __pmac
generic_get_mb_info(struct device_node* node, int param, int value)
{
......@@ -1561,6 +1682,26 @@ static struct feature_table_entry core99_features[] __pmacdata = {
{ 0, NULL }
};
/* RackMac
*/
static struct feature_table_entry rackmac_features[] __pmacdata = {
{ PMAC_FTR_SCC_ENABLE, core99_scc_enable },
{ PMAC_FTR_IDE_ENABLE, core99_ide_enable },
{ PMAC_FTR_IDE_RESET, core99_ide_reset },
{ PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },
{ PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },
{ PMAC_FTR_USB_ENABLE, core99_usb_enable },
{ PMAC_FTR_1394_ENABLE, core99_firewire_enable },
{ PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },
{ PMAC_FTR_SLEEP_STATE, core99_sleep_state },
#ifdef CONFIG_SMP
{ PMAC_FTR_RESET_CPU, core99_reset_cpu },
#endif /* CONFIG_SMP */
{ PMAC_FTR_READ_GPIO, core99_read_gpio },
{ PMAC_FTR_WRITE_GPIO, core99_write_gpio },
{ 0, NULL }
};
/* Pangea features
*/
static struct feature_table_entry pangea_features[] __pmacdata = {
......@@ -1581,6 +1722,26 @@ static struct feature_table_entry pangea_features[] __pmacdata = {
{ 0, NULL }
};
/* Intrepid features
*/
static struct feature_table_entry intrepid_features[] __pmacdata = {
{ PMAC_FTR_SCC_ENABLE, core99_scc_enable },
{ PMAC_FTR_MODEM_ENABLE, pangea_modem_enable },
{ PMAC_FTR_IDE_ENABLE, core99_ide_enable },
{ PMAC_FTR_IDE_RESET, core99_ide_reset },
{ PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },
{ PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },
{ PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable },
{ PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable },
{ PMAC_FTR_USB_ENABLE, core99_usb_enable },
{ PMAC_FTR_1394_ENABLE, core99_firewire_enable },
{ PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },
{ PMAC_FTR_SLEEP_STATE, core99_sleep_state },
{ PMAC_FTR_READ_GPIO, core99_read_gpio },
{ PMAC_FTR_WRITE_GPIO, core99_write_gpio },
{ 0, NULL }
};
static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
/* Warning: ordering is important as some models may claim
* beeing compatible with several types
......@@ -1611,11 +1772,11 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
},
{ "AAPL,3400/2400", "PowerBook 3400",
PMAC_TYPE_HOOPER, ohare_features,
PMAC_MB_CAN_SLEEP
PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
},
{ "AAPL,3500", "PowerBook 3500",
PMAC_TYPE_KANGA, ohare_features,
PMAC_MB_CAN_SLEEP
PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
},
{ "AAPL,Gossamer", "PowerMac G3 (Gossamer)",
PMAC_TYPE_GOSSAMER, heathrow_desktop_features,
......@@ -1627,11 +1788,11 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
},
{ "AAPL,PowerBook1998", "PowerBook Wallstreet",
PMAC_TYPE_WALLSTREET, heathrow_laptop_features,
PMAC_MB_CAN_SLEEP
PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
},
{ "AAPL,PowerBook1,1", "PowerBook 101 (Lombard)",
{ "PowerBook1,1", "PowerBook 101 (Lombard)",
PMAC_TYPE_101_PBOOK, paddington_features,
PMAC_MB_CAN_SLEEP
PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
},
{ "iMac,1", "iMac (first generation)",
PMAC_TYPE_ORIG_IMAC, paddington_features,
......@@ -1641,13 +1802,21 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
PMAC_TYPE_PANGEA_IMAC, pangea_features,
PMAC_MB_CAN_SLEEP
},
{ "PowerBook4,2", "iBook 2 with 14\" LCD",
{ "PowerBook4,3", "iBook 2 rev. 2",
PMAC_TYPE_IBOOK2, pangea_features,
PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
},
{ "PowerBook4,2", "iBook 2",
PMAC_TYPE_IBOOK2, pangea_features,
PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
},
{ "PowerBook4,1", "iBook 2",
PMAC_TYPE_IBOOK2, pangea_features,
PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
},
{ "PowerMac4,4", "eMac",
PMAC_TYPE_EMAC, core99_features,
PMAC_MB_CAN_SLEEP
},
{ "PowerMac4,2", "Flat panel iMac",
PMAC_TYPE_FLAT_PANEL_IMAC, pangea_features,
......@@ -1663,34 +1832,35 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
},
{ "PowerBook2,1", "iBook (first generation)",
PMAC_TYPE_ORIG_IBOOK, core99_features,
PMAC_MB_CAN_SLEEP
PMAC_MB_CAN_SLEEP | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
},
{ "PowerMac3,1", "PowerMac G4 AGP Graphics",
PMAC_TYPE_SAWTOOTH, core99_features,
0
PMAC_MB_OLD_CORE99
},
{ "PowerMac3,2", "PowerMac G4 AGP Graphics",
PMAC_TYPE_SAWTOOTH, core99_features,
0
PMAC_MB_OLD_CORE99
},
{ "PowerMac3,3", "PowerMac G4 AGP Graphics",
PMAC_TYPE_SAWTOOTH, core99_features,
0
PMAC_MB_OLD_CORE99
},
{ "PowerMac2,1", "iMac FireWire",
PMAC_TYPE_FW_IMAC, core99_features,
PMAC_MB_CAN_SLEEP
PMAC_MB_CAN_SLEEP | PMAC_MB_OLD_CORE99
},
{ "PowerMac2,2", "iMac FireWire",
PMAC_TYPE_FW_IMAC, core99_features,
PMAC_MB_CAN_SLEEP
PMAC_MB_CAN_SLEEP | PMAC_MB_OLD_CORE99
},
{ "PowerBook2,2", "iBook FireWire",
PMAC_TYPE_FW_IBOOK, core99_features,
PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
},
{ "PowerMac5,1", "PowerMac G4 Cube",
PMAC_TYPE_CUBE, core99_features,
PMAC_MB_OLD_CORE99
},
{ "PowerMac3,4", "PowerMac G4 Silver",
PMAC_TYPE_QUICKSILVER, core99_features,
......@@ -1702,19 +1872,31 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
},
{ "PowerBook3,1", "PowerBook Pismo",
PMAC_TYPE_PISMO, core99_features,
PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
},
{ "PowerBook3,2", "PowerBook Titanium",
PMAC_TYPE_TITANIUM, core99_features,
PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
},
{ "PowerBook3,3", "PowerBook Titanium II",
PMAC_TYPE_TITANIUM2, core99_features,
PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
},
{ "PowerBook3,4", "PowerBook Titanium III",
PMAC_TYPE_TITANIUM3, core99_features,
PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
},
{ "PowerBook3,5", "PowerBook Titanium IV",
PMAC_TYPE_TITANIUM4, core99_features,
PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
},
{ "RackMac1,1", "XServe",
PMAC_TYPE_RACKMAC, rackmac_features,
0,
},
{ "PowerMac3,6", "PowerMac G4 Windtunnel",
PMAC_TYPE_WINDTUNNEL, rackmac_features,
0,
},
};
......@@ -1758,8 +1940,22 @@ probe_motherboard(void)
{
int i;
struct macio_chip* macio = &macio_chips[0];
const char* model = NULL;
struct device_node *dt;
/* Lookup known motherboard type in device-tree */
/* Lookup known motherboard type in device-tree. First try an
* exact match on the "model" property, then try a "compatible"
* match is none is found.
*/
dt = find_devices("device-tree");
if (dt != NULL)
model = (const char *) get_property(dt, "model", NULL);
for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
if (strcmp(model, pmac_mb_defs[i].model_string) == 0) {
pmac_mb = pmac_mb_defs[i];
goto found;
}
}
for(i=0; i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
if (machine_is_compatible(pmac_mb_defs[i].model_string)) {
pmac_mb = pmac_mb_defs[i];
......@@ -1797,6 +1993,11 @@ probe_motherboard(void)
pmac_mb.model_name = "Unknown Pangea-based";
pmac_mb.features = pangea_features;
break;
case macio_intrepid:
pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PANGEA;
pmac_mb.model_name = "Unknown Pangea-based";
pmac_mb.features = intrepid_features;
break;
default:
return -ENODEV;
}
......@@ -1815,6 +2016,7 @@ probe_motherboard(void)
iounmap(mach_id_ptr);
}
#ifdef CONFIG_6xx
/* Set default value of powersave_nap on machines that support it.
* It appears that uninorth rev 3 has a problem with it, we don't
* enable it on those. In theory, the flush-on-lock property is
......@@ -1823,7 +2025,6 @@ probe_motherboard(void)
*/
while (uninorth_base && uninorth_rev > 3) {
struct device_node* np = find_path_device("/cpus");
u32 pvr = mfspr(PVR);
if (!np || !np->child) {
printk(KERN_WARNING "Can't find CPU(s) in device tree !\n");
break;
......@@ -1835,14 +2036,23 @@ probe_motherboard(void)
/* Nap mode not supported if flush-on-lock property is present */
if (get_property(np, "flush-on-lock", NULL))
break;
/* Some 7450 may have problem with NAP mode too ... */
if (((pvr >> 16) == 0x8000) && ((pvr & 0xffff) < 0x0201))
break;
powersave_nap = 1;
printk(KERN_INFO "Processor NAP mode on idle enabled.\n");
break;
}
/* On CPUs that support it (750FX), lowspeed by default during
* NAP mode
*/
powersave_lowspeed = 1;
#endif /* CONFIG_6xx */
/* Check for "mobile" machine */
if (model && (strncmp(model, "PowerBook", 9) == 0
|| strncmp(model, "iBook", 5) == 0))
pmac_mb.board_flags |= PMAC_MB_MOBILE;
printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name);
return 0;
}
......@@ -1857,7 +2067,7 @@ probe_uninorth(void)
/* Locate core99 Uni-N */
uninorth_node = find_devices("uni-n");
if (uninorth_node && uninorth_node->n_addrs > 0) {
uninorth_base = ioremap(uninorth_node->addrs[0].address, 0x1000);
uninorth_base = ioremap(uninorth_node->addrs[0].address, 0x4000);
uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
} else
uninorth_node = NULL;
......@@ -1867,15 +2077,23 @@ probe_uninorth(void)
printk(KERN_INFO "Found Uninorth memory controller & host bridge, revision: %d\n",
uninorth_rev);
printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base);
/* Set the arbitrer QAck delay according to what Apple does
*/
if (uninorth_rev < 0x10) {
if (uninorth_rev < 0x11) {
actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK;
actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 :
UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
UN_OUT(UNI_N_ARB_CTRL, actrl);
}
/* Some more magic as done by them in recent MacOS X on UniNorth
* revs 1.5 to 2.O and Pangea. Seem to toggle the UniN Maxbus/PCI
* memory timeout
*/
if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) || uninorth_rev == 0xc0)
UN_OUT(0x2160, UN_IN(0x2160) & 0x00ffffff);
}
static void __init
......@@ -1917,11 +2135,14 @@ probe_one_macio(const char* name, const char* compat, int type)
u32* did = (u32 *)get_property(node, "device-id", NULL);
if (*did == 0x00000025)
type = macio_pangea;
if (*did == 0x0000003e)
type = macio_intrepid;
}
macio_chips[i].of_node = node;
macio_chips[i].type = type;
macio_chips[i].base = base;
macio_chips[i].flags = MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON;
macio_chips[i].name = macio_names[type];
revp = (u32 *)get_property(node, "revision-id", NULL);
if (revp)
macio_chips[i].rev = *revp;
......@@ -2011,7 +2232,8 @@ set_initial_features(void)
}
if (macio_chips[0].type == macio_keylargo ||
macio_chips[0].type == macio_pangea) {
macio_chips[0].type == macio_pangea ||
macio_chips[0].type == macio_intrepid) {
/* Enable GMAC for now for PCI probing. It will be disabled
* later on after PCI probe
*/
......@@ -2042,6 +2264,17 @@ set_initial_features(void)
np = np->next;
}
/* Enable ATA-100 before PCI probe. */
np = find_devices("ata-6");
while(np) {
if (np->parent
&& device_is_compatible(np->parent, "uni-north")
&& device_is_compatible(np, "kauai-ata")) {
core99_ata100_enable(np, 1);
}
np = np->next;
}
/* Switch airport off */
np = find_devices("radio");
while(np) {
......@@ -2079,9 +2312,6 @@ set_initial_features(void)
initial_serial_shutdown(np);
np = np->next;
}
/* Let hardware settle down */
mdelay(10);
}
void __init
......
......@@ -10,12 +10,13 @@
#define KL_PANGEA_REV 0x100
/* offset from base for feature control registers */
#define KEYLARGO_MBCR 0x34 /* Media bay control/status */
#define KEYLARGO_MBCR 0x34 /* KL Only, Media bay control/status */
#define KEYLARGO_FCR0 0x38
#define KEYLARGO_FCR1 0x3c
#define KEYLARGO_FCR2 0x40
#define KEYLARGO_FCR3 0x44
#define KEYLARGO_FCR4 0x48
#define KEYLARGO_FCR5 0x4c /* Pangea only */
/* GPIO registers */
#define KEYLARGO_GPIO_LEVELS0 0x50
......@@ -85,76 +86,111 @@
#define KL_MBCR_MB1_DEV_RESET 0x02000000
#define KL_MBCR_MB1_ENABLE 0x01000000
#define KL0_SCC_B_INTF_ENABLE 0x00000001
#define KL0_SCC_B_INTF_ENABLE 0x00000001 /* (KL Only) */
#define KL0_SCC_A_INTF_ENABLE 0x00000002
#define KL0_SCC_SLOWPCLK 0x00000004
#define KL0_SCC_RESET 0x00000008
#define KL0_SCCA_ENABLE 0x00000010
#define KL0_SCCB_ENABLE 0x00000020
#define KL0_SCC_CELL_ENABLE 0x00000040
#define KL0_IRDA_HIGH_BAND 0x00000100
#define KL0_IRDA_SOURCE2_SEL 0x00000200
#define KL0_IRDA_SOURCE1_SEL 0x00000400
#define KL0_IRDA_RESET 0x00000800
#define KL0_IRDA_DEFAULT1 0x00001000
#define KL0_IRDA_DEFAULT0 0x00002000
#define KL0_IRDA_FAST_CONNECT 0x00004000
#define KL0_IRDA_ENABLE 0x00008000
#define KL0_IRDA_CLK32_ENABLE 0x00010000
#define KL0_IRDA_CLK19_ENABLE 0x00020000
#define KL0_IRDA_HIGH_BAND 0x00000100 /* (KL Only) */
#define KL0_IRDA_SOURCE2_SEL 0x00000200 /* (KL Only) */
#define KL0_IRDA_SOURCE1_SEL 0x00000400 /* (KL Only) */
#define KL0_PG_USB0_PMI_ENABLE 0x00000400 /* (Pangea/Intrepid Only) */
#define KL0_IRDA_RESET 0x00000800 /* (KL Only) */
#define KL0_PG_USB0_REF_SUSPEND_SEL 0x00000800 /* (Pangea/Intrepid Only) */
#define KL0_IRDA_DEFAULT1 0x00001000 /* (KL Only) */
#define KL0_PG_USB0_REF_SUSPEND 0x00001000 /* (Pangea/Intrepid Only) */
#define KL0_IRDA_DEFAULT0 0x00002000 /* (KL Only) */
#define KL0_PG_USB0_PAD_SUSPEND 0x00002000 /* (Pangea/Intrepid Only) */
#define KL0_IRDA_FAST_CONNECT 0x00004000 /* (KL Only) */
#define KL0_PG_USB1_PMI_ENABLE 0x00004000 /* (Pangea/Intrepid Only) */
#define KL0_IRDA_ENABLE 0x00008000 /* (KL Only) */
#define KL0_PG_USB1_REF_SUSPEND_SEL 0x00008000 /* (Pangea/Intrepid Only) */
#define KL0_IRDA_CLK32_ENABLE 0x00010000 /* (KL Only) */
#define KL0_PG_USB1_REF_SUSPEND 0x00010000 /* (Pangea/Intrepid Only) */
#define KL0_IRDA_CLK19_ENABLE 0x00020000 /* (KL Only) */
#define KL0_PG_USB1_PAD_SUSPEND 0x00020000 /* (Pangea/Intrepid Only) */
#define KL0_USB0_PAD_SUSPEND0 0x00040000
#define KL0_USB0_PAD_SUSPEND1 0x00080000
#define KL0_USB0_CELL_ENABLE 0x00100000
#define KL0_USB1_PAD_SUSPEND0 0x00400000
#define KL0_USB1_PAD_SUSPEND1 0x00800000
#define KL0_USB1_CELL_ENABLE 0x01000000
#define KL0_USB_REF_SUSPEND 0x10000000
#define KL0_USB_REF_SUSPEND 0x10000000 /* (KL Only) */
#define KL0_SERIAL_ENABLE (KL0_SCC_B_INTF_ENABLE | \
KL0_SCC_SLOWPCLK | \
KL0_SCC_CELL_ENABLE | KL0_SCCA_ENABLE)
#define KL1_AUDIO_SEL_22MCLK 0x00000002
#define KL1_AUDIO_CLK_ENABLE_BIT 0x00000008
#define KL1_AUDIO_CLK_OUT_ENABLE 0x00000020 /* Burgundy only ? */
#define KL1_AUDIO_CELL_ENABLE 0x00000040
#define KL1_AUDIO_CHOOSE 0x00000080 /* Burgundy only ? */
#define KL1_USB2_PMI_ENABLE 0x00000001 /* Intrepid only */
#define KL1_AUDIO_SEL_22MCLK 0x00000002 /* KL/Pangea only */
#define KL1_USB2_REF_SUSPEND_SEL 0x00000002 /* Intrepid only */
#define KL1_USB2_REF_SUSPEND 0x00000004 /* Intrepid only */
#define KL1_AUDIO_CLK_ENABLE_BIT 0x00000008 /* KL/Pangea only */
#define KL1_USB2_PAD_SUSPEND_SEL 0x00000008 /* Intrepid only */
#define KL1_USB2_PAD_SUSPEND0 0x00000010 /* Intrepid only */
#define KL1_AUDIO_CLK_OUT_ENABLE 0x00000020 /* KL/Pangea only */
#define KL1_USB2_PAD_SUSPEND1 0x00000020 /* Intrepid only */
#define KL1_AUDIO_CELL_ENABLE 0x00000040 /* KL/Pangea only */
#define KL1_USB2_CELL_ENABLE 0x00000040 /* Intrepid only */
#define KL1_AUDIO_CHOOSE 0x00000080 /* KL/Pangea only */
#define KL1_I2S0_CHOOSE 0x00000200 /* KL Only */
#define KL1_I2S0_CELL_ENABLE 0x00000400
#define KL1_I2S0_CLK_ENABLE_BIT 0x00001000
#define KL1_I2S0_ENABLE 0x00002000
#define KL1_I2S1_CELL_ENABLE 0x00020000
#define KL1_I2S1_CLK_ENABLE_BIT 0x00080000
#define KL1_I2S1_ENABLE 0x00100000
#define KL1_EIDE0_ENABLE 0x00800000
#define KL1_EIDE0_RESET_N 0x01000000
#define KL1_EIDE1_ENABLE 0x04000000
#define KL1_EIDE1_RESET_N 0x08000000
#define KL1_UIDE_ENABLE 0x20000000
#define KL1_UIDE_RESET_N 0x40000000
#define KL1_EIDE0_ENABLE 0x00800000 /* KL/Intrepid Only */
#define KL1_EIDE0_RESET_N 0x01000000 /* KL/Intrepid Only */
#define KL1_EIDE1_ENABLE 0x04000000 /* KL Only */
#define KL1_EIDE1_RESET_N 0x08000000 /* KL Only */
#define KL1_UIDE_ENABLE 0x20000000 /* KL/Pangea Only */
#define KL1_UIDE_RESET_N 0x40000000 /* KL/Pangea Only */
#define KL2_IOBUS_ENABLE 0x00000002
#define KL2_SLEEP_STATE_BIT 0x00000100
#define KL2_SLEEP_STATE_BIT 0x00000100 /* KL Only */
#define KL2_PG_STOP_ALL_CLOCKS 0x00000100 /* Pangea Only */
#define KL2_MPIC_ENABLE 0x00020000
#define KL2_ALT_DATA_OUT 0x02000000
#define KL2_CARDSLOT_RESET 0x00040000 /* Pangea/Intrepid Only */
#define KL2_ALT_DATA_OUT 0x02000000 /* KL Only ??? */
#define KL2_MEM_IS_BIG 0x04000000
#define KL2_CARDSEL_16 0x08000000
#define KL3_SHUTDOWN_PLL_TOTAL 0x00000001
#define KL3_SHUTDOWN_PLLKW6 0x00000002
#define KL3_SHUTDOWN_PLLKW4 0x00000004
#define KL3_SHUTDOWN_PLLKW35 0x00000008
#define KL3_SHUTDOWN_PLLKW12 0x00000010
#define KL3_PLL_RESET 0x00000020
#define KL3_SHUTDOWN_PLL2X 0x00000080
#define KL3_CLK66_ENABLE 0x00000100
#define KL3_SHUTDOWN_PLL_TOTAL 0x00000001 /* KL/Pangea only */
#define KL3_SHUTDOWN_PLLKW6 0x00000002 /* KL/Pangea only */
#define KL3_IT_SHUTDOWN_PLL3 0x00000002 /* Intrepid only */
#define KL3_SHUTDOWN_PLLKW4 0x00000004 /* KL/Pangea only */
#define KL3_IT_SHUTDOWN_PLL2 0x00000004 /* Intrepid only */
#define KL3_SHUTDOWN_PLLKW35 0x00000008 /* KL/Pangea only */
#define KL3_IT_SHUTDOWN_PLL1 0x00000008 /* Intrepid only */
#define KL3_SHUTDOWN_PLLKW12 0x00000010 /* KL Only */
#define KL3_IT_ENABLE_PLL3_SHUTDOWN 0x00000010 /* Intrepid only */
#define KL3_PLL_RESET 0x00000020 /* KL/Pangea only */
#define KL3_IT_ENABLE_PLL2_SHUTDOWN 0x00000020 /* Intrepid only */
#define KL3_IT_ENABLE_PLL1_SHUTDOWN 0x00000010 /* Intrepid only */
#define KL3_SHUTDOWN_PLL2X 0x00000080 /* KL Only */
#define KL3_CLK66_ENABLE 0x00000100 /* KL Only */
#define KL3_CLK49_ENABLE 0x00000200
#define KL3_CLK45_ENABLE 0x00000400
#define KL3_CLK31_ENABLE 0x00000800
#define KL3_CLK31_ENABLE 0x00000800 /* KL/Pangea only */
#define KL3_TIMER_CLK18_ENABLE 0x00001000
#define KL3_I2S1_CLK18_ENABLE 0x00002000
#define KL3_I2S0_CLK18_ENABLE 0x00004000
#define KL3_VIA_CLK16_ENABLE 0x00008000
#define KL3_STOPPING33_ENABLED 0x00080000
#define KL3_VIA_CLK16_ENABLE 0x00008000 /* KL/Pangea only */
#define KL3_IT_VIA_CLK32_ENABLE 0x00008000 /* Intrepid only */
#define KL3_STOPPING33_ENABLED 0x00080000 /* KL Only */
#define KL3_PG_PLL_ENABLE_TEST 0x00080000 /* Pangea Only */
/* Intrepid USB bus 2, port 0,1 */
#define KL3_IT_PORT_WAKEUP_ENABLE(p) (0x00080000 << ((p)<<3))
#define KL3_IT_PORT_RESUME_WAKE_EN(p) (0x00040000 << ((p)<<3))
#define KL3_IT_PORT_CONNECT_WAKE_EN(p) (0x00020000 << ((p)<<3))
#define KL3_IT_PORT_DISCONNECT_WAKE_EN(p) (0x00010000 << ((p)<<3))
#define KL3_IT_PORT_RESUME_STAT(p) (0x00300000 << ((p)<<3))
#define KL3_IT_PORT_CONNECT_STAT(p) (0x00200000 << ((p)<<3))
#define KL3_IT_PORT_DISCONNECT_STAT(p) (0x00100000 << ((p)<<3))
/* Port 0,1 : bus 0, port 2,3 : bus 1 */
#define KL4_PORT_WAKEUP_ENABLE(p) (0x00000008 << ((p)<<3))
......@@ -165,3 +201,10 @@
#define KL4_PORT_CONNECT_STAT(p) (0x00000020 << ((p)<<3))
#define KL4_PORT_DISCONNECT_STAT(p) (0x00000010 << ((p)<<3))
/* Pangea and Intrepid only */
#define KL5_VIA_USE_CLK31 0x000000001 /* Pangea Only */
#define KL5_SCC_USE_CLK31 0x000000002 /* Pangea Only */
#define KL5_PWM_CLK32_EN 0x000000004
#define KL5_CLK3_68_EN 0x000000010
#define KL5_CLK32_EN 0x000000020
#ifndef __MACIO_ASIC_H__
#define __MACIO_ASIC_H__
#include <linux/device.h>
extern struct bus_type macio_bus_type;
/* MacIO device driver is defined later */
struct macio_driver;
struct macio_chip;
#define MACIO_DEV_COUNT_RESOURCE 8
#define MACIO_DEV_COUNT_IRQS 8
/*
* the macio_bus structure is used to describe a "virtual" bus
* within a MacIO ASIC. It's typically provided by a macio_pci_asic
* PCI device, but could be provided differently as well (nubus
* machines using a fake OF tree).
*/
struct macio_bus
{
struct macio_chip *chip; /* macio_chip (private use) */
struct pci_dev *pdev; /* PCI device hosting this bus */
struct list_head devices; /* list of devices on this bus */
};
/*
* the macio_dev structure is used to describe a device
* within an Apple MacIO ASIC.
*/
struct macio_dev
{
struct macio_bus *bus; /* virtual bus this device is on */
struct device_node *node; /* OF node */
struct macio_driver *driver; /* which driver allocated this device */
void *driver_data; /* placeholder for driver specific stuffs */
struct resource resources[MACIO_DEV_COUNT_RESOURCE]; /* I/O */
int irqs[MACIO_DEV_COUNT_IRQS];
struct device dev; /* Generic device interface */
};
#define to_macio_device(d) container_of(d, struct macio_dev, dev)
/*
* Struct used for matching a device
*/
struct macio_match
{
char *name;
char *type;
char *compatible;
};
#define MACIO_ANY_MATCH ((char *)-1L)
/*
* A driver for a mac-io chip based device
*/
struct macio_driver
{
struct list_head node;
char *name;
struct macio_match *match_table;
int (*probe)(struct macio_dev* dev, const struct macio_match *match);
int (*remove)(struct macio_dev* dev);
int (*suspend)(struct macio_dev* dev, u32 state, u32 level);
int (*resume)(struct macio_dev* dev, u32 level);
int (*shutdown)(struct macio_dev* dev);
struct device_driver driver;
};
#define to_macio_driver(drv) container_of(drv,struct macio_driver, driver)
extern int macio_register_driver(struct macio_driver *);
extern void macio_unregister_driver(struct macio_driver *);
#endif /* __MACIO_ASIC_H__ */
......@@ -31,10 +31,16 @@
#ifndef __PPC_ASM_PMAC_FEATURE_H
#define __PPC_ASM_PMAC_FEATURE_H
#include <asm/macio_asic.h>
/*
* Known Mac motherboard models
*
* Please, report any error here to benh@kernel.crashing.org, thanks !
*
* Note that I don't fully maintain this list for Core99 & MacRISC2
* and I'm considering removing all NewWorld entries from it and
* entirely rely on the model string.
*/
/* PowerSurge are the first generation of PCI Pmacs. This include
......@@ -85,10 +91,16 @@
#define PMAC_TYPE_QUICKSILVER 0x45 /* QuickSilver G4s */
#define PMAC_TYPE_PISMO 0x46 /* Pismo PowerBook */
#define PMAC_TYPE_TITANIUM 0x47 /* Titanium PowerBook */
#define PMAC_TYPE_TITANIUM2 0x48 /* Titanium II PowerBook */
#define PMAC_TYPE_TITANIUM3 0x49 /* Titanium III PowerBook (with L3) */
#define PMAC_TYPE_TITANIUM2 0x48 /* Titanium II PowerBook (no L3, M6) */
#define PMAC_TYPE_TITANIUM3 0x49 /* Titanium III PowerBook (with L3 & M7) */
#define PMAC_TYPE_TITANIUM4 0x50 /* Titanium IV PowerBook (with L3 & M9) */
#define PMAC_TYPE_EMAC 0x50 /* eMac */
#define PMAC_TYPE_UNKNOWN_CORE99 0x5f
/* MacRisc2 with UniNorth 2.0 */
#define PMAC_TYPE_RACKMAC 0x80 /* XServe */
#define PMAC_TYPE_WINDTUNNEL 0x81
/* MacRISC2 machines based on the Pangea chipset
*/
#define PMAC_TYPE_PANGEA_IMAC 0x100 /* Flower Power iMac */
......@@ -96,12 +108,18 @@
#define PMAC_TYPE_FLAT_PANEL_IMAC 0x102 /* Flat panel iMac */
#define PMAC_TYPE_UNKNOWN_PANGEA 0x10f
/* MacRISC2 machines based on the Intrepid chipset
*/
#define PMAC_TYPE_UNKNOWN_INTREPID 0x11f /* Generic */
/*
* Motherboard flags
*/
#define PMAC_MB_CAN_SLEEP 0x00000001
#define PMAC_MB_HAS_FW_POWER 0x00000002
#define PMAC_MB_OLD_CORE99 0x00000004
#define PMAC_MB_MOBILE 0x00000008
/*
* Feature calls supported on pmac
......@@ -251,5 +269,60 @@ extern void pmac_feature_init(void);
#define PMAC_FTR_DEF(x) ((_MACH_Pmac << 16) | (x))
/*
* The part below is for use by macio_asic.c only, do not rely
* on the data structures or constants below in a normal driver
*
*/
#define MAX_MACIO_CHIPS 2
enum {
macio_unknown = 0,
macio_grand_central,
macio_ohare,
macio_ohareII,
macio_heathrow,
macio_gatwick,
macio_paddington,
macio_keylargo,
macio_pangea,
macio_intrepid,
};
struct macio_chip
{
struct device_node *of_node;
int type;
const char *name;
int rev;
volatile u32 *base;
unsigned long flags;
/* For use by macio_asic PCI driver */
struct macio_bus lbus;
};
extern struct macio_chip macio_chips[MAX_MACIO_CHIPS];
#define MACIO_FLAG_SCCA_ON 0x00000001
#define MACIO_FLAG_SCCB_ON 0x00000002
#define MACIO_FLAG_SCC_LOCKED 0x00000004
#define MACIO_FLAG_AIRPORT_ON 0x00000010
#define MACIO_FLAG_FW_SUPPORTED 0x00000020
extern struct macio_chip* macio_find(struct device_node* child, int type);
#define MACIO_FCR32(macio, r) ((macio)->base + ((r) >> 2))
#define MACIO_FCR8(macio, r) (((volatile u8*)((macio)->base)) + (r))
#define MACIO_IN32(r) (in_le32(MACIO_FCR32(macio,r)))
#define MACIO_OUT32(r,v) (out_le32(MACIO_FCR32(macio,r), (v)))
#define MACIO_BIS(r,v) (MACIO_OUT32((r), MACIO_IN32(r) | (v)))
#define MACIO_BIC(r,v) (MACIO_OUT32((r), MACIO_IN32(r) & ~(v)))
#define MACIO_IN8(r) (in_8(MACIO_FCR8(macio,r)))
#define MACIO_OUT8(r,v) (out_8(MACIO_FCR8(macio,r), (v)))
#endif /* __PPC_ASM_PMAC_FEATURE_H */
#endif /* __KERNEL__ */
......@@ -28,6 +28,7 @@
#define UNI_N_CFG_GART_INVAL 0x00000001
#define UNI_N_CFG_GART_ENABLE 0x00000100
#define UNI_N_CFG_GART_2xRESET 0x00010000
#define UNI_N_CFG_GART_DISSBADET 0x00020000
/* My understanding of UniNorth AGP as of UniNorth rev 1.0x,
* revision 1.5 (x4 AGP) may need further changes.
......@@ -94,6 +95,7 @@
#define UNI_N_CLOCK_CNTL_PCI 0x00000001 /* PCI2 clock control */
#define UNI_N_CLOCK_CNTL_GMAC 0x00000002 /* GMAC clock control */
#define UNI_N_CLOCK_CNTL_FW 0x00000004 /* FireWire clock control */
#define UNI_N_CLOCK_CNTL_ATA100 0x00000010 /* ATA-100 clock control (U2) */
/* Power Management control */
#define UNI_N_POWER_MGT 0x0030
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment