Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
このコミットが含まれているのは:
Linus Torvalds
2005-04-16 15:20:36 -07:00
コミット 1da177e4c3
17291個のファイルの変更6718755行の追加0行の削除

8
arch/sh/boards/mpc1211/Makefile ノーマルファイル
ファイルの表示

@@ -0,0 +1,8 @@
#
# Makefile for the Interface (CTP/PCI/MPC-SH02) specific parts of the kernel
#
obj-y := setup.o rtc.o led.o
obj-$(CONFIG_PCI) += pci.o

64
arch/sh/boards/mpc1211/led.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,64 @@
/*
* linux/arch/sh/kernel/led_mpc1211.c
*
* Copyright (C) 2001 Saito.K & Jeanne
*
* This file contains Interface MPC-1211 specific LED code.
*/
#include <linux/config.h>
static void mach_led(int position, int value)
{
volatile unsigned char* p = (volatile unsigned char*)0xa2000000;
if (value) {
*p |= 1;
} else {
*p &= ~1;
}
}
#ifdef CONFIG_HEARTBEAT
#include <linux/sched.h>
/* Cycle the LED's in the clasic Knightrider/Sun pattern */
void heartbeat_mpc1211(void)
{
static unsigned int cnt = 0, period = 0;
volatile unsigned char* p = (volatile unsigned char*)0xa2000000;
static unsigned bit = 0, up = 1;
cnt += 1;
if (cnt < period) {
return;
}
cnt = 0;
/* Go through the points (roughly!):
* f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
*/
period = 110 - ( (300<<FSHIFT)/
((avenrun[0]/5) + (3<<FSHIFT)) );
if (up) {
if (bit == 7) {
bit--;
up=0;
} else {
bit ++;
}
} else {
if (bit == 0) {
bit++;
up=1;
} else {
bit--;
}
}
*p = 1<<bit;
}
#endif /* CONFIG_HEARTBEAT */

296
arch/sh/boards/mpc1211/pci.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,296 @@
/*
* Low-Level PCI Support for the MPC-1211(CTP/PCI/MPC-SH02)
*
* (c) 2002-2003 Saito.K & Jeanne
*
* Dustin McIntire (dustin@sensoria.com)
* Derived from arch/i386/kernel/pci-*.c which bore the message:
* (c) 1999--2000 Martin Mares <mj@ucw.cz>
*
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
*
*/
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/sched.h>
#include <linux/ioport.h>
#include <linux/errno.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/machvec.h>
#include <asm/io.h>
#include <asm/mpc1211/pci.h>
static struct resource mpcpci_io_resource = {
"MPCPCI IO",
0x00000000,
0xffffffff,
IORESOURCE_IO
};
static struct resource mpcpci_mem_resource = {
"MPCPCI mem",
0x00000000,
0xffffffff,
IORESOURCE_MEM
};
static struct pci_ops pci_direct_conf1;
struct pci_channel board_pci_channels[] = {
{&pci_direct_conf1, &mpcpci_io_resource, &mpcpci_mem_resource, 0, 256},
{NULL, NULL, NULL, 0, 0},
};
/*
* Direct access to PCI hardware...
*/
#define CONFIG_CMD(bus, devfn, where) (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
/*
* Functions for accessing PCI configuration space with type 1 accesses
*/
static int pci_conf1_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
{
u32 word;
unsigned long flags;
/*
* PCIPDR may only be accessed as 32 bit words,
* so we must do byte alignment by hand
*/
local_irq_save(flags);
writel(CONFIG_CMD(bus,devfn,where), PCIPAR);
word = readl(PCIPDR);
local_irq_restore(flags);
switch (size) {
case 1:
switch (where & 0x3) {
case 3:
*value = (u8)(word >> 24);
break;
case 2:
*value = (u8)(word >> 16);
break;
case 1:
*value = (u8)(word >> 8);
break;
default:
*value = (u8)word;
break;
}
break;
case 2:
switch (where & 0x3) {
case 3:
*value = (u16)(word >> 24);
local_irq_save(flags);
writel(CONFIG_CMD(bus,devfn,(where+1)), PCIPAR);
word = readl(PCIPDR);
local_irq_restore(flags);
*value |= ((word & 0xff) << 8);
break;
case 2:
*value = (u16)(word >> 16);
break;
case 1:
*value = (u16)(word >> 8);
break;
default:
*value = (u16)word;
break;
}
break;
case 4:
*value = word;
break;
}
PCIDBG(4,"pci_conf1_read@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),*value);
return PCIBIOS_SUCCESSFUL;
}
/*
* Since MPC-1211 only does 32bit access we'll have to do a read,mask,write operation.
* We'll allow an odd byte offset, though it should be illegal.
*/
static int pci_conf1_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
{
u32 word,mask = 0;
unsigned long flags;
u32 shift = (where & 3) * 8;
if(size == 1) {
mask = ((1 << 8) - 1) << shift; // create the byte mask
} else if(size == 2){
if(shift == 24)
return PCIBIOS_BAD_REGISTER_NUMBER;
mask = ((1 << 16) - 1) << shift; // create the word mask
}
local_irq_save(flags);
writel(CONFIG_CMD(bus,devfn,where), PCIPAR);
if(size == 4){
writel(value, PCIPDR);
local_irq_restore(flags);
PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),value);
return PCIBIOS_SUCCESSFUL;
}
word = readl(PCIPDR);
word &= ~mask;
word |= ((value << shift) & mask);
writel(word, PCIPDR);
local_irq_restore(flags);
PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),word);
return PCIBIOS_SUCCESSFUL;
}
#undef CONFIG_CMD
static struct pci_ops pci_direct_conf1 = {
.read = pci_conf1_read,
.write = pci_conf1_write,
};
static void __devinit quirk_ali_ide_ports(struct pci_dev *dev)
{
dev->resource[0].start = 0x1f0;
dev->resource[0].end = 0x1f7;
dev->resource[0].flags = IORESOURCE_IO;
dev->resource[1].start = 0x3f6;
dev->resource[1].end = 0x3f6;
dev->resource[1].flags = IORESOURCE_IO;
dev->resource[2].start = 0x170;
dev->resource[2].end = 0x177;
dev->resource[2].flags = IORESOURCE_IO;
dev->resource[3].start = 0x376;
dev->resource[3].end = 0x376;
dev->resource[3].flags = IORESOURCE_IO;
dev->resource[4].start = 0xf000;
dev->resource[4].end = 0xf00f;
dev->resource[4].flags = IORESOURCE_IO;
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, quirk_ali_ide_ports);
char * __devinit pcibios_setup(char *str)
{
return str;
}
/*
* Called after each bus is probed, but before its children
* are examined.
*/
void __init pcibios_fixup_bus(struct pci_bus *b)
{
pci_read_bridge_bases(b);
}
/*
* IRQ functions
*/
static inline u8 bridge_swizzle(u8 pin, u8 slot)
{
return (((pin-1) + slot) % 4) + 1;
}
static inline u8 bridge_swizzle_pci_1(u8 pin, u8 slot)
{
return (((pin-1) - slot) & 3) + 1;
}
static u8 __init mpc1211_swizzle(struct pci_dev *dev, u8 *pinp)
{
unsigned long flags;
u8 pin = *pinp;
u32 word;
for ( ; dev->bus->self; dev = dev->bus->self) {
if (!pin)
continue;
if (dev->bus->number == 1) {
local_irq_save(flags);
writel(0x80000000 | 0x2c, PCIPAR);
word = readl(PCIPDR);
local_irq_restore(flags);
word >>= 16;
if (word == 0x0001)
pin = bridge_swizzle_pci_1(pin, PCI_SLOT(dev->devfn));
else
pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
} else
pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
}
*pinp = pin;
return PCI_SLOT(dev->devfn);
}
static int __init map_mpc1211_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
int irq = -1;
/* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
if (dev->bus->number == 0) {
switch (slot) {
case 13: irq = 9; break; /* USB */
case 22: irq = 10; break; /* LAN */
default: irq = 0; break;
}
} else {
switch (pin) {
case 0: irq = 0; break;
case 1: irq = 7; break;
case 2: irq = 9; break;
case 3: irq = 10; break;
case 4: irq = 11; break;
}
}
if( irq < 0 ) {
PCIDBG(3, "PCI: Error mapping IRQ on device %s\n", pci_name(dev));
return irq;
}
PCIDBG(2, "Setting IRQ for slot %s to %d\n", pci_name(dev), irq);
return irq;
}
void __init pcibios_fixup_irqs(void)
{
pci_fixup_irqs(mpc1211_swizzle, map_mpc1211_irq);
}
void pcibios_align_resource(void *data, struct resource *res,
unsigned long size, unsigned long align)
{
unsigned long start = res->start;
if (res->flags & IORESOURCE_IO) {
if (start >= 0x10000UL) {
if ((start & 0xffffUL) < 0x4000UL) {
start = (start & 0xffff0000UL) + 0x4000UL;
} else if ((start & 0xffffUL) >= 0xf000UL) {
start = (start & 0xffff0000UL) + 0x10000UL;
}
res->start = start;
} else {
if (start & 0x300) {
start = (start + 0x3ff) & ~0x3ff;
res->start = start;
}
}
}
}

152
arch/sh/boards/mpc1211/rtc.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,152 @@
/*
* linux/arch/sh/kernel/rtc-mpc1211.c -- MPC-1211 on-chip RTC support
*
* Copyright (C) 2002 Saito.K & Jeanne
*
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/time.h>
#include <linux/mc146818rtc.h>
#ifndef BCD_TO_BIN
#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
#endif
#ifndef BIN_TO_BCD
#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
#endif
/* arc/i386/kernel/time.c */
unsigned long get_cmos_time(void)
{
unsigned int year, mon, day, hour, min, sec;
int i;
spin_lock(&rtc_lock);
/* The Linux interpretation of the CMOS clock register contents:
* When the Update-In-Progress (UIP) flag goes from 1 to 0, the
* RTC registers show the second which has precisely just started.
* Let's hope other operating systems interpret the RTC the same way.
*/
/* read RTC exactly on falling edge of update flag */
for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
break;
for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
break;
do { /* Isn't this overkill ? UIP above should guarantee consistency */
sec = CMOS_READ(RTC_SECONDS);
min = CMOS_READ(RTC_MINUTES);
hour = CMOS_READ(RTC_HOURS);
day = CMOS_READ(RTC_DAY_OF_MONTH);
mon = CMOS_READ(RTC_MONTH);
year = CMOS_READ(RTC_YEAR);
} while (sec != CMOS_READ(RTC_SECONDS));
if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
{
BCD_TO_BIN(sec);
BCD_TO_BIN(min);
BCD_TO_BIN(hour);
BCD_TO_BIN(day);
BCD_TO_BIN(mon);
BCD_TO_BIN(year);
}
spin_unlock(&rtc_lock);
if ((year += 1900) < 1970)
year += 100;
return mktime(year, mon, day, hour, min, sec);
}
void mpc1211_rtc_gettimeofday(struct timeval *tv)
{
tv->tv_sec = get_cmos_time();
tv->tv_usec = 0;
}
/* arc/i386/kernel/time.c */
/*
* In order to set the CMOS clock precisely, set_rtc_mmss has to be
* called 500 ms after the second nowtime has started, because when
* nowtime is written into the registers of the CMOS clock, it will
* jump to the next second precisely 500 ms later. Check the Motorola
* MC146818A or Dallas DS12887 data sheet for details.
*
* BUG: This routine does not handle hour overflow properly; it just
* sets the minutes. Usually you'll only notice that after reboot!
*/
static int set_rtc_mmss(unsigned long nowtime)
{
int retval = 0;
int real_seconds, real_minutes, cmos_minutes;
unsigned char save_control, save_freq_select;
/* gets recalled with irq locally disabled */
spin_lock(&rtc_lock);
save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
cmos_minutes = CMOS_READ(RTC_MINUTES);
if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
BCD_TO_BIN(cmos_minutes);
/*
* since we're only adjusting minutes and seconds,
* don't interfere with hour overflow. This avoids
* messing with unknown time zones but requires your
* RTC not to be off by more than 15 minutes
*/
real_seconds = nowtime % 60;
real_minutes = nowtime / 60;
if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
real_minutes += 30; /* correct for half hour time zone */
real_minutes %= 60;
if (abs(real_minutes - cmos_minutes) < 30) {
if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
BIN_TO_BCD(real_seconds);
BIN_TO_BCD(real_minutes);
}
CMOS_WRITE(real_seconds,RTC_SECONDS);
CMOS_WRITE(real_minutes,RTC_MINUTES);
} else {
printk(KERN_WARNING
"set_rtc_mmss: can't update from %d to %d\n",
cmos_minutes, real_minutes);
retval = -1;
}
/* The following flags have to be released exactly in this order,
* otherwise the DS12887 (popular MC146818A clone with integrated
* battery and quartz) will not reset the oscillator and will not
* update precisely 500 ms later. You won't find this mentioned in
* the Dallas Semiconductor data sheets, but who believes data
* sheets anyway ... -- Markus Kuhn
*/
CMOS_WRITE(save_control, RTC_CONTROL);
CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
spin_unlock(&rtc_lock);
return retval;
}
int mpc1211_rtc_settimeofday(const struct timeval *tv)
{
unsigned long nowtime = tv->tv_sec;
return set_rtc_mmss(nowtime);
}
void mpc1211_time_init(void)
{
rtc_get_time = mpc1211_rtc_gettimeofday;
rtc_set_time = mpc1211_rtc_settimeofday;
}

360
arch/sh/boards/mpc1211/setup.c ノーマルファイル
ファイルの表示

@@ -0,0 +1,360 @@
/*
* linux/arch/sh/board/mpc1211/setup.c
*
* Copyright (C) 2002 Saito.K & Jeanne, Fujii.Y
*
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <asm/machvec.h>
#include <asm/mpc1211/mpc1211.h>
#include <asm/mpc1211/pci.h>
#include <asm/mpc1211/m1543c.h>
/* ALI15X3 SMBus address offsets */
#define SMBHSTSTS (0 + 0x3100)
#define SMBHSTCNT (1 + 0x3100)
#define SMBHSTSTART (2 + 0x3100)
#define SMBHSTCMD (7 + 0x3100)
#define SMBHSTADD (3 + 0x3100)
#define SMBHSTDAT0 (4 + 0x3100)
#define SMBHSTDAT1 (5 + 0x3100)
#define SMBBLKDAT (6 + 0x3100)
/* Other settings */
#define MAX_TIMEOUT 500 /* times 1/100 sec */
/* ALI15X3 command constants */
#define ALI15X3_ABORT 0x04
#define ALI15X3_T_OUT 0x08
#define ALI15X3_QUICK 0x00
#define ALI15X3_BYTE 0x10
#define ALI15X3_BYTE_DATA 0x20
#define ALI15X3_WORD_DATA 0x30
#define ALI15X3_BLOCK_DATA 0x40
#define ALI15X3_BLOCK_CLR 0x80
/* ALI15X3 status register bits */
#define ALI15X3_STS_IDLE 0x04
#define ALI15X3_STS_BUSY 0x08
#define ALI15X3_STS_DONE 0x10
#define ALI15X3_STS_DEV 0x20 /* device error */
#define ALI15X3_STS_COLL 0x40 /* collision or no response */
#define ALI15X3_STS_TERM 0x80 /* terminated by abort */
#define ALI15X3_STS_ERR 0xE0 /* all the bad error bits */
const char *get_system_type(void)
{
return "Interface MPC-1211(CTP/PCI/MPC-SH02)";
}
static void __init pci_write_config(unsigned long busNo,
unsigned long devNo,
unsigned long fncNo,
unsigned long cnfAdd,
unsigned long cnfData)
{
ctrl_outl((0x80000000
+ ((busNo & 0xff) << 16)
+ ((devNo & 0x1f) << 11)
+ ((fncNo & 0x07) << 8)
+ (cnfAdd & 0xfc)), PCIPAR);
ctrl_outl(cnfData, PCIPDR);
}
/*
Initialize IRQ setting
*/
static unsigned char m_irq_mask = 0xfb;
static unsigned char s_irq_mask = 0xff;
volatile unsigned long irq_err_count;
static void disable_mpc1211_irq(unsigned int irq)
{
unsigned long flags;
save_and_cli(flags);
if( irq < 8) {
m_irq_mask |= (1 << irq);
outb(m_irq_mask,I8259_M_MR);
} else {
s_irq_mask |= (1 << (irq - 8));
outb(s_irq_mask,I8259_S_MR);
}
restore_flags(flags);
}
static void enable_mpc1211_irq(unsigned int irq)
{
unsigned long flags;
save_and_cli(flags);
if( irq < 8) {
m_irq_mask &= ~(1 << irq);
outb(m_irq_mask,I8259_M_MR);
} else {
s_irq_mask &= ~(1 << (irq - 8));
outb(s_irq_mask,I8259_S_MR);
}
restore_flags(flags);
}
static inline int mpc1211_irq_real(unsigned int irq)
{
int value;
int irqmask;
if ( irq < 8) {
irqmask = 1<<irq;
outb(0x0b,I8259_M_CR); /* ISR register */
value = inb(I8259_M_CR) & irqmask;
outb(0x0a,I8259_M_CR); /* back ro the IPR reg */
return value;
}
irqmask = 1<<(irq - 8);
outb(0x0b,I8259_S_CR); /* ISR register */
value = inb(I8259_S_CR) & irqmask;
outb(0x0a,I8259_S_CR); /* back ro the IPR reg */
return value;
}
static void mask_and_ack_mpc1211(unsigned int irq)
{
unsigned long flags;
save_and_cli(flags);
if(irq < 8) {
if(m_irq_mask & (1<<irq)){
if(!mpc1211_irq_real(irq)){
irq_err_count++;
printk("spurious 8259A interrupt: IRQ %x\n",irq);
}
} else {
m_irq_mask |= (1<<irq);
}
inb(I8259_M_MR); /* DUMMY */
outb(m_irq_mask,I8259_M_MR); /* disable */
outb(0x60+irq,I8259_M_CR); /* EOI */
} else {
if(s_irq_mask & (1<<(irq - 8))){
if(!mpc1211_irq_real(irq)){
irq_err_count++;
printk("spurious 8259A interrupt: IRQ %x\n",irq);
}
} else {
s_irq_mask |= (1<<(irq - 8));
}
inb(I8259_S_MR); /* DUMMY */
outb(s_irq_mask,I8259_S_MR); /* disable */
outb(0x60+(irq-8),I8259_S_CR); /* EOI */
outb(0x60+2,I8259_M_CR);
}
restore_flags(flags);
}
static void end_mpc1211_irq(unsigned int irq)
{
enable_mpc1211_irq(irq);
}
static unsigned int startup_mpc1211_irq(unsigned int irq)
{
enable_mpc1211_irq(irq);
return 0;
}
static void shutdown_mpc1211_irq(unsigned int irq)
{
disable_mpc1211_irq(irq);
}
static struct hw_interrupt_type mpc1211_irq_type = {
.typename = "MPC1211-IRQ",
.startup = startup_mpc1211_irq,
.shutdown = shutdown_mpc1211_irq,
.enable = enable_mpc1211_irq,
.disable = disable_mpc1211_irq,
.ack = mask_and_ack_mpc1211,
.end = end_mpc1211_irq
};
static void make_mpc1211_irq(unsigned int irq)
{
irq_desc[irq].handler = &mpc1211_irq_type;
irq_desc[irq].status = IRQ_DISABLED;
irq_desc[irq].action = 0;
irq_desc[irq].depth = 1;
disable_mpc1211_irq(irq);
}
int mpc1211_irq_demux(int irq)
{
unsigned int poll;
if( irq == 2 ) {
outb(0x0c,I8259_M_CR);
poll = inb(I8259_M_CR);
if(poll & 0x80) {
irq = (poll & 0x07);
}
if( irq == 2) {
outb(0x0c,I8259_S_CR);
poll = inb(I8259_S_CR);
irq = (poll & 0x07) + 8;
}
}
return irq;
}
void __init init_mpc1211_IRQ(void)
{
int i;
/*
* Super I/O (Just mimic PC):
* 1: keyboard
* 3: serial 1
* 4: serial 0
* 5: printer
* 6: floppy
* 8: rtc
* 10: lan
* 12: mouse
* 14: ide0
* 15: ide1
*/
pci_write_config(0,0,0,0x54, 0xb0b0002d);
outb(0x11, I8259_M_CR); /* mater icw1 edge trigger */
outb(0x11, I8259_S_CR); /* slave icw1 edge trigger */
outb(0x20, I8259_M_MR); /* m icw2 base vec 0x08 */
outb(0x28, I8259_S_MR); /* s icw2 base vec 0x70 */
outb(0x04, I8259_M_MR); /* m icw3 slave irq2 */
outb(0x02, I8259_S_MR); /* s icw3 slave id */
outb(0x01, I8259_M_MR); /* m icw4 non buf normal eoi*/
outb(0x01, I8259_S_MR); /* s icw4 non buf normal eo1*/
outb(0xfb, I8259_M_MR); /* disable irq0--irq7 */
outb(0xff, I8259_S_MR); /* disable irq8--irq15 */
for ( i=0; i < 16; i++) {
if(i != 2) {
make_mpc1211_irq(i);
}
}
}
/*
Initialize the board
*/
static void delay (void)
{
volatile unsigned short tmp;
tmp = *(volatile unsigned short *) 0xa0000000;
}
static void delay1000 (void)
{
int i;
for (i=0; i<1000; i++)
delay ();
}
static int put_smb_blk(unsigned char *p, int address, int command, int no)
{
int temp;
int timeout;
int i;
outb(0xff, SMBHSTSTS);
temp = inb(SMBHSTSTS);
for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE); timeout++) {
delay1000();
temp = inb(SMBHSTSTS);
}
if (timeout >= MAX_TIMEOUT){
return -1;
}
outb(((address & 0x7f) << 1), SMBHSTADD);
outb(0xc0, SMBHSTCNT);
outb(command & 0xff, SMBHSTCMD);
outb(no & 0x1f, SMBHSTDAT0);
for(i = 1; i <= no; i++) {
outb(*p++, SMBBLKDAT);
}
outb(0xff, SMBHSTSTART);
temp = inb(SMBHSTSTS);
for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE)); timeout++) {
delay1000();
temp = inb(SMBHSTSTS);
}
if (timeout >= MAX_TIMEOUT) {
return -2;
}
if ( temp & ALI15X3_STS_ERR ){
return -3;
}
return 0;
}
/*
* The Machine Vector
*/
struct sh_machine_vector mv_mpc1211 __initmv = {
.mv_nr_irqs = 48,
.mv_irq_demux = mpc1211_irq_demux,
.mv_init_irq = init_mpc1211_IRQ,
#ifdef CONFIG_HEARTBEAT
.mv_heartbeat = heartbeat_mpc1211,
#endif
};
ALIAS_MV(mpc1211)
/* arch/sh/boards/mpc1211/rtc.c */
void mpc1211_time_init(void);
int __init platform_setup(void)
{
unsigned char spd_buf[128];
__set_io_port_base(PA_PCI_IO);
pci_write_config(0,0,0,0x54, 0xb0b00000);
do {
outb(ALI15X3_ABORT, SMBHSTCNT);
spd_buf[0] = 0x0c;
spd_buf[1] = 0x43;
spd_buf[2] = 0x7f;
spd_buf[3] = 0x03;
spd_buf[4] = 0x00;
spd_buf[5] = 0x03;
spd_buf[6] = 0x00;
} while (put_smb_blk(spd_buf, 0x69, 0, 7) < 0);
board_time_init = mpc1211_time_init;
return 0;
}