|
From: Andy P. <at...@us...> - 2002-04-10 18:30:55
|
Update of /cvsroot/linux-vax/kernel-2.4/arch/mips/ddb5xxx/common
In directory usw-pr-cvs1:/tmp/cvs-serv20728/mips/ddb5xxx/common
Added Files:
Makefile irq.c irq_cpu.c nile4.c pci.c pci_auto.c prom.c
rtc_ds1386.c
Log Message:
synch 2.4.15 commit 39
--- NEW FILE ---
#
# Makefile for the common code of NEC DDB-Vrc5xxx board
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
.S.s:
$(CPP) $(CFLAGS) $< -o $*.s
.S.o:
$(CC) $(CFLAGS) -c $< -o $*.o
O_TARGET:= ddb5xxx.o
obj-y += irq.o irq_cpu.o nile4.o prom.o pci.o pci_auto.o rtc_ds1386.o
include $(TOPDIR)/Rules.make
--- NEW FILE ---
/*
* Copyright 2001 MontaVista Software Inc.
* Author: js...@mv... or js...@ju...
*
* arch/mips/ddb5xxx/common/irq.c
* Common irq code for DDB boards. This really should belong
* arch/mips/kernel/irq.c. Need to talk to Ralf.
*
* 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.
*/
#include <linux/config.h>
#include <linux/init.h>
void (*irq_setup)(void);
void __init init_IRQ(void)
{
#ifdef CONFIG_REMOTE_DEBUG
extern void breakpoint(void);
extern void set_debug_traps(void);
printk("Wait for gdb client connection ...\n");
set_debug_traps();
breakpoint();
#endif
/* invoke board-specific irq setup */
irq_setup();
}
--- NEW FILE ---
/***********************************************************************
* Copyright 2001 MontaVista Software Inc.
* Author: Jun Sun, js...@mv... or js...@ju...
*
* arch/mips/ddb5xxx/common/irq_cpu.c
* This file define the irq handler for MIPS CPU interrupts.
*
* 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.
***********************************************************************
*/
/*
* Almost all MIPS CPUs define 8 interrupt sources. They are typically
* level triggered (i.e., cannot be cleared from CPU; must be cleared from
* device). The first two are software interrupts. The last one is
* usually cpu timer interrupt if coutner register is present.
*
* This file exports one global function:
* mips_cpu_irq_init(u32 irq_base);
*/
#include <linux/irq.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <asm/mipsregs.h>
/* [jsun] sooner or later we should move this debug stuff to MIPS common */
#include <asm/ddb5xxx/debug.h>
static int mips_cpu_irq_base=-1;
static void
mips_cpu_irq_enable(unsigned int irq)
{
MIPS_ASSERT(mips_cpu_irq_base != -1);
MIPS_ASSERT(irq >= mips_cpu_irq_base);
MIPS_ASSERT(irq < mips_cpu_irq_base+8);
clear_cp0_cause( 1 << (irq - mips_cpu_irq_base + 8));
set_cp0_status(1 << (irq - mips_cpu_irq_base + 8));
}
static void
mips_cpu_irq_disable(unsigned int irq)
{
MIPS_ASSERT(mips_cpu_irq_base != -1);
MIPS_ASSERT(irq >= mips_cpu_irq_base);
MIPS_ASSERT(irq < mips_cpu_irq_base+8);
clear_cp0_status(1 << (irq - mips_cpu_irq_base + 8));
}
static unsigned int mips_cpu_irq_startup(unsigned int irq)
{
mips_cpu_irq_enable(irq);
return 0;
}
#define mips_cpu_irq_shutdown mips_cpu_irq_disable
static void
mips_cpu_irq_ack(unsigned int irq)
{
MIPS_ASSERT(mips_cpu_irq_base != -1);
MIPS_ASSERT(irq >= mips_cpu_irq_base);
MIPS_ASSERT(irq < mips_cpu_irq_base+8);
/* although we attemp to clear the IP bit in cause reigster, I think
* usually it is cleared by device (irq source)
*/
clear_cp0_cause( 1 << (irq - mips_cpu_irq_base + 8));
/* I am not fully convinced that I should disable irq here */
}
static void
mips_cpu_irq_end(unsigned int irq)
{
MIPS_ASSERT(mips_cpu_irq_base != -1);
MIPS_ASSERT(irq >= mips_cpu_irq_base);
MIPS_ASSERT(irq < mips_cpu_irq_base+8);
/* I am not fully convinced that I should enable irq here */
}
static hw_irq_controller mips_cpu_irq_controller = {
"CPU_irq",
mips_cpu_irq_startup,
mips_cpu_irq_shutdown,
mips_cpu_irq_enable,
mips_cpu_irq_disable,
mips_cpu_irq_ack,
mips_cpu_irq_end,
NULL /* no affinity stuff for UP */
};
void
mips_cpu_irq_init(u32 irq_base)
{
extern irq_desc_t irq_desc[];
u32 i;
for (i= irq_base; i< irq_base+8; i++) {
irq_desc[i].status = IRQ_DISABLED;
irq_desc[i].action = NULL;
irq_desc[i].depth = 1;
irq_desc[i].handler = &mips_cpu_irq_controller;
}
mips_cpu_irq_base = irq_base;
}
--- NEW FILE ---
/***********************************************************************
*
* Copyright 2001 MontaVista Software Inc.
* Author: js...@mv... or js...@ju...
*
* arch/mips/ddb5xxx/common/nile4.c
* misc low-level routines for vrc-5xxx controllers.
*
* derived from original code by Geert Uytterhoeven <ge...@so...>
*
* 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.
*
***********************************************************************
*/
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <asm/ddb5xxx/ddb5xxx.h>
#include <asm/ddb5xxx/debug.h>
u32
ddb_calc_pdar(u32 phys, u32 size, int width,
int on_memory_bus, int pci_visible)
{
u32 maskbits;
u32 widthbits;
switch (size) {
#if 0 /* We don't support 4 GB yet */
case 0x100000000: /* 4 GB */
maskbits = 4;
break;
#endif
case 0x80000000: /* 2 GB */
maskbits = 5;
break;
case 0x40000000: /* 1 GB */
maskbits = 6;
break;
case 0x20000000: /* 512 MB */
maskbits = 7;
break;
case 0x10000000: /* 256 MB */
maskbits = 8;
break;
case 0x08000000: /* 128 MB */
maskbits = 9;
break;
case 0x04000000: /* 64 MB */
maskbits = 10;
break;
case 0x02000000: /* 32 MB */
maskbits = 11;
break;
case 0x01000000: /* 16 MB */
maskbits = 12;
break;
case 0x00800000: /* 8 MB */
maskbits = 13;
break;
case 0x00400000: /* 4 MB */
maskbits = 14;
break;
case 0x00200000: /* 2 MB */
maskbits = 15;
break;
case 0: /* OFF */
maskbits = 0;
break;
default:
panic("nile4_set_pdar: unsupported size %p\n", (void *) size);
}
switch (width) {
case 8:
widthbits = 0;
break;
case 16:
widthbits = 1;
break;
case 32:
widthbits = 2;
break;
case 64:
widthbits = 3;
break;
default:
panic("nile4_set_pdar: unsupported width %d\n", width);
}
return maskbits | (on_memory_bus ? 0x10 : 0) |
(pci_visible ? 0x20 : 0) | (widthbits << 6) |
(phys & 0xffe00000);
}
void
ddb_set_pdar(u32 pdar, u32 phys, u32 size, int width,
int on_memory_bus, int pci_visible)
{
u32 temp= ddb_calc_pdar(phys, size, width, on_memory_bus, pci_visible);
ddb_out32(pdar, temp);
ddb_out32(pdar + 4, 0);
/*
* When programming a PDAR, the register should be read immediately
* after writing it. This ensures that address decoders are properly
* configured.
* [jsun] is this really necesary?
*/
ddb_in32(pdar);
ddb_in32(pdar + 4);
}
/*
* routines that mess with PCIINITx registers
*/
void ddb_set_pmr(u32 pmr, u32 type, u32 addr, u32 options)
{
switch (type) {
case DDB_PCICMD_IACK: /* PCI Interrupt Acknowledge */
case DDB_PCICMD_IO: /* PCI I/O Space */
case DDB_PCICMD_MEM: /* PCI Memory Space */
case DDB_PCICMD_CFG: /* PCI Configuration Space */
break;
default:
panic("nile4_set_pmr: invalid type %d\n", type);
}
ddb_out32(pmr, (type << 1) | (addr & 0xffe00000) | options );
ddb_out32(pmr + 4, 0);
}
--- NEW FILE ---
/***********************************************************************
* Copyright 2001 MontaVista Software Inc.
* Author: Jun Sun, js...@mv... or js...@ju...
*
* arch/mips/ddb5xxx/common/pci.c
* Common PCI routines for DDB5xxx - as a matter of fact, meant for all
* MIPS machines.
*
* 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 common PCI routines meant to be shared for
* all MIPS machines.
*
* Strategies:
*
* . We rely on pci_auto.c file to assign PCI resources (MEM and IO)
* TODO: this shold be optional for some machines where they do have
* a real "pcibios" that does resource assignment.
*
* . We then use pci_scan_bus() to "discover" all the resources for
* later use by Linux.
*
* . We finally reply on a board supplied function, pcibios_fixup_irq(), to
* to assign the interrupts. We may use setup-irq.c under drivers/pci
* later.
*
* . Specifically, we will *NOT* use pci_assign_unassigned_resources(),
* because we assume all PCI devices should have the resources correctly
* assigned and recorded.
*
* Limitations:
*
* . We "collapse" all IO and MEM spaces in sub-buses under a top-level bus
* into a contiguous range.
*
* . In the case of Memory space, the rnage is 1:1 mapping with CPU physical
* address space.
*
* . In the case of IO space, it starts from 0, and the beginning address
* is mapped to KSEG0ADDR(mips_io_port) in the CPU physical address.
*
* . These are the current MIPS limitations (by ioremap, etc). In the
* future, we may remove them.
*
* Credits:
* Most of the code are derived from the pci routines from PPC and Alpha,
* which were mostly writtne by
* Cort Dougan, co...@fs...
* Matt Porter, mp...@mv...
* Dave Rusling dav...@re...
* David Mosberger da...@cs...
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <asm/ddb5xxx/pci.h>
#include <asm/ddb5xxx/debug.h>
struct pci_fixup pcibios_fixups[] = { {0} };
extern int pciauto_assign_resources(int busno, struct pci_channel * hose);
void __init pcibios_init(void)
{
struct pci_channel *p;
struct pci_bus *bus;
int busno;
/* assign resources */
busno=0;
for (p= mips_pci_channels; p->pci_ops != NULL; p++) {
busno = pciauto_assign_resources(busno, p) + 1;
}
/* scan the buses */
busno = 0;
for (p= mips_pci_channels; p->pci_ops != NULL; p++) {
bus = pci_scan_bus(busno, p->pci_ops, p);
busno = bus->subordinate+1;
}
/* fixup irqs (board specific routines) */
pcibios_fixup_irqs();
/*
* should we do a fixup of ioport_resource and iomem_resource
* based on mips_pci_channels?
* Let us wait and see if this is a common need and whether there
* are exceptions. Until then, each board should adjust them
* perhaps in their setup() function.
*/
}
int pcibios_enable_device(struct pci_dev *dev)
{
/* pciauto_assign_resources() will enable all devices found */
return 0;
}
unsigned long __init
pci_bridge_check_io(struct pci_dev *bridge)
{
u16 io;
pci_read_config_word(bridge, PCI_IO_BASE, &io);
if (!io) {
pci_write_config_word(bridge, PCI_IO_BASE, 0xf0f0);
pci_read_config_word(bridge, PCI_IO_BASE, &io);
pci_write_config_word(bridge, PCI_IO_BASE, 0x0);
}
if (io)
return IORESOURCE_IO;
printk(KERN_WARNING "PCI: bridge %s does not support I/O forwarding!\n",
bridge->name);
return 0;
}
void __init pcibios_fixup_bus(struct pci_bus *bus)
{
/* Propogate hose info into the subordinate devices. */
struct pci_channel *hose = bus->sysdata;
struct pci_dev *dev = bus->self;
if (!dev) {
/* Root bus */
bus->resource[0] = hose->io_resource;
bus->resource[1] = hose->mem_resource;
} else {
/* This is a bridge. Do not care how it's initialized,
just link its resources to the bus ones */
int i;
for(i=0; i<3; i++) {
bus->resource[i] =
&dev->resource[PCI_BRIDGE_RESOURCES+i];
bus->resource[i]->name = bus->name;
}
bus->resource[0]->flags |= pci_bridge_check_io(dev);
bus->resource[1]->flags |= IORESOURCE_MEM;
/* For now, propogate hose limits to the bus;
we'll adjust them later. */
bus->resource[0]->end = hose->io_resource->end;
bus->resource[1]->end = hose->mem_resource->end;
/* Turn off downstream PF memory address range by default */
bus->resource[2]->start = 1024*1024;
bus->resource[2]->end = bus->resource[2]->start - 1;
}
}
char *pcibios_setup(char *str)
{
return str;
}
void
pcibios_align_resource(void *data, struct resource *res, unsigned long size)
{
/* this should not be called */
MIPS_ASSERT(1 == 0);
}
void
pcibios_update_resource(struct pci_dev *dev, struct resource *root,
struct resource *res, int resource)
{
/* this should not be called */
MIPS_ASSERT(1 == 0);
}
--- NEW FILE ---
/*
* arch/ppc/kernel/pci_auto.c
*
* PCI autoconfiguration library
*
* Author: Matt Porter <mp...@mv...>
*
* Copyright 2000, 2001 MontaVista Software Inc.
*
* 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.
*/
/*
* Modified for MIPS by Jun Sun, js...@mv...
*
* . Simplify the interface between pci_auto and the rest: a single function.
* . Assign resources from low address to upper address.
* . change most int to u32.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <asm/ddb5xxx/pci.h>
#include <asm/ddb5xxx/debug.h>
#define DEBUG
#ifdef DEBUG
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
/* These are used for config access before all the PCI probing
has been done. */
int early_read_config_byte(struct pci_channel *hose, int bus, int dev_fn, int where, u8 *val);
int early_read_config_word(struct pci_channel *hose, int bus, int dev_fn, int where, u16 *val);
int early_read_config_dword(struct pci_channel *hose, int bus, int dev_fn, int where, u32 *val);
int early_write_config_byte(struct pci_channel *hose, int bus, int dev_fn, int where, u8 val);
int early_write_config_word(struct pci_channel *hose, int bus, int dev_fn, int where, u16 val);
int early_write_config_dword(struct pci_channel *hose, int bus, int dev_fn, int where, u32 val);
static u32 pciauto_lower_iospc;
static u32 pciauto_upper_iospc;
static u32 pciauto_lower_memspc;
static u32 pciauto_upper_memspc;
void __init
pciauto_setup_bars(struct pci_channel *hose,
int current_bus,
int pci_devfn)
{
u32 bar_response, bar_size, bar_value;
u32 bar, addr_mask, bar_nr = 0;
u32 * upper_limit;
u32 * lower_limit;
int found_mem64 = 0;
DBG("PCI Autoconfig: Found Bus %d, Device %d, Function %d\n",
current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn) );
for (bar = PCI_BASE_ADDRESS_0; bar <= PCI_BASE_ADDRESS_5; bar+=4)
{
/* Tickle the BAR and get the response */
early_write_config_dword(hose,
current_bus,
pci_devfn,
bar,
0xffffffff);
early_read_config_dword(hose,
current_bus,
pci_devfn,
bar,
&bar_response);
/* If BAR is not implemented go to the next BAR */
if (!bar_response)
continue;
/* Check the BAR type and set our address mask */
if (bar_response & PCI_BASE_ADDRESS_SPACE)
{
addr_mask = PCI_BASE_ADDRESS_IO_MASK;
upper_limit = &pciauto_upper_iospc;
lower_limit = &pciauto_lower_iospc;
DBG("PCI Autoconfig: BAR %d, I/O, ", bar_nr);
}
else
{
if ( (bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
PCI_BASE_ADDRESS_MEM_TYPE_64)
found_mem64 = 1;
addr_mask = PCI_BASE_ADDRESS_MEM_MASK;
upper_limit = &pciauto_upper_memspc;
lower_limit = &pciauto_lower_memspc;
DBG("PCI Autoconfig: BAR %d, Mem, ", bar_nr);
}
/* Calculate requested size */
bar_size = ~(bar_response & addr_mask) + 1;
/* Allocate a base address */
bar_value = ((*lower_limit - 1) & ~(bar_size - 1)) + bar_size;
MIPS_ASSERT(bar_value + bar_size <= *upper_limit);
/* Write it out and update our limit */
early_write_config_dword(hose,
current_bus,
pci_devfn,
bar,
bar_value);
*lower_limit = bar_value + bar_size;
/*
* If we are a 64-bit decoder then increment to the
* upper 32 bits of the bar and force it to locate
* in the lower 4GB of memory.
*/
if (found_mem64)
{
bar += 4;
early_write_config_dword(hose,
current_bus,
pci_devfn,
bar,
0x00000000);
}
bar_nr++;
DBG("size=0x%x, address=0x%x\n",
bar_size, bar_value);
}
}
void __init
pciauto_prescan_setup_bridge(struct pci_channel *hose,
int current_bus,
int pci_devfn,
int sub_bus)
{
int cmdstat;
/* Configure bus number registers */
early_write_config_byte(hose,
current_bus,
pci_devfn,
PCI_PRIMARY_BUS,
current_bus);
early_write_config_byte(hose,
current_bus,
pci_devfn,
PCI_SECONDARY_BUS,
sub_bus + 1);
early_write_config_byte(hose,
current_bus,
pci_devfn,
PCI_SUBORDINATE_BUS,
0xff);
/* Round memory allocator to 1MB boundary */
pciauto_upper_memspc &= ~(0x100000 - 1);
/* Round I/O allocator to 4KB boundary */
pciauto_upper_iospc &= ~(0x1000 - 1);
/* Set up memory and I/O filter limits, assume 32-bit I/O space */
early_write_config_word(hose,
current_bus,
pci_devfn,
PCI_MEMORY_LIMIT,
((pciauto_upper_memspc - 1) & 0xfff00000) >> 16);
early_write_config_byte(hose,
current_bus,
pci_devfn,
PCI_IO_LIMIT,
((pciauto_upper_iospc - 1) & 0x0000f000) >> 8);
early_write_config_word(hose,
current_bus,
pci_devfn,
PCI_IO_LIMIT_UPPER16,
((pciauto_upper_iospc - 1) & 0xffff0000) >> 16);
/* We don't support prefetchable memory for now, so disable */
early_write_config_word(hose,
current_bus,
pci_devfn,
PCI_PREF_MEMORY_BASE,
0x1000);
early_write_config_word(hose,
current_bus,
pci_devfn,
PCI_PREF_MEMORY_LIMIT,
0x1000);
/* Enable memory and I/O accesses, enable bus master */
early_read_config_dword(hose,
current_bus,
pci_devfn,
PCI_COMMAND,
&cmdstat);
early_write_config_dword(hose,
current_bus,
pci_devfn,
PCI_COMMAND,
cmdstat |
PCI_COMMAND_IO |
PCI_COMMAND_MEMORY |
PCI_COMMAND_MASTER);
}
void __init
pciauto_postscan_setup_bridge(struct pci_channel *hose,
int current_bus,
int pci_devfn,
int sub_bus)
{
/* Configure bus number registers */
early_write_config_byte(hose,
current_bus,
pci_devfn,
PCI_SUBORDINATE_BUS,
sub_bus);
/* Round memory allocator to 1MB boundary */
pciauto_upper_memspc &= ~(0x100000 - 1);
early_write_config_word(hose,
current_bus,
pci_devfn,
PCI_MEMORY_BASE,
pciauto_upper_memspc >> 16);
/* Round I/O allocator to 4KB boundary */
pciauto_upper_iospc &= ~(0x1000 - 1);
early_write_config_byte(hose,
current_bus,
pci_devfn,
PCI_IO_BASE,
(pciauto_upper_iospc & 0x0000f000) >> 8);
early_write_config_word(hose,
current_bus,
pci_devfn,
PCI_IO_BASE_UPPER16,
pciauto_upper_iospc >> 16);
}
#define PCIAUTO_IDE_MODE_MASK 0x05
int __init
pciauto_bus_scan(struct pci_channel *hose, int current_bus)
{
int sub_bus;
u32 pci_devfn, pci_class, cmdstat, found_multi=0;
unsigned short vid;
unsigned char header_type;
sub_bus = current_bus;
for (pci_devfn=0; pci_devfn<0xff; pci_devfn++) {
if (PCI_FUNC(pci_devfn) && !found_multi)
continue;
early_read_config_byte(hose,
current_bus,
pci_devfn,
PCI_HEADER_TYPE,
&header_type);
if (!PCI_FUNC(pci_devfn))
found_multi = header_type & 0x80;
early_read_config_word(hose,
current_bus,
pci_devfn,
PCI_VENDOR_ID,
&vid);
if (vid == 0xffff) continue;
early_read_config_dword(hose,
current_bus,
pci_devfn,
PCI_CLASS_REVISION, &pci_class);
if ( (pci_class >> 16) == PCI_CLASS_BRIDGE_PCI ) {
DBG("PCI Autoconfig: Found P2P bridge, device %d\n", PCI_SLOT(pci_devfn));
pciauto_prescan_setup_bridge(hose,
current_bus,
pci_devfn,
sub_bus);
sub_bus = pciauto_bus_scan(hose, sub_bus+1);
pciauto_postscan_setup_bridge(hose,
current_bus,
pci_devfn,
sub_bus);
} else if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) {
unsigned char prg_iface;
early_read_config_byte(hose,
current_bus,
pci_devfn,
PCI_CLASS_PROG,
&prg_iface);
if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) {
DBG("PCI Autoconfig: Skipping legacy mode IDE controller\n");
continue;
}
}
/*
* Found a peripheral, enable some standard
* settings
*/
early_read_config_dword(hose,
current_bus,
pci_devfn,
PCI_COMMAND,
&cmdstat);
early_write_config_dword(hose,
current_bus,
pci_devfn,
PCI_COMMAND,
cmdstat |
PCI_COMMAND_IO |
PCI_COMMAND_MEMORY |
PCI_COMMAND_MASTER);
early_write_config_byte(hose,
current_bus,
pci_devfn,
PCI_LATENCY_TIMER,
0x80);
/* Allocate PCI I/O and/or memory space */
pciauto_setup_bars(hose,
current_bus,
pci_devfn);
}
return sub_bus;
}
int __init
pciauto_assign_resources(int busno, struct pci_channel *hose)
{
/* setup resource limits */
pciauto_lower_iospc = hose->io_resource->start;
pciauto_upper_iospc = hose->io_resource->end + 1;
pciauto_lower_memspc = hose->mem_resource->start;
pciauto_upper_memspc = hose->mem_resource->end + 1;
return pciauto_bus_scan(hose, busno);
}
/*
* These functions are used early on before PCI scanning is done
* and all of the pci_dev and pci_bus structures have been created.
*/
static struct pci_dev *
fake_pci_dev(struct pci_channel *hose, int busnr, int devfn)
{
static struct pci_dev dev;
static struct pci_bus bus;
dev.bus = &bus;
dev.sysdata = hose;
dev.devfn = devfn;
bus.number = busnr;
bus.ops = hose->pci_ops;
return &dev;
}
#define EARLY_PCI_OP(rw, size, type) \
int early_##rw##_config_##size(struct pci_channel *hose, int bus, \
int devfn, int offset, type value) \
{ \
return pci_##rw##_config_##size(fake_pci_dev(hose, bus, devfn), \
offset, value); \
}
EARLY_PCI_OP(read, byte, u8 *)
EARLY_PCI_OP(read, word, u16 *)
EARLY_PCI_OP(read, dword, u32 *)
EARLY_PCI_OP(write, byte, u8)
EARLY_PCI_OP(write, word, u16)
EARLY_PCI_OP(write, dword, u32)
--- NEW FILE ---
/***********************************************************************
*
* Copyright 2001 MontaVista Software Inc.
* Author: js...@mv... or js...@ju...
*
* arch/mips/ddb5xxx/common/prom.c
* prom.c file.
*
* 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.
*
***********************************************************************
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/bootmem.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <asm/ddb5xxx/ddb5xxx.h>
char arcs_cmdline[COMMAND_LINE_SIZE];
/* [js...@ju...] PMON passes arguments in C main() style */
void __init prom_init(int argc, const char **arg)
{
int i;
/* arg[0] is "g", the rest is boot parameters */
arcs_cmdline[0] = '\0';
for (i = 1; i < argc; i++) {
if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
>= sizeof(arcs_cmdline))
break;
strcat(arcs_cmdline, arg[i]);
strcat(arcs_cmdline, " ");
}
mips_machgroup = MACH_GROUP_NEC_DDB;
#if defined(CONFIG_DDB5074)
mips_machtype = MACH_NEC_DDB5074;
#elif defined(CONFIG_DDB5476)
mips_machtype = MACH_NEC_DDB5476;
#elif defined(CONFIG_DDB5477)
mips_machtype = MACH_NEC_DDB5477;
#endif
add_memory_region(0, DDB_SDRAM_SIZE, BOOT_MEM_RAM);
}
void __init prom_free_prom_memory(void)
{
}
--- NEW FILE ---
/*
* Copyright 2001 MontaVista Software Inc.
* Author: js...@mv... or js...@ju...
*
* arch/mips/ddb5xxx/common/rtc_ds1386.c
* low-level RTC hookups for s for Dallas 1396 chip.
*
* 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 exports a function, rtc_ds1386_init(), which expects an
* uncached base address as the argument. It will set the two function
* pointers expected by the MIPS generic timer code.
*/
#include <linux/types.h>
#include <linux/time.h>
#include <asm/time.h>
#include <asm/addrspace.h>
#include <asm/ddb5xxx/debug.h>
#define EPOCH 2000
#undef BCD_TO_BIN
#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
#undef BIN_TO_BCD
#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
#define READ_RTC(x) *(volatile unsigned char*)(rtc_base+x)
#define WRITE_RTC(x, y) *(volatile unsigned char*)(rtc_base+x) = y
static unsigned long rtc_base;
static unsigned long
rtc_ds1386_get_time(void)
{
u8 byte;
u8 temp;
unsigned int year, month, day, hour, minute, second;
/* let us freeze external registers */
byte = READ_RTC(0xB);
byte &= 0x3f;
WRITE_RTC(0xB, byte);
/* read time data */
year = BCD_TO_BIN(READ_RTC(0xA)) + EPOCH;
month = BCD_TO_BIN(READ_RTC(0x9) & 0x1f);
day = BCD_TO_BIN(READ_RTC(0x8));
minute = BCD_TO_BIN(READ_RTC(0x2));
second = BCD_TO_BIN(READ_RTC(0x1));
/* hour is special - deal with it later */
temp = READ_RTC(0x4);
/* enable time transfer */
byte |= 0x80;
WRITE_RTC(0xB, byte);
/* calc hour */
if (temp & 0x40) {
/* 12 hour format */
hour = BCD_TO_BIN(temp & 0x1f);
if (temp & 0x20) hour += 12; /* PM */
} else {
/* 24 hour format */
hour = BCD_TO_BIN(temp & 0x3f);
}
return mktime(year, month, day, hour, minute, second);
}
static int
rtc_ds1386_set_time(unsigned long t)
{
struct rtc_time tm;
u8 byte;
u8 temp;
u8 year, month, day, hour, minute, second;
/* let us freeze external registers */
byte = READ_RTC(0xB);
byte &= 0x3f;
WRITE_RTC(0xB, byte);
/* convert */
to_tm(t, &tm);
/* check each field one by one */
year = BIN_TO_BCD(tm.tm_year - EPOCH);
if (year != READ_RTC(0xA)) {
WRITE_RTC(0xA, year);
}
temp = READ_RTC(0x9);
month = BIN_TO_BCD(tm.tm_mon);
if (month != (temp & 0x1f)) {
WRITE_RTC( 0x9,
(month & 0x1f) | (temp & ~0x1f) );
}
day = BIN_TO_BCD(tm.tm_mday);
if (day != READ_RTC(0x8)) {
WRITE_RTC(0x8, day);
}
temp = READ_RTC(0x4);
if (temp & 0x40) {
/* 12 hour format */
hour = 0x40;
if (tm.tm_hour > 12) {
hour |= 0x20 | (BIN_TO_BCD(hour-12) & 0x1f);
} else {
hour |= BIN_TO_BCD(tm.tm_hour);
}
} else {
/* 24 hour format */
hour = BIN_TO_BCD(tm.tm_hour) & 0x3f;
}
if (hour != temp) WRITE_RTC(0x4, hour);
minute = BIN_TO_BCD(tm.tm_min);
if (minute != READ_RTC(0x2)) {
WRITE_RTC(0x2, minute);
}
second = BIN_TO_BCD(tm.tm_sec);
if (second != READ_RTC(0x1)) {
WRITE_RTC(0x1, second);
}
return 0;
}
void
rtc_ds1386_init(unsigned long base)
{
unsigned char byte;
/* remember the base */
rtc_base = base;
MIPS_ASSERT((rtc_base & 0xe0000000) == KSEG1);
/* turn on RTC if it is not on */
byte = READ_RTC(0x9);
if (byte & 0x80) {
byte &= 0x7f;
WRITE_RTC(0x9, byte);
}
/* enable time transfer */
byte = READ_RTC(0xB);
byte |= 0x80;
WRITE_RTC(0xB, byte);
/* set the function pointers */
rtc_get_time = rtc_ds1386_get_time;
rtc_set_time = rtc_ds1386_set_time;
}
|