Statistics
| Branch: | Revision:

root / hw / omap2.c @ 6693665a

History | View | Annotate | Download (141.9 kB)

1 827df9f3 balrog
/*
2 827df9f3 balrog
 * TI OMAP processors emulation.
3 827df9f3 balrog
 *
4 827df9f3 balrog
 * Copyright (C) 2007-2008 Nokia Corporation
5 827df9f3 balrog
 * Written by Andrzej Zaborowski <andrew@openedhand.com>
6 827df9f3 balrog
 *
7 827df9f3 balrog
 * This program is free software; you can redistribute it and/or
8 827df9f3 balrog
 * modify it under the terms of the GNU General Public License as
9 827df9f3 balrog
 * published by the Free Software Foundation; either version 2 or
10 827df9f3 balrog
 * (at your option) version 3 of the License.
11 827df9f3 balrog
 *
12 827df9f3 balrog
 * This program is distributed in the hope that it will be useful,
13 827df9f3 balrog
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 827df9f3 balrog
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 827df9f3 balrog
 * GNU General Public License for more details.
16 827df9f3 balrog
 *
17 fad6cb1a aurel32
 * You should have received a copy of the GNU General Public License along
18 fad6cb1a aurel32
 * with this program; if not, write to the Free Software Foundation, Inc.,
19 fad6cb1a aurel32
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 827df9f3 balrog
 */
21 827df9f3 balrog
#include "hw.h"
22 827df9f3 balrog
#include "arm-misc.h"
23 827df9f3 balrog
#include "omap.h"
24 827df9f3 balrog
#include "sysemu.h"
25 827df9f3 balrog
#include "qemu-timer.h"
26 827df9f3 balrog
#include "qemu-char.h"
27 827df9f3 balrog
#include "flash.h"
28 afbb5194 balrog
#include "soc_dma.h"
29 99570a40 balrog
#include "audio/audio.h"
30 827df9f3 balrog
31 827df9f3 balrog
/* GP timers */
32 827df9f3 balrog
struct omap_gp_timer_s {
33 827df9f3 balrog
    qemu_irq irq;
34 827df9f3 balrog
    qemu_irq wkup;
35 827df9f3 balrog
    qemu_irq in;
36 827df9f3 balrog
    qemu_irq out;
37 827df9f3 balrog
    omap_clk clk;
38 827df9f3 balrog
    QEMUTimer *timer;
39 827df9f3 balrog
    QEMUTimer *match;
40 827df9f3 balrog
    struct omap_target_agent_s *ta;
41 827df9f3 balrog
42 827df9f3 balrog
    int in_val;
43 827df9f3 balrog
    int out_val;
44 827df9f3 balrog
    int64_t time;
45 827df9f3 balrog
    int64_t rate;
46 827df9f3 balrog
    int64_t ticks_per_sec;
47 827df9f3 balrog
48 827df9f3 balrog
    int16_t config;
49 827df9f3 balrog
    int status;
50 827df9f3 balrog
    int it_ena;
51 827df9f3 balrog
    int wu_ena;
52 827df9f3 balrog
    int enable;
53 827df9f3 balrog
    int inout;
54 827df9f3 balrog
    int capt2;
55 827df9f3 balrog
    int pt;
56 827df9f3 balrog
    enum {
57 827df9f3 balrog
        gpt_trigger_none, gpt_trigger_overflow, gpt_trigger_both
58 827df9f3 balrog
    } trigger;
59 827df9f3 balrog
    enum {
60 827df9f3 balrog
        gpt_capture_none, gpt_capture_rising,
61 827df9f3 balrog
        gpt_capture_falling, gpt_capture_both
62 827df9f3 balrog
    } capture;
63 827df9f3 balrog
    int scpwm;
64 827df9f3 balrog
    int ce;
65 827df9f3 balrog
    int pre;
66 827df9f3 balrog
    int ptv;
67 827df9f3 balrog
    int ar;
68 827df9f3 balrog
    int st;
69 827df9f3 balrog
    int posted;
70 827df9f3 balrog
    uint32_t val;
71 827df9f3 balrog
    uint32_t load_val;
72 827df9f3 balrog
    uint32_t capture_val[2];
73 827df9f3 balrog
    uint32_t match_val;
74 827df9f3 balrog
    int capt_num;
75 827df9f3 balrog
76 827df9f3 balrog
    uint16_t writeh;        /* LSB */
77 827df9f3 balrog
    uint16_t readh;        /* MSB */
78 827df9f3 balrog
};
79 827df9f3 balrog
80 827df9f3 balrog
#define GPT_TCAR_IT        (1 << 2)
81 827df9f3 balrog
#define GPT_OVF_IT        (1 << 1)
82 827df9f3 balrog
#define GPT_MAT_IT        (1 << 0)
83 827df9f3 balrog
84 827df9f3 balrog
static inline void omap_gp_timer_intr(struct omap_gp_timer_s *timer, int it)
85 827df9f3 balrog
{
86 827df9f3 balrog
    if (timer->it_ena & it) {
87 827df9f3 balrog
        if (!timer->status)
88 827df9f3 balrog
            qemu_irq_raise(timer->irq);
89 827df9f3 balrog
90 827df9f3 balrog
        timer->status |= it;
91 827df9f3 balrog
        /* Or are the status bits set even when masked?
92 827df9f3 balrog
         * i.e. is masking applied before or after the status register?  */
93 827df9f3 balrog
    }
94 827df9f3 balrog
95 827df9f3 balrog
    if (timer->wu_ena & it)
96 827df9f3 balrog
        qemu_irq_pulse(timer->wkup);
97 827df9f3 balrog
}
98 827df9f3 balrog
99 827df9f3 balrog
static inline void omap_gp_timer_out(struct omap_gp_timer_s *timer, int level)
100 827df9f3 balrog
{
101 827df9f3 balrog
    if (!timer->inout && timer->out_val != level) {
102 827df9f3 balrog
        timer->out_val = level;
103 827df9f3 balrog
        qemu_set_irq(timer->out, level);
104 827df9f3 balrog
    }
105 827df9f3 balrog
}
106 827df9f3 balrog
107 827df9f3 balrog
static inline uint32_t omap_gp_timer_read(struct omap_gp_timer_s *timer)
108 827df9f3 balrog
{
109 827df9f3 balrog
    uint64_t distance;
110 827df9f3 balrog
111 827df9f3 balrog
    if (timer->st && timer->rate) {
112 827df9f3 balrog
        distance = qemu_get_clock(vm_clock) - timer->time;
113 827df9f3 balrog
        distance = muldiv64(distance, timer->rate, timer->ticks_per_sec);
114 827df9f3 balrog
115 827df9f3 balrog
        if (distance >= 0xffffffff - timer->val)
116 827df9f3 balrog
            return 0xffffffff;
117 827df9f3 balrog
        else
118 827df9f3 balrog
            return timer->val + distance;
119 827df9f3 balrog
    } else
120 827df9f3 balrog
        return timer->val;
121 827df9f3 balrog
}
122 827df9f3 balrog
123 827df9f3 balrog
static inline void omap_gp_timer_sync(struct omap_gp_timer_s *timer)
124 827df9f3 balrog
{
125 827df9f3 balrog
    if (timer->st) {
126 827df9f3 balrog
        timer->val = omap_gp_timer_read(timer);
127 827df9f3 balrog
        timer->time = qemu_get_clock(vm_clock);
128 827df9f3 balrog
    }
129 827df9f3 balrog
}
130 827df9f3 balrog
131 827df9f3 balrog
static inline void omap_gp_timer_update(struct omap_gp_timer_s *timer)
132 827df9f3 balrog
{
133 827df9f3 balrog
    int64_t expires, matches;
134 827df9f3 balrog
135 827df9f3 balrog
    if (timer->st && timer->rate) {
136 827df9f3 balrog
        expires = muldiv64(0x100000000ll - timer->val,
137 827df9f3 balrog
                        timer->ticks_per_sec, timer->rate);
138 827df9f3 balrog
        qemu_mod_timer(timer->timer, timer->time + expires);
139 827df9f3 balrog
140 827df9f3 balrog
        if (timer->ce && timer->match_val >= timer->val) {
141 827df9f3 balrog
            matches = muldiv64(timer->match_val - timer->val,
142 827df9f3 balrog
                            timer->ticks_per_sec, timer->rate);
143 827df9f3 balrog
            qemu_mod_timer(timer->match, timer->time + matches);
144 827df9f3 balrog
        } else
145 827df9f3 balrog
            qemu_del_timer(timer->match);
146 827df9f3 balrog
    } else {
147 827df9f3 balrog
        qemu_del_timer(timer->timer);
148 827df9f3 balrog
        qemu_del_timer(timer->match);
149 827df9f3 balrog
        omap_gp_timer_out(timer, timer->scpwm);
150 827df9f3 balrog
    }
151 827df9f3 balrog
}
152 827df9f3 balrog
153 827df9f3 balrog
static inline void omap_gp_timer_trigger(struct omap_gp_timer_s *timer)
154 827df9f3 balrog
{
155 827df9f3 balrog
    if (timer->pt)
156 827df9f3 balrog
        /* TODO in overflow-and-match mode if the first event to
157 75554a3c balrog
         * occur is the match, don't toggle.  */
158 827df9f3 balrog
        omap_gp_timer_out(timer, !timer->out_val);
159 827df9f3 balrog
    else
160 827df9f3 balrog
        /* TODO inverted pulse on timer->out_val == 1?  */
161 827df9f3 balrog
        qemu_irq_pulse(timer->out);
162 827df9f3 balrog
}
163 827df9f3 balrog
164 827df9f3 balrog
static void omap_gp_timer_tick(void *opaque)
165 827df9f3 balrog
{
166 827df9f3 balrog
    struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
167 827df9f3 balrog
168 827df9f3 balrog
    if (!timer->ar) {
169 827df9f3 balrog
        timer->st = 0;
170 827df9f3 balrog
        timer->val = 0;
171 827df9f3 balrog
    } else {
172 827df9f3 balrog
        timer->val = timer->load_val;
173 827df9f3 balrog
        timer->time = qemu_get_clock(vm_clock);
174 827df9f3 balrog
    }
175 827df9f3 balrog
176 827df9f3 balrog
    if (timer->trigger == gpt_trigger_overflow ||
177 827df9f3 balrog
                    timer->trigger == gpt_trigger_both)
178 827df9f3 balrog
        omap_gp_timer_trigger(timer);
179 827df9f3 balrog
180 827df9f3 balrog
    omap_gp_timer_intr(timer, GPT_OVF_IT);
181 827df9f3 balrog
    omap_gp_timer_update(timer);
182 827df9f3 balrog
}
183 827df9f3 balrog
184 827df9f3 balrog
static void omap_gp_timer_match(void *opaque)
185 827df9f3 balrog
{
186 827df9f3 balrog
    struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
187 827df9f3 balrog
188 827df9f3 balrog
    if (timer->trigger == gpt_trigger_both)
189 827df9f3 balrog
        omap_gp_timer_trigger(timer);
190 827df9f3 balrog
191 827df9f3 balrog
    omap_gp_timer_intr(timer, GPT_MAT_IT);
192 827df9f3 balrog
}
193 827df9f3 balrog
194 827df9f3 balrog
static void omap_gp_timer_input(void *opaque, int line, int on)
195 827df9f3 balrog
{
196 827df9f3 balrog
    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
197 827df9f3 balrog
    int trigger;
198 827df9f3 balrog
199 827df9f3 balrog
    switch (s->capture) {
200 827df9f3 balrog
    default:
201 827df9f3 balrog
    case gpt_capture_none:
202 827df9f3 balrog
        trigger = 0;
203 827df9f3 balrog
        break;
204 827df9f3 balrog
    case gpt_capture_rising:
205 827df9f3 balrog
        trigger = !s->in_val && on;
206 827df9f3 balrog
        break;
207 827df9f3 balrog
    case gpt_capture_falling:
208 827df9f3 balrog
        trigger = s->in_val && !on;
209 827df9f3 balrog
        break;
210 827df9f3 balrog
    case gpt_capture_both:
211 827df9f3 balrog
        trigger = (s->in_val == !on);
212 827df9f3 balrog
        break;
213 827df9f3 balrog
    }
214 827df9f3 balrog
    s->in_val = on;
215 827df9f3 balrog
216 827df9f3 balrog
    if (s->inout && trigger && s->capt_num < 2) {
217 827df9f3 balrog
        s->capture_val[s->capt_num] = omap_gp_timer_read(s);
218 827df9f3 balrog
219 827df9f3 balrog
        if (s->capt2 == s->capt_num ++)
220 827df9f3 balrog
            omap_gp_timer_intr(s, GPT_TCAR_IT);
221 827df9f3 balrog
    }
222 827df9f3 balrog
}
223 827df9f3 balrog
224 827df9f3 balrog
static void omap_gp_timer_clk_update(void *opaque, int line, int on)
225 827df9f3 balrog
{
226 827df9f3 balrog
    struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
227 827df9f3 balrog
228 827df9f3 balrog
    omap_gp_timer_sync(timer);
229 827df9f3 balrog
    timer->rate = on ? omap_clk_getrate(timer->clk) : 0;
230 827df9f3 balrog
    omap_gp_timer_update(timer);
231 827df9f3 balrog
}
232 827df9f3 balrog
233 827df9f3 balrog
static void omap_gp_timer_clk_setup(struct omap_gp_timer_s *timer)
234 827df9f3 balrog
{
235 827df9f3 balrog
    omap_clk_adduser(timer->clk,
236 827df9f3 balrog
                    qemu_allocate_irqs(omap_gp_timer_clk_update, timer, 1)[0]);
237 827df9f3 balrog
    timer->rate = omap_clk_getrate(timer->clk);
238 827df9f3 balrog
}
239 827df9f3 balrog
240 827df9f3 balrog
static void omap_gp_timer_reset(struct omap_gp_timer_s *s)
241 827df9f3 balrog
{
242 827df9f3 balrog
    s->config = 0x000;
243 827df9f3 balrog
    s->status = 0;
244 827df9f3 balrog
    s->it_ena = 0;
245 827df9f3 balrog
    s->wu_ena = 0;
246 827df9f3 balrog
    s->inout = 0;
247 827df9f3 balrog
    s->capt2 = 0;
248 827df9f3 balrog
    s->capt_num = 0;
249 827df9f3 balrog
    s->pt = 0;
250 827df9f3 balrog
    s->trigger = gpt_trigger_none;
251 827df9f3 balrog
    s->capture = gpt_capture_none;
252 827df9f3 balrog
    s->scpwm = 0;
253 827df9f3 balrog
    s->ce = 0;
254 827df9f3 balrog
    s->pre = 0;
255 827df9f3 balrog
    s->ptv = 0;
256 827df9f3 balrog
    s->ar = 0;
257 827df9f3 balrog
    s->st = 0;
258 827df9f3 balrog
    s->posted = 1;
259 827df9f3 balrog
    s->val = 0x00000000;
260 827df9f3 balrog
    s->load_val = 0x00000000;
261 827df9f3 balrog
    s->capture_val[0] = 0x00000000;
262 827df9f3 balrog
    s->capture_val[1] = 0x00000000;
263 827df9f3 balrog
    s->match_val = 0x00000000;
264 827df9f3 balrog
    omap_gp_timer_update(s);
265 827df9f3 balrog
}
266 827df9f3 balrog
267 827df9f3 balrog
static uint32_t omap_gp_timer_readw(void *opaque, target_phys_addr_t addr)
268 827df9f3 balrog
{
269 827df9f3 balrog
    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
270 827df9f3 balrog
271 8da3ff18 pbrook
    switch (addr) {
272 827df9f3 balrog
    case 0x00:        /* TIDR */
273 827df9f3 balrog
        return 0x21;
274 827df9f3 balrog
275 827df9f3 balrog
    case 0x10:        /* TIOCP_CFG */
276 827df9f3 balrog
        return s->config;
277 827df9f3 balrog
278 827df9f3 balrog
    case 0x14:        /* TISTAT */
279 827df9f3 balrog
        /* ??? When's this bit reset? */
280 827df9f3 balrog
        return 1;                                                /* RESETDONE */
281 827df9f3 balrog
282 827df9f3 balrog
    case 0x18:        /* TISR */
283 827df9f3 balrog
        return s->status;
284 827df9f3 balrog
285 827df9f3 balrog
    case 0x1c:        /* TIER */
286 827df9f3 balrog
        return s->it_ena;
287 827df9f3 balrog
288 827df9f3 balrog
    case 0x20:        /* TWER */
289 827df9f3 balrog
        return s->wu_ena;
290 827df9f3 balrog
291 827df9f3 balrog
    case 0x24:        /* TCLR */
292 827df9f3 balrog
        return (s->inout << 14) |
293 827df9f3 balrog
                (s->capt2 << 13) |
294 827df9f3 balrog
                (s->pt << 12) |
295 827df9f3 balrog
                (s->trigger << 10) |
296 827df9f3 balrog
                (s->capture << 8) |
297 827df9f3 balrog
                (s->scpwm << 7) |
298 827df9f3 balrog
                (s->ce << 6) |
299 827df9f3 balrog
                (s->pre << 5) |
300 827df9f3 balrog
                (s->ptv << 2) |
301 827df9f3 balrog
                (s->ar << 1) |
302 827df9f3 balrog
                (s->st << 0);
303 827df9f3 balrog
304 827df9f3 balrog
    case 0x28:        /* TCRR */
305 827df9f3 balrog
        return omap_gp_timer_read(s);
306 827df9f3 balrog
307 827df9f3 balrog
    case 0x2c:        /* TLDR */
308 827df9f3 balrog
        return s->load_val;
309 827df9f3 balrog
310 827df9f3 balrog
    case 0x30:        /* TTGR */
311 827df9f3 balrog
        return 0xffffffff;
312 827df9f3 balrog
313 827df9f3 balrog
    case 0x34:        /* TWPS */
314 827df9f3 balrog
        return 0x00000000;        /* No posted writes pending.  */
315 827df9f3 balrog
316 827df9f3 balrog
    case 0x38:        /* TMAR */
317 827df9f3 balrog
        return s->match_val;
318 827df9f3 balrog
319 827df9f3 balrog
    case 0x3c:        /* TCAR1 */
320 827df9f3 balrog
        return s->capture_val[0];
321 827df9f3 balrog
322 827df9f3 balrog
    case 0x40:        /* TSICR */
323 827df9f3 balrog
        return s->posted << 2;
324 827df9f3 balrog
325 827df9f3 balrog
    case 0x44:        /* TCAR2 */
326 827df9f3 balrog
        return s->capture_val[1];
327 827df9f3 balrog
    }
328 827df9f3 balrog
329 827df9f3 balrog
    OMAP_BAD_REG(addr);
330 827df9f3 balrog
    return 0;
331 827df9f3 balrog
}
332 827df9f3 balrog
333 827df9f3 balrog
static uint32_t omap_gp_timer_readh(void *opaque, target_phys_addr_t addr)
334 827df9f3 balrog
{
335 827df9f3 balrog
    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
336 827df9f3 balrog
    uint32_t ret;
337 827df9f3 balrog
338 827df9f3 balrog
    if (addr & 2)
339 827df9f3 balrog
        return s->readh;
340 827df9f3 balrog
    else {
341 827df9f3 balrog
        ret = omap_gp_timer_readw(opaque, addr);
342 827df9f3 balrog
        s->readh = ret >> 16;
343 827df9f3 balrog
        return ret & 0xffff;
344 827df9f3 balrog
    }
345 827df9f3 balrog
}
346 827df9f3 balrog
347 827df9f3 balrog
static CPUReadMemoryFunc *omap_gp_timer_readfn[] = {
348 827df9f3 balrog
    omap_badwidth_read32,
349 827df9f3 balrog
    omap_gp_timer_readh,
350 827df9f3 balrog
    omap_gp_timer_readw,
351 827df9f3 balrog
};
352 827df9f3 balrog
353 827df9f3 balrog
static void omap_gp_timer_write(void *opaque, target_phys_addr_t addr,
354 827df9f3 balrog
                uint32_t value)
355 827df9f3 balrog
{
356 827df9f3 balrog
    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
357 827df9f3 balrog
358 8da3ff18 pbrook
    switch (addr) {
359 827df9f3 balrog
    case 0x00:        /* TIDR */
360 827df9f3 balrog
    case 0x14:        /* TISTAT */
361 827df9f3 balrog
    case 0x34:        /* TWPS */
362 827df9f3 balrog
    case 0x3c:        /* TCAR1 */
363 827df9f3 balrog
    case 0x44:        /* TCAR2 */
364 827df9f3 balrog
        OMAP_RO_REG(addr);
365 827df9f3 balrog
        break;
366 827df9f3 balrog
367 827df9f3 balrog
    case 0x10:        /* TIOCP_CFG */
368 827df9f3 balrog
        s->config = value & 0x33d;
369 827df9f3 balrog
        if (((value >> 3) & 3) == 3)                                /* IDLEMODE */
370 827df9f3 balrog
            fprintf(stderr, "%s: illegal IDLEMODE value in TIOCP_CFG\n",
371 827df9f3 balrog
                            __FUNCTION__);
372 827df9f3 balrog
        if (value & 2)                                                /* SOFTRESET */
373 827df9f3 balrog
            omap_gp_timer_reset(s);
374 827df9f3 balrog
        break;
375 827df9f3 balrog
376 827df9f3 balrog
    case 0x18:        /* TISR */
377 827df9f3 balrog
        if (value & GPT_TCAR_IT)
378 827df9f3 balrog
            s->capt_num = 0;
379 827df9f3 balrog
        if (s->status && !(s->status &= ~value))
380 827df9f3 balrog
            qemu_irq_lower(s->irq);
381 827df9f3 balrog
        break;
382 827df9f3 balrog
383 827df9f3 balrog
    case 0x1c:        /* TIER */
384 827df9f3 balrog
        s->it_ena = value & 7;
385 827df9f3 balrog
        break;
386 827df9f3 balrog
387 827df9f3 balrog
    case 0x20:        /* TWER */
388 827df9f3 balrog
        s->wu_ena = value & 7;
389 827df9f3 balrog
        break;
390 827df9f3 balrog
391 827df9f3 balrog
    case 0x24:        /* TCLR */
392 827df9f3 balrog
        omap_gp_timer_sync(s);
393 827df9f3 balrog
        s->inout = (value >> 14) & 1;
394 827df9f3 balrog
        s->capt2 = (value >> 13) & 1;
395 827df9f3 balrog
        s->pt = (value >> 12) & 1;
396 827df9f3 balrog
        s->trigger = (value >> 10) & 3;
397 827df9f3 balrog
        if (s->capture == gpt_capture_none &&
398 827df9f3 balrog
                        ((value >> 8) & 3) != gpt_capture_none)
399 827df9f3 balrog
            s->capt_num = 0;
400 827df9f3 balrog
        s->capture = (value >> 8) & 3;
401 827df9f3 balrog
        s->scpwm = (value >> 7) & 1;
402 827df9f3 balrog
        s->ce = (value >> 6) & 1;
403 827df9f3 balrog
        s->pre = (value >> 5) & 1;
404 827df9f3 balrog
        s->ptv = (value >> 2) & 7;
405 827df9f3 balrog
        s->ar = (value >> 1) & 1;
406 827df9f3 balrog
        s->st = (value >> 0) & 1;
407 827df9f3 balrog
        if (s->inout && s->trigger != gpt_trigger_none)
408 827df9f3 balrog
            fprintf(stderr, "%s: GP timer pin must be an output "
409 827df9f3 balrog
                            "for this trigger mode\n", __FUNCTION__);
410 827df9f3 balrog
        if (!s->inout && s->capture != gpt_capture_none)
411 827df9f3 balrog
            fprintf(stderr, "%s: GP timer pin must be an input "
412 827df9f3 balrog
                            "for this capture mode\n", __FUNCTION__);
413 827df9f3 balrog
        if (s->trigger == gpt_trigger_none)
414 827df9f3 balrog
            omap_gp_timer_out(s, s->scpwm);
415 827df9f3 balrog
        /* TODO: make sure this doesn't overflow 32-bits */
416 827df9f3 balrog
        s->ticks_per_sec = ticks_per_sec << (s->pre ? s->ptv + 1 : 0);
417 827df9f3 balrog
        omap_gp_timer_update(s);
418 827df9f3 balrog
        break;
419 827df9f3 balrog
420 827df9f3 balrog
    case 0x28:        /* TCRR */
421 827df9f3 balrog
        s->time = qemu_get_clock(vm_clock);
422 827df9f3 balrog
        s->val = value;
423 827df9f3 balrog
        omap_gp_timer_update(s);
424 827df9f3 balrog
        break;
425 827df9f3 balrog
426 827df9f3 balrog
    case 0x2c:        /* TLDR */
427 827df9f3 balrog
        s->load_val = value;
428 827df9f3 balrog
        break;
429 827df9f3 balrog
430 827df9f3 balrog
    case 0x30:        /* TTGR */
431 827df9f3 balrog
        s->time = qemu_get_clock(vm_clock);
432 827df9f3 balrog
        s->val = s->load_val;
433 827df9f3 balrog
        omap_gp_timer_update(s);
434 827df9f3 balrog
        break;
435 827df9f3 balrog
436 827df9f3 balrog
    case 0x38:        /* TMAR */
437 827df9f3 balrog
        omap_gp_timer_sync(s);
438 827df9f3 balrog
        s->match_val = value;
439 827df9f3 balrog
        omap_gp_timer_update(s);
440 827df9f3 balrog
        break;
441 827df9f3 balrog
442 827df9f3 balrog
    case 0x40:        /* TSICR */
443 827df9f3 balrog
        s->posted = (value >> 2) & 1;
444 827df9f3 balrog
        if (value & 2)        /* How much exactly are we supposed to reset? */
445 827df9f3 balrog
            omap_gp_timer_reset(s);
446 827df9f3 balrog
        break;
447 827df9f3 balrog
448 827df9f3 balrog
    default:
449 827df9f3 balrog
        OMAP_BAD_REG(addr);
450 827df9f3 balrog
    }
451 827df9f3 balrog
}
452 827df9f3 balrog
453 827df9f3 balrog
static void omap_gp_timer_writeh(void *opaque, target_phys_addr_t addr,
454 827df9f3 balrog
                uint32_t value)
455 827df9f3 balrog
{
456 827df9f3 balrog
    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
457 827df9f3 balrog
458 827df9f3 balrog
    if (addr & 2)
459 827df9f3 balrog
        return omap_gp_timer_write(opaque, addr, (value << 16) | s->writeh);
460 827df9f3 balrog
    else
461 827df9f3 balrog
        s->writeh = (uint16_t) value;
462 827df9f3 balrog
}
463 827df9f3 balrog
464 827df9f3 balrog
static CPUWriteMemoryFunc *omap_gp_timer_writefn[] = {
465 827df9f3 balrog
    omap_badwidth_write32,
466 827df9f3 balrog
    omap_gp_timer_writeh,
467 827df9f3 balrog
    omap_gp_timer_write,
468 827df9f3 balrog
};
469 827df9f3 balrog
470 827df9f3 balrog
struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta,
471 827df9f3 balrog
                qemu_irq irq, omap_clk fclk, omap_clk iclk)
472 827df9f3 balrog
{
473 827df9f3 balrog
    int iomemtype;
474 827df9f3 balrog
    struct omap_gp_timer_s *s = (struct omap_gp_timer_s *)
475 827df9f3 balrog
            qemu_mallocz(sizeof(struct omap_gp_timer_s));
476 827df9f3 balrog
477 827df9f3 balrog
    s->ta = ta;
478 827df9f3 balrog
    s->irq = irq;
479 827df9f3 balrog
    s->clk = fclk;
480 827df9f3 balrog
    s->timer = qemu_new_timer(vm_clock, omap_gp_timer_tick, s);
481 827df9f3 balrog
    s->match = qemu_new_timer(vm_clock, omap_gp_timer_match, s);
482 827df9f3 balrog
    s->in = qemu_allocate_irqs(omap_gp_timer_input, s, 1)[0];
483 827df9f3 balrog
    omap_gp_timer_reset(s);
484 827df9f3 balrog
    omap_gp_timer_clk_setup(s);
485 827df9f3 balrog
486 c66fb5bc balrog
    iomemtype = l4_register_io_memory(0, omap_gp_timer_readfn,
487 827df9f3 balrog
                    omap_gp_timer_writefn, s);
488 8da3ff18 pbrook
    omap_l4_attach(ta, 0, iomemtype);
489 827df9f3 balrog
490 827df9f3 balrog
    return s;
491 827df9f3 balrog
}
492 827df9f3 balrog
493 827df9f3 balrog
/* 32-kHz Sync Timer of the OMAP2 */
494 827df9f3 balrog
static uint32_t omap_synctimer_read(struct omap_synctimer_s *s) {
495 827df9f3 balrog
    return muldiv64(qemu_get_clock(vm_clock), 0x8000, ticks_per_sec);
496 827df9f3 balrog
}
497 827df9f3 balrog
498 827df9f3 balrog
static void omap_synctimer_reset(struct omap_synctimer_s *s)
499 827df9f3 balrog
{
500 827df9f3 balrog
    s->val = omap_synctimer_read(s);
501 827df9f3 balrog
}
502 827df9f3 balrog
503 827df9f3 balrog
static uint32_t omap_synctimer_readw(void *opaque, target_phys_addr_t addr)
504 827df9f3 balrog
{
505 827df9f3 balrog
    struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
506 827df9f3 balrog
507 8da3ff18 pbrook
    switch (addr) {
508 827df9f3 balrog
    case 0x00:        /* 32KSYNCNT_REV */
509 827df9f3 balrog
        return 0x21;
510 827df9f3 balrog
511 827df9f3 balrog
    case 0x10:        /* CR */
512 827df9f3 balrog
        return omap_synctimer_read(s) - s->val;
513 827df9f3 balrog
    }
514 827df9f3 balrog
515 827df9f3 balrog
    OMAP_BAD_REG(addr);
516 827df9f3 balrog
    return 0;
517 827df9f3 balrog
}
518 827df9f3 balrog
519 827df9f3 balrog
static uint32_t omap_synctimer_readh(void *opaque, target_phys_addr_t addr)
520 827df9f3 balrog
{
521 827df9f3 balrog
    struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
522 827df9f3 balrog
    uint32_t ret;
523 827df9f3 balrog
524 827df9f3 balrog
    if (addr & 2)
525 827df9f3 balrog
        return s->readh;
526 827df9f3 balrog
    else {
527 827df9f3 balrog
        ret = omap_synctimer_readw(opaque, addr);
528 827df9f3 balrog
        s->readh = ret >> 16;
529 827df9f3 balrog
        return ret & 0xffff;
530 827df9f3 balrog
    }
531 827df9f3 balrog
}
532 827df9f3 balrog
533 827df9f3 balrog
static CPUReadMemoryFunc *omap_synctimer_readfn[] = {
534 827df9f3 balrog
    omap_badwidth_read32,
535 827df9f3 balrog
    omap_synctimer_readh,
536 827df9f3 balrog
    omap_synctimer_readw,
537 827df9f3 balrog
};
538 827df9f3 balrog
539 827df9f3 balrog
static void omap_synctimer_write(void *opaque, target_phys_addr_t addr,
540 827df9f3 balrog
                uint32_t value)
541 827df9f3 balrog
{
542 827df9f3 balrog
    OMAP_BAD_REG(addr);
543 827df9f3 balrog
}
544 827df9f3 balrog
545 827df9f3 balrog
static CPUWriteMemoryFunc *omap_synctimer_writefn[] = {
546 827df9f3 balrog
    omap_badwidth_write32,
547 827df9f3 balrog
    omap_synctimer_write,
548 827df9f3 balrog
    omap_synctimer_write,
549 827df9f3 balrog
};
550 827df9f3 balrog
551 827df9f3 balrog
void omap_synctimer_init(struct omap_target_agent_s *ta,
552 827df9f3 balrog
                struct omap_mpu_state_s *mpu, omap_clk fclk, omap_clk iclk)
553 827df9f3 balrog
{
554 827df9f3 balrog
    struct omap_synctimer_s *s = &mpu->synctimer;
555 827df9f3 balrog
556 827df9f3 balrog
    omap_synctimer_reset(s);
557 8da3ff18 pbrook
    omap_l4_attach(ta, 0, l4_register_io_memory(0,
558 8da3ff18 pbrook
                      omap_synctimer_readfn, omap_synctimer_writefn, s));
559 827df9f3 balrog
}
560 827df9f3 balrog
561 827df9f3 balrog
/* General-Purpose Interface of OMAP2 */
562 827df9f3 balrog
struct omap2_gpio_s {
563 827df9f3 balrog
    qemu_irq irq[2];
564 827df9f3 balrog
    qemu_irq wkup;
565 827df9f3 balrog
    qemu_irq *in;
566 827df9f3 balrog
    qemu_irq handler[32];
567 827df9f3 balrog
568 827df9f3 balrog
    uint8_t config[2];
569 827df9f3 balrog
    uint32_t inputs;
570 827df9f3 balrog
    uint32_t outputs;
571 827df9f3 balrog
    uint32_t dir;
572 827df9f3 balrog
    uint32_t level[2];
573 827df9f3 balrog
    uint32_t edge[2];
574 827df9f3 balrog
    uint32_t mask[2];
575 827df9f3 balrog
    uint32_t wumask;
576 827df9f3 balrog
    uint32_t ints[2];
577 827df9f3 balrog
    uint32_t debounce;
578 827df9f3 balrog
    uint8_t delay;
579 827df9f3 balrog
};
580 827df9f3 balrog
581 827df9f3 balrog
static inline void omap_gpio_module_int_update(struct omap2_gpio_s *s,
582 827df9f3 balrog
                int line)
583 827df9f3 balrog
{
584 827df9f3 balrog
    qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]);
585 827df9f3 balrog
}
586 827df9f3 balrog
587 827df9f3 balrog
static void omap_gpio_module_wake(struct omap2_gpio_s *s, int line)
588 827df9f3 balrog
{
589 827df9f3 balrog
    if (!(s->config[0] & (1 << 2)))                        /* ENAWAKEUP */
590 827df9f3 balrog
        return;
591 827df9f3 balrog
    if (!(s->config[0] & (3 << 3)))                        /* Force Idle */
592 827df9f3 balrog
        return;
593 827df9f3 balrog
    if (!(s->wumask & (1 << line)))
594 827df9f3 balrog
        return;
595 827df9f3 balrog
596 827df9f3 balrog
    qemu_irq_raise(s->wkup);
597 827df9f3 balrog
}
598 827df9f3 balrog
599 827df9f3 balrog
static inline void omap_gpio_module_out_update(struct omap2_gpio_s *s,
600 827df9f3 balrog
                uint32_t diff)
601 827df9f3 balrog
{
602 827df9f3 balrog
    int ln;
603 827df9f3 balrog
604 827df9f3 balrog
    s->outputs ^= diff;
605 827df9f3 balrog
    diff &= ~s->dir;
606 827df9f3 balrog
    while ((ln = ffs(diff))) {
607 827df9f3 balrog
        ln --;
608 827df9f3 balrog
        qemu_set_irq(s->handler[ln], (s->outputs >> ln) & 1);
609 827df9f3 balrog
        diff &= ~(1 << ln);
610 827df9f3 balrog
    }
611 827df9f3 balrog
}
612 827df9f3 balrog
613 827df9f3 balrog
static void omap_gpio_module_level_update(struct omap2_gpio_s *s, int line)
614 827df9f3 balrog
{
615 827df9f3 balrog
    s->ints[line] |= s->dir &
616 827df9f3 balrog
            ((s->inputs & s->level[1]) | (~s->inputs & s->level[0]));
617 827df9f3 balrog
    omap_gpio_module_int_update(s, line);
618 827df9f3 balrog
}
619 827df9f3 balrog
620 827df9f3 balrog
static inline void omap_gpio_module_int(struct omap2_gpio_s *s, int line)
621 827df9f3 balrog
{
622 827df9f3 balrog
    s->ints[0] |= 1 << line;
623 827df9f3 balrog
    omap_gpio_module_int_update(s, 0);
624 827df9f3 balrog
    s->ints[1] |= 1 << line;
625 827df9f3 balrog
    omap_gpio_module_int_update(s, 1);
626 827df9f3 balrog
    omap_gpio_module_wake(s, line);
627 827df9f3 balrog
}
628 827df9f3 balrog
629 827df9f3 balrog
static void omap_gpio_module_set(void *opaque, int line, int level)
630 827df9f3 balrog
{
631 827df9f3 balrog
    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
632 827df9f3 balrog
633 827df9f3 balrog
    if (level) {
634 827df9f3 balrog
        if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1]))
635 827df9f3 balrog
            omap_gpio_module_int(s, line);
636 827df9f3 balrog
        s->inputs |= 1 << line;
637 827df9f3 balrog
    } else {
638 827df9f3 balrog
        if (s->dir & (1 << line) & ((s->inputs & s->edge[1]) | s->level[0]))
639 827df9f3 balrog
            omap_gpio_module_int(s, line);
640 827df9f3 balrog
        s->inputs &= ~(1 << line);
641 827df9f3 balrog
    }
642 827df9f3 balrog
}
643 827df9f3 balrog
644 827df9f3 balrog
static void omap_gpio_module_reset(struct omap2_gpio_s *s)
645 827df9f3 balrog
{
646 827df9f3 balrog
    s->config[0] = 0;
647 827df9f3 balrog
    s->config[1] = 2;
648 827df9f3 balrog
    s->ints[0] = 0;
649 827df9f3 balrog
    s->ints[1] = 0;
650 827df9f3 balrog
    s->mask[0] = 0;
651 827df9f3 balrog
    s->mask[1] = 0;
652 827df9f3 balrog
    s->wumask = 0;
653 827df9f3 balrog
    s->dir = ~0;
654 827df9f3 balrog
    s->level[0] = 0;
655 827df9f3 balrog
    s->level[1] = 0;
656 827df9f3 balrog
    s->edge[0] = 0;
657 827df9f3 balrog
    s->edge[1] = 0;
658 827df9f3 balrog
    s->debounce = 0;
659 827df9f3 balrog
    s->delay = 0;
660 827df9f3 balrog
}
661 827df9f3 balrog
662 827df9f3 balrog
static uint32_t omap_gpio_module_read(void *opaque, target_phys_addr_t addr)
663 827df9f3 balrog
{
664 827df9f3 balrog
    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
665 827df9f3 balrog
666 8da3ff18 pbrook
    switch (addr) {
667 827df9f3 balrog
    case 0x00:        /* GPIO_REVISION */
668 827df9f3 balrog
        return 0x18;
669 827df9f3 balrog
670 827df9f3 balrog
    case 0x10:        /* GPIO_SYSCONFIG */
671 827df9f3 balrog
        return s->config[0];
672 827df9f3 balrog
673 827df9f3 balrog
    case 0x14:        /* GPIO_SYSSTATUS */
674 827df9f3 balrog
        return 0x01;
675 827df9f3 balrog
676 827df9f3 balrog
    case 0x18:        /* GPIO_IRQSTATUS1 */
677 827df9f3 balrog
        return s->ints[0];
678 827df9f3 balrog
679 827df9f3 balrog
    case 0x1c:        /* GPIO_IRQENABLE1 */
680 827df9f3 balrog
    case 0x60:        /* GPIO_CLEARIRQENABLE1 */
681 827df9f3 balrog
    case 0x64:        /* GPIO_SETIRQENABLE1 */
682 827df9f3 balrog
        return s->mask[0];
683 827df9f3 balrog
684 827df9f3 balrog
    case 0x20:        /* GPIO_WAKEUPENABLE */
685 827df9f3 balrog
    case 0x80:        /* GPIO_CLEARWKUENA */
686 827df9f3 balrog
    case 0x84:        /* GPIO_SETWKUENA */
687 827df9f3 balrog
        return s->wumask;
688 827df9f3 balrog
689 827df9f3 balrog
    case 0x28:        /* GPIO_IRQSTATUS2 */
690 827df9f3 balrog
        return s->ints[1];
691 827df9f3 balrog
692 827df9f3 balrog
    case 0x2c:        /* GPIO_IRQENABLE2 */
693 827df9f3 balrog
    case 0x70:        /* GPIO_CLEARIRQENABLE2 */
694 827df9f3 balrog
    case 0x74:        /* GPIO_SETIREQNEABLE2 */
695 827df9f3 balrog
        return s->mask[1];
696 827df9f3 balrog
697 827df9f3 balrog
    case 0x30:        /* GPIO_CTRL */
698 827df9f3 balrog
        return s->config[1];
699 827df9f3 balrog
700 827df9f3 balrog
    case 0x34:        /* GPIO_OE */
701 827df9f3 balrog
        return s->dir;
702 827df9f3 balrog
703 827df9f3 balrog
    case 0x38:        /* GPIO_DATAIN */
704 827df9f3 balrog
        return s->inputs;
705 827df9f3 balrog
706 827df9f3 balrog
    case 0x3c:        /* GPIO_DATAOUT */
707 827df9f3 balrog
    case 0x90:        /* GPIO_CLEARDATAOUT */
708 827df9f3 balrog
    case 0x94:        /* GPIO_SETDATAOUT */
709 827df9f3 balrog
        return s->outputs;
710 827df9f3 balrog
711 827df9f3 balrog
    case 0x40:        /* GPIO_LEVELDETECT0 */
712 827df9f3 balrog
        return s->level[0];
713 827df9f3 balrog
714 827df9f3 balrog
    case 0x44:        /* GPIO_LEVELDETECT1 */
715 827df9f3 balrog
        return s->level[1];
716 827df9f3 balrog
717 827df9f3 balrog
    case 0x48:        /* GPIO_RISINGDETECT */
718 827df9f3 balrog
        return s->edge[0];
719 827df9f3 balrog
720 827df9f3 balrog
    case 0x4c:        /* GPIO_FALLINGDETECT */
721 827df9f3 balrog
        return s->edge[1];
722 827df9f3 balrog
723 827df9f3 balrog
    case 0x50:        /* GPIO_DEBOUNCENABLE */
724 827df9f3 balrog
        return s->debounce;
725 827df9f3 balrog
726 827df9f3 balrog
    case 0x54:        /* GPIO_DEBOUNCINGTIME */
727 827df9f3 balrog
        return s->delay;
728 827df9f3 balrog
    }
729 827df9f3 balrog
730 827df9f3 balrog
    OMAP_BAD_REG(addr);
731 827df9f3 balrog
    return 0;
732 827df9f3 balrog
}
733 827df9f3 balrog
734 827df9f3 balrog
static void omap_gpio_module_write(void *opaque, target_phys_addr_t addr,
735 827df9f3 balrog
                uint32_t value)
736 827df9f3 balrog
{
737 827df9f3 balrog
    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
738 827df9f3 balrog
    uint32_t diff;
739 827df9f3 balrog
    int ln;
740 827df9f3 balrog
741 8da3ff18 pbrook
    switch (addr) {
742 827df9f3 balrog
    case 0x00:        /* GPIO_REVISION */
743 827df9f3 balrog
    case 0x14:        /* GPIO_SYSSTATUS */
744 827df9f3 balrog
    case 0x38:        /* GPIO_DATAIN */
745 827df9f3 balrog
        OMAP_RO_REG(addr);
746 827df9f3 balrog
        break;
747 827df9f3 balrog
748 827df9f3 balrog
    case 0x10:        /* GPIO_SYSCONFIG */
749 827df9f3 balrog
        if (((value >> 3) & 3) == 3)
750 827df9f3 balrog
            fprintf(stderr, "%s: bad IDLEMODE value\n", __FUNCTION__);
751 827df9f3 balrog
        if (value & 2)
752 827df9f3 balrog
            omap_gpio_module_reset(s);
753 827df9f3 balrog
        s->config[0] = value & 0x1d;
754 827df9f3 balrog
        break;
755 827df9f3 balrog
756 827df9f3 balrog
    case 0x18:        /* GPIO_IRQSTATUS1 */
757 827df9f3 balrog
        if (s->ints[0] & value) {
758 827df9f3 balrog
            s->ints[0] &= ~value;
759 827df9f3 balrog
            omap_gpio_module_level_update(s, 0);
760 827df9f3 balrog
        }
761 827df9f3 balrog
        break;
762 827df9f3 balrog
763 827df9f3 balrog
    case 0x1c:        /* GPIO_IRQENABLE1 */
764 827df9f3 balrog
        s->mask[0] = value;
765 827df9f3 balrog
        omap_gpio_module_int_update(s, 0);
766 827df9f3 balrog
        break;
767 827df9f3 balrog
768 827df9f3 balrog
    case 0x20:        /* GPIO_WAKEUPENABLE */
769 827df9f3 balrog
        s->wumask = value;
770 827df9f3 balrog
        break;
771 827df9f3 balrog
772 827df9f3 balrog
    case 0x28:        /* GPIO_IRQSTATUS2 */
773 827df9f3 balrog
        if (s->ints[1] & value) {
774 827df9f3 balrog
            s->ints[1] &= ~value;
775 827df9f3 balrog
            omap_gpio_module_level_update(s, 1);
776 827df9f3 balrog
        }
777 827df9f3 balrog
        break;
778 827df9f3 balrog
779 827df9f3 balrog
    case 0x2c:        /* GPIO_IRQENABLE2 */
780 827df9f3 balrog
        s->mask[1] = value;
781 827df9f3 balrog
        omap_gpio_module_int_update(s, 1);
782 827df9f3 balrog
        break;
783 827df9f3 balrog
784 827df9f3 balrog
    case 0x30:        /* GPIO_CTRL */
785 827df9f3 balrog
        s->config[1] = value & 7;
786 827df9f3 balrog
        break;
787 827df9f3 balrog
788 827df9f3 balrog
    case 0x34:        /* GPIO_OE */
789 827df9f3 balrog
        diff = s->outputs & (s->dir ^ value);
790 827df9f3 balrog
        s->dir = value;
791 827df9f3 balrog
792 827df9f3 balrog
        value = s->outputs & ~s->dir;
793 827df9f3 balrog
        while ((ln = ffs(diff))) {
794 827df9f3 balrog
            diff &= ~(1 <<-- ln);
795 827df9f3 balrog
            qemu_set_irq(s->handler[ln], (value >> ln) & 1);
796 827df9f3 balrog
        }
797 827df9f3 balrog
798 827df9f3 balrog
        omap_gpio_module_level_update(s, 0);
799 827df9f3 balrog
        omap_gpio_module_level_update(s, 1);
800 827df9f3 balrog
        break;
801 827df9f3 balrog
802 827df9f3 balrog
    case 0x3c:        /* GPIO_DATAOUT */
803 827df9f3 balrog
        omap_gpio_module_out_update(s, s->outputs ^ value);
804 827df9f3 balrog
        break;
805 827df9f3 balrog
806 827df9f3 balrog
    case 0x40:        /* GPIO_LEVELDETECT0 */
807 827df9f3 balrog
        s->level[0] = value;
808 827df9f3 balrog
        omap_gpio_module_level_update(s, 0);
809 827df9f3 balrog
        omap_gpio_module_level_update(s, 1);
810 827df9f3 balrog
        break;
811 827df9f3 balrog
812 827df9f3 balrog
    case 0x44:        /* GPIO_LEVELDETECT1 */
813 827df9f3 balrog
        s->level[1] = value;
814 827df9f3 balrog
        omap_gpio_module_level_update(s, 0);
815 827df9f3 balrog
        omap_gpio_module_level_update(s, 1);
816 827df9f3 balrog
        break;
817 827df9f3 balrog
818 827df9f3 balrog
    case 0x48:        /* GPIO_RISINGDETECT */
819 827df9f3 balrog
        s->edge[0] = value;
820 827df9f3 balrog
        break;
821 827df9f3 balrog
822 827df9f3 balrog
    case 0x4c:        /* GPIO_FALLINGDETECT */
823 827df9f3 balrog
        s->edge[1] = value;
824 827df9f3 balrog
        break;
825 827df9f3 balrog
826 827df9f3 balrog
    case 0x50:        /* GPIO_DEBOUNCENABLE */
827 827df9f3 balrog
        s->debounce = value;
828 827df9f3 balrog
        break;
829 827df9f3 balrog
830 827df9f3 balrog
    case 0x54:        /* GPIO_DEBOUNCINGTIME */
831 827df9f3 balrog
        s->delay = value;
832 827df9f3 balrog
        break;
833 827df9f3 balrog
834 827df9f3 balrog
    case 0x60:        /* GPIO_CLEARIRQENABLE1 */
835 827df9f3 balrog
        s->mask[0] &= ~value;
836 827df9f3 balrog
        omap_gpio_module_int_update(s, 0);
837 827df9f3 balrog
        break;
838 827df9f3 balrog
839 827df9f3 balrog
    case 0x64:        /* GPIO_SETIRQENABLE1 */
840 827df9f3 balrog
        s->mask[0] |= value;
841 827df9f3 balrog
        omap_gpio_module_int_update(s, 0);
842 827df9f3 balrog
        break;
843 827df9f3 balrog
844 827df9f3 balrog
    case 0x70:        /* GPIO_CLEARIRQENABLE2 */
845 827df9f3 balrog
        s->mask[1] &= ~value;
846 827df9f3 balrog
        omap_gpio_module_int_update(s, 1);
847 827df9f3 balrog
        break;
848 827df9f3 balrog
849 827df9f3 balrog
    case 0x74:        /* GPIO_SETIREQNEABLE2 */
850 827df9f3 balrog
        s->mask[1] |= value;
851 827df9f3 balrog
        omap_gpio_module_int_update(s, 1);
852 827df9f3 balrog
        break;
853 827df9f3 balrog
854 827df9f3 balrog
    case 0x80:        /* GPIO_CLEARWKUENA */
855 827df9f3 balrog
        s->wumask &= ~value;
856 827df9f3 balrog
        break;
857 827df9f3 balrog
858 827df9f3 balrog
    case 0x84:        /* GPIO_SETWKUENA */
859 827df9f3 balrog
        s->wumask |= value;
860 827df9f3 balrog
        break;
861 827df9f3 balrog
862 827df9f3 balrog
    case 0x90:        /* GPIO_CLEARDATAOUT */
863 827df9f3 balrog
        omap_gpio_module_out_update(s, s->outputs & value);
864 827df9f3 balrog
        break;
865 827df9f3 balrog
866 827df9f3 balrog
    case 0x94:        /* GPIO_SETDATAOUT */
867 827df9f3 balrog
        omap_gpio_module_out_update(s, ~s->outputs & value);
868 827df9f3 balrog
        break;
869 827df9f3 balrog
870 827df9f3 balrog
    default:
871 827df9f3 balrog
        OMAP_BAD_REG(addr);
872 827df9f3 balrog
        return;
873 827df9f3 balrog
    }
874 827df9f3 balrog
}
875 827df9f3 balrog
876 827df9f3 balrog
static uint32_t omap_gpio_module_readp(void *opaque, target_phys_addr_t addr)
877 827df9f3 balrog
{
878 827df9f3 balrog
    return omap_gpio_module_readp(opaque, addr) >> ((addr & 3) << 3);
879 827df9f3 balrog
}
880 827df9f3 balrog
881 827df9f3 balrog
static void omap_gpio_module_writep(void *opaque, target_phys_addr_t addr,
882 827df9f3 balrog
                uint32_t value)
883 827df9f3 balrog
{
884 827df9f3 balrog
    uint32_t cur = 0;
885 827df9f3 balrog
    uint32_t mask = 0xffff;
886 827df9f3 balrog
887 8da3ff18 pbrook
    switch (addr & ~3) {
888 827df9f3 balrog
    case 0x00:        /* GPIO_REVISION */
889 827df9f3 balrog
    case 0x14:        /* GPIO_SYSSTATUS */
890 827df9f3 balrog
    case 0x38:        /* GPIO_DATAIN */
891 827df9f3 balrog
        OMAP_RO_REG(addr);
892 827df9f3 balrog
        break;
893 827df9f3 balrog
894 827df9f3 balrog
    case 0x10:        /* GPIO_SYSCONFIG */
895 827df9f3 balrog
    case 0x1c:        /* GPIO_IRQENABLE1 */
896 827df9f3 balrog
    case 0x20:        /* GPIO_WAKEUPENABLE */
897 827df9f3 balrog
    case 0x2c:        /* GPIO_IRQENABLE2 */
898 827df9f3 balrog
    case 0x30:        /* GPIO_CTRL */
899 827df9f3 balrog
    case 0x34:        /* GPIO_OE */
900 827df9f3 balrog
    case 0x3c:        /* GPIO_DATAOUT */
901 827df9f3 balrog
    case 0x40:        /* GPIO_LEVELDETECT0 */
902 827df9f3 balrog
    case 0x44:        /* GPIO_LEVELDETECT1 */
903 827df9f3 balrog
    case 0x48:        /* GPIO_RISINGDETECT */
904 827df9f3 balrog
    case 0x4c:        /* GPIO_FALLINGDETECT */
905 827df9f3 balrog
    case 0x50:        /* GPIO_DEBOUNCENABLE */
906 827df9f3 balrog
    case 0x54:        /* GPIO_DEBOUNCINGTIME */
907 827df9f3 balrog
        cur = omap_gpio_module_read(opaque, addr & ~3) &
908 827df9f3 balrog
                ~(mask << ((addr & 3) << 3));
909 827df9f3 balrog
910 827df9f3 balrog
        /* Fall through.  */
911 827df9f3 balrog
    case 0x18:        /* GPIO_IRQSTATUS1 */
912 827df9f3 balrog
    case 0x28:        /* GPIO_IRQSTATUS2 */
913 827df9f3 balrog
    case 0x60:        /* GPIO_CLEARIRQENABLE1 */
914 827df9f3 balrog
    case 0x64:        /* GPIO_SETIRQENABLE1 */
915 827df9f3 balrog
    case 0x70:        /* GPIO_CLEARIRQENABLE2 */
916 827df9f3 balrog
    case 0x74:        /* GPIO_SETIREQNEABLE2 */
917 827df9f3 balrog
    case 0x80:        /* GPIO_CLEARWKUENA */
918 827df9f3 balrog
    case 0x84:        /* GPIO_SETWKUENA */
919 827df9f3 balrog
    case 0x90:        /* GPIO_CLEARDATAOUT */
920 827df9f3 balrog
    case 0x94:        /* GPIO_SETDATAOUT */
921 827df9f3 balrog
        value <<= (addr & 3) << 3;
922 827df9f3 balrog
        omap_gpio_module_write(opaque, addr, cur | value);
923 827df9f3 balrog
        break;
924 827df9f3 balrog
925 827df9f3 balrog
    default:
926 827df9f3 balrog
        OMAP_BAD_REG(addr);
927 827df9f3 balrog
        return;
928 827df9f3 balrog
    }
929 827df9f3 balrog
}
930 827df9f3 balrog
931 827df9f3 balrog
static CPUReadMemoryFunc *omap_gpio_module_readfn[] = {
932 827df9f3 balrog
    omap_gpio_module_readp,
933 827df9f3 balrog
    omap_gpio_module_readp,
934 827df9f3 balrog
    omap_gpio_module_read,
935 827df9f3 balrog
};
936 827df9f3 balrog
937 827df9f3 balrog
static CPUWriteMemoryFunc *omap_gpio_module_writefn[] = {
938 827df9f3 balrog
    omap_gpio_module_writep,
939 827df9f3 balrog
    omap_gpio_module_writep,
940 827df9f3 balrog
    omap_gpio_module_write,
941 827df9f3 balrog
};
942 827df9f3 balrog
943 827df9f3 balrog
static void omap_gpio_module_init(struct omap2_gpio_s *s,
944 827df9f3 balrog
                struct omap_target_agent_s *ta, int region,
945 827df9f3 balrog
                qemu_irq mpu, qemu_irq dsp, qemu_irq wkup,
946 827df9f3 balrog
                omap_clk fclk, omap_clk iclk)
947 827df9f3 balrog
{
948 827df9f3 balrog
    int iomemtype;
949 827df9f3 balrog
950 827df9f3 balrog
    s->irq[0] = mpu;
951 827df9f3 balrog
    s->irq[1] = dsp;
952 827df9f3 balrog
    s->wkup = wkup;
953 827df9f3 balrog
    s->in = qemu_allocate_irqs(omap_gpio_module_set, s, 32);
954 827df9f3 balrog
955 c66fb5bc balrog
    iomemtype = l4_register_io_memory(0, omap_gpio_module_readfn,
956 827df9f3 balrog
                    omap_gpio_module_writefn, s);
957 8da3ff18 pbrook
    omap_l4_attach(ta, region, iomemtype);
958 827df9f3 balrog
}
959 827df9f3 balrog
960 827df9f3 balrog
struct omap_gpif_s {
961 827df9f3 balrog
    struct omap2_gpio_s module[5];
962 827df9f3 balrog
    int modules;
963 827df9f3 balrog
964 827df9f3 balrog
    int autoidle;
965 827df9f3 balrog
    int gpo;
966 827df9f3 balrog
};
967 827df9f3 balrog
968 827df9f3 balrog
static void omap_gpif_reset(struct omap_gpif_s *s)
969 827df9f3 balrog
{
970 827df9f3 balrog
    int i;
971 827df9f3 balrog
972 827df9f3 balrog
    for (i = 0; i < s->modules; i ++)
973 827df9f3 balrog
        omap_gpio_module_reset(s->module + i);
974 827df9f3 balrog
975 827df9f3 balrog
    s->autoidle = 0;
976 827df9f3 balrog
    s->gpo = 0;
977 827df9f3 balrog
}
978 827df9f3 balrog
979 827df9f3 balrog
static uint32_t omap_gpif_top_read(void *opaque, target_phys_addr_t addr)
980 827df9f3 balrog
{
981 827df9f3 balrog
    struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
982 827df9f3 balrog
983 8da3ff18 pbrook
    switch (addr) {
984 827df9f3 balrog
    case 0x00:        /* IPGENERICOCPSPL_REVISION */
985 827df9f3 balrog
        return 0x18;
986 827df9f3 balrog
987 827df9f3 balrog
    case 0x10:        /* IPGENERICOCPSPL_SYSCONFIG */
988 827df9f3 balrog
        return s->autoidle;
989 827df9f3 balrog
990 827df9f3 balrog
    case 0x14:        /* IPGENERICOCPSPL_SYSSTATUS */
991 827df9f3 balrog
        return 0x01;
992 827df9f3 balrog
993 827df9f3 balrog
    case 0x18:        /* IPGENERICOCPSPL_IRQSTATUS */
994 827df9f3 balrog
        return 0x00;
995 827df9f3 balrog
996 827df9f3 balrog
    case 0x40:        /* IPGENERICOCPSPL_GPO */
997 827df9f3 balrog
        return s->gpo;
998 827df9f3 balrog
999 827df9f3 balrog
    case 0x50:        /* IPGENERICOCPSPL_GPI */
1000 827df9f3 balrog
        return 0x00;
1001 827df9f3 balrog
    }
1002 827df9f3 balrog
1003 827df9f3 balrog
    OMAP_BAD_REG(addr);
1004 827df9f3 balrog
    return 0;
1005 827df9f3 balrog
}
1006 827df9f3 balrog
1007 827df9f3 balrog
static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,
1008 827df9f3 balrog
                uint32_t value)
1009 827df9f3 balrog
{
1010 827df9f3 balrog
    struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
1011 827df9f3 balrog
1012 8da3ff18 pbrook
    switch (addr) {
1013 827df9f3 balrog
    case 0x00:        /* IPGENERICOCPSPL_REVISION */
1014 827df9f3 balrog
    case 0x14:        /* IPGENERICOCPSPL_SYSSTATUS */
1015 827df9f3 balrog
    case 0x18:        /* IPGENERICOCPSPL_IRQSTATUS */
1016 827df9f3 balrog
    case 0x50:        /* IPGENERICOCPSPL_GPI */
1017 827df9f3 balrog
        OMAP_RO_REG(addr);
1018 827df9f3 balrog
        break;
1019 827df9f3 balrog
1020 827df9f3 balrog
    case 0x10:        /* IPGENERICOCPSPL_SYSCONFIG */
1021 827df9f3 balrog
        if (value & (1 << 1))                                        /* SOFTRESET */
1022 827df9f3 balrog
            omap_gpif_reset(s);
1023 827df9f3 balrog
        s->autoidle = value & 1;
1024 827df9f3 balrog
        break;
1025 827df9f3 balrog
1026 827df9f3 balrog
    case 0x40:        /* IPGENERICOCPSPL_GPO */
1027 827df9f3 balrog
        s->gpo = value & 1;
1028 827df9f3 balrog
        break;
1029 827df9f3 balrog
1030 827df9f3 balrog
    default:
1031 827df9f3 balrog
        OMAP_BAD_REG(addr);
1032 827df9f3 balrog
        return;
1033 827df9f3 balrog
    }
1034 827df9f3 balrog
}
1035 827df9f3 balrog
1036 827df9f3 balrog
static CPUReadMemoryFunc *omap_gpif_top_readfn[] = {
1037 827df9f3 balrog
    omap_gpif_top_read,
1038 827df9f3 balrog
    omap_gpif_top_read,
1039 827df9f3 balrog
    omap_gpif_top_read,
1040 827df9f3 balrog
};
1041 827df9f3 balrog
1042 827df9f3 balrog
static CPUWriteMemoryFunc *omap_gpif_top_writefn[] = {
1043 827df9f3 balrog
    omap_gpif_top_write,
1044 827df9f3 balrog
    omap_gpif_top_write,
1045 827df9f3 balrog
    omap_gpif_top_write,
1046 827df9f3 balrog
};
1047 827df9f3 balrog
1048 827df9f3 balrog
struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
1049 827df9f3 balrog
                qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules)
1050 827df9f3 balrog
{
1051 827df9f3 balrog
    int iomemtype, i;
1052 827df9f3 balrog
    struct omap_gpif_s *s = (struct omap_gpif_s *)
1053 827df9f3 balrog
            qemu_mallocz(sizeof(struct omap_gpif_s));
1054 827df9f3 balrog
    int region[4] = { 0, 2, 4, 5 };
1055 827df9f3 balrog
1056 827df9f3 balrog
    s->modules = modules;
1057 827df9f3 balrog
    for (i = 0; i < modules; i ++)
1058 827df9f3 balrog
        omap_gpio_module_init(s->module + i, ta, region[i],
1059 827df9f3 balrog
                        irq[i], 0, 0, fclk[i], iclk);
1060 827df9f3 balrog
1061 827df9f3 balrog
    omap_gpif_reset(s);
1062 827df9f3 balrog
1063 c66fb5bc balrog
    iomemtype = l4_register_io_memory(0, omap_gpif_top_readfn,
1064 827df9f3 balrog
                    omap_gpif_top_writefn, s);
1065 8da3ff18 pbrook
    omap_l4_attach(ta, 1, iomemtype);
1066 827df9f3 balrog
1067 827df9f3 balrog
    return s;
1068 827df9f3 balrog
}
1069 827df9f3 balrog
1070 827df9f3 balrog
qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start)
1071 827df9f3 balrog
{
1072 827df9f3 balrog
    if (start >= s->modules * 32 || start < 0)
1073 2ac71179 Paul Brook
        hw_error("%s: No GPIO line %i\n", __FUNCTION__, start);
1074 827df9f3 balrog
    return s->module[start >> 5].in + (start & 31);
1075 827df9f3 balrog
}
1076 827df9f3 balrog
1077 827df9f3 balrog
void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler)
1078 827df9f3 balrog
{
1079 827df9f3 balrog
    if (line >= s->modules * 32 || line < 0)
1080 2ac71179 Paul Brook
        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
1081 827df9f3 balrog
    s->module[line >> 5].handler[line & 31] = handler;
1082 827df9f3 balrog
}
1083 827df9f3 balrog
1084 827df9f3 balrog
/* Multichannel SPI */
1085 827df9f3 balrog
struct omap_mcspi_s {
1086 827df9f3 balrog
    qemu_irq irq;
1087 827df9f3 balrog
    int chnum;
1088 827df9f3 balrog
1089 827df9f3 balrog
    uint32_t sysconfig;
1090 827df9f3 balrog
    uint32_t systest;
1091 827df9f3 balrog
    uint32_t irqst;
1092 827df9f3 balrog
    uint32_t irqen;
1093 827df9f3 balrog
    uint32_t wken;
1094 827df9f3 balrog
    uint32_t control;
1095 827df9f3 balrog
1096 827df9f3 balrog
    struct omap_mcspi_ch_s {
1097 827df9f3 balrog
        qemu_irq txdrq;
1098 827df9f3 balrog
        qemu_irq rxdrq;
1099 e927bb00 balrog
        uint32_t (*txrx)(void *opaque, uint32_t, int);
1100 827df9f3 balrog
        void *opaque;
1101 827df9f3 balrog
1102 827df9f3 balrog
        uint32_t tx;
1103 827df9f3 balrog
        uint32_t rx;
1104 827df9f3 balrog
1105 827df9f3 balrog
        uint32_t config;
1106 827df9f3 balrog
        uint32_t status;
1107 827df9f3 balrog
        uint32_t control;
1108 827df9f3 balrog
    } ch[4];
1109 827df9f3 balrog
};
1110 827df9f3 balrog
1111 827df9f3 balrog
static inline void omap_mcspi_interrupt_update(struct omap_mcspi_s *s)
1112 827df9f3 balrog
{
1113 827df9f3 balrog
    qemu_set_irq(s->irq, s->irqst & s->irqen);
1114 827df9f3 balrog
}
1115 827df9f3 balrog
1116 827df9f3 balrog
static inline void omap_mcspi_dmarequest_update(struct omap_mcspi_ch_s *ch)
1117 827df9f3 balrog
{
1118 827df9f3 balrog
    qemu_set_irq(ch->txdrq,
1119 827df9f3 balrog
                    (ch->control & 1) &&                /* EN */
1120 827df9f3 balrog
                    (ch->config & (1 << 14)) &&                /* DMAW */
1121 827df9f3 balrog
                    (ch->status & (1 << 1)) &&                /* TXS */
1122 827df9f3 balrog
                    ((ch->config >> 12) & 3) != 1);        /* TRM */
1123 827df9f3 balrog
    qemu_set_irq(ch->rxdrq,
1124 827df9f3 balrog
                    (ch->control & 1) &&                /* EN */
1125 827df9f3 balrog
                    (ch->config & (1 << 15)) &&                /* DMAW */
1126 827df9f3 balrog
                    (ch->status & (1 << 0)) &&                /* RXS */
1127 827df9f3 balrog
                    ((ch->config >> 12) & 3) != 2);        /* TRM */
1128 827df9f3 balrog
}
1129 827df9f3 balrog
1130 827df9f3 balrog
static void omap_mcspi_transfer_run(struct omap_mcspi_s *s, int chnum)
1131 827df9f3 balrog
{
1132 827df9f3 balrog
    struct omap_mcspi_ch_s *ch = s->ch + chnum;
1133 827df9f3 balrog
1134 827df9f3 balrog
    if (!(ch->control & 1))                                /* EN */
1135 827df9f3 balrog
        return;
1136 827df9f3 balrog
    if ((ch->status & (1 << 0)) &&                        /* RXS */
1137 827df9f3 balrog
                    ((ch->config >> 12) & 3) != 2 &&        /* TRM */
1138 827df9f3 balrog
                    !(ch->config & (1 << 19)))                /* TURBO */
1139 827df9f3 balrog
        goto intr_update;
1140 827df9f3 balrog
    if ((ch->status & (1 << 1)) &&                        /* TXS */
1141 827df9f3 balrog
                    ((ch->config >> 12) & 3) != 1)        /* TRM */
1142 827df9f3 balrog
        goto intr_update;
1143 827df9f3 balrog
1144 827df9f3 balrog
    if (!(s->control & 1) ||                                /* SINGLE */
1145 827df9f3 balrog
                    (ch->config & (1 << 20))) {                /* FORCE */
1146 827df9f3 balrog
        if (ch->txrx)
1147 e927bb00 balrog
            ch->rx = ch->txrx(ch->opaque, ch->tx,        /* WL */
1148 e927bb00 balrog
                            1 + (0x1f & (ch->config >> 7)));
1149 827df9f3 balrog
    }
1150 827df9f3 balrog
1151 827df9f3 balrog
    ch->tx = 0;
1152 827df9f3 balrog
    ch->status |= 1 << 2;                                /* EOT */
1153 827df9f3 balrog
    ch->status |= 1 << 1;                                /* TXS */
1154 827df9f3 balrog
    if (((ch->config >> 12) & 3) != 2)                        /* TRM */
1155 827df9f3 balrog
        ch->status |= 1 << 0;                                /* RXS */
1156 827df9f3 balrog
1157 827df9f3 balrog
intr_update:
1158 827df9f3 balrog
    if ((ch->status & (1 << 0)) &&                        /* RXS */
1159 827df9f3 balrog
                    ((ch->config >> 12) & 3) != 2 &&        /* TRM */
1160 827df9f3 balrog
                    !(ch->config & (1 << 19)))                /* TURBO */
1161 827df9f3 balrog
        s->irqst |= 1 << (2 + 4 * chnum);                /* RX_FULL */
1162 827df9f3 balrog
    if ((ch->status & (1 << 1)) &&                        /* TXS */
1163 827df9f3 balrog
                    ((ch->config >> 12) & 3) != 1)        /* TRM */
1164 827df9f3 balrog
        s->irqst |= 1 << (0 + 4 * chnum);                /* TX_EMPTY */
1165 827df9f3 balrog
    omap_mcspi_interrupt_update(s);
1166 827df9f3 balrog
    omap_mcspi_dmarequest_update(ch);
1167 827df9f3 balrog
}
1168 827df9f3 balrog
1169 827df9f3 balrog
static void omap_mcspi_reset(struct omap_mcspi_s *s)
1170 827df9f3 balrog
{
1171 827df9f3 balrog
    int ch;
1172 827df9f3 balrog
1173 827df9f3 balrog
    s->sysconfig = 0;
1174 827df9f3 balrog
    s->systest = 0;
1175 827df9f3 balrog
    s->irqst = 0;
1176 827df9f3 balrog
    s->irqen = 0;
1177 827df9f3 balrog
    s->wken = 0;
1178 827df9f3 balrog
    s->control = 4;
1179 827df9f3 balrog
1180 827df9f3 balrog
    for (ch = 0; ch < 4; ch ++) {
1181 827df9f3 balrog
        s->ch[ch].config = 0x060000;
1182 827df9f3 balrog
        s->ch[ch].status = 2;                                /* TXS */
1183 827df9f3 balrog
        s->ch[ch].control = 0;
1184 827df9f3 balrog
1185 827df9f3 balrog
        omap_mcspi_dmarequest_update(s->ch + ch);
1186 827df9f3 balrog
    }
1187 827df9f3 balrog
1188 827df9f3 balrog
    omap_mcspi_interrupt_update(s);
1189 827df9f3 balrog
}
1190 827df9f3 balrog
1191 827df9f3 balrog
static uint32_t omap_mcspi_read(void *opaque, target_phys_addr_t addr)
1192 827df9f3 balrog
{
1193 827df9f3 balrog
    struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
1194 827df9f3 balrog
    int ch = 0;
1195 827df9f3 balrog
    uint32_t ret;
1196 827df9f3 balrog
1197 8da3ff18 pbrook
    switch (addr) {
1198 827df9f3 balrog
    case 0x00:        /* MCSPI_REVISION */
1199 827df9f3 balrog
        return 0x91;
1200 827df9f3 balrog
1201 827df9f3 balrog
    case 0x10:        /* MCSPI_SYSCONFIG */
1202 827df9f3 balrog
        return s->sysconfig;
1203 827df9f3 balrog
1204 827df9f3 balrog
    case 0x14:        /* MCSPI_SYSSTATUS */
1205 827df9f3 balrog
        return 1;                                        /* RESETDONE */
1206 827df9f3 balrog
1207 827df9f3 balrog
    case 0x18:        /* MCSPI_IRQSTATUS */
1208 827df9f3 balrog
        return s->irqst;
1209 827df9f3 balrog
1210 827df9f3 balrog
    case 0x1c:        /* MCSPI_IRQENABLE */
1211 827df9f3 balrog
        return s->irqen;
1212 827df9f3 balrog
1213 827df9f3 balrog
    case 0x20:        /* MCSPI_WAKEUPENABLE */
1214 827df9f3 balrog
        return s->wken;
1215 827df9f3 balrog
1216 827df9f3 balrog
    case 0x24:        /* MCSPI_SYST */
1217 827df9f3 balrog
        return s->systest;
1218 827df9f3 balrog
1219 827df9f3 balrog
    case 0x28:        /* MCSPI_MODULCTRL */
1220 827df9f3 balrog
        return s->control;
1221 827df9f3 balrog
1222 827df9f3 balrog
    case 0x68: ch ++;
1223 827df9f3 balrog
    case 0x54: ch ++;
1224 827df9f3 balrog
    case 0x40: ch ++;
1225 827df9f3 balrog
    case 0x2c:        /* MCSPI_CHCONF */
1226 827df9f3 balrog
        return s->ch[ch].config;
1227 827df9f3 balrog
1228 827df9f3 balrog
    case 0x6c: ch ++;
1229 827df9f3 balrog
    case 0x58: ch ++;
1230 827df9f3 balrog
    case 0x44: ch ++;
1231 827df9f3 balrog
    case 0x30:        /* MCSPI_CHSTAT */
1232 827df9f3 balrog
        return s->ch[ch].status;
1233 827df9f3 balrog
1234 827df9f3 balrog
    case 0x70: ch ++;
1235 827df9f3 balrog
    case 0x5c: ch ++;
1236 827df9f3 balrog
    case 0x48: ch ++;
1237 827df9f3 balrog
    case 0x34:        /* MCSPI_CHCTRL */
1238 827df9f3 balrog
        return s->ch[ch].control;
1239 827df9f3 balrog
1240 827df9f3 balrog
    case 0x74: ch ++;
1241 827df9f3 balrog
    case 0x60: ch ++;
1242 827df9f3 balrog
    case 0x4c: ch ++;
1243 827df9f3 balrog
    case 0x38:        /* MCSPI_TX */
1244 827df9f3 balrog
        return s->ch[ch].tx;
1245 827df9f3 balrog
1246 827df9f3 balrog
    case 0x78: ch ++;
1247 827df9f3 balrog
    case 0x64: ch ++;
1248 827df9f3 balrog
    case 0x50: ch ++;
1249 827df9f3 balrog
    case 0x3c:        /* MCSPI_RX */
1250 827df9f3 balrog
        s->ch[ch].status &= ~(1 << 0);                        /* RXS */
1251 827df9f3 balrog
        ret = s->ch[ch].rx;
1252 827df9f3 balrog
        omap_mcspi_transfer_run(s, ch);
1253 827df9f3 balrog
        return ret;
1254 827df9f3 balrog
    }
1255 827df9f3 balrog
1256 827df9f3 balrog
    OMAP_BAD_REG(addr);
1257 827df9f3 balrog
    return 0;
1258 827df9f3 balrog
}
1259 827df9f3 balrog
1260 827df9f3 balrog
static void omap_mcspi_write(void *opaque, target_phys_addr_t addr,
1261 827df9f3 balrog
                uint32_t value)
1262 827df9f3 balrog
{
1263 827df9f3 balrog
    struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
1264 827df9f3 balrog
    int ch = 0;
1265 827df9f3 balrog
1266 8da3ff18 pbrook
    switch (addr) {
1267 827df9f3 balrog
    case 0x00:        /* MCSPI_REVISION */
1268 827df9f3 balrog
    case 0x14:        /* MCSPI_SYSSTATUS */
1269 827df9f3 balrog
    case 0x30:        /* MCSPI_CHSTAT0 */
1270 827df9f3 balrog
    case 0x3c:        /* MCSPI_RX0 */
1271 827df9f3 balrog
    case 0x44:        /* MCSPI_CHSTAT1 */
1272 827df9f3 balrog
    case 0x50:        /* MCSPI_RX1 */
1273 827df9f3 balrog
    case 0x58:        /* MCSPI_CHSTAT2 */
1274 827df9f3 balrog
    case 0x64:        /* MCSPI_RX2 */
1275 827df9f3 balrog
    case 0x6c:        /* MCSPI_CHSTAT3 */
1276 827df9f3 balrog
    case 0x78:        /* MCSPI_RX3 */
1277 827df9f3 balrog
        OMAP_RO_REG(addr);
1278 827df9f3 balrog
        return;
1279 827df9f3 balrog
1280 827df9f3 balrog
    case 0x10:        /* MCSPI_SYSCONFIG */
1281 827df9f3 balrog
        if (value & (1 << 1))                                /* SOFTRESET */
1282 827df9f3 balrog
            omap_mcspi_reset(s);
1283 827df9f3 balrog
        s->sysconfig = value & 0x31d;
1284 827df9f3 balrog
        break;
1285 827df9f3 balrog
1286 827df9f3 balrog
    case 0x18:        /* MCSPI_IRQSTATUS */
1287 827df9f3 balrog
        if (!((s->control & (1 << 3)) && (s->systest & (1 << 11)))) {
1288 827df9f3 balrog
            s->irqst &= ~value;
1289 827df9f3 balrog
            omap_mcspi_interrupt_update(s);
1290 827df9f3 balrog
        }
1291 827df9f3 balrog
        break;
1292 827df9f3 balrog
1293 827df9f3 balrog
    case 0x1c:        /* MCSPI_IRQENABLE */
1294 827df9f3 balrog
        s->irqen = value & 0x1777f;
1295 827df9f3 balrog
        omap_mcspi_interrupt_update(s);
1296 827df9f3 balrog
        break;
1297 827df9f3 balrog
1298 827df9f3 balrog
    case 0x20:        /* MCSPI_WAKEUPENABLE */
1299 827df9f3 balrog
        s->wken = value & 1;
1300 827df9f3 balrog
        break;
1301 827df9f3 balrog
1302 827df9f3 balrog
    case 0x24:        /* MCSPI_SYST */
1303 827df9f3 balrog
        if (s->control & (1 << 3))                        /* SYSTEM_TEST */
1304 827df9f3 balrog
            if (value & (1 << 11)) {                        /* SSB */
1305 827df9f3 balrog
                s->irqst |= 0x1777f;
1306 827df9f3 balrog
                omap_mcspi_interrupt_update(s);
1307 827df9f3 balrog
            }
1308 827df9f3 balrog
        s->systest = value & 0xfff;
1309 827df9f3 balrog
        break;
1310 827df9f3 balrog
1311 827df9f3 balrog
    case 0x28:        /* MCSPI_MODULCTRL */
1312 827df9f3 balrog
        if (value & (1 << 3))                                /* SYSTEM_TEST */
1313 827df9f3 balrog
            if (s->systest & (1 << 11)) {                /* SSB */
1314 827df9f3 balrog
                s->irqst |= 0x1777f;
1315 827df9f3 balrog
                omap_mcspi_interrupt_update(s);
1316 827df9f3 balrog
            }
1317 827df9f3 balrog
        s->control = value & 0xf;
1318 827df9f3 balrog
        break;
1319 827df9f3 balrog
1320 827df9f3 balrog
    case 0x68: ch ++;
1321 827df9f3 balrog
    case 0x54: ch ++;
1322 827df9f3 balrog
    case 0x40: ch ++;
1323 827df9f3 balrog
    case 0x2c:        /* MCSPI_CHCONF */
1324 827df9f3 balrog
        if ((value ^ s->ch[ch].config) & (3 << 14))        /* DMAR | DMAW */
1325 827df9f3 balrog
            omap_mcspi_dmarequest_update(s->ch + ch);
1326 827df9f3 balrog
        if (((value >> 12) & 3) == 3)                        /* TRM */
1327 827df9f3 balrog
            fprintf(stderr, "%s: invalid TRM value (3)\n", __FUNCTION__);
1328 827df9f3 balrog
        if (((value >> 7) & 0x1f) < 3)                        /* WL */
1329 827df9f3 balrog
            fprintf(stderr, "%s: invalid WL value (%i)\n",
1330 827df9f3 balrog
                            __FUNCTION__, (value >> 7) & 0x1f);
1331 827df9f3 balrog
        s->ch[ch].config = value & 0x7fffff;
1332 827df9f3 balrog
        break;
1333 827df9f3 balrog
1334 827df9f3 balrog
    case 0x70: ch ++;
1335 827df9f3 balrog
    case 0x5c: ch ++;
1336 827df9f3 balrog
    case 0x48: ch ++;
1337 827df9f3 balrog
    case 0x34:        /* MCSPI_CHCTRL */
1338 827df9f3 balrog
        if (value & ~s->ch[ch].control & 1) {                /* EN */
1339 827df9f3 balrog
            s->ch[ch].control |= 1;
1340 827df9f3 balrog
            omap_mcspi_transfer_run(s, ch);
1341 827df9f3 balrog
        } else
1342 827df9f3 balrog
            s->ch[ch].control = value & 1;
1343 827df9f3 balrog
        break;
1344 827df9f3 balrog
1345 827df9f3 balrog
    case 0x74: ch ++;
1346 827df9f3 balrog
    case 0x60: ch ++;
1347 827df9f3 balrog
    case 0x4c: ch ++;
1348 827df9f3 balrog
    case 0x38:        /* MCSPI_TX */
1349 827df9f3 balrog
        s->ch[ch].tx = value;
1350 827df9f3 balrog
        s->ch[ch].status &= ~(1 << 1);                        /* TXS */
1351 827df9f3 balrog
        omap_mcspi_transfer_run(s, ch);
1352 827df9f3 balrog
        break;
1353 827df9f3 balrog
1354 827df9f3 balrog
    default:
1355 827df9f3 balrog
        OMAP_BAD_REG(addr);
1356 827df9f3 balrog
        return;
1357 827df9f3 balrog
    }
1358 827df9f3 balrog
}
1359 827df9f3 balrog
1360 827df9f3 balrog
static CPUReadMemoryFunc *omap_mcspi_readfn[] = {
1361 827df9f3 balrog
    omap_badwidth_read32,
1362 827df9f3 balrog
    omap_badwidth_read32,
1363 827df9f3 balrog
    omap_mcspi_read,
1364 827df9f3 balrog
};
1365 827df9f3 balrog
1366 827df9f3 balrog
static CPUWriteMemoryFunc *omap_mcspi_writefn[] = {
1367 827df9f3 balrog
    omap_badwidth_write32,
1368 827df9f3 balrog
    omap_badwidth_write32,
1369 827df9f3 balrog
    omap_mcspi_write,
1370 827df9f3 balrog
};
1371 827df9f3 balrog
1372 827df9f3 balrog
struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum,
1373 827df9f3 balrog
                qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
1374 827df9f3 balrog
{
1375 827df9f3 balrog
    int iomemtype;
1376 827df9f3 balrog
    struct omap_mcspi_s *s = (struct omap_mcspi_s *)
1377 827df9f3 balrog
            qemu_mallocz(sizeof(struct omap_mcspi_s));
1378 827df9f3 balrog
    struct omap_mcspi_ch_s *ch = s->ch;
1379 827df9f3 balrog
1380 827df9f3 balrog
    s->irq = irq;
1381 827df9f3 balrog
    s->chnum = chnum;
1382 827df9f3 balrog
    while (chnum --) {
1383 827df9f3 balrog
        ch->txdrq = *drq ++;
1384 827df9f3 balrog
        ch->rxdrq = *drq ++;
1385 827df9f3 balrog
        ch ++;
1386 827df9f3 balrog
    }
1387 827df9f3 balrog
    omap_mcspi_reset(s);
1388 827df9f3 balrog
1389 c66fb5bc balrog
    iomemtype = l4_register_io_memory(0, omap_mcspi_readfn,
1390 827df9f3 balrog
                    omap_mcspi_writefn, s);
1391 8da3ff18 pbrook
    omap_l4_attach(ta, 0, iomemtype);
1392 827df9f3 balrog
1393 827df9f3 balrog
    return s;
1394 827df9f3 balrog
}
1395 827df9f3 balrog
1396 827df9f3 balrog
void omap_mcspi_attach(struct omap_mcspi_s *s,
1397 e927bb00 balrog
                uint32_t (*txrx)(void *opaque, uint32_t, int), void *opaque,
1398 827df9f3 balrog
                int chipselect)
1399 827df9f3 balrog
{
1400 827df9f3 balrog
    if (chipselect < 0 || chipselect >= s->chnum)
1401 2ac71179 Paul Brook
        hw_error("%s: Bad chipselect %i\n", __FUNCTION__, chipselect);
1402 827df9f3 balrog
1403 827df9f3 balrog
    s->ch[chipselect].txrx = txrx;
1404 827df9f3 balrog
    s->ch[chipselect].opaque = opaque;
1405 827df9f3 balrog
}
1406 827df9f3 balrog
1407 99570a40 balrog
/* Enhanced Audio Controller (CODEC only) */
1408 99570a40 balrog
struct omap_eac_s {
1409 99570a40 balrog
    qemu_irq irq;
1410 99570a40 balrog
1411 99570a40 balrog
    uint16_t sysconfig;
1412 99570a40 balrog
    uint8_t config[4];
1413 99570a40 balrog
    uint8_t control;
1414 99570a40 balrog
    uint8_t address;
1415 99570a40 balrog
    uint16_t data;
1416 99570a40 balrog
    uint8_t vtol;
1417 99570a40 balrog
    uint8_t vtsl;
1418 99570a40 balrog
    uint16_t mixer;
1419 99570a40 balrog
    uint16_t gain[4];
1420 99570a40 balrog
    uint8_t att;
1421 99570a40 balrog
    uint16_t max[7];
1422 99570a40 balrog
1423 99570a40 balrog
    struct {
1424 99570a40 balrog
        qemu_irq txdrq;
1425 99570a40 balrog
        qemu_irq rxdrq;
1426 99570a40 balrog
        uint32_t (*txrx)(void *opaque, uint32_t, int);
1427 99570a40 balrog
        void *opaque;
1428 99570a40 balrog
1429 99570a40 balrog
#define EAC_BUF_LEN 1024
1430 99570a40 balrog
        uint32_t rxbuf[EAC_BUF_LEN];
1431 ab17b46d balrog
        int rxoff;
1432 99570a40 balrog
        int rxlen;
1433 99570a40 balrog
        int rxavail;
1434 99570a40 balrog
        uint32_t txbuf[EAC_BUF_LEN];
1435 99570a40 balrog
        int txlen;
1436 99570a40 balrog
        int txavail;
1437 99570a40 balrog
1438 99570a40 balrog
        int enable;
1439 99570a40 balrog
        int rate;
1440 99570a40 balrog
1441 99570a40 balrog
        uint16_t config[4];
1442 99570a40 balrog
1443 99570a40 balrog
        /* These need to be moved to the actual codec */
1444 99570a40 balrog
        QEMUSoundCard card;
1445 99570a40 balrog
        SWVoiceIn *in_voice;
1446 99570a40 balrog
        SWVoiceOut *out_voice;
1447 99570a40 balrog
        int hw_enable;
1448 99570a40 balrog
    } codec;
1449 99570a40 balrog
1450 99570a40 balrog
    struct {
1451 99570a40 balrog
        uint8_t control;
1452 99570a40 balrog
        uint16_t config;
1453 99570a40 balrog
    } modem, bt;
1454 99570a40 balrog
};
1455 99570a40 balrog
1456 99570a40 balrog
static inline void omap_eac_interrupt_update(struct omap_eac_s *s)
1457 99570a40 balrog
{
1458 99570a40 balrog
    qemu_set_irq(s->irq, (s->codec.config[1] >> 14) & 1);        /* AURDI */
1459 99570a40 balrog
}
1460 99570a40 balrog
1461 99570a40 balrog
static inline void omap_eac_in_dmarequest_update(struct omap_eac_s *s)
1462 99570a40 balrog
{
1463 ab17b46d balrog
    qemu_set_irq(s->codec.rxdrq, (s->codec.rxavail || s->codec.rxlen) &&
1464 99570a40 balrog
                    ((s->codec.config[1] >> 12) & 1));                /* DMAREN */
1465 99570a40 balrog
}
1466 99570a40 balrog
1467 99570a40 balrog
static inline void omap_eac_out_dmarequest_update(struct omap_eac_s *s)
1468 99570a40 balrog
{
1469 99570a40 balrog
    qemu_set_irq(s->codec.txdrq, s->codec.txlen < s->codec.txavail &&
1470 99570a40 balrog
                    ((s->codec.config[1] >> 11) & 1));                /* DMAWEN */
1471 99570a40 balrog
}
1472 99570a40 balrog
1473 99570a40 balrog
static inline void omap_eac_in_refill(struct omap_eac_s *s)
1474 99570a40 balrog
{
1475 ab17b46d balrog
    int left = MIN(EAC_BUF_LEN - s->codec.rxlen, s->codec.rxavail) << 2;
1476 ab17b46d balrog
    int start = ((s->codec.rxoff + s->codec.rxlen) & (EAC_BUF_LEN - 1)) << 2;
1477 ab17b46d balrog
    int leftwrap = MIN(left, (EAC_BUF_LEN << 2) - start);
1478 ab17b46d balrog
    int recv = 1;
1479 ab17b46d balrog
    uint8_t *buf = (uint8_t *) s->codec.rxbuf + start;
1480 ab17b46d balrog
1481 ab17b46d balrog
    left -= leftwrap;
1482 ab17b46d balrog
    start = 0;
1483 ab17b46d balrog
    while (leftwrap && (recv = AUD_read(s->codec.in_voice, buf + start,
1484 ab17b46d balrog
                                    leftwrap)) > 0) {        /* Be defensive */
1485 ab17b46d balrog
        start += recv;
1486 ab17b46d balrog
        leftwrap -= recv;
1487 ab17b46d balrog
    }
1488 ab17b46d balrog
    if (recv <= 0)
1489 ab17b46d balrog
        s->codec.rxavail = 0;
1490 ab17b46d balrog
    else
1491 ab17b46d balrog
        s->codec.rxavail -= start >> 2;
1492 ab17b46d balrog
    s->codec.rxlen += start >> 2;
1493 ab17b46d balrog
1494 ab17b46d balrog
    if (recv > 0 && left > 0) {
1495 ab17b46d balrog
        start = 0;
1496 ab17b46d balrog
        while (left && (recv = AUD_read(s->codec.in_voice,
1497 ab17b46d balrog
                                        (uint8_t *) s->codec.rxbuf + start,
1498 ab17b46d balrog
                                        left)) > 0) {        /* Be defensive */
1499 ab17b46d balrog
            start += recv;
1500 ab17b46d balrog
            left -= recv;
1501 ab17b46d balrog
        }
1502 ab17b46d balrog
        if (recv <= 0)
1503 ab17b46d balrog
            s->codec.rxavail = 0;
1504 ab17b46d balrog
        else
1505 ab17b46d balrog
            s->codec.rxavail -= start >> 2;
1506 ab17b46d balrog
        s->codec.rxlen += start >> 2;
1507 ab17b46d balrog
    }
1508 99570a40 balrog
}
1509 99570a40 balrog
1510 99570a40 balrog
static inline void omap_eac_out_empty(struct omap_eac_s *s)
1511 99570a40 balrog
{
1512 ab17b46d balrog
    int left = s->codec.txlen << 2;
1513 ab17b46d balrog
    int start = 0;
1514 ab17b46d balrog
    int sent = 1;
1515 ab17b46d balrog
1516 ab17b46d balrog
    while (left && (sent = AUD_write(s->codec.out_voice,
1517 ab17b46d balrog
                                    (uint8_t *) s->codec.txbuf + start,
1518 ab17b46d balrog
                                    left)) > 0) {        /* Be defensive */
1519 ab17b46d balrog
        start += sent;
1520 ab17b46d balrog
        left -= sent;
1521 ab17b46d balrog
    }
1522 99570a40 balrog
1523 ab17b46d balrog
    if (!sent) {
1524 ab17b46d balrog
        s->codec.txavail = 0;
1525 ab17b46d balrog
        omap_eac_out_dmarequest_update(s);
1526 ab17b46d balrog
    }
1527 99570a40 balrog
1528 ab17b46d balrog
    if (start)
1529 ab17b46d balrog
        s->codec.txlen = 0;
1530 99570a40 balrog
}
1531 99570a40 balrog
1532 99570a40 balrog
static void omap_eac_in_cb(void *opaque, int avail_b)
1533 99570a40 balrog
{
1534 99570a40 balrog
    struct omap_eac_s *s = (struct omap_eac_s *) opaque;
1535 99570a40 balrog
1536 99570a40 balrog
    s->codec.rxavail = avail_b >> 2;
1537 ab17b46d balrog
    omap_eac_in_refill(s);
1538 99570a40 balrog
    /* TODO: possibly discard current buffer if overrun */
1539 ab17b46d balrog
    omap_eac_in_dmarequest_update(s);
1540 99570a40 balrog
}
1541 99570a40 balrog
1542 99570a40 balrog
static void omap_eac_out_cb(void *opaque, int free_b)
1543 99570a40 balrog
{
1544 99570a40 balrog
    struct omap_eac_s *s = (struct omap_eac_s *) opaque;
1545 99570a40 balrog
1546 99570a40 balrog
    s->codec.txavail = free_b >> 2;
1547 ab17b46d balrog
    if (s->codec.txlen)
1548 ab17b46d balrog
        omap_eac_out_empty(s);
1549 ab17b46d balrog
    else
1550 ab17b46d balrog
        omap_eac_out_dmarequest_update(s);
1551 99570a40 balrog
}
1552 99570a40 balrog
1553 99570a40 balrog
static void omap_eac_enable_update(struct omap_eac_s *s)
1554 99570a40 balrog
{
1555 99570a40 balrog
    s->codec.enable = !(s->codec.config[1] & 1) &&                /* EACPWD */
1556 99570a40 balrog
            (s->codec.config[1] & 2) &&                                /* AUDEN */
1557 99570a40 balrog
            s->codec.hw_enable;
1558 99570a40 balrog
}
1559 99570a40 balrog
1560 99570a40 balrog
static const int omap_eac_fsint[4] = {
1561 99570a40 balrog
    8000,
1562 99570a40 balrog
    11025,
1563 99570a40 balrog
    22050,
1564 99570a40 balrog
    44100,
1565 99570a40 balrog
};
1566 99570a40 balrog
1567 99570a40 balrog
static const int omap_eac_fsint2[8] = {
1568 99570a40 balrog
    8000,
1569 99570a40 balrog
    11025,
1570 99570a40 balrog
    22050,
1571 99570a40 balrog
    44100,
1572 99570a40 balrog
    48000,
1573 99570a40 balrog
    0, 0, 0,
1574 99570a40 balrog
};
1575 99570a40 balrog
1576 99570a40 balrog
static const int omap_eac_fsint3[16] = {
1577 99570a40 balrog
    8000,
1578 99570a40 balrog
    11025,
1579 99570a40 balrog
    16000,
1580 99570a40 balrog
    22050,
1581 99570a40 balrog
    24000,
1582 99570a40 balrog
    32000,
1583 99570a40 balrog
    44100,
1584 99570a40 balrog
    48000,
1585 99570a40 balrog
    0, 0, 0, 0, 0, 0, 0, 0,
1586 99570a40 balrog
};
1587 99570a40 balrog
1588 99570a40 balrog
static void omap_eac_rate_update(struct omap_eac_s *s)
1589 99570a40 balrog
{
1590 99570a40 balrog
    int fsint[3];
1591 99570a40 balrog
1592 99570a40 balrog
    fsint[2] = (s->codec.config[3] >> 9) & 0xf;
1593 99570a40 balrog
    fsint[1] = (s->codec.config[2] >> 0) & 0x7;
1594 99570a40 balrog
    fsint[0] = (s->codec.config[0] >> 6) & 0x3;
1595 99570a40 balrog
    if (fsint[2] < 0xf)
1596 99570a40 balrog
        s->codec.rate = omap_eac_fsint3[fsint[2]];
1597 99570a40 balrog
    else if (fsint[1] < 0x7)
1598 99570a40 balrog
        s->codec.rate = omap_eac_fsint2[fsint[1]];
1599 99570a40 balrog
    else
1600 99570a40 balrog
        s->codec.rate = omap_eac_fsint[fsint[0]];
1601 99570a40 balrog
}
1602 99570a40 balrog
1603 99570a40 balrog
static void omap_eac_volume_update(struct omap_eac_s *s)
1604 99570a40 balrog
{
1605 99570a40 balrog
    /* TODO */
1606 99570a40 balrog
}
1607 99570a40 balrog
1608 99570a40 balrog
static void omap_eac_format_update(struct omap_eac_s *s)
1609 99570a40 balrog
{
1610 1ea879e5 malc
    struct audsettings fmt;
1611 99570a40 balrog
1612 ab17b46d balrog
    /* The hardware buffers at most one sample */
1613 ab17b46d balrog
    if (s->codec.rxlen)
1614 ab17b46d balrog
        s->codec.rxlen = 1;
1615 99570a40 balrog
1616 99570a40 balrog
    if (s->codec.in_voice) {
1617 99570a40 balrog
        AUD_set_active_in(s->codec.in_voice, 0);
1618 99570a40 balrog
        AUD_close_in(&s->codec.card, s->codec.in_voice);
1619 99570a40 balrog
        s->codec.in_voice = 0;
1620 99570a40 balrog
    }
1621 99570a40 balrog
    if (s->codec.out_voice) {
1622 ab17b46d balrog
        omap_eac_out_empty(s);
1623 99570a40 balrog
        AUD_set_active_out(s->codec.out_voice, 0);
1624 99570a40 balrog
        AUD_close_out(&s->codec.card, s->codec.out_voice);
1625 99570a40 balrog
        s->codec.out_voice = 0;
1626 ab17b46d balrog
        s->codec.txavail = 0;
1627 99570a40 balrog
    }
1628 ab17b46d balrog
    /* Discard what couldn't be written */
1629 ab17b46d balrog
    s->codec.txlen = 0;
1630 99570a40 balrog
1631 99570a40 balrog
    omap_eac_enable_update(s);
1632 99570a40 balrog
    if (!s->codec.enable)
1633 99570a40 balrog
        return;
1634 99570a40 balrog
1635 99570a40 balrog
    omap_eac_rate_update(s);
1636 99570a40 balrog
    fmt.endianness = ((s->codec.config[0] >> 8) & 1);                /* LI_BI */
1637 99570a40 balrog
    fmt.nchannels = ((s->codec.config[0] >> 10) & 1) ? 2 : 1;        /* MN_ST */
1638 99570a40 balrog
    fmt.freq = s->codec.rate;
1639 99570a40 balrog
    /* TODO: signedness possibly depends on the CODEC hardware - or
1640 99570a40 balrog
     * does I2S specify it?  */
1641 99570a40 balrog
    /* All register writes are 16 bits so we we store 16-bit samples
1642 99570a40 balrog
     * in the buffers regardless of AGCFR[B8_16] value.  */
1643 99570a40 balrog
    fmt.fmt = AUD_FMT_U16;
1644 99570a40 balrog
1645 99570a40 balrog
    s->codec.in_voice = AUD_open_in(&s->codec.card, s->codec.in_voice,
1646 99570a40 balrog
                    "eac.codec.in", s, omap_eac_in_cb, &fmt);
1647 99570a40 balrog
    s->codec.out_voice = AUD_open_out(&s->codec.card, s->codec.out_voice,
1648 99570a40 balrog
                    "eac.codec.out", s, omap_eac_out_cb, &fmt);
1649 99570a40 balrog
1650 99570a40 balrog
    omap_eac_volume_update(s);
1651 99570a40 balrog
1652 99570a40 balrog
    AUD_set_active_in(s->codec.in_voice, 1);
1653 99570a40 balrog
    AUD_set_active_out(s->codec.out_voice, 1);
1654 99570a40 balrog
}
1655 99570a40 balrog
1656 99570a40 balrog
static void omap_eac_reset(struct omap_eac_s *s)
1657 99570a40 balrog
{
1658 99570a40 balrog
    s->sysconfig = 0;
1659 99570a40 balrog
    s->config[0] = 0x0c;
1660 99570a40 balrog
    s->config[1] = 0x09;
1661 99570a40 balrog
    s->config[2] = 0xab;
1662 99570a40 balrog
    s->config[3] = 0x03;
1663 99570a40 balrog
    s->control = 0x00;
1664 99570a40 balrog
    s->address = 0x00;
1665 99570a40 balrog
    s->data = 0x0000;
1666 99570a40 balrog
    s->vtol = 0x00;
1667 99570a40 balrog
    s->vtsl = 0x00;
1668 99570a40 balrog
    s->mixer = 0x0000;
1669 99570a40 balrog
    s->gain[0] = 0xe7e7;
1670 99570a40 balrog
    s->gain[1] = 0x6767;
1671 99570a40 balrog
    s->gain[2] = 0x6767;
1672 99570a40 balrog
    s->gain[3] = 0x6767;
1673 99570a40 balrog
    s->att = 0xce;
1674 99570a40 balrog
    s->max[0] = 0;
1675 99570a40 balrog
    s->max[1] = 0;
1676 99570a40 balrog
    s->max[2] = 0;
1677 99570a40 balrog
    s->max[3] = 0;
1678 99570a40 balrog
    s->max[4] = 0;
1679 99570a40 balrog
    s->max[5] = 0;
1680 99570a40 balrog
    s->max[6] = 0;
1681 99570a40 balrog
1682 99570a40 balrog
    s->modem.control = 0x00;
1683 99570a40 balrog
    s->modem.config = 0x0000;
1684 99570a40 balrog
    s->bt.control = 0x00;
1685 99570a40 balrog
    s->bt.config = 0x0000;
1686 99570a40 balrog
    s->codec.config[0] = 0x0649;
1687 99570a40 balrog
    s->codec.config[1] = 0x0000;
1688 99570a40 balrog
    s->codec.config[2] = 0x0007;
1689 99570a40 balrog
    s->codec.config[3] = 0x1ffc;
1690 ab17b46d balrog
    s->codec.rxoff = 0;
1691 99570a40 balrog
    s->codec.rxlen = 0;
1692 99570a40 balrog
    s->codec.txlen = 0;
1693 99570a40 balrog
    s->codec.rxavail = 0;
1694 99570a40 balrog
    s->codec.txavail = 0;
1695 99570a40 balrog
1696 99570a40 balrog
    omap_eac_format_update(s);
1697 99570a40 balrog
    omap_eac_interrupt_update(s);
1698 99570a40 balrog
}
1699 99570a40 balrog
1700 99570a40 balrog
static uint32_t omap_eac_read(void *opaque, target_phys_addr_t addr)
1701 99570a40 balrog
{
1702 99570a40 balrog
    struct omap_eac_s *s = (struct omap_eac_s *) opaque;
1703 ab17b46d balrog
    uint32_t ret;
1704 99570a40 balrog
1705 8da3ff18 pbrook
    switch (addr) {
1706 99570a40 balrog
    case 0x000:        /* CPCFR1 */
1707 99570a40 balrog
        return s->config[0];
1708 99570a40 balrog
    case 0x004:        /* CPCFR2 */
1709 99570a40 balrog
        return s->config[1];
1710 99570a40 balrog
    case 0x008:        /* CPCFR3 */
1711 99570a40 balrog
        return s->config[2];
1712 99570a40 balrog
    case 0x00c:        /* CPCFR4 */
1713 99570a40 balrog
        return s->config[3];
1714 99570a40 balrog
1715 99570a40 balrog
    case 0x010:        /* CPTCTL */
1716 99570a40 balrog
        return s->control | ((s->codec.rxavail + s->codec.rxlen > 0) << 7) |
1717 99570a40 balrog
                ((s->codec.txlen < s->codec.txavail) << 5);
1718 99570a40 balrog
1719 99570a40 balrog
    case 0x014:        /* CPTTADR */
1720 99570a40 balrog
        return s->address;
1721 99570a40 balrog
    case 0x018:        /* CPTDATL */
1722 99570a40 balrog
        return s->data & 0xff;
1723 99570a40 balrog
    case 0x01c:        /* CPTDATH */
1724 99570a40 balrog
        return s->data >> 8;
1725 99570a40 balrog
    case 0x020:        /* CPTVSLL */
1726 99570a40 balrog
        return s->vtol;
1727 99570a40 balrog
    case 0x024:        /* CPTVSLH */
1728 99570a40 balrog
        return s->vtsl | (3 << 5);        /* CRDY1 | CRDY2 */
1729 99570a40 balrog
    case 0x040:        /* MPCTR */
1730 99570a40 balrog
        return s->modem.control;
1731 99570a40 balrog
    case 0x044:        /* MPMCCFR */
1732 99570a40 balrog
        return s->modem.config;
1733 99570a40 balrog
    case 0x060:        /* BPCTR */
1734 99570a40 balrog
        return s->bt.control;
1735 99570a40 balrog
    case 0x064:        /* BPMCCFR */
1736 99570a40 balrog
        return s->bt.config;
1737 99570a40 balrog
    case 0x080:        /* AMSCFR */
1738 99570a40 balrog
        return s->mixer;
1739 99570a40 balrog
    case 0x084:        /* AMVCTR */
1740 99570a40 balrog
        return s->gain[0];
1741 99570a40 balrog
    case 0x088:        /* AM1VCTR */
1742 99570a40 balrog
        return s->gain[1];
1743 99570a40 balrog
    case 0x08c:        /* AM2VCTR */
1744 99570a40 balrog
        return s->gain[2];
1745 99570a40 balrog
    case 0x090:        /* AM3VCTR */
1746 99570a40 balrog
        return s->gain[3];
1747 99570a40 balrog
    case 0x094:        /* ASTCTR */
1748 99570a40 balrog
        return s->att;
1749 99570a40 balrog
    case 0x098:        /* APD1LCR */
1750 99570a40 balrog
        return s->max[0];
1751 99570a40 balrog
    case 0x09c:        /* APD1RCR */
1752 99570a40 balrog
        return s->max[1];
1753 99570a40 balrog
    case 0x0a0:        /* APD2LCR */
1754 99570a40 balrog
        return s->max[2];
1755 99570a40 balrog
    case 0x0a4:        /* APD2RCR */
1756 99570a40 balrog
        return s->max[3];
1757 99570a40 balrog
    case 0x0a8:        /* APD3LCR */
1758 99570a40 balrog
        return s->max[4];
1759 99570a40 balrog
    case 0x0ac:        /* APD3RCR */
1760 99570a40 balrog
        return s->max[5];
1761 99570a40 balrog
    case 0x0b0:        /* APD4R */
1762 99570a40 balrog
        return s->max[6];
1763 99570a40 balrog
    case 0x0b4:        /* ADWR */
1764 99570a40 balrog
        /* This should be write-only?  Docs list it as read-only.  */
1765 99570a40 balrog
        return 0x0000;
1766 99570a40 balrog
    case 0x0b8:        /* ADRDR */
1767 ab17b46d balrog
        if (likely(s->codec.rxlen > 1)) {
1768 ab17b46d balrog
            ret = s->codec.rxbuf[s->codec.rxoff ++];
1769 ab17b46d balrog
            s->codec.rxlen --;
1770 ab17b46d balrog
            s->codec.rxoff &= EAC_BUF_LEN - 1;
1771 ab17b46d balrog
            return ret;
1772 ab17b46d balrog
        } else if (s->codec.rxlen) {
1773 ab17b46d balrog
            ret = s->codec.rxbuf[s->codec.rxoff ++];
1774 ab17b46d balrog
            s->codec.rxlen --;
1775 ab17b46d balrog
            s->codec.rxoff &= EAC_BUF_LEN - 1;
1776 99570a40 balrog
            if (s->codec.rxavail)
1777 99570a40 balrog
                omap_eac_in_refill(s);
1778 ab17b46d balrog
            omap_eac_in_dmarequest_update(s);
1779 ab17b46d balrog
            return ret;
1780 99570a40 balrog
        }
1781 99570a40 balrog
        return 0x0000;
1782 99570a40 balrog
    case 0x0bc:        /* AGCFR */
1783 99570a40 balrog
        return s->codec.config[0];
1784 99570a40 balrog
    case 0x0c0:        /* AGCTR */
1785 99570a40 balrog
        return s->codec.config[1] | ((s->codec.config[1] & 2) << 14);
1786 99570a40 balrog
    case 0x0c4:        /* AGCFR2 */
1787 99570a40 balrog
        return s->codec.config[2];
1788 99570a40 balrog
    case 0x0c8:        /* AGCFR3 */
1789 99570a40 balrog
        return s->codec.config[3];
1790 99570a40 balrog
    case 0x0cc:        /* MBPDMACTR */
1791 99570a40 balrog
    case 0x0d0:        /* MPDDMARR */
1792 99570a40 balrog
    case 0x0d8:        /* MPUDMARR */
1793 99570a40 balrog
    case 0x0e4:        /* BPDDMARR */
1794 99570a40 balrog
    case 0x0ec:        /* BPUDMARR */
1795 99570a40 balrog
        return 0x0000;
1796 99570a40 balrog
1797 99570a40 balrog
    case 0x100:        /* VERSION_NUMBER */
1798 99570a40 balrog
        return 0x0010;
1799 99570a40 balrog
1800 99570a40 balrog
    case 0x104:        /* SYSCONFIG */
1801 99570a40 balrog
        return s->sysconfig;
1802 99570a40 balrog
1803 99570a40 balrog
    case 0x108:        /* SYSSTATUS */
1804 99570a40 balrog
        return 1 | 0xe;                                        /* RESETDONE | stuff */
1805 99570a40 balrog
    }
1806 99570a40 balrog
1807 99570a40 balrog
    OMAP_BAD_REG(addr);
1808 99570a40 balrog
    return 0;
1809 99570a40 balrog
}
1810 99570a40 balrog
1811 99570a40 balrog
static void omap_eac_write(void *opaque, target_phys_addr_t addr,
1812 99570a40 balrog
                uint32_t value)
1813 99570a40 balrog
{
1814 99570a40 balrog
    struct omap_eac_s *s = (struct omap_eac_s *) opaque;
1815 99570a40 balrog
1816 8da3ff18 pbrook
    switch (addr) {
1817 99570a40 balrog
    case 0x098:        /* APD1LCR */
1818 99570a40 balrog
    case 0x09c:        /* APD1RCR */
1819 99570a40 balrog
    case 0x0a0:        /* APD2LCR */
1820 99570a40 balrog
    case 0x0a4:        /* APD2RCR */
1821 99570a40 balrog
    case 0x0a8:        /* APD3LCR */
1822 99570a40 balrog
    case 0x0ac:        /* APD3RCR */
1823 99570a40 balrog
    case 0x0b0:        /* APD4R */
1824 99570a40 balrog
    case 0x0b8:        /* ADRDR */
1825 99570a40 balrog
    case 0x0d0:        /* MPDDMARR */
1826 99570a40 balrog
    case 0x0d8:        /* MPUDMARR */
1827 99570a40 balrog
    case 0x0e4:        /* BPDDMARR */
1828 99570a40 balrog
    case 0x0ec:        /* BPUDMARR */
1829 99570a40 balrog
    case 0x100:        /* VERSION_NUMBER */
1830 99570a40 balrog
    case 0x108:        /* SYSSTATUS */
1831 99570a40 balrog
        OMAP_RO_REG(addr);
1832 99570a40 balrog
        return;
1833 99570a40 balrog
1834 99570a40 balrog
    case 0x000:        /* CPCFR1 */
1835 99570a40 balrog
        s->config[0] = value & 0xff;
1836 99570a40 balrog
        omap_eac_format_update(s);
1837 99570a40 balrog
        break;
1838 99570a40 balrog
    case 0x004:        /* CPCFR2 */
1839 99570a40 balrog
        s->config[1] = value & 0xff;
1840 99570a40 balrog
        omap_eac_format_update(s);
1841 99570a40 balrog
        break;
1842 99570a40 balrog
    case 0x008:        /* CPCFR3 */
1843 99570a40 balrog
        s->config[2] = value & 0xff;
1844 99570a40 balrog
        omap_eac_format_update(s);
1845 99570a40 balrog
        break;
1846 99570a40 balrog
    case 0x00c:        /* CPCFR4 */
1847 99570a40 balrog
        s->config[3] = value & 0xff;
1848 99570a40 balrog
        omap_eac_format_update(s);
1849 99570a40 balrog
        break;
1850 99570a40 balrog
1851 99570a40 balrog
    case 0x010:        /* CPTCTL */
1852 99570a40 balrog
        /* Assuming TXF and TXE bits are read-only... */
1853 99570a40 balrog
        s->control = value & 0x5f;
1854 99570a40 balrog
        omap_eac_interrupt_update(s);
1855 99570a40 balrog
        break;
1856 99570a40 balrog
1857 99570a40 balrog
    case 0x014:        /* CPTTADR */
1858 99570a40 balrog
        s->address = value & 0xff;
1859 99570a40 balrog
        break;
1860 99570a40 balrog
    case 0x018:        /* CPTDATL */
1861 99570a40 balrog
        s->data &= 0xff00;
1862 99570a40 balrog
        s->data |= value & 0xff;
1863 99570a40 balrog
        break;
1864 99570a40 balrog
    case 0x01c:        /* CPTDATH */
1865 99570a40 balrog
        s->data &= 0x00ff;
1866 99570a40 balrog
        s->data |= value << 8;
1867 99570a40 balrog
        break;
1868 99570a40 balrog
    case 0x020:        /* CPTVSLL */
1869 99570a40 balrog
        s->vtol = value & 0xf8;
1870 99570a40 balrog
        break;
1871 99570a40 balrog
    case 0x024:        /* CPTVSLH */
1872 99570a40 balrog
        s->vtsl = value & 0x9f;
1873 99570a40 balrog
        break;
1874 99570a40 balrog
    case 0x040:        /* MPCTR */
1875 99570a40 balrog
        s->modem.control = value & 0x8f;
1876 99570a40 balrog
        break;
1877 99570a40 balrog
    case 0x044:        /* MPMCCFR */
1878 99570a40 balrog
        s->modem.config = value & 0x7fff;
1879 99570a40 balrog
        break;
1880 99570a40 balrog
    case 0x060:        /* BPCTR */
1881 99570a40 balrog
        s->bt.control = value & 0x8f;
1882 99570a40 balrog
        break;
1883 99570a40 balrog
    case 0x064:        /* BPMCCFR */
1884 99570a40 balrog
        s->bt.config = value & 0x7fff;
1885 99570a40 balrog
        break;
1886 99570a40 balrog
    case 0x080:        /* AMSCFR */
1887 99570a40 balrog
        s->mixer = value & 0x0fff;
1888 99570a40 balrog
        break;
1889 99570a40 balrog
    case 0x084:        /* AMVCTR */
1890 99570a40 balrog
        s->gain[0] = value & 0xffff;
1891 99570a40 balrog
        break;
1892 99570a40 balrog
    case 0x088:        /* AM1VCTR */
1893 99570a40 balrog
        s->gain[1] = value & 0xff7f;
1894 99570a40 balrog
        break;
1895 99570a40 balrog
    case 0x08c:        /* AM2VCTR */
1896 99570a40 balrog
        s->gain[2] = value & 0xff7f;
1897 99570a40 balrog
        break;
1898 99570a40 balrog
    case 0x090:        /* AM3VCTR */
1899 99570a40 balrog
        s->gain[3] = value & 0xff7f;
1900 99570a40 balrog
        break;
1901 99570a40 balrog
    case 0x094:        /* ASTCTR */
1902 99570a40 balrog
        s->att = value & 0xff;
1903 99570a40 balrog
        break;
1904 99570a40 balrog
1905 99570a40 balrog
    case 0x0b4:        /* ADWR */
1906 99570a40 balrog
        s->codec.txbuf[s->codec.txlen ++] = value;
1907 99570a40 balrog
        if (unlikely(s->codec.txlen == EAC_BUF_LEN ||
1908 99570a40 balrog
                                s->codec.txlen == s->codec.txavail)) {
1909 99570a40 balrog
            if (s->codec.txavail)
1910 99570a40 balrog
                omap_eac_out_empty(s);
1911 ab17b46d balrog
            /* Discard what couldn't be written */
1912 ab17b46d balrog
            s->codec.txlen = 0;
1913 99570a40 balrog
        }
1914 99570a40 balrog
        break;
1915 99570a40 balrog
1916 99570a40 balrog
    case 0x0bc:        /* AGCFR */
1917 99570a40 balrog
        s->codec.config[0] = value & 0x07ff;
1918 99570a40 balrog
        omap_eac_format_update(s);
1919 99570a40 balrog
        break;
1920 99570a40 balrog
    case 0x0c0:        /* AGCTR */
1921 99570a40 balrog
        s->codec.config[1] = value & 0x780f;
1922 99570a40 balrog
        omap_eac_format_update(s);
1923 99570a40 balrog
        break;
1924 99570a40 balrog
    case 0x0c4:        /* AGCFR2 */
1925 99570a40 balrog
        s->codec.config[2] = value & 0x003f;
1926 99570a40 balrog
        omap_eac_format_update(s);
1927 99570a40 balrog
        break;
1928 99570a40 balrog
    case 0x0c8:        /* AGCFR3 */
1929 99570a40 balrog
        s->codec.config[3] = value & 0xffff;
1930 99570a40 balrog
        omap_eac_format_update(s);
1931 99570a40 balrog
        break;
1932 99570a40 balrog
    case 0x0cc:        /* MBPDMACTR */
1933 99570a40 balrog
    case 0x0d4:        /* MPDDMAWR */
1934 99570a40 balrog
    case 0x0e0:        /* MPUDMAWR */
1935 99570a40 balrog
    case 0x0e8:        /* BPDDMAWR */
1936 99570a40 balrog
    case 0x0f0:        /* BPUDMAWR */
1937 99570a40 balrog
        break;
1938 99570a40 balrog
1939 99570a40 balrog
    case 0x104:        /* SYSCONFIG */
1940 99570a40 balrog
        if (value & (1 << 1))                                /* SOFTRESET */
1941 99570a40 balrog
            omap_eac_reset(s);
1942 99570a40 balrog
        s->sysconfig = value & 0x31d;
1943 99570a40 balrog
        break;
1944 99570a40 balrog
1945 99570a40 balrog
    default:
1946 99570a40 balrog
        OMAP_BAD_REG(addr);
1947 99570a40 balrog
        return;
1948 99570a40 balrog
    }
1949 99570a40 balrog
}
1950 99570a40 balrog
1951 99570a40 balrog
static CPUReadMemoryFunc *omap_eac_readfn[] = {
1952 99570a40 balrog
    omap_badwidth_read16,
1953 99570a40 balrog
    omap_eac_read,
1954 99570a40 balrog
    omap_badwidth_read16,
1955 99570a40 balrog
};
1956 99570a40 balrog
1957 99570a40 balrog
static CPUWriteMemoryFunc *omap_eac_writefn[] = {
1958 99570a40 balrog
    omap_badwidth_write16,
1959 99570a40 balrog
    omap_eac_write,
1960 99570a40 balrog
    omap_badwidth_write16,
1961 99570a40 balrog
};
1962 99570a40 balrog
1963 99570a40 balrog
struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
1964 99570a40 balrog
                qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
1965 99570a40 balrog
{
1966 99570a40 balrog
    int iomemtype;
1967 99570a40 balrog
    struct omap_eac_s *s = (struct omap_eac_s *)
1968 99570a40 balrog
            qemu_mallocz(sizeof(struct omap_eac_s));
1969 99570a40 balrog
1970 99570a40 balrog
    s->irq = irq;
1971 99570a40 balrog
    s->codec.rxdrq = *drq ++;
1972 99570a40 balrog
    s->codec.txdrq = *drq ++;
1973 99570a40 balrog
    omap_eac_reset(s);
1974 99570a40 balrog
1975 99570a40 balrog
#ifdef HAS_AUDIO
1976 1a7dafce malc
    AUD_register_card("OMAP EAC", &s->codec.card);
1977 99570a40 balrog
1978 99570a40 balrog
    iomemtype = cpu_register_io_memory(0, omap_eac_readfn,
1979 99570a40 balrog
                    omap_eac_writefn, s);
1980 8da3ff18 pbrook
    omap_l4_attach(ta, 0, iomemtype);
1981 99570a40 balrog
#endif
1982 99570a40 balrog
1983 99570a40 balrog
    return s;
1984 99570a40 balrog
}
1985 99570a40 balrog
1986 54585ffe balrog
/* STI/XTI (emulation interface) console - reverse engineered only */
1987 54585ffe balrog
struct omap_sti_s {
1988 54585ffe balrog
    qemu_irq irq;
1989 54585ffe balrog
    CharDriverState *chr;
1990 54585ffe balrog
1991 54585ffe balrog
    uint32_t sysconfig;
1992 54585ffe balrog
    uint32_t systest;
1993 54585ffe balrog
    uint32_t irqst;
1994 54585ffe balrog
    uint32_t irqen;
1995 54585ffe balrog
    uint32_t clkcontrol;
1996 54585ffe balrog
    uint32_t serial_config;
1997 54585ffe balrog
};
1998 54585ffe balrog
1999 54585ffe balrog
#define STI_TRACE_CONSOLE_CHANNEL        239
2000 54585ffe balrog
#define STI_TRACE_CONTROL_CHANNEL        253
2001 54585ffe balrog
2002 54585ffe balrog
static inline void omap_sti_interrupt_update(struct omap_sti_s *s)
2003 54585ffe balrog
{
2004 54585ffe balrog
    qemu_set_irq(s->irq, s->irqst & s->irqen);
2005 54585ffe balrog
}
2006 54585ffe balrog
2007 54585ffe balrog
static void omap_sti_reset(struct omap_sti_s *s)
2008 54585ffe balrog
{
2009 54585ffe balrog
    s->sysconfig = 0;
2010 54585ffe balrog
    s->irqst = 0;
2011 54585ffe balrog
    s->irqen = 0;
2012 54585ffe balrog
    s->clkcontrol = 0;
2013 54585ffe balrog
    s->serial_config = 0;
2014 54585ffe balrog
2015 54585ffe balrog
    omap_sti_interrupt_update(s);
2016 54585ffe balrog
}
2017 54585ffe balrog
2018 54585ffe balrog
static uint32_t omap_sti_read(void *opaque, target_phys_addr_t addr)
2019 54585ffe balrog
{
2020 54585ffe balrog
    struct omap_sti_s *s = (struct omap_sti_s *) opaque;
2021 54585ffe balrog
2022 8da3ff18 pbrook
    switch (addr) {
2023 54585ffe balrog
    case 0x00:        /* STI_REVISION */
2024 54585ffe balrog
        return 0x10;
2025 54585ffe balrog
2026 54585ffe balrog
    case 0x10:        /* STI_SYSCONFIG */
2027 54585ffe balrog
        return s->sysconfig;
2028 54585ffe balrog
2029 54585ffe balrog
    case 0x14:        /* STI_SYSSTATUS / STI_RX_STATUS / XTI_SYSSTATUS */
2030 54585ffe balrog
        return 0x00;
2031 54585ffe balrog
2032 54585ffe balrog
    case 0x18:        /* STI_IRQSTATUS */
2033 54585ffe balrog
        return s->irqst;
2034 54585ffe balrog
2035 54585ffe balrog
    case 0x1c:        /* STI_IRQSETEN / STI_IRQCLREN */
2036 54585ffe balrog
        return s->irqen;
2037 54585ffe balrog
2038 54585ffe balrog
    case 0x24:        /* STI_ER / STI_DR / XTI_TRACESELECT */
2039 54585ffe balrog
    case 0x28:        /* STI_RX_DR / XTI_RXDATA */
2040 e927bb00 balrog
        /* TODO */
2041 e927bb00 balrog
        return 0;
2042 54585ffe balrog
2043 54585ffe balrog
    case 0x2c:        /* STI_CLK_CTRL / XTI_SCLKCRTL */
2044 54585ffe balrog
        return s->clkcontrol;
2045 54585ffe balrog
2046 54585ffe balrog
    case 0x30:        /* STI_SERIAL_CFG / XTI_SCONFIG */
2047 54585ffe balrog
        return s->serial_config;
2048 54585ffe balrog
    }
2049 54585ffe balrog
2050 54585ffe balrog
    OMAP_BAD_REG(addr);
2051 54585ffe balrog
    return 0;
2052 54585ffe balrog
}
2053 54585ffe balrog
2054 54585ffe balrog
static void omap_sti_write(void *opaque, target_phys_addr_t addr,
2055 54585ffe balrog
                uint32_t value)
2056 54585ffe balrog
{
2057 54585ffe balrog
    struct omap_sti_s *s = (struct omap_sti_s *) opaque;
2058 54585ffe balrog
2059 8da3ff18 pbrook
    switch (addr) {
2060 54585ffe balrog
    case 0x00:        /* STI_REVISION */
2061 54585ffe balrog
    case 0x14:        /* STI_SYSSTATUS / STI_RX_STATUS / XTI_SYSSTATUS */
2062 54585ffe balrog
        OMAP_RO_REG(addr);
2063 54585ffe balrog
        return;
2064 54585ffe balrog
2065 54585ffe balrog
    case 0x10:        /* STI_SYSCONFIG */
2066 54585ffe balrog
        if (value & (1 << 1))                                /* SOFTRESET */
2067 54585ffe balrog
            omap_sti_reset(s);
2068 54585ffe balrog
        s->sysconfig = value & 0xfe;
2069 54585ffe balrog
        break;
2070 54585ffe balrog
2071 54585ffe balrog
    case 0x18:        /* STI_IRQSTATUS */
2072 54585ffe balrog
        s->irqst &= ~value;
2073 54585ffe balrog
        omap_sti_interrupt_update(s);
2074 54585ffe balrog
        break;
2075 54585ffe balrog
2076 54585ffe balrog
    case 0x1c:        /* STI_IRQSETEN / STI_IRQCLREN */
2077 54585ffe balrog
        s->irqen = value & 0xffff;
2078 54585ffe balrog
        omap_sti_interrupt_update(s);
2079 54585ffe balrog
        break;
2080 54585ffe balrog
2081 54585ffe balrog
    case 0x2c:        /* STI_CLK_CTRL / XTI_SCLKCRTL */
2082 54585ffe balrog
        s->clkcontrol = value & 0xff;
2083 54585ffe balrog
        break;
2084 54585ffe balrog
2085 54585ffe balrog
    case 0x30:        /* STI_SERIAL_CFG / XTI_SCONFIG */
2086 54585ffe balrog
        s->serial_config = value & 0xff;
2087 54585ffe balrog
        break;
2088 54585ffe balrog
2089 54585ffe balrog
    case 0x24:        /* STI_ER / STI_DR / XTI_TRACESELECT */
2090 54585ffe balrog
    case 0x28:        /* STI_RX_DR / XTI_RXDATA */
2091 e927bb00 balrog
        /* TODO */
2092 e927bb00 balrog
        return;
2093 e927bb00 balrog
2094 54585ffe balrog
    default:
2095 54585ffe balrog
        OMAP_BAD_REG(addr);
2096 54585ffe balrog
        return;
2097 54585ffe balrog
    }
2098 54585ffe balrog
}
2099 54585ffe balrog
2100 54585ffe balrog
static CPUReadMemoryFunc *omap_sti_readfn[] = {
2101 54585ffe balrog
    omap_badwidth_read32,
2102 54585ffe balrog
    omap_badwidth_read32,
2103 54585ffe balrog
    omap_sti_read,
2104 54585ffe balrog
};
2105 54585ffe balrog
2106 54585ffe balrog
static CPUWriteMemoryFunc *omap_sti_writefn[] = {
2107 54585ffe balrog
    omap_badwidth_write32,
2108 54585ffe balrog
    omap_badwidth_write32,
2109 54585ffe balrog
    omap_sti_write,
2110 54585ffe balrog
};
2111 54585ffe balrog
2112 54585ffe balrog
static uint32_t omap_sti_fifo_read(void *opaque, target_phys_addr_t addr)
2113 54585ffe balrog
{
2114 54585ffe balrog
    OMAP_BAD_REG(addr);
2115 54585ffe balrog
    return 0;
2116 54585ffe balrog
}
2117 54585ffe balrog
2118 54585ffe balrog
static void omap_sti_fifo_write(void *opaque, target_phys_addr_t addr,
2119 54585ffe balrog
                uint32_t value)
2120 54585ffe balrog
{
2121 54585ffe balrog
    struct omap_sti_s *s = (struct omap_sti_s *) opaque;
2122 8da3ff18 pbrook
    int ch = addr >> 6;
2123 54585ffe balrog
    uint8_t byte = value;
2124 54585ffe balrog
2125 54585ffe balrog
    if (ch == STI_TRACE_CONTROL_CHANNEL) {
2126 54585ffe balrog
        /* Flush channel <i>value</i>.  */
2127 75554a3c balrog
        qemu_chr_write(s->chr, (const uint8_t *) "\r", 1);
2128 54585ffe balrog
    } else if (ch == STI_TRACE_CONSOLE_CHANNEL || 1) {
2129 54585ffe balrog
        if (value == 0xc0 || value == 0xc3) {
2130 54585ffe balrog
            /* Open channel <i>ch</i>.  */
2131 54585ffe balrog
        } else if (value == 0x00)
2132 75554a3c balrog
            qemu_chr_write(s->chr, (const uint8_t *) "\n", 1);
2133 54585ffe balrog
        else
2134 54585ffe balrog
            qemu_chr_write(s->chr, &byte, 1);
2135 54585ffe balrog
    }
2136 54585ffe balrog
}
2137 54585ffe balrog
2138 54585ffe balrog
static CPUReadMemoryFunc *omap_sti_fifo_readfn[] = {
2139 54585ffe balrog
    omap_sti_fifo_read,
2140 54585ffe balrog
    omap_badwidth_read8,
2141 54585ffe balrog
    omap_badwidth_read8,
2142 54585ffe balrog
};
2143 54585ffe balrog
2144 54585ffe balrog
static CPUWriteMemoryFunc *omap_sti_fifo_writefn[] = {
2145 54585ffe balrog
    omap_sti_fifo_write,
2146 54585ffe balrog
    omap_badwidth_write8,
2147 54585ffe balrog
    omap_badwidth_write8,
2148 54585ffe balrog
};
2149 54585ffe balrog
2150 b1d8e52e blueswir1
static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta,
2151 54585ffe balrog
                target_phys_addr_t channel_base, qemu_irq irq, omap_clk clk,
2152 54585ffe balrog
                CharDriverState *chr)
2153 54585ffe balrog
{
2154 54585ffe balrog
    int iomemtype;
2155 54585ffe balrog
    struct omap_sti_s *s = (struct omap_sti_s *)
2156 54585ffe balrog
            qemu_mallocz(sizeof(struct omap_sti_s));
2157 54585ffe balrog
2158 54585ffe balrog
    s->irq = irq;
2159 54585ffe balrog
    omap_sti_reset(s);
2160 54585ffe balrog
2161 ceecf1d1 aurel32
    s->chr = chr ?: qemu_chr_open("null", "null", NULL);
2162 54585ffe balrog
2163 c66fb5bc balrog
    iomemtype = l4_register_io_memory(0, omap_sti_readfn,
2164 54585ffe balrog
                    omap_sti_writefn, s);
2165 8da3ff18 pbrook
    omap_l4_attach(ta, 0, iomemtype);
2166 54585ffe balrog
2167 54585ffe balrog
    iomemtype = cpu_register_io_memory(0, omap_sti_fifo_readfn,
2168 54585ffe balrog
                    omap_sti_fifo_writefn, s);
2169 8da3ff18 pbrook
    cpu_register_physical_memory(channel_base, 0x10000, iomemtype);
2170 54585ffe balrog
2171 54585ffe balrog
    return s;
2172 54585ffe balrog
}
2173 54585ffe balrog
2174 827df9f3 balrog
/* L4 Interconnect */
2175 827df9f3 balrog
struct omap_target_agent_s {
2176 827df9f3 balrog
    struct omap_l4_s *bus;
2177 827df9f3 balrog
    int regions;
2178 827df9f3 balrog
    struct omap_l4_region_s *start;
2179 827df9f3 balrog
    target_phys_addr_t base;
2180 827df9f3 balrog
    uint32_t component;
2181 827df9f3 balrog
    uint32_t control;
2182 827df9f3 balrog
    uint32_t status;
2183 827df9f3 balrog
};
2184 827df9f3 balrog
2185 827df9f3 balrog
struct omap_l4_s {
2186 827df9f3 balrog
    target_phys_addr_t base;
2187 827df9f3 balrog
    int ta_num;
2188 827df9f3 balrog
    struct omap_target_agent_s ta[0];
2189 827df9f3 balrog
};
2190 827df9f3 balrog
2191 c66fb5bc balrog
#ifdef L4_MUX_HACK
2192 c66fb5bc balrog
static int omap_l4_io_entries;
2193 c66fb5bc balrog
static int omap_cpu_io_entry;
2194 c66fb5bc balrog
static struct omap_l4_entry {
2195 c66fb5bc balrog
        CPUReadMemoryFunc **mem_read;
2196 c66fb5bc balrog
        CPUWriteMemoryFunc **mem_write;
2197 c66fb5bc balrog
        void *opaque;
2198 c66fb5bc balrog
} *omap_l4_io_entry;
2199 c66fb5bc balrog
static CPUReadMemoryFunc **omap_l4_io_readb_fn;
2200 c66fb5bc balrog
static CPUReadMemoryFunc **omap_l4_io_readh_fn;
2201 c66fb5bc balrog
static CPUReadMemoryFunc **omap_l4_io_readw_fn;
2202 c66fb5bc balrog
static CPUWriteMemoryFunc **omap_l4_io_writeb_fn;
2203 c66fb5bc balrog
static CPUWriteMemoryFunc **omap_l4_io_writeh_fn;
2204 c66fb5bc balrog
static CPUWriteMemoryFunc **omap_l4_io_writew_fn;
2205 c66fb5bc balrog
static void **omap_l4_io_opaque;
2206 c66fb5bc balrog
2207 c66fb5bc balrog
int l4_register_io_memory(int io_index, CPUReadMemoryFunc **mem_read,
2208 c66fb5bc balrog
                CPUWriteMemoryFunc **mem_write, void *opaque)
2209 c66fb5bc balrog
{
2210 c66fb5bc balrog
    omap_l4_io_entry[omap_l4_io_entries].mem_read = mem_read;
2211 c66fb5bc balrog
    omap_l4_io_entry[omap_l4_io_entries].mem_write = mem_write;
2212 c66fb5bc balrog
    omap_l4_io_entry[omap_l4_io_entries].opaque = opaque;
2213 c66fb5bc balrog
2214 c66fb5bc balrog
    return omap_l4_io_entries ++;
2215 c66fb5bc balrog
}
2216 c66fb5bc balrog
2217 c66fb5bc balrog
static uint32_t omap_l4_io_readb(void *opaque, target_phys_addr_t addr)
2218 c66fb5bc balrog
{
2219 c66fb5bc balrog
    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
2220 c66fb5bc balrog
2221 c66fb5bc balrog
    return omap_l4_io_readb_fn[i](omap_l4_io_opaque[i], addr);
2222 c66fb5bc balrog
}
2223 c66fb5bc balrog
2224 c66fb5bc balrog
static uint32_t omap_l4_io_readh(void *opaque, target_phys_addr_t addr)
2225 c66fb5bc balrog
{
2226 c66fb5bc balrog
    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
2227 c66fb5bc balrog
2228 c66fb5bc balrog
    return omap_l4_io_readh_fn[i](omap_l4_io_opaque[i], addr);
2229 c66fb5bc balrog
}
2230 c66fb5bc balrog
2231 c66fb5bc balrog
static uint32_t omap_l4_io_readw(void *opaque, target_phys_addr_t addr)
2232 c66fb5bc balrog
{
2233 c66fb5bc balrog
    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
2234 c66fb5bc balrog
2235 c66fb5bc balrog
    return omap_l4_io_readw_fn[i](omap_l4_io_opaque[i], addr);
2236 c66fb5bc balrog
}
2237 c66fb5bc balrog
2238 c66fb5bc balrog
static void omap_l4_io_writeb(void *opaque, target_phys_addr_t addr,
2239 c66fb5bc balrog
                uint32_t value)
2240 c66fb5bc balrog
{
2241 c66fb5bc balrog
    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
2242 c66fb5bc balrog
2243 c66fb5bc balrog
    return omap_l4_io_writeb_fn[i](omap_l4_io_opaque[i], addr, value);
2244 c66fb5bc balrog
}
2245 c66fb5bc balrog
2246 c66fb5bc balrog
static void omap_l4_io_writeh(void *opaque, target_phys_addr_t addr,
2247 c66fb5bc balrog
                uint32_t value)
2248 c66fb5bc balrog
{
2249 c66fb5bc balrog
    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
2250 c66fb5bc balrog
2251 c66fb5bc balrog
    return omap_l4_io_writeh_fn[i](omap_l4_io_opaque[i], addr, value);
2252 c66fb5bc balrog
}
2253 c66fb5bc balrog
2254 c66fb5bc balrog
static void omap_l4_io_writew(void *opaque, target_phys_addr_t addr,
2255 c66fb5bc balrog
                uint32_t value)
2256 c66fb5bc balrog
{
2257 c66fb5bc balrog
    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
2258 c66fb5bc balrog
2259 c66fb5bc balrog
    return omap_l4_io_writew_fn[i](omap_l4_io_opaque[i], addr, value);
2260 c66fb5bc balrog
}
2261 c66fb5bc balrog
2262 c66fb5bc balrog
static CPUReadMemoryFunc *omap_l4_io_readfn[] = {
2263 c66fb5bc balrog
    omap_l4_io_readb,
2264 c66fb5bc balrog
    omap_l4_io_readh,
2265 c66fb5bc balrog
    omap_l4_io_readw,
2266 c66fb5bc balrog
};
2267 c66fb5bc balrog
2268 c66fb5bc balrog
static CPUWriteMemoryFunc *omap_l4_io_writefn[] = {
2269 c66fb5bc balrog
    omap_l4_io_writeb,
2270 c66fb5bc balrog
    omap_l4_io_writeh,
2271 c66fb5bc balrog
    omap_l4_io_writew,
2272 c66fb5bc balrog
};
2273 c66fb5bc balrog
#endif
2274 c66fb5bc balrog
2275 827df9f3 balrog
struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num)
2276 827df9f3 balrog
{
2277 827df9f3 balrog
    struct omap_l4_s *bus = qemu_mallocz(
2278 827df9f3 balrog
                    sizeof(*bus) + ta_num * sizeof(*bus->ta));
2279 827df9f3 balrog
2280 827df9f3 balrog
    bus->ta_num = ta_num;
2281 827df9f3 balrog
    bus->base = base;
2282 827df9f3 balrog
2283 c66fb5bc balrog
#ifdef L4_MUX_HACK
2284 c66fb5bc balrog
    omap_l4_io_entries = 1;
2285 c66fb5bc balrog
    omap_l4_io_entry = qemu_mallocz(125 * sizeof(*omap_l4_io_entry));
2286 c66fb5bc balrog
2287 c66fb5bc balrog
    omap_cpu_io_entry =
2288 c66fb5bc balrog
            cpu_register_io_memory(0, omap_l4_io_readfn,
2289 c66fb5bc balrog
                            omap_l4_io_writefn, bus);
2290 c66fb5bc balrog
# define L4_PAGES        (0xb4000 / TARGET_PAGE_SIZE)
2291 c66fb5bc balrog
    omap_l4_io_readb_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
2292 c66fb5bc balrog
    omap_l4_io_readh_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
2293 c66fb5bc balrog
    omap_l4_io_readw_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
2294 c66fb5bc balrog
    omap_l4_io_writeb_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
2295 c66fb5bc balrog
    omap_l4_io_writeh_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
2296 c66fb5bc balrog
    omap_l4_io_writew_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
2297 c66fb5bc balrog
    omap_l4_io_opaque = qemu_mallocz(sizeof(void *) * L4_PAGES);
2298 c66fb5bc balrog
#endif
2299 c66fb5bc balrog
2300 827df9f3 balrog
    return bus;
2301 827df9f3 balrog
}
2302 827df9f3 balrog
2303 827df9f3 balrog
static uint32_t omap_l4ta_read(void *opaque, target_phys_addr_t addr)
2304 827df9f3 balrog
{
2305 827df9f3 balrog
    struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
2306 827df9f3 balrog
2307 8da3ff18 pbrook
    switch (addr) {
2308 827df9f3 balrog
    case 0x00:        /* COMPONENT */
2309 827df9f3 balrog
        return s->component;
2310 827df9f3 balrog
2311 827df9f3 balrog
    case 0x20:        /* AGENT_CONTROL */
2312 827df9f3 balrog
        return s->control;
2313 827df9f3 balrog
2314 827df9f3 balrog
    case 0x28:        /* AGENT_STATUS */
2315 827df9f3 balrog
        return s->status;
2316 827df9f3 balrog
    }
2317 827df9f3 balrog
2318 827df9f3 balrog
    OMAP_BAD_REG(addr);
2319 827df9f3 balrog
    return 0;
2320 827df9f3 balrog
}
2321 827df9f3 balrog
2322 827df9f3 balrog
static void omap_l4ta_write(void *opaque, target_phys_addr_t addr,
2323 827df9f3 balrog
                uint32_t value)
2324 827df9f3 balrog
{
2325 827df9f3 balrog
    struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
2326 827df9f3 balrog
2327 8da3ff18 pbrook
    switch (addr) {
2328 827df9f3 balrog
    case 0x00:        /* COMPONENT */
2329 827df9f3 balrog
    case 0x28:        /* AGENT_STATUS */
2330 827df9f3 balrog
        OMAP_RO_REG(addr);
2331 827df9f3 balrog
        break;
2332 827df9f3 balrog
2333 827df9f3 balrog
    case 0x20:        /* AGENT_CONTROL */
2334 827df9f3 balrog
        s->control = value & 0x01000700;
2335 827df9f3 balrog
        if (value & 1)                                        /* OCP_RESET */
2336 827df9f3 balrog
            s->status &= ~1;                                /* REQ_TIMEOUT */
2337 827df9f3 balrog
        break;
2338 827df9f3 balrog
2339 827df9f3 balrog
    default:
2340 827df9f3 balrog
        OMAP_BAD_REG(addr);
2341 827df9f3 balrog
    }
2342 827df9f3 balrog
}
2343 827df9f3 balrog
2344 827df9f3 balrog
static CPUReadMemoryFunc *omap_l4ta_readfn[] = {
2345 827df9f3 balrog
    omap_badwidth_read16,
2346 827df9f3 balrog
    omap_l4ta_read,
2347 827df9f3 balrog
    omap_badwidth_read16,
2348 827df9f3 balrog
};
2349 827df9f3 balrog
2350 827df9f3 balrog
static CPUWriteMemoryFunc *omap_l4ta_writefn[] = {
2351 827df9f3 balrog
    omap_badwidth_write32,
2352 827df9f3 balrog
    omap_badwidth_write32,
2353 827df9f3 balrog
    omap_l4ta_write,
2354 827df9f3 balrog
};
2355 827df9f3 balrog
2356 827df9f3 balrog
#define L4TA(n)                (n)
2357 827df9f3 balrog
#define L4TAO(n)        ((n) + 39)
2358 827df9f3 balrog
2359 827df9f3 balrog
static struct omap_l4_region_s {
2360 827df9f3 balrog
    target_phys_addr_t offset;
2361 827df9f3 balrog
    size_t size;
2362 827df9f3 balrog
    int access;
2363 827df9f3 balrog
} omap_l4_region[125] = {
2364 827df9f3 balrog
    [  1] = { 0x40800,  0x800, 32          }, /* Initiator agent */
2365 827df9f3 balrog
    [  2] = { 0x41000, 0x1000, 32          }, /* Link agent */
2366 827df9f3 balrog
    [  0] = { 0x40000,  0x800, 32          }, /* Address and protection */
2367 827df9f3 balrog
    [  3] = { 0x00000, 0x1000, 32 | 16 | 8 }, /* System Control and Pinout */
2368 827df9f3 balrog
    [  4] = { 0x01000, 0x1000, 32 | 16 | 8 }, /* L4TAO1 */
2369 827df9f3 balrog
    [  5] = { 0x04000, 0x1000, 32 | 16     }, /* 32K Timer */
2370 827df9f3 balrog
    [  6] = { 0x05000, 0x1000, 32 | 16 | 8 }, /* L4TAO2 */
2371 827df9f3 balrog
    [  7] = { 0x08000,  0x800, 32          }, /* PRCM Region A */
2372 827df9f3 balrog
    [  8] = { 0x08800,  0x800, 32          }, /* PRCM Region B */
2373 827df9f3 balrog
    [  9] = { 0x09000, 0x1000, 32 | 16 | 8 }, /* L4TAO */
2374 827df9f3 balrog
    [ 10] = { 0x12000, 0x1000, 32 | 16 | 8 }, /* Test (BCM) */
2375 827df9f3 balrog
    [ 11] = { 0x13000, 0x1000, 32 | 16 | 8 }, /* L4TA1 */
2376 827df9f3 balrog
    [ 12] = { 0x14000, 0x1000, 32          }, /* Test/emulation (TAP) */
2377 827df9f3 balrog
    [ 13] = { 0x15000, 0x1000, 32 | 16 | 8 }, /* L4TA2 */
2378 827df9f3 balrog
    [ 14] = { 0x18000, 0x1000, 32 | 16 | 8 }, /* GPIO1 */
2379 827df9f3 balrog
    [ 16] = { 0x1a000, 0x1000, 32 | 16 | 8 }, /* GPIO2 */
2380 827df9f3 balrog
    [ 18] = { 0x1c000, 0x1000, 32 | 16 | 8 }, /* GPIO3 */
2381 827df9f3 balrog
    [ 19] = { 0x1e000, 0x1000, 32 | 16 | 8 }, /* GPIO4 */
2382 827df9f3 balrog
    [ 15] = { 0x19000, 0x1000, 32 | 16 | 8 }, /* Quad GPIO TOP */
2383 827df9f3 balrog
    [ 17] = { 0x1b000, 0x1000, 32 | 16 | 8 }, /* L4TA3 */
2384 827df9f3 balrog
    [ 20] = { 0x20000, 0x1000, 32 | 16 | 8 }, /* WD Timer 1 (Secure) */
2385 827df9f3 balrog
    [ 22] = { 0x22000, 0x1000, 32 | 16 | 8 }, /* WD Timer 2 (OMAP) */
2386 827df9f3 balrog
    [ 21] = { 0x21000, 0x1000, 32 | 16 | 8 }, /* Dual WD timer TOP */
2387 827df9f3 balrog
    [ 23] = { 0x23000, 0x1000, 32 | 16 | 8 }, /* L4TA4 */
2388 827df9f3 balrog
    [ 24] = { 0x28000, 0x1000, 32 | 16 | 8 }, /* GP Timer 1 */
2389 827df9f3 balrog
    [ 25] = { 0x29000, 0x1000, 32 | 16 | 8 }, /* L4TA7 */
2390 827df9f3 balrog
    [ 26] = { 0x48000, 0x2000, 32 | 16 | 8 }, /* Emulation (ARM11ETB) */
2391 827df9f3 balrog
    [ 27] = { 0x4a000, 0x1000, 32 | 16 | 8 }, /* L4TA9 */
2392 827df9f3 balrog
    [ 28] = { 0x50000,  0x400, 32 | 16 | 8 }, /* Display top */
2393 827df9f3 balrog
    [ 29] = { 0x50400,  0x400, 32 | 16 | 8 }, /* Display control */
2394 827df9f3 balrog
    [ 30] = { 0x50800,  0x400, 32 | 16 | 8 }, /* Display RFBI */
2395 827df9f3 balrog
    [ 31] = { 0x50c00,  0x400, 32 | 16 | 8 }, /* Display encoder */
2396 827df9f3 balrog
    [ 32] = { 0x51000, 0x1000, 32 | 16 | 8 }, /* L4TA10 */
2397 827df9f3 balrog
    [ 33] = { 0x52000,  0x400, 32 | 16 | 8 }, /* Camera top */
2398 827df9f3 balrog
    [ 34] = { 0x52400,  0x400, 32 | 16 | 8 }, /* Camera core */
2399 827df9f3 balrog
    [ 35] = { 0x52800,  0x400, 32 | 16 | 8 }, /* Camera DMA */
2400 827df9f3 balrog
    [ 36] = { 0x52c00,  0x400, 32 | 16 | 8 }, /* Camera MMU */
2401 827df9f3 balrog
    [ 37] = { 0x53000, 0x1000, 32 | 16 | 8 }, /* L4TA11 */
2402 827df9f3 balrog
    [ 38] = { 0x56000, 0x1000, 32 | 16 | 8 }, /* sDMA */
2403 827df9f3 balrog
    [ 39] = { 0x57000, 0x1000, 32 | 16 | 8 }, /* L4TA12 */
2404 827df9f3 balrog
    [ 40] = { 0x58000, 0x1000, 32 | 16 | 8 }, /* SSI top */
2405 827df9f3 balrog
    [ 41] = { 0x59000, 0x1000, 32 | 16 | 8 }, /* SSI GDD */
2406 827df9f3 balrog
    [ 42] = { 0x5a000, 0x1000, 32 | 16 | 8 }, /* SSI Port1 */
2407 827df9f3 balrog
    [ 43] = { 0x5b000, 0x1000, 32 | 16 | 8 }, /* SSI Port2 */
2408 827df9f3 balrog
    [ 44] = { 0x5c000, 0x1000, 32 | 16 | 8 }, /* L4TA13 */
2409 827df9f3 balrog
    [ 45] = { 0x5e000, 0x1000, 32 | 16 | 8 }, /* USB OTG */
2410 827df9f3 balrog
    [ 46] = { 0x5f000, 0x1000, 32 | 16 | 8 }, /* L4TAO4 */
2411 827df9f3 balrog
    [ 47] = { 0x60000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER1SDRC) */
2412 827df9f3 balrog
    [ 48] = { 0x61000, 0x1000, 32 | 16 | 8 }, /* L4TA14 */
2413 827df9f3 balrog
    [ 49] = { 0x62000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER2GPMC) */
2414 827df9f3 balrog
    [ 50] = { 0x63000, 0x1000, 32 | 16 | 8 }, /* L4TA15 */
2415 827df9f3 balrog
    [ 51] = { 0x64000, 0x1000, 32 | 16 | 8 }, /* Emulation (WIN_TRACER3OCM) */
2416 827df9f3 balrog
    [ 52] = { 0x65000, 0x1000, 32 | 16 | 8 }, /* L4TA16 */
2417 827df9f3 balrog
    [ 53] = { 0x66000,  0x300, 32 | 16 | 8 }, /* Emulation (WIN_TRACER4L4) */
2418 827df9f3 balrog
    [ 54] = { 0x67000, 0x1000, 32 | 16 | 8 }, /* L4TA17 */
2419 827df9f3 balrog
    [ 55] = { 0x68000, 0x1000, 32 | 16 | 8 }, /* Emulation (XTI) */
2420 827df9f3 balrog
    [ 56] = { 0x69000, 0x1000, 32 | 16 | 8 }, /* L4TA18 */
2421 827df9f3 balrog
    [ 57] = { 0x6a000, 0x1000,      16 | 8 }, /* UART1 */
2422 827df9f3 balrog
    [ 58] = { 0x6b000, 0x1000, 32 | 16 | 8 }, /* L4TA19 */
2423 827df9f3 balrog
    [ 59] = { 0x6c000, 0x1000,      16 | 8 }, /* UART2 */
2424 827df9f3 balrog
    [ 60] = { 0x6d000, 0x1000, 32 | 16 | 8 }, /* L4TA20 */
2425 827df9f3 balrog
    [ 61] = { 0x6e000, 0x1000,      16 | 8 }, /* UART3 */
2426 827df9f3 balrog
    [ 62] = { 0x6f000, 0x1000, 32 | 16 | 8 }, /* L4TA21 */
2427 827df9f3 balrog
    [ 63] = { 0x70000, 0x1000,      16     }, /* I2C1 */
2428 827df9f3 balrog
    [ 64] = { 0x71000, 0x1000, 32 | 16 | 8 }, /* L4TAO5 */
2429 827df9f3 balrog
    [ 65] = { 0x72000, 0x1000,      16     }, /* I2C2 */
2430 827df9f3 balrog
    [ 66] = { 0x73000, 0x1000, 32 | 16 | 8 }, /* L4TAO6 */
2431 827df9f3 balrog
    [ 67] = { 0x74000, 0x1000,      16     }, /* McBSP1 */
2432 827df9f3 balrog
    [ 68] = { 0x75000, 0x1000, 32 | 16 | 8 }, /* L4TAO7 */
2433 827df9f3 balrog
    [ 69] = { 0x76000, 0x1000,      16     }, /* McBSP2 */
2434 827df9f3 balrog
    [ 70] = { 0x77000, 0x1000, 32 | 16 | 8 }, /* L4TAO8 */
2435 827df9f3 balrog
    [ 71] = { 0x24000, 0x1000, 32 | 16 | 8 }, /* WD Timer 3 (DSP) */
2436 827df9f3 balrog
    [ 72] = { 0x25000, 0x1000, 32 | 16 | 8 }, /* L4TA5 */
2437 827df9f3 balrog
    [ 73] = { 0x26000, 0x1000, 32 | 16 | 8 }, /* WD Timer 4 (IVA) */
2438 827df9f3 balrog
    [ 74] = { 0x27000, 0x1000, 32 | 16 | 8 }, /* L4TA6 */
2439 827df9f3 balrog
    [ 75] = { 0x2a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 2 */
2440 827df9f3 balrog
    [ 76] = { 0x2b000, 0x1000, 32 | 16 | 8 }, /* L4TA8 */
2441 827df9f3 balrog
    [ 77] = { 0x78000, 0x1000, 32 | 16 | 8 }, /* GP Timer 3 */
2442 827df9f3 balrog
    [ 78] = { 0x79000, 0x1000, 32 | 16 | 8 }, /* L4TA22 */
2443 827df9f3 balrog
    [ 79] = { 0x7a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 4 */
2444 827df9f3 balrog
    [ 80] = { 0x7b000, 0x1000, 32 | 16 | 8 }, /* L4TA23 */
2445 827df9f3 balrog
    [ 81] = { 0x7c000, 0x1000, 32 | 16 | 8 }, /* GP Timer 5 */
2446 827df9f3 balrog
    [ 82] = { 0x7d000, 0x1000, 32 | 16 | 8 }, /* L4TA24 */
2447 827df9f3 balrog
    [ 83] = { 0x7e000, 0x1000, 32 | 16 | 8 }, /* GP Timer 6 */
2448 827df9f3 balrog
    [ 84] = { 0x7f000, 0x1000, 32 | 16 | 8 }, /* L4TA25 */
2449 827df9f3 balrog
    [ 85] = { 0x80000, 0x1000, 32 | 16 | 8 }, /* GP Timer 7 */
2450 827df9f3 balrog
    [ 86] = { 0x81000, 0x1000, 32 | 16 | 8 }, /* L4TA26 */
2451 827df9f3 balrog
    [ 87] = { 0x82000, 0x1000, 32 | 16 | 8 }, /* GP Timer 8 */
2452 827df9f3 balrog
    [ 88] = { 0x83000, 0x1000, 32 | 16 | 8 }, /* L4TA27 */
2453 827df9f3 balrog
    [ 89] = { 0x84000, 0x1000, 32 | 16 | 8 }, /* GP Timer 9 */
2454 827df9f3 balrog
    [ 90] = { 0x85000, 0x1000, 32 | 16 | 8 }, /* L4TA28 */
2455 827df9f3 balrog
    [ 91] = { 0x86000, 0x1000, 32 | 16 | 8 }, /* GP Timer 10 */
2456 827df9f3 balrog
    [ 92] = { 0x87000, 0x1000, 32 | 16 | 8 }, /* L4TA29 */
2457 827df9f3 balrog
    [ 93] = { 0x88000, 0x1000, 32 | 16 | 8 }, /* GP Timer 11 */
2458 827df9f3 balrog
    [ 94] = { 0x89000, 0x1000, 32 | 16 | 8 }, /* L4TA30 */
2459 827df9f3 balrog
    [ 95] = { 0x8a000, 0x1000, 32 | 16 | 8 }, /* GP Timer 12 */
2460 827df9f3 balrog
    [ 96] = { 0x8b000, 0x1000, 32 | 16 | 8 }, /* L4TA31 */
2461 827df9f3 balrog
    [ 97] = { 0x90000, 0x1000,      16     }, /* EAC */
2462 827df9f3 balrog
    [ 98] = { 0x91000, 0x1000, 32 | 16 | 8 }, /* L4TA32 */
2463 827df9f3 balrog
    [ 99] = { 0x92000, 0x1000,      16     }, /* FAC */
2464 827df9f3 balrog
    [100] = { 0x93000, 0x1000, 32 | 16 | 8 }, /* L4TA33 */
2465 827df9f3 balrog
    [101] = { 0x94000, 0x1000, 32 | 16 | 8 }, /* IPC (MAILBOX) */
2466 827df9f3 balrog
    [102] = { 0x95000, 0x1000, 32 | 16 | 8 }, /* L4TA34 */
2467 827df9f3 balrog
    [103] = { 0x98000, 0x1000, 32 | 16 | 8 }, /* SPI1 */
2468 827df9f3 balrog
    [104] = { 0x99000, 0x1000, 32 | 16 | 8 }, /* L4TA35 */
2469 827df9f3 balrog
    [105] = { 0x9a000, 0x1000, 32 | 16 | 8 }, /* SPI2 */
2470 827df9f3 balrog
    [106] = { 0x9b000, 0x1000, 32 | 16 | 8 }, /* L4TA36 */
2471 827df9f3 balrog
    [107] = { 0x9c000, 0x1000,      16 | 8 }, /* MMC SDIO */
2472 827df9f3 balrog
    [108] = { 0x9d000, 0x1000, 32 | 16 | 8 }, /* L4TAO9 */
2473 827df9f3 balrog
    [109] = { 0x9e000, 0x1000, 32 | 16 | 8 }, /* MS_PRO */
2474 827df9f3 balrog
    [110] = { 0x9f000, 0x1000, 32 | 16 | 8 }, /* L4TAO10 */
2475 827df9f3 balrog
    [111] = { 0xa0000, 0x1000, 32          }, /* RNG */
2476 827df9f3 balrog
    [112] = { 0xa1000, 0x1000, 32 | 16 | 8 }, /* L4TAO11 */
2477 827df9f3 balrog
    [113] = { 0xa2000, 0x1000, 32          }, /* DES3DES */
2478 827df9f3 balrog
    [114] = { 0xa3000, 0x1000, 32 | 16 | 8 }, /* L4TAO12 */
2479 827df9f3 balrog
    [115] = { 0xa4000, 0x1000, 32          }, /* SHA1MD5 */
2480 827df9f3 balrog
    [116] = { 0xa5000, 0x1000, 32 | 16 | 8 }, /* L4TAO13 */
2481 827df9f3 balrog
    [117] = { 0xa6000, 0x1000, 32          }, /* AES */
2482 827df9f3 balrog
    [118] = { 0xa7000, 0x1000, 32 | 16 | 8 }, /* L4TA37 */
2483 827df9f3 balrog
    [119] = { 0xa8000, 0x2000, 32          }, /* PKA */
2484 827df9f3 balrog
    [120] = { 0xaa000, 0x1000, 32 | 16 | 8 }, /* L4TA38 */
2485 827df9f3 balrog
    [121] = { 0xb0000, 0x1000, 32          }, /* MG */
2486 827df9f3 balrog
    [122] = { 0xb1000, 0x1000, 32 | 16 | 8 },
2487 827df9f3 balrog
    [123] = { 0xb2000, 0x1000, 32          }, /* HDQ/1-Wire */
2488 827df9f3 balrog
    [124] = { 0xb3000, 0x1000, 32 | 16 | 8 }, /* L4TA39 */
2489 827df9f3 balrog
};
2490 827df9f3 balrog
2491 827df9f3 balrog
static struct omap_l4_agent_info_s {
2492 827df9f3 balrog
    int ta;
2493 827df9f3 balrog
    int region;
2494 827df9f3 balrog
    int regions;
2495 827df9f3 balrog
    int ta_region;
2496 827df9f3 balrog
} omap_l4_agent_info[54] = {
2497 827df9f3 balrog
    { 0,           0, 3, 2 }, /* L4IA initiatior agent */
2498 827df9f3 balrog
    { L4TAO(1),    3, 2, 1 }, /* Control and pinout module */
2499 827df9f3 balrog
    { L4TAO(2),    5, 2, 1 }, /* 32K timer */
2500 827df9f3 balrog
    { L4TAO(3),    7, 3, 2 }, /* PRCM */
2501 827df9f3 balrog
    { L4TA(1),    10, 2, 1 }, /* BCM */
2502 827df9f3 balrog
    { L4TA(2),    12, 2, 1 }, /* Test JTAG */
2503 827df9f3 balrog
    { L4TA(3),    14, 6, 3 }, /* Quad GPIO */
2504 827df9f3 balrog
    { L4TA(4),    20, 4, 3 }, /* WD timer 1/2 */
2505 827df9f3 balrog
    { L4TA(7),    24, 2, 1 }, /* GP timer 1 */
2506 827df9f3 balrog
    { L4TA(9),    26, 2, 1 }, /* ATM11 ETB */
2507 827df9f3 balrog
    { L4TA(10),   28, 5, 4 }, /* Display subsystem */
2508 827df9f3 balrog
    { L4TA(11),   33, 5, 4 }, /* Camera subsystem */
2509 827df9f3 balrog
    { L4TA(12),   38, 2, 1 }, /* sDMA */
2510 827df9f3 balrog
    { L4TA(13),   40, 5, 4 }, /* SSI */
2511 827df9f3 balrog
    { L4TAO(4),   45, 2, 1 }, /* USB */
2512 827df9f3 balrog
    { L4TA(14),   47, 2, 1 }, /* Win Tracer1 */
2513 827df9f3 balrog
    { L4TA(15),   49, 2, 1 }, /* Win Tracer2 */
2514 827df9f3 balrog
    { L4TA(16),   51, 2, 1 }, /* Win Tracer3 */
2515 827df9f3 balrog
    { L4TA(17),   53, 2, 1 }, /* Win Tracer4 */
2516 827df9f3 balrog
    { L4TA(18),   55, 2, 1 }, /* XTI */
2517 827df9f3 balrog
    { L4TA(19),   57, 2, 1 }, /* UART1 */
2518 827df9f3 balrog
    { L4TA(20),   59, 2, 1 }, /* UART2 */
2519 827df9f3 balrog
    { L4TA(21),   61, 2, 1 }, /* UART3 */
2520 827df9f3 balrog
    { L4TAO(5),   63, 2, 1 }, /* I2C1 */
2521 827df9f3 balrog
    { L4TAO(6),   65, 2, 1 }, /* I2C2 */
2522 827df9f3 balrog
    { L4TAO(7),   67, 2, 1 }, /* McBSP1 */
2523 827df9f3 balrog
    { L4TAO(8),   69, 2, 1 }, /* McBSP2 */
2524 827df9f3 balrog
    { L4TA(5),    71, 2, 1 }, /* WD Timer 3 (DSP) */
2525 827df9f3 balrog
    { L4TA(6),    73, 2, 1 }, /* WD Timer 4 (IVA) */
2526 827df9f3 balrog
    { L4TA(8),    75, 2, 1 }, /* GP Timer 2 */
2527 827df9f3 balrog
    { L4TA(22),   77, 2, 1 }, /* GP Timer 3 */
2528 827df9f3 balrog
    { L4TA(23),   79, 2, 1 }, /* GP Timer 4 */
2529 827df9f3 balrog
    { L4TA(24),   81, 2, 1 }, /* GP Timer 5 */
2530 827df9f3 balrog
    { L4TA(25),   83, 2, 1 }, /* GP Timer 6 */
2531 827df9f3 balrog
    { L4TA(26),   85, 2, 1 }, /* GP Timer 7 */
2532 827df9f3 balrog
    { L4TA(27),   87, 2, 1 }, /* GP Timer 8 */
2533 827df9f3 balrog
    { L4TA(28),   89, 2, 1 }, /* GP Timer 9 */
2534 827df9f3 balrog
    { L4TA(29),   91, 2, 1 }, /* GP Timer 10 */
2535 827df9f3 balrog
    { L4TA(30),   93, 2, 1 }, /* GP Timer 11 */
2536 827df9f3 balrog
    { L4TA(31),   95, 2, 1 }, /* GP Timer 12 */
2537 827df9f3 balrog
    { L4TA(32),   97, 2, 1 }, /* EAC */
2538 827df9f3 balrog
    { L4TA(33),   99, 2, 1 }, /* FAC */
2539 827df9f3 balrog
    { L4TA(34),  101, 2, 1 }, /* IPC */
2540 827df9f3 balrog
    { L4TA(35),  103, 2, 1 }, /* SPI1 */
2541 827df9f3 balrog
    { L4TA(36),  105, 2, 1 }, /* SPI2 */
2542 827df9f3 balrog
    { L4TAO(9),  107, 2, 1 }, /* MMC SDIO */
2543 827df9f3 balrog
    { L4TAO(10), 109, 2, 1 },
2544 827df9f3 balrog
    { L4TAO(11), 111, 2, 1 }, /* RNG */
2545 827df9f3 balrog
    { L4TAO(12), 113, 2, 1 }, /* DES3DES */
2546 827df9f3 balrog
    { L4TAO(13), 115, 2, 1 }, /* SHA1MD5 */
2547 827df9f3 balrog
    { L4TA(37),  117, 2, 1 }, /* AES */
2548 827df9f3 balrog
    { L4TA(38),  119, 2, 1 }, /* PKA */
2549 827df9f3 balrog
    { -1,        121, 2, 1 },
2550 827df9f3 balrog
    { L4TA(39),  123, 2, 1 }, /* HDQ/1-Wire */
2551 827df9f3 balrog
};
2552 827df9f3 balrog
2553 827df9f3 balrog
#define omap_l4ta(bus, cs)        omap_l4ta_get(bus, L4TA(cs))
2554 827df9f3 balrog
#define omap_l4tao(bus, cs)        omap_l4ta_get(bus, L4TAO(cs))
2555 827df9f3 balrog
2556 827df9f3 balrog
struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus, int cs)
2557 827df9f3 balrog
{
2558 827df9f3 balrog
    int i, iomemtype;
2559 827df9f3 balrog
    struct omap_target_agent_s *ta = 0;
2560 827df9f3 balrog
    struct omap_l4_agent_info_s *info = 0;
2561 827df9f3 balrog
2562 827df9f3 balrog
    for (i = 0; i < bus->ta_num; i ++)
2563 827df9f3 balrog
        if (omap_l4_agent_info[i].ta == cs) {
2564 827df9f3 balrog
            ta = &bus->ta[i];
2565 827df9f3 balrog
            info = &omap_l4_agent_info[i];
2566 827df9f3 balrog
            break;
2567 827df9f3 balrog
        }
2568 827df9f3 balrog
    if (!ta) {
2569 827df9f3 balrog
        fprintf(stderr, "%s: bad target agent (%i)\n", __FUNCTION__, cs);
2570 827df9f3 balrog
        exit(-1);
2571 827df9f3 balrog
    }
2572 827df9f3 balrog
2573 827df9f3 balrog
    ta->bus = bus;
2574 827df9f3 balrog
    ta->start = &omap_l4_region[info->region];
2575 827df9f3 balrog
    ta->regions = info->regions;
2576 827df9f3 balrog
2577 827df9f3 balrog
    ta->component = ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
2578 827df9f3 balrog
    ta->status = 0x00000000;
2579 827df9f3 balrog
    ta->control = 0x00000200;        /* XXX 01000200 for L4TAO */
2580 827df9f3 balrog
2581 c66fb5bc balrog
    iomemtype = l4_register_io_memory(0, omap_l4ta_readfn,
2582 827df9f3 balrog
                    omap_l4ta_writefn, ta);
2583 c66fb5bc balrog
    ta->base = omap_l4_attach(ta, info->ta_region, iomemtype);
2584 827df9f3 balrog
2585 827df9f3 balrog
    return ta;
2586 827df9f3 balrog
}
2587 827df9f3 balrog
2588 827df9f3 balrog
target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
2589 827df9f3 balrog
                int iotype)
2590 827df9f3 balrog
{
2591 827df9f3 balrog
    target_phys_addr_t base;
2592 c66fb5bc balrog
    ssize_t size;
2593 c66fb5bc balrog
#ifdef L4_MUX_HACK
2594 c66fb5bc balrog
    int i;
2595 c66fb5bc balrog
#endif
2596 827df9f3 balrog
2597 827df9f3 balrog
    if (region < 0 || region >= ta->regions) {
2598 827df9f3 balrog
        fprintf(stderr, "%s: bad io region (%i)\n", __FUNCTION__, region);
2599 827df9f3 balrog
        exit(-1);
2600 827df9f3 balrog
    }
2601 827df9f3 balrog
2602 827df9f3 balrog
    base = ta->bus->base + ta->start[region].offset;
2603 827df9f3 balrog
    size = ta->start[region].size;
2604 c66fb5bc balrog
    if (iotype) {
2605 c66fb5bc balrog
#ifndef L4_MUX_HACK
2606 827df9f3 balrog
        cpu_register_physical_memory(base, size, iotype);
2607 c66fb5bc balrog
#else
2608 c66fb5bc balrog
        cpu_register_physical_memory(base, size, omap_cpu_io_entry);
2609 c66fb5bc balrog
        i = (base - ta->bus->base) / TARGET_PAGE_SIZE;
2610 c66fb5bc balrog
        for (; size > 0; size -= TARGET_PAGE_SIZE, i ++) {
2611 c66fb5bc balrog
            omap_l4_io_readb_fn[i] = omap_l4_io_entry[iotype].mem_read[0];
2612 c66fb5bc balrog
            omap_l4_io_readh_fn[i] = omap_l4_io_entry[iotype].mem_read[1];
2613 c66fb5bc balrog
            omap_l4_io_readw_fn[i] = omap_l4_io_entry[iotype].mem_read[2];
2614 c66fb5bc balrog
            omap_l4_io_writeb_fn[i] = omap_l4_io_entry[iotype].mem_write[0];
2615 c66fb5bc balrog
            omap_l4_io_writeh_fn[i] = omap_l4_io_entry[iotype].mem_write[1];
2616 c66fb5bc balrog
            omap_l4_io_writew_fn[i] = omap_l4_io_entry[iotype].mem_write[2];
2617 c66fb5bc balrog
            omap_l4_io_opaque[i] = omap_l4_io_entry[iotype].opaque;
2618 c66fb5bc balrog
        }
2619 c66fb5bc balrog
#endif
2620 c66fb5bc balrog
    }
2621 827df9f3 balrog
2622 827df9f3 balrog
    return base;
2623 827df9f3 balrog
}
2624 827df9f3 balrog
2625 827df9f3 balrog
/* TEST-Chip-level TAP */
2626 827df9f3 balrog
static uint32_t omap_tap_read(void *opaque, target_phys_addr_t addr)
2627 827df9f3 balrog
{
2628 827df9f3 balrog
    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
2629 827df9f3 balrog
2630 8da3ff18 pbrook
    switch (addr) {
2631 827df9f3 balrog
    case 0x204:        /* IDCODE_reg */
2632 827df9f3 balrog
        switch (s->mpu_model) {
2633 827df9f3 balrog
        case omap2420:
2634 827df9f3 balrog
        case omap2422:
2635 827df9f3 balrog
        case omap2423:
2636 827df9f3 balrog
            return 0x5b5d902f;        /* ES 2.2 */
2637 827df9f3 balrog
        case omap2430:
2638 827df9f3 balrog
            return 0x5b68a02f;        /* ES 2.2 */
2639 827df9f3 balrog
        case omap3430:
2640 827df9f3 balrog
            return 0x1b7ae02f;        /* ES 2 */
2641 827df9f3 balrog
        default:
2642 2ac71179 Paul Brook
            hw_error("%s: Bad mpu model\n", __FUNCTION__);
2643 827df9f3 balrog
        }
2644 827df9f3 balrog
2645 827df9f3 balrog
    case 0x208:        /* PRODUCTION_ID_reg for OMAP2 */
2646 827df9f3 balrog
    case 0x210:        /* PRODUCTION_ID_reg for OMAP3 */
2647 827df9f3 balrog
        switch (s->mpu_model) {
2648 827df9f3 balrog
        case omap2420:
2649 827df9f3 balrog
            return 0x000254f0;        /* POP ESHS2.1.1 in N91/93/95, ES2 in N800 */
2650 827df9f3 balrog
        case omap2422:
2651 827df9f3 balrog
            return 0x000400f0;
2652 827df9f3 balrog
        case omap2423:
2653 827df9f3 balrog
            return 0x000800f0;
2654 827df9f3 balrog
        case omap2430:
2655 827df9f3 balrog
            return 0x000000f0;
2656 827df9f3 balrog
        case omap3430:
2657 827df9f3 balrog
            return 0x000000f0;
2658 827df9f3 balrog
        default:
2659 2ac71179 Paul Brook
            hw_error("%s: Bad mpu model\n", __FUNCTION__);
2660 827df9f3 balrog
        }
2661 827df9f3 balrog
2662 827df9f3 balrog
    case 0x20c:
2663 827df9f3 balrog
        switch (s->mpu_model) {
2664 827df9f3 balrog
        case omap2420:
2665 827df9f3 balrog
        case omap2422:
2666 827df9f3 balrog
        case omap2423:
2667 827df9f3 balrog
            return 0xcafeb5d9;        /* ES 2.2 */
2668 827df9f3 balrog
        case omap2430:
2669 827df9f3 balrog
            return 0xcafeb68a;        /* ES 2.2 */
2670 827df9f3 balrog
        case omap3430:
2671 827df9f3 balrog
            return 0xcafeb7ae;        /* ES 2 */
2672 827df9f3 balrog
        default:
2673 2ac71179 Paul Brook
            hw_error("%s: Bad mpu model\n", __FUNCTION__);
2674 827df9f3 balrog
        }
2675 827df9f3 balrog
2676 827df9f3 balrog
    case 0x218:        /* DIE_ID_reg */
2677 827df9f3 balrog
        return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
2678 827df9f3 balrog
    case 0x21c:        /* DIE_ID_reg */
2679 827df9f3 balrog
        return 0x54 << 24;
2680 827df9f3 balrog
    case 0x220:        /* DIE_ID_reg */
2681 827df9f3 balrog
        return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
2682 827df9f3 balrog
    case 0x224:        /* DIE_ID_reg */
2683 827df9f3 balrog
        return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
2684 827df9f3 balrog
    }
2685 827df9f3 balrog
2686 827df9f3 balrog
    OMAP_BAD_REG(addr);
2687 827df9f3 balrog
    return 0;
2688 827df9f3 balrog
}
2689 827df9f3 balrog
2690 827df9f3 balrog
static void omap_tap_write(void *opaque, target_phys_addr_t addr,
2691 827df9f3 balrog
                uint32_t value)
2692 827df9f3 balrog
{
2693 827df9f3 balrog
    OMAP_BAD_REG(addr);
2694 827df9f3 balrog
}
2695 827df9f3 balrog
2696 827df9f3 balrog
static CPUReadMemoryFunc *omap_tap_readfn[] = {
2697 827df9f3 balrog
    omap_badwidth_read32,
2698 827df9f3 balrog
    omap_badwidth_read32,
2699 827df9f3 balrog
    omap_tap_read,
2700 827df9f3 balrog
};
2701 827df9f3 balrog
2702 827df9f3 balrog
static CPUWriteMemoryFunc *omap_tap_writefn[] = {
2703 827df9f3 balrog
    omap_badwidth_write32,
2704 827df9f3 balrog
    omap_badwidth_write32,
2705 827df9f3 balrog
    omap_tap_write,
2706 827df9f3 balrog
};
2707 827df9f3 balrog
2708 827df9f3 balrog
void omap_tap_init(struct omap_target_agent_s *ta,
2709 827df9f3 balrog
                struct omap_mpu_state_s *mpu)
2710 827df9f3 balrog
{
2711 8da3ff18 pbrook
    omap_l4_attach(ta, 0, l4_register_io_memory(0,
2712 827df9f3 balrog
                            omap_tap_readfn, omap_tap_writefn, mpu));
2713 827df9f3 balrog
}
2714 827df9f3 balrog
2715 827df9f3 balrog
/* Power, Reset, and Clock Management */
2716 827df9f3 balrog
struct omap_prcm_s {
2717 827df9f3 balrog
    qemu_irq irq[3];
2718 827df9f3 balrog
    struct omap_mpu_state_s *mpu;
2719 827df9f3 balrog
2720 827df9f3 balrog
    uint32_t irqst[3];
2721 827df9f3 balrog
    uint32_t irqen[3];
2722 827df9f3 balrog
2723 827df9f3 balrog
    uint32_t sysconfig;
2724 827df9f3 balrog
    uint32_t voltctrl;
2725 827df9f3 balrog
    uint32_t scratch[20];
2726 827df9f3 balrog
2727 827df9f3 balrog
    uint32_t clksrc[1];
2728 827df9f3 balrog
    uint32_t clkout[1];
2729 827df9f3 balrog
    uint32_t clkemul[1];
2730 827df9f3 balrog
    uint32_t clkpol[1];
2731 827df9f3 balrog
    uint32_t clksel[8];
2732 827df9f3 balrog
    uint32_t clken[12];
2733 827df9f3 balrog
    uint32_t clkctrl[4];
2734 827df9f3 balrog
    uint32_t clkidle[7];
2735 827df9f3 balrog
    uint32_t setuptime[2];
2736 827df9f3 balrog
2737 827df9f3 balrog
    uint32_t wkup[3];
2738 827df9f3 balrog
    uint32_t wken[3];
2739 827df9f3 balrog
    uint32_t wkst[3];
2740 827df9f3 balrog
    uint32_t rst[4];
2741 827df9f3 balrog
    uint32_t rstctrl[1];
2742 827df9f3 balrog
    uint32_t power[4];
2743 827df9f3 balrog
    uint32_t rsttime_wkup;
2744 827df9f3 balrog
2745 827df9f3 balrog
    uint32_t ev;
2746 827df9f3 balrog
    uint32_t evtime[2];
2747 51fec3cc balrog
2748 51fec3cc balrog
    int dpll_lock, apll_lock[2];
2749 827df9f3 balrog
};
2750 827df9f3 balrog
2751 827df9f3 balrog
static void omap_prcm_int_update(struct omap_prcm_s *s, int dom)
2752 827df9f3 balrog
{
2753 827df9f3 balrog
    qemu_set_irq(s->irq[dom], s->irqst[dom] & s->irqen[dom]);
2754 827df9f3 balrog
    /* XXX or is the mask applied before PRCM_IRQSTATUS_* ? */
2755 827df9f3 balrog
}
2756 827df9f3 balrog
2757 827df9f3 balrog
static uint32_t omap_prcm_read(void *opaque, target_phys_addr_t addr)
2758 827df9f3 balrog
{
2759 827df9f3 balrog
    struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
2760 51fec3cc balrog
    uint32_t ret;
2761 827df9f3 balrog
2762 8da3ff18 pbrook
    switch (addr) {
2763 827df9f3 balrog
    case 0x000:        /* PRCM_REVISION */
2764 827df9f3 balrog
        return 0x10;
2765 827df9f3 balrog
2766 827df9f3 balrog
    case 0x010:        /* PRCM_SYSCONFIG */
2767 827df9f3 balrog
        return s->sysconfig;
2768 827df9f3 balrog
2769 827df9f3 balrog
    case 0x018:        /* PRCM_IRQSTATUS_MPU */
2770 827df9f3 balrog
        return s->irqst[0];
2771 827df9f3 balrog
2772 827df9f3 balrog
    case 0x01c:        /* PRCM_IRQENABLE_MPU */
2773 827df9f3 balrog
        return s->irqen[0];
2774 827df9f3 balrog
2775 827df9f3 balrog
    case 0x050:        /* PRCM_VOLTCTRL */
2776 827df9f3 balrog
        return s->voltctrl;
2777 827df9f3 balrog
    case 0x054:        /* PRCM_VOLTST */
2778 827df9f3 balrog
        return s->voltctrl & 3;
2779 827df9f3 balrog
2780 827df9f3 balrog
    case 0x060:        /* PRCM_CLKSRC_CTRL */
2781 827df9f3 balrog
        return s->clksrc[0];
2782 827df9f3 balrog
    case 0x070:        /* PRCM_CLKOUT_CTRL */
2783 827df9f3 balrog
        return s->clkout[0];
2784 827df9f3 balrog
    case 0x078:        /* PRCM_CLKEMUL_CTRL */
2785 827df9f3 balrog
        return s->clkemul[0];
2786 827df9f3 balrog
    case 0x080:        /* PRCM_CLKCFG_CTRL */
2787 827df9f3 balrog
    case 0x084:        /* PRCM_CLKCFG_STATUS */
2788 827df9f3 balrog
        return 0;
2789 827df9f3 balrog
2790 827df9f3 balrog
    case 0x090:        /* PRCM_VOLTSETUP */
2791 827df9f3 balrog
        return s->setuptime[0];
2792 827df9f3 balrog
2793 827df9f3 balrog
    case 0x094:        /* PRCM_CLKSSETUP */
2794 827df9f3 balrog
        return s->setuptime[1];
2795 827df9f3 balrog
2796 827df9f3 balrog
    case 0x098:        /* PRCM_POLCTRL */
2797 827df9f3 balrog
        return s->clkpol[0];
2798 827df9f3 balrog
2799 827df9f3 balrog
    case 0x0b0:        /* GENERAL_PURPOSE1 */
2800 827df9f3 balrog
    case 0x0b4:        /* GENERAL_PURPOSE2 */
2801 827df9f3 balrog
    case 0x0b8:        /* GENERAL_PURPOSE3 */
2802 827df9f3 balrog
    case 0x0bc:        /* GENERAL_PURPOSE4 */
2803 827df9f3 balrog
    case 0x0c0:        /* GENERAL_PURPOSE5 */
2804 827df9f3 balrog
    case 0x0c4:        /* GENERAL_PURPOSE6 */
2805 827df9f3 balrog
    case 0x0c8:        /* GENERAL_PURPOSE7 */
2806 827df9f3 balrog
    case 0x0cc:        /* GENERAL_PURPOSE8 */
2807 827df9f3 balrog
    case 0x0d0:        /* GENERAL_PURPOSE9 */
2808 827df9f3 balrog
    case 0x0d4:        /* GENERAL_PURPOSE10 */
2809 827df9f3 balrog
    case 0x0d8:        /* GENERAL_PURPOSE11 */
2810 827df9f3 balrog
    case 0x0dc:        /* GENERAL_PURPOSE12 */
2811 827df9f3 balrog
    case 0x0e0:        /* GENERAL_PURPOSE13 */
2812 827df9f3 balrog
    case 0x0e4:        /* GENERAL_PURPOSE14 */
2813 827df9f3 balrog
    case 0x0e8:        /* GENERAL_PURPOSE15 */
2814 827df9f3 balrog
    case 0x0ec:        /* GENERAL_PURPOSE16 */
2815 827df9f3 balrog
    case 0x0f0:        /* GENERAL_PURPOSE17 */
2816 827df9f3 balrog
    case 0x0f4:        /* GENERAL_PURPOSE18 */
2817 827df9f3 balrog
    case 0x0f8:        /* GENERAL_PURPOSE19 */
2818 827df9f3 balrog
    case 0x0fc:        /* GENERAL_PURPOSE20 */
2819 8da3ff18 pbrook
        return s->scratch[(addr - 0xb0) >> 2];
2820 827df9f3 balrog
2821 827df9f3 balrog
    case 0x140:        /* CM_CLKSEL_MPU */
2822 827df9f3 balrog
        return s->clksel[0];
2823 827df9f3 balrog
    case 0x148:        /* CM_CLKSTCTRL_MPU */
2824 827df9f3 balrog
        return s->clkctrl[0];
2825 827df9f3 balrog
2826 827df9f3 balrog
    case 0x158:        /* RM_RSTST_MPU */
2827 827df9f3 balrog
        return s->rst[0];
2828 827df9f3 balrog
    case 0x1c8:        /* PM_WKDEP_MPU */
2829 827df9f3 balrog
        return s->wkup[0];
2830 827df9f3 balrog
    case 0x1d4:        /* PM_EVGENCTRL_MPU */
2831 827df9f3 balrog
        return s->ev;
2832 827df9f3 balrog
    case 0x1d8:        /* PM_EVEGENONTIM_MPU */
2833 827df9f3 balrog
        return s->evtime[0];
2834 827df9f3 balrog
    case 0x1dc:        /* PM_EVEGENOFFTIM_MPU */
2835 827df9f3 balrog
        return s->evtime[1];
2836 827df9f3 balrog
    case 0x1e0:        /* PM_PWSTCTRL_MPU */
2837 827df9f3 balrog
        return s->power[0];
2838 827df9f3 balrog
    case 0x1e4:        /* PM_PWSTST_MPU */
2839 827df9f3 balrog
        return 0;
2840 827df9f3 balrog
2841 827df9f3 balrog
    case 0x200:        /* CM_FCLKEN1_CORE */
2842 827df9f3 balrog
        return s->clken[0];
2843 827df9f3 balrog
    case 0x204:        /* CM_FCLKEN2_CORE */
2844 827df9f3 balrog
        return s->clken[1];
2845 827df9f3 balrog
    case 0x210:        /* CM_ICLKEN1_CORE */
2846 827df9f3 balrog
        return s->clken[2];
2847 827df9f3 balrog
    case 0x214:        /* CM_ICLKEN2_CORE */
2848 827df9f3 balrog
        return s->clken[3];
2849 827df9f3 balrog
    case 0x21c:        /* CM_ICLKEN4_CORE */
2850 827df9f3 balrog
        return s->clken[4];
2851 827df9f3 balrog
2852 827df9f3 balrog
    case 0x220:        /* CM_IDLEST1_CORE */
2853 827df9f3 balrog
        /* TODO: check the actual iclk status */
2854 827df9f3 balrog
        return 0x7ffffff9;
2855 827df9f3 balrog
    case 0x224:        /* CM_IDLEST2_CORE */
2856 827df9f3 balrog
        /* TODO: check the actual iclk status */
2857 827df9f3 balrog
        return 0x00000007;
2858 827df9f3 balrog
    case 0x22c:        /* CM_IDLEST4_CORE */
2859 827df9f3 balrog
        /* TODO: check the actual iclk status */
2860 827df9f3 balrog
        return 0x0000001f;
2861 827df9f3 balrog
2862 827df9f3 balrog
    case 0x230:        /* CM_AUTOIDLE1_CORE */
2863 827df9f3 balrog
        return s->clkidle[0];
2864 827df9f3 balrog
    case 0x234:        /* CM_AUTOIDLE2_CORE */
2865 827df9f3 balrog
        return s->clkidle[1];
2866 827df9f3 balrog
    case 0x238:        /* CM_AUTOIDLE3_CORE */
2867 827df9f3 balrog
        return s->clkidle[2];
2868 827df9f3 balrog
    case 0x23c:        /* CM_AUTOIDLE4_CORE */
2869 827df9f3 balrog
        return s->clkidle[3];
2870 827df9f3 balrog
2871 827df9f3 balrog
    case 0x240:        /* CM_CLKSEL1_CORE */
2872 827df9f3 balrog
        return s->clksel[1];
2873 827df9f3 balrog
    case 0x244:        /* CM_CLKSEL2_CORE */
2874 827df9f3 balrog
        return s->clksel[2];
2875 827df9f3 balrog
2876 827df9f3 balrog
    case 0x248:        /* CM_CLKSTCTRL_CORE */
2877 827df9f3 balrog
        return s->clkctrl[1];
2878 827df9f3 balrog
2879 827df9f3 balrog
    case 0x2a0:        /* PM_WKEN1_CORE */
2880 827df9f3 balrog
        return s->wken[0];
2881 827df9f3 balrog
    case 0x2a4:        /* PM_WKEN2_CORE */
2882 827df9f3 balrog
        return s->wken[1];
2883 827df9f3 balrog
2884 827df9f3 balrog
    case 0x2b0:        /* PM_WKST1_CORE */
2885 827df9f3 balrog
        return s->wkst[0];
2886 827df9f3 balrog
    case 0x2b4:        /* PM_WKST2_CORE */
2887 827df9f3 balrog
        return s->wkst[1];
2888 827df9f3 balrog
    case 0x2c8:        /* PM_WKDEP_CORE */
2889 827df9f3 balrog
        return 0x1e;
2890 827df9f3 balrog
2891 827df9f3 balrog
    case 0x2e0:        /* PM_PWSTCTRL_CORE */
2892 827df9f3 balrog
        return s->power[1];
2893 827df9f3 balrog
    case 0x2e4:        /* PM_PWSTST_CORE */
2894 827df9f3 balrog
        return 0x000030 | (s->power[1] & 0xfc00);
2895 827df9f3 balrog
2896 827df9f3 balrog
    case 0x300:        /* CM_FCLKEN_GFX */
2897 827df9f3 balrog
        return s->clken[5];
2898 827df9f3 balrog
    case 0x310:        /* CM_ICLKEN_GFX */
2899 827df9f3 balrog
        return s->clken[6];
2900 827df9f3 balrog
    case 0x320:        /* CM_IDLEST_GFX */
2901 827df9f3 balrog
        /* TODO: check the actual iclk status */
2902 827df9f3 balrog
        return 0x00000001;
2903 827df9f3 balrog
    case 0x340:        /* CM_CLKSEL_GFX */
2904 827df9f3 balrog
        return s->clksel[3];
2905 827df9f3 balrog
    case 0x348:        /* CM_CLKSTCTRL_GFX */
2906 827df9f3 balrog
        return s->clkctrl[2];
2907 827df9f3 balrog
    case 0x350:        /* RM_RSTCTRL_GFX */
2908 827df9f3 balrog
        return s->rstctrl[0];
2909 827df9f3 balrog
    case 0x358:        /* RM_RSTST_GFX */
2910 827df9f3 balrog
        return s->rst[1];
2911 827df9f3 balrog
    case 0x3c8:        /* PM_WKDEP_GFX */
2912 827df9f3 balrog
        return s->wkup[1];
2913 827df9f3 balrog
2914 827df9f3 balrog
    case 0x3e0:        /* PM_PWSTCTRL_GFX */
2915 827df9f3 balrog
        return s->power[2];
2916 827df9f3 balrog
    case 0x3e4:        /* PM_PWSTST_GFX */
2917 827df9f3 balrog
        return s->power[2] & 3;
2918 827df9f3 balrog
2919 827df9f3 balrog
    case 0x400:        /* CM_FCLKEN_WKUP */
2920 827df9f3 balrog
        return s->clken[7];
2921 827df9f3 balrog
    case 0x410:        /* CM_ICLKEN_WKUP */
2922 827df9f3 balrog
        return s->clken[8];
2923 827df9f3 balrog
    case 0x420:        /* CM_IDLEST_WKUP */
2924 827df9f3 balrog
        /* TODO: check the actual iclk status */
2925 827df9f3 balrog
        return 0x0000003f;
2926 827df9f3 balrog
    case 0x430:        /* CM_AUTOIDLE_WKUP */
2927 827df9f3 balrog
        return s->clkidle[4];
2928 827df9f3 balrog
    case 0x440:        /* CM_CLKSEL_WKUP */
2929 827df9f3 balrog
        return s->clksel[4];
2930 827df9f3 balrog
    case 0x450:        /* RM_RSTCTRL_WKUP */
2931 827df9f3 balrog
        return 0;
2932 827df9f3 balrog
    case 0x454:        /* RM_RSTTIME_WKUP */
2933 827df9f3 balrog
        return s->rsttime_wkup;
2934 827df9f3 balrog
    case 0x458:        /* RM_RSTST_WKUP */
2935 827df9f3 balrog
        return s->rst[2];
2936 827df9f3 balrog
    case 0x4a0:        /* PM_WKEN_WKUP */
2937 827df9f3 balrog
        return s->wken[2];
2938 827df9f3 balrog
    case 0x4b0:        /* PM_WKST_WKUP */
2939 827df9f3 balrog
        return s->wkst[2];
2940 827df9f3 balrog
2941 827df9f3 balrog
    case 0x500:        /* CM_CLKEN_PLL */
2942 827df9f3 balrog
        return s->clken[9];
2943 827df9f3 balrog
    case 0x520:        /* CM_IDLEST_CKGEN */
2944 51fec3cc balrog
        ret = 0x0000070 | (s->apll_lock[0] << 9) | (s->apll_lock[1] << 8);
2945 827df9f3 balrog
        if (!(s->clksel[6] & 3))
2946 51fec3cc balrog
            /* Core uses 32-kHz clock */
2947 51fec3cc balrog
            ret |= 3 << 0;
2948 51fec3cc balrog
        else if (!s->dpll_lock)
2949 51fec3cc balrog
            /* DPLL not locked, core uses ref_clk */
2950 51fec3cc balrog
            ret |= 1 << 0;
2951 51fec3cc balrog
        else
2952 51fec3cc balrog
            /* Core uses DPLL */
2953 51fec3cc balrog
            ret |= 2 << 0;
2954 51fec3cc balrog
        return ret;
2955 827df9f3 balrog
    case 0x530:        /* CM_AUTOIDLE_PLL */
2956 827df9f3 balrog
        return s->clkidle[5];
2957 827df9f3 balrog
    case 0x540:        /* CM_CLKSEL1_PLL */
2958 827df9f3 balrog
        return s->clksel[5];
2959 827df9f3 balrog
    case 0x544:        /* CM_CLKSEL2_PLL */
2960 827df9f3 balrog
        return s->clksel[6];
2961 827df9f3 balrog
2962 827df9f3 balrog
    case 0x800:        /* CM_FCLKEN_DSP */
2963 827df9f3 balrog
        return s->clken[10];
2964 827df9f3 balrog
    case 0x810:        /* CM_ICLKEN_DSP */
2965 827df9f3 balrog
        return s->clken[11];
2966 827df9f3 balrog
    case 0x820:        /* CM_IDLEST_DSP */
2967 827df9f3 balrog
        /* TODO: check the actual iclk status */
2968 827df9f3 balrog
        return 0x00000103;
2969 827df9f3 balrog
    case 0x830:        /* CM_AUTOIDLE_DSP */
2970 827df9f3 balrog
        return s->clkidle[6];
2971 827df9f3 balrog
    case 0x840:        /* CM_CLKSEL_DSP */
2972 827df9f3 balrog
        return s->clksel[7];
2973 827df9f3 balrog
    case 0x848:        /* CM_CLKSTCTRL_DSP */
2974 827df9f3 balrog
        return s->clkctrl[3];
2975 827df9f3 balrog
    case 0x850:        /* RM_RSTCTRL_DSP */
2976 827df9f3 balrog
        return 0;
2977 827df9f3 balrog
    case 0x858:        /* RM_RSTST_DSP */
2978 827df9f3 balrog
        return s->rst[3];
2979 827df9f3 balrog
    case 0x8c8:        /* PM_WKDEP_DSP */
2980 827df9f3 balrog
        return s->wkup[2];
2981 827df9f3 balrog
    case 0x8e0:        /* PM_PWSTCTRL_DSP */
2982 827df9f3 balrog
        return s->power[3];
2983 827df9f3 balrog
    case 0x8e4:        /* PM_PWSTST_DSP */
2984 827df9f3 balrog
        return 0x008030 | (s->power[3] & 0x3003);
2985 827df9f3 balrog
2986 827df9f3 balrog
    case 0x8f0:        /* PRCM_IRQSTATUS_DSP */
2987 827df9f3 balrog
        return s->irqst[1];
2988 827df9f3 balrog
    case 0x8f4:        /* PRCM_IRQENABLE_DSP */
2989 827df9f3 balrog
        return s->irqen[1];
2990 827df9f3 balrog
2991 827df9f3 balrog
    case 0x8f8:        /* PRCM_IRQSTATUS_IVA */
2992 827df9f3 balrog
        return s->irqst[2];
2993 827df9f3 balrog
    case 0x8fc:        /* PRCM_IRQENABLE_IVA */
2994 827df9f3 balrog
        return s->irqen[2];
2995 827df9f3 balrog
    }
2996 827df9f3 balrog
2997 827df9f3 balrog
    OMAP_BAD_REG(addr);
2998 827df9f3 balrog
    return 0;
2999 827df9f3 balrog
}
3000 827df9f3 balrog
3001 51fec3cc balrog
static void omap_prcm_apll_update(struct omap_prcm_s *s)
3002 51fec3cc balrog
{
3003 51fec3cc balrog
    int mode[2];
3004 51fec3cc balrog
3005 51fec3cc balrog
    mode[0] = (s->clken[9] >> 6) & 3;
3006 51fec3cc balrog
    s->apll_lock[0] = (mode[0] == 3);
3007 51fec3cc balrog
    mode[1] = (s->clken[9] >> 2) & 3;
3008 51fec3cc balrog
    s->apll_lock[1] = (mode[1] == 3);
3009 51fec3cc balrog
    /* TODO: update clocks */
3010 51fec3cc balrog
3011 51fec3cc balrog
    if (mode[0] == 1 || mode[0] == 2 || mode[1] == 1 || mode[2] == 2)
3012 51fec3cc balrog
        fprintf(stderr, "%s: bad EN_54M_PLL or bad EN_96M_PLL\n",
3013 51fec3cc balrog
                        __FUNCTION__);
3014 51fec3cc balrog
}
3015 51fec3cc balrog
3016 51fec3cc balrog
static void omap_prcm_dpll_update(struct omap_prcm_s *s)
3017 51fec3cc balrog
{
3018 51fec3cc balrog
    omap_clk dpll = omap_findclk(s->mpu, "dpll");
3019 51fec3cc balrog
    omap_clk dpll_x2 = omap_findclk(s->mpu, "dpll");
3020 51fec3cc balrog
    omap_clk core = omap_findclk(s->mpu, "core_clk");
3021 51fec3cc balrog
    int mode = (s->clken[9] >> 0) & 3;
3022 51fec3cc balrog
    int mult, div;
3023 51fec3cc balrog
3024 51fec3cc balrog
    mult = (s->clksel[5] >> 12) & 0x3ff;
3025 51fec3cc balrog
    div = (s->clksel[5] >> 8) & 0xf;
3026 51fec3cc balrog
    if (mult == 0 || mult == 1)
3027 51fec3cc balrog
        mode = 1;        /* Bypass */
3028 51fec3cc balrog
3029 51fec3cc balrog
    s->dpll_lock = 0;
3030 51fec3cc balrog
    switch (mode) {
3031 51fec3cc balrog
    case 0:
3032 51fec3cc balrog
        fprintf(stderr, "%s: bad EN_DPLL\n", __FUNCTION__);
3033 51fec3cc balrog
        break;
3034 51fec3cc balrog
    case 1:        /* Low-power bypass mode (Default) */
3035 51fec3cc balrog
    case 2:        /* Fast-relock bypass mode */
3036 51fec3cc balrog
        omap_clk_setrate(dpll, 1, 1);
3037 51fec3cc balrog
        omap_clk_setrate(dpll_x2, 1, 1);
3038 51fec3cc balrog
        break;
3039 51fec3cc balrog
    case 3:        /* Lock mode */
3040 51fec3cc balrog
        s->dpll_lock = 1; /* After 20 FINT cycles (ref_clk / (div + 1)).  */
3041 51fec3cc balrog
3042 51fec3cc balrog
        omap_clk_setrate(dpll, div + 1, mult);
3043 51fec3cc balrog
        omap_clk_setrate(dpll_x2, div + 1, mult * 2);
3044 51fec3cc balrog
        break;
3045 51fec3cc balrog
    }
3046 51fec3cc balrog
3047 51fec3cc balrog
    switch ((s->clksel[6] >> 0) & 3) {
3048 51fec3cc balrog
    case 0:
3049 51fec3cc balrog
        omap_clk_reparent(core, omap_findclk(s->mpu, "clk32-kHz"));
3050 51fec3cc balrog
        break;
3051 51fec3cc balrog
    case 1:
3052 51fec3cc balrog
        omap_clk_reparent(core, dpll);
3053 51fec3cc balrog
        break;
3054 51fec3cc balrog
    case 2:
3055 51fec3cc balrog
        /* Default */
3056 51fec3cc balrog
        omap_clk_reparent(core, dpll_x2);
3057 51fec3cc balrog
        break;
3058 51fec3cc balrog
    case 3:
3059 51fec3cc balrog
        fprintf(stderr, "%s: bad CORE_CLK_SRC\n", __FUNCTION__);
3060 51fec3cc balrog
        break;
3061 51fec3cc balrog
    }
3062 51fec3cc balrog
}
3063 51fec3cc balrog
3064 827df9f3 balrog
static void omap_prcm_write(void *opaque, target_phys_addr_t addr,
3065 827df9f3 balrog
                uint32_t value)
3066 827df9f3 balrog
{
3067 827df9f3 balrog
    struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
3068 827df9f3 balrog
3069 8da3ff18 pbrook
    switch (addr) {
3070 827df9f3 balrog
    case 0x000:        /* PRCM_REVISION */
3071 827df9f3 balrog
    case 0x054:        /* PRCM_VOLTST */
3072 827df9f3 balrog
    case 0x084:        /* PRCM_CLKCFG_STATUS */
3073 827df9f3 balrog
    case 0x1e4:        /* PM_PWSTST_MPU */
3074 827df9f3 balrog
    case 0x220:        /* CM_IDLEST1_CORE */
3075 827df9f3 balrog
    case 0x224:        /* CM_IDLEST2_CORE */
3076 827df9f3 balrog
    case 0x22c:        /* CM_IDLEST4_CORE */
3077 827df9f3 balrog
    case 0x2c8:        /* PM_WKDEP_CORE */
3078 827df9f3 balrog
    case 0x2e4:        /* PM_PWSTST_CORE */
3079 827df9f3 balrog
    case 0x320:        /* CM_IDLEST_GFX */
3080 827df9f3 balrog
    case 0x3e4:        /* PM_PWSTST_GFX */
3081 827df9f3 balrog
    case 0x420:        /* CM_IDLEST_WKUP */
3082 827df9f3 balrog
    case 0x520:        /* CM_IDLEST_CKGEN */
3083 827df9f3 balrog
    case 0x820:        /* CM_IDLEST_DSP */
3084 827df9f3 balrog
    case 0x8e4:        /* PM_PWSTST_DSP */
3085 827df9f3 balrog
        OMAP_RO_REG(addr);
3086 827df9f3 balrog
        return;
3087 827df9f3 balrog
3088 827df9f3 balrog
    case 0x010:        /* PRCM_SYSCONFIG */
3089 827df9f3 balrog
        s->sysconfig = value & 1;
3090 827df9f3 balrog
        break;
3091 827df9f3 balrog
3092 827df9f3 balrog
    case 0x018:        /* PRCM_IRQSTATUS_MPU */
3093 827df9f3 balrog
        s->irqst[0] &= ~value;
3094 827df9f3 balrog
        omap_prcm_int_update(s, 0);
3095 827df9f3 balrog
        break;
3096 827df9f3 balrog
    case 0x01c:        /* PRCM_IRQENABLE_MPU */
3097 827df9f3 balrog
        s->irqen[0] = value & 0x3f;
3098 827df9f3 balrog
        omap_prcm_int_update(s, 0);
3099 827df9f3 balrog
        break;
3100 827df9f3 balrog
3101 827df9f3 balrog
    case 0x050:        /* PRCM_VOLTCTRL */
3102 827df9f3 balrog
        s->voltctrl = value & 0xf1c3;
3103 827df9f3 balrog
        break;
3104 827df9f3 balrog
3105 827df9f3 balrog
    case 0x060:        /* PRCM_CLKSRC_CTRL */
3106 827df9f3 balrog
        s->clksrc[0] = value & 0xdb;
3107 827df9f3 balrog
        /* TODO update clocks */
3108 827df9f3 balrog
        break;
3109 827df9f3 balrog
3110 827df9f3 balrog
    case 0x070:        /* PRCM_CLKOUT_CTRL */
3111 827df9f3 balrog
        s->clkout[0] = value & 0xbbbb;
3112 827df9f3 balrog
        /* TODO update clocks */
3113 827df9f3 balrog
        break;
3114 827df9f3 balrog
3115 827df9f3 balrog
    case 0x078:        /* PRCM_CLKEMUL_CTRL */
3116 827df9f3 balrog
        s->clkemul[0] = value & 1;
3117 827df9f3 balrog
        /* TODO update clocks */
3118 827df9f3 balrog
        break;
3119 827df9f3 balrog
3120 827df9f3 balrog
    case 0x080:        /* PRCM_CLKCFG_CTRL */
3121 827df9f3 balrog
        break;
3122 827df9f3 balrog
3123 827df9f3 balrog
    case 0x090:        /* PRCM_VOLTSETUP */
3124 827df9f3 balrog
        s->setuptime[0] = value & 0xffff;
3125 827df9f3 balrog
        break;
3126 827df9f3 balrog
    case 0x094:        /* PRCM_CLKSSETUP */
3127 827df9f3 balrog
        s->setuptime[1] = value & 0xffff;
3128 827df9f3 balrog
        break;
3129 827df9f3 balrog
3130 827df9f3 balrog
    case 0x098:        /* PRCM_POLCTRL */
3131 827df9f3 balrog
        s->clkpol[0] = value & 0x701;
3132 827df9f3 balrog
        break;
3133 827df9f3 balrog
3134 827df9f3 balrog
    case 0x0b0:        /* GENERAL_PURPOSE1 */
3135 827df9f3 balrog
    case 0x0b4:        /* GENERAL_PURPOSE2 */
3136 827df9f3 balrog
    case 0x0b8:        /* GENERAL_PURPOSE3 */
3137 827df9f3 balrog
    case 0x0bc:        /* GENERAL_PURPOSE4 */
3138 827df9f3 balrog
    case 0x0c0:        /* GENERAL_PURPOSE5 */
3139 827df9f3 balrog
    case 0x0c4:        /* GENERAL_PURPOSE6 */
3140 827df9f3 balrog
    case 0x0c8:        /* GENERAL_PURPOSE7 */
3141 827df9f3 balrog
    case 0x0cc:        /* GENERAL_PURPOSE8 */
3142 827df9f3 balrog
    case 0x0d0:        /* GENERAL_PURPOSE9 */
3143 827df9f3 balrog
    case 0x0d4:        /* GENERAL_PURPOSE10 */
3144 827df9f3 balrog
    case 0x0d8:        /* GENERAL_PURPOSE11 */
3145 827df9f3 balrog
    case 0x0dc:        /* GENERAL_PURPOSE12 */
3146 827df9f3 balrog
    case 0x0e0:        /* GENERAL_PURPOSE13 */
3147 827df9f3 balrog
    case 0x0e4:        /* GENERAL_PURPOSE14 */
3148 827df9f3 balrog
    case 0x0e8:        /* GENERAL_PURPOSE15 */
3149 827df9f3 balrog
    case 0x0ec:        /* GENERAL_PURPOSE16 */
3150 827df9f3 balrog
    case 0x0f0:        /* GENERAL_PURPOSE17 */
3151 827df9f3 balrog
    case 0x0f4:        /* GENERAL_PURPOSE18 */
3152 827df9f3 balrog
    case 0x0f8:        /* GENERAL_PURPOSE19 */
3153 827df9f3 balrog
    case 0x0fc:        /* GENERAL_PURPOSE20 */
3154 8da3ff18 pbrook
        s->scratch[(addr - 0xb0) >> 2] = value;
3155 827df9f3 balrog
        break;
3156 827df9f3 balrog
3157 827df9f3 balrog
    case 0x140:        /* CM_CLKSEL_MPU */
3158 827df9f3 balrog
        s->clksel[0] = value & 0x1f;
3159 827df9f3 balrog
        /* TODO update clocks */
3160 827df9f3 balrog
        break;
3161 827df9f3 balrog
    case 0x148:        /* CM_CLKSTCTRL_MPU */
3162 827df9f3 balrog
        s->clkctrl[0] = value & 0x1f;
3163 827df9f3 balrog
        break;
3164 827df9f3 balrog
3165 827df9f3 balrog
    case 0x158:        /* RM_RSTST_MPU */
3166 827df9f3 balrog
        s->rst[0] &= ~value;
3167 827df9f3 balrog
        break;
3168 827df9f3 balrog
    case 0x1c8:        /* PM_WKDEP_MPU */
3169 827df9f3 balrog
        s->wkup[0] = value & 0x15;
3170 827df9f3 balrog
        break;
3171 827df9f3 balrog
3172 827df9f3 balrog
    case 0x1d4:        /* PM_EVGENCTRL_MPU */
3173 827df9f3 balrog
        s->ev = value & 0x1f;
3174 827df9f3 balrog
        break;
3175 827df9f3 balrog
    case 0x1d8:        /* PM_EVEGENONTIM_MPU */
3176 827df9f3 balrog
        s->evtime[0] = value;
3177 827df9f3 balrog
        break;
3178 827df9f3 balrog
    case 0x1dc:        /* PM_EVEGENOFFTIM_MPU */
3179 827df9f3 balrog
        s->evtime[1] = value;
3180 827df9f3 balrog
        break;
3181 827df9f3 balrog
3182 827df9f3 balrog
    case 0x1e0:        /* PM_PWSTCTRL_MPU */
3183 827df9f3 balrog
        s->power[0] = value & 0xc0f;
3184 827df9f3 balrog
        break;
3185 827df9f3 balrog
3186 827df9f3 balrog
    case 0x200:        /* CM_FCLKEN1_CORE */
3187 827df9f3 balrog
        s->clken[0] = value & 0xbfffffff;
3188 827df9f3 balrog
        /* TODO update clocks */
3189 99570a40 balrog
        /* The EN_EAC bit only gets/puts func_96m_clk.  */
3190 827df9f3 balrog
        break;
3191 827df9f3 balrog
    case 0x204:        /* CM_FCLKEN2_CORE */
3192 827df9f3 balrog
        s->clken[1] = value & 0x00000007;
3193 827df9f3 balrog
        /* TODO update clocks */
3194 827df9f3 balrog
        break;
3195 827df9f3 balrog
    case 0x210:        /* CM_ICLKEN1_CORE */
3196 827df9f3 balrog
        s->clken[2] = value & 0xfffffff9;
3197 827df9f3 balrog
        /* TODO update clocks */
3198 99570a40 balrog
        /* The EN_EAC bit only gets/puts core_l4_iclk.  */
3199 827df9f3 balrog
        break;
3200 827df9f3 balrog
    case 0x214:        /* CM_ICLKEN2_CORE */
3201 827df9f3 balrog
        s->clken[3] = value & 0x00000007;
3202 827df9f3 balrog
        /* TODO update clocks */
3203 827df9f3 balrog
        break;
3204 827df9f3 balrog
    case 0x21c:        /* CM_ICLKEN4_CORE */
3205 827df9f3 balrog
        s->clken[4] = value & 0x0000001f;
3206 827df9f3 balrog
        /* TODO update clocks */
3207 827df9f3 balrog
        break;
3208 827df9f3 balrog
3209 827df9f3 balrog
    case 0x230:        /* CM_AUTOIDLE1_CORE */
3210 827df9f3 balrog
        s->clkidle[0] = value & 0xfffffff9;
3211 827df9f3 balrog
        /* TODO update clocks */
3212 827df9f3 balrog
        break;
3213 827df9f3 balrog
    case 0x234:        /* CM_AUTOIDLE2_CORE */
3214 827df9f3 balrog
        s->clkidle[1] = value & 0x00000007;
3215 827df9f3 balrog
        /* TODO update clocks */
3216 827df9f3 balrog
        break;
3217 827df9f3 balrog
    case 0x238:        /* CM_AUTOIDLE3_CORE */
3218 827df9f3 balrog
        s->clkidle[2] = value & 0x00000007;
3219 827df9f3 balrog
        /* TODO update clocks */
3220 827df9f3 balrog
        break;
3221 827df9f3 balrog
    case 0x23c:        /* CM_AUTOIDLE4_CORE */
3222 827df9f3 balrog
        s->clkidle[3] = value & 0x0000001f;
3223 827df9f3 balrog
        /* TODO update clocks */
3224 827df9f3 balrog
        break;
3225 827df9f3 balrog
3226 827df9f3 balrog
    case 0x240:        /* CM_CLKSEL1_CORE */
3227 827df9f3 balrog
        s->clksel[1] = value & 0x0fffbf7f;
3228 827df9f3 balrog
        /* TODO update clocks */
3229 827df9f3 balrog
        break;
3230 827df9f3 balrog
3231 827df9f3 balrog
    case 0x244:        /* CM_CLKSEL2_CORE */
3232 827df9f3 balrog
        s->clksel[2] = value & 0x00fffffc;
3233 827df9f3 balrog
        /* TODO update clocks */
3234 827df9f3 balrog
        break;
3235 827df9f3 balrog
3236 827df9f3 balrog
    case 0x248:        /* CM_CLKSTCTRL_CORE */
3237 827df9f3 balrog
        s->clkctrl[1] = value & 0x7;
3238 827df9f3 balrog
        break;
3239 827df9f3 balrog
3240 827df9f3 balrog
    case 0x2a0:        /* PM_WKEN1_CORE */
3241 827df9f3 balrog
        s->wken[0] = value & 0x04667ff8;
3242 827df9f3 balrog
        break;
3243 827df9f3 balrog
    case 0x2a4:        /* PM_WKEN2_CORE */
3244 827df9f3 balrog
        s->wken[1] = value & 0x00000005;
3245 827df9f3 balrog
        break;
3246 827df9f3 balrog
3247 827df9f3 balrog
    case 0x2b0:        /* PM_WKST1_CORE */
3248 827df9f3 balrog
        s->wkst[0] &= ~value;
3249 827df9f3 balrog
        break;
3250 827df9f3 balrog
    case 0x2b4:        /* PM_WKST2_CORE */
3251 827df9f3 balrog
        s->wkst[1] &= ~value;
3252 827df9f3 balrog
        break;
3253 827df9f3 balrog
3254 827df9f3 balrog
    case 0x2e0:        /* PM_PWSTCTRL_CORE */
3255 827df9f3 balrog
        s->power[1] = (value & 0x00fc3f) | (1 << 2);
3256 827df9f3 balrog
        break;
3257 827df9f3 balrog
3258 827df9f3 balrog
    case 0x300:        /* CM_FCLKEN_GFX */
3259 827df9f3 balrog
        s->clken[5] = value & 6;
3260 827df9f3 balrog
        /* TODO update clocks */
3261 827df9f3 balrog
        break;
3262 827df9f3 balrog
    case 0x310:        /* CM_ICLKEN_GFX */
3263 827df9f3 balrog
        s->clken[6] = value & 1;
3264 827df9f3 balrog
        /* TODO update clocks */
3265 827df9f3 balrog
        break;
3266 827df9f3 balrog
    case 0x340:        /* CM_CLKSEL_GFX */
3267 827df9f3 balrog
        s->clksel[3] = value & 7;
3268 827df9f3 balrog
        /* TODO update clocks */
3269 827df9f3 balrog
        break;
3270 827df9f3 balrog
    case 0x348:        /* CM_CLKSTCTRL_GFX */
3271 827df9f3 balrog
        s->clkctrl[2] = value & 1;
3272 827df9f3 balrog
        break;
3273 827df9f3 balrog
    case 0x350:        /* RM_RSTCTRL_GFX */
3274 827df9f3 balrog
        s->rstctrl[0] = value & 1;
3275 827df9f3 balrog
        /* TODO: reset */
3276 827df9f3 balrog
        break;
3277 827df9f3 balrog
    case 0x358:        /* RM_RSTST_GFX */
3278 827df9f3 balrog
        s->rst[1] &= ~value;
3279 827df9f3 balrog
        break;
3280 827df9f3 balrog
    case 0x3c8:        /* PM_WKDEP_GFX */
3281 827df9f3 balrog
        s->wkup[1] = value & 0x13;
3282 827df9f3 balrog
        break;
3283 827df9f3 balrog
    case 0x3e0:        /* PM_PWSTCTRL_GFX */
3284 827df9f3 balrog
        s->power[2] = (value & 0x00c0f) | (3 << 2);
3285 827df9f3 balrog
        break;
3286 827df9f3 balrog
3287 827df9f3 balrog
    case 0x400:        /* CM_FCLKEN_WKUP */
3288 827df9f3 balrog
        s->clken[7] = value & 0xd;
3289 827df9f3 balrog
        /* TODO update clocks */
3290 827df9f3 balrog
        break;
3291 827df9f3 balrog
    case 0x410:        /* CM_ICLKEN_WKUP */
3292 827df9f3 balrog
        s->clken[8] = value & 0x3f;
3293 827df9f3 balrog
        /* TODO update clocks */
3294 827df9f3 balrog
        break;
3295 827df9f3 balrog
    case 0x430:        /* CM_AUTOIDLE_WKUP */
3296 827df9f3 balrog
        s->clkidle[4] = value & 0x0000003f;
3297 827df9f3 balrog
        /* TODO update clocks */
3298 827df9f3 balrog
        break;
3299 827df9f3 balrog
    case 0x440:        /* CM_CLKSEL_WKUP */
3300 827df9f3 balrog
        s->clksel[4] = value & 3;
3301 827df9f3 balrog
        /* TODO update clocks */
3302 827df9f3 balrog
        break;
3303 827df9f3 balrog
    case 0x450:        /* RM_RSTCTRL_WKUP */
3304 827df9f3 balrog
        /* TODO: reset */
3305 827df9f3 balrog
        if (value & 2)
3306 827df9f3 balrog
            qemu_system_reset_request();
3307 827df9f3 balrog
        break;
3308 827df9f3 balrog
    case 0x454:        /* RM_RSTTIME_WKUP */
3309 827df9f3 balrog
        s->rsttime_wkup = value & 0x1fff;
3310 827df9f3 balrog
        break;
3311 827df9f3 balrog
    case 0x458:        /* RM_RSTST_WKUP */
3312 827df9f3 balrog
        s->rst[2] &= ~value;
3313 827df9f3 balrog
        break;
3314 827df9f3 balrog
    case 0x4a0:        /* PM_WKEN_WKUP */
3315 827df9f3 balrog
        s->wken[2] = value & 0x00000005;
3316 827df9f3 balrog
        break;
3317 827df9f3 balrog
    case 0x4b0:        /* PM_WKST_WKUP */
3318 827df9f3 balrog
        s->wkst[2] &= ~value;
3319 827df9f3 balrog
        break;
3320 827df9f3 balrog
3321 827df9f3 balrog
    case 0x500:        /* CM_CLKEN_PLL */
3322 51fec3cc balrog
        if (value & 0xffffff30)
3323 51fec3cc balrog
            fprintf(stderr, "%s: write 0s in CM_CLKEN_PLL for "
3324 51fec3cc balrog
                            "future compatiblity\n", __FUNCTION__);
3325 51fec3cc balrog
        if ((s->clken[9] ^ value) & 0xcc) {
3326 51fec3cc balrog
            s->clken[9] &= ~0xcc;
3327 51fec3cc balrog
            s->clken[9] |= value & 0xcc;
3328 51fec3cc balrog
            omap_prcm_apll_update(s);
3329 51fec3cc balrog
        }
3330 51fec3cc balrog
        if ((s->clken[9] ^ value) & 3) {
3331 51fec3cc balrog
            s->clken[9] &= ~3;
3332 51fec3cc balrog
            s->clken[9] |= value & 3;
3333 51fec3cc balrog
            omap_prcm_dpll_update(s);
3334 51fec3cc balrog
        }
3335 827df9f3 balrog
        break;
3336 827df9f3 balrog
    case 0x530:        /* CM_AUTOIDLE_PLL */
3337 827df9f3 balrog
        s->clkidle[5] = value & 0x000000cf;
3338 827df9f3 balrog
        /* TODO update clocks */
3339 827df9f3 balrog
        break;
3340 827df9f3 balrog
    case 0x540:        /* CM_CLKSEL1_PLL */
3341 51fec3cc balrog
        if (value & 0xfc4000d7)
3342 51fec3cc balrog
            fprintf(stderr, "%s: write 0s in CM_CLKSEL1_PLL for "
3343 51fec3cc balrog
                            "future compatiblity\n", __FUNCTION__);
3344 51fec3cc balrog
        if ((s->clksel[5] ^ value) & 0x003fff00) {
3345 51fec3cc balrog
            s->clksel[5] = value & 0x03bfff28;
3346 51fec3cc balrog
            omap_prcm_dpll_update(s);
3347 51fec3cc balrog
        }
3348 51fec3cc balrog
        /* TODO update the other clocks */
3349 51fec3cc balrog
3350 827df9f3 balrog
        s->clksel[5] = value & 0x03bfff28;
3351 827df9f3 balrog
        break;
3352 827df9f3 balrog
    case 0x544:        /* CM_CLKSEL2_PLL */
3353 51fec3cc balrog
        if (value & ~3)
3354 51fec3cc balrog
            fprintf(stderr, "%s: write 0s in CM_CLKSEL2_PLL[31:2] for "
3355 51fec3cc balrog
                            "future compatiblity\n", __FUNCTION__);
3356 51fec3cc balrog
        if (s->clksel[6] != (value & 3)) {
3357 51fec3cc balrog
            s->clksel[6] = value & 3;
3358 51fec3cc balrog
            omap_prcm_dpll_update(s);
3359 51fec3cc balrog
        }
3360 827df9f3 balrog
        break;
3361 827df9f3 balrog
3362 827df9f3 balrog
    case 0x800:        /* CM_FCLKEN_DSP */
3363 827df9f3 balrog
        s->clken[10] = value & 0x501;
3364 827df9f3 balrog
        /* TODO update clocks */
3365 827df9f3 balrog
        break;
3366 827df9f3 balrog
    case 0x810:        /* CM_ICLKEN_DSP */
3367 827df9f3 balrog
        s->clken[11] = value & 0x2;
3368 827df9f3 balrog
        /* TODO update clocks */
3369 827df9f3 balrog
        break;
3370 827df9f3 balrog
    case 0x830:        /* CM_AUTOIDLE_DSP */
3371 827df9f3 balrog
        s->clkidle[6] = value & 0x2;
3372 827df9f3 balrog
        /* TODO update clocks */
3373 827df9f3 balrog
        break;
3374 827df9f3 balrog
    case 0x840:        /* CM_CLKSEL_DSP */
3375 827df9f3 balrog
        s->clksel[7] = value & 0x3fff;
3376 827df9f3 balrog
        /* TODO update clocks */
3377 827df9f3 balrog
        break;
3378 827df9f3 balrog
    case 0x848:        /* CM_CLKSTCTRL_DSP */
3379 827df9f3 balrog
        s->clkctrl[3] = value & 0x101;
3380 827df9f3 balrog
        break;
3381 827df9f3 balrog
    case 0x850:        /* RM_RSTCTRL_DSP */
3382 827df9f3 balrog
        /* TODO: reset */
3383 827df9f3 balrog
        break;
3384 827df9f3 balrog
    case 0x858:        /* RM_RSTST_DSP */
3385 827df9f3 balrog
        s->rst[3] &= ~value;
3386 827df9f3 balrog
        break;
3387 827df9f3 balrog
    case 0x8c8:        /* PM_WKDEP_DSP */
3388 827df9f3 balrog
        s->wkup[2] = value & 0x13;
3389 827df9f3 balrog
        break;
3390 827df9f3 balrog
    case 0x8e0:        /* PM_PWSTCTRL_DSP */
3391 827df9f3 balrog
        s->power[3] = (value & 0x03017) | (3 << 2);
3392 827df9f3 balrog
        break;
3393 827df9f3 balrog
3394 827df9f3 balrog
    case 0x8f0:        /* PRCM_IRQSTATUS_DSP */
3395 827df9f3 balrog
        s->irqst[1] &= ~value;
3396 827df9f3 balrog
        omap_prcm_int_update(s, 1);
3397 827df9f3 balrog
        break;
3398 827df9f3 balrog
    case 0x8f4:        /* PRCM_IRQENABLE_DSP */
3399 827df9f3 balrog
        s->irqen[1] = value & 0x7;
3400 827df9f3 balrog
        omap_prcm_int_update(s, 1);
3401 827df9f3 balrog
        break;
3402 827df9f3 balrog
3403 827df9f3 balrog
    case 0x8f8:        /* PRCM_IRQSTATUS_IVA */
3404 827df9f3 balrog
        s->irqst[2] &= ~value;
3405 827df9f3 balrog
        omap_prcm_int_update(s, 2);
3406 827df9f3 balrog
        break;
3407 827df9f3 balrog
    case 0x8fc:        /* PRCM_IRQENABLE_IVA */
3408 827df9f3 balrog
        s->irqen[2] = value & 0x7;
3409 827df9f3 balrog
        omap_prcm_int_update(s, 2);
3410 827df9f3 balrog
        break;
3411 827df9f3 balrog
3412 827df9f3 balrog
    default:
3413 827df9f3 balrog
        OMAP_BAD_REG(addr);
3414 827df9f3 balrog
        return;
3415 827df9f3 balrog
    }
3416 827df9f3 balrog
}
3417 827df9f3 balrog
3418 827df9f3 balrog
static CPUReadMemoryFunc *omap_prcm_readfn[] = {
3419 827df9f3 balrog
    omap_badwidth_read32,
3420 827df9f3 balrog
    omap_badwidth_read32,
3421 827df9f3 balrog
    omap_prcm_read,
3422 827df9f3 balrog
};
3423 827df9f3 balrog
3424 827df9f3 balrog
static CPUWriteMemoryFunc *omap_prcm_writefn[] = {
3425 827df9f3 balrog
    omap_badwidth_write32,
3426 827df9f3 balrog
    omap_badwidth_write32,
3427 827df9f3 balrog
    omap_prcm_write,
3428 827df9f3 balrog
};
3429 827df9f3 balrog
3430 827df9f3 balrog
static void omap_prcm_reset(struct omap_prcm_s *s)
3431 827df9f3 balrog
{
3432 827df9f3 balrog
    s->sysconfig = 0;
3433 827df9f3 balrog
    s->irqst[0] = 0;
3434 827df9f3 balrog
    s->irqst[1] = 0;
3435 827df9f3 balrog
    s->irqst[2] = 0;
3436 827df9f3 balrog
    s->irqen[0] = 0;
3437 827df9f3 balrog
    s->irqen[1] = 0;
3438 827df9f3 balrog
    s->irqen[2] = 0;
3439 827df9f3 balrog
    s->voltctrl = 0x1040;
3440 827df9f3 balrog
    s->ev = 0x14;
3441 827df9f3 balrog
    s->evtime[0] = 0;
3442 827df9f3 balrog
    s->evtime[1] = 0;
3443 827df9f3 balrog
    s->clkctrl[0] = 0;
3444 827df9f3 balrog
    s->clkctrl[1] = 0;
3445 827df9f3 balrog
    s->clkctrl[2] = 0;
3446 827df9f3 balrog
    s->clkctrl[3] = 0;
3447 827df9f3 balrog
    s->clken[1] = 7;
3448 827df9f3 balrog
    s->clken[3] = 7;
3449 827df9f3 balrog
    s->clken[4] = 0;
3450 827df9f3 balrog
    s->clken[5] = 0;
3451 827df9f3 balrog
    s->clken[6] = 0;
3452 827df9f3 balrog
    s->clken[7] = 0xc;
3453 827df9f3 balrog
    s->clken[8] = 0x3e;
3454 827df9f3 balrog
    s->clken[9] = 0x0d;
3455 827df9f3 balrog
    s->clken[10] = 0;
3456 827df9f3 balrog
    s->clken[11] = 0;
3457 827df9f3 balrog
    s->clkidle[0] = 0;
3458 827df9f3 balrog
    s->clkidle[2] = 7;
3459 827df9f3 balrog
    s->clkidle[3] = 0;
3460 827df9f3 balrog
    s->clkidle[4] = 0;
3461 827df9f3 balrog
    s->clkidle[5] = 0x0c;
3462 827df9f3 balrog
    s->clkidle[6] = 0;
3463 827df9f3 balrog
    s->clksel[0] = 0x01;
3464 827df9f3 balrog
    s->clksel[1] = 0x02100121;
3465 827df9f3 balrog
    s->clksel[2] = 0x00000000;
3466 827df9f3 balrog
    s->clksel[3] = 0x01;
3467 827df9f3 balrog
    s->clksel[4] = 0;
3468 827df9f3 balrog
    s->clksel[7] = 0x0121;
3469 827df9f3 balrog
    s->wkup[0] = 0x15;
3470 827df9f3 balrog
    s->wkup[1] = 0x13;
3471 827df9f3 balrog
    s->wkup[2] = 0x13;
3472 827df9f3 balrog
    s->wken[0] = 0x04667ff8;
3473 827df9f3 balrog
    s->wken[1] = 0x00000005;
3474 827df9f3 balrog
    s->wken[2] = 5;
3475 827df9f3 balrog
    s->wkst[0] = 0;
3476 827df9f3 balrog
    s->wkst[1] = 0;
3477 827df9f3 balrog
    s->wkst[2] = 0;
3478 827df9f3 balrog
    s->power[0] = 0x00c;
3479 827df9f3 balrog
    s->power[1] = 4;
3480 827df9f3 balrog
    s->power[2] = 0x0000c;
3481 827df9f3 balrog
    s->power[3] = 0x14;
3482 827df9f3 balrog
    s->rstctrl[0] = 1;
3483 827df9f3 balrog
    s->rst[3] = 1;
3484 51fec3cc balrog
    omap_prcm_apll_update(s);
3485 51fec3cc balrog
    omap_prcm_dpll_update(s);
3486 827df9f3 balrog
}
3487 827df9f3 balrog
3488 827df9f3 balrog
static void omap_prcm_coldreset(struct omap_prcm_s *s)
3489 827df9f3 balrog
{
3490 827df9f3 balrog
    s->setuptime[0] = 0;
3491 827df9f3 balrog
    s->setuptime[1] = 0;
3492 827df9f3 balrog
    memset(&s->scratch, 0, sizeof(s->scratch));
3493 827df9f3 balrog
    s->rst[0] = 0x01;
3494 827df9f3 balrog
    s->rst[1] = 0x00;
3495 827df9f3 balrog
    s->rst[2] = 0x01;
3496 827df9f3 balrog
    s->clken[0] = 0;
3497 827df9f3 balrog
    s->clken[2] = 0;
3498 827df9f3 balrog
    s->clkidle[1] = 0;
3499 827df9f3 balrog
    s->clksel[5] = 0;
3500 827df9f3 balrog
    s->clksel[6] = 2;
3501 827df9f3 balrog
    s->clksrc[0] = 0x43;
3502 827df9f3 balrog
    s->clkout[0] = 0x0303;
3503 827df9f3 balrog
    s->clkemul[0] = 0;
3504 827df9f3 balrog
    s->clkpol[0] = 0x100;
3505 827df9f3 balrog
    s->rsttime_wkup = 0x1002;
3506 827df9f3 balrog
3507 827df9f3 balrog
    omap_prcm_reset(s);
3508 827df9f3 balrog
}
3509 827df9f3 balrog
3510 827df9f3 balrog
struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
3511 827df9f3 balrog
                qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int,
3512 827df9f3 balrog
                struct omap_mpu_state_s *mpu)
3513 827df9f3 balrog
{
3514 827df9f3 balrog
    int iomemtype;
3515 827df9f3 balrog
    struct omap_prcm_s *s = (struct omap_prcm_s *)
3516 827df9f3 balrog
            qemu_mallocz(sizeof(struct omap_prcm_s));
3517 827df9f3 balrog
3518 827df9f3 balrog
    s->irq[0] = mpu_int;
3519 827df9f3 balrog
    s->irq[1] = dsp_int;
3520 827df9f3 balrog
    s->irq[2] = iva_int;
3521 827df9f3 balrog
    s->mpu = mpu;
3522 827df9f3 balrog
    omap_prcm_coldreset(s);
3523 827df9f3 balrog
3524 c66fb5bc balrog
    iomemtype = l4_register_io_memory(0, omap_prcm_readfn,
3525 827df9f3 balrog
                    omap_prcm_writefn, s);
3526 8da3ff18 pbrook
    omap_l4_attach(ta, 0, iomemtype);
3527 827df9f3 balrog
    omap_l4_attach(ta, 1, iomemtype);
3528 827df9f3 balrog
3529 827df9f3 balrog
    return s;
3530 827df9f3 balrog
}
3531 827df9f3 balrog
3532 827df9f3 balrog
/* System and Pinout control */
3533 827df9f3 balrog
struct omap_sysctl_s {
3534 827df9f3 balrog
    struct omap_mpu_state_s *mpu;
3535 827df9f3 balrog
3536 827df9f3 balrog
    uint32_t sysconfig;
3537 827df9f3 balrog
    uint32_t devconfig;
3538 827df9f3 balrog
    uint32_t psaconfig;
3539 827df9f3 balrog
    uint32_t padconf[0x45];
3540 827df9f3 balrog
    uint8_t obs;
3541 827df9f3 balrog
    uint32_t msuspendmux[5];
3542 827df9f3 balrog
};
3543 827df9f3 balrog
3544 f451387a balrog
static uint32_t omap_sysctl_read8(void *opaque, target_phys_addr_t addr)
3545 f451387a balrog
{
3546 f451387a balrog
3547 f451387a balrog
    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
3548 f451387a balrog
    int pad_offset, byte_offset;
3549 f451387a balrog
    int value;
3550 f451387a balrog
3551 8da3ff18 pbrook
    switch (addr) {
3552 f451387a balrog
    case 0x030 ... 0x140:        /* CONTROL_PADCONF - only used in the POP */
3553 8da3ff18 pbrook
        pad_offset = (addr - 0x30) >> 2;
3554 8da3ff18 pbrook
        byte_offset = (addr - 0x30) & (4 - 1);
3555 f451387a balrog
3556 f451387a balrog
        value = s->padconf[pad_offset];
3557 f451387a balrog
        value = (value >> (byte_offset * 8)) & 0xff;
3558 f451387a balrog
3559 f451387a balrog
        return value;
3560 f451387a balrog
3561 f451387a balrog
    default:
3562 f451387a balrog
        break;
3563 f451387a balrog
    }
3564 f451387a balrog
3565 f451387a balrog
    OMAP_BAD_REG(addr);
3566 f451387a balrog
    return 0;
3567 f451387a balrog
}
3568 f451387a balrog
3569 827df9f3 balrog
static uint32_t omap_sysctl_read(void *opaque, target_phys_addr_t addr)
3570 827df9f3 balrog
{
3571 827df9f3 balrog
    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
3572 827df9f3 balrog
3573 8da3ff18 pbrook
    switch (addr) {
3574 827df9f3 balrog
    case 0x000:        /* CONTROL_REVISION */
3575 827df9f3 balrog
        return 0x20;
3576 827df9f3 balrog
3577 827df9f3 balrog
    case 0x010:        /* CONTROL_SYSCONFIG */
3578 827df9f3 balrog
        return s->sysconfig;
3579 827df9f3 balrog
3580 827df9f3 balrog
    case 0x030 ... 0x140:        /* CONTROL_PADCONF - only used in the POP */
3581 8da3ff18 pbrook
        return s->padconf[(addr - 0x30) >> 2];
3582 827df9f3 balrog
3583 827df9f3 balrog
    case 0x270:        /* CONTROL_DEBOBS */
3584 827df9f3 balrog
        return s->obs;
3585 827df9f3 balrog
3586 827df9f3 balrog
    case 0x274:        /* CONTROL_DEVCONF */
3587 827df9f3 balrog
        return s->devconfig;
3588 827df9f3 balrog
3589 827df9f3 balrog
    case 0x28c:        /* CONTROL_EMU_SUPPORT */
3590 827df9f3 balrog
        return 0;
3591 827df9f3 balrog
3592 827df9f3 balrog
    case 0x290:        /* CONTROL_MSUSPENDMUX_0 */
3593 827df9f3 balrog
        return s->msuspendmux[0];
3594 827df9f3 balrog
    case 0x294:        /* CONTROL_MSUSPENDMUX_1 */
3595 827df9f3 balrog
        return s->msuspendmux[1];
3596 827df9f3 balrog
    case 0x298:        /* CONTROL_MSUSPENDMUX_2 */
3597 827df9f3 balrog
        return s->msuspendmux[2];
3598 827df9f3 balrog
    case 0x29c:        /* CONTROL_MSUSPENDMUX_3 */
3599 827df9f3 balrog
        return s->msuspendmux[3];
3600 827df9f3 balrog
    case 0x2a0:        /* CONTROL_MSUSPENDMUX_4 */
3601 827df9f3 balrog
        return s->msuspendmux[4];
3602 827df9f3 balrog
    case 0x2a4:        /* CONTROL_MSUSPENDMUX_5 */
3603 827df9f3 balrog
        return 0;
3604 827df9f3 balrog
3605 827df9f3 balrog
    case 0x2b8:        /* CONTROL_PSA_CTRL */
3606 827df9f3 balrog
        return s->psaconfig;
3607 827df9f3 balrog
    case 0x2bc:        /* CONTROL_PSA_CMD */
3608 827df9f3 balrog
    case 0x2c0:        /* CONTROL_PSA_VALUE */
3609 827df9f3 balrog
        return 0;
3610 827df9f3 balrog
3611 827df9f3 balrog
    case 0x2b0:        /* CONTROL_SEC_CTRL */
3612 827df9f3 balrog
        return 0x800000f1;
3613 827df9f3 balrog
    case 0x2d0:        /* CONTROL_SEC_EMU */
3614 827df9f3 balrog
        return 0x80000015;
3615 827df9f3 balrog
    case 0x2d4:        /* CONTROL_SEC_TAP */
3616 827df9f3 balrog
        return 0x8000007f;
3617 827df9f3 balrog
    case 0x2b4:        /* CONTROL_SEC_TEST */
3618 827df9f3 balrog
    case 0x2f0:        /* CONTROL_SEC_STATUS */
3619 827df9f3 balrog
    case 0x2f4:        /* CONTROL_SEC_ERR_STATUS */
3620 827df9f3 balrog
        /* Secure mode is not present on general-pusrpose device.  Outside
3621 827df9f3 balrog
         * secure mode these values cannot be read or written.  */
3622 827df9f3 balrog
        return 0;
3623 827df9f3 balrog
3624 827df9f3 balrog
    case 0x2d8:        /* CONTROL_OCM_RAM_PERM */
3625 827df9f3 balrog
        return 0xff;
3626 827df9f3 balrog
    case 0x2dc:        /* CONTROL_OCM_PUB_RAM_ADD */
3627 827df9f3 balrog
    case 0x2e0:        /* CONTROL_EXT_SEC_RAM_START_ADD */
3628 827df9f3 balrog
    case 0x2e4:        /* CONTROL_EXT_SEC_RAM_STOP_ADD */
3629 827df9f3 balrog
        /* No secure mode so no Extended Secure RAM present.  */
3630 827df9f3 balrog
        return 0;
3631 827df9f3 balrog
3632 827df9f3 balrog
    case 0x2f8:        /* CONTROL_STATUS */
3633 827df9f3 balrog
        /* Device Type => General-purpose */
3634 827df9f3 balrog
        return 0x0300;
3635 827df9f3 balrog
    case 0x2fc:        /* CONTROL_GENERAL_PURPOSE_STATUS */
3636 827df9f3 balrog
3637 827df9f3 balrog
    case 0x300:        /* CONTROL_RPUB_KEY_H_0 */
3638 827df9f3 balrog
    case 0x304:        /* CONTROL_RPUB_KEY_H_1 */
3639 827df9f3 balrog
    case 0x308:        /* CONTROL_RPUB_KEY_H_2 */
3640 827df9f3 balrog
    case 0x30c:        /* CONTROL_RPUB_KEY_H_3 */
3641 827df9f3 balrog
        return 0xdecafbad;
3642 827df9f3 balrog
3643 827df9f3 balrog
    case 0x310:        /* CONTROL_RAND_KEY_0 */
3644 827df9f3 balrog
    case 0x314:        /* CONTROL_RAND_KEY_1 */
3645 827df9f3 balrog
    case 0x318:        /* CONTROL_RAND_KEY_2 */
3646 827df9f3 balrog
    case 0x31c:        /* CONTROL_RAND_KEY_3 */
3647 827df9f3 balrog
    case 0x320:        /* CONTROL_CUST_KEY_0 */
3648 827df9f3 balrog
    case 0x324:        /* CONTROL_CUST_KEY_1 */
3649 827df9f3 balrog
    case 0x330:        /* CONTROL_TEST_KEY_0 */
3650 827df9f3 balrog
    case 0x334:        /* CONTROL_TEST_KEY_1 */
3651 827df9f3 balrog
    case 0x338:        /* CONTROL_TEST_KEY_2 */
3652 827df9f3 balrog
    case 0x33c:        /* CONTROL_TEST_KEY_3 */
3653 827df9f3 balrog
    case 0x340:        /* CONTROL_TEST_KEY_4 */
3654 827df9f3 balrog
    case 0x344:        /* CONTROL_TEST_KEY_5 */
3655 827df9f3 balrog
    case 0x348:        /* CONTROL_TEST_KEY_6 */
3656 827df9f3 balrog
    case 0x34c:        /* CONTROL_TEST_KEY_7 */
3657 827df9f3 balrog
    case 0x350:        /* CONTROL_TEST_KEY_8 */
3658 827df9f3 balrog
    case 0x354:        /* CONTROL_TEST_KEY_9 */
3659 827df9f3 balrog
        /* Can only be accessed in secure mode and when C_FieldAccEnable
3660 827df9f3 balrog
         * bit is set in CONTROL_SEC_CTRL.
3661 827df9f3 balrog
         * TODO: otherwise an interconnect access error is generated.  */
3662 827df9f3 balrog
        return 0;
3663 827df9f3 balrog
    }
3664 827df9f3 balrog
3665 827df9f3 balrog
    OMAP_BAD_REG(addr);
3666 827df9f3 balrog
    return 0;
3667 827df9f3 balrog
}
3668 827df9f3 balrog
3669 f451387a balrog
static void omap_sysctl_write8(void *opaque, target_phys_addr_t addr,
3670 f451387a balrog
                uint32_t value)
3671 f451387a balrog
{
3672 f451387a balrog
    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
3673 f451387a balrog
    int pad_offset, byte_offset;
3674 f451387a balrog
    int prev_value;
3675 f451387a balrog
3676 8da3ff18 pbrook
    switch (addr) {
3677 f451387a balrog
    case 0x030 ... 0x140:        /* CONTROL_PADCONF - only used in the POP */
3678 8da3ff18 pbrook
        pad_offset = (addr - 0x30) >> 2;
3679 8da3ff18 pbrook
        byte_offset = (addr - 0x30) & (4 - 1);
3680 f451387a balrog
3681 f451387a balrog
        prev_value = s->padconf[pad_offset];
3682 f451387a balrog
        prev_value &= ~(0xff << (byte_offset * 8));
3683 f451387a balrog
        prev_value |= ((value & 0x1f1f1f1f) << (byte_offset * 8)) & 0x1f1f1f1f;
3684 f451387a balrog
        s->padconf[pad_offset] = prev_value;
3685 f451387a balrog
        break;
3686 f451387a balrog
3687 f451387a balrog
    default:
3688 f451387a balrog
        OMAP_BAD_REG(addr);
3689 f451387a balrog
        break;
3690 f451387a balrog
    }
3691 f451387a balrog
}
3692 f451387a balrog
3693 827df9f3 balrog
static void omap_sysctl_write(void *opaque, target_phys_addr_t addr,
3694 827df9f3 balrog
                uint32_t value)
3695 827df9f3 balrog
{
3696 827df9f3 balrog
    struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
3697 827df9f3 balrog
3698 8da3ff18 pbrook
    switch (addr) {
3699 827df9f3 balrog
    case 0x000:        /* CONTROL_REVISION */
3700 827df9f3 balrog
    case 0x2a4:        /* CONTROL_MSUSPENDMUX_5 */
3701 827df9f3 balrog
    case 0x2c0:        /* CONTROL_PSA_VALUE */
3702 827df9f3 balrog
    case 0x2f8:        /* CONTROL_STATUS */
3703 827df9f3 balrog
    case 0x2fc:        /* CONTROL_GENERAL_PURPOSE_STATUS */
3704 827df9f3 balrog
    case 0x300:        /* CONTROL_RPUB_KEY_H_0 */
3705 827df9f3 balrog
    case 0x304:        /* CONTROL_RPUB_KEY_H_1 */
3706 827df9f3 balrog
    case 0x308:        /* CONTROL_RPUB_KEY_H_2 */
3707 827df9f3 balrog
    case 0x30c:        /* CONTROL_RPUB_KEY_H_3 */
3708 827df9f3 balrog
    case 0x310:        /* CONTROL_RAND_KEY_0 */
3709 827df9f3 balrog
    case 0x314:        /* CONTROL_RAND_KEY_1 */
3710 827df9f3 balrog
    case 0x318:        /* CONTROL_RAND_KEY_2 */
3711 827df9f3 balrog
    case 0x31c:        /* CONTROL_RAND_KEY_3 */
3712 827df9f3 balrog
    case 0x320:        /* CONTROL_CUST_KEY_0 */
3713 827df9f3 balrog
    case 0x324:        /* CONTROL_CUST_KEY_1 */
3714 827df9f3 balrog
    case 0x330:        /* CONTROL_TEST_KEY_0 */
3715 827df9f3 balrog
    case 0x334:        /* CONTROL_TEST_KEY_1 */
3716 827df9f3 balrog
    case 0x338:        /* CONTROL_TEST_KEY_2 */
3717 827df9f3 balrog
    case 0x33c:        /* CONTROL_TEST_KEY_3 */
3718 827df9f3 balrog
    case 0x340:        /* CONTROL_TEST_KEY_4 */
3719 827df9f3 balrog
    case 0x344:        /* CONTROL_TEST_KEY_5 */
3720 827df9f3 balrog
    case 0x348:        /* CONTROL_TEST_KEY_6 */
3721 827df9f3 balrog
    case 0x34c:        /* CONTROL_TEST_KEY_7 */
3722 827df9f3 balrog
    case 0x350:        /* CONTROL_TEST_KEY_8 */
3723 827df9f3 balrog
    case 0x354:        /* CONTROL_TEST_KEY_9 */
3724 827df9f3 balrog
        OMAP_RO_REG(addr);
3725 827df9f3 balrog
        return;
3726 827df9f3 balrog
3727 827df9f3 balrog
    case 0x010:        /* CONTROL_SYSCONFIG */
3728 827df9f3 balrog
        s->sysconfig = value & 0x1e;
3729 827df9f3 balrog
        break;
3730 827df9f3 balrog
3731 827df9f3 balrog
    case 0x030 ... 0x140:        /* CONTROL_PADCONF - only used in the POP */
3732 827df9f3 balrog
        /* XXX: should check constant bits */
3733 8da3ff18 pbrook
        s->padconf[(addr - 0x30) >> 2] = value & 0x1f1f1f1f;
3734 827df9f3 balrog
        break;
3735 827df9f3 balrog
3736 827df9f3 balrog
    case 0x270:        /* CONTROL_DEBOBS */
3737 827df9f3 balrog
        s->obs = value & 0xff;
3738 827df9f3 balrog
        break;
3739 827df9f3 balrog
3740 827df9f3 balrog
    case 0x274:        /* CONTROL_DEVCONF */
3741 827df9f3 balrog
        s->devconfig = value & 0xffffc7ff;
3742 827df9f3 balrog
        break;
3743 827df9f3 balrog
3744 827df9f3 balrog
    case 0x28c:        /* CONTROL_EMU_SUPPORT */
3745 827df9f3 balrog
        break;
3746 827df9f3 balrog
3747 827df9f3 balrog
    case 0x290:        /* CONTROL_MSUSPENDMUX_0 */
3748 827df9f3 balrog
        s->msuspendmux[0] = value & 0x3fffffff;
3749 827df9f3 balrog
        break;
3750 827df9f3 balrog
    case 0x294:        /* CONTROL_MSUSPENDMUX_1 */
3751 827df9f3 balrog
        s->msuspendmux[1] = value & 0x3fffffff;
3752 827df9f3 balrog
        break;
3753 827df9f3 balrog
    case 0x298:        /* CONTROL_MSUSPENDMUX_2 */
3754 827df9f3 balrog
        s->msuspendmux[2] = value & 0x3fffffff;
3755 827df9f3 balrog
        break;
3756 827df9f3 balrog
    case 0x29c:        /* CONTROL_MSUSPENDMUX_3 */
3757 827df9f3 balrog
        s->msuspendmux[3] = value & 0x3fffffff;
3758 827df9f3 balrog
        break;
3759 827df9f3 balrog
    case 0x2a0:        /* CONTROL_MSUSPENDMUX_4 */
3760 827df9f3 balrog
        s->msuspendmux[4] = value & 0x3fffffff;
3761 827df9f3 balrog
        break;
3762 827df9f3 balrog
3763 827df9f3 balrog
    case 0x2b8:        /* CONTROL_PSA_CTRL */
3764 827df9f3 balrog
        s->psaconfig = value & 0x1c;
3765 827df9f3 balrog
        s->psaconfig |= (value & 0x20) ? 2 : 1;
3766 827df9f3 balrog
        break;
3767 827df9f3 balrog
    case 0x2bc:        /* CONTROL_PSA_CMD */
3768 827df9f3 balrog
        break;
3769 827df9f3 balrog
3770 827df9f3 balrog
    case 0x2b0:        /* CONTROL_SEC_CTRL */
3771 827df9f3 balrog
    case 0x2b4:        /* CONTROL_SEC_TEST */
3772 827df9f3 balrog
    case 0x2d0:        /* CONTROL_SEC_EMU */
3773 827df9f3 balrog
    case 0x2d4:        /* CONTROL_SEC_TAP */
3774 827df9f3 balrog
    case 0x2d8:        /* CONTROL_OCM_RAM_PERM */
3775 827df9f3 balrog
    case 0x2dc:        /* CONTROL_OCM_PUB_RAM_ADD */
3776 827df9f3 balrog
    case 0x2e0:        /* CONTROL_EXT_SEC_RAM_START_ADD */
3777 827df9f3 balrog
    case 0x2e4:        /* CONTROL_EXT_SEC_RAM_STOP_ADD */
3778 827df9f3 balrog
    case 0x2f0:        /* CONTROL_SEC_STATUS */
3779 827df9f3 balrog
    case 0x2f4:        /* CONTROL_SEC_ERR_STATUS */
3780 827df9f3 balrog
        break;
3781 827df9f3 balrog
3782 827df9f3 balrog
    default:
3783 827df9f3 balrog
        OMAP_BAD_REG(addr);
3784 827df9f3 balrog
        return;
3785 827df9f3 balrog
    }
3786 827df9f3 balrog
}
3787 827df9f3 balrog
3788 827df9f3 balrog
static CPUReadMemoryFunc *omap_sysctl_readfn[] = {
3789 f451387a balrog
    omap_sysctl_read8,
3790 827df9f3 balrog
    omap_badwidth_read32,        /* TODO */
3791 827df9f3 balrog
    omap_sysctl_read,
3792 827df9f3 balrog
};
3793 827df9f3 balrog
3794 827df9f3 balrog
static CPUWriteMemoryFunc *omap_sysctl_writefn[] = {
3795 f451387a balrog
    omap_sysctl_write8,
3796 827df9f3 balrog
    omap_badwidth_write32,        /* TODO */
3797 827df9f3 balrog
    omap_sysctl_write,
3798 827df9f3 balrog
};
3799 827df9f3 balrog
3800 827df9f3 balrog
static void omap_sysctl_reset(struct omap_sysctl_s *s)
3801 827df9f3 balrog
{
3802 827df9f3 balrog
    /* (power-on reset) */
3803 827df9f3 balrog
    s->sysconfig = 0;
3804 827df9f3 balrog
    s->obs = 0;
3805 827df9f3 balrog
    s->devconfig = 0x0c000000;
3806 827df9f3 balrog
    s->msuspendmux[0] = 0x00000000;
3807 827df9f3 balrog
    s->msuspendmux[1] = 0x00000000;
3808 827df9f3 balrog
    s->msuspendmux[2] = 0x00000000;
3809 827df9f3 balrog
    s->msuspendmux[3] = 0x00000000;
3810 827df9f3 balrog
    s->msuspendmux[4] = 0x00000000;
3811 827df9f3 balrog
    s->psaconfig = 1;
3812 827df9f3 balrog
3813 827df9f3 balrog
    s->padconf[0x00] = 0x000f0f0f;
3814 827df9f3 balrog
    s->padconf[0x01] = 0x00000000;
3815 827df9f3 balrog
    s->padconf[0x02] = 0x00000000;
3816 827df9f3 balrog
    s->padconf[0x03] = 0x00000000;
3817 827df9f3 balrog
    s->padconf[0x04] = 0x00000000;
3818 827df9f3 balrog
    s->padconf[0x05] = 0x00000000;
3819 827df9f3 balrog
    s->padconf[0x06] = 0x00000000;
3820 827df9f3 balrog
    s->padconf[0x07] = 0x00000000;
3821 827df9f3 balrog
    s->padconf[0x08] = 0x08080800;
3822 827df9f3 balrog
    s->padconf[0x09] = 0x08080808;
3823 827df9f3 balrog
    s->padconf[0x0a] = 0x08080808;
3824 827df9f3 balrog
    s->padconf[0x0b] = 0x08080808;
3825 827df9f3 balrog
    s->padconf[0x0c] = 0x08080808;
3826 827df9f3 balrog
    s->padconf[0x0d] = 0x08080800;
3827 827df9f3 balrog
    s->padconf[0x0e] = 0x08080808;
3828 827df9f3 balrog
    s->padconf[0x0f] = 0x08080808;
3829 827df9f3 balrog
    s->padconf[0x10] = 0x18181808;        /* | 0x07070700 if SBoot3 */
3830 827df9f3 balrog
    s->padconf[0x11] = 0x18181818;        /* | 0x07070707 if SBoot3 */
3831 827df9f3 balrog
    s->padconf[0x12] = 0x18181818;        /* | 0x07070707 if SBoot3 */
3832 827df9f3 balrog
    s->padconf[0x13] = 0x18181818;        /* | 0x07070707 if SBoot3 */
3833 827df9f3 balrog
    s->padconf[0x14] = 0x18181818;        /* | 0x00070707 if SBoot3 */
3834 827df9f3 balrog
    s->padconf[0x15] = 0x18181818;
3835 827df9f3 balrog
    s->padconf[0x16] = 0x18181818;        /* | 0x07000000 if SBoot3 */
3836 827df9f3 balrog
    s->padconf[0x17] = 0x1f001f00;
3837 827df9f3 balrog
    s->padconf[0x18] = 0x1f1f1f1f;
3838 827df9f3 balrog
    s->padconf[0x19] = 0x00000000;
3839 827df9f3 balrog
    s->padconf[0x1a] = 0x1f180000;
3840 827df9f3 balrog
    s->padconf[0x1b] = 0x00001f1f;
3841 827df9f3 balrog
    s->padconf[0x1c] = 0x1f001f00;
3842 827df9f3 balrog
    s->padconf[0x1d] = 0x00000000;
3843 827df9f3 balrog
    s->padconf[0x1e] = 0x00000000;
3844 827df9f3 balrog
    s->padconf[0x1f] = 0x08000000;
3845 827df9f3 balrog
    s->padconf[0x20] = 0x08080808;
3846 827df9f3 balrog
    s->padconf[0x21] = 0x08080808;
3847 827df9f3 balrog
    s->padconf[0x22] = 0x0f080808;
3848 827df9f3 balrog
    s->padconf[0x23] = 0x0f0f0f0f;
3849 827df9f3 balrog
    s->padconf[0x24] = 0x000f0f0f;
3850 827df9f3 balrog
    s->padconf[0x25] = 0x1f1f1f0f;
3851 827df9f3 balrog
    s->padconf[0x26] = 0x080f0f1f;
3852 827df9f3 balrog
    s->padconf[0x27] = 0x070f1808;
3853 827df9f3 balrog
    s->padconf[0x28] = 0x0f070707;
3854 827df9f3 balrog
    s->padconf[0x29] = 0x000f0f1f;
3855 827df9f3 balrog
    s->padconf[0x2a] = 0x0f0f0f1f;
3856 827df9f3 balrog
    s->padconf[0x2b] = 0x08000000;
3857 827df9f3 balrog
    s->padconf[0x2c] = 0x0000001f;
3858 827df9f3 balrog
    s->padconf[0x2d] = 0x0f0f1f00;
3859 827df9f3 balrog
    s->padconf[0x2e] = 0x1f1f0f0f;
3860 827df9f3 balrog
    s->padconf[0x2f] = 0x0f1f1f1f;
3861 827df9f3 balrog
    s->padconf[0x30] = 0x0f0f0f0f;
3862 827df9f3 balrog
    s->padconf[0x31] = 0x0f1f0f1f;
3863 827df9f3 balrog
    s->padconf[0x32] = 0x0f0f0f0f;
3864 827df9f3 balrog
    s->padconf[0x33] = 0x0f1f0f1f;
3865 827df9f3 balrog
    s->padconf[0x34] = 0x1f1f0f0f;
3866 827df9f3 balrog
    s->padconf[0x35] = 0x0f0f1f1f;
3867 827df9f3 balrog
    s->padconf[0x36] = 0x0f0f1f0f;
3868 827df9f3 balrog
    s->padconf[0x37] = 0x0f0f0f0f;
3869 827df9f3 balrog
    s->padconf[0x38] = 0x1f18180f;
3870 827df9f3 balrog
    s->padconf[0x39] = 0x1f1f1f1f;
3871 827df9f3 balrog
    s->padconf[0x3a] = 0x00001f1f;
3872 827df9f3 balrog
    s->padconf[0x3b] = 0x00000000;
3873 827df9f3 balrog
    s->padconf[0x3c] = 0x00000000;
3874 827df9f3 balrog
    s->padconf[0x3d] = 0x0f0f0f0f;
3875 827df9f3 balrog
    s->padconf[0x3e] = 0x18000f0f;
3876 827df9f3 balrog
    s->padconf[0x3f] = 0x00070000;
3877 827df9f3 balrog
    s->padconf[0x40] = 0x00000707;
3878 827df9f3 balrog
    s->padconf[0x41] = 0x0f1f0700;
3879 827df9f3 balrog
    s->padconf[0x42] = 0x1f1f070f;
3880 827df9f3 balrog
    s->padconf[0x43] = 0x0008081f;
3881 827df9f3 balrog
    s->padconf[0x44] = 0x00000800;
3882 827df9f3 balrog
}
3883 827df9f3 balrog
3884 827df9f3 balrog
struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
3885 827df9f3 balrog
                omap_clk iclk, struct omap_mpu_state_s *mpu)
3886 827df9f3 balrog
{
3887 827df9f3 balrog
    int iomemtype;
3888 827df9f3 balrog
    struct omap_sysctl_s *s = (struct omap_sysctl_s *)
3889 827df9f3 balrog
            qemu_mallocz(sizeof(struct omap_sysctl_s));
3890 827df9f3 balrog
3891 827df9f3 balrog
    s->mpu = mpu;
3892 827df9f3 balrog
    omap_sysctl_reset(s);
3893 827df9f3 balrog
3894 c66fb5bc balrog
    iomemtype = l4_register_io_memory(0, omap_sysctl_readfn,
3895 827df9f3 balrog
                    omap_sysctl_writefn, s);
3896 8da3ff18 pbrook
    omap_l4_attach(ta, 0, iomemtype);
3897 827df9f3 balrog
3898 827df9f3 balrog
    return s;
3899 827df9f3 balrog
}
3900 827df9f3 balrog
3901 827df9f3 balrog
/* SDRAM Controller Subsystem */
3902 827df9f3 balrog
struct omap_sdrc_s {
3903 827df9f3 balrog
    uint8_t config;
3904 827df9f3 balrog
};
3905 827df9f3 balrog
3906 827df9f3 balrog
static void omap_sdrc_reset(struct omap_sdrc_s *s)
3907 827df9f3 balrog
{
3908 827df9f3 balrog
    s->config = 0x10;
3909 827df9f3 balrog
}
3910 827df9f3 balrog
3911 827df9f3 balrog
static uint32_t omap_sdrc_read(void *opaque, target_phys_addr_t addr)
3912 827df9f3 balrog
{
3913 827df9f3 balrog
    struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
3914 827df9f3 balrog
3915 8da3ff18 pbrook
    switch (addr) {
3916 827df9f3 balrog
    case 0x00:        /* SDRC_REVISION */
3917 827df9f3 balrog
        return 0x20;
3918 827df9f3 balrog
3919 827df9f3 balrog
    case 0x10:        /* SDRC_SYSCONFIG */
3920 827df9f3 balrog
        return s->config;
3921 827df9f3 balrog
3922 827df9f3 balrog
    case 0x14:        /* SDRC_SYSSTATUS */
3923 827df9f3 balrog
        return 1;                                                /* RESETDONE */
3924 827df9f3 balrog
3925 827df9f3 balrog
    case 0x40:        /* SDRC_CS_CFG */
3926 827df9f3 balrog
    case 0x44:        /* SDRC_SHARING */
3927 827df9f3 balrog
    case 0x48:        /* SDRC_ERR_ADDR */
3928 827df9f3 balrog
    case 0x4c:        /* SDRC_ERR_TYPE */
3929 827df9f3 balrog
    case 0x60:        /* SDRC_DLLA_SCTRL */
3930 827df9f3 balrog
    case 0x64:        /* SDRC_DLLA_STATUS */
3931 827df9f3 balrog
    case 0x68:        /* SDRC_DLLB_CTRL */
3932 827df9f3 balrog
    case 0x6c:        /* SDRC_DLLB_STATUS */
3933 827df9f3 balrog
    case 0x70:        /* SDRC_POWER */
3934 827df9f3 balrog
    case 0x80:        /* SDRC_MCFG_0 */
3935 827df9f3 balrog
    case 0x84:        /* SDRC_MR_0 */
3936 827df9f3 balrog
    case 0x88:        /* SDRC_EMR1_0 */
3937 827df9f3 balrog
    case 0x8c:        /* SDRC_EMR2_0 */
3938 827df9f3 balrog
    case 0x90:        /* SDRC_EMR3_0 */
3939 827df9f3 balrog
    case 0x94:        /* SDRC_DCDL1_CTRL */
3940 827df9f3 balrog
    case 0x98:        /* SDRC_DCDL2_CTRL */
3941 827df9f3 balrog
    case 0x9c:        /* SDRC_ACTIM_CTRLA_0 */
3942 827df9f3 balrog
    case 0xa0:        /* SDRC_ACTIM_CTRLB_0 */
3943 827df9f3 balrog
    case 0xa4:        /* SDRC_RFR_CTRL_0 */
3944 827df9f3 balrog
    case 0xa8:        /* SDRC_MANUAL_0 */
3945 827df9f3 balrog
    case 0xb0:        /* SDRC_MCFG_1 */
3946 827df9f3 balrog
    case 0xb4:        /* SDRC_MR_1 */
3947 827df9f3 balrog
    case 0xb8:        /* SDRC_EMR1_1 */
3948 827df9f3 balrog
    case 0xbc:        /* SDRC_EMR2_1 */
3949 827df9f3 balrog
    case 0xc0:        /* SDRC_EMR3_1 */
3950 827df9f3 balrog
    case 0xc4:        /* SDRC_ACTIM_CTRLA_1 */
3951 827df9f3 balrog
    case 0xc8:        /* SDRC_ACTIM_CTRLB_1 */
3952 827df9f3 balrog
    case 0xd4:        /* SDRC_RFR_CTRL_1 */
3953 827df9f3 balrog
    case 0xd8:        /* SDRC_MANUAL_1 */
3954 827df9f3 balrog
        return 0x00;
3955 827df9f3 balrog
    }
3956 827df9f3 balrog
3957 827df9f3 balrog
    OMAP_BAD_REG(addr);
3958 827df9f3 balrog
    return 0;
3959 827df9f3 balrog
}
3960 827df9f3 balrog
3961 827df9f3 balrog
static void omap_sdrc_write(void *opaque, target_phys_addr_t addr,
3962 827df9f3 balrog
                uint32_t value)
3963 827df9f3 balrog
{
3964 827df9f3 balrog
    struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
3965 827df9f3 balrog
3966 8da3ff18 pbrook
    switch (addr) {
3967 827df9f3 balrog
    case 0x00:        /* SDRC_REVISION */
3968 827df9f3 balrog
    case 0x14:        /* SDRC_SYSSTATUS */
3969 827df9f3 balrog
    case 0x48:        /* SDRC_ERR_ADDR */
3970 827df9f3 balrog
    case 0x64:        /* SDRC_DLLA_STATUS */
3971 827df9f3 balrog
    case 0x6c:        /* SDRC_DLLB_STATUS */
3972 827df9f3 balrog
        OMAP_RO_REG(addr);
3973 827df9f3 balrog
        return;
3974 827df9f3 balrog
3975 827df9f3 balrog
    case 0x10:        /* SDRC_SYSCONFIG */
3976 827df9f3 balrog
        if ((value >> 3) != 0x2)
3977 827df9f3 balrog
            fprintf(stderr, "%s: bad SDRAM idle mode %i\n",
3978 827df9f3 balrog
                            __FUNCTION__, value >> 3);
3979 827df9f3 balrog
        if (value & 2)
3980 827df9f3 balrog
            omap_sdrc_reset(s);
3981 827df9f3 balrog
        s->config = value & 0x18;
3982 827df9f3 balrog
        break;
3983 827df9f3 balrog
3984 827df9f3 balrog
    case 0x40:        /* SDRC_CS_CFG */
3985 827df9f3 balrog
    case 0x44:        /* SDRC_SHARING */
3986 827df9f3 balrog
    case 0x4c:        /* SDRC_ERR_TYPE */
3987 827df9f3 balrog
    case 0x60:        /* SDRC_DLLA_SCTRL */
3988 827df9f3 balrog
    case 0x68:        /* SDRC_DLLB_CTRL */
3989 827df9f3 balrog
    case 0x70:        /* SDRC_POWER */
3990 827df9f3 balrog
    case 0x80:        /* SDRC_MCFG_0 */
3991 827df9f3 balrog
    case 0x84:        /* SDRC_MR_0 */
3992 827df9f3 balrog
    case 0x88:        /* SDRC_EMR1_0 */
3993 827df9f3 balrog
    case 0x8c:        /* SDRC_EMR2_0 */
3994 827df9f3 balrog
    case 0x90:        /* SDRC_EMR3_0 */
3995 827df9f3 balrog
    case 0x94:        /* SDRC_DCDL1_CTRL */
3996 827df9f3 balrog
    case 0x98:        /* SDRC_DCDL2_CTRL */
3997 827df9f3 balrog
    case 0x9c:        /* SDRC_ACTIM_CTRLA_0 */
3998 827df9f3 balrog
    case 0xa0:        /* SDRC_ACTIM_CTRLB_0 */
3999 827df9f3 balrog
    case 0xa4:        /* SDRC_RFR_CTRL_0 */
4000 827df9f3 balrog
    case 0xa8:        /* SDRC_MANUAL_0 */
4001 827df9f3 balrog
    case 0xb0:        /* SDRC_MCFG_1 */
4002 827df9f3 balrog
    case 0xb4:        /* SDRC_MR_1 */
4003 827df9f3 balrog
    case 0xb8:        /* SDRC_EMR1_1 */
4004 827df9f3 balrog
    case 0xbc:        /* SDRC_EMR2_1 */
4005 827df9f3 balrog
    case 0xc0:        /* SDRC_EMR3_1 */
4006 827df9f3 balrog
    case 0xc4:        /* SDRC_ACTIM_CTRLA_1 */
4007 827df9f3 balrog
    case 0xc8:        /* SDRC_ACTIM_CTRLB_1 */
4008 827df9f3 balrog
    case 0xd4:        /* SDRC_RFR_CTRL_1 */
4009 827df9f3 balrog
    case 0xd8:        /* SDRC_MANUAL_1 */
4010 827df9f3 balrog
        break;
4011 827df9f3 balrog
4012 827df9f3 balrog
    default:
4013 827df9f3 balrog
        OMAP_BAD_REG(addr);
4014 827df9f3 balrog
        return;
4015 827df9f3 balrog
    }
4016 827df9f3 balrog
}
4017 827df9f3 balrog
4018 827df9f3 balrog
static CPUReadMemoryFunc *omap_sdrc_readfn[] = {
4019 827df9f3 balrog
    omap_badwidth_read32,
4020 827df9f3 balrog
    omap_badwidth_read32,
4021 827df9f3 balrog
    omap_sdrc_read,
4022 827df9f3 balrog
};
4023 827df9f3 balrog
4024 827df9f3 balrog
static CPUWriteMemoryFunc *omap_sdrc_writefn[] = {
4025 827df9f3 balrog
    omap_badwidth_write32,
4026 827df9f3 balrog
    omap_badwidth_write32,
4027 827df9f3 balrog
    omap_sdrc_write,
4028 827df9f3 balrog
};
4029 827df9f3 balrog
4030 827df9f3 balrog
struct omap_sdrc_s *omap_sdrc_init(target_phys_addr_t base)
4031 827df9f3 balrog
{
4032 827df9f3 balrog
    int iomemtype;
4033 827df9f3 balrog
    struct omap_sdrc_s *s = (struct omap_sdrc_s *)
4034 827df9f3 balrog
            qemu_mallocz(sizeof(struct omap_sdrc_s));
4035 827df9f3 balrog
4036 827df9f3 balrog
    omap_sdrc_reset(s);
4037 827df9f3 balrog
4038 827df9f3 balrog
    iomemtype = cpu_register_io_memory(0, omap_sdrc_readfn,
4039 827df9f3 balrog
                    omap_sdrc_writefn, s);
4040 8da3ff18 pbrook
    cpu_register_physical_memory(base, 0x1000, iomemtype);
4041 827df9f3 balrog
4042 827df9f3 balrog
    return s;
4043 827df9f3 balrog
}
4044 827df9f3 balrog
4045 827df9f3 balrog
/* General-Purpose Memory Controller */
4046 827df9f3 balrog
struct omap_gpmc_s {
4047 827df9f3 balrog
    qemu_irq irq;
4048 827df9f3 balrog
4049 827df9f3 balrog
    uint8_t sysconfig;
4050 827df9f3 balrog
    uint16_t irqst;
4051 827df9f3 balrog
    uint16_t irqen;
4052 827df9f3 balrog
    uint16_t timeout;
4053 827df9f3 balrog
    uint16_t config;
4054 827df9f3 balrog
    uint32_t prefconfig[2];
4055 827df9f3 balrog
    int prefcontrol;
4056 827df9f3 balrog
    int preffifo;
4057 827df9f3 balrog
    int prefcount;
4058 827df9f3 balrog
    struct omap_gpmc_cs_file_s {
4059 827df9f3 balrog
        uint32_t config[7];
4060 827df9f3 balrog
        target_phys_addr_t base;
4061 827df9f3 balrog
        size_t size;
4062 827df9f3 balrog
        int iomemtype;
4063 827df9f3 balrog
        void (*base_update)(void *opaque, target_phys_addr_t new);
4064 827df9f3 balrog
        void (*unmap)(void *opaque);
4065 827df9f3 balrog
        void *opaque;
4066 827df9f3 balrog
    } cs_file[8];
4067 827df9f3 balrog
    int ecc_cs;
4068 827df9f3 balrog
    int ecc_ptr;
4069 827df9f3 balrog
    uint32_t ecc_cfg;
4070 bc24a225 Paul Brook
    ECCState ecc[9];
4071 827df9f3 balrog
};
4072 827df9f3 balrog
4073 827df9f3 balrog
static void omap_gpmc_int_update(struct omap_gpmc_s *s)
4074 827df9f3 balrog
{
4075 827df9f3 balrog
    qemu_set_irq(s->irq, s->irqen & s->irqst);
4076 827df9f3 balrog
}
4077 827df9f3 balrog
4078 827df9f3 balrog
static void omap_gpmc_cs_map(struct omap_gpmc_cs_file_s *f, int base, int mask)
4079 827df9f3 balrog
{
4080 827df9f3 balrog
    /* TODO: check for overlapping regions and report access errors */
4081 827df9f3 balrog
    if ((mask != 0x8 && mask != 0xc && mask != 0xe && mask != 0xf) ||
4082 827df9f3 balrog
                    (base < 0 || base >= 0x40) ||
4083 827df9f3 balrog
                    (base & 0x0f & ~mask)) {
4084 827df9f3 balrog
        fprintf(stderr, "%s: wrong cs address mapping/decoding!\n",
4085 827df9f3 balrog
                        __FUNCTION__);
4086 827df9f3 balrog
        return;
4087 827df9f3 balrog
    }
4088 827df9f3 balrog
4089 827df9f3 balrog
    if (!f->opaque)
4090 827df9f3 balrog
        return;
4091 827df9f3 balrog
4092 827df9f3 balrog
    f->base = base << 24;
4093 827df9f3 balrog
    f->size = (0x0fffffff & ~(mask << 24)) + 1;
4094 827df9f3 balrog
    /* TODO: rather than setting the size of the mapping (which should be
4095 827df9f3 balrog
     * constant), the mask should cause wrapping of the address space, so
4096 827df9f3 balrog
     * that the same memory becomes accessible at every <i>size</i> bytes
4097 827df9f3 balrog
     * starting from <i>base</i>.  */
4098 827df9f3 balrog
    if (f->iomemtype)
4099 827df9f3 balrog
        cpu_register_physical_memory(f->base, f->size, f->iomemtype);
4100 827df9f3 balrog
4101 827df9f3 balrog
    if (f->base_update)
4102 827df9f3 balrog
        f->base_update(f->opaque, f->base);
4103 827df9f3 balrog
}
4104 827df9f3 balrog
4105 827df9f3 balrog
static void omap_gpmc_cs_unmap(struct omap_gpmc_cs_file_s *f)
4106 827df9f3 balrog
{
4107 827df9f3 balrog
    if (f->size) {
4108 827df9f3 balrog
        if (f->unmap)
4109 827df9f3 balrog
            f->unmap(f->opaque);
4110 827df9f3 balrog
        if (f->iomemtype)
4111 827df9f3 balrog
            cpu_register_physical_memory(f->base, f->size, IO_MEM_UNASSIGNED);
4112 827df9f3 balrog
        f->base = 0;
4113 827df9f3 balrog
        f->size = 0;
4114 827df9f3 balrog
    }
4115 827df9f3 balrog
}
4116 827df9f3 balrog
4117 827df9f3 balrog
static void omap_gpmc_reset(struct omap_gpmc_s *s)
4118 827df9f3 balrog
{
4119 827df9f3 balrog
    int i;
4120 827df9f3 balrog
4121 827df9f3 balrog
    s->sysconfig = 0;
4122 827df9f3 balrog
    s->irqst = 0;
4123 827df9f3 balrog
    s->irqen = 0;
4124 827df9f3 balrog
    omap_gpmc_int_update(s);
4125 827df9f3 balrog
    s->timeout = 0;
4126 827df9f3 balrog
    s->config = 0xa00;
4127 827df9f3 balrog
    s->prefconfig[0] = 0x00004000;
4128 827df9f3 balrog
    s->prefconfig[1] = 0x00000000;
4129 827df9f3 balrog
    s->prefcontrol = 0;
4130 827df9f3 balrog
    s->preffifo = 0;
4131 827df9f3 balrog
    s->prefcount = 0;
4132 827df9f3 balrog
    for (i = 0; i < 8; i ++) {
4133 827df9f3 balrog
        if (s->cs_file[i].config[6] & (1 << 6))                        /* CSVALID */
4134 827df9f3 balrog
            omap_gpmc_cs_unmap(s->cs_file + i);
4135 827df9f3 balrog
        s->cs_file[i].config[0] = i ? 1 << 12 : 0;
4136 827df9f3 balrog
        s->cs_file[i].config[1] = 0x101001;
4137 827df9f3 balrog
        s->cs_file[i].config[2] = 0x020201;
4138 827df9f3 balrog
        s->cs_file[i].config[3] = 0x10031003;
4139 827df9f3 balrog
        s->cs_file[i].config[4] = 0x10f1111;
4140 827df9f3 balrog
        s->cs_file[i].config[5] = 0;
4141 827df9f3 balrog
        s->cs_file[i].config[6] = 0xf00 | (i ? 0 : 1 << 6);
4142 827df9f3 balrog
        if (s->cs_file[i].config[6] & (1 << 6))                        /* CSVALID */
4143 827df9f3 balrog
            omap_gpmc_cs_map(&s->cs_file[i],
4144 827df9f3 balrog
                            s->cs_file[i].config[6] & 0x1f,        /* MASKADDR */
4145 827df9f3 balrog
                        (s->cs_file[i].config[6] >> 8 & 0xf));        /* BASEADDR */
4146 827df9f3 balrog
    }
4147 827df9f3 balrog
    omap_gpmc_cs_map(s->cs_file, 0, 0xf);
4148 827df9f3 balrog
    s->ecc_cs = 0;
4149 827df9f3 balrog
    s->ecc_ptr = 0;
4150 827df9f3 balrog
    s->ecc_cfg = 0x3fcff000;
4151 827df9f3 balrog
    for (i = 0; i < 9; i ++)
4152 827df9f3 balrog
        ecc_reset(&s->ecc[i]);
4153 827df9f3 balrog
}
4154 827df9f3 balrog
4155 827df9f3 balrog
static uint32_t omap_gpmc_read(void *opaque, target_phys_addr_t addr)
4156 827df9f3 balrog
{
4157 827df9f3 balrog
    struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
4158 827df9f3 balrog
    int cs;
4159 827df9f3 balrog
    struct omap_gpmc_cs_file_s *f;
4160 827df9f3 balrog
4161 8da3ff18 pbrook
    switch (addr) {
4162 827df9f3 balrog
    case 0x000:        /* GPMC_REVISION */
4163 827df9f3 balrog
        return 0x20;
4164 827df9f3 balrog
4165 827df9f3 balrog
    case 0x010:        /* GPMC_SYSCONFIG */
4166 827df9f3 balrog
        return s->sysconfig;
4167 827df9f3 balrog
4168 827df9f3 balrog
    case 0x014:        /* GPMC_SYSSTATUS */
4169 827df9f3 balrog
        return 1;                                                /* RESETDONE */
4170 827df9f3 balrog
4171 827df9f3 balrog
    case 0x018:        /* GPMC_IRQSTATUS */
4172 827df9f3 balrog
        return s->irqst;
4173 827df9f3 balrog
4174 827df9f3 balrog
    case 0x01c:        /* GPMC_IRQENABLE */
4175 827df9f3 balrog
        return s->irqen;
4176 827df9f3 balrog
4177 827df9f3 balrog
    case 0x040:        /* GPMC_TIMEOUT_CONTROL */
4178 827df9f3 balrog
        return s->timeout;
4179 827df9f3 balrog
4180 827df9f3 balrog
    case 0x044:        /* GPMC_ERR_ADDRESS */
4181 827df9f3 balrog
    case 0x048:        /* GPMC_ERR_TYPE */
4182 827df9f3 balrog
        return 0;
4183 827df9f3 balrog
4184 827df9f3 balrog
    case 0x050:        /* GPMC_CONFIG */
4185 827df9f3 balrog
        return s->config;
4186 827df9f3 balrog
4187 827df9f3 balrog
    case 0x054:        /* GPMC_STATUS */
4188 827df9f3 balrog
        return 0x001;
4189 827df9f3 balrog
4190 827df9f3 balrog
    case 0x060 ... 0x1d4:
4191 8da3ff18 pbrook
        cs = (addr - 0x060) / 0x30;
4192 8da3ff18 pbrook
        addr -= cs * 0x30;
4193 827df9f3 balrog
        f = s->cs_file + cs;
4194 8da3ff18 pbrook
        switch (addr) {
4195 827df9f3 balrog
            case 0x60:        /* GPMC_CONFIG1 */
4196 827df9f3 balrog
                return f->config[0];
4197 827df9f3 balrog
            case 0x64:        /* GPMC_CONFIG2 */
4198 827df9f3 balrog
                return f->config[1];
4199 827df9f3 balrog
            case 0x68:        /* GPMC_CONFIG3 */
4200 827df9f3 balrog
                return f->config[2];
4201 827df9f3 balrog
            case 0x6c:        /* GPMC_CONFIG4 */
4202 827df9f3 balrog
                return f->config[3];
4203 827df9f3 balrog
            case 0x70:        /* GPMC_CONFIG5 */
4204 827df9f3 balrog
                return f->config[4];
4205 827df9f3 balrog
            case 0x74:        /* GPMC_CONFIG6 */
4206 827df9f3 balrog
                return f->config[5];
4207 827df9f3 balrog
            case 0x78:        /* GPMC_CONFIG7 */
4208 827df9f3 balrog
                return f->config[6];
4209 827df9f3 balrog
            case 0x84:        /* GPMC_NAND_DATA */
4210 827df9f3 balrog
                return 0;
4211 827df9f3 balrog
        }
4212 827df9f3 balrog
        break;
4213 827df9f3 balrog
4214 827df9f3 balrog
    case 0x1e0:        /* GPMC_PREFETCH_CONFIG1 */
4215 827df9f3 balrog
        return s->prefconfig[0];
4216 827df9f3 balrog
    case 0x1e4:        /* GPMC_PREFETCH_CONFIG2 */
4217 827df9f3 balrog
        return s->prefconfig[1];
4218 827df9f3 balrog
    case 0x1ec:        /* GPMC_PREFETCH_CONTROL */
4219 827df9f3 balrog
        return s->prefcontrol;
4220 827df9f3 balrog
    case 0x1f0:        /* GPMC_PREFETCH_STATUS */
4221 827df9f3 balrog
        return (s->preffifo << 24) |
4222 827df9f3 balrog
                ((s->preffifo >
4223 827df9f3 balrog
                  ((s->prefconfig[0] >> 8) & 0x7f) ? 1 : 0) << 16) |
4224 827df9f3 balrog
                s->prefcount;
4225 827df9f3 balrog
4226 827df9f3 balrog
    case 0x1f4:        /* GPMC_ECC_CONFIG */
4227 827df9f3 balrog
        return s->ecc_cs;
4228 827df9f3 balrog
    case 0x1f8:        /* GPMC_ECC_CONTROL */
4229 827df9f3 balrog
        return s->ecc_ptr;
4230 827df9f3 balrog
    case 0x1fc:        /* GPMC_ECC_SIZE_CONFIG */
4231 827df9f3 balrog
        return s->ecc_cfg;
4232 827df9f3 balrog
    case 0x200 ... 0x220:        /* GPMC_ECC_RESULT */
4233 8da3ff18 pbrook
        cs = (addr & 0x1f) >> 2;
4234 827df9f3 balrog
        /* TODO: check correctness */
4235 827df9f3 balrog
        return
4236 827df9f3 balrog
                ((s->ecc[cs].cp    &  0x07) <<  0) |
4237 827df9f3 balrog
                ((s->ecc[cs].cp    &  0x38) << 13) |
4238 827df9f3 balrog
                ((s->ecc[cs].lp[0] & 0x1ff) <<  3) |
4239 827df9f3 balrog
                ((s->ecc[cs].lp[1] & 0x1ff) << 19);
4240 827df9f3 balrog
4241 827df9f3 balrog
    case 0x230:        /* GPMC_TESTMODE_CTRL */
4242 827df9f3 balrog
        return 0;
4243 827df9f3 balrog
    case 0x234:        /* GPMC_PSA_LSB */
4244 827df9f3 balrog
    case 0x238:        /* GPMC_PSA_MSB */
4245 827df9f3 balrog
        return 0x00000000;
4246 827df9f3 balrog
    }
4247 827df9f3 balrog
4248 827df9f3 balrog
    OMAP_BAD_REG(addr);
4249 827df9f3 balrog
    return 0;
4250 827df9f3 balrog
}
4251 827df9f3 balrog
4252 827df9f3 balrog
static void omap_gpmc_write(void *opaque, target_phys_addr_t addr,
4253 827df9f3 balrog
                uint32_t value)
4254 827df9f3 balrog
{
4255 827df9f3 balrog
    struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
4256 827df9f3 balrog
    int cs;
4257 827df9f3 balrog
    struct omap_gpmc_cs_file_s *f;
4258 827df9f3 balrog
4259 8da3ff18 pbrook
    switch (addr) {
4260 827df9f3 balrog
    case 0x000:        /* GPMC_REVISION */
4261 827df9f3 balrog
    case 0x014:        /* GPMC_SYSSTATUS */
4262 827df9f3 balrog
    case 0x054:        /* GPMC_STATUS */
4263 827df9f3 balrog
    case 0x1f0:        /* GPMC_PREFETCH_STATUS */
4264 827df9f3 balrog
    case 0x200 ... 0x220:        /* GPMC_ECC_RESULT */
4265 827df9f3 balrog
    case 0x234:        /* GPMC_PSA_LSB */
4266 827df9f3 balrog
    case 0x238:        /* GPMC_PSA_MSB */
4267 827df9f3 balrog
        OMAP_RO_REG(addr);
4268 827df9f3 balrog
        break;
4269 827df9f3 balrog
4270 827df9f3 balrog
    case 0x010:        /* GPMC_SYSCONFIG */
4271 827df9f3 balrog
        if ((value >> 3) == 0x3)
4272 827df9f3 balrog
            fprintf(stderr, "%s: bad SDRAM idle mode %i\n",
4273 827df9f3 balrog
                            __FUNCTION__, value >> 3);
4274 827df9f3 balrog
        if (value & 2)
4275 827df9f3 balrog
            omap_gpmc_reset(s);
4276 827df9f3 balrog
        s->sysconfig = value & 0x19;
4277 827df9f3 balrog
        break;
4278 827df9f3 balrog
4279 827df9f3 balrog
    case 0x018:        /* GPMC_IRQSTATUS */
4280 827df9f3 balrog
        s->irqen = ~value;
4281 827df9f3 balrog
        omap_gpmc_int_update(s);
4282 827df9f3 balrog
        break;
4283 827df9f3 balrog
4284 827df9f3 balrog
    case 0x01c:        /* GPMC_IRQENABLE */
4285 827df9f3 balrog
        s->irqen = value & 0xf03;
4286 827df9f3 balrog
        omap_gpmc_int_update(s);
4287 827df9f3 balrog
        break;
4288 827df9f3 balrog
4289 827df9f3 balrog
    case 0x040:        /* GPMC_TIMEOUT_CONTROL */
4290 827df9f3 balrog
        s->timeout = value & 0x1ff1;
4291 827df9f3 balrog
        break;
4292 827df9f3 balrog
4293 827df9f3 balrog
    case 0x044:        /* GPMC_ERR_ADDRESS */
4294 827df9f3 balrog
    case 0x048:        /* GPMC_ERR_TYPE */
4295 827df9f3 balrog
        break;
4296 827df9f3 balrog
4297 827df9f3 balrog
    case 0x050:        /* GPMC_CONFIG */
4298 827df9f3 balrog
        s->config = value & 0xf13;
4299 827df9f3 balrog
        break;
4300 827df9f3 balrog
4301 827df9f3 balrog
    case 0x060 ... 0x1d4:
4302 8da3ff18 pbrook
        cs = (addr - 0x060) / 0x30;
4303 8da3ff18 pbrook
        addr -= cs * 0x30;
4304 827df9f3 balrog
        f = s->cs_file + cs;
4305 8da3ff18 pbrook
        switch (addr) {
4306 827df9f3 balrog
            case 0x60:        /* GPMC_CONFIG1 */
4307 827df9f3 balrog
                f->config[0] = value & 0xffef3e13;
4308 827df9f3 balrog
                break;
4309 827df9f3 balrog
            case 0x64:        /* GPMC_CONFIG2 */
4310 827df9f3 balrog
                f->config[1] = value & 0x001f1f8f;
4311 827df9f3 balrog
                break;
4312 827df9f3 balrog
            case 0x68:        /* GPMC_CONFIG3 */
4313 827df9f3 balrog
                f->config[2] = value & 0x001f1f8f;
4314 827df9f3 balrog
                break;
4315 827df9f3 balrog
            case 0x6c:        /* GPMC_CONFIG4 */
4316 827df9f3 balrog
                f->config[3] = value & 0x1f8f1f8f;
4317 827df9f3 balrog
                break;
4318 827df9f3 balrog
            case 0x70:        /* GPMC_CONFIG5 */
4319 827df9f3 balrog
                f->config[4] = value & 0x0f1f1f1f;
4320 827df9f3 balrog
                break;
4321 827df9f3 balrog
            case 0x74:        /* GPMC_CONFIG6 */
4322 827df9f3 balrog
                f->config[5] = value & 0x00000fcf;
4323 827df9f3 balrog
                break;
4324 827df9f3 balrog
            case 0x78:        /* GPMC_CONFIG7 */
4325 827df9f3 balrog
                if ((f->config[6] ^ value) & 0xf7f) {
4326 827df9f3 balrog
                    if (f->config[6] & (1 << 6))                /* CSVALID */
4327 827df9f3 balrog
                        omap_gpmc_cs_unmap(f);
4328 827df9f3 balrog
                    if (value & (1 << 6))                        /* CSVALID */
4329 827df9f3 balrog
                        omap_gpmc_cs_map(f, value & 0x1f,        /* MASKADDR */
4330 827df9f3 balrog
                                        (value >> 8 & 0xf));        /* BASEADDR */
4331 827df9f3 balrog
                }
4332 827df9f3 balrog
                f->config[6] = value & 0x00000f7f;
4333 827df9f3 balrog
                break;
4334 827df9f3 balrog
            case 0x7c:        /* GPMC_NAND_COMMAND */
4335 827df9f3 balrog
            case 0x80:        /* GPMC_NAND_ADDRESS */
4336 827df9f3 balrog
            case 0x84:        /* GPMC_NAND_DATA */
4337 827df9f3 balrog
                break;
4338 827df9f3 balrog
4339 827df9f3 balrog
            default:
4340 827df9f3 balrog
                goto bad_reg;
4341 827df9f3 balrog
        }
4342 827df9f3 balrog
        break;
4343 827df9f3 balrog
4344 827df9f3 balrog
    case 0x1e0:        /* GPMC_PREFETCH_CONFIG1 */
4345 827df9f3 balrog
        s->prefconfig[0] = value & 0x7f8f7fbf;
4346 827df9f3 balrog
        /* TODO: update interrupts, fifos, dmas */
4347 827df9f3 balrog
        break;
4348 827df9f3 balrog
4349 827df9f3 balrog
    case 0x1e4:        /* GPMC_PREFETCH_CONFIG2 */
4350 827df9f3 balrog
        s->prefconfig[1] = value & 0x3fff;
4351 827df9f3 balrog
        break;
4352 827df9f3 balrog
4353 827df9f3 balrog
    case 0x1ec:        /* GPMC_PREFETCH_CONTROL */
4354 827df9f3 balrog
        s->prefcontrol = value & 1;
4355 827df9f3 balrog
        if (s->prefcontrol) {
4356 827df9f3 balrog
            if (s->prefconfig[0] & 1)
4357 827df9f3 balrog
                s->preffifo = 0x40;
4358 827df9f3 balrog
            else
4359 827df9f3 balrog
                s->preffifo = 0x00;
4360 827df9f3 balrog
        }
4361 827df9f3 balrog
        /* TODO: start */
4362 827df9f3 balrog
        break;
4363 827df9f3 balrog
4364 827df9f3 balrog
    case 0x1f4:        /* GPMC_ECC_CONFIG */
4365 827df9f3 balrog
        s->ecc_cs = 0x8f;
4366 827df9f3 balrog
        break;
4367 827df9f3 balrog
    case 0x1f8:        /* GPMC_ECC_CONTROL */
4368 827df9f3 balrog
        if (value & (1 << 8))
4369 827df9f3 balrog
            for (cs = 0; cs < 9; cs ++)
4370 827df9f3 balrog
                ecc_reset(&s->ecc[cs]);
4371 827df9f3 balrog
        s->ecc_ptr = value & 0xf;
4372 827df9f3 balrog
        if (s->ecc_ptr == 0 || s->ecc_ptr > 9) {
4373 827df9f3 balrog
            s->ecc_ptr = 0;
4374 827df9f3 balrog
            s->ecc_cs &= ~1;
4375 827df9f3 balrog
        }
4376 827df9f3 balrog
        break;
4377 827df9f3 balrog
    case 0x1fc:        /* GPMC_ECC_SIZE_CONFIG */
4378 827df9f3 balrog
        s->ecc_cfg = value & 0x3fcff1ff;
4379 827df9f3 balrog
        break;
4380 827df9f3 balrog
    case 0x230:        /* GPMC_TESTMODE_CTRL */
4381 827df9f3 balrog
        if (value & 7)
4382 827df9f3 balrog
            fprintf(stderr, "%s: test mode enable attempt\n", __FUNCTION__);
4383 827df9f3 balrog
        break;
4384 827df9f3 balrog
4385 827df9f3 balrog
    default:
4386 827df9f3 balrog
    bad_reg:
4387 827df9f3 balrog
        OMAP_BAD_REG(addr);
4388 827df9f3 balrog
        return;
4389 827df9f3 balrog
    }
4390 827df9f3 balrog
}
4391 827df9f3 balrog
4392 827df9f3 balrog
static CPUReadMemoryFunc *omap_gpmc_readfn[] = {
4393 827df9f3 balrog
    omap_badwidth_read32,        /* TODO */
4394 827df9f3 balrog
    omap_badwidth_read32,        /* TODO */
4395 827df9f3 balrog
    omap_gpmc_read,
4396 827df9f3 balrog
};
4397 827df9f3 balrog
4398 827df9f3 balrog
static CPUWriteMemoryFunc *omap_gpmc_writefn[] = {
4399 827df9f3 balrog
    omap_badwidth_write32,        /* TODO */
4400 827df9f3 balrog
    omap_badwidth_write32,        /* TODO */
4401 827df9f3 balrog
    omap_gpmc_write,
4402 827df9f3 balrog
};
4403 827df9f3 balrog
4404 827df9f3 balrog
struct omap_gpmc_s *omap_gpmc_init(target_phys_addr_t base, qemu_irq irq)
4405 827df9f3 balrog
{
4406 827df9f3 balrog
    int iomemtype;
4407 827df9f3 balrog
    struct omap_gpmc_s *s = (struct omap_gpmc_s *)
4408 827df9f3 balrog
            qemu_mallocz(sizeof(struct omap_gpmc_s));
4409 827df9f3 balrog
4410 827df9f3 balrog
    omap_gpmc_reset(s);
4411 827df9f3 balrog
4412 827df9f3 balrog
    iomemtype = cpu_register_io_memory(0, omap_gpmc_readfn,
4413 827df9f3 balrog
                    omap_gpmc_writefn, s);
4414 8da3ff18 pbrook
    cpu_register_physical_memory(base, 0x1000, iomemtype);
4415 827df9f3 balrog
4416 827df9f3 balrog
    return s;
4417 827df9f3 balrog
}
4418 827df9f3 balrog
4419 827df9f3 balrog
void omap_gpmc_attach(struct omap_gpmc_s *s, int cs, int iomemtype,
4420 827df9f3 balrog
                void (*base_upd)(void *opaque, target_phys_addr_t new),
4421 827df9f3 balrog
                void (*unmap)(void *opaque), void *opaque)
4422 827df9f3 balrog
{
4423 827df9f3 balrog
    struct omap_gpmc_cs_file_s *f;
4424 827df9f3 balrog
4425 827df9f3 balrog
    if (cs < 0 || cs >= 8) {
4426 827df9f3 balrog
        fprintf(stderr, "%s: bad chip-select %i\n", __FUNCTION__, cs);
4427 827df9f3 balrog
        exit(-1);
4428 827df9f3 balrog
    }
4429 827df9f3 balrog
    f = &s->cs_file[cs];
4430 827df9f3 balrog
4431 827df9f3 balrog
    f->iomemtype = iomemtype;
4432 827df9f3 balrog
    f->base_update = base_upd;
4433 827df9f3 balrog
    f->unmap = unmap;
4434 827df9f3 balrog
    f->opaque = opaque;
4435 827df9f3 balrog
4436 827df9f3 balrog
    if (f->config[6] & (1 << 6))                                /* CSVALID */
4437 827df9f3 balrog
        omap_gpmc_cs_map(f, f->config[6] & 0x1f,                /* MASKADDR */
4438 827df9f3 balrog
                        (f->config[6] >> 8 & 0xf));                /* BASEADDR */
4439 827df9f3 balrog
}
4440 827df9f3 balrog
4441 827df9f3 balrog
/* General chip reset */
4442 827df9f3 balrog
static void omap2_mpu_reset(void *opaque)
4443 827df9f3 balrog
{
4444 827df9f3 balrog
    struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
4445 827df9f3 balrog
4446 827df9f3 balrog
    omap_inth_reset(mpu->ih[0]);
4447 827df9f3 balrog
    omap_dma_reset(mpu->dma);
4448 827df9f3 balrog
    omap_prcm_reset(mpu->prcm);
4449 827df9f3 balrog
    omap_sysctl_reset(mpu->sysc);
4450 827df9f3 balrog
    omap_gp_timer_reset(mpu->gptimer[0]);
4451 827df9f3 balrog
    omap_gp_timer_reset(mpu->gptimer[1]);
4452 827df9f3 balrog
    omap_gp_timer_reset(mpu->gptimer[2]);
4453 827df9f3 balrog
    omap_gp_timer_reset(mpu->gptimer[3]);
4454 827df9f3 balrog
    omap_gp_timer_reset(mpu->gptimer[4]);
4455 827df9f3 balrog
    omap_gp_timer_reset(mpu->gptimer[5]);
4456 827df9f3 balrog
    omap_gp_timer_reset(mpu->gptimer[6]);
4457 827df9f3 balrog
    omap_gp_timer_reset(mpu->gptimer[7]);
4458 827df9f3 balrog
    omap_gp_timer_reset(mpu->gptimer[8]);
4459 827df9f3 balrog
    omap_gp_timer_reset(mpu->gptimer[9]);
4460 827df9f3 balrog
    omap_gp_timer_reset(mpu->gptimer[10]);
4461 827df9f3 balrog
    omap_gp_timer_reset(mpu->gptimer[11]);
4462 827df9f3 balrog
    omap_synctimer_reset(&mpu->synctimer);
4463 827df9f3 balrog
    omap_sdrc_reset(mpu->sdrc);
4464 827df9f3 balrog
    omap_gpmc_reset(mpu->gpmc);
4465 827df9f3 balrog
    omap_dss_reset(mpu->dss);
4466 827df9f3 balrog
    omap_uart_reset(mpu->uart[0]);
4467 827df9f3 balrog
    omap_uart_reset(mpu->uart[1]);
4468 827df9f3 balrog
    omap_uart_reset(mpu->uart[2]);
4469 827df9f3 balrog
    omap_mmc_reset(mpu->mmc);
4470 827df9f3 balrog
    omap_gpif_reset(mpu->gpif);
4471 827df9f3 balrog
    omap_mcspi_reset(mpu->mcspi[0]);
4472 827df9f3 balrog
    omap_mcspi_reset(mpu->mcspi[1]);
4473 827df9f3 balrog
    omap_i2c_reset(mpu->i2c[0]);
4474 827df9f3 balrog
    omap_i2c_reset(mpu->i2c[1]);
4475 827df9f3 balrog
    cpu_reset(mpu->env);
4476 827df9f3 balrog
}
4477 827df9f3 balrog
4478 827df9f3 balrog
static int omap2_validate_addr(struct omap_mpu_state_s *s,
4479 827df9f3 balrog
                target_phys_addr_t addr)
4480 827df9f3 balrog
{
4481 827df9f3 balrog
    return 1;
4482 827df9f3 balrog
}
4483 827df9f3 balrog
4484 827df9f3 balrog
static const struct dma_irq_map omap2_dma_irq_map[] = {
4485 827df9f3 balrog
    { 0, OMAP_INT_24XX_SDMA_IRQ0 },
4486 827df9f3 balrog
    { 0, OMAP_INT_24XX_SDMA_IRQ1 },
4487 827df9f3 balrog
    { 0, OMAP_INT_24XX_SDMA_IRQ2 },
4488 827df9f3 balrog
    { 0, OMAP_INT_24XX_SDMA_IRQ3 },
4489 827df9f3 balrog
};
4490 827df9f3 balrog
4491 827df9f3 balrog
struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
4492 3023f332 aliguori
                const char *core)
4493 827df9f3 balrog
{
4494 827df9f3 balrog
    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
4495 827df9f3 balrog
            qemu_mallocz(sizeof(struct omap_mpu_state_s));
4496 7e7c5e4c balrog
    ram_addr_t sram_base, q2_base;
4497 827df9f3 balrog
    qemu_irq *cpu_irq;
4498 827df9f3 balrog
    qemu_irq dma_irqs[4];
4499 827df9f3 balrog
    omap_clk gpio_clks[4];
4500 827df9f3 balrog
    int sdindex;
4501 827df9f3 balrog
    int i;
4502 827df9f3 balrog
4503 827df9f3 balrog
    /* Core */
4504 827df9f3 balrog
    s->mpu_model = omap2420;
4505 827df9f3 balrog
    s->env = cpu_init(core ?: "arm1136-r2");
4506 827df9f3 balrog
    if (!s->env) {
4507 827df9f3 balrog
        fprintf(stderr, "Unable to find CPU definition\n");
4508 827df9f3 balrog
        exit(1);
4509 827df9f3 balrog
    }
4510 827df9f3 balrog
    s->sdram_size = sdram_size;
4511 827df9f3 balrog
    s->sram_size = OMAP242X_SRAM_SIZE;
4512 827df9f3 balrog
4513 827df9f3 balrog
    s->wakeup = qemu_allocate_irqs(omap_mpu_wakeup, s, 1)[0];
4514 827df9f3 balrog
4515 827df9f3 balrog
    /* Clocks */
4516 827df9f3 balrog
    omap_clk_init(s);
4517 827df9f3 balrog
4518 827df9f3 balrog
    /* Memory-mapped stuff */
4519 827df9f3 balrog
    cpu_register_physical_memory(OMAP2_Q2_BASE, s->sdram_size,
4520 7e7c5e4c balrog
                    (q2_base = qemu_ram_alloc(s->sdram_size)) | IO_MEM_RAM);
4521 827df9f3 balrog
    cpu_register_physical_memory(OMAP2_SRAM_BASE, s->sram_size,
4522 827df9f3 balrog
                    (sram_base = qemu_ram_alloc(s->sram_size)) | IO_MEM_RAM);
4523 827df9f3 balrog
4524 827df9f3 balrog
    s->l4 = omap_l4_init(OMAP2_L4_BASE, 54);
4525 827df9f3 balrog
4526 827df9f3 balrog
    /* Actually mapped at any 2K boundary in the ARM11 private-peripheral if */
4527 827df9f3 balrog
    cpu_irq = arm_pic_init_cpu(s->env);
4528 827df9f3 balrog
    s->ih[0] = omap2_inth_init(0x480fe000, 0x1000, 3, &s->irq[0],
4529 827df9f3 balrog
                    cpu_irq[ARM_PIC_CPU_IRQ], cpu_irq[ARM_PIC_CPU_FIQ],
4530 827df9f3 balrog
                    omap_findclk(s, "mpu_intc_fclk"),
4531 827df9f3 balrog
                    omap_findclk(s, "mpu_intc_iclk"));
4532 827df9f3 balrog
4533 827df9f3 balrog
    s->prcm = omap_prcm_init(omap_l4tao(s->l4, 3),
4534 827df9f3 balrog
                    s->irq[0][OMAP_INT_24XX_PRCM_MPU_IRQ], NULL, NULL, s);
4535 827df9f3 balrog
4536 827df9f3 balrog
    s->sysc = omap_sysctl_init(omap_l4tao(s->l4, 1),
4537 827df9f3 balrog
                    omap_findclk(s, "omapctrl_iclk"), s);
4538 827df9f3 balrog
4539 827df9f3 balrog
    for (i = 0; i < 4; i ++)
4540 827df9f3 balrog
        dma_irqs[i] =
4541 827df9f3 balrog
                s->irq[omap2_dma_irq_map[i].ih][omap2_dma_irq_map[i].intr];
4542 827df9f3 balrog
    s->dma = omap_dma4_init(0x48056000, dma_irqs, s, 256, 32,
4543 827df9f3 balrog
                    omap_findclk(s, "sdma_iclk"),
4544 827df9f3 balrog
                    omap_findclk(s, "sdma_fclk"));
4545 827df9f3 balrog
    s->port->addr_valid = omap2_validate_addr;
4546 827df9f3 balrog
4547 afbb5194 balrog
    /* Register SDRAM and SRAM ports for fast DMA transfers.  */
4548 afbb5194 balrog
    soc_dma_port_add_mem_ram(s->dma, q2_base, OMAP2_Q2_BASE, s->sdram_size);
4549 afbb5194 balrog
    soc_dma_port_add_mem_ram(s->dma, sram_base, OMAP2_SRAM_BASE, s->sram_size);
4550 afbb5194 balrog
4551 827df9f3 balrog
    s->uart[0] = omap2_uart_init(omap_l4ta(s->l4, 19),
4552 827df9f3 balrog
                    s->irq[0][OMAP_INT_24XX_UART1_IRQ],
4553 827df9f3 balrog
                    omap_findclk(s, "uart1_fclk"),
4554 827df9f3 balrog
                    omap_findclk(s, "uart1_iclk"),
4555 827df9f3 balrog
                    s->drq[OMAP24XX_DMA_UART1_TX],
4556 827df9f3 balrog
                    s->drq[OMAP24XX_DMA_UART1_RX], serial_hds[0]);
4557 827df9f3 balrog
    s->uart[1] = omap2_uart_init(omap_l4ta(s->l4, 20),
4558 827df9f3 balrog
                    s->irq[0][OMAP_INT_24XX_UART2_IRQ],
4559 827df9f3 balrog
                    omap_findclk(s, "uart2_fclk"),
4560 827df9f3 balrog
                    omap_findclk(s, "uart2_iclk"),
4561 827df9f3 balrog
                    s->drq[OMAP24XX_DMA_UART2_TX],
4562 827df9f3 balrog
                    s->drq[OMAP24XX_DMA_UART2_RX],
4563 827df9f3 balrog
                    serial_hds[0] ? serial_hds[1] : 0);
4564 827df9f3 balrog
    s->uart[2] = omap2_uart_init(omap_l4ta(s->l4, 21),
4565 827df9f3 balrog
                    s->irq[0][OMAP_INT_24XX_UART3_IRQ],
4566 827df9f3 balrog
                    omap_findclk(s, "uart3_fclk"),
4567 827df9f3 balrog
                    omap_findclk(s, "uart3_iclk"),
4568 827df9f3 balrog
                    s->drq[OMAP24XX_DMA_UART3_TX],
4569 827df9f3 balrog
                    s->drq[OMAP24XX_DMA_UART3_RX],
4570 827df9f3 balrog
                    serial_hds[0] && serial_hds[1] ? serial_hds[2] : 0);
4571 827df9f3 balrog
4572 827df9f3 balrog
    s->gptimer[0] = omap_gp_timer_init(omap_l4ta(s->l4, 7),
4573 827df9f3 balrog
                    s->irq[0][OMAP_INT_24XX_GPTIMER1],
4574 827df9f3 balrog
                    omap_findclk(s, "wu_gpt1_clk"),
4575 827df9f3 balrog
                    omap_findclk(s, "wu_l4_iclk"));
4576 827df9f3 balrog
    s->gptimer[1] = omap_gp_timer_init(omap_l4ta(s->l4, 8),
4577 827df9f3 balrog
                    s->irq[0][OMAP_INT_24XX_GPTIMER2],
4578 827df9f3 balrog
                    omap_findclk(s, "core_gpt2_clk"),
4579 827df9f3 balrog
                    omap_findclk(s, "core_l4_iclk"));
4580 827df9f3 balrog
    s->gptimer[2] = omap_gp_timer_init(omap_l4ta(s->l4, 22),
4581 827df9f3 balrog
                    s->irq[0][OMAP_INT_24XX_GPTIMER3],
4582 827df9f3 balrog
                    omap_findclk(s, "core_gpt3_clk"),
4583 827df9f3 balrog
                    omap_findclk(s, "core_l4_iclk"));
4584 827df9f3 balrog
    s->gptimer[3] = omap_gp_timer_init(omap_l4ta(s->l4, 23),
4585 827df9f3 balrog
                    s->irq[0][OMAP_INT_24XX_GPTIMER4],
4586 827df9f3 balrog
                    omap_findclk(s, "core_gpt4_clk"),
4587 827df9f3 balrog
                    omap_findclk(s, "core_l4_iclk"));
4588 827df9f3 balrog
    s->gptimer[4] = omap_gp_timer_init(omap_l4ta(s->l4, 24),
4589 827df9f3 balrog
                    s->irq[0][OMAP_INT_24XX_GPTIMER5],
4590 827df9f3 balrog
                    omap_findclk(s, "core_gpt5_clk"),
4591 827df9f3 balrog
                    omap_findclk(s, "core_l4_iclk"));
4592 827df9f3 balrog
    s->gptimer[5] = omap_gp_timer_init(omap_l4ta(s->l4, 25),
4593 827df9f3 balrog
                    s->irq[0][OMAP_INT_24XX_GPTIMER6],
4594 827df9f3 balrog
                    omap_findclk(s, "core_gpt6_clk"),
4595 827df9f3 balrog
                    omap_findclk(s, "core_l4_iclk"));
4596 827df9f3 balrog
    s->gptimer[6] = omap_gp_timer_init(omap_l4ta(s->l4, 26),
4597 827df9f3 balrog
                    s->irq[0][OMAP_INT_24XX_GPTIMER7],
4598 827df9f3 balrog
                    omap_findclk(s, "core_gpt7_clk"),
4599 827df9f3 balrog
                    omap_findclk(s, "core_l4_iclk"));
4600 827df9f3 balrog
    s->gptimer[7] = omap_gp_timer_init(omap_l4ta(s->l4, 27),
4601 827df9f3 balrog
                    s->irq[0][OMAP_INT_24XX_GPTIMER8],
4602 827df9f3 balrog
                    omap_findclk(s, "core_gpt8_clk"),
4603 827df9f3 balrog
                    omap_findclk(s, "core_l4_iclk"));
4604 827df9f3 balrog
    s->gptimer[8] = omap_gp_timer_init(omap_l4ta(s->l4, 28),
4605 827df9f3 balrog
                    s->irq[0][OMAP_INT_24XX_GPTIMER9],
4606 827df9f3 balrog
                    omap_findclk(s, "core_gpt9_clk"),
4607 827df9f3 balrog
                    omap_findclk(s, "core_l4_iclk"));
4608 827df9f3 balrog
    s->gptimer[9] = omap_gp_timer_init(omap_l4ta(s->l4, 29),
4609 827df9f3 balrog
                    s->irq[0][OMAP_INT_24XX_GPTIMER10],
4610 827df9f3 balrog
                    omap_findclk(s, "core_gpt10_clk"),
4611 827df9f3 balrog
                    omap_findclk(s, "core_l4_iclk"));
4612 827df9f3 balrog
    s->gptimer[10] = omap_gp_timer_init(omap_l4ta(s->l4, 30),
4613 827df9f3 balrog
                    s->irq[0][OMAP_INT_24XX_GPTIMER11],
4614 827df9f3 balrog
                    omap_findclk(s, "core_gpt11_clk"),
4615 827df9f3 balrog
                    omap_findclk(s, "core_l4_iclk"));
4616 827df9f3 balrog
    s->gptimer[11] = omap_gp_timer_init(omap_l4ta(s->l4, 31),
4617 827df9f3 balrog
                    s->irq[0][OMAP_INT_24XX_GPTIMER12],
4618 827df9f3 balrog
                    omap_findclk(s, "core_gpt12_clk"),
4619 827df9f3 balrog
                    omap_findclk(s, "core_l4_iclk"));
4620 827df9f3 balrog
4621 827df9f3 balrog
    omap_tap_init(omap_l4ta(s->l4, 2), s);
4622 827df9f3 balrog
4623 827df9f3 balrog
    omap_synctimer_init(omap_l4tao(s->l4, 2), s,
4624 827df9f3 balrog
                    omap_findclk(s, "clk32-kHz"),
4625 827df9f3 balrog
                    omap_findclk(s, "core_l4_iclk"));
4626 827df9f3 balrog
4627 827df9f3 balrog
    s->i2c[0] = omap2_i2c_init(omap_l4tao(s->l4, 5),
4628 827df9f3 balrog
                    s->irq[0][OMAP_INT_24XX_I2C1_IRQ],
4629 827df9f3 balrog
                    &s->drq[OMAP24XX_DMA_I2C1_TX],
4630 827df9f3 balrog
                    omap_findclk(s, "i2c1.fclk"),
4631 827df9f3 balrog
                    omap_findclk(s, "i2c1.iclk"));
4632 827df9f3 balrog
    s->i2c[1] = omap2_i2c_init(omap_l4tao(s->l4, 6),
4633 827df9f3 balrog
                    s->irq[0][OMAP_INT_24XX_I2C2_IRQ],
4634 827df9f3 balrog
                    &s->drq[OMAP24XX_DMA_I2C2_TX],
4635 827df9f3 balrog
                    omap_findclk(s, "i2c2.fclk"),
4636 827df9f3 balrog
                    omap_findclk(s, "i2c2.iclk"));
4637 827df9f3 balrog
4638 827df9f3 balrog
    gpio_clks[0] = omap_findclk(s, "gpio1_dbclk");
4639 827df9f3 balrog
    gpio_clks[1] = omap_findclk(s, "gpio2_dbclk");
4640 827df9f3 balrog
    gpio_clks[2] = omap_findclk(s, "gpio3_dbclk");
4641 827df9f3 balrog
    gpio_clks[3] = omap_findclk(s, "gpio4_dbclk");
4642 827df9f3 balrog
    s->gpif = omap2_gpio_init(omap_l4ta(s->l4, 3),
4643 827df9f3 balrog
                    &s->irq[0][OMAP_INT_24XX_GPIO_BANK1],
4644 827df9f3 balrog
                    gpio_clks, omap_findclk(s, "gpio_iclk"), 4);
4645 827df9f3 balrog
4646 827df9f3 balrog
    s->sdrc = omap_sdrc_init(0x68009000);
4647 827df9f3 balrog
    s->gpmc = omap_gpmc_init(0x6800a000, s->irq[0][OMAP_INT_24XX_GPMC_IRQ]);
4648 827df9f3 balrog
4649 827df9f3 balrog
    sdindex = drive_get_index(IF_SD, 0, 0);
4650 827df9f3 balrog
    if (sdindex == -1) {
4651 827df9f3 balrog
        fprintf(stderr, "qemu: missing SecureDigital device\n");
4652 827df9f3 balrog
        exit(1);
4653 827df9f3 balrog
    }
4654 827df9f3 balrog
    s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9), drives_table[sdindex].bdrv,
4655 827df9f3 balrog
                    s->irq[0][OMAP_INT_24XX_MMC_IRQ],
4656 827df9f3 balrog
                    &s->drq[OMAP24XX_DMA_MMC1_TX],
4657 827df9f3 balrog
                    omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk"));
4658 827df9f3 balrog
4659 827df9f3 balrog
    s->mcspi[0] = omap_mcspi_init(omap_l4ta(s->l4, 35), 4,
4660 99570a40 balrog
                    s->irq[0][OMAP_INT_24XX_MCSPI1_IRQ],
4661 827df9f3 balrog
                    &s->drq[OMAP24XX_DMA_SPI1_TX0],
4662 827df9f3 balrog
                    omap_findclk(s, "spi1_fclk"),
4663 827df9f3 balrog
                    omap_findclk(s, "spi1_iclk"));
4664 827df9f3 balrog
    s->mcspi[1] = omap_mcspi_init(omap_l4ta(s->l4, 36), 2,
4665 99570a40 balrog
                    s->irq[0][OMAP_INT_24XX_MCSPI2_IRQ],
4666 827df9f3 balrog
                    &s->drq[OMAP24XX_DMA_SPI2_TX0],
4667 827df9f3 balrog
                    omap_findclk(s, "spi2_fclk"),
4668 827df9f3 balrog
                    omap_findclk(s, "spi2_iclk"));
4669 827df9f3 balrog
4670 3023f332 aliguori
    s->dss = omap_dss_init(omap_l4ta(s->l4, 10), 0x68000800,
4671 827df9f3 balrog
                    /* XXX wire M_IRQ_25, D_L2_IRQ_30 and I_IRQ_13 together */
4672 827df9f3 balrog
                    s->irq[0][OMAP_INT_24XX_DSS_IRQ], s->drq[OMAP24XX_DMA_DSS],
4673 827df9f3 balrog
                    omap_findclk(s, "dss_clk1"), omap_findclk(s, "dss_clk2"),
4674 827df9f3 balrog
                    omap_findclk(s, "dss_54m_clk"),
4675 827df9f3 balrog
                    omap_findclk(s, "dss_l3_iclk"),
4676 827df9f3 balrog
                    omap_findclk(s, "dss_l4_iclk"));
4677 827df9f3 balrog
4678 54585ffe balrog
    omap_sti_init(omap_l4ta(s->l4, 18), 0x54000000,
4679 54585ffe balrog
                    s->irq[0][OMAP_INT_24XX_STI], omap_findclk(s, "emul_ck"),
4680 54585ffe balrog
                    serial_hds[0] && serial_hds[1] && serial_hds[2] ?
4681 54585ffe balrog
                    serial_hds[3] : 0);
4682 54585ffe balrog
4683 99570a40 balrog
    s->eac = omap_eac_init(omap_l4ta(s->l4, 32),
4684 99570a40 balrog
                    s->irq[0][OMAP_INT_24XX_EAC_IRQ],
4685 99570a40 balrog
                    /* Ten consecutive lines */
4686 99570a40 balrog
                    &s->drq[OMAP24XX_DMA_EAC_AC_RD],
4687 99570a40 balrog
                    omap_findclk(s, "func_96m_clk"),
4688 99570a40 balrog
                    omap_findclk(s, "core_l4_iclk"));
4689 99570a40 balrog
4690 827df9f3 balrog
    /* All register mappings (includin those not currenlty implemented):
4691 827df9f3 balrog
     * SystemControlMod        48000000 - 48000fff
4692 827df9f3 balrog
     * SystemControlL4        48001000 - 48001fff
4693 827df9f3 balrog
     * 32kHz Timer Mod        48004000 - 48004fff
4694 827df9f3 balrog
     * 32kHz Timer L4        48005000 - 48005fff
4695 827df9f3 balrog
     * PRCM ModA        48008000 - 480087ff
4696 827df9f3 balrog
     * PRCM ModB        48008800 - 48008fff
4697 827df9f3 balrog
     * PRCM L4                48009000 - 48009fff
4698 827df9f3 balrog
     * TEST-BCM Mod        48012000 - 48012fff
4699 827df9f3 balrog
     * TEST-BCM L4        48013000 - 48013fff
4700 827df9f3 balrog
     * TEST-TAP Mod        48014000 - 48014fff
4701 827df9f3 balrog
     * TEST-TAP L4        48015000 - 48015fff
4702 827df9f3 balrog
     * GPIO1 Mod        48018000 - 48018fff
4703 827df9f3 balrog
     * GPIO Top                48019000 - 48019fff
4704 827df9f3 balrog
     * GPIO2 Mod        4801a000 - 4801afff
4705 827df9f3 balrog
     * GPIO L4                4801b000 - 4801bfff
4706 827df9f3 balrog
     * GPIO3 Mod        4801c000 - 4801cfff
4707 827df9f3 balrog
     * GPIO4 Mod        4801e000 - 4801efff
4708 827df9f3 balrog
     * WDTIMER1 Mod        48020000 - 48010fff
4709 827df9f3 balrog
     * WDTIMER Top        48021000 - 48011fff
4710 827df9f3 balrog
     * WDTIMER2 Mod        48022000 - 48012fff
4711 827df9f3 balrog
     * WDTIMER L4        48023000 - 48013fff
4712 827df9f3 balrog
     * WDTIMER3 Mod        48024000 - 48014fff
4713 827df9f3 balrog
     * WDTIMER3 L4        48025000 - 48015fff
4714 827df9f3 balrog
     * WDTIMER4 Mod        48026000 - 48016fff
4715 827df9f3 balrog
     * WDTIMER4 L4        48027000 - 48017fff
4716 827df9f3 balrog
     * GPTIMER1 Mod        48028000 - 48018fff
4717 827df9f3 balrog
     * GPTIMER1 L4        48029000 - 48019fff
4718 827df9f3 balrog
     * GPTIMER2 Mod        4802a000 - 4801afff
4719 827df9f3 balrog
     * GPTIMER2 L4        4802b000 - 4801bfff
4720 827df9f3 balrog
     * L4-Config AP        48040000 - 480407ff
4721 827df9f3 balrog
     * L4-Config IP        48040800 - 48040fff
4722 827df9f3 balrog
     * L4-Config LA        48041000 - 48041fff
4723 827df9f3 balrog
     * ARM11ETB Mod        48048000 - 48049fff
4724 827df9f3 balrog
     * ARM11ETB L4        4804a000 - 4804afff
4725 827df9f3 balrog
     * DISPLAY Top        48050000 - 480503ff
4726 827df9f3 balrog
     * DISPLAY DISPC        48050400 - 480507ff
4727 827df9f3 balrog
     * DISPLAY RFBI        48050800 - 48050bff
4728 827df9f3 balrog
     * DISPLAY VENC        48050c00 - 48050fff
4729 827df9f3 balrog
     * DISPLAY L4        48051000 - 48051fff
4730 827df9f3 balrog
     * CAMERA Top        48052000 - 480523ff
4731 827df9f3 balrog
     * CAMERA core        48052400 - 480527ff
4732 827df9f3 balrog
     * CAMERA DMA        48052800 - 48052bff
4733 827df9f3 balrog
     * CAMERA MMU        48052c00 - 48052fff
4734 827df9f3 balrog
     * CAMERA L4        48053000 - 48053fff
4735 827df9f3 balrog
     * SDMA Mod                48056000 - 48056fff
4736 827df9f3 balrog
     * SDMA L4                48057000 - 48057fff
4737 827df9f3 balrog
     * SSI Top                48058000 - 48058fff
4738 827df9f3 balrog
     * SSI GDD                48059000 - 48059fff
4739 827df9f3 balrog
     * SSI Port1        4805a000 - 4805afff
4740 827df9f3 balrog
     * SSI Port2        4805b000 - 4805bfff
4741 827df9f3 balrog
     * SSI L4                4805c000 - 4805cfff
4742 827df9f3 balrog
     * USB Mod                4805e000 - 480fefff
4743 827df9f3 balrog
     * USB L4                4805f000 - 480fffff
4744 827df9f3 balrog
     * WIN_TRACER1 Mod        48060000 - 48060fff
4745 827df9f3 balrog
     * WIN_TRACER1 L4        48061000 - 48061fff
4746 827df9f3 balrog
     * WIN_TRACER2 Mod        48062000 - 48062fff
4747 827df9f3 balrog
     * WIN_TRACER2 L4        48063000 - 48063fff
4748 827df9f3 balrog
     * WIN_TRACER3 Mod        48064000 - 48064fff
4749 827df9f3 balrog
     * WIN_TRACER3 L4        48065000 - 48065fff
4750 827df9f3 balrog
     * WIN_TRACER4 Top        48066000 - 480660ff
4751 827df9f3 balrog
     * WIN_TRACER4 ETT        48066100 - 480661ff
4752 827df9f3 balrog
     * WIN_TRACER4 WT        48066200 - 480662ff
4753 827df9f3 balrog
     * WIN_TRACER4 L4        48067000 - 48067fff
4754 827df9f3 balrog
     * XTI Mod                48068000 - 48068fff
4755 827df9f3 balrog
     * XTI L4                48069000 - 48069fff
4756 827df9f3 balrog
     * UART1 Mod        4806a000 - 4806afff
4757 827df9f3 balrog
     * UART1 L4                4806b000 - 4806bfff
4758 827df9f3 balrog
     * UART2 Mod        4806c000 - 4806cfff
4759 827df9f3 balrog
     * UART2 L4                4806d000 - 4806dfff
4760 827df9f3 balrog
     * UART3 Mod        4806e000 - 4806efff
4761 827df9f3 balrog
     * UART3 L4                4806f000 - 4806ffff
4762 827df9f3 balrog
     * I2C1 Mod                48070000 - 48070fff
4763 827df9f3 balrog
     * I2C1 L4                48071000 - 48071fff
4764 827df9f3 balrog
     * I2C2 Mod                48072000 - 48072fff
4765 827df9f3 balrog
     * I2C2 L4                48073000 - 48073fff
4766 827df9f3 balrog
     * McBSP1 Mod        48074000 - 48074fff
4767 827df9f3 balrog
     * McBSP1 L4        48075000 - 48075fff
4768 827df9f3 balrog
     * McBSP2 Mod        48076000 - 48076fff
4769 827df9f3 balrog
     * McBSP2 L4        48077000 - 48077fff
4770 827df9f3 balrog
     * GPTIMER3 Mod        48078000 - 48078fff
4771 827df9f3 balrog
     * GPTIMER3 L4        48079000 - 48079fff
4772 827df9f3 balrog
     * GPTIMER4 Mod        4807a000 - 4807afff
4773 827df9f3 balrog
     * GPTIMER4 L4        4807b000 - 4807bfff
4774 827df9f3 balrog
     * GPTIMER5 Mod        4807c000 - 4807cfff
4775 827df9f3 balrog
     * GPTIMER5 L4        4807d000 - 4807dfff
4776 827df9f3 balrog
     * GPTIMER6 Mod        4807e000 - 4807efff
4777 827df9f3 balrog
     * GPTIMER6 L4        4807f000 - 4807ffff
4778 827df9f3 balrog
     * GPTIMER7 Mod        48080000 - 48080fff
4779 827df9f3 balrog
     * GPTIMER7 L4        48081000 - 48081fff
4780 827df9f3 balrog
     * GPTIMER8 Mod        48082000 - 48082fff
4781 827df9f3 balrog
     * GPTIMER8 L4        48083000 - 48083fff
4782 827df9f3 balrog
     * GPTIMER9 Mod        48084000 - 48084fff
4783 827df9f3 balrog
     * GPTIMER9 L4        48085000 - 48085fff
4784 827df9f3 balrog
     * GPTIMER10 Mod        48086000 - 48086fff
4785 827df9f3 balrog
     * GPTIMER10 L4        48087000 - 48087fff
4786 827df9f3 balrog
     * GPTIMER11 Mod        48088000 - 48088fff
4787 827df9f3 balrog
     * GPTIMER11 L4        48089000 - 48089fff
4788 827df9f3 balrog
     * GPTIMER12 Mod        4808a000 - 4808afff
4789 827df9f3 balrog
     * GPTIMER12 L4        4808b000 - 4808bfff
4790 827df9f3 balrog
     * EAC Mod                48090000 - 48090fff
4791 827df9f3 balrog
     * EAC L4                48091000 - 48091fff
4792 827df9f3 balrog
     * FAC Mod                48092000 - 48092fff
4793 827df9f3 balrog
     * FAC L4                48093000 - 48093fff
4794 827df9f3 balrog
     * MAILBOX Mod        48094000 - 48094fff
4795 827df9f3 balrog
     * MAILBOX L4        48095000 - 48095fff
4796 827df9f3 balrog
     * SPI1 Mod                48098000 - 48098fff
4797 827df9f3 balrog
     * SPI1 L4                48099000 - 48099fff
4798 827df9f3 balrog
     * SPI2 Mod                4809a000 - 4809afff
4799 827df9f3 balrog
     * SPI2 L4                4809b000 - 4809bfff
4800 827df9f3 balrog
     * MMC/SDIO Mod        4809c000 - 4809cfff
4801 827df9f3 balrog
     * MMC/SDIO L4        4809d000 - 4809dfff
4802 827df9f3 balrog
     * MS_PRO Mod        4809e000 - 4809efff
4803 827df9f3 balrog
     * MS_PRO L4        4809f000 - 4809ffff
4804 827df9f3 balrog
     * RNG Mod                480a0000 - 480a0fff
4805 827df9f3 balrog
     * RNG L4                480a1000 - 480a1fff
4806 827df9f3 balrog
     * DES3DES Mod        480a2000 - 480a2fff
4807 827df9f3 balrog
     * DES3DES L4        480a3000 - 480a3fff
4808 827df9f3 balrog
     * SHA1MD5 Mod        480a4000 - 480a4fff
4809 827df9f3 balrog
     * SHA1MD5 L4        480a5000 - 480a5fff
4810 827df9f3 balrog
     * AES Mod                480a6000 - 480a6fff
4811 827df9f3 balrog
     * AES L4                480a7000 - 480a7fff
4812 827df9f3 balrog
     * PKA Mod                480a8000 - 480a9fff
4813 827df9f3 balrog
     * PKA L4                480aa000 - 480aafff
4814 827df9f3 balrog
     * MG Mod                480b0000 - 480b0fff
4815 827df9f3 balrog
     * MG L4                480b1000 - 480b1fff
4816 827df9f3 balrog
     * HDQ/1-wire Mod        480b2000 - 480b2fff
4817 827df9f3 balrog
     * HDQ/1-wire L4        480b3000 - 480b3fff
4818 827df9f3 balrog
     * MPU interrupt        480fe000 - 480fefff
4819 54585ffe balrog
     * STI channel base        54000000 - 5400ffff
4820 827df9f3 balrog
     * IVA RAM                5c000000 - 5c01ffff
4821 827df9f3 balrog
     * IVA ROM                5c020000 - 5c027fff
4822 827df9f3 balrog
     * IMG_BUF_A        5c040000 - 5c040fff
4823 827df9f3 balrog
     * IMG_BUF_B        5c042000 - 5c042fff
4824 827df9f3 balrog
     * VLCDS                5c048000 - 5c0487ff
4825 827df9f3 balrog
     * IMX_COEF                5c049000 - 5c04afff
4826 827df9f3 balrog
     * IMX_CMD                5c051000 - 5c051fff
4827 827df9f3 balrog
     * VLCDQ                5c053000 - 5c0533ff
4828 827df9f3 balrog
     * VLCDH                5c054000 - 5c054fff
4829 827df9f3 balrog
     * SEQ_CMD                5c055000 - 5c055fff
4830 827df9f3 balrog
     * IMX_REG                5c056000 - 5c0560ff
4831 827df9f3 balrog
     * VLCD_REG                5c056100 - 5c0561ff
4832 827df9f3 balrog
     * SEQ_REG                5c056200 - 5c0562ff
4833 827df9f3 balrog
     * IMG_BUF_REG        5c056300 - 5c0563ff
4834 827df9f3 balrog
     * SEQIRQ_REG        5c056400 - 5c0564ff
4835 827df9f3 balrog
     * OCP_REG                5c060000 - 5c060fff
4836 827df9f3 balrog
     * SYSC_REG                5c070000 - 5c070fff
4837 827df9f3 balrog
     * MMU_REG                5d000000 - 5d000fff
4838 827df9f3 balrog
     * sDMA R                68000400 - 680005ff
4839 827df9f3 balrog
     * sDMA W                68000600 - 680007ff
4840 827df9f3 balrog
     * Display Control        68000800 - 680009ff
4841 827df9f3 balrog
     * DSP subsystem        68000a00 - 68000bff
4842 827df9f3 balrog
     * MPU subsystem        68000c00 - 68000dff
4843 827df9f3 balrog
     * IVA subsystem        68001000 - 680011ff
4844 827df9f3 balrog
     * USB                68001200 - 680013ff
4845 827df9f3 balrog
     * Camera                68001400 - 680015ff
4846 827df9f3 balrog
     * VLYNQ (firewall)        68001800 - 68001bff
4847 827df9f3 balrog
     * VLYNQ                68001e00 - 68001fff
4848 827df9f3 balrog
     * SSI                68002000 - 680021ff
4849 827df9f3 balrog
     * L4                68002400 - 680025ff
4850 827df9f3 balrog
     * DSP (firewall)        68002800 - 68002bff
4851 827df9f3 balrog
     * DSP subsystem        68002e00 - 68002fff
4852 827df9f3 balrog
     * IVA (firewall)        68003000 - 680033ff
4853 827df9f3 balrog
     * IVA                68003600 - 680037ff
4854 827df9f3 balrog
     * GFX                68003a00 - 68003bff
4855 827df9f3 balrog
     * CMDWR emulation        68003c00 - 68003dff
4856 827df9f3 balrog
     * SMS                68004000 - 680041ff
4857 827df9f3 balrog
     * OCM                68004200 - 680043ff
4858 827df9f3 balrog
     * GPMC                68004400 - 680045ff
4859 827df9f3 balrog
     * RAM (firewall)        68005000 - 680053ff
4860 827df9f3 balrog
     * RAM (err login)        68005400 - 680057ff
4861 827df9f3 balrog
     * ROM (firewall)        68005800 - 68005bff
4862 827df9f3 balrog
     * ROM (err login)        68005c00 - 68005fff
4863 827df9f3 balrog
     * GPMC (firewall)        68006000 - 680063ff
4864 827df9f3 balrog
     * GPMC (err login)        68006400 - 680067ff
4865 827df9f3 balrog
     * SMS (err login)        68006c00 - 68006fff
4866 827df9f3 balrog
     * SMS registers        68008000 - 68008fff
4867 827df9f3 balrog
     * SDRC registers        68009000 - 68009fff
4868 827df9f3 balrog
     * GPMC registers        6800a000   6800afff
4869 827df9f3 balrog
     */
4870 827df9f3 balrog
4871 8217606e Jan Kiszka
    qemu_register_reset(omap2_mpu_reset, 0, s);
4872 827df9f3 balrog
4873 827df9f3 balrog
    return s;
4874 827df9f3 balrog
}