Skip to content

Commit

Permalink
sh: Add support for Solution Engine 7206 and 7619 boards.
Browse files Browse the repository at this point in the history
This adds support for the Solution Engine 7206 and 7619.

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
  • Loading branch information
ysat0 authored and pmundt committed Dec 6, 2006
1 parent b229632 commit f36af3f
Show file tree
Hide file tree
Showing 9 changed files with 1,404 additions and 0 deletions.
7 changes: 7 additions & 0 deletions arch/sh/boards/se/7206/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#
# Makefile for the 7206 SolutionEngine specific parts of the kernel
#

obj-y := setup.o io.o irq.o
obj-$(CONFIG_HEARTBEAT) += led.o

123 changes: 123 additions & 0 deletions arch/sh/boards/se/7206/io.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/* $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);
}
161 changes: 161 additions & 0 deletions arch/sh/boards/se/7206/irq.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
* 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;
}
57 changes: 57 additions & 0 deletions arch/sh/boards/se/7206/led.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* 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 */
Loading

0 comments on commit f36af3f

Please sign in to comment.