2 * TI OMAP3 High-Speed USB Host and OTG Controller emulation.
4 * Copyright (C) 2009 Nokia Corporation
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 or
9 * (at your option) version 3 of the License.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "qemu-common.h"
21 #include "qemu-timer.h"
27 #define OMAP3_HSUSB_DEBUG
29 #ifdef OMAP3_HSUSB_DEBUG
30 #define TRACE(fmt,...) fprintf(stderr, "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
35 extern CPUReadMemoryFunc *musb_read[];
36 extern CPUWriteMemoryFunc *musb_write[];
38 struct omap3_hsusb_otg_s {
50 static void omap3_hsusb_otg_reset(struct omap3_hsusb_otg_s *s)
59 static uint32_t omap3_hsusb_otg_readb(void *opaque, target_phys_addr_t addr)
61 struct omap3_hsusb_otg_s *s = (struct omap3_hsusb_otg_s *)opaque;
63 return musb_read[0](s->musb, addr);
65 return musb_read[0](s->musb, 0x20 + ((addr >> 3 ) & 0x3c));
70 static uint32_t omap3_hsusb_otg_readh(void *opaque, target_phys_addr_t addr)
72 struct omap3_hsusb_otg_s *s = (struct omap3_hsusb_otg_s *)opaque;
74 return musb_read[1](s->musb, addr);
76 return musb_read[1](s->musb, 0x20 + ((addr >> 3 ) & 0x3c));
81 static uint32_t omap3_hsusb_otg_read(void *opaque, target_phys_addr_t addr)
83 struct omap3_hsusb_otg_s *s = (struct omap3_hsusb_otg_s *)opaque;
86 return musb_read[2](s->musb, addr);
88 return musb_read[2](s->musb, 0x20 + ((addr >> 3 ) & 0x3c));
91 case 0x400: /* OTG_REVISION */
92 TRACE("OTG_REVISION: 0x%08x", s->rev);
94 case 0x404: /* OTG_SYSCONFIG */
95 TRACE("OTG_SYSCONFIG: 0x%08x", s->sysconfig);
97 case 0x408: /* OTG_SYSSTATUS */
98 TRACE("OTG_SYSSTATUS: 0x00000001");
99 return 1; /* reset finished */
100 case 0x40c: /* OTG_INTERFSEL */
101 TRACE("OTG_INTERFSEL: 0x%08x", s->interfsel);
103 case 0x410: /* OTG_SIMENABLE */
104 TRACE("OTG_SIMENABLE: 0x%08x", s->simenable);
106 case 0x414: /* OTG_FORCESTDBY */
107 TRACE("OTG_FORCESTDBY: 0x%08x", s->forcestdby);
108 return s->forcestdby;
116 static void omap3_hsusb_otg_writeb(void *opaque, target_phys_addr_t addr,
119 struct omap3_hsusb_otg_s *s = (struct omap3_hsusb_otg_s *)opaque;
122 musb_write[0](s->musb, addr, value);
123 else if (addr < 0x400)
124 musb_write[0](s->musb, 0x20 + ((addr >> 3) & 0x3c), value);
129 static void omap3_hsusb_otg_writeh(void *opaque, target_phys_addr_t addr,
132 struct omap3_hsusb_otg_s *s = (struct omap3_hsusb_otg_s *)opaque;
135 musb_write[1](s->musb, addr, value);
136 else if (addr < 0x400)
137 musb_write[1](s->musb, 0x20 + ((addr >> 3) & 0x3c), value);
142 static void omap3_hsusb_otg_write(void *opaque, target_phys_addr_t addr,
145 struct omap3_hsusb_otg_s *s = (struct omap3_hsusb_otg_s *)opaque;
148 musb_write[1](s->musb, addr, value);
149 else if (addr < 0x400)
150 musb_write[1](s->musb, 0x20 + ((addr >> 3) & 0x3c), value);
152 case 0x400: /* OTG_REVISION */
153 case 0x408: /* OTG_SYSSTATUS */
154 OMAP_RO_REGV(addr, value);
156 case 0x404: /* OTG_SYSCONFIG */
157 TRACE("OTG_SYSCONFIG = 0x%08x", value);
158 if (value & 2) /* SOFTRESET */
159 omap3_hsusb_otg_reset(s);
160 s->sysconfig = value & 0x301f;
162 case 0x40c: /* OTG_INTERFSEL */
163 TRACE("OTG_INTERFSEL = 0x%08x", value);
164 s->interfsel = value & 0x3;
166 case 0x410: /* OTG_SIMENABLE */
167 TRACE("OTG_SIMENABLE = 0x%08x", value);
168 s->simenable = value & 1;
170 case 0x414: /* OTG_FORCESTDBY */
171 TRACE("OTG_FORCESTDBY = 0x%08x", value);
172 s->forcestdby = value & 1;
175 OMAP_BAD_REGV(addr, value);
180 static CPUReadMemoryFunc *omap3_hsusb_otg_readfn[] = {
181 omap3_hsusb_otg_readb,
182 omap3_hsusb_otg_readh,
183 omap3_hsusb_otg_read,
186 static CPUWriteMemoryFunc *omap3_hsusb_otg_writefn[] = {
187 omap3_hsusb_otg_writeb,
188 omap3_hsusb_otg_writeh,
189 omap3_hsusb_otg_write,
192 static void omap3_hsusb_musb_core_intr(void *opaque, int source, int level)
194 struct omap3_hsusb_otg_s *s = (struct omap3_hsusb_otg_s *)opaque;
196 qemu_set_irq(s->mc_irq, musb_core_intr_get(s->musb));
199 static void omap3_hsusb_otg_init(struct omap_target_agent_s *otg_ta,
202 struct omap3_hsusb_otg_s *s)
205 s->dma_irq = dma_irq;
207 omap_l4_attach(otg_ta, 0, l4_register_io_memory(0, omap3_hsusb_otg_readfn,
208 omap3_hsusb_otg_writefn, s));
210 s->musb = musb_init(qemu_allocate_irqs(omap3_hsusb_musb_core_intr, s, __musb_irq_max));
211 omap3_hsusb_otg_reset(s);
214 struct omap3_hsusb_host_s {
224 static uint32_t omap3_hsusb_host_read(void *opaque, target_phys_addr_t addr)
226 TRACE("0x%04x", addr);
230 static void omap3_hsusb_host_write(void *opaque, target_phys_addr_t addr,
233 TRACE("0x%04x = 0x%08x", addr, value);
236 static CPUReadMemoryFunc *omap3_hsusb_host_readfn[] = {
237 omap_badwidth_read32,
238 omap_badwidth_read32,
239 omap3_hsusb_host_read,
242 static CPUWriteMemoryFunc *omap3_hsusb_host_writefn[] = {
243 omap_badwidth_write32,
244 omap_badwidth_write32,
245 omap3_hsusb_host_write,
248 static uint32_t omap3_hsusb_tll_read(void *opaque, target_phys_addr_t addr)
250 TRACE("0x%04x", addr);
254 static void omap3_hsusb_tll_write(void *opaque, target_phys_addr_t addr,
257 TRACE("0x%04x = 0x%08x", addr, value);
260 static CPUReadMemoryFunc *omap3_hsusb_tll_readfn[] = {
261 omap_badwidth_read32,
262 omap_badwidth_read32,
263 omap3_hsusb_tll_read,
266 static CPUWriteMemoryFunc *omap3_hsusb_tll_writefn[] = {
267 omap_badwidth_write32,
268 omap_badwidth_write32,
269 omap3_hsusb_tll_write,
272 static void omap3_hsusb_host_init(struct omap_target_agent_s *host_ta,
273 struct omap_target_agent_s *tll_ta,
277 struct omap3_hsusb_host_s *s)
279 s->hc.ohci_irq = ohci_irq;
280 s->hc.ehci_irq = ehci_irq;
281 s->tll.irq = tll_irq;
283 omap_l4_attach(host_ta, 0, l4_register_io_memory(0, omap3_hsusb_host_readfn,
284 omap3_hsusb_host_writefn, s));
285 omap_l4_attach(tll_ta, 0, l4_register_io_memory(0, omap3_hsusb_tll_readfn,
286 omap3_hsusb_tll_writefn, s));
289 struct omap3_hsusb_s {
290 struct omap3_hsusb_otg_s otg;
291 struct omap3_hsusb_host_s host;
294 struct omap3_hsusb_s *omap3_hsusb_init(struct omap_target_agent_s *otg_ta,
295 struct omap_target_agent_s *host_ta,
296 struct omap_target_agent_s *tll_ta,
303 struct omap3_hsusb_s *s = qemu_mallocz(sizeof(struct omap3_hsusb_s));
304 omap3_hsusb_otg_init(otg_ta, mc_irq, dma_irq, &s->otg);
305 omap3_hsusb_host_init(host_ta, tll_ta, ohci_irq, ehci_irq, tll_irq, &s->host);