Commit a7fdd90b authored by Paul Mackerras's avatar Paul Mackerras
Browse files

[PATCH] ppc: Remove powermac support from ARCH=ppc


This makes it possible to build kernels for PReP and/or CHRP
with ARCH=ppc by removing the (non-building) powermac support.
It's now also possible to select PReP and CHRP independently.
Powermac users should now build with ARCH=powerpc instead of
ARCH=ppc.  (This does mean that it is no longer possible to
build a 32-bit kernel for a G5.)
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent e8625d46
/*
* arch/ppc/platforms/pmac_low_i2c.c
*
* Copyright (C) 2003 Ben. Herrenschmidt (benh@kernel.crashing.org)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* This file contains some low-level i2c access routines that
* need to be used by various bits of the PowerMac platform code
* at times where the real asynchronous & interrupt driven driver
* cannot be used. The API borrows some semantics from the darwin
* driver in order to ease the implementation of the platform
* properties parser
*/
#include <linux/config.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/adb.h>
#include <linux/pmu.h>
#include <asm/keylargo.h>
#include <asm/uninorth.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/pmac_low_i2c.h>
#define MAX_LOW_I2C_HOST 4
#if 1
#define DBG(x...) do {\
printk(KERN_DEBUG "KW:" x); \
} while(0)
#else
#define DBGG(x...)
#endif
struct low_i2c_host;
typedef int (*low_i2c_func_t)(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len);
struct low_i2c_host
{
struct device_node *np; /* OF device node */
struct semaphore mutex; /* Access mutex for use by i2c-keywest */
low_i2c_func_t func; /* Access function */
int is_open : 1; /* Poor man's access control */
int mode; /* Current mode */
int channel; /* Current channel */
int num_channels; /* Number of channels */
void __iomem * base; /* For keywest-i2c, base address */
int bsteps; /* And register stepping */
int speed; /* And speed */
};
static struct low_i2c_host low_i2c_hosts[MAX_LOW_I2C_HOST];
/* No locking is necessary on allocation, we are running way before
* anything can race with us
*/
static struct low_i2c_host *find_low_i2c_host(struct device_node *np)
{
int i;
for (i = 0; i < MAX_LOW_I2C_HOST; i++)
if (low_i2c_hosts[i].np == np)
return &low_i2c_hosts[i];
return NULL;
}
/*
*
* i2c-keywest implementation (UniNorth, U2, U3, Keylargo's)
*
*/
/*
* Keywest i2c definitions borrowed from drivers/i2c/i2c-keywest.h,
* should be moved somewhere in include/asm-ppc/
*/
/* Register indices */
typedef enum {
reg_mode = 0,
reg_control,
reg_status,
reg_isr,
reg_ier,
reg_addr,
reg_subaddr,
reg_data
} reg_t;
/* Mode register */
#define KW_I2C_MODE_100KHZ 0x00
#define KW_I2C_MODE_50KHZ 0x01
#define KW_I2C_MODE_25KHZ 0x02
#define KW_I2C_MODE_DUMB 0x00
#define KW_I2C_MODE_STANDARD 0x04
#define KW_I2C_MODE_STANDARDSUB 0x08
#define KW_I2C_MODE_COMBINED 0x0C
#define KW_I2C_MODE_MODE_MASK 0x0C
#define KW_I2C_MODE_CHAN_MASK 0xF0
/* Control register */
#define KW_I2C_CTL_AAK 0x01
#define KW_I2C_CTL_XADDR 0x02
#define KW_I2C_CTL_STOP 0x04
#define KW_I2C_CTL_START 0x08
/* Status register */
#define KW_I2C_STAT_BUSY 0x01
#define KW_I2C_STAT_LAST_AAK 0x02
#define KW_I2C_STAT_LAST_RW 0x04
#define KW_I2C_STAT_SDA 0x08
#define KW_I2C_STAT_SCL 0x10
/* IER & ISR registers */
#define KW_I2C_IRQ_DATA 0x01
#define KW_I2C_IRQ_ADDR 0x02
#define KW_I2C_IRQ_STOP 0x04
#define KW_I2C_IRQ_START 0x08
#define KW_I2C_IRQ_MASK 0x0F
/* State machine states */
enum {
state_idle,
state_addr,
state_read,
state_write,
state_stop,
state_dead
};
#define WRONG_STATE(name) do {\
printk(KERN_DEBUG "KW: wrong state. Got %s, state: %s (isr: %02x)\n", \
name, __kw_state_names[state], isr); \
} while(0)
static const char *__kw_state_names[] = {
"state_idle",
"state_addr",
"state_read",
"state_write",
"state_stop",
"state_dead"
};
static inline u8 __kw_read_reg(struct low_i2c_host *host, reg_t reg)
{
return in_8(host->base + (((unsigned)reg) << host->bsteps));
}
static inline void __kw_write_reg(struct low_i2c_host *host, reg_t reg, u8 val)
{
out_8(host->base + (((unsigned)reg) << host->bsteps), val);
(void)__kw_read_reg(host, reg_subaddr);
}
#define kw_write_reg(reg, val) __kw_write_reg(host, reg, val)
#define kw_read_reg(reg) __kw_read_reg(host, reg)
/* Don't schedule, the g5 fan controller is too
* timing sensitive
*/
static u8 kw_wait_interrupt(struct low_i2c_host* host)
{
int i;
u8 isr;
for (i = 0; i < 200000; i++) {
isr = kw_read_reg(reg_isr) & KW_I2C_IRQ_MASK;
if (isr != 0)
return isr;
udelay(1);
}
return isr;
}
static int kw_handle_interrupt(struct low_i2c_host *host, int state, int rw, int *rc, u8 **data, int *len, u8 isr)
{
u8 ack;
if (isr == 0) {
if (state != state_stop) {
DBG("KW: Timeout !\n");
*rc = -EIO;
goto stop;
}
if (state == state_stop) {
ack = kw_read_reg(reg_status);
if (!(ack & KW_I2C_STAT_BUSY)) {
state = state_idle;
kw_write_reg(reg_ier, 0x00);
}
}
return state;
}
if (isr & KW_I2C_IRQ_ADDR) {
ack = kw_read_reg(reg_status);
if (state != state_addr) {
kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
WRONG_STATE("KW_I2C_IRQ_ADDR");
*rc = -EIO;
goto stop;
}
if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
*rc = -ENODEV;
DBG("KW: NAK on address\n");
return state_stop;
} else {
if (rw) {
state = state_read;
if (*len > 1)
kw_write_reg(reg_control, KW_I2C_CTL_AAK);
} else {
state = state_write;
kw_write_reg(reg_data, **data);
(*data)++; (*len)--;
}
}
kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
}
if (isr & KW_I2C_IRQ_DATA) {
if (state == state_read) {
**data = kw_read_reg(reg_data);
(*data)++; (*len)--;
kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
if ((*len) == 0)
state = state_stop;
else if ((*len) == 1)
kw_write_reg(reg_control, 0);
} else if (state == state_write) {
ack = kw_read_reg(reg_status);
if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
DBG("KW: nack on data write\n");
*rc = -EIO;
goto stop;
} else if (*len) {
kw_write_reg(reg_data, **data);
(*data)++; (*len)--;
} else {
kw_write_reg(reg_control, KW_I2C_CTL_STOP);
state = state_stop;
*rc = 0;
}
kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
} else {
kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
WRONG_STATE("KW_I2C_IRQ_DATA");
if (state != state_stop) {
*rc = -EIO;
goto stop;
}
}
}
if (isr & KW_I2C_IRQ_STOP) {
kw_write_reg(reg_isr, KW_I2C_IRQ_STOP);
if (state != state_stop) {
WRONG_STATE("KW_I2C_IRQ_STOP");
*rc = -EIO;
}
return state_idle;
}
if (isr & KW_I2C_IRQ_START)
kw_write_reg(reg_isr, KW_I2C_IRQ_START);
return state;
stop:
kw_write_reg(reg_control, KW_I2C_CTL_STOP);
return state_stop;
}
static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr, u8 *data, int len)
{
u8 mode_reg = host->speed;
int state = state_addr;
int rc = 0;
/* Setup mode & subaddress if any */
switch(host->mode) {
case pmac_low_i2c_mode_dumb:
printk(KERN_ERR "low_i2c: Dumb mode not supported !\n");
return -EINVAL;
case pmac_low_i2c_mode_std:
mode_reg |= KW_I2C_MODE_STANDARD;
break;
case pmac_low_i2c_mode_stdsub:
mode_reg |= KW_I2C_MODE_STANDARDSUB;
kw_write_reg(reg_subaddr, subaddr);
break;
case pmac_low_i2c_mode_combined:
mode_reg |= KW_I2C_MODE_COMBINED;
kw_write_reg(reg_subaddr, subaddr);
break;
}
/* Setup channel & clear pending irqs */
kw_write_reg(reg_isr, kw_read_reg(reg_isr));
kw_write_reg(reg_mode, mode_reg | (host->channel << 4));
kw_write_reg(reg_status, 0);
/* Set up address and r/w bit */
kw_write_reg(reg_addr, addr);
/* Start sending address & disable interrupt*/
kw_write_reg(reg_ier, 0 /*KW_I2C_IRQ_MASK*/);
kw_write_reg(reg_control, KW_I2C_CTL_XADDR);
/* State machine, to turn into an interrupt handler */
while(state != state_idle) {
u8 isr = kw_wait_interrupt(host);
state = kw_handle_interrupt(host, state, addr & 1, &rc, &data, &len, isr);
}
return rc;
}
static void keywest_low_i2c_add(struct device_node *np)
{
struct low_i2c_host *host = find_low_i2c_host(NULL);
unsigned long *psteps, *prate, steps, aoffset = 0;
struct device_node *parent;
if (host == NULL) {
printk(KERN_ERR "low_i2c: Can't allocate host for %s\n",
np->full_name);
return;
}
memset(host, 0, sizeof(*host));
init_MUTEX(&host->mutex);
host->np = of_node_get(np);
psteps = (unsigned long *)get_property(np, "AAPL,address-step", NULL);
steps = psteps ? (*psteps) : 0x10;
for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++)
steps >>= 1;
parent = of_get_parent(np);
host->num_channels = 1;
if (parent && parent->name[0] == 'u') {
host->num_channels = 2;
aoffset = 3;
}
/* Select interface rate */
host->speed = KW_I2C_MODE_100KHZ;
prate = (unsigned long *)get_property(np, "AAPL,i2c-rate", NULL);
if (prate) switch(*prate) {
case 100:
host->speed = KW_I2C_MODE_100KHZ;
break;
case 50:
host->speed = KW_I2C_MODE_50KHZ;
break;
case 25:
host->speed = KW_I2C_MODE_25KHZ;
break;
}
host->mode = pmac_low_i2c_mode_std;
host->base = ioremap(np->addrs[0].address + aoffset,
np->addrs[0].size);
host->func = keywest_low_i2c_func;
}
/*
*
* PMU implementation
*
*/
#ifdef CONFIG_ADB_PMU
static int pmu_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len)
{
// TODO
return -ENODEV;
}
static void pmu_low_i2c_add(struct device_node *np)
{
struct low_i2c_host *host = find_low_i2c_host(NULL);
if (host == NULL) {
printk(KERN_ERR "low_i2c: Can't allocate host for %s\n",
np->full_name);
return;
}
memset(host, 0, sizeof(*host));
init_MUTEX(&host->mutex);
host->np = of_node_get(np);
host->num_channels = 3;
host->mode = pmac_low_i2c_mode_std;
host->func = pmu_low_i2c_func;
}
#endif /* CONFIG_ADB_PMU */
void __init pmac_init_low_i2c(void)
{
struct device_node *np;
/* Probe keywest-i2c busses */
np = of_find_compatible_node(NULL, "i2c", "keywest-i2c");
while(np) {
keywest_low_i2c_add(np);
np = of_find_compatible_node(np, "i2c", "keywest-i2c");
}
#ifdef CONFIG_ADB_PMU
/* Probe PMU busses */
np = of_find_node_by_name(NULL, "via-pmu");
if (np)
pmu_low_i2c_add(np);
#endif /* CONFIG_ADB_PMU */
/* TODO: Add CUDA support as well */
}
int pmac_low_i2c_lock(struct device_node *np)
{
struct low_i2c_host *host = find_low_i2c_host(np);
if (!host)
return -ENODEV;
down(&host->mutex);
return 0;
}
EXPORT_SYMBOL(pmac_low_i2c_lock);
int pmac_low_i2c_unlock(struct device_node *np)
{
struct low_i2c_host *host = find_low_i2c_host(np);
if (!host)
return -ENODEV;
up(&host->mutex);
return 0;
}
EXPORT_SYMBOL(pmac_low_i2c_unlock);
int pmac_low_i2c_open(struct device_node *np, int channel)
{
struct low_i2c_host *host = find_low_i2c_host(np);
if (!host)
return -ENODEV;
if (channel >= host->num_channels)
return -EINVAL;
down(&host->mutex);
host->is_open = 1;
host->channel = channel;
return 0;
}
EXPORT_SYMBOL(pmac_low_i2c_open);
int pmac_low_i2c_close(struct device_node *np)
{
struct low_i2c_host *host = find_low_i2c_host(np);
if (!host)
return -ENODEV;
host->is_open = 0;
up(&host->mutex);
return 0;
}
EXPORT_SYMBOL(pmac_low_i2c_close);
int pmac_low_i2c_setmode(struct device_node *np, int mode)
{
struct low_i2c_host *host = find_low_i2c_host(np);
if (!host)
return -ENODEV;
WARN_ON(!host->is_open);
host->mode = mode;
return 0;
}
EXPORT_SYMBOL(pmac_low_i2c_setmode);
int pmac_low_i2c_xfer(struct device_node *np, u8 addrdir, u8 subaddr, u8 *data, int len)
{
struct low_i2c_host *host = find_low_i2c_host(np);
if (!host)
return -ENODEV;
WARN_ON(!host->is_open);
return host->func(host, addrdir, subaddr, data, len);
}
EXPORT_SYMBOL(pmac_low_i2c_xfer);
/*
* arch/ppc/platforms/pmac_nvram.c
*
* Copyright (C) 2002 Benjamin Herrenschmidt (benh@kernel.crashing.org)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Todo: - add support for the OF persistent properties
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/stddef.h>
#include <linux/string.h>
#include <linux/nvram.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/adb.h>
#include <linux/pmu.h>
#include <linux/bootmem.h>
#include <linux/completion.h>
#include <linux/spinlock.h>
#include <asm/sections.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/nvram.h>
#define DEBUG
#ifdef DEBUG
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
#define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */
#define CORE99_SIGNATURE 0x5a
#define CORE99_ADLER_START 0x14
/* On Core99, nvram is either a sharp, a micron or an AMD flash */
#define SM_FLASH_STATUS_DONE 0x80
#define SM_FLASH_STATUS_ERR 0x38
#define SM_FLASH_CMD_ERASE_CONFIRM 0xd0
#define SM_FLASH_CMD_ERASE_SETUP 0x20
#define SM_FLASH_CMD_RESET 0xff
#define SM_FLASH_CMD_WRITE_SETUP 0x40
#define SM_FLASH_CMD_CLEAR_STATUS 0x50
#define SM_FLASH_CMD_READ_STATUS 0x70
/* CHRP NVRAM header */
struct chrp_header {
u8 signature;
u8 cksum;
u16 len;
char name[12];
u8 data[0];
};
struct core99_header {
struct chrp_header hdr;
u32 adler;
u32 generation;
u32 reserved[2];
};
/*
* Read and write the non-volatile RAM on PowerMacs and CHRP machines.
*/
static int nvram_naddrs;
static volatile unsigned char *nvram_addr;
static volatile unsigned char *nvram_data;
static int nvram_mult, is_core_99;
static int core99_bank = 0;
static int nvram_partitions[3];
static DEFINE_SPINLOCK(nv_lock);
extern int pmac_newworld;
extern int system_running;
static int (*core99_write_bank)(int bank, u8* datas);
static int (*core99_erase_bank)(int bank);
static char *nvram_image;
static unsigned char core99_nvram_read_byte(int addr)
{
if (nvram_image == NULL)
return 0xff;
return nvram_image[addr];
}
static void core99_nvram_write_byte(int addr, unsigned char val)
{
if (nvram_image == NULL)
return;
nvram_image[addr] = val;
}
static unsigned char direct_nvram_read_byte(int addr)
{
return in_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult]);
}
static void direct_nvram_write_byte(int addr, unsigned char val)
{
out_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult], val);
}
static unsigned char indirect_nvram_read_byte(int addr)
{
unsigned char val;
unsigned long flags;
spin_lock_irqsave(&nv_lock, flags);
out_8(nvram_addr, addr >> 5);
val = in_8(&nvram_data[(addr & 0x1f) << 4]);
spin_unlock_irqrestore(&nv_lock, flags);
return val;
}
static void indirect_nvram_write_byte(int addr, unsigned char val)
{
unsigned long flags;
spin_lock_irqsave(&nv_lock, flags);
out_8(nvram_addr, addr >> 5);
out_8(&nvram_data[(addr & 0x1f) << 4], val);
spin_unlock_irqrestore(&nv_lock, flags);
}
#ifdef CONFIG_ADB_PMU
static void pmu_nvram_complete(struct adb_request *req)
{
if (req->arg)
complete((struct completion *)req->arg);
}
static unsigned char pmu_nvram_read_byte(int addr)
{
struct adb_request req;
DECLARE_COMPLETION(req_complete);
req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;
if (pmu_request(&req, pmu_nvram_complete, 3, PMU_READ_NVRAM,
(addr >> 8) & 0xff, addr & 0xff))
return 0xff;
if (system_state == SYSTEM_RUNNING)
wait_for_completion(&req_complete);
while (!req.complete)
pmu_poll();
return req.reply[0];
}
static void pmu_nvram_write_byte(int addr, unsigned char val)
{
struct adb_request req;
DECLARE_COMPLETION(req_complete);
req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;
if (pmu_request(&req, pmu_nvram_complete, 4, PMU_WRITE_NVRAM,
(addr >> 8) & 0xff, addr & 0xff, val))
return;
if (system_state == SYSTEM_RUNNING)
wait_for_completion(&req_complete);
while (!req.complete)
pmu_poll();
}
#endif /* CONFIG_ADB_PMU */
static u8 chrp_checksum(struct chrp_header* hdr)
{
u8 *ptr;
u16 sum = hdr->signature;
for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++)
sum += *ptr;
while (sum > 0xFF)
sum = (sum & 0xFF) + (sum>>8);
return sum;
}
static u32 core99_calc_adler(u8 *buffer)
{
int cnt;
u32 low, high;
buffer += CORE99_ADLER_START;
low = 1;
high = 0;
for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) {
if ((cnt % 5000) == 0) {
high %= 65521UL;
high %= 65521UL;
}
low += buffer[cnt];
high += low;
}
low %= 65521UL;
high %= 65521UL;
return (high << 16) | low;
}
static u32 core99_check(u8* datas)
{
struct core99_header* hdr99 = (struct core99_header*)datas;
if (hdr99->hdr.signature != CORE99_SIGNATURE) {
DBG("Invalid signature\n");
return 0;
}
if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) {
DBG("Invalid checksum\n");
return 0;
}
if (hdr99->adler != core99_calc_adler(datas)) {
DBG("Invalid adler\n");
return 0;
}
return hdr99->generation;
}
static int sm_erase_bank(int bank)
{
int stat, i;
unsigned long timeout;
u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank);
out_8(base, SM_FLASH_CMD_ERASE_SETUP);
out_8(base, SM_FLASH_CMD_ERASE_CONFIRM);
timeout = 0;
do {
if (++timeout > 1000000) {
printk(KERN_ERR "nvram: Sharp/Miron flash erase timeout !\n");
break;
}
out_8(base, SM_FLASH_CMD_READ_STATUS);
stat = in_8(base);
} while (!(stat & SM_FLASH_STATUS_DONE));
out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
out_8(base, SM_FLASH_CMD_RESET);
for (i=0; i<NVRAM_SIZE; i++)
if (base[i] != 0xff) {
printk(KERN_ERR "nvram: Sharp/Micron flash erase failed !\n");
return -ENXIO;
}
return 0;
}
static int sm_write_bank(int bank, u8* datas)
{
int i, stat = 0;
unsigned long timeout;
u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
DBG("nvram: Sharp/Micron Writing bank %d...\n", bank);
for (i=0; i<NVRAM_SIZE; i++) {
out_8(base+i, SM_FLASH_CMD_WRITE_SETUP);
udelay(1);
out_8(base+i, datas[i]);
timeout = 0;
do {
if (++timeout > 1000000) {
printk(KERN_ERR "nvram: Sharp/Micron flash write timeout !\n");
break;
}
out_8(base, SM_FLASH_CMD_READ_STATUS);
stat = in_8(base);
} while (!(stat & SM_FLASH_STATUS_DONE));
if (!(stat & SM_FLASH_STATUS_DONE))
break;
}
out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
out_8(base, SM_FLASH_CMD_RESET);
for (i=0; i<NVRAM_SIZE; i++)
if (base[i] != datas[i]) {
printk(KERN_ERR "nvram: Sharp/Micron flash write failed !\n");
return -ENXIO;
}
return 0;
}
static int amd_erase_bank(int bank)
{
int i, stat = 0;
unsigned long timeout;
u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
DBG("nvram: AMD Erasing bank %d...\n", bank);
/* Unlock 1 */
out_8(base+0x555, 0xaa);
udelay(1);
/* Unlock 2 */
out_8(base+0x2aa, 0x55);
udelay(1);
/* Sector-Erase */
out_8(base+0x555, 0x80);
udelay(1);
out_8(base+0x555, 0xaa);
udelay(1);
out_8(base+0x2aa, 0x55);
udelay(1);
out_8(base, 0x30);
udelay(1);
timeout = 0;
do {
if (++timeout > 1000000) {
printk(KERN_ERR "nvram: AMD flash erase timeout !\n");
break;
}
stat = in_8(base) ^ in_8(base);
} while (stat != 0);
/* Reset */
out_8(base, 0xf0);
udelay(1);
for (i=0; i<NVRAM_SIZE; i++)
if (base[i] != 0xff) {
printk(KERN_ERR "nvram: AMD flash erase failed !\n");
return -ENXIO;
}
return 0;
}
static int amd_write_bank(int bank, u8* datas)
{
int i, stat = 0;
unsigned long timeout;
u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
DBG("nvram: AMD Writing bank %d...\n", bank);
for (i=0; i<NVRAM_SIZE; i++) {
/* Unlock 1 */
out_8(base+0x555, 0xaa);
udelay(1);
/* Unlock 2 */
out_8(base+0x2aa, 0x55);
udelay(1);
/* Write single word */
out_8(base+0x555, 0xa0);
udelay(1);
out_8(base+i, datas[i]);
timeout = 0;
do {
if (++timeout > 1000000) {
printk(KERN_ERR "nvram: AMD flash write timeout !\n");
break;
}
stat = in_8(base) ^ in_8(base);
} while (stat != 0);
if (stat != 0)
break;
}
/* Reset */
out_8(base, 0xf0);
udelay(1);
for (i=0; i<NVRAM_SIZE; i++)
if (base[i] != datas[i]) {
printk(KERN_ERR "nvram: AMD flash write failed !\n");
return -ENXIO;
}
return 0;
}
static void __init lookup_partitions(void)
{
u8 buffer[17];
int i, offset;
struct chrp_header* hdr;
if (pmac_newworld) {
nvram_partitions[pmac_nvram_OF] = -1;
nvram_partitions[pmac_nvram_XPRAM] = -1;
nvram_partitions[pmac_nvram_NR] = -1;
hdr = (struct chrp_header *)buffer;
offset = 0;
buffer[16] = 0;
do {
for (i=0;i<16;i++)
buffer[i] = nvram_read_byte(offset+i);
if (!strcmp(hdr->name, "common"))
nvram_partitions[pmac_nvram_OF] = offset + 0x10;
if (!strcmp(hdr->name, "APL,MacOS75")) {
nvram_partitions[pmac_nvram_XPRAM] = offset + 0x10;
nvram_partitions[pmac_nvram_NR] = offset + 0x110;
}
offset += (hdr->len * 0x10);
} while(offset < NVRAM_SIZE);
} else {
nvram_partitions[pmac_nvram_OF] = 0x1800;
nvram_partitions[pmac_nvram_XPRAM] = 0x1300;
nvram_partitions[pmac_nvram_NR] = 0x1400;
}
DBG("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]);
DBG("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]);
DBG("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]);
}
static void core99_nvram_sync(void)
{
struct core99_header* hdr99;
unsigned long flags;
if (!is_core_99 || !nvram_data || !nvram_image)
return;
spin_lock_irqsave(&nv_lock, flags);
if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE,
NVRAM_SIZE))
goto bail;
DBG("Updating nvram...\n");
hdr99 = (struct core99_header*)nvram_image;
hdr99->generation++;
hdr99->hdr.signature = CORE99_SIGNATURE;
hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr);
hdr99->adler = core99_calc_adler(nvram_image);
core99_bank = core99_bank ? 0 : 1;
if (core99_erase_bank)
if (core99_erase_bank(core99_bank)) {
printk("nvram: Error erasing bank %d\n", core99_bank);
goto bail;
}
if (core99_write_bank)
if (core99_write_bank(core99_bank, nvram_image))
printk("nvram: Error writing bank %d\n", core99_bank);
bail:
spin_unlock_irqrestore(&nv_lock, flags);
#ifdef DEBUG
mdelay(2000);
#endif
}
void __init pmac_nvram_init(void)
{
struct device_node *dp;
nvram_naddrs = 0;
dp = find_devices("nvram");
if (dp == NULL) {
printk(KERN_ERR "Can't find NVRAM device\n");
return;
}
nvram_naddrs = dp->n_addrs;
is_core_99 = device_is_compatible(dp, "nvram,flash");
if (is_core_99) {
int i;
u32 gen_bank0, gen_bank1;
if (nvram_naddrs < 1) {
printk(KERN_ERR "nvram: no address\n");
return;
}
nvram_image = alloc_bootmem(NVRAM_SIZE);
if (nvram_image == NULL) {
printk(KERN_ERR "nvram: can't allocate ram image\n");
return;
}
nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2);
nvram_naddrs = 1; /* Make sure we get the correct case */
DBG("nvram: Checking bank 0...\n");
gen_bank0 = core99_check((u8 *)nvram_data);
gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE);
core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0;
DBG("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1);
DBG("nvram: Active bank is: %d\n", core99_bank);
for (i=0; i<NVRAM_SIZE; i++)
nvram_image[i] = nvram_data[i + core99_bank*NVRAM_SIZE];
ppc_md.nvram_read_val = core99_nvram_read_byte;
ppc_md.nvram_write_val = core99_nvram_write_byte;
ppc_md.nvram_sync = core99_nvram_sync;
/*
* Maybe we could be smarter here though making an exclusive list
* of known flash chips is a bit nasty as older OF didn't provide us
* with a useful "compatible" entry. A solution would be to really
* identify the chip using flash id commands and base ourselves on
* a list of known chips IDs
*/
if (device_is_compatible(dp, "amd-0137")) {
core99_erase_bank = amd_erase_bank;
core99_write_bank = amd_write_bank;
} else {
core99_erase_bank = sm_erase_bank;
core99_write_bank = sm_write_bank;
}
} else if (_machine == _MACH_chrp && nvram_naddrs == 1) {
nvram_data = ioremap(dp->addrs[0].address + isa_mem_base,
dp->addrs[0].size);
nvram_mult = 1;
ppc_md.nvram_read_val = direct_nvram_read_byte;
ppc_md.nvram_write_val = direct_nvram_write_byte;
} else if (nvram_naddrs == 1) {
nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size);
nvram_mult = (dp->addrs[0].size + NVRAM_SIZE - 1) / NVRAM_SIZE;
ppc_md.nvram_read_val = direct_nvram_read_byte;
ppc_md.nvram_write_val = direct_nvram_write_byte;
} else if (nvram_naddrs == 2) {
nvram_addr = ioremap(dp->addrs[0].address, dp->addrs[0].size);
nvram_data = ioremap(dp->addrs[1].address, dp->addrs[1].size);
ppc_md.nvram_read_val = indirect_nvram_read_byte;
ppc_md.nvram_write_val = indirect_nvram_write_byte;
} else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) {
#ifdef CONFIG_ADB_PMU
nvram_naddrs = -1;
ppc_md.nvram_read_val = pmu_nvram_read_byte;
ppc_md.nvram_write_val = pmu_nvram_write_byte;
#endif /* CONFIG_ADB_PMU */
} else {
printk(KERN_ERR "Don't know how to access NVRAM with %d addresses\n",
nvram_naddrs);
}
lookup_partitions();
}
int pmac_get_partition(int partition)
{
return nvram_partitions[partition];
}
u8 pmac_xpram_read(int xpaddr)
{
int offset = nvram_partitions[pmac_nvram_XPRAM];
if (offset < 0)
return 0xff;
return ppc_md.nvram_read_val(xpaddr + offset);
}
void pmac_xpram_write(int xpaddr, u8 data)
{
int offset = nvram_partitions[pmac_nvram_XPRAM];
if (offset < 0)
return;
ppc_md.nvram_write_val(xpaddr + offset, data);
}
EXPORT_SYMBOL(pmac_get_partition);
EXPORT_SYMBOL(pmac_xpram_read);
EXPORT_SYMBOL(pmac_xpram_write);
This diff is collapsed.
This diff is collapsed.
#ifndef __PPC_PLATFORMS_PMAC_PIC_H
#define __PPC_PLATFORMS_PMAC_PIC_H
#include <linux/irq.h>
extern struct hw_interrupt_type pmac_pic;
void pmac_pic_init(void);
int pmac_get_irq(struct pt_regs *regs);
#endif /* __PPC_PLATFORMS_PMAC_PIC_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -39,8 +39,6 @@ obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \ ...@@ -39,8 +39,6 @@ obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \
ppc_sys.o mpc8xx_devices.o mpc8xx_sys.o ppc_sys.o mpc8xx_devices.o mpc8xx_sys.o
obj-$(CONFIG_PCI_QSPAN) += qspan_pci.o obj-$(CONFIG_PCI_QSPAN) += qspan_pci.o
obj-$(CONFIG_PPC_OF) += prom_init.o prom.o obj-$(CONFIG_PPC_OF) += prom_init.o prom.o
obj-$(CONFIG_PPC_PMAC) += open_pic.o
obj-$(CONFIG_POWER4) += open_pic2.o
obj-$(CONFIG_PPC_CHRP) += open_pic.o obj-$(CONFIG_PPC_CHRP) += open_pic.o
obj-$(CONFIG_PPC_PREP) += open_pic.o todc_time.o obj-$(CONFIG_PPC_PREP) += open_pic.o todc_time.o
obj-$(CONFIG_BAMBOO) += pci_auto.o todc_time.o obj-$(CONFIG_BAMBOO) += pci_auto.o todc_time.o
......
...@@ -70,8 +70,6 @@ int use_of_interrupt_tree; ...@@ -70,8 +70,6 @@ int use_of_interrupt_tree;
struct device_node *dflt_interrupt_controller; struct device_node *dflt_interrupt_controller;
int num_interrupt_controllers; int num_interrupt_controllers;
int pmac_newworld;
extern unsigned int rtas_entry; /* physical pointer */ extern unsigned int rtas_entry; /* physical pointer */
extern struct device_node *allnodes; extern struct device_node *allnodes;
...@@ -123,22 +121,13 @@ finish_device_tree(void) ...@@ -123,22 +121,13 @@ finish_device_tree(void)
unsigned long mem = (unsigned long) klimit; unsigned long mem = (unsigned long) klimit;
struct device_node *np; struct device_node *np;
/* All newworld pmac machines and CHRPs now use the interrupt tree */ /* All CHRPs now use the interrupt tree */
for (np = allnodes; np != NULL; np = np->allnext) { for (np = allnodes; np != NULL; np = np->allnext) {
if (get_property(np, "interrupt-parent", NULL)) { if (get_property(np, "interrupt-parent", NULL)) {
use_of_interrupt_tree = 1; use_of_interrupt_tree = 1;
break; break;
} }
} }
if (_machine == _MACH_Pmac && use_of_interrupt_tree)
pmac_newworld = 1;
#ifdef CONFIG_BOOTX_TEXT
if (boot_infos && pmac_newworld) {
prom_print("WARNING ! BootX/miBoot booting is not supported on this machine\n");
prom_print(" You should use an Open Firmware bootloader\n");
}
#endif /* CONFIG_BOOTX_TEXT */
if (use_of_interrupt_tree) { if (use_of_interrupt_tree) {
/* /*
...@@ -434,16 +423,10 @@ finish_node_interrupts(struct device_node *np, unsigned long mem_start) ...@@ -434,16 +423,10 @@ finish_node_interrupts(struct device_node *np, unsigned long mem_start)
* those machines, we want to offset interrupts from the * those machines, we want to offset interrupts from the
* second openpic by 128 -- BenH * second openpic by 128 -- BenH
*/ */
if (_machine != _MACH_Pmac && num_interrupt_controllers > 1 if (num_interrupt_controllers > 1
&& ic != NULL && ic != NULL
&& get_property(ic, "interrupt-parent", NULL) == NULL) && get_property(ic, "interrupt-parent", NULL) == NULL)
offset = 16; offset = 16;
else if (_machine == _MACH_Pmac && num_interrupt_controllers > 1
&& ic != NULL && ic->parent != NULL) {
char *name = get_property(ic->parent, "name", NULL);
if (name && !strcmp(name, "u3"))
offset = 128;
}
np->intrs[i].line = irq[0] + offset; np->intrs[i].line = irq[0] + offset;
if (n > 1) if (n > 1)
......
This diff is collapsed.
...@@ -16,9 +16,6 @@ ...@@ -16,9 +16,6 @@
#include <asm/bootx.h> #include <asm/bootx.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/xmon.h> #include <asm/xmon.h>
#ifdef CONFIG_PMAC_BACKLIGHT
#include <asm/backlight.h>
#endif
#include "nonstdio.h" #include "nonstdio.h"
#include "privinst.h" #include "privinst.h"
...@@ -260,16 +257,6 @@ int xmon(struct pt_regs *excp) ...@@ -260,16 +257,6 @@ int xmon(struct pt_regs *excp)
*/ */
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
remove_bpts(); remove_bpts();
#ifdef CONFIG_PMAC_BACKLIGHT
if( setjmp(bus_error_jmp) == 0 ) {
debugger_fault_handler = handle_fault;
sync();
set_backlight_enable(1);
set_backlight_level(BACKLIGHT_MAX);
sync();
}
debugger_fault_handler = NULL;
#endif /* CONFIG_PMAC_BACKLIGHT */
cmd = cmds(excp); cmd = cmds(excp);
if (cmd == 's') { if (cmd == 's') {
xmon_trace[smp_processor_id()] = SSTEP; xmon_trace[smp_processor_id()] = SSTEP;
......
...@@ -2734,7 +2734,7 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk) ...@@ -2734,7 +2734,7 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
* BIOS does tho. Right now, all this PM stuff is pmac-only for that * BIOS does tho. Right now, all this PM stuff is pmac-only for that
* reason. --BenH * reason. --BenH
*/ */
#if defined(CONFIG_PM) && defined(CONFIG_PPC_OF) #if defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC)
if (_machine == _MACH_Pmac && rinfo->of_node) { if (_machine == _MACH_Pmac && rinfo->of_node) {
if (rinfo->is_mobility && rinfo->pm_reg && if (rinfo->is_mobility && rinfo->pm_reg &&
rinfo->family <= CHIP_FAMILY_RV250) rinfo->family <= CHIP_FAMILY_RV250)
...@@ -2778,12 +2778,12 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk) ...@@ -2778,12 +2778,12 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
OUTREG(TV_DAC_CNTL, INREG(TV_DAC_CNTL) | 0x07000000); OUTREG(TV_DAC_CNTL, INREG(TV_DAC_CNTL) | 0x07000000);
#endif #endif
} }
#endif /* defined(CONFIG_PM) && defined(CONFIG_PPC_OF) */ #endif /* defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC) */
} }
void radeonfb_pm_exit(struct radeonfb_info *rinfo) void radeonfb_pm_exit(struct radeonfb_info *rinfo)
{ {
#if defined(CONFIG_PM) && defined(CONFIG_PPC_OF) #if defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC)
if (rinfo->pm_mode != radeon_pm_none) if (rinfo->pm_mode != radeon_pm_none)
pmac_set_early_video_resume(NULL, NULL); pmac_set_early_video_resume(NULL, NULL);
#endif #endif
......
...@@ -167,6 +167,14 @@ extern int of_address_to_resource(struct device_node *dev, int index, ...@@ -167,6 +167,14 @@ extern int of_address_to_resource(struct device_node *dev, int index,
extern int of_pci_address_to_resource(struct device_node *dev, int bar, extern int of_pci_address_to_resource(struct device_node *dev, int bar,
struct resource *r); struct resource *r);
#ifndef CONFIG_PPC_OF
/*
* Fallback definitions for builds where we don't have prom.c included.
*/
#define machine_is_compatible(x) 0
#define of_find_compatible_node(f, t, c) NULL
#define get_property(p, n, l) NULL
#endif
#endif /* _PPC_PROM_H */ #endif /* _PPC_PROM_H */
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
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