Statistics
| Branch: | Revision:

root / hw / omap2.c @ 7cc0dd20

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