Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc8fb5d0 authored by Paul Mundt's avatar Paul Mundt
Browse files

sh: Solution Engine SH7343 board support.



This adds support for the SE7343 board.

Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 91b91d01
Loading
Loading
Loading
Loading
+22 −13
Original line number Diff line number Diff line
@@ -51,18 +51,23 @@ source "init/Kconfig"

menu "System type"

config SOLUTION_ENGINE
	bool

choice
	prompt "SuperH system type"
	default SH_UNKNOWN

config SH_SOLUTION_ENGINE
	bool "SolutionEngine"
	select SOLUTION_ENGINE
	help
	  Select SolutionEngine if configuring for a Hitachi SH7709
	  or SH7750 evaluation board.

config SH_7751_SOLUTION_ENGINE
	bool "SolutionEngine7751"
	select SOLUTION_ENGINE
	select CPU_SUBTYPE_SH7751
	help
	  Select 7751 SolutionEngine if configuring for a Hitachi SH7751
@@ -70,17 +75,27 @@ config SH_7751_SOLUTION_ENGINE

config SH_7300_SOLUTION_ENGINE
	bool "SolutionEngine7300"
	select SOLUTION_ENGINE
	select CPU_SUBTYPE_SH7300
	help
	  Select 7300 SolutionEngine if configuring for a Hitachi SH7300(SH-Mobile V)
	  evaluation board.
	  Select 7300 SolutionEngine if configuring for a Hitachi
	  SH7300(SH-Mobile V) evaluation board.

config SH_7343_SOLUTION_ENGINE
	bool "SolutionEngine7343"
	select SOLUTION_ENGINE
	select CPU_SUBTYPE_SH7343
	help
	  Select 7343 SolutionEngine if configuring for a Hitachi
	  SH7343 (SH-Mobile 3AS) evaluation board.

config SH_73180_SOLUTION_ENGINE
       bool "SolutionEngine73180"
	select SOLUTION_ENGINE
	select CPU_SUBTYPE_SH73180
	help
         Select 73180 SolutionEngine if configuring for a Hitachi SH73180(SH-Mobile 3)
         evaluation board.
	  Select 73180 SolutionEngine if configuring for a Hitachi
	  SH73180(SH-Mobile 3) evaluation board.

config SH_7751_SYSTEMH
	bool "SystemH7751R"
@@ -394,9 +409,7 @@ source "arch/sh/cchips/Kconfig"
config HEARTBEAT
	bool "Heartbeat LED"
	depends on SH_MPC1211 || SH_SH03 || \
		   SH_BIGSUR || \
		   SH_7751_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || \
		   SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || \
		   SH_BIGSUR || SOLUTION_ENGINE || \
		   SH_RTS7751R2D || SH_SH4202_MICRODEV || SH_LANDISK
	help
	  Use the power-on LED on your machine as a load meter.  The exact
@@ -431,10 +444,6 @@ config KEXEC
	  support.  As of this writing the exact hardware interface is
	  strongly in flux, so no good recommendation can be made.

config PREEMPT
	bool "Preemptible Kernel (EXPERIMENTAL)"
	depends on EXPERIMENTAL

config SMP
	bool "Symmetric multi-processing support"
	---help---
+1 −0
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@ core-$(CONFIG_SH_FPU_EMU) += arch/sh/math-emu/
machdir-$(CONFIG_SH_SOLUTION_ENGINE)		:= se/770x
machdir-$(CONFIG_SH_7751_SOLUTION_ENGINE)	:= se/7751
machdir-$(CONFIG_SH_7300_SOLUTION_ENGINE)	:= se/7300
machdir-$(CONFIG_SH_7343_SOLUTION_ENGINE)	:= se/7343
machdir-$(CONFIG_SH_73180_SOLUTION_ENGINE)	:= se/73180
machdir-$(CONFIG_SH_HP6XX)			:= hp6xx
machdir-$(CONFIG_SH_EC3104)			:= ec3104
+7 −0
Original line number Diff line number Diff line
#
# Makefile for the 7343 SolutionEngine specific parts of the kernel
#

obj-y	 := setup.o io.o irq.o

obj-$(CONFIG_HEARTBEAT) += led.o
+275 −0
Original line number Diff line number Diff line
/*
 * arch/sh/boards/se/7343/io.c
 *
 * I/O routine for SH-Mobile3AS 7343 SolutionEngine.
 *
 */

#include <linux/config.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <asm/mach/se7343.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)
{
	static int count;

	if (count < 100)
		count++;

	port &= 0xFFFF;

	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);
}

#ifdef CONFIG_SMC91X
/* MSTLANEX01 LAN at 0xb400:0000 */
static struct iop laniop = {
	.start = 0x00,
	.end = 0x0F,
	.base = 0x04000000,
	.check = simple_check,
	.inb = simple_inb,
	.inw = simple_inw,
	.outb = simple_outb,
	.outw = simple_outw,
};
#endif

#ifdef CONFIG_NE2000
/* 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,
};
#endif

#ifdef CONFIG_IDE
/* 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,
};
#endif

static __inline__ struct iop *
port2iop(unsigned long port)
{
	if (0) ;
#if defined(CONFIG_SMC91X)
	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 NULL;
}

static inline void
delay(void)
{
	ctrl_inw(0xac000000);
	ctrl_inw(0xac000000);
}

unsigned char
sh7343se_inb(unsigned long port)
{
	struct iop *p = port2iop(port);
	return (p->inb) (p, port);
}

unsigned char
sh7343se_inb_p(unsigned long port)
{
	unsigned char v = sh7343se_inb(port);
	delay();
	return v;
}

unsigned short
sh7343se_inw(unsigned long port)
{
	struct iop *p = port2iop(port);
	return (p->inw) (p, port);
}

unsigned int
sh7343se_inl(unsigned long port)
{
	badio(inl, port);
}

void
sh7343se_outb(unsigned char value, unsigned long port)
{
	struct iop *p = port2iop(port);
	(p->outb) (p, value, port);
}

void
sh7343se_outb_p(unsigned char value, unsigned long port)
{
	sh7343se_outb(value, port);
	delay();
}

void
sh7343se_outw(unsigned short value, unsigned long port)
{
	struct iop *p = port2iop(port);
	(p->outw) (p, value, port);
}

void
sh7343se_outl(unsigned int value, unsigned long port)
{
	badio(outl, port);
}

void
sh7343se_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
sh7343se_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
sh7343se_insl(unsigned long port, void *addr, unsigned long count)
{
	badio(insl, port);
}

void
sh7343se_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
sh7343se_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
sh7343se_outsl(unsigned long port, const void *addr, unsigned long count)
{
	badio(outsw, port);
}
+193 −0
Original line number Diff line number Diff line
/*
 * arch/sh/boards/se/7343/irq.c
 *
 */

#include <linux/config.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/mach/se7343.h>

static void
disable_intreq_irq(unsigned int irq)
{
	int bit = irq - OFFCHIP_IRQ_BASE;
	u16 val;

	val = ctrl_inw(PA_CPLD_IMSK);
	val |= 1 << bit;
	ctrl_outw(val, PA_CPLD_IMSK);
}

static void
enable_intreq_irq(unsigned int irq)
{
	int bit = irq - OFFCHIP_IRQ_BASE;
	u16 val;

	val = ctrl_inw(PA_CPLD_IMSK);
	val &= ~(1 << bit);
	ctrl_outw(val, PA_CPLD_IMSK);
}

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 = "FPGA-IRQ",
	.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
};

static 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)
{
	int bit;
	volatile u16 val;

	if (irq == IRQ5_IRQ) {
		/* Read status Register */
		val = ctrl_inw(PA_CPLD_ST);
		bit = ffs(val);
		if (bit != 0)
			return OFFCHIP_IRQ_BASE + bit - 1;
	}
	return irq;
}

/* IRQ5 is multiplexed between the following sources:
 * 1. PC Card socket
 * 2. Extension slot
 * 3. USB Controller
 * 4. Serial Controller
 *
 * We configure IRQ5 as a cascade IRQ.
 */
static struct irqaction irq5 = { no_action, 0, CPU_MASK_NONE, "IRQ5-cascade",
				NULL, NULL};

/*
 * Initialize IRQ setting
 */
void __init
init_7343se_IRQ(void)
{
	/* Setup Multiplexed interrupts */
	ctrl_outw(8, PA_CPLD_MODESET);	/* Set all CPLD interrupts to active
					 * low.
					 */
	/* Mask all CPLD controller interrupts */
	ctrl_outw(0x0fff, PA_CPLD_IMSK);

	/* PC Card interrupts */
	make_intreq_irq(PC_IRQ0);
	make_intreq_irq(PC_IRQ1);
	make_intreq_irq(PC_IRQ2);
	make_intreq_irq(PC_IRQ3);

	/* Extension Slot Interrupts */
	make_intreq_irq(EXT_IRQ0);
	make_intreq_irq(EXT_IRQ1);
	make_intreq_irq(EXT_IRQ2);
	make_intreq_irq(EXT_IRQ3);

	/* USB Controller interrupts */
	make_intreq_irq(USB_IRQ0);
	make_intreq_irq(USB_IRQ1);

	/* Serial Controller interrupts */
	make_intreq_irq(UART_IRQ0);
	make_intreq_irq(UART_IRQ1);

	/* Setup all external interrupts to be active low */
	ctrl_outw(0xaaaa, INTC_ICR1);

	make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR+2, IRQ5_IPR_POS, IRQ5_PRIORITY);
	setup_irq(IRQ5_IRQ, &irq5);
	/* Set port control to use IRQ5 */
	*(u16 *)0xA4050108 &= ~0xc;

	make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY);
	make_ipr_irq(VPU_IRQ, VPU_IPR_ADDR, VPU_IPR_POS, 8);

	ctrl_outb(0x0f, INTC_IMCR5);	/* enable SCIF IRQ */

	make_ipr_irq(DMTE0_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
	make_ipr_irq(DMTE1_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
	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(DMTE5_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY);

	/* I2C block */
	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(IIC1_ALI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY);
	make_ipr_irq(IIC1_TACKI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS,
		     IIC1_PRIORITY);
	make_ipr_irq(IIC1_WAITI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS,
		     IIC1_PRIORITY);
	make_ipr_irq(IIC1_DTEI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY);

	/* SIOF */
	make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY);

	/* SIU */
	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);

	/*MFI interrupt*/

	make_ipr_irq(MFI_IRQ, MFI_IPR_ADDR, MFI_IPR_POS, MFI_PRIORITY);

	/* LCD controller */
	make_ipr_irq(LCDC_IRQ, LCDC_IPR_ADDR, LCDC_IPR_POS, LCDC_PRIORITY);
	ctrl_outw(0x2000, PA_MRSHPC + 0x0c);	/* mrshpc irq enable */
}
Loading