Statistics
| Branch: | Revision:

root / hw / twl92230.c @ 0d09e41a

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