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

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
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
#
# Makefile for the 7206 SolutionEngine specific parts of the kernel
#

obj-y	 := setup.o io.o irq.o
obj-$(CONFIG_HEARTBEAT) += led.o
+123 −0
Original line number Diff line number Diff line
/* $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 −0
Original line number Diff line number Diff line
/*
 * 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 −0
Original line number Diff line number Diff line
/*
 * 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 */
+80 −0
Original line number Diff line number Diff line
/*
 *
 * 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)
Loading