1 // SPDX-License-Identifier: GPL-2.0
3 * arch/sh/drivers/superhyway/ops-sh4-202.c
5 * SuperHyway bus support for SH4-202
7 * Copyright (C) 2005 Paul Mundt
9 #include <linux/kernel.h>
10 #include <linux/init.h>
11 #include <linux/superhyway.h>
12 #include <linux/string.h>
13 #include <asm/addrspace.h>
16 #define PHYS_EMI_CBLOCK P4SEGADDR(0x1ec00000)
17 #define PHYS_EMI_DBLOCK P4SEGADDR(0x08000000)
18 #define PHYS_FEMI_CBLOCK P4SEGADDR(0x1f800000)
19 #define PHYS_FEMI_DBLOCK P4SEGADDR(0x00000000)
21 #define PHYS_EPBR_BLOCK P4SEGADDR(0x1de00000)
22 #define PHYS_DMAC_BLOCK P4SEGADDR(0x1fa00000)
23 #define PHYS_PBR_BLOCK P4SEGADDR(0x1fc00000)
25 static struct resource emi_resources
[] = {
27 .start
= PHYS_EMI_CBLOCK
,
28 .end
= PHYS_EMI_CBLOCK
+ 0x00300000 - 1,
29 .flags
= IORESOURCE_MEM
,
32 .start
= PHYS_EMI_DBLOCK
,
33 .end
= PHYS_EMI_DBLOCK
+ 0x08000000 - 1,
34 .flags
= IORESOURCE_MEM
,
38 static struct superhyway_device emi_device
= {
40 .num_resources
= ARRAY_SIZE(emi_resources
),
41 .resource
= emi_resources
,
44 static struct resource femi_resources
[] = {
46 .start
= PHYS_FEMI_CBLOCK
,
47 .end
= PHYS_FEMI_CBLOCK
+ 0x00100000 - 1,
48 .flags
= IORESOURCE_MEM
,
51 .start
= PHYS_FEMI_DBLOCK
,
52 .end
= PHYS_FEMI_DBLOCK
+ 0x08000000 - 1,
53 .flags
= IORESOURCE_MEM
,
57 static struct superhyway_device femi_device
= {
59 .num_resources
= ARRAY_SIZE(femi_resources
),
60 .resource
= femi_resources
,
63 static struct resource epbr_resources
[] = {
65 .start
= P4SEGADDR(0x1e7ffff8),
66 .end
= P4SEGADDR(0x1e7ffff8 + (sizeof(u32
) * 2) - 1),
67 .flags
= IORESOURCE_MEM
,
70 .start
= PHYS_EPBR_BLOCK
,
71 .end
= PHYS_EPBR_BLOCK
+ 0x00a00000 - 1,
72 .flags
= IORESOURCE_MEM
,
76 static struct superhyway_device epbr_device
= {
78 .num_resources
= ARRAY_SIZE(epbr_resources
),
79 .resource
= epbr_resources
,
82 static struct resource dmac_resource
= {
83 .start
= PHYS_DMAC_BLOCK
,
84 .end
= PHYS_DMAC_BLOCK
+ 0x00100000 - 1,
85 .flags
= IORESOURCE_MEM
,
88 static struct superhyway_device dmac_device
= {
91 .resource
= &dmac_resource
,
94 static struct resource pbr_resources
[] = {
96 .start
= P4SEGADDR(0x1ffffff8),
97 .end
= P4SEGADDR(0x1ffffff8 + (sizeof(u32
) * 2) - 1),
98 .flags
= IORESOURCE_MEM
,
101 .start
= PHYS_PBR_BLOCK
,
102 .end
= PHYS_PBR_BLOCK
+ 0x00400000 - (sizeof(u32
) * 2) - 1,
103 .flags
= IORESOURCE_MEM
,
107 static struct superhyway_device pbr_device
= {
109 .num_resources
= ARRAY_SIZE(pbr_resources
),
110 .resource
= pbr_resources
,
113 static struct superhyway_device
*sh4202_devices
[] __initdata
= {
114 &emi_device
, &femi_device
, &epbr_device
, &dmac_device
, &pbr_device
,
117 static int sh4202_read_vcr(unsigned long base
, struct superhyway_vcr_info
*vcr
)
123 * XXX: Even though the SH4-202 Evaluation Device documentation
124 * indicates that VCRL is mapped first with VCRH at a + 0x04
125 * offset, the opposite seems to be true.
127 * Some modules (PBR and ePBR for instance) also appear to have
128 * VCRL/VCRH flipped in the documentation, but on the SH4-202
129 * itself it appears that these are all consistently mapped with
130 * VCRH preceding VCRL.
132 * Do not trust the documentation, for it is evil.
134 vcrh
= __raw_readl(base
);
135 vcrl
= __raw_readl(base
+ sizeof(u32
));
137 tmp
= ((u64
)vcrh
<< 32) | vcrl
;
138 memcpy(vcr
, &tmp
, sizeof(u64
));
143 static int sh4202_write_vcr(unsigned long base
, struct superhyway_vcr_info vcr
)
145 u64 tmp
= *(u64
*)&vcr
;
147 __raw_writel((tmp
>> 32) & 0xffffffff, base
);
148 __raw_writel(tmp
& 0xffffffff, base
+ sizeof(u32
));
153 static struct superhyway_ops sh4202_superhyway_ops
= {
154 .read_vcr
= sh4202_read_vcr
,
155 .write_vcr
= sh4202_write_vcr
,
158 struct superhyway_bus superhyway_channels
[] = {
159 { &sh4202_superhyway_ops
, },
163 int __init
superhyway_scan_bus(struct superhyway_bus
*bus
)
165 return superhyway_add_devices(bus
, sh4202_devices
,
166 ARRAY_SIZE(sh4202_devices
));