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