2 * TI OMAP L4 interconnect emulation.
4 * Copyright (C) 2007-2009 Nokia Corporation
5 * Written by Andrzej Zaborowski <andrew@openedhand.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 or
10 * (at your option) any later version of the License.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, see <http://www.gnu.org/licenses/>.
24 static int omap_l4_io_entries
;
25 static int omap_cpu_io_entry
;
26 static struct omap_l4_entry
{
27 CPUReadMemoryFunc
* const *mem_read
;
28 CPUWriteMemoryFunc
* const *mem_write
;
31 static CPUReadMemoryFunc
* const *omap_l4_io_readb_fn
;
32 static CPUReadMemoryFunc
* const *omap_l4_io_readh_fn
;
33 static CPUReadMemoryFunc
* const *omap_l4_io_readw_fn
;
34 static CPUWriteMemoryFunc
* const *omap_l4_io_writeb_fn
;
35 static CPUWriteMemoryFunc
* const *omap_l4_io_writeh_fn
;
36 static CPUWriteMemoryFunc
* const *omap_l4_io_writew_fn
;
37 static void **omap_l4_io_opaque
;
39 int l4_register_io_memory(CPUReadMemoryFunc
* const *mem_read
,
40 CPUWriteMemoryFunc
* const *mem_write
, void *opaque
)
42 omap_l4_io_entry
[omap_l4_io_entries
].mem_read
= mem_read
;
43 omap_l4_io_entry
[omap_l4_io_entries
].mem_write
= mem_write
;
44 omap_l4_io_entry
[omap_l4_io_entries
].opaque
= opaque
;
46 return omap_l4_io_entries
++;
49 static uint32_t omap_l4_io_readb(void *opaque
, target_phys_addr_t addr
)
51 unsigned int i
= (addr
- OMAP2_L4_BASE
) >> TARGET_PAGE_BITS
;
53 return omap_l4_io_readb_fn
[i
](omap_l4_io_opaque
[i
], addr
);
56 static uint32_t omap_l4_io_readh(void *opaque
, target_phys_addr_t addr
)
58 unsigned int i
= (addr
- OMAP2_L4_BASE
) >> TARGET_PAGE_BITS
;
60 return omap_l4_io_readh_fn
[i
](omap_l4_io_opaque
[i
], addr
);
63 static uint32_t omap_l4_io_readw(void *opaque
, target_phys_addr_t addr
)
65 unsigned int i
= (addr
- OMAP2_L4_BASE
) >> TARGET_PAGE_BITS
;
67 return omap_l4_io_readw_fn
[i
](omap_l4_io_opaque
[i
], addr
);
70 static void omap_l4_io_writeb(void *opaque
, target_phys_addr_t addr
,
73 unsigned int i
= (addr
- OMAP2_L4_BASE
) >> TARGET_PAGE_BITS
;
75 return omap_l4_io_writeb_fn
[i
](omap_l4_io_opaque
[i
], addr
, value
);
78 static void omap_l4_io_writeh(void *opaque
, target_phys_addr_t addr
,
81 unsigned int i
= (addr
- OMAP2_L4_BASE
) >> TARGET_PAGE_BITS
;
83 return omap_l4_io_writeh_fn
[i
](omap_l4_io_opaque
[i
], addr
, value
);
86 static void omap_l4_io_writew(void *opaque
, target_phys_addr_t addr
,
89 unsigned int i
= (addr
- OMAP2_L4_BASE
) >> TARGET_PAGE_BITS
;
91 return omap_l4_io_writew_fn
[i
](omap_l4_io_opaque
[i
], addr
, value
);
94 static CPUReadMemoryFunc
* const omap_l4_io_readfn
[] = {
100 static CPUWriteMemoryFunc
* const omap_l4_io_writefn
[] = {
106 int l4_register_io_memory(CPUReadMemoryFunc
* const *mem_read
,
107 CPUWriteMemoryFunc
* const *mem_write
,
110 return cpu_register_io_memory(mem_read
, mem_write
, opaque
,
111 DEVICE_NATIVE_ENDIAN
);
116 target_phys_addr_t base
;
118 struct omap_target_agent_s ta
[0];
121 struct omap_l4_s
*omap_l4_init(target_phys_addr_t base
, int ta_num
)
123 struct omap_l4_s
*bus
= qemu_mallocz(
124 sizeof(*bus
) + ta_num
* sizeof(*bus
->ta
));
126 bus
->ta_num
= ta_num
;
130 omap_l4_io_entries
= 1;
131 omap_l4_io_entry
= qemu_mallocz(125 * sizeof(*omap_l4_io_entry
));
134 cpu_register_io_memory(omap_l4_io_readfn
,
135 omap_l4_io_writefn
, bus
, DEVICE_NATIVE_ENDIAN
);
136 # define L4_PAGES (0xb4000 / TARGET_PAGE_SIZE)
137 omap_l4_io_readb_fn
= qemu_mallocz(sizeof(void *) * L4_PAGES
);
138 omap_l4_io_readh_fn
= qemu_mallocz(sizeof(void *) * L4_PAGES
);
139 omap_l4_io_readw_fn
= qemu_mallocz(sizeof(void *) * L4_PAGES
);
140 omap_l4_io_writeb_fn
= qemu_mallocz(sizeof(void *) * L4_PAGES
);
141 omap_l4_io_writeh_fn
= qemu_mallocz(sizeof(void *) * L4_PAGES
);
142 omap_l4_io_writew_fn
= qemu_mallocz(sizeof(void *) * L4_PAGES
);
143 omap_l4_io_opaque
= qemu_mallocz(sizeof(void *) * L4_PAGES
);
149 target_phys_addr_t
omap_l4_region_base(struct omap_target_agent_s
*ta
,
152 return ta
->bus
->base
+ ta
->start
[region
].offset
;
155 static uint32_t omap_l4ta_read(void *opaque
, target_phys_addr_t addr
)
157 struct omap_target_agent_s
*s
= (struct omap_target_agent_s
*) opaque
;
160 case 0x00: /* COMPONENT */
163 case 0x20: /* AGENT_CONTROL */
166 case 0x28: /* AGENT_STATUS */
174 static void omap_l4ta_write(void *opaque
, target_phys_addr_t addr
,
177 struct omap_target_agent_s
*s
= (struct omap_target_agent_s
*) opaque
;
180 case 0x00: /* COMPONENT */
181 case 0x28: /* AGENT_STATUS */
185 case 0x20: /* AGENT_CONTROL */
186 s
->control
= value
& 0x01000700;
187 if (value
& 1) /* OCP_RESET */
188 s
->status
&= ~1; /* REQ_TIMEOUT */
196 static CPUReadMemoryFunc
* const omap_l4ta_readfn
[] = {
197 omap_badwidth_read16
,
199 omap_badwidth_read16
,
202 static CPUWriteMemoryFunc
* const omap_l4ta_writefn
[] = {
203 omap_badwidth_write32
,
204 omap_badwidth_write32
,
208 struct omap_target_agent_s
*omap_l4ta_get(struct omap_l4_s
*bus
,
209 const struct omap_l4_region_s
*regions
,
210 const struct omap_l4_agent_info_s
*agents
,
214 struct omap_target_agent_s
*ta
= NULL
;
215 const struct omap_l4_agent_info_s
*info
= NULL
;
217 for (i
= 0; i
< bus
->ta_num
; i
++)
218 if (agents
[i
].ta
== cs
) {
224 fprintf(stderr
, "%s: bad target agent (%i)\n", __FUNCTION__
, cs
);
229 ta
->start
= ®ions
[info
->region
];
230 ta
->regions
= info
->regions
;
232 ta
->component
= ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
233 ta
->status
= 0x00000000;
234 ta
->control
= 0x00000200; /* XXX 01000200 for L4TAO */
236 iomemtype
= l4_register_io_memory(omap_l4ta_readfn
,
237 omap_l4ta_writefn
, ta
);
238 ta
->base
= omap_l4_attach(ta
, info
->ta_region
, iomemtype
);
243 target_phys_addr_t
omap_l4_attach(struct omap_target_agent_s
*ta
, int region
,
246 target_phys_addr_t base
;
252 if (region
< 0 || region
>= ta
->regions
) {
253 fprintf(stderr
, "%s: bad io region (%i)\n", __FUNCTION__
, region
);
257 base
= ta
->bus
->base
+ ta
->start
[region
].offset
;
258 size
= ta
->start
[region
].size
;
261 cpu_register_physical_memory(base
, size
, iotype
);
263 cpu_register_physical_memory(base
, size
, omap_cpu_io_entry
);
264 i
= (base
- ta
->bus
->base
) / TARGET_PAGE_SIZE
;
265 for (; size
> 0; size
-= TARGET_PAGE_SIZE
, i
++) {
266 omap_l4_io_readb_fn
[i
] = omap_l4_io_entry
[iotype
].mem_read
[0];
267 omap_l4_io_readh_fn
[i
] = omap_l4_io_entry
[iotype
].mem_read
[1];
268 omap_l4_io_readw_fn
[i
] = omap_l4_io_entry
[iotype
].mem_read
[2];
269 omap_l4_io_writeb_fn
[i
] = omap_l4_io_entry
[iotype
].mem_write
[0];
270 omap_l4_io_writeh_fn
[i
] = omap_l4_io_entry
[iotype
].mem_write
[1];
271 omap_l4_io_writew_fn
[i
] = omap_l4_io_entry
[iotype
].mem_write
[2];
272 omap_l4_io_opaque
[i
] = omap_l4_io_entry
[iotype
].opaque
;