Fixed MTP to work with TWRP

This commit is contained in:
awab228 2018-06-19 23:16:04 +02:00
commit f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions

View file

@ -0,0 +1,99 @@
if ARCH_FOOTBRIDGE
menu "Footbridge Implementations"
config ARCH_CATS
bool "CATS"
select CLKEVT_I8253
select CLKSRC_I8253
select FOOTBRIDGE_HOST
select ISA
select ISA_DMA
select PCI
help
Say Y here if you intend to run this kernel on the CATS.
Saying N will reduce the size of the Footbridge kernel.
config ARCH_PERSONAL_SERVER
bool "Compaq Personal Server"
select FOOTBRIDGE_HOST
select ISA
select ISA_DMA
select PCI
---help---
Say Y here if you intend to run this kernel on the Compaq
Personal Server.
Saying N will reduce the size of the Footbridge kernel.
The Compaq Personal Server is not available for purchase.
There are no product plans beyond the current research
prototypes at this time. Information is available at:
<http://www.crl.hpl.hp.com/projects/personalserver/>
If you have any questions or comments about the Compaq Personal
Server, send e-mail to <skiff@crl.dec.com>.
config ARCH_EBSA285_ADDIN
bool "EBSA285 (addin mode)"
select ARCH_EBSA285
select FOOTBRIDGE_ADDIN
help
Say Y here if you intend to run this kernel on the EBSA285 card
in addin mode.
Saying N will reduce the size of the Footbridge kernel.
config ARCH_EBSA285_HOST
bool "EBSA285 (host mode)"
select ARCH_EBSA285
select FOOTBRIDGE_HOST
select ISA
select ISA_DMA
select ARCH_MAY_HAVE_PC_FDC
select PCI
help
Say Y here if you intend to run this kernel on the EBSA285 card
in host ("central function") mode.
Saying N will reduce the size of the Footbridge kernel.
config ARCH_NETWINDER
bool "NetWinder"
select CLKEVT_I8253
select CLKSRC_I8253
select FOOTBRIDGE_HOST
select ISA
select ISA_DMA
select PCI
select VIRT_TO_BUS
help
Say Y here if you intend to run this kernel on the Rebel.COM
NetWinder. Information about this machine can be found at:
<http://www.netwinder.org/>
Saying N will reduce the size of the Footbridge kernel.
endmenu
# Footbridge support
config FOOTBRIDGE
bool
# Footbridge in host mode
config FOOTBRIDGE_HOST
bool
select ARCH_MIGHT_HAVE_PC_SERIO
# Footbridge in addin mode
config FOOTBRIDGE_ADDIN
bool
# EBSA285 board in either host or addin mode
config ARCH_EBSA285
bool
endif

View file

@ -0,0 +1,22 @@
#
# Makefile for the linux kernel.
#
# Object file lists.
obj-y := common.o dma.o isa-irq.o
pci-y += dc21285.o
pci-$(CONFIG_ARCH_CATS) += cats-pci.o
pci-$(CONFIG_ARCH_EBSA285_HOST) += ebsa285-pci.o
pci-$(CONFIG_ARCH_NETWINDER) += netwinder-pci.o
pci-$(CONFIG_ARCH_PERSONAL_SERVER) += personal-pci.o
obj-$(CONFIG_ARCH_CATS) += cats-hw.o isa-timer.o
obj-$(CONFIG_ARCH_EBSA285) += ebsa285.o dc21285-timer.o
obj-$(CONFIG_ARCH_NETWINDER) += netwinder-hw.o isa-timer.o
obj-$(CONFIG_ARCH_PERSONAL_SERVER) += personal.o dc21285-timer.o
obj-$(CONFIG_PCI) +=$(pci-y)
obj-$(CONFIG_ISA) += isa.o isa-rtc.o

View file

@ -0,0 +1,4 @@
zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000

View file

@ -0,0 +1,97 @@
/*
* linux/arch/arm/mach-footbridge/cats-hw.c
*
* CATS machine fixup
*
* Copyright (C) 1998, 1999 Russell King, Phil Blundell
*/
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/screen_info.h>
#include <linux/io.h>
#include <linux/spinlock.h>
#include <asm/hardware/dec21285.h>
#include <asm/mach-types.h>
#include <asm/setup.h>
#include <asm/mach/arch.h>
#include "common.h"
#define CFG_PORT 0x370
#define INDEX_PORT (CFG_PORT)
#define DATA_PORT (CFG_PORT + 1)
static int __init cats_hw_init(void)
{
if (machine_is_cats()) {
/* Set Aladdin to CONFIGURE mode */
outb(0x51, CFG_PORT);
outb(0x23, CFG_PORT);
/* Select logical device 3 */
outb(0x07, INDEX_PORT);
outb(0x03, DATA_PORT);
/* Set parallel port to DMA channel 3, ECP+EPP1.9,
enable EPP timeout */
outb(0x74, INDEX_PORT);
outb(0x03, DATA_PORT);
outb(0xf0, INDEX_PORT);
outb(0x0f, DATA_PORT);
outb(0xf1, INDEX_PORT);
outb(0x07, DATA_PORT);
/* Select logical device 4 */
outb(0x07, INDEX_PORT);
outb(0x04, DATA_PORT);
/* UART1 high speed mode */
outb(0xf0, INDEX_PORT);
outb(0x02, DATA_PORT);
/* Select logical device 5 */
outb(0x07, INDEX_PORT);
outb(0x05, DATA_PORT);
/* UART2 high speed mode */
outb(0xf0, INDEX_PORT);
outb(0x02, DATA_PORT);
/* Set Aladdin to RUN mode */
outb(0xbb, CFG_PORT);
}
return 0;
}
__initcall(cats_hw_init);
/*
* CATS uses soft-reboot by default, since
* hard reboots fail on early boards.
*/
static void __init
fixup_cats(struct tag *tags, char **cmdline)
{
#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
screen_info.orig_video_lines = 25;
screen_info.orig_video_points = 16;
screen_info.orig_y = 24;
#endif
}
MACHINE_START(CATS, "Chalice-CATS")
/* Maintainer: Philip Blundell */
.atag_offset = 0x100,
.reboot_mode = REBOOT_SOFT,
.fixup = fixup_cats,
.map_io = footbridge_map_io,
.init_irq = footbridge_init_irq,
.init_time = isa_timer_init,
.restart = footbridge_restart,
MACHINE_END

View file

@ -0,0 +1,63 @@
/*
* linux/arch/arm/mach-footbridge/cats-pci.c
*
* PCI bios-type initialisation for PCI machines
*
* Bits taken from various places.
*/
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <asm/irq.h>
#include <asm/mach/pci.h>
#include <asm/mach-types.h>
/* cats host-specific stuff */
static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 };
static u8 cats_no_swizzle(struct pci_dev *dev, u8 *pin)
{
return 0;
}
static int __init cats_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
if (dev->irq >= 255)
return -1; /* not a valid interrupt. */
if (dev->irq >= 128)
return dev->irq & 0x1f;
if (dev->irq >= 1 && dev->irq <= 4)
return irqmap_cats[dev->irq - 1];
if (dev->irq != 0)
printk("PCI: device %02x:%02x has unknown irq line %x\n",
dev->bus->number, dev->devfn, dev->irq);
return -1;
}
/*
* why not the standard PCI swizzle? does this prevent 4-port tulip
* cards being used (ie, pci-pci bridge based cards)?
*/
static struct hw_pci cats_pci __initdata = {
.swizzle = cats_no_swizzle,
.map_irq = cats_map_irq,
.nr_controllers = 1,
.ops = &dc21285_ops,
.setup = dc21285_setup,
.preinit = dc21285_preinit,
.postinit = dc21285_postinit,
};
static int __init cats_pci_init(void)
{
if (machine_is_cats())
pci_common_init(&cats_pci);
return 0;
}
subsys_initcall(cats_pci_init);

View file

@ -0,0 +1,268 @@
/*
* linux/arch/arm/mach-footbridge/common.c
*
* Copyright (C) 1998-2000 Russell King, Dave Gilbert.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/list.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/spinlock.h>
#include <video/vga.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
#include <asm/setup.h>
#include <asm/system_misc.h>
#include <asm/hardware/dec21285.h>
#include <asm/mach/irq.h>
#include <asm/mach/map.h>
#include <asm/mach/pci.h>
#include "common.h"
unsigned int mem_fclk_21285 = 50000000;
EXPORT_SYMBOL(mem_fclk_21285);
static int __init early_fclk(char *arg)
{
mem_fclk_21285 = simple_strtoul(arg, NULL, 0);
return 0;
}
early_param("mem_fclk_21285", early_fclk);
static int __init parse_tag_memclk(const struct tag *tag)
{
mem_fclk_21285 = tag->u.memclk.fmemclk;
return 0;
}
__tagtable(ATAG_MEMCLK, parse_tag_memclk);
/*
* Footbridge IRQ translation table
* Converts from our IRQ numbers into FootBridge masks
*/
static const int fb_irq_mask[] = {
IRQ_MASK_UART_RX, /* 0 */
IRQ_MASK_UART_TX, /* 1 */
IRQ_MASK_TIMER1, /* 2 */
IRQ_MASK_TIMER2, /* 3 */
IRQ_MASK_TIMER3, /* 4 */
IRQ_MASK_IN0, /* 5 */
IRQ_MASK_IN1, /* 6 */
IRQ_MASK_IN2, /* 7 */
IRQ_MASK_IN3, /* 8 */
IRQ_MASK_DOORBELLHOST, /* 9 */
IRQ_MASK_DMA1, /* 10 */
IRQ_MASK_DMA2, /* 11 */
IRQ_MASK_PCI, /* 12 */
IRQ_MASK_SDRAMPARITY, /* 13 */
IRQ_MASK_I2OINPOST, /* 14 */
IRQ_MASK_PCI_ABORT, /* 15 */
IRQ_MASK_PCI_SERR, /* 16 */
IRQ_MASK_DISCARD_TIMER, /* 17 */
IRQ_MASK_PCI_DPERR, /* 18 */
IRQ_MASK_PCI_PERR, /* 19 */
};
static void fb_mask_irq(struct irq_data *d)
{
*CSR_IRQ_DISABLE = fb_irq_mask[_DC21285_INR(d->irq)];
}
static void fb_unmask_irq(struct irq_data *d)
{
*CSR_IRQ_ENABLE = fb_irq_mask[_DC21285_INR(d->irq)];
}
static struct irq_chip fb_chip = {
.irq_ack = fb_mask_irq,
.irq_mask = fb_mask_irq,
.irq_unmask = fb_unmask_irq,
};
static void __init __fb_init_irq(void)
{
unsigned int irq;
/*
* setup DC21285 IRQs
*/
*CSR_IRQ_DISABLE = -1;
*CSR_FIQ_DISABLE = -1;
for (irq = _DC21285_IRQ(0); irq < _DC21285_IRQ(20); irq++) {
irq_set_chip_and_handler(irq, &fb_chip, handle_level_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
}
void __init footbridge_init_irq(void)
{
__fb_init_irq();
if (!footbridge_cfn_mode())
return;
if (machine_is_ebsa285())
/* The following is dependent on which slot
* you plug the Southbridge card into. We
* currently assume that you plug it into
* the right-hand most slot.
*/
isa_init_irq(IRQ_PCI);
if (machine_is_cats())
isa_init_irq(IRQ_IN2);
if (machine_is_netwinder())
isa_init_irq(IRQ_IN3);
}
/*
* Common mapping for all systems. Note that the outbound write flush is
* commented out since there is a "No Fix" problem with it. Not mapping
* it means that we have extra bullet protection on our feet.
*/
static struct map_desc fb_common_io_desc[] __initdata = {
{
.virtual = ARMCSR_BASE,
.pfn = __phys_to_pfn(DC21285_ARMCSR_BASE),
.length = ARMCSR_SIZE,
.type = MT_DEVICE,
}
};
/*
* The mapping when the footbridge is in host mode. We don't map any of
* this when we are in add-in mode.
*/
static struct map_desc ebsa285_host_io_desc[] __initdata = {
#if defined(CONFIG_ARCH_FOOTBRIDGE) && defined(CONFIG_FOOTBRIDGE_HOST)
{
.virtual = PCIMEM_BASE,
.pfn = __phys_to_pfn(DC21285_PCI_MEM),
.length = PCIMEM_SIZE,
.type = MT_DEVICE,
}, {
.virtual = PCICFG0_BASE,
.pfn = __phys_to_pfn(DC21285_PCI_TYPE_0_CONFIG),
.length = PCICFG0_SIZE,
.type = MT_DEVICE,
}, {
.virtual = PCICFG1_BASE,
.pfn = __phys_to_pfn(DC21285_PCI_TYPE_1_CONFIG),
.length = PCICFG1_SIZE,
.type = MT_DEVICE,
}, {
.virtual = PCIIACK_BASE,
.pfn = __phys_to_pfn(DC21285_PCI_IACK),
.length = PCIIACK_SIZE,
.type = MT_DEVICE,
},
#endif
};
void __init footbridge_map_io(void)
{
/*
* Set up the common mapping first; we need this to
* determine whether we're in host mode or not.
*/
iotable_init(fb_common_io_desc, ARRAY_SIZE(fb_common_io_desc));
/*
* Now, work out what we've got to map in addition on this
* platform.
*/
if (footbridge_cfn_mode()) {
iotable_init(ebsa285_host_io_desc, ARRAY_SIZE(ebsa285_host_io_desc));
pci_map_io_early(__phys_to_pfn(DC21285_PCI_IO));
}
vga_base = PCIMEM_BASE;
}
void footbridge_restart(enum reboot_mode mode, const char *cmd)
{
if (mode == REBOOT_SOFT) {
/* Jump into the ROM */
soft_restart(0x41000000);
} else {
/*
* Force the watchdog to do a CPU reset.
*
* After making sure that the watchdog is disabled
* (so we can change the timer registers) we first
* enable the timer to autoreload itself. Next, the
* timer interval is set really short and any
* current interrupt request is cleared (so we can
* see an edge transition). Finally, TIMER4 is
* enabled as the watchdog.
*/
*CSR_SA110_CNTL &= ~(1 << 13);
*CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE |
TIMER_CNTL_AUTORELOAD |
TIMER_CNTL_DIV16;
*CSR_TIMER4_LOAD = 0x2;
*CSR_TIMER4_CLR = 0;
*CSR_SA110_CNTL |= (1 << 13);
}
}
#ifdef CONFIG_FOOTBRIDGE_ADDIN
static inline unsigned long fb_bus_sdram_offset(void)
{
return *CSR_PCISDRAMBASE & 0xfffffff0;
}
/*
* These two functions convert virtual addresses to PCI addresses and PCI
* addresses to virtual addresses. Note that it is only legal to use these
* on memory obtained via get_zeroed_page or kmalloc.
*/
unsigned long __virt_to_bus(unsigned long res)
{
WARN_ON(res < PAGE_OFFSET || res >= (unsigned long)high_memory);
return res + (fb_bus_sdram_offset() - PAGE_OFFSET);
}
EXPORT_SYMBOL(__virt_to_bus);
unsigned long __bus_to_virt(unsigned long res)
{
res = res - (fb_bus_sdram_offset() - PAGE_OFFSET);
WARN_ON(res < PAGE_OFFSET || res >= (unsigned long)high_memory);
return res;
}
EXPORT_SYMBOL(__bus_to_virt);
unsigned long __pfn_to_bus(unsigned long pfn)
{
return __pfn_to_phys(pfn) + (fb_bus_sdram_offset() - PHYS_OFFSET);
}
EXPORT_SYMBOL(__pfn_to_bus);
unsigned long __bus_to_pfn(unsigned long bus)
{
return __phys_to_pfn(bus - (fb_bus_sdram_offset() - PHYS_OFFSET));
}
EXPORT_SYMBOL(__bus_to_pfn);
#endif

View file

@ -0,0 +1,14 @@
#include <linux/reboot.h>
extern void footbridge_timer_init(void);
extern void isa_timer_init(void);
extern void isa_rtc_init(void);
extern void footbridge_map_io(void);
extern void footbridge_init_irq(void);
extern void isa_init_irq(unsigned int irq);
extern void footbridge_restart(enum reboot_mode, const char *);
extern void footbridge_sched_clock(void);

View file

@ -0,0 +1,142 @@
/*
* linux/arch/arm/mach-footbridge/dc21285-timer.c
*
* Copyright (C) 1998 Russell King.
* Copyright (C) 1998 Phil Blundell
*/
#include <linux/clockchips.h>
#include <linux/clocksource.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched_clock.h>
#include <asm/irq.h>
#include <asm/hardware/dec21285.h>
#include <asm/mach/time.h>
#include <asm/system_info.h>
#include "common.h"
static cycle_t cksrc_dc21285_read(struct clocksource *cs)
{
return cs->mask - *CSR_TIMER2_VALUE;
}
static int cksrc_dc21285_enable(struct clocksource *cs)
{
*CSR_TIMER2_LOAD = cs->mask;
*CSR_TIMER2_CLR = 0;
*CSR_TIMER2_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV16;
return 0;
}
static void cksrc_dc21285_disable(struct clocksource *cs)
{
*CSR_TIMER2_CNTL = 0;
}
static struct clocksource cksrc_dc21285 = {
.name = "dc21285_timer2",
.rating = 200,
.read = cksrc_dc21285_read,
.enable = cksrc_dc21285_enable,
.disable = cksrc_dc21285_disable,
.mask = CLOCKSOURCE_MASK(24),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
static int ckevt_dc21285_set_next_event(unsigned long delta,
struct clock_event_device *c)
{
*CSR_TIMER1_CLR = 0;
*CSR_TIMER1_LOAD = delta;
*CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV16;
return 0;
}
static void ckevt_dc21285_set_mode(enum clock_event_mode mode,
struct clock_event_device *c)
{
switch (mode) {
case CLOCK_EVT_MODE_RESUME:
case CLOCK_EVT_MODE_PERIODIC:
*CSR_TIMER1_CLR = 0;
*CSR_TIMER1_LOAD = (mem_fclk_21285 + 8 * HZ) / (16 * HZ);
*CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD |
TIMER_CNTL_DIV16;
break;
case CLOCK_EVT_MODE_ONESHOT:
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
*CSR_TIMER1_CNTL = 0;
break;
}
}
static struct clock_event_device ckevt_dc21285 = {
.name = "dc21285_timer1",
.features = CLOCK_EVT_FEAT_PERIODIC |
CLOCK_EVT_FEAT_ONESHOT,
.rating = 200,
.irq = IRQ_TIMER1,
.set_next_event = ckevt_dc21285_set_next_event,
.set_mode = ckevt_dc21285_set_mode,
};
static irqreturn_t timer1_interrupt(int irq, void *dev_id)
{
struct clock_event_device *ce = dev_id;
*CSR_TIMER1_CLR = 0;
/* Stop the timer if in one-shot mode */
if (ce->mode == CLOCK_EVT_MODE_ONESHOT)
*CSR_TIMER1_CNTL = 0;
ce->event_handler(ce);
return IRQ_HANDLED;
}
static struct irqaction footbridge_timer_irq = {
.name = "dc21285_timer1",
.handler = timer1_interrupt,
.flags = IRQF_TIMER | IRQF_IRQPOLL,
.dev_id = &ckevt_dc21285,
};
/*
* Set up timer interrupt.
*/
void __init footbridge_timer_init(void)
{
struct clock_event_device *ce = &ckevt_dc21285;
unsigned rate = DIV_ROUND_CLOSEST(mem_fclk_21285, 16);
clocksource_register_hz(&cksrc_dc21285, rate);
setup_irq(ce->irq, &footbridge_timer_irq);
ce->cpumask = cpumask_of(smp_processor_id());
clockevents_config_and_register(ce, rate, 0x4, 0xffffff);
}
static u64 notrace footbridge_read_sched_clock(void)
{
return ~*CSR_TIMER3_VALUE;
}
void __init footbridge_sched_clock(void)
{
unsigned rate = DIV_ROUND_CLOSEST(mem_fclk_21285, 16);
*CSR_TIMER3_LOAD = 0;
*CSR_TIMER3_CLR = 0;
*CSR_TIMER3_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV16;
sched_clock_register(footbridge_read_sched_clock, 24, rate);
}

View file

@ -0,0 +1,376 @@
/*
* linux/arch/arm/kernel/dec21285.c: PCI functions for DC21285
*
* Copyright (C) 1998-2001 Russell King
* Copyright (C) 1998-2000 Phil Blundell
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/spinlock.h>
#include <asm/irq.h>
#include <asm/mach/pci.h>
#include <asm/hardware/dec21285.h>
#define MAX_SLOTS 21
#define PCICMD_ABORT ((PCI_STATUS_REC_MASTER_ABORT| \
PCI_STATUS_REC_TARGET_ABORT)<<16)
#define PCICMD_ERROR_BITS ((PCI_STATUS_DETECTED_PARITY | \
PCI_STATUS_REC_MASTER_ABORT | \
PCI_STATUS_REC_TARGET_ABORT | \
PCI_STATUS_PARITY) << 16)
extern int setup_arm_irq(int, struct irqaction *);
extern void pcibios_report_status(u_int status_mask, int warn);
static unsigned long
dc21285_base_address(struct pci_bus *bus, unsigned int devfn)
{
unsigned long addr = 0;
if (bus->number == 0) {
if (PCI_SLOT(devfn) == 0)
/*
* For devfn 0, point at the 21285
*/
addr = ARMCSR_BASE;
else {
devfn -= 1 << 3;
if (devfn < PCI_DEVFN(MAX_SLOTS, 0))
addr = PCICFG0_BASE | 0xc00000 | (devfn << 8);
}
} else
addr = PCICFG1_BASE | (bus->number << 16) | (devfn << 8);
return addr;
}
static int
dc21285_read_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *value)
{
unsigned long addr = dc21285_base_address(bus, devfn);
u32 v = 0xffffffff;
if (addr)
switch (size) {
case 1:
asm("ldrb %0, [%1, %2]"
: "=r" (v) : "r" (addr), "r" (where) : "cc");
break;
case 2:
asm("ldrh %0, [%1, %2]"
: "=r" (v) : "r" (addr), "r" (where) : "cc");
break;
case 4:
asm("ldr %0, [%1, %2]"
: "=r" (v) : "r" (addr), "r" (where) : "cc");
break;
}
*value = v;
v = *CSR_PCICMD;
if (v & PCICMD_ABORT) {
*CSR_PCICMD = v & (0xffff|PCICMD_ABORT);
return -1;
}
return PCIBIOS_SUCCESSFUL;
}
static int
dc21285_write_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 value)
{
unsigned long addr = dc21285_base_address(bus, devfn);
u32 v;
if (addr)
switch (size) {
case 1:
asm("strb %0, [%1, %2]"
: : "r" (value), "r" (addr), "r" (where)
: "cc");
break;
case 2:
asm("strh %0, [%1, %2]"
: : "r" (value), "r" (addr), "r" (where)
: "cc");
break;
case 4:
asm("str %0, [%1, %2]"
: : "r" (value), "r" (addr), "r" (where)
: "cc");
break;
}
v = *CSR_PCICMD;
if (v & PCICMD_ABORT) {
*CSR_PCICMD = v & (0xffff|PCICMD_ABORT);
return -1;
}
return PCIBIOS_SUCCESSFUL;
}
struct pci_ops dc21285_ops = {
.read = dc21285_read_config,
.write = dc21285_write_config,
};
static struct timer_list serr_timer;
static struct timer_list perr_timer;
static void dc21285_enable_error(unsigned long __data)
{
switch (__data) {
case IRQ_PCI_SERR:
del_timer(&serr_timer);
break;
case IRQ_PCI_PERR:
del_timer(&perr_timer);
break;
}
enable_irq(__data);
}
/*
* Warn on PCI errors.
*/
static irqreturn_t dc21285_abort_irq(int irq, void *dev_id)
{
unsigned int cmd;
unsigned int status;
cmd = *CSR_PCICMD;
status = cmd >> 16;
cmd = cmd & 0xffff;
if (status & PCI_STATUS_REC_MASTER_ABORT) {
printk(KERN_DEBUG "PCI: master abort, pc=0x%08lx\n",
instruction_pointer(get_irq_regs()));
cmd |= PCI_STATUS_REC_MASTER_ABORT << 16;
}
if (status & PCI_STATUS_REC_TARGET_ABORT) {
printk(KERN_DEBUG "PCI: target abort: ");
pcibios_report_status(PCI_STATUS_REC_MASTER_ABORT |
PCI_STATUS_SIG_TARGET_ABORT |
PCI_STATUS_REC_TARGET_ABORT, 1);
printk("\n");
cmd |= PCI_STATUS_REC_TARGET_ABORT << 16;
}
*CSR_PCICMD = cmd;
return IRQ_HANDLED;
}
static irqreturn_t dc21285_serr_irq(int irq, void *dev_id)
{
struct timer_list *timer = dev_id;
unsigned int cntl;
printk(KERN_DEBUG "PCI: system error received: ");
pcibios_report_status(PCI_STATUS_SIG_SYSTEM_ERROR, 1);
printk("\n");
cntl = *CSR_SA110_CNTL & 0xffffdf07;
*CSR_SA110_CNTL = cntl | SA110_CNTL_RXSERR;
/*
* back off this interrupt
*/
disable_irq(irq);
timer->expires = jiffies + HZ;
add_timer(timer);
return IRQ_HANDLED;
}
static irqreturn_t dc21285_discard_irq(int irq, void *dev_id)
{
printk(KERN_DEBUG "PCI: discard timer expired\n");
*CSR_SA110_CNTL &= 0xffffde07;
return IRQ_HANDLED;
}
static irqreturn_t dc21285_dparity_irq(int irq, void *dev_id)
{
unsigned int cmd;
printk(KERN_DEBUG "PCI: data parity error detected: ");
pcibios_report_status(PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY, 1);
printk("\n");
cmd = *CSR_PCICMD & 0xffff;
*CSR_PCICMD = cmd | 1 << 24;
return IRQ_HANDLED;
}
static irqreturn_t dc21285_parity_irq(int irq, void *dev_id)
{
struct timer_list *timer = dev_id;
unsigned int cmd;
printk(KERN_DEBUG "PCI: parity error detected: ");
pcibios_report_status(PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY, 1);
printk("\n");
cmd = *CSR_PCICMD & 0xffff;
*CSR_PCICMD = cmd | 1 << 31;
/*
* back off this interrupt
*/
disable_irq(irq);
timer->expires = jiffies + HZ;
add_timer(timer);
return IRQ_HANDLED;
}
int __init dc21285_setup(int nr, struct pci_sys_data *sys)
{
struct resource *res;
if (nr || !footbridge_cfn_mode())
return 0;
res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
if (!res) {
printk("out of memory for root bus resources");
return 0;
}
res[0].flags = IORESOURCE_MEM;
res[0].name = "Footbridge non-prefetch";
res[1].flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
res[1].name = "Footbridge prefetch";
allocate_resource(&iomem_resource, &res[1], 0x20000000,
0xa0000000, 0xffffffff, 0x20000000, NULL, NULL);
allocate_resource(&iomem_resource, &res[0], 0x40000000,
0x80000000, 0xffffffff, 0x40000000, NULL, NULL);
sys->mem_offset = DC21285_PCI_MEM;
pci_add_resource_offset(&sys->resources, &res[0], sys->mem_offset);
pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
return 1;
}
#define dc21285_request_irq(_a, _b, _c, _d, _e) \
WARN_ON(request_irq(_a, _b, _c, _d, _e) < 0)
void __init dc21285_preinit(void)
{
unsigned int mem_size, mem_mask;
int cfn_mode;
pcibios_min_mem = 0x81000000;
mem_size = (unsigned int)high_memory - PAGE_OFFSET;
for (mem_mask = 0x00100000; mem_mask < 0x10000000; mem_mask <<= 1)
if (mem_mask >= mem_size)
break;
/*
* These registers need to be set up whether we're the
* central function or not.
*/
*CSR_SDRAMBASEMASK = (mem_mask - 1) & 0x0ffc0000;
*CSR_SDRAMBASEOFFSET = 0;
*CSR_ROMBASEMASK = 0x80000000;
*CSR_CSRBASEMASK = 0;
*CSR_CSRBASEOFFSET = 0;
*CSR_PCIADDR_EXTN = 0;
cfn_mode = __footbridge_cfn_mode();
printk(KERN_INFO "PCI: DC21285 footbridge, revision %02lX, in "
"%s mode\n", *CSR_CLASSREV & 0xff, cfn_mode ?
"central function" : "addin");
if (footbridge_cfn_mode()) {
/*
* Clear any existing errors - we aren't
* interested in historical data...
*/
*CSR_SA110_CNTL = (*CSR_SA110_CNTL & 0xffffde07) |
SA110_CNTL_RXSERR;
*CSR_PCICMD = (*CSR_PCICMD & 0xffff) | PCICMD_ERROR_BITS;
}
init_timer(&serr_timer);
init_timer(&perr_timer);
serr_timer.data = IRQ_PCI_SERR;
serr_timer.function = dc21285_enable_error;
perr_timer.data = IRQ_PCI_PERR;
perr_timer.function = dc21285_enable_error;
/*
* We don't care if these fail.
*/
dc21285_request_irq(IRQ_PCI_SERR, dc21285_serr_irq, 0,
"PCI system error", &serr_timer);
dc21285_request_irq(IRQ_PCI_PERR, dc21285_parity_irq, 0,
"PCI parity error", &perr_timer);
dc21285_request_irq(IRQ_PCI_ABORT, dc21285_abort_irq, 0,
"PCI abort", NULL);
dc21285_request_irq(IRQ_DISCARD_TIMER, dc21285_discard_irq, 0,
"Discard timer", NULL);
dc21285_request_irq(IRQ_PCI_DPERR, dc21285_dparity_irq, 0,
"PCI data parity", NULL);
if (cfn_mode) {
/*
* Map our SDRAM at a known address in PCI space, just in case
* the firmware had other ideas. Using a nonzero base is
* necessary, since some VGA cards forcefully use PCI addresses
* in the range 0x000a0000 to 0x000c0000. (eg, S3 cards).
*/
*CSR_PCICSRBASE = 0xf4000000;
*CSR_PCICSRIOBASE = 0;
*CSR_PCISDRAMBASE = __virt_to_bus(PAGE_OFFSET);
*CSR_PCIROMBASE = 0;
*CSR_PCICMD = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
PCI_COMMAND_INVALIDATE | PCICMD_ERROR_BITS;
} else if (footbridge_cfn_mode() != 0) {
/*
* If we are not compiled to accept "add-in" mode, then
* we are using a constant virt_to_bus translation which
* can not hope to cater for the way the host BIOS has
* set up the machine.
*/
panic("PCI: this kernel is compiled for central "
"function mode only");
}
}
void __init dc21285_postinit(void)
{
register_isa_ports(DC21285_PCI_MEM, DC21285_PCI_IO, 0);
}

View file

@ -0,0 +1,57 @@
/*
* linux/arch/arm/kernel/dma-ebsa285.c
*
* Copyright (C) 1998 Phil Blundell
*
* DMA functions specific to EBSA-285/CATS architectures
*
* Changelog:
* 09-Nov-1998 RMK Split out ISA DMA functions to dma-isa.c
* 17-Mar-1999 RMK Allow any EBSA285-like architecture to have
* ISA DMA controllers.
*/
#include <linux/init.h>
#include <linux/io.h>
#include <linux/spinlock.h>
#include <asm/dma.h>
#include <asm/scatterlist.h>
#include <asm/mach/dma.h>
#include <asm/hardware/dec21285.h>
#if 0
static int fb_dma_request(unsigned int chan, dma_t *dma)
{
return -EINVAL;
}
static void fb_dma_enable(unsigned int chan, dma_t *dma)
{
}
static void fb_dma_disable(unsigned int chan, dma_t *dma)
{
}
static struct dma_ops fb_dma_ops = {
.type = "fb",
.request = fb_dma_request,
.enable = fb_dma_enable,
.disable = fb_dma_disable,
};
#endif
static int __init fb_dma_init(void)
{
#if 0
dma[_DC21285_DMA(0)].d_ops = &fb_dma_ops;
dma[_DC21285_DMA(1)].d_ops = &fb_dma_ops;
#endif
#ifdef CONFIG_ISA_DMA
if (footbridge_cfn_mode())
isa_init_dma();
#endif
return 0;
}
core_initcall(fb_dma_init);

View file

@ -0,0 +1,47 @@
/*
* linux/arch/arm/mach-footbridge/ebsa285-pci.c
*
* PCI bios-type initialisation for PCI machines
*
* Bits taken from various places.
*/
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <asm/irq.h>
#include <asm/mach/pci.h>
#include <asm/mach-types.h>
static int irqmap_ebsa285[] __initdata = { IRQ_IN3, IRQ_IN1, IRQ_IN0, IRQ_PCI };
static int __init ebsa285_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
dev->device == PCI_DEVICE_ID_CONTAQ_82C693)
switch (PCI_FUNC(dev->devfn)) {
case 1: return 14;
case 2: return 15;
case 3: return 12;
}
return irqmap_ebsa285[(slot + pin) & 3];
}
static struct hw_pci ebsa285_pci __initdata = {
.map_irq = ebsa285_map_irq,
.nr_controllers = 1,
.ops = &dc21285_ops,
.setup = dc21285_setup,
.preinit = dc21285_preinit,
.postinit = dc21285_postinit,
};
static int __init ebsa285_init_pci(void)
{
if (machine_is_ebsa285())
pci_common_init(&ebsa285_pci);
return 0;
}
subsys_initcall(ebsa285_init_pci);

View file

@ -0,0 +1,123 @@
/*
* linux/arch/arm/mach-footbridge/ebsa285.c
*
* EBSA285 machine fixup
*/
#include <linux/init.h>
#include <linux/io.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/leds.h>
#include <asm/hardware/dec21285.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include "common.h"
/* LEDs */
#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
#define XBUS_AMBER_L BIT(0)
#define XBUS_GREEN_L BIT(1)
#define XBUS_RED_L BIT(2)
#define XBUS_TOGGLE BIT(7)
struct ebsa285_led {
struct led_classdev cdev;
u8 mask;
};
/*
* The triggers lines up below will only be used if the
* LED triggers are compiled in.
*/
static const struct {
const char *name;
const char *trigger;
} ebsa285_leds[] = {
{ "ebsa285:amber", "cpu0", },
{ "ebsa285:green", "heartbeat", },
{ "ebsa285:red",},
};
static unsigned char hw_led_state;
static void __iomem *xbus;
static void ebsa285_led_set(struct led_classdev *cdev,
enum led_brightness b)
{
struct ebsa285_led *led = container_of(cdev,
struct ebsa285_led, cdev);
if (b == LED_OFF)
hw_led_state |= led->mask;
else
hw_led_state &= ~led->mask;
writeb(hw_led_state, xbus);
}
static enum led_brightness ebsa285_led_get(struct led_classdev *cdev)
{
struct ebsa285_led *led = container_of(cdev,
struct ebsa285_led, cdev);
return hw_led_state & led->mask ? LED_OFF : LED_FULL;
}
static int __init ebsa285_leds_init(void)
{
int i;
if (!machine_is_ebsa285())
return -ENODEV;
xbus = ioremap(XBUS_CS2, SZ_4K);
if (!xbus)
return -ENOMEM;
/* 3 LEDS all off */
hw_led_state = XBUS_AMBER_L | XBUS_GREEN_L | XBUS_RED_L;
writeb(hw_led_state, xbus);
for (i = 0; i < ARRAY_SIZE(ebsa285_leds); i++) {
struct ebsa285_led *led;
led = kzalloc(sizeof(*led), GFP_KERNEL);
if (!led)
break;
led->cdev.name = ebsa285_leds[i].name;
led->cdev.brightness_set = ebsa285_led_set;
led->cdev.brightness_get = ebsa285_led_get;
led->cdev.default_trigger = ebsa285_leds[i].trigger;
led->mask = BIT(i);
if (led_classdev_register(NULL, &led->cdev) < 0) {
kfree(led);
break;
}
}
return 0;
}
/*
* Since we may have triggers on any subsystem, defer registration
* until after subsystem_init.
*/
fs_initcall(ebsa285_leds_init);
#endif
MACHINE_START(EBSA285, "EBSA285")
/* Maintainer: Russell King */
.atag_offset = 0x100,
.video_start = 0x000a0000,
.video_end = 0x000bffff,
.map_io = footbridge_map_io,
.init_early = footbridge_sched_clock,
.init_irq = footbridge_init_irq,
.init_time = footbridge_timer_init,
.restart = footbridge_restart,
MACHINE_END

View file

@ -0,0 +1,42 @@
/* arch/arm/mach-footbridge/include/mach/debug-macro.S
*
* Debugging macro include header
*
* Copyright (C) 1994-1999 Russell King
* Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <asm/hardware/dec21285.h>
#include <mach/hardware.h>
/* For EBSA285 debugging */
.equ dc21285_high, ARMCSR_BASE & 0xff000000
.equ dc21285_low, ARMCSR_BASE & 0x00ffffff
.macro addruart, rp, rv, tmp
.if dc21285_low
mov \rp, #dc21285_low
.else
mov \rp, #0
.endif
orr \rv, \rp, #dc21285_high
orr \rp, \rp, #0x42000000
.endm
.macro senduart,rd,rx
str \rd, [\rx, #0x160] @ UARTDR
.endm
.macro busyuart,rd,rx
1001: ldr \rd, [\rx, #0x178] @ UARTFLG
tst \rd, #1 << 3
bne 1001b
.endm
.macro waituart,rd,rx
.endm

View file

@ -0,0 +1,107 @@
/*
* arch/arm/mach-footbridge/include/mach/entry-macro.S
*
* Low-level IRQ helper macros for footbridge-based platforms
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <mach/hardware.h>
#include <mach/irqs.h>
#include <asm/hardware/dec21285.h>
.equ dc21285_high, ARMCSR_BASE & 0xff000000
.equ dc21285_low, ARMCSR_BASE & 0x00ffffff
.macro get_irqnr_preamble, base, tmp
mov \base, #dc21285_high
.if dc21285_low
orr \base, \base, #dc21285_low
.endif
.endm
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
ldr \irqstat, [\base, #0x180] @ get interrupts
mov \irqnr, #IRQ_SDRAMPARITY
tst \irqstat, #IRQ_MASK_SDRAMPARITY
bne 1001f
tst \irqstat, #IRQ_MASK_UART_RX
movne \irqnr, #IRQ_CONRX
bne 1001f
tst \irqstat, #IRQ_MASK_DMA1
movne \irqnr, #IRQ_DMA1
bne 1001f
tst \irqstat, #IRQ_MASK_DMA2
movne \irqnr, #IRQ_DMA2
bne 1001f
tst \irqstat, #IRQ_MASK_IN0
movne \irqnr, #IRQ_IN0
bne 1001f
tst \irqstat, #IRQ_MASK_IN1
movne \irqnr, #IRQ_IN1
bne 1001f
tst \irqstat, #IRQ_MASK_IN2
movne \irqnr, #IRQ_IN2
bne 1001f
tst \irqstat, #IRQ_MASK_IN3
movne \irqnr, #IRQ_IN3
bne 1001f
tst \irqstat, #IRQ_MASK_PCI
movne \irqnr, #IRQ_PCI
bne 1001f
tst \irqstat, #IRQ_MASK_DOORBELLHOST
movne \irqnr, #IRQ_DOORBELLHOST
bne 1001f
tst \irqstat, #IRQ_MASK_I2OINPOST
movne \irqnr, #IRQ_I2OINPOST
bne 1001f
tst \irqstat, #IRQ_MASK_TIMER1
movne \irqnr, #IRQ_TIMER1
bne 1001f
tst \irqstat, #IRQ_MASK_TIMER2
movne \irqnr, #IRQ_TIMER2
bne 1001f
tst \irqstat, #IRQ_MASK_TIMER3
movne \irqnr, #IRQ_TIMER3
bne 1001f
tst \irqstat, #IRQ_MASK_UART_TX
movne \irqnr, #IRQ_CONTX
bne 1001f
tst \irqstat, #IRQ_MASK_PCI_ABORT
movne \irqnr, #IRQ_PCI_ABORT
bne 1001f
tst \irqstat, #IRQ_MASK_PCI_SERR
movne \irqnr, #IRQ_PCI_SERR
bne 1001f
tst \irqstat, #IRQ_MASK_DISCARD_TIMER
movne \irqnr, #IRQ_DISCARD_TIMER
bne 1001f
tst \irqstat, #IRQ_MASK_PCI_DPERR
movne \irqnr, #IRQ_PCI_DPERR
bne 1001f
tst \irqstat, #IRQ_MASK_PCI_PERR
movne \irqnr, #IRQ_PCI_PERR
1001:
.endm

View file

@ -0,0 +1,99 @@
/*
* arch/arm/mach-footbridge/include/mach/hardware.h
*
* Copyright (C) 1998-1999 Russell King.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This file contains the hardware definitions of the EBSA-285.
*/
#ifndef __ASM_ARCH_HARDWARE_H
#define __ASM_ARCH_HARDWARE_H
/* Virtual Physical Size
* 0xff800000 0x40000000 1MB X-Bus
* 0xff000000 0x7c000000 1MB PCI I/O space
* 0xfe000000 0x42000000 1MB CSR
* 0xfd000000 0x78000000 1MB Outbound write flush (not supported)
* 0xfc000000 0x79000000 1MB PCI IACK/special space
* 0xfb000000 0x7a000000 16MB PCI Config type 1
* 0xfa000000 0x7b000000 16MB PCI Config type 0
* 0xf9000000 0x50000000 1MB Cache flush
* 0xf0000000 0x80000000 16MB ISA memory
*/
#ifdef CONFIG_MMU
#define MMU_IO(a, b) (a)
#else
#define MMU_IO(a, b) (b)
#endif
#define XBUS_SIZE 0x00100000
#define XBUS_BASE MMU_IO(0xff800000, 0x40000000)
#define ARMCSR_SIZE 0x00100000
#define ARMCSR_BASE MMU_IO(0xfe000000, 0x42000000)
#define WFLUSH_SIZE 0x00100000
#define WFLUSH_BASE MMU_IO(0xfd000000, 0x78000000)
#define PCIIACK_SIZE 0x00100000
#define PCIIACK_BASE MMU_IO(0xfc000000, 0x79000000)
#define PCICFG1_SIZE 0x01000000
#define PCICFG1_BASE MMU_IO(0xfb000000, 0x7a000000)
#define PCICFG0_SIZE 0x01000000
#define PCICFG0_BASE MMU_IO(0xfa000000, 0x7b000000)
#define PCIMEM_SIZE 0x01000000
#define PCIMEM_BASE MMU_IO(0xf0000000, 0x80000000)
#define XBUS_CS2 0x40012000
#define XBUS_SWITCH ((volatile unsigned char *)(XBUS_BASE + 0x12000))
#define XBUS_SWITCH_SWITCH ((*XBUS_SWITCH) & 15)
#define XBUS_SWITCH_J17_13 ((*XBUS_SWITCH) & (1 << 4))
#define XBUS_SWITCH_J17_11 ((*XBUS_SWITCH) & (1 << 5))
#define XBUS_SWITCH_J17_9 ((*XBUS_SWITCH) & (1 << 6))
#define UNCACHEABLE_ADDR (ARMCSR_BASE + 0x108)
/* PIC irq control */
#define PIC_LO 0x20
#define PIC_MASK_LO 0x21
#define PIC_HI 0xA0
#define PIC_MASK_HI 0xA1
/* GPIO pins */
#define GPIO_CCLK 0x800
#define GPIO_DSCLK 0x400
#define GPIO_E2CLK 0x200
#define GPIO_IOLOAD 0x100
#define GPIO_RED_LED 0x080
#define GPIO_WDTIMER 0x040
#define GPIO_DATA 0x020
#define GPIO_IOCLK 0x010
#define GPIO_DONE 0x008
#define GPIO_FAN 0x004
#define GPIO_GREEN_LED 0x002
#define GPIO_RESET 0x001
/* CPLD pins */
#define CPLD_DS_ENABLE 8
#define CPLD_7111_DISABLE 4
#define CPLD_UNMUTE 2
#define CPLD_FLASH_WR_ENABLE 1
#ifndef __ASSEMBLY__
extern raw_spinlock_t nw_gpio_lock;
extern void nw_gpio_modify_op(unsigned int mask, unsigned int set);
extern void nw_gpio_modify_io(unsigned int mask, unsigned int in);
extern unsigned int nw_gpio_read(void);
extern void nw_cpld_modify(unsigned int mask, unsigned int set);
#endif
#endif

View file

@ -0,0 +1,23 @@
/*
* arch/arm/mach-footbridge/include/mach/io.h
*
* Copyright (C) 1997-1999 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Modifications:
* 06-12-1997 RMK Created.
* 07-04-1999 RMK Major cleanup
*/
#ifndef __ASM_ARM_ARCH_IO_H
#define __ASM_ARM_ARCH_IO_H
/*
* Translation of various i/o addresses to host addresses for !CONFIG_MMU
*/
#define PCIO_BASE 0x7c000000
#define __io(a) ((void __iomem *)(PCIO_BASE + (a)))
#endif

View file

@ -0,0 +1,96 @@
/*
* arch/arm/mach-footbridge/include/mach/irqs.h
*
* Copyright (C) 1998 Russell King
* Copyright (C) 1998 Phil Blundell
*
* Changelog:
* 20-Jan-1998 RMK Started merge of EBSA286, CATS and NetWinder
* 01-Feb-1999 PJB ISA IRQs start at 0 not 16
*/
#include <asm/mach-types.h>
#define NR_IRQS 36
#define NR_DC21285_IRQS 16
#define _ISA_IRQ(x) (0 + (x))
#define _ISA_INR(x) ((x) - 0)
#define _DC21285_IRQ(x) (16 + (x))
#define _DC21285_INR(x) ((x) - 16)
/*
* This is a list of all interrupts that the 21285
* can generate and we handle.
*/
#define IRQ_CONRX _DC21285_IRQ(0)
#define IRQ_CONTX _DC21285_IRQ(1)
#define IRQ_TIMER1 _DC21285_IRQ(2)
#define IRQ_TIMER2 _DC21285_IRQ(3)
#define IRQ_TIMER3 _DC21285_IRQ(4)
#define IRQ_IN0 _DC21285_IRQ(5)
#define IRQ_IN1 _DC21285_IRQ(6)
#define IRQ_IN2 _DC21285_IRQ(7)
#define IRQ_IN3 _DC21285_IRQ(8)
#define IRQ_DOORBELLHOST _DC21285_IRQ(9)
#define IRQ_DMA1 _DC21285_IRQ(10)
#define IRQ_DMA2 _DC21285_IRQ(11)
#define IRQ_PCI _DC21285_IRQ(12)
#define IRQ_SDRAMPARITY _DC21285_IRQ(13)
#define IRQ_I2OINPOST _DC21285_IRQ(14)
#define IRQ_PCI_ABORT _DC21285_IRQ(15)
#define IRQ_PCI_SERR _DC21285_IRQ(16)
#define IRQ_DISCARD_TIMER _DC21285_IRQ(17)
#define IRQ_PCI_DPERR _DC21285_IRQ(18)
#define IRQ_PCI_PERR _DC21285_IRQ(19)
#define IRQ_ISA_TIMER _ISA_IRQ(0)
#define IRQ_ISA_KEYBOARD _ISA_IRQ(1)
#define IRQ_ISA_CASCADE _ISA_IRQ(2)
#define IRQ_ISA_UART2 _ISA_IRQ(3)
#define IRQ_ISA_UART _ISA_IRQ(4)
#define IRQ_ISA_FLOPPY _ISA_IRQ(6)
#define IRQ_ISA_PRINTER _ISA_IRQ(7)
#define IRQ_ISA_RTC_ALARM _ISA_IRQ(8)
#define IRQ_ISA_2 _ISA_IRQ(9)
#define IRQ_ISA_PS2MOUSE _ISA_IRQ(12)
#define IRQ_ISA_HARDDISK1 _ISA_IRQ(14)
#define IRQ_ISA_HARDDISK2 _ISA_IRQ(15)
#define IRQ_MASK_UART_RX (1 << 2)
#define IRQ_MASK_UART_TX (1 << 3)
#define IRQ_MASK_TIMER1 (1 << 4)
#define IRQ_MASK_TIMER2 (1 << 5)
#define IRQ_MASK_TIMER3 (1 << 6)
#define IRQ_MASK_IN0 (1 << 8)
#define IRQ_MASK_IN1 (1 << 9)
#define IRQ_MASK_IN2 (1 << 10)
#define IRQ_MASK_IN3 (1 << 11)
#define IRQ_MASK_DOORBELLHOST (1 << 15)
#define IRQ_MASK_DMA1 (1 << 16)
#define IRQ_MASK_DMA2 (1 << 17)
#define IRQ_MASK_PCI (1 << 18)
#define IRQ_MASK_SDRAMPARITY (1 << 24)
#define IRQ_MASK_I2OINPOST (1 << 25)
#define IRQ_MASK_PCI_ABORT ((1 << 29) | (1 << 30))
#define IRQ_MASK_PCI_SERR (1 << 23)
#define IRQ_MASK_DISCARD_TIMER (1 << 27)
#define IRQ_MASK_PCI_DPERR (1 << 28)
#define IRQ_MASK_PCI_PERR (1 << 31)
/*
* Netwinder interrupt allocations
*/
#define IRQ_NETWINDER_ETHER10 IRQ_IN0
#define IRQ_NETWINDER_ETHER100 IRQ_IN1
#define IRQ_NETWINDER_VIDCOMP IRQ_IN2
#define IRQ_NETWINDER_PS2MOUSE _ISA_IRQ(5)
#define IRQ_NETWINDER_IR _ISA_IRQ(6)
#define IRQ_NETWINDER_BUTTON _ISA_IRQ(10)
#define IRQ_NETWINDER_VGA _ISA_IRQ(11)
#define IRQ_NETWINDER_SOUND _ISA_IRQ(12)
#define I8042_KBD_IRQ IRQ_ISA_KEYBOARD
#define I8042_AUX_IRQ (machine_is_netwinder() ? IRQ_NETWINDER_PS2MOUSE : IRQ_ISA_PS2MOUSE)
#define IRQ_FLOPPYDISK IRQ_ISA_FLOPPY
#define irq_canonicalize(_i) (((_i) == IRQ_ISA_CASCADE) ? IRQ_ISA_2 : _i)

View file

@ -0,0 +1,25 @@
/*
* arch/arm/mach-footbridge/include/mach/isa-dma.h
*
* Architecture DMA routines
*
* Copyright (C) 1998,1999 Russell King
* Copyright (C) 1998,1999 Philip Blundell
*/
#ifndef __ASM_ARCH_DMA_H
#define __ASM_ARCH_DMA_H
/*
* The 21285 has two internal DMA channels; we call these 8 and 9.
* On CATS hardware we have an additional eight ISA dma channels
* numbered 0..7.
*/
#define _ISA_DMA(x) (0+(x))
#define _DC21285_DMA(x) (8+(x))
#define MAX_DMA_CHANNELS 10
#define DMA_FLOPPY _ISA_DMA(2)
#define DMA_ISA_CASCADE _ISA_DMA(4)
#endif /* _ASM_ARCH_DMA_H */

View file

@ -0,0 +1,64 @@
/*
* arch/arm/mach-footbridge/include/mach/memory.h
*
* Copyright (C) 1996-1999 Russell King.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Changelog:
* 20-Oct-1996 RMK Created
* 31-Dec-1997 RMK Fixed definitions to reduce warnings.
* 17-May-1998 DAG Added __virt_to_bus and __bus_to_virt functions.
* 21-Nov-1998 RMK Changed __virt_to_bus and __bus_to_virt to macros.
* 21-Mar-1999 RMK Added PAGE_OFFSET for co285 architecture.
* Renamed to memory.h
* Moved PAGE_OFFSET and TASK_SIZE here
*/
#ifndef __ASM_ARCH_MEMORY_H
#define __ASM_ARCH_MEMORY_H
#if defined(CONFIG_FOOTBRIDGE_ADDIN)
/*
* If we may be using add-in footbridge mode, then we must
* use the out-of-line translation that makes use of the
* PCI BAR
*/
#ifndef __ASSEMBLY__
extern unsigned long __virt_to_bus(unsigned long);
extern unsigned long __bus_to_virt(unsigned long);
extern unsigned long __pfn_to_bus(unsigned long);
extern unsigned long __bus_to_pfn(unsigned long);
#endif
#define __virt_to_bus __virt_to_bus
#define __bus_to_virt __bus_to_virt
#elif defined(CONFIG_FOOTBRIDGE_HOST)
/*
* The footbridge is programmed to expose the system RAM at 0xe0000000.
* The requirement is that the RAM isn't placed at bus address 0, which
* would clash with VGA cards.
*/
#define BUS_OFFSET 0xe0000000
#define __virt_to_bus(x) ((x) + (BUS_OFFSET - PAGE_OFFSET))
#define __bus_to_virt(x) ((x) - (BUS_OFFSET - PAGE_OFFSET))
#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - PHYS_OFFSET))
#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - PHYS_OFFSET))
#else
#error "Undefined footbridge mode"
#endif
/*
* Cache flushing area.
*/
#define FLUSH_BASE 0xf9000000
#define FLUSH_BASE_PHYS 0x50000000
#endif

View file

@ -0,0 +1,37 @@
/*
* arch/arm/mach-footbridge/include/mach/uncompress.h
*
* Copyright (C) 1996-1999 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <asm/mach-types.h>
/*
* Note! This could cause problems on the NetWinder
*/
#define DC21285_BASE ((volatile unsigned int *)0x42000160)
#define SER0_BASE ((volatile unsigned char *)0x7c0003f8)
static inline void putc(char c)
{
if (machine_is_netwinder()) {
while ((SER0_BASE[5] & 0x60) != 0x60)
barrier();
SER0_BASE[0] = c;
} else {
while (DC21285_BASE[6] & 8);
DC21285_BASE[0] = c;
}
}
static inline void flush(void)
{
}
/*
* nothing to do
*/
#define arch_decomp_setup()

View file

@ -0,0 +1,183 @@
/*
* linux/arch/arm/mach-footbridge/irq.c
*
* Copyright (C) 1996-2000 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Changelog:
* 22-Aug-1998 RMK Restructured IRQ routines
* 03-Sep-1998 PJB Merged CATS support
* 20-Jan-1998 RMK Started merge of EBSA286, CATS and NetWinder
* 26-Jan-1999 PJB Don't use IACK on CATS
* 16-Mar-1999 RMK Added autodetect of ISA PICs
*/
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/spinlock.h>
#include <asm/mach/irq.h>
#include <mach/hardware.h>
#include <asm/hardware/dec21285.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
#include "common.h"
static void isa_mask_pic_lo_irq(struct irq_data *d)
{
unsigned int mask = 1 << (d->irq & 7);
outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
}
static void isa_ack_pic_lo_irq(struct irq_data *d)
{
unsigned int mask = 1 << (d->irq & 7);
outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
outb(0x20, PIC_LO);
}
static void isa_unmask_pic_lo_irq(struct irq_data *d)
{
unsigned int mask = 1 << (d->irq & 7);
outb(inb(PIC_MASK_LO) & ~mask, PIC_MASK_LO);
}
static struct irq_chip isa_lo_chip = {
.irq_ack = isa_ack_pic_lo_irq,
.irq_mask = isa_mask_pic_lo_irq,
.irq_unmask = isa_unmask_pic_lo_irq,
};
static void isa_mask_pic_hi_irq(struct irq_data *d)
{
unsigned int mask = 1 << (d->irq & 7);
outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
}
static void isa_ack_pic_hi_irq(struct irq_data *d)
{
unsigned int mask = 1 << (d->irq & 7);
outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
outb(0x62, PIC_LO);
outb(0x20, PIC_HI);
}
static void isa_unmask_pic_hi_irq(struct irq_data *d)
{
unsigned int mask = 1 << (d->irq & 7);
outb(inb(PIC_MASK_HI) & ~mask, PIC_MASK_HI);
}
static struct irq_chip isa_hi_chip = {
.irq_ack = isa_ack_pic_hi_irq,
.irq_mask = isa_mask_pic_hi_irq,
.irq_unmask = isa_unmask_pic_hi_irq,
};
static void
isa_irq_handler(unsigned int irq, struct irq_desc *desc)
{
unsigned int isa_irq = *(unsigned char *)PCIIACK_BASE;
if (isa_irq < _ISA_IRQ(0) || isa_irq >= _ISA_IRQ(16)) {
do_bad_IRQ(isa_irq, desc);
return;
}
generic_handle_irq(isa_irq);
}
static struct irqaction irq_cascade = {
.handler = no_action,
.name = "cascade",
};
static struct resource pic1_resource = {
.name = "pic1",
.start = 0x20,
.end = 0x3f,
};
static struct resource pic2_resource = {
.name = "pic2",
.start = 0xa0,
.end = 0xbf,
};
void __init isa_init_irq(unsigned int host_irq)
{
unsigned int irq;
/*
* Setup, and then probe for an ISA PIC
* If the PIC is not there, then we
* ignore the PIC.
*/
outb(0x11, PIC_LO);
outb(_ISA_IRQ(0), PIC_MASK_LO); /* IRQ number */
outb(0x04, PIC_MASK_LO); /* Slave on Ch2 */
outb(0x01, PIC_MASK_LO); /* x86 */
outb(0xf5, PIC_MASK_LO); /* pattern: 11110101 */
outb(0x11, PIC_HI);
outb(_ISA_IRQ(8), PIC_MASK_HI); /* IRQ number */
outb(0x02, PIC_MASK_HI); /* Slave on Ch1 */
outb(0x01, PIC_MASK_HI); /* x86 */
outb(0xfa, PIC_MASK_HI); /* pattern: 11111010 */
outb(0x0b, PIC_LO);
outb(0x0b, PIC_HI);
if (inb(PIC_MASK_LO) == 0xf5 && inb(PIC_MASK_HI) == 0xfa) {
outb(0xff, PIC_MASK_LO);/* mask all IRQs */
outb(0xff, PIC_MASK_HI);/* mask all IRQs */
} else {
printk(KERN_INFO "IRQ: ISA PIC not found\n");
host_irq = (unsigned int)-1;
}
if (host_irq != (unsigned int)-1) {
for (irq = _ISA_IRQ(0); irq < _ISA_IRQ(8); irq++) {
irq_set_chip_and_handler(irq, &isa_lo_chip,
handle_level_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
for (irq = _ISA_IRQ(8); irq < _ISA_IRQ(16); irq++) {
irq_set_chip_and_handler(irq, &isa_hi_chip,
handle_level_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
request_resource(&ioport_resource, &pic1_resource);
request_resource(&ioport_resource, &pic2_resource);
setup_irq(IRQ_ISA_CASCADE, &irq_cascade);
irq_set_chained_handler(host_irq, isa_irq_handler);
/*
* On the NetWinder, don't automatically
* enable ISA IRQ11 when it is requested.
* There appears to be a missing pull-up
* resistor on this line.
*/
if (machine_is_netwinder())
set_irq_flags(_ISA_IRQ(11), IRQF_VALID |
IRQF_PROBE | IRQF_NOAUTOEN);
}
}

View file

@ -0,0 +1,57 @@
/*
* arch/arm/mach-footbridge/isa-rtc.c
*
* Copyright (C) 1998 Russell King.
* Copyright (C) 1998 Phil Blundell
*
* CATS has a real-time clock, though the evaluation board doesn't.
*
* Changelog:
* 21-Mar-1998 RMK Created
* 27-Aug-1998 PJB CATS support
* 28-Dec-1998 APH Made leds optional
* 20-Jan-1999 RMK Started merge of EBSA285, CATS and NetWinder
* 16-Mar-1999 RMK More support for EBSA285-like machines with RTCs in
*/
#define RTC_PORT(x) (0x70+(x))
#define RTC_ALWAYS_BCD 0
#include <linux/init.h>
#include <linux/mc146818rtc.h>
#include <linux/bcd.h>
#include <linux/io.h>
#include "common.h"
void __init isa_rtc_init(void)
{
int reg_d, reg_b;
/*
* Probe for the RTC.
*/
reg_d = CMOS_READ(RTC_REG_D);
/*
* make sure the divider is set
*/
CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_REG_A);
/*
* Set control reg B
* (24 hour mode, update enabled)
*/
reg_b = CMOS_READ(RTC_REG_B) & 0x7f;
reg_b |= 2;
CMOS_WRITE(reg_b, RTC_REG_B);
if ((CMOS_READ(RTC_REG_A) & 0x7f) == RTC_REF_CLCK_32KHZ &&
CMOS_READ(RTC_REG_B) == reg_b) {
/*
* We have a RTC. Check the battery
*/
if ((reg_d & 0x80) == 0)
printk(KERN_WARNING "RTC: *** warning: CMOS battery bad\n");
}
}

View file

@ -0,0 +1,40 @@
/*
* linux/arch/arm/mach-footbridge/isa-timer.c
*
* Copyright (C) 1998 Russell King.
* Copyright (C) 1998 Phil Blundell
*/
#include <linux/clockchips.h>
#include <linux/i8253.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/spinlock.h>
#include <linux/timex.h>
#include <asm/irq.h>
#include <asm/mach/time.h>
#include "common.h"
static irqreturn_t pit_timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *ce = dev_id;
ce->event_handler(ce);
return IRQ_HANDLED;
}
static struct irqaction pit_timer_irq = {
.name = "pit",
.handler = pit_timer_interrupt,
.flags = IRQF_TIMER | IRQF_IRQPOLL,
.dev_id = &i8253_clockevent,
};
void __init isa_timer_init(void)
{
clocksource_i8253_init();
setup_irq(i8253_clockevent.irq, &pit_timer_irq);
clockevent_i8253_init(false);
}

View file

@ -0,0 +1,101 @@
/*
* linux/arch/arm/mach-footbridge/isa.c
*
* Copyright (C) 2004 Russell King.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/serial_8250.h>
#include <asm/irq.h>
#include <asm/hardware/dec21285.h>
#include "common.h"
static struct resource rtc_resources[] = {
[0] = {
.start = 0x70,
.end = 0x73,
.flags = IORESOURCE_IO,
},
[1] = {
.start = IRQ_ISA_RTC_ALARM,
.end = IRQ_ISA_RTC_ALARM,
.flags = IORESOURCE_IRQ,
}
};
static struct platform_device rtc_device = {
.name = "rtc_cmos",
.id = -1,
.resource = rtc_resources,
.num_resources = ARRAY_SIZE(rtc_resources),
};
static struct resource serial_resources[] = {
[0] = {
.start = 0x3f8,
.end = 0x3ff,
.flags = IORESOURCE_IO,
},
[1] = {
.start = 0x2f8,
.end = 0x2ff,
.flags = IORESOURCE_IO,
},
};
static struct plat_serial8250_port serial_platform_data[] = {
{
.iobase = 0x3f8,
.irq = IRQ_ISA_UART,
.uartclk = 1843200,
.regshift = 0,
.iotype = UPIO_PORT,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
},
{
.iobase = 0x2f8,
.irq = IRQ_ISA_UART2,
.uartclk = 1843200,
.regshift = 0,
.iotype = UPIO_PORT,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
},
{ },
};
static struct platform_device serial_device = {
.name = "serial8250",
.id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = serial_platform_data,
},
.resource = serial_resources,
.num_resources = ARRAY_SIZE(serial_resources),
};
static int __init footbridge_isa_init(void)
{
int err = 0;
if (!footbridge_cfn_mode())
return 0;
/* Personal server doesn't have RTC */
if (!machine_is_personal_server()) {
isa_rtc_init();
err = platform_device_register(&rtc_device);
if (err)
printk(KERN_ERR "Unable to register RTC device: %d\n", err);
}
err = platform_device_register(&serial_device);
if (err)
printk(KERN_ERR "Unable to register serial device: %d\n", err);
return 0;
}
arch_initcall(footbridge_isa_init);

View file

@ -0,0 +1,771 @@
/*
* linux/arch/arm/mach-footbridge/netwinder-hw.c
*
* Netwinder machine fixup
*
* Copyright (C) 1998, 1999 Russell King, Phil Blundell
*/
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/leds.h>
#include <asm/hardware/dec21285.h>
#include <asm/mach-types.h>
#include <asm/setup.h>
#include <asm/system_misc.h>
#include <asm/mach/arch.h>
#include "common.h"
#define IRDA_IO_BASE 0x180
#define GP1_IO_BASE 0x338
#define GP2_IO_BASE 0x33a
/*
* Winbond WB83977F accessibility stuff
*/
static inline void wb977_open(void)
{
outb(0x87, 0x370);
outb(0x87, 0x370);
}
static inline void wb977_close(void)
{
outb(0xaa, 0x370);
}
static inline void wb977_wb(int reg, int val)
{
outb(reg, 0x370);
outb(val, 0x371);
}
static inline void wb977_ww(int reg, int val)
{
outb(reg, 0x370);
outb(val >> 8, 0x371);
outb(reg + 1, 0x370);
outb(val & 255, 0x371);
}
#define wb977_device_select(dev) wb977_wb(0x07, dev)
#define wb977_device_disable() wb977_wb(0x30, 0x00)
#define wb977_device_enable() wb977_wb(0x30, 0x01)
/*
* This is a lock for accessing ports GP1_IO_BASE and GP2_IO_BASE
*/
DEFINE_RAW_SPINLOCK(nw_gpio_lock);
EXPORT_SYMBOL(nw_gpio_lock);
static unsigned int current_gpio_op;
static unsigned int current_gpio_io;
static unsigned int current_cpld;
void nw_gpio_modify_op(unsigned int mask, unsigned int set)
{
unsigned int new_gpio, changed;
new_gpio = (current_gpio_op & ~mask) | set;
changed = new_gpio ^ current_gpio_op;
current_gpio_op = new_gpio;
if (changed & 0xff)
outb(new_gpio, GP1_IO_BASE);
if (changed & 0xff00)
outb(new_gpio >> 8, GP2_IO_BASE);
}
EXPORT_SYMBOL(nw_gpio_modify_op);
static inline void __gpio_modify_io(int mask, int in)
{
unsigned int new_gpio, changed;
int port;
new_gpio = (current_gpio_io & ~mask) | in;
changed = new_gpio ^ current_gpio_io;
current_gpio_io = new_gpio;
changed >>= 1;
new_gpio >>= 1;
wb977_device_select(7);
for (port = 0xe1; changed && port < 0xe8; changed >>= 1) {
wb977_wb(port, new_gpio & 1);
port += 1;
new_gpio >>= 1;
}
wb977_device_select(8);
for (port = 0xe8; changed && port < 0xec; changed >>= 1) {
wb977_wb(port, new_gpio & 1);
port += 1;
new_gpio >>= 1;
}
}
void nw_gpio_modify_io(unsigned int mask, unsigned int in)
{
/* Open up the SuperIO chip */
wb977_open();
__gpio_modify_io(mask, in);
/* Close up the EFER gate */
wb977_close();
}
EXPORT_SYMBOL(nw_gpio_modify_io);
unsigned int nw_gpio_read(void)
{
return inb(GP1_IO_BASE) | inb(GP2_IO_BASE) << 8;
}
EXPORT_SYMBOL(nw_gpio_read);
/*
* Initialise the Winbond W83977F global registers
*/
static inline void wb977_init_global(void)
{
/*
* Enable R/W config registers
*/
wb977_wb(0x26, 0x40);
/*
* Power down FDC (not used)
*/
wb977_wb(0x22, 0xfe);
/*
* GP12, GP11, CIRRX, IRRXH, GP10
*/
wb977_wb(0x2a, 0xc1);
/*
* GP23, GP22, GP21, GP20, GP13
*/
wb977_wb(0x2b, 0x6b);
/*
* GP17, GP16, GP15, GP14
*/
wb977_wb(0x2c, 0x55);
}
/*
* Initialise the Winbond W83977F printer port
*/
static inline void wb977_init_printer(void)
{
wb977_device_select(1);
/*
* mode 1 == EPP
*/
wb977_wb(0xf0, 0x01);
}
/*
* Initialise the Winbond W83977F keyboard controller
*/
static inline void wb977_init_keyboard(void)
{
wb977_device_select(5);
/*
* Keyboard controller address
*/
wb977_ww(0x60, 0x0060);
wb977_ww(0x62, 0x0064);
/*
* Keyboard IRQ 1, active high, edge trigger
*/
wb977_wb(0x70, 1);
wb977_wb(0x71, 0x02);
/*
* Mouse IRQ 5, active high, edge trigger
*/
wb977_wb(0x72, 5);
wb977_wb(0x73, 0x02);
/*
* KBC 8MHz
*/
wb977_wb(0xf0, 0x40);
/*
* Enable device
*/
wb977_device_enable();
}
/*
* Initialise the Winbond W83977F Infra-Red device
*/
static inline void wb977_init_irda(void)
{
wb977_device_select(6);
/*
* IR base address
*/
wb977_ww(0x60, IRDA_IO_BASE);
/*
* IRDA IRQ 6, active high, edge trigger
*/
wb977_wb(0x70, 6);
wb977_wb(0x71, 0x02);
/*
* RX DMA - ISA DMA 0
*/
wb977_wb(0x74, 0x00);
/*
* TX DMA - Disable Tx DMA
*/
wb977_wb(0x75, 0x04);
/*
* Append CRC, Enable bank selection
*/
wb977_wb(0xf0, 0x03);
/*
* Enable device
*/
wb977_device_enable();
}
/*
* Initialise Winbond W83977F general purpose IO
*/
static inline void wb977_init_gpio(void)
{
unsigned long flags;
/*
* Set up initial I/O definitions
*/
current_gpio_io = -1;
__gpio_modify_io(-1, GPIO_DONE | GPIO_WDTIMER);
wb977_device_select(7);
/*
* Group1 base address
*/
wb977_ww(0x60, GP1_IO_BASE);
wb977_ww(0x62, 0);
wb977_ww(0x64, 0);
/*
* GP10 (Orage button) IRQ 10, active high, edge trigger
*/
wb977_wb(0x70, 10);
wb977_wb(0x71, 0x02);
/*
* GP10: Debounce filter enabled, IRQ, input
*/
wb977_wb(0xe0, 0x19);
/*
* Enable Group1
*/
wb977_device_enable();
wb977_device_select(8);
/*
* Group2 base address
*/
wb977_ww(0x60, GP2_IO_BASE);
/*
* Clear watchdog timer regs
* - timer disable
*/
wb977_wb(0xf2, 0x00);
/*
* - disable LED, no mouse nor keyboard IRQ
*/
wb977_wb(0xf3, 0x00);
/*
* - timer counting, disable power LED, disable timeouot
*/
wb977_wb(0xf4, 0x00);
/*
* Enable group2
*/
wb977_device_enable();
/*
* Set Group1/Group2 outputs
*/
raw_spin_lock_irqsave(&nw_gpio_lock, flags);
nw_gpio_modify_op(-1, GPIO_RED_LED | GPIO_FAN);
raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
}
/*
* Initialise the Winbond W83977F chip.
*/
static void __init wb977_init(void)
{
request_region(0x370, 2, "W83977AF configuration");
/*
* Open up the SuperIO chip
*/
wb977_open();
/*
* Initialise the global registers
*/
wb977_init_global();
/*
* Initialise the various devices in
* the multi-IO chip.
*/
wb977_init_printer();
wb977_init_keyboard();
wb977_init_irda();
wb977_init_gpio();
/*
* Close up the EFER gate
*/
wb977_close();
}
void nw_cpld_modify(unsigned int mask, unsigned int set)
{
int msk;
current_cpld = (current_cpld & ~mask) | set;
nw_gpio_modify_io(GPIO_DATA | GPIO_IOCLK | GPIO_IOLOAD, 0);
nw_gpio_modify_op(GPIO_IOLOAD, 0);
for (msk = 8; msk; msk >>= 1) {
int bit = current_cpld & msk;
nw_gpio_modify_op(GPIO_DATA | GPIO_IOCLK, bit ? GPIO_DATA : 0);
nw_gpio_modify_op(GPIO_IOCLK, GPIO_IOCLK);
}
nw_gpio_modify_op(GPIO_IOCLK|GPIO_DATA, 0);
nw_gpio_modify_op(GPIO_IOLOAD|GPIO_DSCLK, GPIO_IOLOAD|GPIO_DSCLK);
nw_gpio_modify_op(GPIO_IOLOAD, 0);
}
EXPORT_SYMBOL(nw_cpld_modify);
static void __init cpld_init(void)
{
unsigned long flags;
raw_spin_lock_irqsave(&nw_gpio_lock, flags);
nw_cpld_modify(-1, CPLD_UNMUTE | CPLD_7111_DISABLE);
raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
}
static unsigned char rwa_unlock[] __initdata =
{ 0x00, 0x00, 0x6a, 0xb5, 0xda, 0xed, 0xf6, 0xfb, 0x7d, 0xbe, 0xdf, 0x6f, 0x37, 0x1b,
0x0d, 0x86, 0xc3, 0x61, 0xb0, 0x58, 0x2c, 0x16, 0x8b, 0x45, 0xa2, 0xd1, 0xe8, 0x74,
0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39 };
#ifndef DEBUG
#define dprintk(x...)
#else
#define dprintk(x...) printk(x)
#endif
#define WRITE_RWA(r,v) do { outb((r), 0x279); udelay(10); outb((v), 0xa79); } while (0)
static inline void rwa010_unlock(void)
{
int i;
WRITE_RWA(2, 2);
mdelay(10);
for (i = 0; i < sizeof(rwa_unlock); i++) {
outb(rwa_unlock[i], 0x279);
udelay(10);
}
}
static inline void rwa010_read_ident(void)
{
unsigned char si[9];
int i, j;
WRITE_RWA(3, 0);
WRITE_RWA(0, 128);
outb(1, 0x279);
mdelay(1);
dprintk("Identifier: ");
for (i = 0; i < 9; i++) {
si[i] = 0;
for (j = 0; j < 8; j++) {
int bit;
udelay(250);
inb(0x203);
udelay(250);
bit = inb(0x203);
dprintk("%02X ", bit);
bit = (bit == 0xaa) ? 1 : 0;
si[i] |= bit << j;
}
dprintk("(%02X) ", si[i]);
}
dprintk("\n");
}
static inline void rwa010_global_init(void)
{
WRITE_RWA(6, 2); // Assign a card no = 2
dprintk("Card no = %d\n", inb(0x203));
/* disable the modem section of the chip */
WRITE_RWA(7, 3);
WRITE_RWA(0x30, 0);
/* disable the cdrom section of the chip */
WRITE_RWA(7, 4);
WRITE_RWA(0x30, 0);
/* disable the MPU-401 section of the chip */
WRITE_RWA(7, 2);
WRITE_RWA(0x30, 0);
}
static inline void rwa010_game_port_init(void)
{
int i;
WRITE_RWA(7, 5);
dprintk("Slider base: ");
WRITE_RWA(0x61, 1);
i = inb(0x203);
WRITE_RWA(0x60, 2);
dprintk("%02X%02X (201)\n", inb(0x203), i);
WRITE_RWA(0x30, 1);
}
static inline void rwa010_waveartist_init(int base, int irq, int dma)
{
int i;
WRITE_RWA(7, 0);
dprintk("WaveArtist base: ");
WRITE_RWA(0x61, base & 255);
i = inb(0x203);
WRITE_RWA(0x60, base >> 8);
dprintk("%02X%02X (%X),", inb(0x203), i, base);
WRITE_RWA(0x70, irq);
dprintk(" irq: %d (%d),", inb(0x203), irq);
WRITE_RWA(0x74, dma);
dprintk(" dma: %d (%d)\n", inb(0x203), dma);
WRITE_RWA(0x30, 1);
}
static inline void rwa010_soundblaster_init(int sb_base, int al_base, int irq, int dma)
{
int i;
WRITE_RWA(7, 1);
dprintk("SoundBlaster base: ");
WRITE_RWA(0x61, sb_base & 255);
i = inb(0x203);
WRITE_RWA(0x60, sb_base >> 8);
dprintk("%02X%02X (%X),", inb(0x203), i, sb_base);
dprintk(" irq: ");
WRITE_RWA(0x70, irq);
dprintk("%d (%d),", inb(0x203), irq);
dprintk(" 8-bit DMA: ");
WRITE_RWA(0x74, dma);
dprintk("%d (%d)\n", inb(0x203), dma);
dprintk("AdLib base: ");
WRITE_RWA(0x63, al_base & 255);
i = inb(0x203);
WRITE_RWA(0x62, al_base >> 8);
dprintk("%02X%02X (%X)\n", inb(0x203), i, al_base);
WRITE_RWA(0x30, 1);
}
static void rwa010_soundblaster_reset(void)
{
int i;
outb(1, 0x226);
udelay(3);
outb(0, 0x226);
for (i = 0; i < 5; i++) {
if (inb(0x22e) & 0x80)
break;
mdelay(1);
}
if (i == 5)
printk("SoundBlaster: DSP reset failed\n");
dprintk("SoundBlaster DSP reset: %02X (AA)\n", inb(0x22a));
for (i = 0; i < 5; i++) {
if ((inb(0x22c) & 0x80) == 0)
break;
mdelay(1);
}
if (i == 5)
printk("SoundBlaster: DSP not ready\n");
else {
outb(0xe1, 0x22c);
dprintk("SoundBlaster DSP id: ");
i = inb(0x22a);
udelay(1);
i |= inb(0x22a) << 8;
dprintk("%04X\n", i);
for (i = 0; i < 5; i++) {
if ((inb(0x22c) & 0x80) == 0)
break;
mdelay(1);
}
if (i == 5)
printk("SoundBlaster: could not turn speaker off\n");
outb(0xd3, 0x22c);
}
/* turn on OPL3 */
outb(5, 0x38a);
outb(1, 0x38b);
}
static void __init rwa010_init(void)
{
rwa010_unlock();
rwa010_read_ident();
rwa010_global_init();
rwa010_game_port_init();
rwa010_waveartist_init(0x250, 3, 7);
rwa010_soundblaster_init(0x220, 0x388, 3, 1);
rwa010_soundblaster_reset();
}
/*
* Initialise any other hardware after we've got the PCI bus
* initialised. We may need the PCI bus to talk to this other
* hardware.
*/
static int __init nw_hw_init(void)
{
if (machine_is_netwinder()) {
wb977_init();
cpld_init();
rwa010_init();
}
return 0;
}
__initcall(nw_hw_init);
/*
* Older NeTTroms either do not provide a parameters
* page, or they don't supply correct information in
* the parameter page.
*/
static void __init
fixup_netwinder(struct tag *tags, char **cmdline)
{
#ifdef CONFIG_ISAPNP
extern int isapnp_disable;
/*
* We must not use the kernels ISAPnP code
* on the NetWinder - it will reset the settings
* for the WaveArtist chip and render it inoperable.
*/
isapnp_disable = 1;
#endif
}
static void netwinder_restart(enum reboot_mode mode, const char *cmd)
{
if (mode == REBOOT_SOFT) {
/* Jump into the ROM */
soft_restart(0x41000000);
} else {
local_irq_disable();
local_fiq_disable();
/* open up the SuperIO chip */
outb(0x87, 0x370);
outb(0x87, 0x370);
/* aux function group 1 (logical device 7) */
outb(0x07, 0x370);
outb(0x07, 0x371);
/* set GP16 for WD-TIMER output */
outb(0xe6, 0x370);
outb(0x00, 0x371);
/* set a RED LED and toggle WD_TIMER for rebooting */
outb(0xc4, 0x338);
}
}
/* LEDs */
#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
struct netwinder_led {
struct led_classdev cdev;
u8 mask;
};
/*
* The triggers lines up below will only be used if the
* LED triggers are compiled in.
*/
static const struct {
const char *name;
const char *trigger;
} netwinder_leds[] = {
{ "netwinder:green", "heartbeat", },
{ "netwinder:red", "cpu0", },
};
/*
* The LED control in Netwinder is reversed:
* - setting bit means turn off LED
* - clearing bit means turn on LED
*/
static void netwinder_led_set(struct led_classdev *cdev,
enum led_brightness b)
{
struct netwinder_led *led = container_of(cdev,
struct netwinder_led, cdev);
unsigned long flags;
u32 reg;
raw_spin_lock_irqsave(&nw_gpio_lock, flags);
reg = nw_gpio_read();
if (b != LED_OFF)
reg &= ~led->mask;
else
reg |= led->mask;
nw_gpio_modify_op(led->mask, reg);
raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
}
static enum led_brightness netwinder_led_get(struct led_classdev *cdev)
{
struct netwinder_led *led = container_of(cdev,
struct netwinder_led, cdev);
unsigned long flags;
u32 reg;
raw_spin_lock_irqsave(&nw_gpio_lock, flags);
reg = nw_gpio_read();
raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
return (reg & led->mask) ? LED_OFF : LED_FULL;
}
static int __init netwinder_leds_init(void)
{
int i;
if (!machine_is_netwinder())
return -ENODEV;
for (i = 0; i < ARRAY_SIZE(netwinder_leds); i++) {
struct netwinder_led *led;
led = kzalloc(sizeof(*led), GFP_KERNEL);
if (!led)
break;
led->cdev.name = netwinder_leds[i].name;
led->cdev.brightness_set = netwinder_led_set;
led->cdev.brightness_get = netwinder_led_get;
led->cdev.default_trigger = netwinder_leds[i].trigger;
if (i == 0)
led->mask = GPIO_GREEN_LED;
else
led->mask = GPIO_RED_LED;
if (led_classdev_register(NULL, &led->cdev) < 0) {
kfree(led);
break;
}
}
return 0;
}
/*
* Since we may have triggers on any subsystem, defer registration
* until after subsystem_init.
*/
fs_initcall(netwinder_leds_init);
#endif
MACHINE_START(NETWINDER, "Rebel-NetWinder")
/* Maintainer: Russell King/Rebel.com */
.atag_offset = 0x100,
.video_start = 0x000a0000,
.video_end = 0x000bffff,
.reserve_lp0 = 1,
.reserve_lp2 = 1,
.fixup = fixup_netwinder,
.map_io = footbridge_map_io,
.init_irq = footbridge_init_irq,
.init_time = isa_timer_init,
.restart = netwinder_restart,
MACHINE_END

View file

@ -0,0 +1,61 @@
/*
* linux/arch/arm/mach-footbridge/netwinder-pci.c
*
* PCI bios-type initialisation for PCI machines
*
* Bits taken from various places.
*/
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <asm/irq.h>
#include <asm/mach/pci.h>
#include <asm/mach-types.h>
/*
* We now use the slot ID instead of the device identifiers to select
* which interrupt is routed where.
*/
static int __init netwinder_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
switch (slot) {
case 0: /* host bridge */
return 0;
case 9: /* CyberPro */
return IRQ_NETWINDER_VGA;
case 10: /* DC21143 */
return IRQ_NETWINDER_ETHER100;
case 12: /* Winbond 553 */
return IRQ_ISA_HARDDISK1;
case 13: /* Winbond 89C940F */
return IRQ_NETWINDER_ETHER10;
default:
printk(KERN_ERR "PCI: unknown device in slot %s\n",
pci_name(dev));
return 0;
}
}
static struct hw_pci netwinder_pci __initdata = {
.map_irq = netwinder_map_irq,
.nr_controllers = 1,
.ops = &dc21285_ops,
.setup = dc21285_setup,
.preinit = dc21285_preinit,
.postinit = dc21285_postinit,
};
static int __init netwinder_pci_init(void)
{
if (machine_is_netwinder())
pci_common_init(&netwinder_pci);
return 0;
}
subsys_initcall(netwinder_pci_init);

View file

@ -0,0 +1,57 @@
/*
* linux/arch/arm/mach-footbridge/personal-pci.c
*
* PCI bios-type initialisation for PCI machines
*
* Bits taken from various places.
*/
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <asm/irq.h>
#include <asm/mach/pci.h>
#include <asm/mach-types.h>
static int irqmap_personal_server[] __initdata = {
IRQ_IN0, IRQ_IN1, IRQ_IN2, IRQ_IN3, 0, 0, 0,
IRQ_DOORBELLHOST, IRQ_DMA1, IRQ_DMA2, IRQ_PCI
};
static int __init personal_server_map_irq(const struct pci_dev *dev, u8 slot,
u8 pin)
{
unsigned char line;
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &line);
if (line > 0x40 && line <= 0x5f) {
/* line corresponds to the bit controlling this interrupt
* in the footbridge. Ignore the first 8 interrupt bits,
* look up the rest in the map. IN0 is bit number 8
*/
return irqmap_personal_server[(line & 0x1f) - 8];
} else if (line == 0) {
/* no interrupt */
return 0;
} else
return irqmap_personal_server[(line - 1) & 3];
}
static struct hw_pci personal_server_pci __initdata = {
.map_irq = personal_server_map_irq,
.nr_controllers = 1,
.ops = &dc21285_ops,
.setup = dc21285_setup,
.preinit = dc21285_preinit,
.postinit = dc21285_postinit,
};
static int __init personal_pci_init(void)
{
if (machine_is_personal_server())
pci_common_init(&personal_server_pci);
return 0;
}
subsys_initcall(personal_pci_init);

View file

@ -0,0 +1,24 @@
/*
* linux/arch/arm/mach-footbridge/personal.c
*
* Personal server (Skiff) machine fixup
*/
#include <linux/init.h>
#include <linux/spinlock.h>
#include <asm/hardware/dec21285.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include "common.h"
MACHINE_START(PERSONAL_SERVER, "Compaq-PersonalServer")
/* Maintainer: Jamey Hicks / George France */
.atag_offset = 0x100,
.map_io = footbridge_map_io,
.init_irq = footbridge_init_irq,
.init_time = footbridge_timer_init,
.restart = footbridge_restart,
MACHINE_END