Statistics
| Branch: | Revision:

root / hw / twl92230.c @ a08784dd

History | View | Annotate | Download (24.3 kB)

1 7e7c5e4c balrog
/*
2 7e7c5e4c balrog
 * TI TWL92230C energy-management companion device for the OMAP24xx.
3 7e7c5e4c balrog
 * Aka. Menelaus (N4200 MENELAUS1_V2.2)
4 7e7c5e4c balrog
 *
5 7e7c5e4c balrog
 * Copyright (C) 2008 Nokia Corporation
6 7e7c5e4c balrog
 * Written by Andrzej Zaborowski <andrew@openedhand.com>
7 7e7c5e4c balrog
 *
8 7e7c5e4c balrog
 * This program is free software; you can redistribute it and/or
9 7e7c5e4c balrog
 * modify it under the terms of the GNU General Public License as
10 7e7c5e4c balrog
 * published by the Free Software Foundation; either version 2 or
11 7e7c5e4c balrog
 * (at your option) version 3 of the License.
12 7e7c5e4c balrog
 *
13 7e7c5e4c balrog
 * This program is distributed in the hope that it will be useful,
14 7e7c5e4c balrog
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 7e7c5e4c balrog
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 7e7c5e4c balrog
 * GNU General Public License for more details.
17 7e7c5e4c balrog
 *
18 fad6cb1a aurel32
 * You should have received a copy of the GNU General Public License along
19 8167ee88 Blue Swirl
 * with this program; if not, see <http://www.gnu.org/licenses/>.
20 7e7c5e4c balrog
 */
21 7e7c5e4c balrog
22 7e7c5e4c balrog
#include "hw.h"
23 7e7c5e4c balrog
#include "qemu-timer.h"
24 7e7c5e4c balrog
#include "i2c.h"
25 7e7c5e4c balrog
#include "console.h"
26 7e7c5e4c balrog
27 7e7c5e4c balrog
#define VERBOSE 1
28 7e7c5e4c balrog
29 bc24a225 Paul Brook
typedef struct {
30 7e7c5e4c balrog
    i2c_slave i2c;
31 7e7c5e4c balrog
32 7e7c5e4c balrog
    int firstbyte;
33 7e7c5e4c balrog
    uint8_t reg;
34 7e7c5e4c balrog
35 7e7c5e4c balrog
    uint8_t vcore[5];
36 7e7c5e4c balrog
    uint8_t dcdc[3];
37 7e7c5e4c balrog
    uint8_t ldo[8];
38 7e7c5e4c balrog
    uint8_t sleep[2];
39 7e7c5e4c balrog
    uint8_t osc;
40 7e7c5e4c balrog
    uint8_t detect;
41 7e7c5e4c balrog
    uint16_t mask;
42 7e7c5e4c balrog
    uint16_t status;
43 7e7c5e4c balrog
    uint8_t dir;
44 7e7c5e4c balrog
    uint8_t inputs;
45 7e7c5e4c balrog
    uint8_t outputs;
46 7e7c5e4c balrog
    uint8_t bbsms;
47 7e7c5e4c balrog
    uint8_t pull[4];
48 7e7c5e4c balrog
    uint8_t mmc_ctrl[3];
49 7e7c5e4c balrog
    uint8_t mmc_debounce;
50 7e7c5e4c balrog
    struct {
51 7e7c5e4c balrog
        uint8_t ctrl;
52 7e7c5e4c balrog
        uint16_t comp;
53 b0f74c87 balrog
        QEMUTimer *hz_tm;
54 7e7c5e4c balrog
        int64_t next;
55 7e7c5e4c balrog
        struct tm tm;
56 7e7c5e4c balrog
        struct tm new;
57 7e7c5e4c balrog
        struct tm alm;
58 aec454d2 balrog
        int sec_offset;
59 aec454d2 balrog
        int alm_sec;
60 aec454d2 balrog
        int next_comp;
61 7e7c5e4c balrog
    } rtc;
62 f0495f56 Juan Quintela
    uint16_t rtc_next_vmstate;
63 d3356811 Paul Brook
    qemu_irq out[4];
64 7e7c5e4c balrog
    qemu_irq *in;
65 b53d44e5 Juan Quintela
    uint8_t pwrbtn_state;
66 7e7c5e4c balrog
    qemu_irq pwrbtn;
67 bc24a225 Paul Brook
} MenelausState;
68 7e7c5e4c balrog
69 bc24a225 Paul Brook
static inline void menelaus_update(MenelausState *s)
70 7e7c5e4c balrog
{
71 d3356811 Paul Brook
    qemu_set_irq(s->out[3], s->status & ~s->mask);
72 7e7c5e4c balrog
}
73 7e7c5e4c balrog
74 bc24a225 Paul Brook
static inline void menelaus_rtc_start(MenelausState *s)
75 7e7c5e4c balrog
{
76 7bd427d8 Paolo Bonzini
    s->rtc.next += qemu_get_clock_ms(rt_clock);
77 b0f74c87 balrog
    qemu_mod_timer(s->rtc.hz_tm, s->rtc.next);
78 7e7c5e4c balrog
}
79 7e7c5e4c balrog
80 bc24a225 Paul Brook
static inline void menelaus_rtc_stop(MenelausState *s)
81 7e7c5e4c balrog
{
82 b0f74c87 balrog
    qemu_del_timer(s->rtc.hz_tm);
83 7bd427d8 Paolo Bonzini
    s->rtc.next -= qemu_get_clock_ms(rt_clock);
84 7e7c5e4c balrog
    if (s->rtc.next < 1)
85 7e7c5e4c balrog
        s->rtc.next = 1;
86 7e7c5e4c balrog
}
87 7e7c5e4c balrog
88 bc24a225 Paul Brook
static void menelaus_rtc_update(MenelausState *s)
89 7e7c5e4c balrog
{
90 aec454d2 balrog
    qemu_get_timedate(&s->rtc.tm, s->rtc.sec_offset);
91 7e7c5e4c balrog
}
92 7e7c5e4c balrog
93 bc24a225 Paul Brook
static void menelaus_alm_update(MenelausState *s)
94 7e7c5e4c balrog
{
95 7e7c5e4c balrog
    if ((s->rtc.ctrl & 3) == 3)
96 aec454d2 balrog
        s->rtc.alm_sec = qemu_timedate_diff(&s->rtc.alm) - s->rtc.sec_offset;
97 7e7c5e4c balrog
}
98 7e7c5e4c balrog
99 7e7c5e4c balrog
static void menelaus_rtc_hz(void *opaque)
100 7e7c5e4c balrog
{
101 bc24a225 Paul Brook
    MenelausState *s = (MenelausState *) opaque;
102 7e7c5e4c balrog
103 aec454d2 balrog
    s->rtc.next_comp --;
104 aec454d2 balrog
    s->rtc.alm_sec --;
105 7e7c5e4c balrog
    s->rtc.next += 1000;
106 b0f74c87 balrog
    qemu_mod_timer(s->rtc.hz_tm, s->rtc.next);
107 7e7c5e4c balrog
    if ((s->rtc.ctrl >> 3) & 3) {                                /* EVERY */
108 7e7c5e4c balrog
        menelaus_rtc_update(s);
109 7e7c5e4c balrog
        if (((s->rtc.ctrl >> 3) & 3) == 1 && !s->rtc.tm.tm_sec)
110 7e7c5e4c balrog
            s->status |= 1 << 8;                                /* RTCTMR */
111 7e7c5e4c balrog
        else if (((s->rtc.ctrl >> 3) & 3) == 2 && !s->rtc.tm.tm_min)
112 7e7c5e4c balrog
            s->status |= 1 << 8;                                /* RTCTMR */
113 7e7c5e4c balrog
        else if (!s->rtc.tm.tm_hour)
114 7e7c5e4c balrog
            s->status |= 1 << 8;                                /* RTCTMR */
115 7e7c5e4c balrog
    } else
116 7e7c5e4c balrog
        s->status |= 1 << 8;                                        /* RTCTMR */
117 7e7c5e4c balrog
    if ((s->rtc.ctrl >> 1) & 1) {                                /* RTC_AL_EN */
118 aec454d2 balrog
        if (s->rtc.alm_sec == 0)
119 7e7c5e4c balrog
            s->status |= 1 << 9;                                /* RTCALM */
120 7e7c5e4c balrog
        /* TODO: wake-up */
121 7e7c5e4c balrog
    }
122 aec454d2 balrog
    if (s->rtc.next_comp <= 0) {
123 7e7c5e4c balrog
        s->rtc.next -= muldiv64((int16_t) s->rtc.comp, 1000, 0x8000);
124 aec454d2 balrog
        s->rtc.next_comp = 3600;
125 7e7c5e4c balrog
    }
126 7e7c5e4c balrog
    menelaus_update(s);
127 7e7c5e4c balrog
}
128 7e7c5e4c balrog
129 8fcd3692 blueswir1
static void menelaus_reset(i2c_slave *i2c)
130 7e7c5e4c balrog
{
131 bc24a225 Paul Brook
    MenelausState *s = (MenelausState *) i2c;
132 7e7c5e4c balrog
    s->reg = 0x00;
133 7e7c5e4c balrog
134 7e7c5e4c balrog
    s->vcore[0] = 0x0c;        /* XXX: X-loader needs 0x8c? check!  */
135 7e7c5e4c balrog
    s->vcore[1] = 0x05;
136 7e7c5e4c balrog
    s->vcore[2] = 0x02;
137 7e7c5e4c balrog
    s->vcore[3] = 0x0c;
138 7e7c5e4c balrog
    s->vcore[4] = 0x03;
139 7e7c5e4c balrog
    s->dcdc[0] = 0x33;        /* Depends on wiring */
140 7e7c5e4c balrog
    s->dcdc[1] = 0x03;
141 7e7c5e4c balrog
    s->dcdc[2] = 0x00;
142 7e7c5e4c balrog
    s->ldo[0] = 0x95;
143 7e7c5e4c balrog
    s->ldo[1] = 0x7e;
144 7e7c5e4c balrog
    s->ldo[2] = 0x00;
145 7e7c5e4c balrog
    s->ldo[3] = 0x00;        /* Depends on wiring */
146 7e7c5e4c balrog
    s->ldo[4] = 0x03;        /* Depends on wiring */
147 7e7c5e4c balrog
    s->ldo[5] = 0x00;
148 7e7c5e4c balrog
    s->ldo[6] = 0x00;
149 7e7c5e4c balrog
    s->ldo[7] = 0x00;
150 7e7c5e4c balrog
    s->sleep[0] = 0x00;
151 7e7c5e4c balrog
    s->sleep[1] = 0x00;
152 7e7c5e4c balrog
    s->osc = 0x01;
153 7e7c5e4c balrog
    s->detect = 0x09;
154 7e7c5e4c balrog
    s->mask = 0x0fff;
155 7e7c5e4c balrog
    s->status = 0;
156 7e7c5e4c balrog
    s->dir = 0x07;
157 7e7c5e4c balrog
    s->outputs = 0x00;
158 7e7c5e4c balrog
    s->bbsms = 0x00;
159 7e7c5e4c balrog
    s->pull[0] = 0x00;
160 7e7c5e4c balrog
    s->pull[1] = 0x00;
161 7e7c5e4c balrog
    s->pull[2] = 0x00;
162 7e7c5e4c balrog
    s->pull[3] = 0x00;
163 7e7c5e4c balrog
    s->mmc_ctrl[0] = 0x03;
164 7e7c5e4c balrog
    s->mmc_ctrl[1] = 0xc0;
165 7e7c5e4c balrog
    s->mmc_ctrl[2] = 0x00;
166 7e7c5e4c balrog
    s->mmc_debounce = 0x05;
167 7e7c5e4c balrog
168 7e7c5e4c balrog
    if (s->rtc.ctrl & 1)
169 7e7c5e4c balrog
        menelaus_rtc_stop(s);
170 7e7c5e4c balrog
    s->rtc.ctrl = 0x00;
171 7e7c5e4c balrog
    s->rtc.comp = 0x0000;
172 7e7c5e4c balrog
    s->rtc.next = 1000;
173 aec454d2 balrog
    s->rtc.sec_offset = 0;
174 aec454d2 balrog
    s->rtc.next_comp = 1800;
175 aec454d2 balrog
    s->rtc.alm_sec = 1800;
176 7e7c5e4c balrog
    s->rtc.alm.tm_sec = 0x00;
177 7e7c5e4c balrog
    s->rtc.alm.tm_min = 0x00;
178 7e7c5e4c balrog
    s->rtc.alm.tm_hour = 0x00;
179 7e7c5e4c balrog
    s->rtc.alm.tm_mday = 0x01;
180 7e7c5e4c balrog
    s->rtc.alm.tm_mon = 0x00;
181 7e7c5e4c balrog
    s->rtc.alm.tm_year = 2004;
182 7e7c5e4c balrog
    menelaus_update(s);
183 7e7c5e4c balrog
}
184 7e7c5e4c balrog
185 7e7c5e4c balrog
static void menelaus_gpio_set(void *opaque, int line, int level)
186 7e7c5e4c balrog
{
187 bc24a225 Paul Brook
    MenelausState *s = (MenelausState *) opaque;
188 7e7c5e4c balrog
189 7e7c5e4c balrog
    /* No interrupt generated */
190 7e7c5e4c balrog
    s->inputs &= ~(1 << line);
191 7e7c5e4c balrog
    s->inputs |= level << line;
192 7e7c5e4c balrog
}
193 7e7c5e4c balrog
194 7e7c5e4c balrog
static void menelaus_pwrbtn_set(void *opaque, int line, int level)
195 7e7c5e4c balrog
{
196 bc24a225 Paul Brook
    MenelausState *s = (MenelausState *) opaque;
197 7e7c5e4c balrog
198 7e7c5e4c balrog
    if (!s->pwrbtn_state && level) {
199 7e7c5e4c balrog
        s->status |= 1 << 11;                                        /* PSHBTN */
200 7e7c5e4c balrog
        menelaus_update(s);
201 7e7c5e4c balrog
    }
202 7e7c5e4c balrog
    s->pwrbtn_state = level;
203 7e7c5e4c balrog
}
204 7e7c5e4c balrog
205 7e7c5e4c balrog
#define MENELAUS_REV                0x01
206 7e7c5e4c balrog
#define MENELAUS_VCORE_CTRL1        0x02
207 7e7c5e4c balrog
#define MENELAUS_VCORE_CTRL2        0x03
208 7e7c5e4c balrog
#define MENELAUS_VCORE_CTRL3        0x04
209 7e7c5e4c balrog
#define MENELAUS_VCORE_CTRL4        0x05
210 7e7c5e4c balrog
#define MENELAUS_VCORE_CTRL5        0x06
211 7e7c5e4c balrog
#define MENELAUS_DCDC_CTRL1        0x07
212 7e7c5e4c balrog
#define MENELAUS_DCDC_CTRL2        0x08
213 7e7c5e4c balrog
#define MENELAUS_DCDC_CTRL3        0x09
214 7e7c5e4c balrog
#define MENELAUS_LDO_CTRL1        0x0a
215 7e7c5e4c balrog
#define MENELAUS_LDO_CTRL2        0x0b
216 7e7c5e4c balrog
#define MENELAUS_LDO_CTRL3        0x0c
217 7e7c5e4c balrog
#define MENELAUS_LDO_CTRL4        0x0d
218 7e7c5e4c balrog
#define MENELAUS_LDO_CTRL5        0x0e
219 7e7c5e4c balrog
#define MENELAUS_LDO_CTRL6        0x0f
220 7e7c5e4c balrog
#define MENELAUS_LDO_CTRL7        0x10
221 7e7c5e4c balrog
#define MENELAUS_LDO_CTRL8        0x11
222 7e7c5e4c balrog
#define MENELAUS_SLEEP_CTRL1        0x12
223 7e7c5e4c balrog
#define MENELAUS_SLEEP_CTRL2        0x13
224 7e7c5e4c balrog
#define MENELAUS_DEVICE_OFF        0x14
225 7e7c5e4c balrog
#define MENELAUS_OSC_CTRL        0x15
226 7e7c5e4c balrog
#define MENELAUS_DETECT_CTRL        0x16
227 7e7c5e4c balrog
#define MENELAUS_INT_MASK1        0x17
228 7e7c5e4c balrog
#define MENELAUS_INT_MASK2        0x18
229 7e7c5e4c balrog
#define MENELAUS_INT_STATUS1        0x19
230 7e7c5e4c balrog
#define MENELAUS_INT_STATUS2        0x1a
231 7e7c5e4c balrog
#define MENELAUS_INT_ACK1        0x1b
232 7e7c5e4c balrog
#define MENELAUS_INT_ACK2        0x1c
233 7e7c5e4c balrog
#define MENELAUS_GPIO_CTRL        0x1d
234 7e7c5e4c balrog
#define MENELAUS_GPIO_IN        0x1e
235 7e7c5e4c balrog
#define MENELAUS_GPIO_OUT        0x1f
236 7e7c5e4c balrog
#define MENELAUS_BBSMS                0x20
237 7e7c5e4c balrog
#define MENELAUS_RTC_CTRL        0x21
238 7e7c5e4c balrog
#define MENELAUS_RTC_UPDATE        0x22
239 7e7c5e4c balrog
#define MENELAUS_RTC_SEC        0x23
240 7e7c5e4c balrog
#define MENELAUS_RTC_MIN        0x24
241 7e7c5e4c balrog
#define MENELAUS_RTC_HR                0x25
242 7e7c5e4c balrog
#define MENELAUS_RTC_DAY        0x26
243 7e7c5e4c balrog
#define MENELAUS_RTC_MON        0x27
244 7e7c5e4c balrog
#define MENELAUS_RTC_YR                0x28
245 7e7c5e4c balrog
#define MENELAUS_RTC_WKDAY        0x29
246 7e7c5e4c balrog
#define MENELAUS_RTC_AL_SEC        0x2a
247 7e7c5e4c balrog
#define MENELAUS_RTC_AL_MIN        0x2b
248 7e7c5e4c balrog
#define MENELAUS_RTC_AL_HR        0x2c
249 7e7c5e4c balrog
#define MENELAUS_RTC_AL_DAY        0x2d
250 7e7c5e4c balrog
#define MENELAUS_RTC_AL_MON        0x2e
251 7e7c5e4c balrog
#define MENELAUS_RTC_AL_YR        0x2f
252 7e7c5e4c balrog
#define MENELAUS_RTC_COMP_MSB        0x30
253 7e7c5e4c balrog
#define MENELAUS_RTC_COMP_LSB        0x31
254 7e7c5e4c balrog
#define MENELAUS_S1_PULL_EN        0x32
255 7e7c5e4c balrog
#define MENELAUS_S1_PULL_DIR        0x33
256 7e7c5e4c balrog
#define MENELAUS_S2_PULL_EN        0x34
257 7e7c5e4c balrog
#define MENELAUS_S2_PULL_DIR        0x35
258 7e7c5e4c balrog
#define MENELAUS_MCT_CTRL1        0x36
259 7e7c5e4c balrog
#define MENELAUS_MCT_CTRL2        0x37
260 7e7c5e4c balrog
#define MENELAUS_MCT_CTRL3        0x38
261 7e7c5e4c balrog
#define MENELAUS_MCT_PIN_ST        0x39
262 7e7c5e4c balrog
#define MENELAUS_DEBOUNCE1        0x3a
263 7e7c5e4c balrog
264 7e7c5e4c balrog
static uint8_t menelaus_read(void *opaque, uint8_t addr)
265 7e7c5e4c balrog
{
266 bc24a225 Paul Brook
    MenelausState *s = (MenelausState *) opaque;
267 7e7c5e4c balrog
    int reg = 0;
268 7e7c5e4c balrog
269 7e7c5e4c balrog
    switch (addr) {
270 7e7c5e4c balrog
    case MENELAUS_REV:
271 7e7c5e4c balrog
        return 0x22;
272 7e7c5e4c balrog
273 7e7c5e4c balrog
    case MENELAUS_VCORE_CTRL5: reg ++;
274 7e7c5e4c balrog
    case MENELAUS_VCORE_CTRL4: reg ++;
275 7e7c5e4c balrog
    case MENELAUS_VCORE_CTRL3: reg ++;
276 7e7c5e4c balrog
    case MENELAUS_VCORE_CTRL2: reg ++;
277 7e7c5e4c balrog
    case MENELAUS_VCORE_CTRL1:
278 7e7c5e4c balrog
        return s->vcore[reg];
279 7e7c5e4c balrog
280 7e7c5e4c balrog
    case MENELAUS_DCDC_CTRL3: reg ++;
281 7e7c5e4c balrog
    case MENELAUS_DCDC_CTRL2: reg ++;
282 7e7c5e4c balrog
    case MENELAUS_DCDC_CTRL1:
283 7e7c5e4c balrog
        return s->dcdc[reg];
284 7e7c5e4c balrog
285 7e7c5e4c balrog
    case MENELAUS_LDO_CTRL8: reg ++;
286 7e7c5e4c balrog
    case MENELAUS_LDO_CTRL7: reg ++;
287 7e7c5e4c balrog
    case MENELAUS_LDO_CTRL6: reg ++;
288 7e7c5e4c balrog
    case MENELAUS_LDO_CTRL5: reg ++;
289 7e7c5e4c balrog
    case MENELAUS_LDO_CTRL4: reg ++;
290 7e7c5e4c balrog
    case MENELAUS_LDO_CTRL3: reg ++;
291 7e7c5e4c balrog
    case MENELAUS_LDO_CTRL2: reg ++;
292 7e7c5e4c balrog
    case MENELAUS_LDO_CTRL1:
293 7e7c5e4c balrog
        return s->ldo[reg];
294 7e7c5e4c balrog
295 7e7c5e4c balrog
    case MENELAUS_SLEEP_CTRL2: reg ++;
296 7e7c5e4c balrog
    case MENELAUS_SLEEP_CTRL1:
297 7e7c5e4c balrog
        return s->sleep[reg];
298 7e7c5e4c balrog
299 7e7c5e4c balrog
    case MENELAUS_DEVICE_OFF:
300 7e7c5e4c balrog
        return 0;
301 7e7c5e4c balrog
302 7e7c5e4c balrog
    case MENELAUS_OSC_CTRL:
303 7e7c5e4c balrog
        return s->osc | (1 << 7);                        /* CLK32K_GOOD */
304 7e7c5e4c balrog
305 7e7c5e4c balrog
    case MENELAUS_DETECT_CTRL:
306 7e7c5e4c balrog
        return s->detect;
307 7e7c5e4c balrog
308 7e7c5e4c balrog
    case MENELAUS_INT_MASK1:
309 7e7c5e4c balrog
        return (s->mask >> 0) & 0xff;
310 7e7c5e4c balrog
    case MENELAUS_INT_MASK2:
311 7e7c5e4c balrog
        return (s->mask >> 8) & 0xff;
312 7e7c5e4c balrog
313 7e7c5e4c balrog
    case MENELAUS_INT_STATUS1:
314 7e7c5e4c balrog
        return (s->status >> 0) & 0xff;
315 7e7c5e4c balrog
    case MENELAUS_INT_STATUS2:
316 7e7c5e4c balrog
        return (s->status >> 8) & 0xff;
317 7e7c5e4c balrog
318 7e7c5e4c balrog
    case MENELAUS_INT_ACK1:
319 7e7c5e4c balrog
    case MENELAUS_INT_ACK2:
320 7e7c5e4c balrog
        return 0;
321 7e7c5e4c balrog
322 7e7c5e4c balrog
    case MENELAUS_GPIO_CTRL:
323 7e7c5e4c balrog
        return s->dir;
324 7e7c5e4c balrog
    case MENELAUS_GPIO_IN:
325 7e7c5e4c balrog
        return s->inputs | (~s->dir & s->outputs);
326 7e7c5e4c balrog
    case MENELAUS_GPIO_OUT:
327 7e7c5e4c balrog
        return s->outputs;
328 7e7c5e4c balrog
329 7e7c5e4c balrog
    case MENELAUS_BBSMS:
330 7e7c5e4c balrog
        return s->bbsms;
331 7e7c5e4c balrog
332 7e7c5e4c balrog
    case MENELAUS_RTC_CTRL:
333 7e7c5e4c balrog
        return s->rtc.ctrl;
334 7e7c5e4c balrog
    case MENELAUS_RTC_UPDATE:
335 7e7c5e4c balrog
        return 0x00;
336 7e7c5e4c balrog
    case MENELAUS_RTC_SEC:
337 7e7c5e4c balrog
        menelaus_rtc_update(s);
338 7e7c5e4c balrog
        return to_bcd(s->rtc.tm.tm_sec);
339 7e7c5e4c balrog
    case MENELAUS_RTC_MIN:
340 7e7c5e4c balrog
        menelaus_rtc_update(s);
341 7e7c5e4c balrog
        return to_bcd(s->rtc.tm.tm_min);
342 7e7c5e4c balrog
    case MENELAUS_RTC_HR:
343 7e7c5e4c balrog
        menelaus_rtc_update(s);
344 7e7c5e4c balrog
        if ((s->rtc.ctrl >> 2) & 1)                        /* MODE12_n24 */
345 7e7c5e4c balrog
            return to_bcd((s->rtc.tm.tm_hour % 12) + 1) |
346 7e7c5e4c balrog
                    (!!(s->rtc.tm.tm_hour >= 12) << 7);        /* PM_nAM */
347 7e7c5e4c balrog
        else
348 7e7c5e4c balrog
            return to_bcd(s->rtc.tm.tm_hour);
349 7e7c5e4c balrog
    case MENELAUS_RTC_DAY:
350 7e7c5e4c balrog
        menelaus_rtc_update(s);
351 7e7c5e4c balrog
        return to_bcd(s->rtc.tm.tm_mday);
352 7e7c5e4c balrog
    case MENELAUS_RTC_MON:
353 7e7c5e4c balrog
        menelaus_rtc_update(s);
354 7e7c5e4c balrog
        return to_bcd(s->rtc.tm.tm_mon + 1);
355 7e7c5e4c balrog
    case MENELAUS_RTC_YR:
356 7e7c5e4c balrog
        menelaus_rtc_update(s);
357 7e7c5e4c balrog
        return to_bcd(s->rtc.tm.tm_year - 2000);
358 7e7c5e4c balrog
    case MENELAUS_RTC_WKDAY:
359 7e7c5e4c balrog
        menelaus_rtc_update(s);
360 7e7c5e4c balrog
        return to_bcd(s->rtc.tm.tm_wday);
361 7e7c5e4c balrog
    case MENELAUS_RTC_AL_SEC:
362 7e7c5e4c balrog
        return to_bcd(s->rtc.alm.tm_sec);
363 7e7c5e4c balrog
    case MENELAUS_RTC_AL_MIN:
364 7e7c5e4c balrog
        return to_bcd(s->rtc.alm.tm_min);
365 7e7c5e4c balrog
    case MENELAUS_RTC_AL_HR:
366 7e7c5e4c balrog
        if ((s->rtc.ctrl >> 2) & 1)                        /* MODE12_n24 */
367 7e7c5e4c balrog
            return to_bcd((s->rtc.alm.tm_hour % 12) + 1) |
368 7e7c5e4c balrog
                    (!!(s->rtc.alm.tm_hour >= 12) << 7);/* AL_PM_nAM */
369 7e7c5e4c balrog
        else
370 7e7c5e4c balrog
            return to_bcd(s->rtc.alm.tm_hour);
371 7e7c5e4c balrog
    case MENELAUS_RTC_AL_DAY:
372 7e7c5e4c balrog
        return to_bcd(s->rtc.alm.tm_mday);
373 7e7c5e4c balrog
    case MENELAUS_RTC_AL_MON:
374 7e7c5e4c balrog
        return to_bcd(s->rtc.alm.tm_mon + 1);
375 7e7c5e4c balrog
    case MENELAUS_RTC_AL_YR:
376 7e7c5e4c balrog
        return to_bcd(s->rtc.alm.tm_year - 2000);
377 7e7c5e4c balrog
    case MENELAUS_RTC_COMP_MSB:
378 7e7c5e4c balrog
        return (s->rtc.comp >> 8) & 0xff;
379 7e7c5e4c balrog
    case MENELAUS_RTC_COMP_LSB:
380 7e7c5e4c balrog
        return (s->rtc.comp >> 0) & 0xff;
381 7e7c5e4c balrog
382 7e7c5e4c balrog
    case MENELAUS_S1_PULL_EN:
383 7e7c5e4c balrog
        return s->pull[0];
384 7e7c5e4c balrog
    case MENELAUS_S1_PULL_DIR:
385 7e7c5e4c balrog
        return s->pull[1];
386 7e7c5e4c balrog
    case MENELAUS_S2_PULL_EN:
387 7e7c5e4c balrog
        return s->pull[2];
388 7e7c5e4c balrog
    case MENELAUS_S2_PULL_DIR:
389 7e7c5e4c balrog
        return s->pull[3];
390 7e7c5e4c balrog
391 7e7c5e4c balrog
    case MENELAUS_MCT_CTRL3: reg ++;
392 7e7c5e4c balrog
    case MENELAUS_MCT_CTRL2: reg ++;
393 7e7c5e4c balrog
    case MENELAUS_MCT_CTRL1:
394 7e7c5e4c balrog
        return s->mmc_ctrl[reg];
395 7e7c5e4c balrog
    case MENELAUS_MCT_PIN_ST:
396 7e7c5e4c balrog
        /* TODO: return the real Card Detect */
397 7e7c5e4c balrog
        return 0;
398 7e7c5e4c balrog
    case MENELAUS_DEBOUNCE1:
399 7e7c5e4c balrog
        return s->mmc_debounce;
400 7e7c5e4c balrog
401 7e7c5e4c balrog
    default:
402 7e7c5e4c balrog
#ifdef VERBOSE
403 7e7c5e4c balrog
        printf("%s: unknown register %02x\n", __FUNCTION__, addr);
404 7e7c5e4c balrog
#endif
405 7e7c5e4c balrog
        break;
406 7e7c5e4c balrog
    }
407 7e7c5e4c balrog
    return 0;
408 7e7c5e4c balrog
}
409 7e7c5e4c balrog
410 7e7c5e4c balrog
static void menelaus_write(void *opaque, uint8_t addr, uint8_t value)
411 7e7c5e4c balrog
{
412 bc24a225 Paul Brook
    MenelausState *s = (MenelausState *) opaque;
413 7e7c5e4c balrog
    int line;
414 7e7c5e4c balrog
    int reg = 0;
415 7e7c5e4c balrog
    struct tm tm;
416 7e7c5e4c balrog
417 7e7c5e4c balrog
    switch (addr) {
418 7e7c5e4c balrog
    case MENELAUS_VCORE_CTRL1:
419 7e7c5e4c balrog
        s->vcore[0] = (value & 0xe) | MIN(value & 0x1f, 0x12);
420 7e7c5e4c balrog
        break;
421 7e7c5e4c balrog
    case MENELAUS_VCORE_CTRL2:
422 7e7c5e4c balrog
        s->vcore[1] = value;
423 7e7c5e4c balrog
        break;
424 7e7c5e4c balrog
    case MENELAUS_VCORE_CTRL3:
425 7e7c5e4c balrog
        s->vcore[2] = MIN(value & 0x1f, 0x12);
426 7e7c5e4c balrog
        break;
427 7e7c5e4c balrog
    case MENELAUS_VCORE_CTRL4:
428 7e7c5e4c balrog
        s->vcore[3] = MIN(value & 0x1f, 0x12);
429 7e7c5e4c balrog
        break;
430 7e7c5e4c balrog
    case MENELAUS_VCORE_CTRL5:
431 7e7c5e4c balrog
        s->vcore[4] = value & 3;
432 7e7c5e4c balrog
        /* XXX
433 7e7c5e4c balrog
         * auto set to 3 on M_Active, nRESWARM
434 7e7c5e4c balrog
         * auto set to 0 on M_WaitOn, M_Backup
435 7e7c5e4c balrog
         */
436 7e7c5e4c balrog
        break;
437 7e7c5e4c balrog
438 7e7c5e4c balrog
    case MENELAUS_DCDC_CTRL1:
439 7e7c5e4c balrog
        s->dcdc[0] = value & 0x3f;
440 7e7c5e4c balrog
        break;
441 7e7c5e4c balrog
    case MENELAUS_DCDC_CTRL2:
442 7e7c5e4c balrog
        s->dcdc[1] = value & 0x07;
443 7e7c5e4c balrog
        /* XXX
444 7e7c5e4c balrog
         * auto set to 3 on M_Active, nRESWARM
445 7e7c5e4c balrog
         * auto set to 0 on M_WaitOn, M_Backup
446 7e7c5e4c balrog
         */
447 7e7c5e4c balrog
        break;
448 7e7c5e4c balrog
    case MENELAUS_DCDC_CTRL3:
449 7e7c5e4c balrog
        s->dcdc[2] = value & 0x07;
450 7e7c5e4c balrog
        break;
451 7e7c5e4c balrog
452 7e7c5e4c balrog
    case MENELAUS_LDO_CTRL1:
453 7e7c5e4c balrog
        s->ldo[0] = value;
454 7e7c5e4c balrog
        break;
455 7e7c5e4c balrog
    case MENELAUS_LDO_CTRL2:
456 7e7c5e4c balrog
        s->ldo[1] = value & 0x7f;
457 7e7c5e4c balrog
        /* XXX
458 7e7c5e4c balrog
         * auto set to 0x7e on M_WaitOn, M_Backup
459 7e7c5e4c balrog
         */
460 7e7c5e4c balrog
        break;
461 7e7c5e4c balrog
    case MENELAUS_LDO_CTRL3:
462 7e7c5e4c balrog
        s->ldo[2] = value & 3;
463 7e7c5e4c balrog
        /* XXX
464 7e7c5e4c balrog
         * auto set to 3 on M_Active, nRESWARM
465 7e7c5e4c balrog
         * auto set to 0 on M_WaitOn, M_Backup
466 7e7c5e4c balrog
         */
467 7e7c5e4c balrog
        break;
468 7e7c5e4c balrog
    case MENELAUS_LDO_CTRL4:
469 7e7c5e4c balrog
        s->ldo[3] = value & 3;
470 7e7c5e4c balrog
        /* XXX
471 7e7c5e4c balrog
         * auto set to 3 on M_Active, nRESWARM
472 7e7c5e4c balrog
         * auto set to 0 on M_WaitOn, M_Backup
473 7e7c5e4c balrog
         */
474 7e7c5e4c balrog
        break;
475 7e7c5e4c balrog
    case MENELAUS_LDO_CTRL5:
476 7e7c5e4c balrog
        s->ldo[4] = value & 3;
477 7e7c5e4c balrog
        /* XXX
478 7e7c5e4c balrog
         * auto set to 3 on M_Active, nRESWARM
479 7e7c5e4c balrog
         * auto set to 0 on M_WaitOn, M_Backup
480 7e7c5e4c balrog
         */
481 7e7c5e4c balrog
        break;
482 7e7c5e4c balrog
    case MENELAUS_LDO_CTRL6:
483 7e7c5e4c balrog
        s->ldo[5] = value & 3;
484 7e7c5e4c balrog
        break;
485 7e7c5e4c balrog
    case MENELAUS_LDO_CTRL7:
486 7e7c5e4c balrog
        s->ldo[6] = value & 3;
487 7e7c5e4c balrog
        break;
488 7e7c5e4c balrog
    case MENELAUS_LDO_CTRL8:
489 7e7c5e4c balrog
        s->ldo[7] = value & 3;
490 7e7c5e4c balrog
        break;
491 7e7c5e4c balrog
492 7e7c5e4c balrog
    case MENELAUS_SLEEP_CTRL2: reg ++;
493 7e7c5e4c balrog
    case MENELAUS_SLEEP_CTRL1:
494 7e7c5e4c balrog
        s->sleep[reg] = value;
495 7e7c5e4c balrog
        break;
496 7e7c5e4c balrog
497 7e7c5e4c balrog
    case MENELAUS_DEVICE_OFF:
498 7e7c5e4c balrog
        if (value & 1)
499 7e7c5e4c balrog
            menelaus_reset(&s->i2c);
500 7e7c5e4c balrog
        break;
501 7e7c5e4c balrog
502 7e7c5e4c balrog
    case MENELAUS_OSC_CTRL:
503 7e7c5e4c balrog
        s->osc = value & 7;
504 7e7c5e4c balrog
        break;
505 7e7c5e4c balrog
506 7e7c5e4c balrog
    case MENELAUS_DETECT_CTRL:
507 7e7c5e4c balrog
        s->detect = value & 0x7f;
508 7e7c5e4c balrog
        break;
509 7e7c5e4c balrog
510 7e7c5e4c balrog
    case MENELAUS_INT_MASK1:
511 7e7c5e4c balrog
        s->mask &= 0xf00;
512 7e7c5e4c balrog
        s->mask |= value << 0;
513 7e7c5e4c balrog
        menelaus_update(s);
514 7e7c5e4c balrog
        break;
515 7e7c5e4c balrog
    case MENELAUS_INT_MASK2:
516 7e7c5e4c balrog
        s->mask &= 0x0ff;
517 7e7c5e4c balrog
        s->mask |= value << 8;
518 7e7c5e4c balrog
        menelaus_update(s);
519 7e7c5e4c balrog
        break;
520 7e7c5e4c balrog
521 7e7c5e4c balrog
    case MENELAUS_INT_ACK1:
522 7e7c5e4c balrog
        s->status &= ~(((uint16_t) value) << 0);
523 7e7c5e4c balrog
        menelaus_update(s);
524 7e7c5e4c balrog
        break;
525 7e7c5e4c balrog
    case MENELAUS_INT_ACK2:
526 7e7c5e4c balrog
        s->status &= ~(((uint16_t) value) << 8);
527 7e7c5e4c balrog
        menelaus_update(s);
528 7e7c5e4c balrog
        break;
529 7e7c5e4c balrog
530 7e7c5e4c balrog
    case MENELAUS_GPIO_CTRL:
531 d3356811 Paul Brook
        for (line = 0; line < 3; line ++) {
532 d3356811 Paul Brook
            if (((s->dir ^ value) >> line) & 1) {
533 d3356811 Paul Brook
                qemu_set_irq(s->out[line],
534 d3356811 Paul Brook
                             ((s->outputs & ~s->dir) >> line) & 1);
535 d3356811 Paul Brook
            }
536 d3356811 Paul Brook
        }
537 7e7c5e4c balrog
        s->dir = value & 0x67;
538 7e7c5e4c balrog
        break;
539 7e7c5e4c balrog
    case MENELAUS_GPIO_OUT:
540 d3356811 Paul Brook
        for (line = 0; line < 3; line ++) {
541 d3356811 Paul Brook
            if ((((s->outputs ^ value) & ~s->dir) >> line) & 1) {
542 d3356811 Paul Brook
                qemu_set_irq(s->out[line], (s->outputs >> line) & 1);
543 d3356811 Paul Brook
            }
544 d3356811 Paul Brook
        }
545 7e7c5e4c balrog
        s->outputs = value & 0x07;
546 7e7c5e4c balrog
        break;
547 7e7c5e4c balrog
548 7e7c5e4c balrog
    case MENELAUS_BBSMS:
549 7e7c5e4c balrog
        s->bbsms = 0x0d;
550 7e7c5e4c balrog
        break;
551 7e7c5e4c balrog
552 7e7c5e4c balrog
    case MENELAUS_RTC_CTRL:
553 7e7c5e4c balrog
        if ((s->rtc.ctrl ^ value) & 1) {                        /* RTC_EN */
554 7e7c5e4c balrog
            if (value & 1)
555 7e7c5e4c balrog
                menelaus_rtc_start(s);
556 7e7c5e4c balrog
            else
557 7e7c5e4c balrog
                menelaus_rtc_stop(s);
558 7e7c5e4c balrog
        }
559 7e7c5e4c balrog
        s->rtc.ctrl = value & 0x1f;
560 7e7c5e4c balrog
        menelaus_alm_update(s);
561 7e7c5e4c balrog
        break;
562 7e7c5e4c balrog
    case MENELAUS_RTC_UPDATE:
563 7e7c5e4c balrog
        menelaus_rtc_update(s);
564 7e7c5e4c balrog
        memcpy(&tm, &s->rtc.tm, sizeof(tm));
565 7e7c5e4c balrog
        switch (value & 0xf) {
566 7e7c5e4c balrog
        case 0:
567 7e7c5e4c balrog
            break;
568 7e7c5e4c balrog
        case 1:
569 7e7c5e4c balrog
            tm.tm_sec = s->rtc.new.tm_sec;
570 7e7c5e4c balrog
            break;
571 7e7c5e4c balrog
        case 2:
572 7e7c5e4c balrog
            tm.tm_min = s->rtc.new.tm_min;
573 7e7c5e4c balrog
            break;
574 7e7c5e4c balrog
        case 3:
575 7e7c5e4c balrog
            if (s->rtc.new.tm_hour > 23)
576 7e7c5e4c balrog
                goto rtc_badness;
577 7e7c5e4c balrog
            tm.tm_hour = s->rtc.new.tm_hour;
578 7e7c5e4c balrog
            break;
579 7e7c5e4c balrog
        case 4:
580 7e7c5e4c balrog
            if (s->rtc.new.tm_mday < 1)
581 7e7c5e4c balrog
                goto rtc_badness;
582 7e7c5e4c balrog
            /* TODO check range */
583 7e7c5e4c balrog
            tm.tm_mday = s->rtc.new.tm_mday;
584 7e7c5e4c balrog
            break;
585 7e7c5e4c balrog
        case 5:
586 7e7c5e4c balrog
            if (s->rtc.new.tm_mon < 0 || s->rtc.new.tm_mon > 11)
587 7e7c5e4c balrog
                goto rtc_badness;
588 7e7c5e4c balrog
            tm.tm_mon = s->rtc.new.tm_mon;
589 7e7c5e4c balrog
            break;
590 7e7c5e4c balrog
        case 6:
591 7e7c5e4c balrog
            tm.tm_year = s->rtc.new.tm_year;
592 7e7c5e4c balrog
            break;
593 7e7c5e4c balrog
        case 7:
594 7e7c5e4c balrog
            /* TODO set .tm_mday instead */
595 7e7c5e4c balrog
            tm.tm_wday = s->rtc.new.tm_wday;
596 7e7c5e4c balrog
            break;
597 7e7c5e4c balrog
        case 8:
598 7e7c5e4c balrog
            if (s->rtc.new.tm_hour > 23)
599 7e7c5e4c balrog
                goto rtc_badness;
600 7e7c5e4c balrog
            if (s->rtc.new.tm_mday < 1)
601 7e7c5e4c balrog
                goto rtc_badness;
602 7e7c5e4c balrog
            if (s->rtc.new.tm_mon < 0 || s->rtc.new.tm_mon > 11)
603 7e7c5e4c balrog
                goto rtc_badness;
604 7e7c5e4c balrog
            tm.tm_sec = s->rtc.new.tm_sec;
605 7e7c5e4c balrog
            tm.tm_min = s->rtc.new.tm_min;
606 7e7c5e4c balrog
            tm.tm_hour = s->rtc.new.tm_hour;
607 7e7c5e4c balrog
            tm.tm_mday = s->rtc.new.tm_mday;
608 7e7c5e4c balrog
            tm.tm_mon = s->rtc.new.tm_mon;
609 7e7c5e4c balrog
            tm.tm_year = s->rtc.new.tm_year;
610 7e7c5e4c balrog
            break;
611 7e7c5e4c balrog
        rtc_badness:
612 7e7c5e4c balrog
        default:
613 7e7c5e4c balrog
            fprintf(stderr, "%s: bad RTC_UPDATE value %02x\n",
614 7e7c5e4c balrog
                            __FUNCTION__, value);
615 7e7c5e4c balrog
            s->status |= 1 << 10;                                /* RTCERR */
616 7e7c5e4c balrog
            menelaus_update(s);
617 7e7c5e4c balrog
        }
618 aec454d2 balrog
        s->rtc.sec_offset = qemu_timedate_diff(&tm);
619 7e7c5e4c balrog
        break;
620 7e7c5e4c balrog
    case MENELAUS_RTC_SEC:
621 7e7c5e4c balrog
        s->rtc.tm.tm_sec = from_bcd(value & 0x7f);
622 7e7c5e4c balrog
        break;
623 7e7c5e4c balrog
    case MENELAUS_RTC_MIN:
624 7e7c5e4c balrog
        s->rtc.tm.tm_min = from_bcd(value & 0x7f);
625 7e7c5e4c balrog
        break;
626 7e7c5e4c balrog
    case MENELAUS_RTC_HR:
627 7e7c5e4c balrog
        s->rtc.tm.tm_hour = (s->rtc.ctrl & (1 << 2)) ?        /* MODE12_n24 */
628 7e7c5e4c balrog
                MIN(from_bcd(value & 0x3f), 12) + ((value >> 7) ? 11 : -1) :
629 7e7c5e4c balrog
                from_bcd(value & 0x3f);
630 7e7c5e4c balrog
        break;
631 7e7c5e4c balrog
    case MENELAUS_RTC_DAY:
632 7e7c5e4c balrog
        s->rtc.tm.tm_mday = from_bcd(value);
633 7e7c5e4c balrog
        break;
634 7e7c5e4c balrog
    case MENELAUS_RTC_MON:
635 7e7c5e4c balrog
        s->rtc.tm.tm_mon = MAX(1, from_bcd(value)) - 1;
636 7e7c5e4c balrog
        break;
637 7e7c5e4c balrog
    case MENELAUS_RTC_YR:
638 7e7c5e4c balrog
        s->rtc.tm.tm_year = 2000 + from_bcd(value);
639 7e7c5e4c balrog
        break;
640 7e7c5e4c balrog
    case MENELAUS_RTC_WKDAY:
641 7e7c5e4c balrog
        s->rtc.tm.tm_mday = from_bcd(value);
642 7e7c5e4c balrog
        break;
643 7e7c5e4c balrog
    case MENELAUS_RTC_AL_SEC:
644 7e7c5e4c balrog
        s->rtc.alm.tm_sec = from_bcd(value & 0x7f);
645 7e7c5e4c balrog
        menelaus_alm_update(s);
646 7e7c5e4c balrog
        break;
647 7e7c5e4c balrog
    case MENELAUS_RTC_AL_MIN:
648 7e7c5e4c balrog
        s->rtc.alm.tm_min = from_bcd(value & 0x7f);
649 7e7c5e4c balrog
        menelaus_alm_update(s);
650 7e7c5e4c balrog
        break;
651 7e7c5e4c balrog
    case MENELAUS_RTC_AL_HR:
652 7e7c5e4c balrog
        s->rtc.alm.tm_hour = (s->rtc.ctrl & (1 << 2)) ?        /* MODE12_n24 */
653 7e7c5e4c balrog
                MIN(from_bcd(value & 0x3f), 12) + ((value >> 7) ? 11 : -1) :
654 7e7c5e4c balrog
                from_bcd(value & 0x3f);
655 7e7c5e4c balrog
        menelaus_alm_update(s);
656 7e7c5e4c balrog
        break;
657 7e7c5e4c balrog
    case MENELAUS_RTC_AL_DAY:
658 7e7c5e4c balrog
        s->rtc.alm.tm_mday = from_bcd(value);
659 7e7c5e4c balrog
        menelaus_alm_update(s);
660 7e7c5e4c balrog
        break;
661 7e7c5e4c balrog
    case MENELAUS_RTC_AL_MON:
662 7e7c5e4c balrog
        s->rtc.alm.tm_mon = MAX(1, from_bcd(value)) - 1;
663 7e7c5e4c balrog
        menelaus_alm_update(s);
664 7e7c5e4c balrog
        break;
665 7e7c5e4c balrog
    case MENELAUS_RTC_AL_YR:
666 7e7c5e4c balrog
        s->rtc.alm.tm_year = 2000 + from_bcd(value);
667 7e7c5e4c balrog
        menelaus_alm_update(s);
668 7e7c5e4c balrog
        break;
669 7e7c5e4c balrog
    case MENELAUS_RTC_COMP_MSB:
670 7e7c5e4c balrog
        s->rtc.comp &= 0xff;
671 7e7c5e4c balrog
        s->rtc.comp |= value << 8;
672 7e7c5e4c balrog
        break;
673 7e7c5e4c balrog
    case MENELAUS_RTC_COMP_LSB:
674 7e7c5e4c balrog
        s->rtc.comp &= 0xff << 8;
675 7e7c5e4c balrog
        s->rtc.comp |= value;
676 7e7c5e4c balrog
        break;
677 7e7c5e4c balrog
678 7e7c5e4c balrog
    case MENELAUS_S1_PULL_EN:
679 7e7c5e4c balrog
        s->pull[0] = value;
680 7e7c5e4c balrog
        break;
681 7e7c5e4c balrog
    case MENELAUS_S1_PULL_DIR:
682 7e7c5e4c balrog
        s->pull[1] = value & 0x1f;
683 7e7c5e4c balrog
        break;
684 7e7c5e4c balrog
    case MENELAUS_S2_PULL_EN:
685 7e7c5e4c balrog
        s->pull[2] = value;
686 7e7c5e4c balrog
        break;
687 7e7c5e4c balrog
    case MENELAUS_S2_PULL_DIR:
688 7e7c5e4c balrog
        s->pull[3] = value & 0x1f;
689 7e7c5e4c balrog
        break;
690 7e7c5e4c balrog
691 7e7c5e4c balrog
    case MENELAUS_MCT_CTRL1:
692 7e7c5e4c balrog
        s->mmc_ctrl[0] = value & 0x7f;
693 7e7c5e4c balrog
        break;
694 7e7c5e4c balrog
    case MENELAUS_MCT_CTRL2:
695 7e7c5e4c balrog
        s->mmc_ctrl[1] = value;
696 7e7c5e4c balrog
        /* TODO update Card Detect interrupts */
697 7e7c5e4c balrog
        break;
698 7e7c5e4c balrog
    case MENELAUS_MCT_CTRL3:
699 7e7c5e4c balrog
        s->mmc_ctrl[2] = value & 0xf;
700 7e7c5e4c balrog
        break;
701 7e7c5e4c balrog
    case MENELAUS_DEBOUNCE1:
702 7e7c5e4c balrog
        s->mmc_debounce = value & 0x3f;
703 7e7c5e4c balrog
        break;
704 7e7c5e4c balrog
705 7e7c5e4c balrog
    default:
706 7e7c5e4c balrog
#ifdef VERBOSE
707 7e7c5e4c balrog
        printf("%s: unknown register %02x\n", __FUNCTION__, addr);
708 7e7c5e4c balrog
#endif
709 7e7c5e4c balrog
    }
710 7e7c5e4c balrog
}
711 7e7c5e4c balrog
712 7e7c5e4c balrog
static void menelaus_event(i2c_slave *i2c, enum i2c_event event)
713 7e7c5e4c balrog
{
714 bc24a225 Paul Brook
    MenelausState *s = (MenelausState *) i2c;
715 7e7c5e4c balrog
716 7e7c5e4c balrog
    if (event == I2C_START_SEND)
717 7e7c5e4c balrog
        s->firstbyte = 1;
718 7e7c5e4c balrog
}
719 7e7c5e4c balrog
720 7e7c5e4c balrog
static int menelaus_tx(i2c_slave *i2c, uint8_t data)
721 7e7c5e4c balrog
{
722 bc24a225 Paul Brook
    MenelausState *s = (MenelausState *) i2c;
723 7e7c5e4c balrog
    /* Interpret register address byte */
724 7e7c5e4c balrog
    if (s->firstbyte) {
725 7e7c5e4c balrog
        s->reg = data;
726 7e7c5e4c balrog
        s->firstbyte = 0;
727 7e7c5e4c balrog
    } else
728 7e7c5e4c balrog
        menelaus_write(s, s->reg ++, data);
729 7e7c5e4c balrog
730 7e7c5e4c balrog
    return 0;
731 7e7c5e4c balrog
}
732 7e7c5e4c balrog
733 7e7c5e4c balrog
static int menelaus_rx(i2c_slave *i2c)
734 7e7c5e4c balrog
{
735 bc24a225 Paul Brook
    MenelausState *s = (MenelausState *) i2c;
736 7e7c5e4c balrog
737 7e7c5e4c balrog
    return menelaus_read(s, s->reg ++);
738 7e7c5e4c balrog
}
739 7e7c5e4c balrog
740 f0495f56 Juan Quintela
/* Save restore 32 bit int as uint16_t
741 f0495f56 Juan Quintela
   This is a Big hack, but it is how the old state did it.
742 f0495f56 Juan Quintela
   Or we broke compatibility in the state, or we can't use struct tm
743 f0495f56 Juan Quintela
 */
744 7e7c5e4c balrog
745 f0495f56 Juan Quintela
static int get_int32_as_uint16(QEMUFile *f, void *pv, size_t size)
746 f0495f56 Juan Quintela
{
747 f0495f56 Juan Quintela
    int *v = pv;
748 f0495f56 Juan Quintela
    *v = qemu_get_be16(f);
749 f0495f56 Juan Quintela
    return 0;
750 7e7c5e4c balrog
}
751 7e7c5e4c balrog
752 f0495f56 Juan Quintela
static void put_int32_as_uint16(QEMUFile *f, void *pv, size_t size)
753 7e7c5e4c balrog
{
754 f0495f56 Juan Quintela
    int *v = pv;
755 f0495f56 Juan Quintela
    qemu_put_be16(f, *v);
756 f0495f56 Juan Quintela
}
757 7e7c5e4c balrog
758 d05ac8fa Blue Swirl
static const VMStateInfo vmstate_hack_int32_as_uint16 = {
759 f0495f56 Juan Quintela
    .name = "int32_as_uint16",
760 f0495f56 Juan Quintela
    .get  = get_int32_as_uint16,
761 f0495f56 Juan Quintela
    .put  = put_int32_as_uint16,
762 f0495f56 Juan Quintela
};
763 7e7c5e4c balrog
764 f0495f56 Juan Quintela
#define VMSTATE_UINT16_HACK(_f, _s)                                  \
765 f0495f56 Juan Quintela
    VMSTATE_SINGLE(_f, _s, 0, vmstate_hack_int32_as_uint16, int32_t)
766 f0495f56 Juan Quintela
767 f0495f56 Juan Quintela
768 f0495f56 Juan Quintela
static const VMStateDescription vmstate_menelaus_tm = {
769 f0495f56 Juan Quintela
    .name = "menelaus_tm",
770 f0495f56 Juan Quintela
    .version_id = 0,
771 f0495f56 Juan Quintela
    .minimum_version_id = 0,
772 f0495f56 Juan Quintela
    .minimum_version_id_old = 0,
773 f0495f56 Juan Quintela
    .fields      = (VMStateField []) {
774 f0495f56 Juan Quintela
        VMSTATE_UINT16_HACK(tm_sec, struct tm),
775 f0495f56 Juan Quintela
        VMSTATE_UINT16_HACK(tm_min, struct tm),
776 f0495f56 Juan Quintela
        VMSTATE_UINT16_HACK(tm_hour, struct tm),
777 f0495f56 Juan Quintela
        VMSTATE_UINT16_HACK(tm_mday, struct tm),
778 f0495f56 Juan Quintela
        VMSTATE_UINT16_HACK(tm_min, struct tm),
779 f0495f56 Juan Quintela
        VMSTATE_UINT16_HACK(tm_year, struct tm),
780 f0495f56 Juan Quintela
        VMSTATE_END_OF_LIST()
781 f0495f56 Juan Quintela
    }
782 f0495f56 Juan Quintela
};
783 7e7c5e4c balrog
784 f0495f56 Juan Quintela
static void menelaus_pre_save(void *opaque)
785 7e7c5e4c balrog
{
786 f0495f56 Juan Quintela
    MenelausState *s = opaque;
787 f0495f56 Juan Quintela
    /* Should be <= 1000 */
788 7bd427d8 Paolo Bonzini
    s->rtc_next_vmstate =  s->rtc.next - qemu_get_clock_ms(rt_clock);
789 f0495f56 Juan Quintela
}
790 7e7c5e4c balrog
791 f0495f56 Juan Quintela
static int menelaus_post_load(void *opaque, int version_id)
792 f0495f56 Juan Quintela
{
793 f0495f56 Juan Quintela
    MenelausState *s = opaque;
794 7e7c5e4c balrog
795 7e7c5e4c balrog
    if (s->rtc.ctrl & 1)                                        /* RTC_EN */
796 7e7c5e4c balrog
        menelaus_rtc_stop(s);
797 f0495f56 Juan Quintela
798 f0495f56 Juan Quintela
    s->rtc.next = s->rtc_next_vmstate;
799 f0495f56 Juan Quintela
800 7e7c5e4c balrog
    menelaus_alm_update(s);
801 7e7c5e4c balrog
    menelaus_update(s);
802 7e7c5e4c balrog
    if (s->rtc.ctrl & 1)                                        /* RTC_EN */
803 7e7c5e4c balrog
        menelaus_rtc_start(s);
804 7e7c5e4c balrog
    return 0;
805 7e7c5e4c balrog
}
806 7e7c5e4c balrog
807 f0495f56 Juan Quintela
static const VMStateDescription vmstate_menelaus = {
808 f0495f56 Juan Quintela
    .name = "menelaus",
809 f0495f56 Juan Quintela
    .version_id = 0,
810 f0495f56 Juan Quintela
    .minimum_version_id = 0,
811 f0495f56 Juan Quintela
    .minimum_version_id_old = 0,
812 f0495f56 Juan Quintela
    .pre_save = menelaus_pre_save,
813 f0495f56 Juan Quintela
    .post_load = menelaus_post_load,
814 f0495f56 Juan Quintela
    .fields      = (VMStateField []) {
815 f0495f56 Juan Quintela
        VMSTATE_INT32(firstbyte, MenelausState),
816 f0495f56 Juan Quintela
        VMSTATE_UINT8(reg, MenelausState),
817 f0495f56 Juan Quintela
        VMSTATE_UINT8_ARRAY(vcore, MenelausState, 5),
818 f0495f56 Juan Quintela
        VMSTATE_UINT8_ARRAY(dcdc, MenelausState, 3),
819 f0495f56 Juan Quintela
        VMSTATE_UINT8_ARRAY(ldo, MenelausState, 8),
820 f0495f56 Juan Quintela
        VMSTATE_UINT8_ARRAY(sleep, MenelausState, 2),
821 f0495f56 Juan Quintela
        VMSTATE_UINT8(osc, MenelausState),
822 f0495f56 Juan Quintela
        VMSTATE_UINT8(detect, MenelausState),
823 f0495f56 Juan Quintela
        VMSTATE_UINT16(mask, MenelausState),
824 f0495f56 Juan Quintela
        VMSTATE_UINT16(status, MenelausState),
825 f0495f56 Juan Quintela
        VMSTATE_UINT8(dir, MenelausState),
826 f0495f56 Juan Quintela
        VMSTATE_UINT8(inputs, MenelausState),
827 f0495f56 Juan Quintela
        VMSTATE_UINT8(outputs, MenelausState),
828 f0495f56 Juan Quintela
        VMSTATE_UINT8(bbsms, MenelausState),
829 f0495f56 Juan Quintela
        VMSTATE_UINT8_ARRAY(pull, MenelausState, 4),
830 f0495f56 Juan Quintela
        VMSTATE_UINT8_ARRAY(mmc_ctrl, MenelausState, 3),
831 f0495f56 Juan Quintela
        VMSTATE_UINT8(mmc_debounce, MenelausState),
832 f0495f56 Juan Quintela
        VMSTATE_UINT8(rtc.ctrl, MenelausState),
833 f0495f56 Juan Quintela
        VMSTATE_UINT16(rtc.comp, MenelausState),
834 f0495f56 Juan Quintela
        VMSTATE_UINT16(rtc_next_vmstate, MenelausState),
835 f0495f56 Juan Quintela
        VMSTATE_STRUCT(rtc.new, MenelausState, 0, vmstate_menelaus_tm,
836 f0495f56 Juan Quintela
                       struct tm),
837 f0495f56 Juan Quintela
        VMSTATE_STRUCT(rtc.alm, MenelausState, 0, vmstate_menelaus_tm,
838 f0495f56 Juan Quintela
                       struct tm),
839 f0495f56 Juan Quintela
        VMSTATE_UINT8(pwrbtn_state, MenelausState),
840 f0495f56 Juan Quintela
        VMSTATE_I2C_SLAVE(i2c, MenelausState),
841 f0495f56 Juan Quintela
        VMSTATE_END_OF_LIST()
842 f0495f56 Juan Quintela
    }
843 f0495f56 Juan Quintela
};
844 f0495f56 Juan Quintela
845 81a322d4 Gerd Hoffmann
static int twl92230_init(i2c_slave *i2c)
846 7e7c5e4c balrog
{
847 d3356811 Paul Brook
    MenelausState *s = FROM_I2C_SLAVE(MenelausState, i2c);
848 7e7c5e4c balrog
849 7bd427d8 Paolo Bonzini
    s->rtc.hz_tm = qemu_new_timer_ms(rt_clock, menelaus_rtc_hz, s);
850 d3356811 Paul Brook
    /* Three output pins plus one interrupt pin.  */
851 d3356811 Paul Brook
    qdev_init_gpio_out(&i2c->qdev, s->out, 4);
852 d3356811 Paul Brook
    qdev_init_gpio_in(&i2c->qdev, menelaus_gpio_set, 3);
853 7e7c5e4c balrog
    s->pwrbtn = qemu_allocate_irqs(menelaus_pwrbtn_set, s, 1)[0];
854 7e7c5e4c balrog
855 7e7c5e4c balrog
    menelaus_reset(&s->i2c);
856 7e7c5e4c balrog
857 81a322d4 Gerd Hoffmann
    return 0;
858 7e7c5e4c balrog
}
859 7e7c5e4c balrog
860 d3356811 Paul Brook
static I2CSlaveInfo twl92230_info = {
861 074f2fff Gerd Hoffmann
    .qdev.name ="twl92230",
862 074f2fff Gerd Hoffmann
    .qdev.size = sizeof(MenelausState),
863 be73cfe2 Juan Quintela
    .qdev.vmsd = &vmstate_menelaus,
864 d3356811 Paul Brook
    .init = twl92230_init,
865 d3356811 Paul Brook
    .event = menelaus_event,
866 d3356811 Paul Brook
    .recv = menelaus_rx,
867 d3356811 Paul Brook
    .send = menelaus_tx
868 d3356811 Paul Brook
};
869 7e7c5e4c balrog
870 d3356811 Paul Brook
static void twl92230_register_devices(void)
871 7e7c5e4c balrog
{
872 074f2fff Gerd Hoffmann
    i2c_register_slave(&twl92230_info);
873 7e7c5e4c balrog
}
874 d3356811 Paul Brook
875 d3356811 Paul Brook
device_init(twl92230_register_devices)