Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | // SPDX-License-Identifier: GPL-2.0 /* * arch/sh/drivers/superhyway/ops-sh4-202.c * * SuperHyway bus support for SH4-202 * * Copyright (C) 2005 Paul Mundt */ #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 preceding VCRL. * * Do not trust the documentation, for it is evil. */ vcrh = __raw_readl(base); vcrl = __raw_readl(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; __raw_writel((tmp >> 32) & 0xffffffff, base); __raw_writel(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)); } |