sh: Titan board support.

Add support for the titan board.

Signed-off-by: Jamie Lenehan <lenehan@twibble.org>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
Jamie Lenehan 2006-09-27 15:05:39 +09:00 committed by Paul Mundt
parent b7e108ee63
commit a09749dd86
10 changed files with 1764 additions and 12 deletions

View File

@ -106,6 +106,7 @@ machdir-$(CONFIG_SH_7751_SYSTEMH) := renesas/systemh
machdir-$(CONFIG_SH_EDOSK7705) := renesas/edosk7705
machdir-$(CONFIG_SH_SH4202_MICRODEV) := superh/microdev
machdir-$(CONFIG_SH_LANDISK) := landisk
machdir-$(CONFIG_SH_TITAN) := titan
machdir-$(CONFIG_SH_UNKNOWN) := unknown
incdir-y := $(notdir $(machdir-y))

View File

@ -0,0 +1,5 @@
#
# Makefile for the Nimble Microsystems TITAN specific parts of the kernel
#
obj-y := setup.o io.o

156
arch/sh/boards/titan/io.c Normal file
View File

@ -0,0 +1,156 @@
/*
* I/O routines for Titan
*/
#include <linux/pci.h>
#include <asm/machvec.h>
#include <asm/addrspace.h>
#include <asm/titan.h>
#include <asm/io.h>
#include "../../drivers/pci/pci-sh7751.h"
#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR)
#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR)
#define PCI_IO_AREA SH7751_PCI_IO_BASE
#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE
#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
#if defined(CONFIG_PCI)
#define CHECK_SH7751_PCIIO(port) \
((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
#define CHECK_SH7751_PCIMEMIO(port) \
((port >= PCIBIOS_MIN_MEM) && (port < (PCIBIOS_MIN_MEM + SH7751_PCI_MEM_SIZE)))
#else
#define CHECK_SH7751_PCIIO(port) (0)
#endif
static inline void delay(void)
{
ctrl_inw(0xa0000000);
}
static inline volatile u16 *port2adr(unsigned int port)
{
maybebadio((unsigned long)port);
return (volatile u16*)port;
}
u8 titan_inb(unsigned long port)
{
if (PXSEG(port))
return ctrl_inb(port);
else if (CHECK_SH7751_PCIIO(port))
return ctrl_inb(PCI_IOMAP(port));
return ctrl_inw(port2adr(port)) & 0xff;
}
u8 titan_inb_p(unsigned long port)
{
u8 v;
if (PXSEG(port))
v = ctrl_inb(port);
else if (CHECK_SH7751_PCIIO(port))
v = ctrl_inb(PCI_IOMAP(port));
else
v = ctrl_inw(port2adr(port)) & 0xff;
delay();
return v;
}
u16 titan_inw(unsigned long port)
{
if (PXSEG(port))
return ctrl_inw(port);
else if (CHECK_SH7751_PCIIO(port))
return ctrl_inw(PCI_IOMAP(port));
else if (port >= 0x2000)
return ctrl_inw(port2adr(port));
else
maybebadio(port);
return 0;
}
u32 titan_inl(unsigned long port)
{
if (PXSEG(port))
return ctrl_inl(port);
else if (CHECK_SH7751_PCIIO(port))
return ctrl_inl(PCI_IOMAP(port));
else if (port >= 0x2000)
return ctrl_inw(port2adr(port));
else
maybebadio(port);
return 0;
}
void titan_outb(u8 value, unsigned long port)
{
if (PXSEG(port))
ctrl_outb(value, port);
else if (CHECK_SH7751_PCIIO(port))
ctrl_outb(value, PCI_IOMAP(port));
else
ctrl_outw(value, port2adr(port));
}
void titan_outb_p(u8 value, unsigned long port)
{
if (PXSEG(port))
ctrl_outb(value, port);
else if (CHECK_SH7751_PCIIO(port))
ctrl_outb(value, PCI_IOMAP(port));
else
ctrl_outw(value, port2adr(port));
delay();
}
void titan_outw(u16 value, unsigned long port)
{
if (PXSEG(port))
ctrl_outw(value, port);
else if (CHECK_SH7751_PCIIO(port))
ctrl_outw(value, PCI_IOMAP(port));
else if (port >= 0x2000)
ctrl_outw(value, port2adr(port));
else
maybebadio(port);
}
void titan_outl(u32 value, unsigned long port)
{
if (PXSEG(port))
ctrl_outl(value, port);
else if (CHECK_SH7751_PCIIO(port))
ctrl_outl(value, PCI_IOMAP(port));
else
maybebadio(port);
}
void titan_insl(unsigned long port, void *dst, unsigned long count)
{
maybebadio(port);
}
void titan_outsl(unsigned long port, const void *src, unsigned long count)
{
maybebadio(port);
}
void *titan_ioremap(unsigned long offset, unsigned long size) {
if (CHECK_SH7751_PCIIO(offset) || CHECK_SH7751_PCIMEMIO(offset))
return (void *)offset;
}
void __iomem *titan_ioport_map(unsigned long port, unsigned int size)
{
if (PXSEG(port))
return (void __iomem *)port;
else if (CHECK_SH7751_PCIIO(port))
return (void __iomem *)PCI_IOMAP(port);
return (void __iomem *)port2adr(port);
}
EXPORT_SYMBOL(titan_ioremap);

View File

@ -0,0 +1,60 @@
/*
* Setup for Titan
*/
#include <linux/init.h>
#include <asm/irq.h>
#include <asm/titan.h>
#include <asm/io.h>
extern void __init pcibios_init_platform(void);
static void __init init_titan_irq(void)
{
/* enable individual interrupt mode for externals */
ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
make_ipr_irq( TITAN_IRQ_WAN, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY); /* PCIRQ0 */
make_ipr_irq( TITAN_IRQ_LAN, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY); /* PCIRQ1 */
make_ipr_irq( TITAN_IRQ_MPCIA, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY); /* PCIRQ2 */
make_ipr_irq( TITAN_IRQ_USB, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY); /* PCIRQ3 */
}
const char *get_system_type(void)
{
return "Titan";
}
int __init platform_setup(void)
{
printk("%s Platform Setup\n", get_system_type());
return 0;
}
struct sh_machine_vector mv_titan __initmv = {
.mv_nr_irqs = NR_IRQS,
.mv_inb = titan_inb,
.mv_inw = titan_inw,
.mv_inl = titan_inl,
.mv_outb = titan_outb,
.mv_outw = titan_outw,
.mv_outl = titan_outl,
.mv_inb_p = titan_inb_p,
.mv_inw_p = titan_inw,
.mv_inl_p = titan_inl,
.mv_outb_p = titan_outb_p,
.mv_outw_p = titan_outw,
.mv_outl_p = titan_outl,
.mv_insl = titan_insl,
.mv_outsl = titan_outsl,
.mv_ioremap = titan_ioremap,
.mv_ioport_map = titan_ioport_map,
.mv_init_irq = init_titan_irq,
.mv_init_pci = pcibios_init_platform,
};
ALIAS_MV(titan)

File diff suppressed because it is too large Load Diff

View File

@ -14,3 +14,4 @@ obj-$(CONFIG_SH_SECUREEDGE5410) += ops-snapgear.o
obj-$(CONFIG_SH_BIGSUR) += ops-bigsur.o
obj-$(CONFIG_SH_RTS7751R2D) += ops-rts7751r2d.o fixups-rts7751r2d.o
obj-$(CONFIG_SH_SH03) += ops-sh03.o fixups-sh03.o
obj-$(CONFIG_SH_TITAN) += ops-titan.o

View File

@ -0,0 +1,84 @@
/*
* arch/sh/drivers/pci/ops-titan.c
*
* Ported to new API by Paul Mundt <lethal@linux-sh.org>
*
* Modified from ops-snapgear.c written by David McCullough
* Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
*
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
*
* PCI initialization for the Titan boards
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <asm/titan.h>
#include "pci-sh7751.h"
int __init pcibios_map_platform_irq(u8 slot, u8 pin)
{
int irq = -1;
switch (slot) {
case 0: irq = TITAN_IRQ_WAN; break; /* eth0 (WAN) */
case 1: irq = TITAN_IRQ_LAN; break; /* eth1 (LAN) */
case 2: irq = TITAN_IRQ_MPCIA; break; /* mPCI A */
case 3: irq = TITAN_IRQ_MPCIB; break; /* mPCI B */
case 4: irq = TITAN_IRQ_USB; break; /* USB */
default:
printk(KERN_INFO "PCI: Bad IRQ mapping request for slot %d\n", slot);
return -1;
}
printk("PCI: Mapping TITAN IRQ for slot %d, pin %c to irq %d\n",
slot, pin - 1 + 'A', irq);
return irq;
}
static struct resource sh7751_io_resource = {
.name = "SH7751_IO",
.start = SH7751_PCI_IO_BASE,
.end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
.flags = IORESOURCE_IO
};
static struct resource sh7751_mem_resource = {
.name = "SH7751_mem",
.start = SH7751_PCI_MEMORY_BASE,
.end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
.flags = IORESOURCE_MEM
};
extern struct pci_ops sh7751_pci_ops;
struct pci_channel board_pci_channels[] = {
{ &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
{ NULL, NULL, NULL, 0, 0 },
};
EXPORT_SYMBOL(board_pci_channels);
static struct sh7751_pci_address_map sh7751_pci_map = {
.window0 = {
.base = SH7751_CS2_BASE_ADDR,
.size = SH7751_MEM_REGION_SIZE*2, /* cs2 and cs3 */
},
.window1 = {
.base = SH7751_CS2_BASE_ADDR,
.size = SH7751_MEM_REGION_SIZE*2,
},
.flags = SH7751_PCIC_NO_RESET,
};
int __init pcibios_init_platform(void)
{
return sh7751_pcic_init(&sh7751_pci_map);
}

View File

@ -1,21 +1,25 @@
/* arch/sh/kernel/pci.c
* $Id: pci.c,v 1.1 2003/08/24 19:15:45 lethal Exp $
/*
* arch/sh/drivers/pci/pci.c
*
* Copyright (c) 2002 M. R. Brown <mrbrown@linux-sh.org>
*
*
* Copyright (c) 2004, 2005 Paul Mundt <lethal@linux-sh.org>
*
* These functions are collected here to reduce duplication of common
* code amongst the many platform-specific PCI support code files.
*
*
* These routines require the following board-specific routines:
* void pcibios_fixup_irqs();
*
* See include/asm-sh/pci.h for more information.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <asm/io.h>
static int __init pcibios_init(void)
{
@ -26,9 +30,8 @@ static int __init pcibios_init(void)
#ifdef CONFIG_PCI_AUTO
/* assign resources */
busno = 0;
for (p = board_pci_channels; p->pci_ops != NULL; p++) {
for (p = board_pci_channels; p->pci_ops != NULL; p++)
busno = pciauto_assign_resources(busno, p) + 1;
}
#endif
/* scan the buses */
@ -61,13 +64,17 @@ pcibios_update_resource(struct pci_dev *dev, struct resource *root,
new |= PCI_ROM_ADDRESS_ENABLE;
reg = dev->rom_base_reg;
} else {
/* Somebody might have asked allocation of a non-standard resource */
/*
* Somebody might have asked allocation of a non-standard
* resource
*/
return;
}
pci_write_config_dword(dev, reg, new);
pci_read_config_dword(dev, reg, &check);
if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ?
PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
printk(KERN_ERR "PCI: Error while updating region "
"%s/%d (%08x != %08x)\n", pci_name(dev), resource,
new, check);
@ -145,7 +152,8 @@ void pcibios_set_master(struct pci_dev *dev)
lat = pcibios_max_latency;
else
return;
printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat);
printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n",
pci_name(dev), lat);
pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
}
@ -153,3 +161,29 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
{
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
}
void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
{
unsigned long start = pci_resource_start(dev, bar);
unsigned long len = pci_resource_len(dev, bar);
unsigned long flags = pci_resource_flags(dev, bar);
if (!len || !start)
return NULL;
if (maxlen && len > maxlen)
len = maxlen;
if (flags & IORESOURCE_IO)
return ioport_map(start, len);
if (flags & IORESOURCE_MEM)
return ioremap(start, len);
return NULL;
}
void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
{
iounmap(addr);
}
EXPORT_SYMBOL(pci_iomap);
EXPORT_SYMBOL(pci_iounmap);

View File

@ -26,3 +26,4 @@ EDOSK7705 SH_EDOSK7705
SH4202_MICRODEV SH_SH4202_MICRODEV
SH03 SH_SH03
LANDISK SH_LANDISK
TITAN SH_TITAN

43
include/asm-sh/titan.h Normal file
View File

@ -0,0 +1,43 @@
/*
* Platform defintions for Titan
*/
#ifndef _ASM_SH_TITAN_TITAN_H
#define _ASM_SH_TITAN_TITAN_H
#define __IO_PREFIX titan
#include <asm/io_generic.h>
/* IRQ assignments */
#define TITAN_IRQ_WAN 2 /* eth0 (WAN) */
#define TITAN_IRQ_LAN 5 /* eth1 (LAN) */
#define TITAN_IRQ_MPCIA 8 /* mPCI A */
#define TITAN_IRQ_MPCIB 11 /* mPCI B */
#define TITAN_IRQ_USB 11 /* USB */
/*
* The external interrupt lines, these take up ints 0 - 15 inclusive
* depending on the priority for the interrupt. In fact the priority
* is the interrupt :-)
*/
#define IRL0_IRQ 0
#define IRL0_IPR_ADDR INTC_IPRD
#define IRL0_IPR_POS 3
#define IRL0_PRIORITY 8
#define IRL1_IRQ 1
#define IRL1_IPR_ADDR INTC_IPRD
#define IRL1_IPR_POS 2
#define IRL1_PRIORITY 8
#define IRL2_IRQ 2
#define IRL2_IPR_ADDR INTC_IPRD
#define IRL2_IPR_POS 1
#define IRL2_PRIORITY 8
#define IRL3_IRQ 3
#define IRL3_IPR_ADDR INTC_IPRD
#define IRL3_IPR_POS 0
#define IRL3_PRIORITY 8
#endif