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
);
115 target_phys_addr_t base
;
117 struct omap_target_agent_s ta
[0];
120 struct omap_l4_s
*omap_l4_init(target_phys_addr_t base
, int ta_num
)
122 struct omap_l4_s
*bus
= qemu_mallocz(
123 sizeof(*bus
) + ta_num
* sizeof(*bus
->ta
));
125 bus
->ta_num
= ta_num
;
129 omap_l4_io_entries
= 1;
130 omap_l4_io_entry
= qemu_mallocz(125 * sizeof(*omap_l4_io_entry
));
133 cpu_register_io_memory(omap_l4_io_readfn
,
134 omap_l4_io_writefn
, bus
);
135 # define L4_PAGES (0xb4000 / TARGET_PAGE_SIZE)
136 omap_l4_io_readb_fn
= qemu_mallocz(sizeof(void *) * L4_PAGES
);
137 omap_l4_io_readh_fn
= qemu_mallocz(sizeof(void *) * L4_PAGES
);
138 omap_l4_io_readw_fn
= qemu_mallocz(sizeof(void *) * L4_PAGES
);
139 omap_l4_io_writeb_fn
= qemu_mallocz(sizeof(void *) * L4_PAGES
);
140 omap_l4_io_writeh_fn
= qemu_mallocz(sizeof(void *) * L4_PAGES
);
141 omap_l4_io_writew_fn
= qemu_mallocz(sizeof(void *) * L4_PAGES
);
142 omap_l4_io_opaque
= qemu_mallocz(sizeof(void *) * L4_PAGES
);
148 static uint32_t omap_l4ta_read(void *opaque
, target_phys_addr_t addr
)
150 struct omap_target_agent_s
*s
= (struct omap_target_agent_s
*) opaque
;
153 case 0x00: /* COMPONENT */
156 case 0x20: /* AGENT_CONTROL */
159 case 0x28: /* AGENT_STATUS */
167 static void omap_l4ta_write(void *opaque
, target_phys_addr_t addr
,
170 struct omap_target_agent_s
*s
= (struct omap_target_agent_s
*) opaque
;
173 case 0x00: /* COMPONENT */
174 case 0x28: /* AGENT_STATUS */
178 case 0x20: /* AGENT_CONTROL */
179 s
->control
= value
& 0x01000700;
180 if (value
& 1) /* OCP_RESET */
181 s
->status
&= ~1; /* REQ_TIMEOUT */
189 static CPUReadMemoryFunc
* const omap_l4ta_readfn
[] = {
190 omap_badwidth_read16
,
192 omap_badwidth_read16
,
195 static CPUWriteMemoryFunc
* const omap_l4ta_writefn
[] = {
196 omap_badwidth_write32
,
197 omap_badwidth_write32
,
201 struct omap_target_agent_s
*omap_l4ta_get(struct omap_l4_s
*bus
,
202 const struct omap_l4_region_s
*regions
,
203 const struct omap_l4_agent_info_s
*agents
,
207 struct omap_target_agent_s
*ta
= NULL
;
208 const struct omap_l4_agent_info_s
*info
= NULL
;
210 for (i
= 0; i
< bus
->ta_num
; i
++)
211 if (agents
[i
].ta
== cs
) {
217 fprintf(stderr
, "%s: bad target agent (%i)\n", __FUNCTION__
, cs
);
222 ta
->start
= ®ions
[info
->region
];
223 ta
->regions
= info
->regions
;
225 ta
->component
= ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
226 ta
->status
= 0x00000000;
227 ta
->control
= 0x00000200; /* XXX 01000200 for L4TAO */
229 iomemtype
= l4_register_io_memory(omap_l4ta_readfn
,
230 omap_l4ta_writefn
, ta
);
231 ta
->base
= omap_l4_attach(ta
, info
->ta_region
, iomemtype
);
236 target_phys_addr_t
omap_l4_attach(struct omap_target_agent_s
*ta
, int region
,
239 target_phys_addr_t base
;
245 if (region
< 0 || region
>= ta
->regions
) {
246 fprintf(stderr
, "%s: bad io region (%i)\n", __FUNCTION__
, region
);
250 base
= ta
->bus
->base
+ ta
->start
[region
].offset
;
251 size
= ta
->start
[region
].size
;
254 cpu_register_physical_memory(base
, size
, iotype
);
256 cpu_register_physical_memory(base
, size
, omap_cpu_io_entry
);
257 i
= (base
- ta
->bus
->base
) / TARGET_PAGE_SIZE
;
258 for (; size
> 0; size
-= TARGET_PAGE_SIZE
, i
++) {
259 omap_l4_io_readb_fn
[i
] = omap_l4_io_entry
[iotype
].mem_read
[0];
260 omap_l4_io_readh_fn
[i
] = omap_l4_io_entry
[iotype
].mem_read
[1];
261 omap_l4_io_readw_fn
[i
] = omap_l4_io_entry
[iotype
].mem_read
[2];
262 omap_l4_io_writeb_fn
[i
] = omap_l4_io_entry
[iotype
].mem_write
[0];
263 omap_l4_io_writeh_fn
[i
] = omap_l4_io_entry
[iotype
].mem_write
[1];
264 omap_l4_io_writew_fn
[i
] = omap_l4_io_entry
[iotype
].mem_write
[2];
265 omap_l4_io_opaque
[i
] = omap_l4_io_entry
[iotype
].opaque
;