diff options
Diffstat (limited to 'arch/sh/boards/mach-se/7751')
-rw-r--r-- | arch/sh/boards/mach-se/7751/Makefile | 7 | ||||
-rw-r--r-- | arch/sh/boards/mach-se/7751/io.c | 135 | ||||
-rw-r--r-- | arch/sh/boards/mach-se/7751/irq.c | 50 | ||||
-rw-r--r-- | arch/sh/boards/mach-se/7751/pci.c | 147 | ||||
-rw-r--r-- | arch/sh/boards/mach-se/7751/setup.c | 78 |
5 files changed, 417 insertions, 0 deletions
diff --git a/arch/sh/boards/mach-se/7751/Makefile b/arch/sh/boards/mach-se/7751/Makefile new file mode 100644 index 000000000000..dbc29f3a9de5 --- /dev/null +++ b/arch/sh/boards/mach-se/7751/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the 7751 SolutionEngine specific parts of the kernel +# + +obj-y := setup.o io.o irq.o + +obj-$(CONFIG_PCI) += pci.o diff --git a/arch/sh/boards/mach-se/7751/io.c b/arch/sh/boards/mach-se/7751/io.c new file mode 100644 index 000000000000..e8d846cec89d --- /dev/null +++ b/arch/sh/boards/mach-se/7751/io.c @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2001 Ian da Silva, Jeremy Siegel + * Based largely on io_se.c. + * + * I/O routine for Hitachi 7751 SolutionEngine. + * + * Initial version only to support LAN access; some + * placeholder code from io_se.c left in with the + * expectation of later SuperIO and PCMCIA access. + */ +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/pci.h> +#include <asm/io.h> +#include <asm/se7751.h> +#include <asm/addrspace.h> + +static inline volatile u16 *port2adr(unsigned int port) +{ + if (port >= 0x2000) + return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000)); + maybebadio((unsigned long)port); + return (volatile __u16*)port; +} + +/* + * General outline: remap really low stuff [eventually] to SuperIO, + * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO) + * is mapped through the PCI IO window. Stuff with high bits (PXSEG) + * should be way beyond the window, and is used w/o translation for + * compatibility. + */ +unsigned char sh7751se_inb(unsigned long port) +{ + if (PXSEG(port)) + return *(volatile unsigned char *)port; + else if (is_pci_ioaddr(port)) + return *(volatile unsigned char *)pci_ioaddr(port); + else + return (*port2adr(port)) & 0xff; +} + +unsigned char sh7751se_inb_p(unsigned long port) +{ + unsigned char v; + + if (PXSEG(port)) + v = *(volatile unsigned char *)port; + else if (is_pci_ioaddr(port)) + v = *(volatile unsigned char *)pci_ioaddr(port); + else + v = (*port2adr(port)) & 0xff; + ctrl_delay(); + return v; +} + +unsigned short sh7751se_inw(unsigned long port) +{ + if (PXSEG(port)) + return *(volatile unsigned short *)port; + else if (is_pci_ioaddr(port)) + return *(volatile unsigned short *)pci_ioaddr(port); + else if (port >= 0x2000) + return *port2adr(port); + else + maybebadio(port); + return 0; +} + +unsigned int sh7751se_inl(unsigned long port) +{ + if (PXSEG(port)) + return *(volatile unsigned long *)port; + else if (is_pci_ioaddr(port)) + return *(volatile unsigned int *)pci_ioaddr(port); + else if (port >= 0x2000) + return *port2adr(port); + else + maybebadio(port); + return 0; +} + +void sh7751se_outb(unsigned char value, unsigned long port) +{ + + if (PXSEG(port)) + *(volatile unsigned char *)port = value; + else if (is_pci_ioaddr(port)) + *((unsigned char*)pci_ioaddr(port)) = value; + else + *(port2adr(port)) = value; +} + +void sh7751se_outb_p(unsigned char value, unsigned long port) +{ + if (PXSEG(port)) + *(volatile unsigned char *)port = value; + else if (is_pci_ioaddr(port)) + *((unsigned char*)pci_ioaddr(port)) = value; + else + *(port2adr(port)) = value; + ctrl_delay(); +} + +void sh7751se_outw(unsigned short value, unsigned long port) +{ + if (PXSEG(port)) + *(volatile unsigned short *)port = value; + else if (is_pci_ioaddr(port)) + *((unsigned short *)pci_ioaddr(port)) = value; + else if (port >= 0x2000) + *port2adr(port) = value; + else + maybebadio(port); +} + +void sh7751se_outl(unsigned int value, unsigned long port) +{ + if (PXSEG(port)) + *(volatile unsigned long *)port = value; + else if (is_pci_ioaddr(port)) + *((unsigned long*)pci_ioaddr(port)) = value; + else + maybebadio(port); +} + +void sh7751se_insl(unsigned long port, void *addr, unsigned long count) +{ + maybebadio(port); +} + +void sh7751se_outsl(unsigned long port, const void *addr, unsigned long count) +{ + maybebadio(port); +} diff --git a/arch/sh/boards/mach-se/7751/irq.c b/arch/sh/boards/mach-se/7751/irq.c new file mode 100644 index 000000000000..c3d12590e5db --- /dev/null +++ b/arch/sh/boards/mach-se/7751/irq.c @@ -0,0 +1,50 @@ +/* + * linux/arch/sh/boards/se/7751/irq.c + * + * Copyright (C) 2000 Kazumoto Kojima + * + * Hitachi SolutionEngine Support. + * + * Modified for 7751 Solution Engine by + * Ian da Silva and Jeremy Siegel, 2001. + */ + +#include <linux/init.h> +#include <linux/irq.h> +#include <asm/irq.h> +#include <asm/se7751.h> + +static struct ipr_data ipr_irq_table[] = { + { 13, 3, 3, 2 }, + /* Add additional entries here as drivers are added and tested. */ +}; + +static unsigned long ipr_offsets[] = { + BCR_ILCRA, + BCR_ILCRB, + BCR_ILCRC, + BCR_ILCRD, + BCR_ILCRE, + BCR_ILCRF, + BCR_ILCRG, +}; + +static struct ipr_desc ipr_irq_desc = { + .ipr_offsets = ipr_offsets, + .nr_offsets = ARRAY_SIZE(ipr_offsets), + + .ipr_data = ipr_irq_table, + .nr_irqs = ARRAY_SIZE(ipr_irq_table), + + .chip = { + .name = "IPR-se7751", + }, +}; + +/* + * Initialize IRQ setting + */ +void __init init_7751se_IRQ(void) +{ + register_ipr_controller(&ipr_irq_desc); +} diff --git a/arch/sh/boards/mach-se/7751/pci.c b/arch/sh/boards/mach-se/7751/pci.c new file mode 100644 index 000000000000..203b2923fe7f --- /dev/null +++ b/arch/sh/boards/mach-se/7751/pci.c @@ -0,0 +1,147 @@ +/* + * linux/arch/sh/boards/se/7751/pci.c + * + * Author: Ian DaSilva (idasilva@mvista.com) + * + * Highly leveraged from pci-bigsur.c, written by Dustin McIntire. + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * PCI initialization for the Hitachi SH7751 Solution Engine board (MS7751SE01) + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/pci.h> + +#include <asm/io.h> +#include "../../../drivers/pci/pci-sh7751.h" + +#define PCIMCR_MRSET_OFF 0xBFFFFFFF +#define PCIMCR_RFSH_OFF 0xFFFFFFFB + +/* + * Only long word accesses of the PCIC's internal local registers and the + * configuration registers from the CPU is supported. + */ +#define PCIC_WRITE(x,v) writel((v), PCI_REG(x)) +#define PCIC_READ(x) readl(PCI_REG(x)) + +/* + * Description: This function sets up and initializes the pcic, sets + * up the BARS, maps the DRAM into the address space etc, etc. + */ +int __init pcibios_init_platform(void) +{ + unsigned long bcr1, wcr1, wcr2, wcr3, mcr; + unsigned short bcr2; + + /* + * Initialize the slave bus controller on the pcic. The values used + * here should not be hardcoded, but they should be taken from the bsc + * on the processor, to make this function as generic as possible. + * (i.e. Another sbc may usr different SDRAM timing settings -- in order + * for the pcic to work, its settings need to be exactly the same.) + */ + bcr1 = (*(volatile unsigned long*)(SH7751_BCR1)); + bcr2 = (*(volatile unsigned short*)(SH7751_BCR2)); + wcr1 = (*(volatile unsigned long*)(SH7751_WCR1)); + wcr2 = (*(volatile unsigned long*)(SH7751_WCR2)); + wcr3 = (*(volatile unsigned long*)(SH7751_WCR3)); + mcr = (*(volatile unsigned long*)(SH7751_MCR)); + + bcr1 = bcr1 | 0x00080000; /* Enable Bit 19, BREQEN */ + (*(volatile unsigned long*)(SH7751_BCR1)) = bcr1; + + bcr1 = bcr1 | 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */ + PCIC_WRITE(SH7751_PCIBCR1, bcr1); /* PCIC BCR1 */ + PCIC_WRITE(SH7751_PCIBCR2, bcr2); /* PCIC BCR2 */ + PCIC_WRITE(SH7751_PCIWCR1, wcr1); /* PCIC WCR1 */ + PCIC_WRITE(SH7751_PCIWCR2, wcr2); /* PCIC WCR2 */ + PCIC_WRITE(SH7751_PCIWCR3, wcr3); /* PCIC WCR3 */ + mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF; + PCIC_WRITE(SH7751_PCIMCR, mcr); /* PCIC MCR */ + + + /* Enable all interrupts, so we know what to fix */ + PCIC_WRITE(SH7751_PCIINTM, 0x0000c3ff); + PCIC_WRITE(SH7751_PCIAINTM, 0x0000380f); + + /* Set up standard PCI config registers */ + PCIC_WRITE(SH7751_PCICONF1, 0xF39000C7); /* Bus Master, Mem & I/O access */ + PCIC_WRITE(SH7751_PCICONF2, 0x00000000); /* PCI Class code & Revision ID */ + PCIC_WRITE(SH7751_PCICONF4, 0xab000001); /* PCI I/O address (local regs) */ + PCIC_WRITE(SH7751_PCICONF5, 0x0c000000); /* PCI MEM address (local RAM) */ + PCIC_WRITE(SH7751_PCICONF6, 0xd0000000); /* PCI MEM address (unused) */ + PCIC_WRITE(SH7751_PCICONF11, 0x35051054); /* PCI Subsystem ID & Vendor ID */ + PCIC_WRITE(SH7751_PCILSR0, 0x03f00000); /* MEM (full 64M exposed) */ + PCIC_WRITE(SH7751_PCILSR1, 0x00000000); /* MEM (unused) */ + PCIC_WRITE(SH7751_PCILAR0, 0x0c000000); /* MEM (direct map from PCI) */ + PCIC_WRITE(SH7751_PCILAR1, 0x00000000); /* MEM (unused) */ + + /* Now turn it on... */ + PCIC_WRITE(SH7751_PCICR, 0xa5000001); + + /* + * Set PCIMBR and PCIIOBR here, assuming a single window + * (16M MEM, 256K IO) is enough. If a larger space is + * needed, the readx/writex and inx/outx functions will + * have to do more (e.g. setting registers for each call). + */ + + /* + * Set the MBR so PCI address is one-to-one with window, + * meaning all calls go straight through... use BUG_ON to + * catch erroneous assumption. + */ + BUG_ON(PCIBIOS_MIN_MEM != SH7751_PCI_MEMORY_BASE); + + PCIC_WRITE(SH7751_PCIMBR, PCIBIOS_MIN_MEM); + + /* Set IOBR for window containing area specified in pci.h */ + PCIC_WRITE(SH7751_PCIIOBR, (PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK)); + + /* All done, may as well say so... */ + printk("SH7751 PCI: Finished initialization of the PCI controller\n"); + + return 1; +} + +int __init pcibios_map_platform_irq(u8 slot, u8 pin) +{ + switch (slot) { + case 0: return 13; + case 1: return 13; /* AMD Ethernet controller */ + case 2: return -1; + case 3: return -1; + case 4: return -1; + default: + printk("PCI: Bad IRQ mapping request for slot %d\n", slot); + return -1; + } +} + +static struct resource sh7751_io_resource = { + .name = "SH7751 IO", + .start = SH7751_PCI_IO_BASE, + .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1, + .flags = IORESOURCE_IO +}; + +static struct resource sh7751_mem_resource = { + .name = "SH7751 mem", + .start = SH7751_PCI_MEMORY_BASE, + .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1, + .flags = IORESOURCE_MEM +}; + +extern struct pci_ops sh7751_pci_ops; + +struct pci_channel board_pci_channels[] = { + { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff }, + { NULL, NULL, NULL, 0, 0 }, +}; + diff --git a/arch/sh/boards/mach-se/7751/setup.c b/arch/sh/boards/mach-se/7751/setup.c new file mode 100644 index 000000000000..deefbfd92591 --- /dev/null +++ b/arch/sh/boards/mach-se/7751/setup.c @@ -0,0 +1,78 @@ +/* + * linux/arch/sh/boards/se/7751/setup.c + * + * Copyright (C) 2000 Kazumoto Kojima + * + * Hitachi SolutionEngine Support. + * + * Modified for 7751 Solution Engine by + * Ian da Silva and Jeremy Siegel, 2001. + */ +#include <linux/init.h> +#include <linux/platform_device.h> +#include <asm/machvec.h> +#include <asm/se7751.h> +#include <asm/io.h> +#include <asm/heartbeat.h> + +static unsigned char heartbeat_bit_pos[] = { 8, 9, 10, 11, 12, 13, 14, 15 }; + +static struct heartbeat_data heartbeat_data = { + .bit_pos = heartbeat_bit_pos, + .nr_bits = ARRAY_SIZE(heartbeat_bit_pos), +}; + +static struct resource heartbeat_resources[] = { + [0] = { + .start = PA_LED, + .end = PA_LED, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device heartbeat_device = { + .name = "heartbeat", + .id = -1, + .dev = { + .platform_data = &heartbeat_data, + }, + .num_resources = ARRAY_SIZE(heartbeat_resources), + .resource = heartbeat_resources, +}; + +static struct platform_device *se7751_devices[] __initdata = { + &heartbeat_device, +}; + +static int __init se7751_devices_setup(void) +{ + return platform_add_devices(se7751_devices, ARRAY_SIZE(se7751_devices)); +} +__initcall(se7751_devices_setup); + +/* + * The Machine Vector + */ +static struct sh_machine_vector mv_7751se __initmv = { + .mv_name = "7751 SolutionEngine", + .mv_nr_irqs = 72, + + .mv_inb = sh7751se_inb, + .mv_inw = sh7751se_inw, + .mv_inl = sh7751se_inl, + .mv_outb = sh7751se_outb, + .mv_outw = sh7751se_outw, + .mv_outl = sh7751se_outl, + + .mv_inb_p = sh7751se_inb_p, + .mv_inw_p = sh7751se_inw, + .mv_inl_p = sh7751se_inl, + .mv_outb_p = sh7751se_outb_p, + .mv_outw_p = sh7751se_outw, + .mv_outl_p = sh7751se_outl, + + .mv_insl = sh7751se_insl, + .mv_outsl = sh7751se_outsl, + + .mv_init_irq = init_7751se_IRQ, +}; |