Skip to content

Commit

Permalink
[PATCH] sh: SuperHyway support for SH4-202
Browse files Browse the repository at this point in the history
This adds support for the relatively quirky (ie, not in line with any known
documentation, and amazed it works at all) SuperHyway implementation on
SH4-202.  This depends on the earlier SuperHyway patch for multiple block
support and VCR refactoring.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
pmundt authored and Linus Torvalds committed Nov 7, 2005
1 parent 055a251 commit d5cb978
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 2 deletions.
5 changes: 3 additions & 2 deletions arch/sh/drivers/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Makefile for the Linux SuperH-specific device drivers.
#

obj-$(CONFIG_PCI) += pci/
obj-$(CONFIG_SH_DMA) += dma/
obj-$(CONFIG_PCI) += pci/
obj-$(CONFIG_SH_DMA) += dma/
obj-$(CONFIG_SUPERHYWAY) += superhyway/

6 changes: 6 additions & 0 deletions arch/sh/drivers/superhyway/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#
# Makefile for the SuperHyway specific kernel interface routines under Linux.
#

obj-$(CONFIG_CPU_SUBTYPE_SH4_202) += ops-sh4-202.o

171 changes: 171 additions & 0 deletions arch/sh/drivers/superhyway/ops-sh4-202.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*
* arch/sh/drivers/superhyway/ops-sh4-202.c
*
* SuperHyway bus support for SH4-202
*
* Copyright (C) 2005 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU
* General Public License. See the file "COPYING" in the main
* directory of this archive for more details.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/superhyway.h>
#include <linux/string.h>
#include <asm/addrspace.h>
#include <asm/io.h>

#define PHYS_EMI_CBLOCK P4SEGADDR(0x1ec00000)
#define PHYS_EMI_DBLOCK P4SEGADDR(0x08000000)
#define PHYS_FEMI_CBLOCK P4SEGADDR(0x1f800000)
#define PHYS_FEMI_DBLOCK P4SEGADDR(0x00000000)

#define PHYS_EPBR_BLOCK P4SEGADDR(0x1de00000)
#define PHYS_DMAC_BLOCK P4SEGADDR(0x1fa00000)
#define PHYS_PBR_BLOCK P4SEGADDR(0x1fc00000)

static struct resource emi_resources[] = {
[0] = {
.start = PHYS_EMI_CBLOCK,
.end = PHYS_EMI_CBLOCK + 0x00300000 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = PHYS_EMI_DBLOCK,
.end = PHYS_EMI_DBLOCK + 0x08000000 - 1,
.flags = IORESOURCE_MEM,
},
};

static struct superhyway_device emi_device = {
.name = "emi",
.num_resources = ARRAY_SIZE(emi_resources),
.resource = emi_resources,
};

static struct resource femi_resources[] = {
[0] = {
.start = PHYS_FEMI_CBLOCK,
.end = PHYS_FEMI_CBLOCK + 0x00100000 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = PHYS_FEMI_DBLOCK,
.end = PHYS_FEMI_DBLOCK + 0x08000000 - 1,
.flags = IORESOURCE_MEM,
},
};

static struct superhyway_device femi_device = {
.name = "femi",
.num_resources = ARRAY_SIZE(femi_resources),
.resource = femi_resources,
};

static struct resource epbr_resources[] = {
[0] = {
.start = P4SEGADDR(0x1e7ffff8),
.end = P4SEGADDR(0x1e7ffff8 + (sizeof(u32) * 2) - 1),
.flags = IORESOURCE_MEM,
},
[1] = {
.start = PHYS_EPBR_BLOCK,
.end = PHYS_EPBR_BLOCK + 0x00a00000 - 1,
.flags = IORESOURCE_MEM,
},
};

static struct superhyway_device epbr_device = {
.name = "epbr",
.num_resources = ARRAY_SIZE(epbr_resources),
.resource = epbr_resources,
};

static struct resource dmac_resource = {
.start = PHYS_DMAC_BLOCK,
.end = PHYS_DMAC_BLOCK + 0x00100000 - 1,
.flags = IORESOURCE_MEM,
};

static struct superhyway_device dmac_device = {
.name = "dmac",
.num_resources = 1,
.resource = &dmac_resource,
};

static struct resource pbr_resources[] = {
[0] = {
.start = P4SEGADDR(0x1ffffff8),
.end = P4SEGADDR(0x1ffffff8 + (sizeof(u32) * 2) - 1),
.flags = IORESOURCE_MEM,
},
[1] = {
.start = PHYS_PBR_BLOCK,
.end = PHYS_PBR_BLOCK + 0x00400000 - (sizeof(u32) * 2) - 1,
.flags = IORESOURCE_MEM,
},
};

static struct superhyway_device pbr_device = {
.name = "pbr",
.num_resources = ARRAY_SIZE(pbr_resources),
.resource = pbr_resources,
};

static struct superhyway_device *sh4202_devices[] __initdata = {
&emi_device, &femi_device, &epbr_device, &dmac_device, &pbr_device,
};

static int sh4202_read_vcr(unsigned long base, struct superhyway_vcr_info *vcr)
{
u32 vcrh, vcrl;
u64 tmp;

/*
* XXX: Even though the SH4-202 Evaluation Device documentation
* indicates that VCRL is mapped first with VCRH at a + 0x04
* offset, the opposite seems to be true.
*
* Some modules (PBR and ePBR for instance) also appear to have
* VCRL/VCRH flipped in the documentation, but on the SH4-202
* itself it appears that these are all consistently mapped with
* VCRH preceeding VCRL.
*
* Do not trust the documentation, for it is evil.
*/
vcrh = ctrl_inl(base);
vcrl = ctrl_inl(base + sizeof(u32));

tmp = ((u64)vcrh << 32) | vcrl;
memcpy(vcr, &tmp, sizeof(u64));

return 0;
}

static int sh4202_write_vcr(unsigned long base, struct superhyway_vcr_info vcr)
{
u64 tmp = *(u64 *)&vcr;

ctrl_outl((tmp >> 32) & 0xffffffff, base);
ctrl_outl(tmp & 0xffffffff, base + sizeof(u32));

return 0;
}

static struct superhyway_ops sh4202_superhyway_ops = {
.read_vcr = sh4202_read_vcr,
.write_vcr = sh4202_write_vcr,
};

struct superhyway_bus superhyway_channels[] = {
{ &sh4202_superhyway_ops, },
{ 0, },
};

int __init superhyway_scan_bus(struct superhyway_bus *bus)
{
return superhyway_add_devices(bus, sh4202_devices,
ARRAY_SIZE(sh4202_devices));
}

0 comments on commit d5cb978

Please sign in to comment.