Statistics
| Branch: | Revision:

root / hw / twl92230.c @ 0b7ade1d

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