Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Этот коммит содержится в:
80
arch/arm/mach-footbridge/Kconfig
Обычный файл
80
arch/arm/mach-footbridge/Kconfig
Обычный файл
@@ -0,0 +1,80 @@
|
||||
if ARCH_FOOTBRIDGE
|
||||
|
||||
menu "Footbridge Implementations"
|
||||
|
||||
config ARCH_CATS
|
||||
bool "CATS"
|
||||
select FOOTBRIDGE_HOST
|
||||
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
|
||||
---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
|
||||
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 FOOTBRIDGE_HOST
|
||||
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
|
||||
|
||||
# Footbridge in addin mode
|
||||
config FOOTBRIDGE_ADDIN
|
||||
bool
|
||||
|
||||
# EBSA285 board in either host or addin mode
|
||||
config ARCH_EBSA285
|
||||
bool
|
||||
|
||||
endif
|
30
arch/arm/mach-footbridge/Makefile
Обычный файл
30
arch/arm/mach-footbridge/Makefile
Обычный файл
@@ -0,0 +1,30 @@
|
||||
#
|
||||
# Makefile for the linux kernel.
|
||||
#
|
||||
|
||||
# Object file lists.
|
||||
|
||||
obj-y := common.o dc21285.o dma.o isa-irq.o time.o
|
||||
obj-m :=
|
||||
obj-n :=
|
||||
obj- :=
|
||||
|
||||
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
|
||||
|
||||
leds-$(CONFIG_ARCH_CO285) += ebsa285-leds.o
|
||||
leds-$(CONFIG_ARCH_EBSA285) += ebsa285-leds.o
|
||||
leds-$(CONFIG_ARCH_NETWINDER) += netwinder-leds.o
|
||||
|
||||
obj-$(CONFIG_ARCH_CATS) += cats-hw.o isa-timer.o
|
||||
obj-$(CONFIG_ARCH_CO285) += co285.o dc21285-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_LEDS) +=$(leds-y)
|
||||
|
||||
obj-$(CONFIG_ISA) += isa.o
|
4
arch/arm/mach-footbridge/Makefile.boot
Обычный файл
4
arch/arm/mach-footbridge/Makefile.boot
Обычный файл
@@ -0,0 +1,4 @@
|
||||
zreladdr-y := 0x00008000
|
||||
params_phys-y := 0x00000100
|
||||
initrd_phys-y := 0x00800000
|
||||
|
95
arch/arm/mach-footbridge/cats-hw.c
Обычный файл
95
arch/arm/mach-footbridge/cats-hw.c
Обычный файл
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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/tty.h>
|
||||
|
||||
#include <asm/hardware/dec21285.h>
|
||||
#include <asm/io.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 machine_desc *desc, struct tag *tags,
|
||||
char **cmdline, struct meminfo *mi)
|
||||
{
|
||||
ORIG_VIDEO_LINES = 25;
|
||||
ORIG_VIDEO_POINTS = 16;
|
||||
ORIG_Y = 24;
|
||||
}
|
||||
|
||||
MACHINE_START(CATS, "Chalice-CATS")
|
||||
MAINTAINER("Philip Blundell")
|
||||
BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000)
|
||||
BOOT_PARAMS(0x00000100)
|
||||
SOFT_REBOOT
|
||||
FIXUP(fixup_cats)
|
||||
MAPIO(footbridge_map_io)
|
||||
INITIRQ(footbridge_init_irq)
|
||||
.timer = &isa_timer,
|
||||
MACHINE_END
|
55
arch/arm/mach-footbridge/cats-pci.c
Обычный файл
55
arch/arm/mach-footbridge/cats-pci.c
Обычный файл
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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 int __init cats_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
|
||||
{
|
||||
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 = NULL,
|
||||
.map_irq = cats_map_irq,
|
||||
.nr_controllers = 1,
|
||||
.setup = dc21285_setup,
|
||||
.scan = dc21285_scan_bus,
|
||||
.preinit = dc21285_preinit,
|
||||
.postinit = dc21285_postinit,
|
||||
};
|
||||
|
||||
static int cats_pci_init(void)
|
||||
{
|
||||
if (machine_is_cats())
|
||||
pci_common_init(&cats_pci);
|
||||
return 0;
|
||||
}
|
||||
|
||||
subsys_initcall(cats_pci_init);
|
38
arch/arm/mach-footbridge/co285.c
Обычный файл
38
arch/arm/mach-footbridge/co285.c
Обычный файл
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-footbridge/co285.c
|
||||
*
|
||||
* CO285 machine fixup
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/hardware/dec21285.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static void __init
|
||||
fixup_coebsa285(struct machine_desc *desc, struct tag *tags,
|
||||
char **cmdline, struct meminfo *mi)
|
||||
{
|
||||
extern unsigned long boot_memory_end;
|
||||
extern char boot_command_line[];
|
||||
|
||||
mi->nr_banks = 1;
|
||||
mi->bank[0].start = PHYS_OFFSET;
|
||||
mi->bank[0].size = boot_memory_end;
|
||||
mi->bank[0].node = 0;
|
||||
|
||||
*cmdline = boot_command_line;
|
||||
}
|
||||
|
||||
MACHINE_START(CO285, "co-EBSA285")
|
||||
MAINTAINER("Mark van Doesburg")
|
||||
BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0x7cf00000)
|
||||
FIXUP(fixup_coebsa285)
|
||||
MAPIO(footbridge_map_io)
|
||||
INITIRQ(footbridge_init_irq)
|
||||
.timer = &footbridge_timer,
|
||||
MACHINE_END
|
||||
|
205
arch/arm/mach-footbridge/common.c
Обычный файл
205
arch/arm/mach-footbridge/common.c
Обычный файл
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* 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/config.h>
|
||||
#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 <asm/pgtable.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/hardware/dec21285.h>
|
||||
|
||||
#include <asm/mach/irq.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
extern void __init isa_init_irq(unsigned int irq);
|
||||
|
||||
unsigned int mem_fclk_21285 = 50000000;
|
||||
|
||||
EXPORT_SYMBOL(mem_fclk_21285);
|
||||
|
||||
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(unsigned int irq)
|
||||
{
|
||||
*CSR_IRQ_DISABLE = fb_irq_mask[_DC21285_INR(irq)];
|
||||
}
|
||||
|
||||
static void fb_unmask_irq(unsigned int irq)
|
||||
{
|
||||
*CSR_IRQ_ENABLE = fb_irq_mask[_DC21285_INR(irq)];
|
||||
}
|
||||
|
||||
static struct irqchip fb_chip = {
|
||||
.ack = fb_mask_irq,
|
||||
.mask = fb_mask_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++) {
|
||||
set_irq_chip(irq, &fb_chip);
|
||||
set_irq_handler(irq, do_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 = {
|
||||
{ ARMCSR_BASE, DC21285_ARMCSR_BASE, ARMCSR_SIZE, MT_DEVICE },
|
||||
{ XBUS_BASE, 0x40000000, XBUS_SIZE, 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)
|
||||
{ PCIMEM_BASE, DC21285_PCI_MEM, PCIMEM_SIZE, MT_DEVICE },
|
||||
{ PCICFG0_BASE, DC21285_PCI_TYPE_0_CONFIG, PCICFG0_SIZE, MT_DEVICE },
|
||||
{ PCICFG1_BASE, DC21285_PCI_TYPE_1_CONFIG, PCICFG1_SIZE, MT_DEVICE },
|
||||
{ PCIIACK_BASE, DC21285_PCI_IACK, PCIIACK_SIZE, MT_DEVICE },
|
||||
{ PCIO_BASE, DC21285_PCI_IO, PCIO_SIZE, MT_DEVICE }
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* The CO-ebsa285 mapping.
|
||||
*/
|
||||
static struct map_desc co285_io_desc[] __initdata = {
|
||||
#ifdef CONFIG_ARCH_CO285
|
||||
{ PCIO_BASE, DC21285_PCI_IO, PCIO_SIZE, MT_DEVICE },
|
||||
{ PCIMEM_BASE, DC21285_PCI_MEM, PCIMEM_SIZE, 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 (machine_is_co285())
|
||||
iotable_init(co285_io_desc, ARRAY_SIZE(co285_io_desc));
|
||||
if (footbridge_cfn_mode())
|
||||
iotable_init(ebsa285_host_io_desc, ARRAY_SIZE(ebsa285_host_io_desc));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FOOTBRIDGE_ADDIN
|
||||
|
||||
/*
|
||||
* 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 - PAGE_OFFSET) + (*CSR_PCISDRAMBASE & 0xfffffff0);
|
||||
}
|
||||
EXPORT_SYMBOL(__virt_to_bus);
|
||||
|
||||
unsigned long __bus_to_virt(unsigned long res)
|
||||
{
|
||||
res -= (*CSR_PCISDRAMBASE & 0xfffffff0);
|
||||
res += PAGE_OFFSET;
|
||||
|
||||
WARN_ON(res < PAGE_OFFSET || res >= (unsigned long)high_memory);
|
||||
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(__bus_to_virt);
|
||||
|
||||
#endif
|
9
arch/arm/mach-footbridge/common.h
Обычный файл
9
arch/arm/mach-footbridge/common.h
Обычный файл
@@ -0,0 +1,9 @@
|
||||
|
||||
extern struct sys_timer footbridge_timer;
|
||||
extern struct sys_timer isa_timer;
|
||||
|
||||
extern void isa_rtc_init(void);
|
||||
|
||||
extern void footbridge_map_io(void);
|
||||
extern void footbridge_init_irq(void);
|
||||
|
68
arch/arm/mach-footbridge/dc21285-timer.c
Обычный файл
68
arch/arm/mach-footbridge/dc21285-timer.c
Обычный файл
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-footbridge/dc21285-timer.c
|
||||
*
|
||||
* Copyright (C) 1998 Russell King.
|
||||
* Copyright (C) 1998 Phil Blundell
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <asm/hardware/dec21285.h>
|
||||
#include <asm/mach/time.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* Footbridge timer 1 support.
|
||||
*/
|
||||
static unsigned long timer1_latch;
|
||||
|
||||
static unsigned long timer1_gettimeoffset (void)
|
||||
{
|
||||
unsigned long value = timer1_latch - *CSR_TIMER1_VALUE;
|
||||
|
||||
return ((tick_nsec / 1000) * value) / timer1_latch;
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
write_seqlock(&xtime_lock);
|
||||
|
||||
*CSR_TIMER1_CLR = 0;
|
||||
|
||||
timer_tick(regs);
|
||||
|
||||
write_sequnlock(&xtime_lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct irqaction footbridge_timer_irq = {
|
||||
.name = "Timer1 timer tick",
|
||||
.handler = timer1_interrupt,
|
||||
.flags = SA_INTERRUPT,
|
||||
};
|
||||
|
||||
/*
|
||||
* Set up timer interrupt.
|
||||
*/
|
||||
static void __init footbridge_timer_init(void)
|
||||
{
|
||||
isa_rtc_init();
|
||||
|
||||
timer1_latch = (mem_fclk_21285 + 8 * HZ) / (16 * HZ);
|
||||
|
||||
*CSR_TIMER1_CLR = 0;
|
||||
*CSR_TIMER1_LOAD = timer1_latch;
|
||||
*CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
|
||||
|
||||
setup_irq(IRQ_TIMER1, &footbridge_timer_irq);
|
||||
}
|
||||
|
||||
struct sys_timer footbridge_timer = {
|
||||
.init = footbridge_timer_init,
|
||||
.offset = timer1_gettimeoffset,
|
||||
};
|
384
arch/arm/mach-footbridge/dc21285.c
Обычный файл
384
arch/arm/mach-footbridge/dc21285.c
Обычный файл
@@ -0,0 +1,384 @@
|
||||
/*
|
||||
* 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/ptrace.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/ioport.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/system.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);
|
||||
extern void register_isa_ports(unsigned int, unsigned int, unsigned int);
|
||||
|
||||
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("ldr%?b %0, [%1, %2]"
|
||||
: "=r" (v) : "r" (addr), "r" (where));
|
||||
break;
|
||||
case 2:
|
||||
asm("ldr%?h %0, [%1, %2]"
|
||||
: "=r" (v) : "r" (addr), "r" (where));
|
||||
break;
|
||||
case 4:
|
||||
asm("ldr%? %0, [%1, %2]"
|
||||
: "=r" (v) : "r" (addr), "r" (where));
|
||||
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("str%?b %0, [%1, %2]"
|
||||
: : "r" (value), "r" (addr), "r" (where));
|
||||
break;
|
||||
case 2:
|
||||
asm("str%?h %0, [%1, %2]"
|
||||
: : "r" (value), "r" (addr), "r" (where));
|
||||
break;
|
||||
case 4:
|
||||
asm("str%? %0, [%1, %2]"
|
||||
: : "r" (value), "r" (addr), "r" (where));
|
||||
break;
|
||||
}
|
||||
|
||||
v = *CSR_PCICMD;
|
||||
if (v & PCICMD_ABORT) {
|
||||
*CSR_PCICMD = v & (0xffff|PCICMD_ABORT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static 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, struct pt_regs *regs)
|
||||
{
|
||||
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(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 pt_regs *regs)
|
||||
{
|
||||
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, struct pt_regs *regs)
|
||||
{
|
||||
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, struct pt_regs *regs)
|
||||
{
|
||||
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 pt_regs *regs)
|
||||
{
|
||||
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 = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL);
|
||||
if (!res) {
|
||||
printk("out of memory for root bus resources");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(res, 0, sizeof(struct resource) * 2);
|
||||
|
||||
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->resource[0] = &ioport_resource;
|
||||
sys->resource[1] = &res[0];
|
||||
sys->resource[2] = &res[1];
|
||||
sys->mem_offset = DC21285_PCI_MEM;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct pci_bus * __init dc21285_scan_bus(int nr, struct pci_sys_data *sys)
|
||||
{
|
||||
return pci_scan_bus(0, &dc21285_ops, sys);
|
||||
}
|
||||
|
||||
void __init dc21285_preinit(void)
|
||||
{
|
||||
unsigned int mem_size, mem_mask;
|
||||
int cfn_mode;
|
||||
|
||||
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.
|
||||
*/
|
||||
request_irq(IRQ_PCI_SERR, dc21285_serr_irq, SA_INTERRUPT,
|
||||
"PCI system error", &serr_timer);
|
||||
request_irq(IRQ_PCI_PERR, dc21285_parity_irq, SA_INTERRUPT,
|
||||
"PCI parity error", &perr_timer);
|
||||
request_irq(IRQ_PCI_ABORT, dc21285_abort_irq, SA_INTERRUPT,
|
||||
"PCI abort", NULL);
|
||||
request_irq(IRQ_DISCARD_TIMER, dc21285_discard_irq, SA_INTERRUPT,
|
||||
"Discard timer", NULL);
|
||||
request_irq(IRQ_PCI_DPERR, dc21285_dparity_irq, SA_INTERRUPT,
|
||||
"PCI data parity", NULL);
|
||||
|
||||
if (cfn_mode) {
|
||||
static struct resource csrio;
|
||||
|
||||
csrio.flags = IORESOURCE_IO;
|
||||
csrio.name = "Footbridge";
|
||||
|
||||
allocate_resource(&ioport_resource, &csrio, 128,
|
||||
0xff00, 0xffff, 128, NULL, NULL);
|
||||
|
||||
/*
|
||||
* 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 = csrio.start;
|
||||
*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);
|
||||
}
|
54
arch/arm/mach-footbridge/dma.c
Обычный файл
54
arch/arm/mach-footbridge/dma.c
Обычный файл
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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/config.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/dma.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <asm/mach/dma.h>
|
||||
#include <asm/hardware/dec21285.h>
|
||||
|
||||
#if 0
|
||||
static int fb_dma_request(dmach_t channel, dma_t *dma)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void fb_dma_enable(dmach_t channel, dma_t *dma)
|
||||
{
|
||||
}
|
||||
|
||||
static void fb_dma_disable(dmach_t channel, 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
|
||||
|
||||
void __init arch_dma_init(dma_t *dma)
|
||||
{
|
||||
#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(dma + _ISA_DMA(0));
|
||||
#endif
|
||||
}
|
140
arch/arm/mach-footbridge/ebsa285-leds.c
Обычный файл
140
arch/arm/mach-footbridge/ebsa285-leds.c
Обычный файл
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-footbridge/ebsa285-leds.c
|
||||
*
|
||||
* 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.
|
||||
* EBSA-285 control routines.
|
||||
*
|
||||
* The EBSA-285 uses the leds as follows:
|
||||
* - Green - toggles state every 50 timer interrupts
|
||||
* - Amber - On if system is not idle
|
||||
* - Red - currently unused
|
||||
*
|
||||
* Changelog:
|
||||
* 02-05-1999 RMK Various cleanups
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/leds.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
#define LED_STATE_ENABLED 1
|
||||
#define LED_STATE_CLAIMED 2
|
||||
static char led_state;
|
||||
static char hw_led_state;
|
||||
|
||||
static DEFINE_SPINLOCK(leds_lock);
|
||||
|
||||
static void ebsa285_leds_event(led_event_t evt)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&leds_lock, flags);
|
||||
|
||||
switch (evt) {
|
||||
case led_start:
|
||||
hw_led_state = XBUS_LED_RED | XBUS_LED_GREEN;
|
||||
#ifndef CONFIG_LEDS_CPU
|
||||
hw_led_state |= XBUS_LED_AMBER;
|
||||
#endif
|
||||
led_state |= LED_STATE_ENABLED;
|
||||
break;
|
||||
|
||||
case led_stop:
|
||||
led_state &= ~LED_STATE_ENABLED;
|
||||
break;
|
||||
|
||||
case led_claim:
|
||||
led_state |= LED_STATE_CLAIMED;
|
||||
hw_led_state = XBUS_LED_RED | XBUS_LED_GREEN | XBUS_LED_AMBER;
|
||||
break;
|
||||
|
||||
case led_release:
|
||||
led_state &= ~LED_STATE_CLAIMED;
|
||||
hw_led_state = XBUS_LED_RED | XBUS_LED_GREEN | XBUS_LED_AMBER;
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_LEDS_TIMER
|
||||
case led_timer:
|
||||
if (!(led_state & LED_STATE_CLAIMED))
|
||||
hw_led_state ^= XBUS_LED_GREEN;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LEDS_CPU
|
||||
case led_idle_start:
|
||||
if (!(led_state & LED_STATE_CLAIMED))
|
||||
hw_led_state |= XBUS_LED_AMBER;
|
||||
break;
|
||||
|
||||
case led_idle_end:
|
||||
if (!(led_state & LED_STATE_CLAIMED))
|
||||
hw_led_state &= ~XBUS_LED_AMBER;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case led_halted:
|
||||
if (!(led_state & LED_STATE_CLAIMED))
|
||||
hw_led_state &= ~XBUS_LED_RED;
|
||||
break;
|
||||
|
||||
case led_green_on:
|
||||
if (led_state & LED_STATE_CLAIMED)
|
||||
hw_led_state &= ~XBUS_LED_GREEN;
|
||||
break;
|
||||
|
||||
case led_green_off:
|
||||
if (led_state & LED_STATE_CLAIMED)
|
||||
hw_led_state |= XBUS_LED_GREEN;
|
||||
break;
|
||||
|
||||
case led_amber_on:
|
||||
if (led_state & LED_STATE_CLAIMED)
|
||||
hw_led_state &= ~XBUS_LED_AMBER;
|
||||
break;
|
||||
|
||||
case led_amber_off:
|
||||
if (led_state & LED_STATE_CLAIMED)
|
||||
hw_led_state |= XBUS_LED_AMBER;
|
||||
break;
|
||||
|
||||
case led_red_on:
|
||||
if (led_state & LED_STATE_CLAIMED)
|
||||
hw_led_state &= ~XBUS_LED_RED;
|
||||
break;
|
||||
|
||||
case led_red_off:
|
||||
if (led_state & LED_STATE_CLAIMED)
|
||||
hw_led_state |= XBUS_LED_RED;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (led_state & LED_STATE_ENABLED)
|
||||
*XBUS_LEDS = hw_led_state;
|
||||
|
||||
spin_unlock_irqrestore(&leds_lock, flags);
|
||||
}
|
||||
|
||||
static int __init leds_init(void)
|
||||
{
|
||||
if (machine_is_ebsa285() || machine_is_co285())
|
||||
leds_event = ebsa285_leds_event;
|
||||
|
||||
leds_event(led_start);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__initcall(leds_init);
|
48
arch/arm/mach-footbridge/ebsa285-pci.c
Обычный файл
48
arch/arm/mach-footbridge/ebsa285-pci.c
Обычный файл
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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(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 = {
|
||||
.swizzle = pci_std_swizzle,
|
||||
.map_irq = ebsa285_map_irq,
|
||||
.nr_controllers = 1,
|
||||
.setup = dc21285_setup,
|
||||
.scan = dc21285_scan_bus,
|
||||
.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);
|
24
arch/arm/mach-footbridge/ebsa285.c
Обычный файл
24
arch/arm/mach-footbridge/ebsa285.c
Обычный файл
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-footbridge/ebsa285.c
|
||||
*
|
||||
* EBSA285 machine fixup
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/hardware/dec21285.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
MACHINE_START(EBSA285, "EBSA285")
|
||||
MAINTAINER("Russell King")
|
||||
BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000)
|
||||
BOOT_PARAMS(0x00000100)
|
||||
VIDEO(0x000a0000, 0x000bffff)
|
||||
MAPIO(footbridge_map_io)
|
||||
INITIRQ(footbridge_init_irq)
|
||||
.timer = &footbridge_timer,
|
||||
MACHINE_END
|
||||
|
168
arch/arm/mach-footbridge/isa-irq.c
Обычный файл
168
arch/arm/mach-footbridge/isa-irq.c
Обычный файл
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* 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 <asm/mach/irq.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/hardware/dec21285.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
static void isa_mask_pic_lo_irq(unsigned int irq)
|
||||
{
|
||||
unsigned int mask = 1 << (irq & 7);
|
||||
|
||||
outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
|
||||
}
|
||||
|
||||
static void isa_ack_pic_lo_irq(unsigned int irq)
|
||||
{
|
||||
unsigned int mask = 1 << (irq & 7);
|
||||
|
||||
outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
|
||||
outb(0x20, PIC_LO);
|
||||
}
|
||||
|
||||
static void isa_unmask_pic_lo_irq(unsigned int irq)
|
||||
{
|
||||
unsigned int mask = 1 << (irq & 7);
|
||||
|
||||
outb(inb(PIC_MASK_LO) & ~mask, PIC_MASK_LO);
|
||||
}
|
||||
|
||||
static struct irqchip isa_lo_chip = {
|
||||
.ack = isa_ack_pic_lo_irq,
|
||||
.mask = isa_mask_pic_lo_irq,
|
||||
.unmask = isa_unmask_pic_lo_irq,
|
||||
};
|
||||
|
||||
static void isa_mask_pic_hi_irq(unsigned int irq)
|
||||
{
|
||||
unsigned int mask = 1 << (irq & 7);
|
||||
|
||||
outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
|
||||
}
|
||||
|
||||
static void isa_ack_pic_hi_irq(unsigned int irq)
|
||||
{
|
||||
unsigned int mask = 1 << (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(unsigned int irq)
|
||||
{
|
||||
unsigned int mask = 1 << (irq & 7);
|
||||
|
||||
outb(inb(PIC_MASK_HI) & ~mask, PIC_MASK_HI);
|
||||
}
|
||||
|
||||
static struct irqchip isa_hi_chip = {
|
||||
.ack = isa_ack_pic_hi_irq,
|
||||
.mask = isa_mask_pic_hi_irq,
|
||||
.unmask = isa_unmask_pic_hi_irq,
|
||||
};
|
||||
|
||||
static void
|
||||
isa_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
|
||||
{
|
||||
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, regs);
|
||||
return;
|
||||
}
|
||||
|
||||
desc = irq_desc + isa_irq;
|
||||
desc->handle(isa_irq, desc, regs);
|
||||
}
|
||||
|
||||
static struct irqaction irq_cascade = { .handler = no_action, .name = "cascade", };
|
||||
static struct resource pic1_resource = { "pic1", 0x20, 0x3f };
|
||||
static struct resource pic2_resource = { "pic2", 0xa0, 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++) {
|
||||
set_irq_chip(irq, &isa_lo_chip);
|
||||
set_irq_handler(irq, do_level_IRQ);
|
||||
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
|
||||
}
|
||||
|
||||
for (irq = _ISA_IRQ(8); irq < _ISA_IRQ(16); irq++) {
|
||||
set_irq_chip(irq, &isa_hi_chip);
|
||||
set_irq_handler(irq, do_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);
|
||||
|
||||
set_irq_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);
|
||||
}
|
||||
}
|
||||
|
||||
|
94
arch/arm/mach-footbridge/isa-timer.c
Обычный файл
94
arch/arm/mach-footbridge/isa-timer.c
Обычный файл
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-footbridge/isa-timer.c
|
||||
*
|
||||
* Copyright (C) 1998 Russell King.
|
||||
* Copyright (C) 1998 Phil Blundell
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <asm/mach/time.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* ISA timer tick support
|
||||
*/
|
||||
#define mSEC_10_from_14 ((14318180 + 100) / 200)
|
||||
|
||||
static unsigned long isa_gettimeoffset(void)
|
||||
{
|
||||
int count;
|
||||
|
||||
static int count_p = (mSEC_10_from_14/6); /* for the first call after boot */
|
||||
static unsigned long jiffies_p = 0;
|
||||
|
||||
/*
|
||||
* cache volatile jiffies temporarily; we have IRQs turned off.
|
||||
*/
|
||||
unsigned long jiffies_t;
|
||||
|
||||
/* timer count may underflow right here */
|
||||
outb_p(0x00, 0x43); /* latch the count ASAP */
|
||||
|
||||
count = inb_p(0x40); /* read the latched count */
|
||||
|
||||
/*
|
||||
* We do this guaranteed double memory access instead of a _p
|
||||
* postfix in the previous port access. Wheee, hackady hack
|
||||
*/
|
||||
jiffies_t = jiffies;
|
||||
|
||||
count |= inb_p(0x40) << 8;
|
||||
|
||||
/* Detect timer underflows. If we haven't had a timer tick since
|
||||
the last time we were called, and time is apparently going
|
||||
backwards, the counter must have wrapped during this routine. */
|
||||
if ((jiffies_t == jiffies_p) && (count > count_p))
|
||||
count -= (mSEC_10_from_14/6);
|
||||
else
|
||||
jiffies_p = jiffies_t;
|
||||
|
||||
count_p = count;
|
||||
|
||||
count = (((mSEC_10_from_14/6)-1) - count) * (tick_nsec / 1000);
|
||||
count = (count + (mSEC_10_from_14/6)/2) / (mSEC_10_from_14/6);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
isa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
write_seqlock(&xtime_lock);
|
||||
timer_tick(regs);
|
||||
write_sequnlock(&xtime_lock);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct irqaction isa_timer_irq = {
|
||||
.name = "ISA timer tick",
|
||||
.handler = isa_timer_interrupt,
|
||||
.flags = SA_INTERRUPT,
|
||||
};
|
||||
|
||||
static void __init isa_timer_init(void)
|
||||
{
|
||||
isa_rtc_init();
|
||||
|
||||
/* enable PIT timer */
|
||||
/* set for periodic (4) and LSB/MSB write (0x30) */
|
||||
outb(0x34, 0x43);
|
||||
outb((mSEC_10_from_14/6) & 0xFF, 0x40);
|
||||
outb((mSEC_10_from_14/6) >> 8, 0x40);
|
||||
|
||||
setup_irq(IRQ_ISA_TIMER, &isa_timer_irq);
|
||||
}
|
||||
|
||||
struct sys_timer isa_timer = {
|
||||
.init = isa_timer_init,
|
||||
.offset = isa_gettimeoffset,
|
||||
};
|
48
arch/arm/mach-footbridge/isa.c
Обычный файл
48
arch/arm/mach-footbridge/isa.c
Обычный файл
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
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 = 0,
|
||||
.dev = {
|
||||
.platform_data = serial_platform_data,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init footbridge_isa_init(void)
|
||||
{
|
||||
return platform_device_register(&serial_device);
|
||||
}
|
||||
|
||||
arch_initcall(footbridge_isa_init);
|
660
arch/arm/mach-footbridge/netwinder-hw.c
Обычный файл
660
arch/arm/mach-footbridge/netwinder-hw.c
Обычный файл
@@ -0,0 +1,660 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-footbridge/netwinder-hw.c
|
||||
*
|
||||
* Netwinder machine fixup
|
||||
*
|
||||
* Copyright (C) 1998, 1999 Russell King, Phil Blundell
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/hardware/dec21285.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/leds.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define IRDA_IO_BASE 0x180
|
||||
#define GP1_IO_BASE 0x338
|
||||
#define GP2_IO_BASE 0x33a
|
||||
|
||||
|
||||
#ifdef CONFIG_LEDS
|
||||
#define DEFAULT_LEDS 0
|
||||
#else
|
||||
#define DEFAULT_LEDS GPIO_GREEN_LED
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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_SPINLOCK(gpio_lock);
|
||||
|
||||
static unsigned int current_gpio_op;
|
||||
static unsigned int current_gpio_io;
|
||||
static unsigned int current_cpld;
|
||||
|
||||
void gpio_modify_op(int mask, 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);
|
||||
}
|
||||
|
||||
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 gpio_modify_io(int mask, int in)
|
||||
{
|
||||
/* Open up the SuperIO chip */
|
||||
wb977_open();
|
||||
|
||||
__gpio_modify_io(mask, in);
|
||||
|
||||
/* Close up the EFER gate */
|
||||
wb977_close();
|
||||
}
|
||||
|
||||
int gpio_read(void)
|
||||
{
|
||||
return inb(GP1_IO_BASE) | inb(GP2_IO_BASE) << 8;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
gpio_modify_op(-1, GPIO_RED_LED | GPIO_FAN);
|
||||
spin_unlock_irqrestore(&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 cpld_modify(int mask, int set)
|
||||
{
|
||||
int msk;
|
||||
|
||||
current_cpld = (current_cpld & ~mask) | set;
|
||||
|
||||
gpio_modify_io(GPIO_DATA | GPIO_IOCLK | GPIO_IOLOAD, 0);
|
||||
gpio_modify_op(GPIO_IOLOAD, 0);
|
||||
|
||||
for (msk = 8; msk; msk >>= 1) {
|
||||
int bit = current_cpld & msk;
|
||||
|
||||
gpio_modify_op(GPIO_DATA | GPIO_IOCLK, bit ? GPIO_DATA : 0);
|
||||
gpio_modify_op(GPIO_IOCLK, GPIO_IOCLK);
|
||||
}
|
||||
|
||||
gpio_modify_op(GPIO_IOCLK|GPIO_DATA, 0);
|
||||
gpio_modify_op(GPIO_IOLOAD|GPIO_DSCLK, GPIO_IOLOAD|GPIO_DSCLK);
|
||||
gpio_modify_op(GPIO_IOLOAD, 0);
|
||||
}
|
||||
|
||||
static void __init cpld_init(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
cpld_modify(-1, CPLD_UNMUTE | CPLD_7111_DISABLE);
|
||||
spin_unlock_irqrestore(&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();
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(gpio_lock);
|
||||
EXPORT_SYMBOL(gpio_modify_op);
|
||||
EXPORT_SYMBOL(gpio_modify_io);
|
||||
EXPORT_SYMBOL(cpld_modify);
|
||||
|
||||
/*
|
||||
* 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()) {
|
||||
unsigned long flags;
|
||||
|
||||
wb977_init();
|
||||
cpld_init();
|
||||
rwa010_init();
|
||||
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, DEFAULT_LEDS);
|
||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||
}
|
||||
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 machine_desc *desc, struct tag *tags,
|
||||
char **cmdline, struct meminfo *mi)
|
||||
{
|
||||
#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
|
||||
}
|
||||
|
||||
MACHINE_START(NETWINDER, "Rebel-NetWinder")
|
||||
MAINTAINER("Russell King/Rebel.com")
|
||||
BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000)
|
||||
BOOT_PARAMS(0x00000100)
|
||||
VIDEO(0x000a0000, 0x000bffff)
|
||||
DISABLE_PARPORT(0)
|
||||
DISABLE_PARPORT(2)
|
||||
FIXUP(fixup_netwinder)
|
||||
MAPIO(footbridge_map_io)
|
||||
INITIRQ(footbridge_init_irq)
|
||||
.timer = &isa_timer,
|
||||
MACHINE_END
|
141
arch/arm/mach-footbridge/netwinder-leds.c
Обычный файл
141
arch/arm/mach-footbridge/netwinder-leds.c
Обычный файл
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-footbridge/netwinder-leds.c
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* NetWinder LED control routines.
|
||||
*
|
||||
* The Netwinder uses the leds as follows:
|
||||
* - Green - toggles state every 50 timer interrupts
|
||||
* - Red - On if the system is not idle
|
||||
*
|
||||
* Changelog:
|
||||
* 02-05-1999 RMK Various cleanups
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/leds.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
#define LED_STATE_ENABLED 1
|
||||
#define LED_STATE_CLAIMED 2
|
||||
static char led_state;
|
||||
static char hw_led_state;
|
||||
|
||||
static DEFINE_SPINLOCK(leds_lock);
|
||||
extern spinlock_t gpio_lock;
|
||||
|
||||
static void netwinder_leds_event(led_event_t evt)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&leds_lock, flags);
|
||||
|
||||
switch (evt) {
|
||||
case led_start:
|
||||
led_state |= LED_STATE_ENABLED;
|
||||
hw_led_state = GPIO_GREEN_LED;
|
||||
break;
|
||||
|
||||
case led_stop:
|
||||
led_state &= ~LED_STATE_ENABLED;
|
||||
break;
|
||||
|
||||
case led_claim:
|
||||
led_state |= LED_STATE_CLAIMED;
|
||||
hw_led_state = 0;
|
||||
break;
|
||||
|
||||
case led_release:
|
||||
led_state &= ~LED_STATE_CLAIMED;
|
||||
hw_led_state = 0;
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_LEDS_TIMER
|
||||
case led_timer:
|
||||
if (!(led_state & LED_STATE_CLAIMED))
|
||||
hw_led_state ^= GPIO_GREEN_LED;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LEDS_CPU
|
||||
case led_idle_start:
|
||||
if (!(led_state & LED_STATE_CLAIMED))
|
||||
hw_led_state &= ~GPIO_RED_LED;
|
||||
break;
|
||||
|
||||
case led_idle_end:
|
||||
if (!(led_state & LED_STATE_CLAIMED))
|
||||
hw_led_state |= GPIO_RED_LED;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case led_halted:
|
||||
if (!(led_state & LED_STATE_CLAIMED))
|
||||
hw_led_state |= GPIO_RED_LED;
|
||||
break;
|
||||
|
||||
case led_green_on:
|
||||
if (led_state & LED_STATE_CLAIMED)
|
||||
hw_led_state |= GPIO_GREEN_LED;
|
||||
break;
|
||||
|
||||
case led_green_off:
|
||||
if (led_state & LED_STATE_CLAIMED)
|
||||
hw_led_state &= ~GPIO_GREEN_LED;
|
||||
break;
|
||||
|
||||
case led_amber_on:
|
||||
if (led_state & LED_STATE_CLAIMED)
|
||||
hw_led_state |= GPIO_GREEN_LED | GPIO_RED_LED;
|
||||
break;
|
||||
|
||||
case led_amber_off:
|
||||
if (led_state & LED_STATE_CLAIMED)
|
||||
hw_led_state &= ~(GPIO_GREEN_LED | GPIO_RED_LED);
|
||||
break;
|
||||
|
||||
case led_red_on:
|
||||
if (led_state & LED_STATE_CLAIMED)
|
||||
hw_led_state |= GPIO_RED_LED;
|
||||
break;
|
||||
|
||||
case led_red_off:
|
||||
if (led_state & LED_STATE_CLAIMED)
|
||||
hw_led_state &= ~GPIO_RED_LED;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&leds_lock, flags);
|
||||
|
||||
if (led_state & LED_STATE_ENABLED) {
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
gpio_modify_op(GPIO_RED_LED | GPIO_GREEN_LED, hw_led_state);
|
||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init leds_init(void)
|
||||
{
|
||||
if (machine_is_netwinder())
|
||||
leds_event = netwinder_leds_event;
|
||||
|
||||
leds_event(led_start);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__initcall(leds_init);
|
62
arch/arm/mach-footbridge/netwinder-pci.c
Обычный файл
62
arch/arm/mach-footbridge/netwinder-pci.c
Обычный файл
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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(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 = {
|
||||
.swizzle = pci_std_swizzle,
|
||||
.map_irq = netwinder_map_irq,
|
||||
.nr_controllers = 1,
|
||||
.setup = dc21285_setup,
|
||||
.scan = dc21285_scan_bus,
|
||||
.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);
|
56
arch/arm/mach-footbridge/personal-pci.c
Обычный файл
56
arch/arm/mach-footbridge/personal-pci.c
Обычный файл
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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(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,
|
||||
.setup = dc21285_setup,
|
||||
.scan = dc21285_scan_bus,
|
||||
.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);
|
23
arch/arm/mach-footbridge/personal.c
Обычный файл
23
arch/arm/mach-footbridge/personal.c
Обычный файл
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-footbridge/personal.c
|
||||
*
|
||||
* Personal server (Skiff) machine fixup
|
||||
*/
|
||||
#include <linux/init.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")
|
||||
BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000)
|
||||
BOOT_PARAMS(0x00000100)
|
||||
MAPIO(footbridge_map_io)
|
||||
INITIRQ(footbridge_init_irq)
|
||||
.timer = &footbridge_timer,
|
||||
MACHINE_END
|
||||
|
180
arch/arm/mach-footbridge/time.c
Обычный файл
180
arch/arm/mach-footbridge/time.c
Обычный файл
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* linux/include/asm-arm/arch-ebsa285/time.h
|
||||
*
|
||||
* 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) (rtc_base+(x))
|
||||
#define RTC_ALWAYS_BCD 0
|
||||
|
||||
#include <linux/timex.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mc146818rtc.h>
|
||||
#include <linux/bcd.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <asm/mach/time.h>
|
||||
#include "common.h"
|
||||
|
||||
static int rtc_base;
|
||||
|
||||
static unsigned long __init get_isa_cmos_time(void)
|
||||
{
|
||||
unsigned int year, mon, day, hour, min, sec;
|
||||
int i;
|
||||
|
||||
// check to see if the RTC makes sense.....
|
||||
if ((CMOS_READ(RTC_VALID) & RTC_VRT) == 0)
|
||||
return mktime(1970, 1, 1, 0, 0, 0);
|
||||
|
||||
/* The Linux interpretation of the CMOS clock register contents:
|
||||
* When the Update-In-Progress (UIP) flag goes from 1 to 0, the
|
||||
* RTC registers show the second which has precisely just started.
|
||||
* Let's hope other operating systems interpret the RTC the same way.
|
||||
*/
|
||||
/* read RTC exactly on falling edge of update flag */
|
||||
for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
|
||||
if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
|
||||
break;
|
||||
|
||||
for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
|
||||
if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
|
||||
break;
|
||||
|
||||
do { /* Isn't this overkill ? UIP above should guarantee consistency */
|
||||
sec = CMOS_READ(RTC_SECONDS);
|
||||
min = CMOS_READ(RTC_MINUTES);
|
||||
hour = CMOS_READ(RTC_HOURS);
|
||||
day = CMOS_READ(RTC_DAY_OF_MONTH);
|
||||
mon = CMOS_READ(RTC_MONTH);
|
||||
year = CMOS_READ(RTC_YEAR);
|
||||
} while (sec != CMOS_READ(RTC_SECONDS));
|
||||
|
||||
if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
|
||||
BCD_TO_BIN(sec);
|
||||
BCD_TO_BIN(min);
|
||||
BCD_TO_BIN(hour);
|
||||
BCD_TO_BIN(day);
|
||||
BCD_TO_BIN(mon);
|
||||
BCD_TO_BIN(year);
|
||||
}
|
||||
if ((year += 1900) < 1970)
|
||||
year += 100;
|
||||
return mktime(year, mon, day, hour, min, sec);
|
||||
}
|
||||
|
||||
static int set_isa_cmos_time(void)
|
||||
{
|
||||
int retval = 0;
|
||||
int real_seconds, real_minutes, cmos_minutes;
|
||||
unsigned char save_control, save_freq_select;
|
||||
unsigned long nowtime = xtime.tv_sec;
|
||||
|
||||
save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
|
||||
CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
|
||||
|
||||
save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
|
||||
CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
|
||||
|
||||
cmos_minutes = CMOS_READ(RTC_MINUTES);
|
||||
if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
|
||||
BCD_TO_BIN(cmos_minutes);
|
||||
|
||||
/*
|
||||
* since we're only adjusting minutes and seconds,
|
||||
* don't interfere with hour overflow. This avoids
|
||||
* messing with unknown time zones but requires your
|
||||
* RTC not to be off by more than 15 minutes
|
||||
*/
|
||||
real_seconds = nowtime % 60;
|
||||
real_minutes = nowtime / 60;
|
||||
if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
|
||||
real_minutes += 30; /* correct for half hour time zone */
|
||||
real_minutes %= 60;
|
||||
|
||||
if (abs(real_minutes - cmos_minutes) < 30) {
|
||||
if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
|
||||
BIN_TO_BCD(real_seconds);
|
||||
BIN_TO_BCD(real_minutes);
|
||||
}
|
||||
CMOS_WRITE(real_seconds,RTC_SECONDS);
|
||||
CMOS_WRITE(real_minutes,RTC_MINUTES);
|
||||
} else
|
||||
retval = -1;
|
||||
|
||||
/* The following flags have to be released exactly in this order,
|
||||
* otherwise the DS12887 (popular MC146818A clone with integrated
|
||||
* battery and quartz) will not reset the oscillator and will not
|
||||
* update precisely 500 ms later. You won't find this mentioned in
|
||||
* the Dallas Semiconductor data sheets, but who believes data
|
||||
* sheets anyway ... -- Markus Kuhn
|
||||
*/
|
||||
CMOS_WRITE(save_control, RTC_CONTROL);
|
||||
CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void __init isa_rtc_init(void)
|
||||
{
|
||||
if (machine_is_co285() ||
|
||||
machine_is_personal_server())
|
||||
/*
|
||||
* Add-in 21285s shouldn't access the RTC
|
||||
*/
|
||||
rtc_base = 0;
|
||||
else
|
||||
rtc_base = 0x70;
|
||||
|
||||
if (rtc_base) {
|
||||
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) {
|
||||
struct timespec tv;
|
||||
|
||||
/*
|
||||
* We have a RTC. Check the battery
|
||||
*/
|
||||
if ((reg_d & 0x80) == 0)
|
||||
printk(KERN_WARNING "RTC: *** warning: CMOS battery bad\n");
|
||||
|
||||
tv.tv_nsec = 0;
|
||||
tv.tv_sec = get_isa_cmos_time();
|
||||
do_settimeofday(&tv);
|
||||
set_rtc = set_isa_cmos_time;
|
||||
} else
|
||||
rtc_base = 0;
|
||||
}
|
||||
}
|
Ссылка в новой задаче
Block a user