Commit f36af3fd authored by Yoshinori Sato's avatar Yoshinori Sato Committed by Paul Mundt

sh: Add support for Solution Engine 7206 and 7619 boards.

This adds support for the Solution Engine 7206 and 7619.
Signed-off-by: default avatarYoshinori Sato <ysato@users.sourceforge.jp>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent b229632a
#
# Makefile for the 7206 SolutionEngine specific parts of the kernel
#
obj-y := setup.o io.o irq.o
obj-$(CONFIG_HEARTBEAT) += led.o
/* $Id: io.c,v 1.5 2004/02/22 23:08:43 kkojima Exp $
*
* linux/arch/sh/boards/se/7206/io.c
*
* Copyright (C) 2006 Yoshinori Sato
*
* I/O routine for Hitachi 7206 SolutionEngine.
*
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <asm/io.h>
#include <asm/se7206.h>
static inline void delay(void)
{
ctrl_inw(0x20000000); /* P2 ROM Area */
}
/* MS7750 requires special versions of in*, out* routines, since
PC-like io ports are located at upper half byte of 16-bit word which
can be accessed only with 16-bit wide. */
static inline volatile __u16 *
port2adr(unsigned int port)
{
if (port >= 0x2000)
return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
else if (port >= 0x300 || port < 0x310)
return (volatile __u16 *) (PA_SMSC + (port - 0x300));
}
unsigned char se7206_inb(unsigned long port)
{
return (*port2adr(port))&0xff;
}
unsigned char se7206_inb_p(unsigned long port)
{
unsigned long v;
v = (*port2adr(port))&0xff;
delay();
return v;
}
unsigned short se7206_inw(unsigned long port)
{
return *port2adr(port);;
}
unsigned int se7206_inl(unsigned long port)
{
maybebadio(port);
return 0;
}
void se7206_outb(unsigned char value, unsigned long port)
{
*(port2adr(port)) = value;
}
void se7206_outb_p(unsigned char value, unsigned long port)
{
*(port2adr(port)) = value;
delay();
}
void se7206_outw(unsigned short value, unsigned long port)
{
*port2adr(port) = value;
}
void se7206_outl(unsigned int value, unsigned long port)
{
maybebadio(port);
}
void se7206_insb(unsigned long port, void *addr, unsigned long count)
{
volatile __u16 *p = port2adr(port);
__u8 *ap = addr;
while (count--)
*ap++ = *p;
}
void se7206_insw(unsigned long port, void *addr, unsigned long count)
{
volatile __u16 *p = port2adr(port);
__u16 *ap = addr;
while (count--)
*ap++ = *p;
}
void se7206_insl(unsigned long port, void *addr, unsigned long count)
{
maybebadio(port);
}
void se7206_outsb(unsigned long port, const void *addr, unsigned long count)
{
volatile __u16 *p = port2adr(port);
const __u8 *ap = addr;
while (count--)
*p = *ap++;
}
void se7206_outsw(unsigned long port, const void *addr, unsigned long count)
{
volatile __u16 *p = port2adr(port);
const __u16 *ap = addr;
while (count--)
*p = *ap++;
}
void se7206_outsl(unsigned long port, const void *addr, unsigned long count)
{
maybebadio(port);
}
/*
* linux/arch/sh/boards/se/7206/irq.c
*
* Copyright (C) 2005,2006 Yoshinori Sato
*
* Hitachi SolutionEngine Support.
*
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/se7206.h>
#define INTSTS0 0x31800000
#define INTSTS1 0x31800002
#define INTMSK0 0x31800004
#define INTMSK1 0x31800006
#define INTSEL 0x31800008
/* shutdown is same as "disable" */
#define shutdown_se7206_irq disable_se7206_irq
static void disable_se7206_irq(unsigned int irq)
{
unsigned short val;
unsigned short mask = 0xffff ^ (0x0f << 4 * (3 - (IRQ0_IRQ - irq)));
unsigned short msk0,msk1;
/* Set the priority in IPR to 0 */
val = ctrl_inw(INTC_IPR01);
val &= mask;
ctrl_outw(val, INTC_IPR01);
/* FPGA mask set */
msk0 = ctrl_inw(INTMSK0);
msk1 = ctrl_inw(INTMSK1);
switch (irq) {
case IRQ0_IRQ:
msk0 |= 0x0010;
break;
case IRQ1_IRQ:
msk0 |= 0x000f;
break;
case IRQ2_IRQ:
msk0 |= 0x0f00;
msk1 |= 0x00ff;
break;
}
ctrl_outw(msk0, INTMSK0);
ctrl_outw(msk1, INTMSK1);
}
static void enable_se7206_irq(unsigned int irq)
{
unsigned short val;
unsigned short value = (0x0001 << 4 * (3 - (IRQ0_IRQ - irq)));
unsigned short msk0,msk1;
/* Set priority in IPR back to original value */
val = ctrl_inw(INTC_IPR01);
val |= value;
ctrl_outw(val, INTC_IPR01);
/* FPGA mask reset */
msk0 = ctrl_inw(INTMSK0);
msk1 = ctrl_inw(INTMSK1);
switch (irq) {
case IRQ0_IRQ:
msk0 &= ~0x0010;
break;
case IRQ1_IRQ:
msk0 &= ~0x000f;
break;
case IRQ2_IRQ:
msk0 &= ~0x0f00;
msk1 &= ~0x00ff;
break;
}
ctrl_outw(msk0, INTMSK0);
ctrl_outw(msk1, INTMSK1);
}
static unsigned int startup_se7206_irq(unsigned int irq)
{
enable_se7206_irq(irq);
return 0; /* never anything pending */
}
static void ack_se7206_irq(unsigned int irq)
{
disable_se7206_irq(irq);
}
static void end_se7206_irq(unsigned int irq)
{
unsigned short sts0,sts1;
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
enable_se7206_irq(irq);
/* FPGA isr clear */
sts0 = ctrl_inw(INTSTS0);
sts1 = ctrl_inw(INTSTS1);
switch (irq) {
case IRQ0_IRQ:
sts0 &= ~0x0010;
break;
case IRQ1_IRQ:
sts0 &= ~0x000f;
break;
case IRQ2_IRQ:
sts0 &= ~0x0f00;
sts1 &= ~0x00ff;
break;
}
ctrl_outw(sts0, INTSTS0);
ctrl_outw(sts1, INTSTS1);
}
static struct hw_interrupt_type se7206_irq_type = {
.typename = "SE7206 FPGA-IRQ",
.startup = startup_se7206_irq,
.shutdown = shutdown_se7206_irq,
.enable = enable_se7206_irq,
.disable = disable_se7206_irq,
.ack = ack_se7206_irq,
.end = end_se7206_irq,
};
static void make_se7206_irq(unsigned int irq)
{
disable_irq_nosync(irq);
irq_desc[irq].handler = &se7206_irq_type;
disable_se7206_irq(irq);
}
/*
* Initialize IRQ setting
*/
void __init init_se7206_IRQ(void)
{
make_se7206_irq(IRQ0_IRQ); /* SMC91C111 */
make_se7206_irq(IRQ1_IRQ); /* ATA */
make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */
ctrl_outw(inw(INTC_ICR1) | 0x000b ,INTC_ICR1 ) ; /* ICR1 */
/* FPGA System register setup*/
ctrl_outw(0x0000,INTSTS0); /* Clear INTSTS0 */
ctrl_outw(0x0000,INTSTS1); /* Clear INTSTS1 */
/* IRQ0=LAN, IRQ1=ATA, IRQ3=SLT,PCM */
ctrl_outw(0x0001,INTSEL);
}
int se7206_irq_demux(int irq)
{
return irq;
}
/*
* linux/arch/sh/kernel/led_se.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 <asm/se7206.h>
#ifdef CONFIG_HEARTBEAT
#include <linux/sched.h>
/* Cycle the LED's in the clasic Knightrider/Sun pattern */
void heartbeat_se(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+8);
}
#endif /* CONFIG_HEARTBEAT */
/*
*
* linux/arch/sh/boards/se/7206/setup.c
*
* Copyright (C) 2006 Yoshinori Sato
*
* Hitachi 7206 SolutionEngine Support.
*
*/
#include <linux/init.h>
#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/se7206.h>
#include <asm/machvec.h>
static struct resource smc91x_resources[] = {
[0] = {
.start = 0x300,
.end = 0x300 + 0x020 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 64,
.end = 64,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device smc91x_device = {
.name = "smc91x",
.id = -1,
.num_resources = ARRAY_SIZE(smc91x_resources),
.resource = smc91x_resources,
};
static int __init se7206_devices_setup(void)
{
return platform_device_register(&smc91x_device);
}
__initcall(se7206_devices_setup);
void heartbeat_se(void);
/*
* The Machine Vector
*/
struct sh_machine_vector mv_se __initmv = {
.mv_name = "SolutionEngine",
.mv_nr_irqs = 256,
.mv_inb = se7206_inb,
.mv_inw = se7206_inw,
.mv_inl = se7206_inl,
.mv_outb = se7206_outb,
.mv_outw = se7206_outw,
.mv_outl = se7206_outl,
.mv_inb_p = se7206_inb_p,
.mv_inw_p = se7206_inw,
.mv_inl_p = se7206_inl,
.mv_outb_p = se7206_outb_p,
.mv_outw_p = se7206_outw,
.mv_outl_p = se7206_outl,
.mv_insb = se7206_insb,
.mv_insw = se7206_insw,
.mv_insl = se7206_insl,
.mv_outsb = se7206_outsb,
.mv_outsw = se7206_outsw,
.mv_outsl = se7206_outsl,
.mv_init_irq = init_se7206_IRQ,
.mv_irq_demux = se7206_irq_demux,
#ifdef CONFIG_HEARTBEAT
.mv_heartbeat = heartbeat_se,
#endif
};
ALIAS_MV(se)
#
# Makefile for the 7619 SolutionEngine specific parts of the kernel
#
obj-y := setup.o io.o
/*
*
* linux/arch/sh/boards/se/7619/io.c
*
* Copyright (C) 2006 Yoshinori Sato
*
* I/O routine for Hitachi 7619 SolutionEngine.
*
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <asm/io.h>
#include <asm/se7619.h>
#include <asm/irq.h>
/* FIXME: M3A-ZAB7 Compact Flash Slot support */
static inline void delay(void)
{
ctrl_inw(0xa0000000); /* Uncached ROM area (P2) */
}
#define badio(name,port) \
printk("bad I/O operation (%s) for port 0x%lx at 0x%08x\n", \
#name, (port), (__u32) __builtin_return_address(0))
unsigned char se7619___inb(unsigned long port)
{
badio(inb, port);
return 0;
}
unsigned char se7619___inb_p(unsigned long port)
{
badio(inb_p, port);
delay();
return 0;
}
unsigned short se7619___inw(unsigned long port)
{
badio(inw, port);
return 0;
}
unsigned int se7619___inl(unsigned long port)
{
badio(inl, port);
return 0;
}
void se7619___outb(unsigned char value, unsigned long port)
{
badio(outb, port);
}
void se7619___outb_p(unsigned char value, unsigned long port)
{
badio(outb_p, port);
delay();
}
void se7619___outw(unsigned short value, unsigned long port)
{
badio(outw, port);
}
void se7619___outl(unsigned int value, unsigned long port)
{
badio(outl, port);
}
void se7619___insb(unsigned long port, void *addr, unsigned long count)
{
badio(inw, port);
}
void se7619___insw(unsigned long port, void *addr, unsigned long count)
{
badio(inw, port);
}
void se7619___insl(unsigned long port, void *addr, unsigned long count)
{
badio(insl, port);
}
void se7619___outsb(unsigned long port, const void *addr, unsigned long count)
{
badio(insl, port);
}
void se7619___outsw(unsigned long port, const void *addr, unsigned long count)
{
badio(insl, port);
}
void se7619___outsl(unsigned long port, const void *addr, unsigned long count)
{
badio(outsw, port);
}
/*
* arch/sh/boards/se/7619/setup.c
*
* Copyright (C) 2006 Yoshinori Sato
*
* Hitachi SH7619 SolutionEngine Support.
*/
#include <linux/init.h>
#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/se7619.h>
#include <asm/machvec.h>
/*
* The Machine Vector
*/
struct sh_machine_vector mv_se __initmv = {
.mv_name = "SolutionEngine",
.mv_nr_irqs = 108,
.mv_inb = se7619___inb,
.mv_inw = se7619___inw,
.mv_inl = se7619___inl,
.mv_outb = se7619___outb,
.mv_outw = se7619___outw,
.mv_outl = se7619___outl,
.mv_inb_p = se7619___inb_p,
.mv_inw_p = se7619___inw,
.mv_inl_p = se7619___inl,
.mv_outb_p = se7619___outb_p,
.mv_outw_p = se7619___outw,
.mv_outl_p = se7619___outl,
.mv_insb = se7619___insb,
.mv_insw = se7619___insw,
.mv_insl = se7619___insl,
.mv_outsb = se7619___outsb,
.mv_outsw = se7619___outsw,
.mv_outsl = se7619___outsl,
};
ALIAS_MV(se)
This diff is collapsed.
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