forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[PATCH] sh: SuperHyway support for SH4-202
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
Showing
3 changed files
with
180 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | ||
} | ||
|