Commit d14cb201 authored by Paul Mundt's avatar Paul Mundt Committed by Linus Torvalds

[PATCH] sh: SE73180 board support

This adds support for the SH73180 Solution Engine.
Signed-off-by: default avatarHiroshi DOYU <Hiroshi_DOYU@montavista.co.jp>
Signed-off-by: default avatarPaul Mundt <paul.mundt@nokia.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 6a65534b
#
# Makefile for the 73180 SolutionEngine specific parts of the kernel
#
obj-y := setup.o io.o irq.o
obj-$(CONFIG_HEARTBEAT) += led.o
/*
* arch/sh/boards/se/73180/io.c
*
* Copyright (C) 2003 YOSHII Takashi <yoshii-takashi@hitachi-ul.co.jp>
* Based on arch/sh/boards/se/7300/io.c
*
* I/O routine for SH-Mobile3 73180 SolutionEngine.
*
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <asm/mach/se73180.h>
#include <asm/io.h>
#define badio(fn, a) panic("bad i/o operation %s for %08lx.", #fn, a)
struct iop {
unsigned long start, end;
unsigned long base;
struct iop *(*check) (struct iop * p, unsigned long port);
unsigned char (*inb) (struct iop * p, unsigned long port);
unsigned short (*inw) (struct iop * p, unsigned long port);
void (*outb) (struct iop * p, unsigned char value, unsigned long port);
void (*outw) (struct iop * p, unsigned short value, unsigned long port);
};
struct iop *
simple_check(struct iop *p, unsigned long port)
{
if ((p->start <= port) && (port <= p->end))
return p;
else
badio(check, port);
}
struct iop *
ide_check(struct iop *p, unsigned long port)
{
if (((0x1f0 <= port) && (port <= 0x1f7)) || (port == 0x3f7))
return p;
return NULL;
}
unsigned char
simple_inb(struct iop *p, unsigned long port)
{
return *(unsigned char *) (p->base + port);
}
unsigned short
simple_inw(struct iop *p, unsigned long port)
{
return *(unsigned short *) (p->base + port);
}
void
simple_outb(struct iop *p, unsigned char value, unsigned long port)
{
*(unsigned char *) (p->base + port) = value;
}
void
simple_outw(struct iop *p, unsigned short value, unsigned long port)
{
*(unsigned short *) (p->base + port) = value;
}
unsigned char
pcc_inb(struct iop *p, unsigned long port)
{
unsigned long addr = p->base + port + 0x40000;
unsigned long v;
if (port & 1)
addr += 0x00400000;
v = *(volatile unsigned char *) addr;
return v;
}
void
pcc_outb(struct iop *p, unsigned char value, unsigned long port)
{
unsigned long addr = p->base + port + 0x40000;
if (port & 1)
addr += 0x00400000;
*(volatile unsigned char *) addr = value;
}
unsigned char
bad_inb(struct iop *p, unsigned long port)
{
badio(inb, port);
}
void
bad_outb(struct iop *p, unsigned char value, unsigned long port)
{
badio(inw, port);
}
/* MSTLANEX01 LAN at 0xb400:0000 */
static struct iop laniop = {
.start = 0x300,
.end = 0x30f,
.base = 0xb4000000,
.check = simple_check,
.inb = simple_inb,
.inw = simple_inw,
.outb = simple_outb,
.outw = simple_outw,
};
/* NE2000 pc card NIC */
static struct iop neiop = {
.start = 0x280,
.end = 0x29f,
.base = 0xb0600000 + 0x80, /* soft 0x280 -> hard 0x300 */
.check = simple_check,
.inb = pcc_inb,
.inw = simple_inw,
.outb = pcc_outb,
.outw = simple_outw,
};
/* CF in CF slot */
static struct iop cfiop = {
.base = 0xb0600000,
.check = ide_check,
.inb = pcc_inb,
.inw = simple_inw,
.outb = pcc_outb,
.outw = simple_outw,
};
static __inline__ struct iop *
port2iop(unsigned long port)
{
if (0) ;
#if defined(CONFIG_SMC91111)
else if (laniop.check(&laniop, port))
return &laniop;
#endif
#if defined(CONFIG_NE2000)
else if (neiop.check(&neiop, port))
return &neiop;
#endif
#if defined(CONFIG_IDE)
else if (cfiop.check(&cfiop, port))
return &cfiop;
#endif
else
return &neiop; /* fallback */
}
static inline void
delay(void)
{
ctrl_inw(0xac000000);
ctrl_inw(0xac000000);
}
unsigned char
sh73180se_inb(unsigned long port)
{
struct iop *p = port2iop(port);
return (p->inb) (p, port);
}
unsigned char
sh73180se_inb_p(unsigned long port)
{
unsigned char v = sh73180se_inb(port);
delay();
return v;
}
unsigned short
sh73180se_inw(unsigned long port)
{
struct iop *p = port2iop(port);
return (p->inw) (p, port);
}
unsigned int
sh73180se_inl(unsigned long port)
{
badio(inl, port);
}
void
sh73180se_outb(unsigned char value, unsigned long port)
{
struct iop *p = port2iop(port);
(p->outb) (p, value, port);
}
void
sh73180se_outb_p(unsigned char value, unsigned long port)
{
sh73180se_outb(value, port);
delay();
}
void
sh73180se_outw(unsigned short value, unsigned long port)
{
struct iop *p = port2iop(port);
(p->outw) (p, value, port);
}
void
sh73180se_outl(unsigned int value, unsigned long port)
{
badio(outl, port);
}
void
sh73180se_insb(unsigned long port, void *addr, unsigned long count)
{
unsigned char *a = addr;
struct iop *p = port2iop(port);
while (count--)
*a++ = (p->inb) (p, port);
}
void
sh73180se_insw(unsigned long port, void *addr, unsigned long count)
{
unsigned short *a = addr;
struct iop *p = port2iop(port);
while (count--)
*a++ = (p->inw) (p, port);
}
void
sh73180se_insl(unsigned long port, void *addr, unsigned long count)
{
badio(insl, port);
}
void
sh73180se_outsb(unsigned long port, const void *addr, unsigned long count)
{
unsigned char *a = (unsigned char *) addr;
struct iop *p = port2iop(port);
while (count--)
(p->outb) (p, *a++, port);
}
void
sh73180se_outsw(unsigned long port, const void *addr, unsigned long count)
{
unsigned short *a = (unsigned short *) addr;
struct iop *p = port2iop(port);
while (count--)
(p->outw) (p, *a++, port);
}
void
sh73180se_outsl(unsigned long port, const void *addr, unsigned long count)
{
badio(outsw, port);
}
/*
* arch/sh/boards/se/73180/irq.c
*
* Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
* Based on arch/sh/boards/se/7300/irq.c
*
* Modified for SH-Mobile SolutionEngine 73180 Support
* by YOSHII Takashi <yoshii-takashi@hitachi-ul.co.jp>
*
*
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/mach/se73180.h>
static int
intreq2irq(int i)
{
if (i == 5)
return 10;
return 32 + 7 - i;
}
static int
irq2intreq(int irq)
{
if (irq == 10)
return 5;
return 7 - (irq - 32);
}
static void
disable_intreq_irq(unsigned int irq)
{
ctrl_outb(1 << (7 - irq2intreq(irq)), INTMSK0);
}
static void
enable_intreq_irq(unsigned int irq)
{
ctrl_outb(1 << (7 - irq2intreq(irq)), INTMSKCLR0);
}
static void
mask_and_ack_intreq_irq(unsigned int irq)
{
disable_intreq_irq(irq);
}
static unsigned int
startup_intreq_irq(unsigned int irq)
{
enable_intreq_irq(irq);
return 0;
}
static void
shutdown_intreq_irq(unsigned int irq)
{
disable_intreq_irq(irq);
}
static void
end_intreq_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
enable_intreq_irq(irq);
}
static struct hw_interrupt_type intreq_irq_type = {
.typename = "intreq",
.startup = startup_intreq_irq,
.shutdown = shutdown_intreq_irq,
.enable = enable_intreq_irq,
.disable = disable_intreq_irq,
.ack = mask_and_ack_intreq_irq,
.end = end_intreq_irq
};
void
make_intreq_irq(unsigned int irq)
{
disable_irq_nosync(irq);
irq_desc[irq].handler = &intreq_irq_type;
disable_intreq_irq(irq);
}
int
shmse_irq_demux(int irq)
{
if (irq == IRQ5_IRQ)
return 10;
return irq;
}
/*
* Initialize IRQ setting
*/
void __init
init_73180se_IRQ(void)
{
make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY);
ctrl_outw(0x2000, 0xb03fffec); /* mrshpc irq enable */
ctrl_outw(0x2000, 0xb07fffec); /* mrshpc irq enable */
ctrl_outl(3 << ((7 - 5) * 4), INTC_INTPRI0); /* irq5 pri=3 */
ctrl_outw(2 << ((7 - 5) * 2), INTC_ICR1); /* low-level irq */
make_intreq_irq(10);
make_ipr_irq(VPU_IRQ, VPU_IPR_ADDR, VPU_IPR_POS, 8);
ctrl_outb(0x0f, INTC_IMCR5); /* enable SCIF IRQ */
make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
make_ipr_irq(DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY);
make_ipr_irq(IIC0_ALI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY);
make_ipr_irq(IIC0_TACKI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS,
IIC0_PRIORITY);
make_ipr_irq(IIC0_WAITI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS,
IIC0_PRIORITY);
make_ipr_irq(IIC0_DTEI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY);
make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY);
make_ipr_irq(SIU_IRQ, SIU_IPR_ADDR, SIU_IPR_POS, SIU_PRIORITY);
/* VIO interrupt */
make_ipr_irq(CEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
make_ipr_irq(BEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
make_ipr_irq(VEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
make_ipr_irq(LCDC_IRQ, LCDC_IPR_ADDR, LCDC_IPR_POS, LCDC_PRIORITY);
ctrl_outw(0x2000, PA_MRSHPC + 0x0c); /* mrshpc irq enable */
}
/*
* arch/sh/boards/se/73180/led.c
*
* Derived from arch/sh/boards/se/770x/led.c
*
* Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
*
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
*
* This file contains Solution Engine specific LED code.
*/
#include <linux/config.h>
#include <linux/sched.h>
#include <asm/mach/se73180.h>
static void
mach_led(int position, int value)
{
volatile unsigned short *p = (volatile unsigned short *) PA_LED;
if (value) {
*p |= (1 << LED_SHIFT);
} else {
*p &= ~(1 << LED_SHIFT);
}
}
/* Cycle the LED's in the clasic Knightrider/Sun pattern */
void
heartbeat_73180se(void)
{
static unsigned int cnt = 0, period = 0;
volatile unsigned short *p = (volatile unsigned short *) PA_LED;
static unsigned bit = 0, up = 1;
cnt += 1;
if (cnt < period) {
return;
}
cnt = 0;
/* Go through the points (roughly!):
* f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110
*/
period = 110 - ((300 << FSHIFT) / ((avenrun[0] / 5) + (3 << FSHIFT)));
if (up) {
if (bit == 7) {
bit--;
up = 0;
} else {
bit++;
}
} else {
if (bit == 0) {
bit++;
up = 1;
} else {
bit--;
}
}
*p = 1 << (bit + LED_SHIFT);
}
/*
* arch/sh/boards/se/73180/setup.c
*
* Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
* Based on arch/sh/setup_shmse.c
*
* Modified for 73180 SolutionEngine
* by YOSHII Takashi <yoshii-takashi@hitachi-ul.co.jp>
*
*/
#include <linux/config.h>
#include <linux/init.h>
#include <asm/machvec.h>
#include <asm/machvec_init.h>
#include <asm/mach/io.h>
void heartbeat_73180se(void);
void init_73180se_IRQ(void);
const char *
get_system_type(void)
{
return "SolutionEngine 73180";
}
/*
* The Machine Vector
*/
struct sh_machine_vector mv_73180se __initmv = {
.mv_nr_irqs = 108,
.mv_inb = sh73180se_inb,
.mv_inw = sh73180se_inw,
.mv_inl = sh73180se_inl,
.mv_outb = sh73180se_outb,
.mv_outw = sh73180se_outw,
.mv_outl = sh73180se_outl,
.mv_inb_p = sh73180se_inb_p,
.mv_inw_p = sh73180se_inw,
.mv_inl_p = sh73180se_inl,
.mv_outb_p = sh73180se_outb_p,
.mv_outw_p = sh73180se_outw,
.mv_outl_p = sh73180se_outl,
.mv_insb = sh73180se_insb,
.mv_insw = sh73180se_insw,
.mv_insl = sh73180se_insl,
.mv_outsb = sh73180se_outsb,
.mv_outsw = sh73180se_outsw,
.mv_outsl = sh73180se_outsl,
.mv_init_irq = init_73180se_IRQ,
#ifdef CONFIG_HEARTBEAT
.mv_heartbeat = heartbeat_73180se,
#endif
};
ALIAS_MV(73180se)
/*
* Initialize the board
*/
void __init
platform_setup(void)
{
}
/*
* include/asm-sh/se73180/io.h
*
* Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
* Based on include/asm-sh/se7300/io.h
*
* IO functions for SH-Mobile3(SH73180) SolutionEngine
*
*/
#ifndef _ASM_SH_IO_73180SE_H
#define _ASM_SH_IO_73180SE_H
extern unsigned char sh73180se_inb(unsigned long port);
extern unsigned short sh73180se_inw(unsigned long port);
extern unsigned int sh73180se_inl(unsigned long port);
extern void sh73180se_outb(unsigned char value, unsigned long port);
extern void sh73180se_outw(unsigned short value, unsigned long port);
extern void sh73180se_outl(unsigned int value, unsigned long port);
extern unsigned char sh73180se_inb_p(unsigned long port);
extern void sh73180se_outb_p(unsigned char value, unsigned long port);
extern void sh73180se_insb(unsigned long port, void *addr, unsigned long count);
extern void sh73180se_insw(unsigned long port, void *addr, unsigned long count);
extern void sh73180se_insl(unsigned long port, void *addr, unsigned long count);
extern void sh73180se_outsb(unsigned long port, const void *addr, unsigned long count);
extern void sh73180se_outsw(unsigned long port, const void *addr, unsigned long count);
extern void sh73180se_outsl(unsigned long port, const void *addr, unsigned long count);
#endif /* _ASM_SH_IO_73180SE_H */
#ifndef __ASM_SH_HITACHI_SE73180_H
#define __ASM_SH_HITACHI_SE73180_H
/*
* include/asm-sh/se/se73180.h
*
* Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
*
* SH-Mobile SolutionEngine 73180 support
*/
/* Box specific addresses. */
/* Area 0 */
#define PA_ROM 0x00000000 /* EPROM */
#define PA_ROM_SIZE 0x00400000 /* EPROM size 4M byte(Actually 2MB) */
#define PA_FROM 0x00400000 /* Flash ROM */
#define PA_FROM_SIZE 0x00400000 /* Flash size 4M byte */
#define PA_SRAM 0x00800000 /* SRAM */
#define PA_FROM_SIZE 0x00400000 /* SRAM size 4M byte */
/* Area 1 */
#define PA_EXT1 0x04000000
#define PA_EXT1_SIZE 0x04000000
/* Area 2 */
#define PA_EXT2 0x08000000
#define PA_EXT2_SIZE 0x04000000
/* Area 3 */
#define PA_SDRAM 0x0c000000
#define PA_SDRAM_SIZE 0x04000000
/* Area 4 */
#define PA_PCIC 0x10000000 /* MR-SHPC-01 PCMCIA */
#define PA_MRSHPC 0xb03fffe0 /* MR-SHPC-01 PCMCIA controller */
#define PA_MRSHPC_MW1 0xb0400000 /* MR-SHPC-01 memory window base */
#define PA_MRSHPC_MW2 0xb0500000 /* MR-SHPC-01 attribute window base */
#define PA_MRSHPC_IO 0xb0600000 /* MR-SHPC-01 I/O window base */
#define MRSHPC_OPTION (PA_MRSHPC + 6)
#define MRSHPC_CSR (PA_MRSHPC + 8)
#define MRSHPC_ISR (PA_MRSHPC + 10)
#define MRSHPC_ICR (PA_MRSHPC + 12)
#define MRSHPC_CPWCR (PA_MRSHPC + 14)
#define MRSHPC_MW0CR1 (PA_MRSHPC + 16)
#define MRSHPC_MW1CR1 (PA_MRSHPC + 18)
#define MRSHPC_IOWCR1 (PA_MRSHPC + 20)
#define MRSHPC_MW0CR2 (PA_MRSHPC + 22)
#define MRSHPC_MW1CR2 (PA_MRSHPC + 24)
#define MRSHPC_IOWCR2 (PA_MRSHPC + 26)
#define MRSHPC_CDCR (PA_MRSHPC + 28)
#define MRSHPC_PCIC_INFO (PA_MRSHPC + 30)
#define PA_LED 0xb0C00000 /* LED */
#define LED_SHIFT 0
#define PA_DIPSW 0xb0900000 /* Dip switch 31 */
#define PA_EPLD_MODESET 0xb0a00000 /* FPGA Mode set register */
#define PA_EPLD_ST1 0xb0a80000 /* FPGA Interrupt status register1 */
#define PA_EPLD_ST2 0xb0ac0000 /* FPGA Interrupt status register2 */
/* Area 5 */
#define PA_EXT5 0x14000000
#define PA_EXT5_SIZE 0x04000000
/* Area 6 */
#define PA_LCD1 0xb8000000
#define PA_LCD2 0xb8800000
#endif /* __ASM_SH_HITACHI_SE73180_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment