a60b438e5cd10243d157a6ed53ed5838f1ec9580
[qemu] / hw / twl4030.c
1 /*
2  * TI TWL4030 emulation
3  *
4  * Copyright (C) 2008 yajin<yajin@vm-kernel.org>
5  * Copyright (C) 2009 Nokia Corporation
6  *
7  * Register implementation based on TPS65950 ES1.0 specification.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22  * MA 02111-1307 USA
23  */
24  
25 #include "hw.h"
26 #include "qemu-timer.h"
27 #include "i2c.h"
28 #include "sysemu.h"
29 #include "console.h"
30 #include "cpu-all.h"
31
32 //#define VERBOSE 1
33
34 #ifdef VERBOSE
35 #define TRACE(fmt, ...) fprintf(stderr, "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
36 #else
37 #define TRACE(...)
38 #endif
39
40 struct twl4030_i2c_s {
41     i2c_slave i2c;
42     int firstbyte;
43     uint8_t reg;
44     qemu_irq irq;
45     uint8 reg_data[256];
46     struct twl4030_s *twl4030;
47 };
48
49 struct twl4030_s {
50     struct twl4030_i2c_s *i2c[5];
51     
52     int key_cfg;
53     int key_tst;
54     
55     uint8_t seq_mem[64][4]; /* power-management sequencing memory */
56 };
57
58 static const uint8_t addr_48_reset_values[256] = {
59     0x51, 0x04, 0x02, 0xc0, 0x41, 0x41, 0x41, 0x10, /* 0x00...0x07 */
60     0x10, 0x10, 0x06, 0x06, 0x06, 0x1f, 0x1f, 0x1f, /* 0x08...0x0f */
61     0x1f, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10...0x17 */
62     0x00, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, /* 0x18...0x1f */
63     0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0a, 0x03, /* 0x20...0x27 */
64     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28...0x2f */
65     0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00, /* 0x30...0x37 */
66     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38...0x3f */
67     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40...0x47 */
68     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48...0x4f */
69     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50...0x57 */
70     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58...0x5f */
71     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60...0x67 */
72     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68...0x6f */
73     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70...0x77 */
74     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78...0x7f */
75     0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, /* 0x80...0x87 */
76     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88...0x8f */
77     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90...0x97 */
78     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98...0x9f */
79     0x00, 0x10, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 0xa0...0xa7 */
80     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8...0xaf */
81     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0...0xb7 */
82     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8...0xb8 */
83     0xa0, 0xa0, 0x64, 0x7f, 0x6c, 0x75, 0x64, 0x20, /* 0xc0...0xc7 */
84     0x01, 0x17, 0x01, 0x02, 0x00, 0x36, 0x44, 0x07, /* 0xc8...0xcf */
85     0x3b, 0x17, 0x6b, 0x04, 0x00, 0x00, 0x00, 0x00, /* 0xd0...0xd7 */
86     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8...0xdf */
87     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0...0xe7 */
88     0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 0xe8...0xef */
89     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0...0xf7 */
90     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00  /* 0xf8...0xff */
91 };
92
93 static const uint8_t addr_49_reset_values[256] = {
94     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00...0x07 */
95     0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, /* 0x08...0x0f */
96     0x3f, 0x3f, 0x3f, 0x3f, 0x25, 0x00, 0x00, 0x00, /* 0x10...0x17 */
97     0x00, 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x55, /* 0x18...0x1f */
98     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20...0x27 */
99     0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, /* 0x28...0x2f */
100     0x13, 0x00, 0x00, 0x00, 0x00, 0x79, 0x11, 0x00, /* 0x30...0x37 */
101     0x00, 0x00, 0x06, 0x00, 0x44, 0x69, 0x00, 0x00, /* 0x38...0x3f */
102     0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, /* 0x40...0x47 */
103     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48...0x4f */
104     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50...0x57 */
105     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58...0x5f */
106     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60...0x67 */
107     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68...0x6f */
108     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70...0x77 */
109     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78...0x7f */
110     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80...0x87 */
111     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88...0x8f */
112     0x00, 0x90, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, /* 0x90...0x97 */
113     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98...0x9f */
114     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0...0xa7 */
115     0x00, 0x00, 0x04, 0x00, 0x55, 0x01, 0x55, 0x05, /* 0xa8...0xaf */
116     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, /* 0xb0...0xb7 */
117     0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, /* 0xb8...0xbf */
118     0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, /* 0xc0...0xc7 */
119     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8...0xcf */
120     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0...0xd7 */
121     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8...0xdf */
122     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0...0xe7 */
123     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8...0xef */
124     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0...0xf7 */
125     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8...0xff */
126 };
127
128 static const uint8_t addr_4a_reset_values[256] = {
129     0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00...0x07 */
130     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08...0x0f */
131     0xc0, 0x8c, 0xde, 0xde, 0x00, 0x00, 0x00, 0x00, /* 0x10...0x17 */
132     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18...0x1f */
133     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20...0x27 */
134     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28...0x2f */
135     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30...0x37 */
136     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38...0x3f */
137     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40...0x47 */
138     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48...0x4f */
139     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50...0x57 */
140     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58...0x5f */
141     0x00, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x55, 0x07, /* 0x60...0x67 */
142     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68...0x6f */
143     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70...0x77 */
144     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78...0x7f */
145     0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, /* 0x80...0x87 */
146     0x00, 0x68, 0x9b, 0x86, 0x48, 0x2a, 0x07, 0x28, /* 0x88...0x8f */
147     0x09, 0x69, 0x90, 0x00, 0x2a, 0x00, 0x02, 0x00, /* 0x90...0x97 */
148     0x10, 0xcd, 0x02, 0x68, 0x03, 0x00, 0x00, 0x00, /* 0x98...0x9f */
149     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0...0xa7 */
150     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8...0xaf */
151     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0...0xb7 */
152     0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, /* 0xb8...0xbf */
153     0x0f, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x01, 0x00, /* 0xc0...0xc7 */
154     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8...0xcf */
155     0x00, 0x00, 0x03, 0x00, 0x00, 0xe0, 0x00, 0x00, /* 0xd0...0xd7 */
156     0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8...0xdf */
157     0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x00, /* 0xe0...0xe7 */
158     0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8...0xef */
159     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0...0xf7 */
160     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /* 0xf8...0xff */
161 };
162
163 static const uint8_t addr_4b_reset_values[256] = {
164     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00...0x07 */
165     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08...0x0f */
166     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10...0x17 */
167     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x18...0x1f */
168     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, /* 0x20...0x27 */
169     0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x60, 0x00, /* 0x28...0x2f */
170     0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0xbf, 0xbf, /* 0x30...0x37 */
171     0xbf, 0xab, 0x00, 0x08, 0x3f, 0x15, 0x40, 0x0e, /* 0x38...0x3f */
172     0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40...0x47 */
173     0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, /* 0x48...0x4f */
174     0x00, 0x02, 0x00, 0x04, 0x0d, 0x00, 0x00, 0x00, /* 0x50...0x57 */
175     0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58...0x5f */
176     0x00, 0x00, 0x2f, 0x18, 0x0f, 0x08, 0x0f, 0x08, /* 0x60...0x67 */
177     0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68...0x6f */
178     0x00, 0x00, 0x00, 0x00, 0x08, 0x02, 0x80, 0x03, /* 0x70...0x77 */
179     0x08, 0x09, 0x00, 0x00, 0x08, 0x03, 0x80, 0x03, /* 0x78...0x7f */
180     0x08, 0x02, 0x00, 0x00, 0x08, 0x00, 0x80, 0x03, /* 0x80...0x87 */
181     0x08, 0x08, 0x20, 0x00, 0x00, 0x02, 0x80, 0x04, /* 0x88...0x8f */
182     0x08, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, /* 0x90...0x97 */
183     0x08, 0x02, 0xe0, 0x01, 0x08, 0x00, 0xe0, 0x00, /* 0x98...0x9f */
184     0x08, 0x01, 0xe0, 0x01, 0x08, 0x04, 0xe0, 0x03, /* 0xa0...0xa7 */
185     0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8...0xaf */
186     0x20, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0...0xb7 */
187     0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, /* 0xb8...0xbf */
188     0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, /* 0xc0...0xc7 */
189     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, /* 0xc8...0xcf */
190     0x00, 0x08, 0xe0, 0x00, 0x08, 0x00, 0x00, 0x00, /* 0xd0...0xd7 */
191     0x14, 0x08, 0xe0, 0x02, 0x08, 0xe0, 0x00, 0x08, /* 0xd8...0xdf */
192     0xe0, 0x05, 0x08, 0xe0, 0x06, 0x08, 0xe0, 0x00, /* 0xe0...0xe7 */
193     0x08, 0xe0, 0x00, 0x08, 0xe0, 0x06, 0x06, 0xe0, /* 0xe8...0xef */
194     0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0...0xf7 */
195     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /* 0xf8...0xff */
196 };
197
198 static uint8_t twl4030_48_read(void *opaque, uint8_t addr)
199 {
200     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
201         
202     TRACE("addr=0x%02x", addr);
203     switch (addr) {
204         case 0x00: /* VENDOR_ID_LO */
205         case 0x01: /* VENDOR_ID_HI */
206         case 0x02: /* PRODUCT_ID_LO */
207         case 0x03: /* PRODUCT_ID_HI */
208             return s->reg_data[addr];
209         case 0x04: /* FUNC_CTRL */
210         case 0x05: /* FUNC_CRTL_SET */
211         case 0x06: /* FUNC_CRTL_CLR */
212             return s->reg_data[0x04];
213         case 0x07: /* IFC_CTRL */
214         case 0x08: /* IFC_CRTL_SET */
215         case 0x09: /* IFC_CRTL_CLR */
216             return s->reg_data[0x07];
217         case 0xac: /* POWER_CTRL */
218         case 0xad: /* POWER_SET */
219         case 0xae: /* POWER_CLR */
220             return s->reg_data[0xac];
221         case 0xfd: /* PHY_PWR_CTRL */
222         case 0xfe: /* PHY_CLK_CTRL */
223             return s->reg_data[addr];
224         case 0xff: /* PHY_CLK_CTRL_STS */
225             if (s->reg_data[0xfd] & 1) /* PHY_PWR_CTRL */
226                 return 0;
227             if (s->reg_data[0xfe] & 1) /* REQ_PHY_DPLL_CLK */
228                 return 1;
229             return (s->reg_data[0x04] >> 6) & 1; /* SUSPENDM */
230         default:
231             fprintf(stderr, "%s: unknown register 0x%02x pc 0x%x\n",
232                     __FUNCTION__, addr, cpu_single_env->regs[15]);
233             break;
234     }
235     return 0;
236 }
237
238 static void twl4030_48_write(void *opaque, uint8_t addr, uint8_t value)
239 {
240     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
241         
242     TRACE("addr=0x%02x, value=0x%02x", addr, value);
243     switch (addr) {
244         case 0x04: /* FUNC_CTRL */
245             s->reg_data[0x04] = value & 0x7f;
246             break;
247         case 0x05: /* FUNC_CRTL_SET */
248             s->reg_data[0x04] = (s->reg_data[0x04] | value) & 0x7f;
249             break;
250         case 0x06: /* FUNC_CTRL_CLEAR */
251             s->reg_data[0x04] = (s->reg_data[0x04] & ~value) & 0x7f;
252             break;
253         case 0x07: /* IFC_CTRL */
254             s->reg_data[0x07] = value & 0x9e;
255             break;
256         case 0x08: /* IFC_CRTL_SET */
257             s->reg_data[0x07] = (s->reg_data[0x07] | value) & 0x9e;
258             break;
259         case 0x09: /* IFC_CRTL_CLEAR */
260             s->reg_data[0x07] = (s->reg_data[0x07] & ~value) & 0x9e;
261             break;
262         case 0xa1: /* CARKIT_SM_CTRL */
263             s->reg_data[0xa1] = value & 0x3f;
264             break;
265         case 0xa2: /* CARKIT_SM_CTRL_SET */
266             s->reg_data[0xa1] = (s->reg_data[0xa1] | value) & 0x3f;
267             break;
268         case 0xa3: /* CARKIT_SM_CTRL_CLR */
269             s->reg_data[0xa1] = (s->reg_data[0xa1] & ~value) & 0x3f;
270             break;
271         case 0xac: /* POWER_CTRL */
272             s->reg_data[0xac] = value & 0x20;
273             break;
274         case 0xad: /* POWER_SET */
275             s->reg_data[0xac] = (s->reg_data[0xac] | value) & 0x20;
276             break;
277         case 0xae: /* POWER_CLEAR */
278             s->reg_data[0xac] = (s->reg_data[0xac] & ~value) & 0x20;
279             break;
280         case 0xbb: /* CARKIT_ANA_CTRL */
281             s->reg_data[0xbb] = value;
282             break;
283         case 0xbc: /* CARKIT_ANA_CTRL_SET */
284             s->reg_data[0xbb] |= value;
285             break;
286         case 0xbd: /* CARKIT_ANA_CTRL_CLR */
287             s->reg_data[0xbb] &= ~value;
288             break;
289         case 0xfd: /* PHY_PWR_CTRL */
290             s->reg_data[addr] = value & 0x1;
291             break;
292         case 0xfe: /* PHY_CLK_CTRL */
293             s->reg_data[addr] = value & 0x7;
294             break;
295         default:
296             fprintf(stderr, "%s: unknown register 0x%02x pc 0x%x\n",
297                     __FUNCTION__, addr, cpu_single_env->regs[15]);
298                         break;
299     }
300 }
301
302 static int twl4030_48_tx(i2c_slave *i2c, uint8_t data)
303 {
304     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
305     /* Interpret register address byte */
306     if (s->firstbyte) {
307         s->reg = data;
308         s->firstbyte = 0;
309     } else
310         twl4030_48_write(s, s->reg++, data);
311         
312     return 0;
313 }
314
315 static int twl4030_48_rx(i2c_slave *i2c)
316 {
317     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
318         
319     return twl4030_48_read(s, s->reg++);
320 }
321
322 static void twl4030_48_reset(i2c_slave *i2c)
323 {
324     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
325     s->reg = 0x00;
326     memcpy(s->reg_data, addr_48_reset_values, 256);
327 }
328
329 static void twl4030_48_event(i2c_slave *i2c, enum i2c_event event)
330 {
331     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
332     
333     if (event == I2C_START_SEND)
334         s->firstbyte = 1;
335 }
336
337 static uint8_t twl4030_49_read(void *opaque, uint8_t addr)
338 {
339     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
340
341     TRACE("addr=0x%02x", addr);
342     switch (addr) {
343         /* AUDIO_VOICE region */
344         case 0x01 ... 0x49:
345             return s->reg_data[addr];
346         /* Test region */
347         case 0x4c ... 0x60:
348             return s->reg_data[addr];
349         /* PIH region */
350         case 0x81: /* PIH_ISR_P1 */
351         case 0x82: /* PIH_ISR_P2 */
352         case 0x83: /* PIH_SIR */
353             return s->reg_data[addr];
354         /* INTBR region */
355         case 0x85 ... 0x97:
356             return s->reg_data[addr];
357         /* GPIO region */
358         case 0x98 ... 0xc5:
359             return s->reg_data[addr];
360         default:
361             fprintf(stderr, "%s: unknown register 0x%02x pc 0x%x\n",
362                     __FUNCTION__, addr, cpu_single_env->regs[15]);
363                         break;
364     }
365     return 0;
366 }
367
368 static void twl4030_49_write(void *opaque, uint8_t addr, uint8_t value)
369 {
370     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
371         
372     TRACE("addr=0x%02x, value=0x%02x", addr, value);
373     switch (addr) {
374         /* AUDIO_VOICE region */
375         case 0x01 ... 0x49:
376             s->reg_data[addr] = value;
377             break;
378         /* Test region */
379         case 0x4c ... 0x59:
380             s->reg_data[addr] = value;
381             break;
382         case 0x5a ... 0x60:
383             /* read-only, ignore */
384             break;
385         /* PIH region */
386         case 0x81: /* PIH_ISR_P1 */
387         case 0x82: /* PIH_ISR_P2 */
388         case 0x83: /* PIH_SIR */
389             s->reg_data[addr] = value;
390             break;
391         /* INTBR region */
392         case 0x85 ... 0x90:
393             /* read-only, ignore */
394             break;
395         case 0x91 ... 0x97:
396             s->reg_data[addr] = value;
397             break;
398         /* GPIO region */
399         case 0x98 ... 0x9a:
400             /* read-only, ignore */
401             break;
402         case 0x9b ... 0xae:
403             s->reg_data[addr] = value;
404             break;
405         case 0xaf: /* GPIOPUPDCTR5 */
406             s->reg_data[addr] = value & 0x0f;
407             break;
408         case 0xb0 ... 0xb5:
409             s->reg_data[addr] = value;
410             break;
411             case 0xb6: /* GPIO_IMR3A */
412             s->reg_data[addr] = value & 0x03;
413             break;
414         case 0xb7 ... 0xc4:
415             s->reg_data[addr] = value;
416             break;
417             case 0xc5: /* GPIO_SIH_CTRL */
418             s->reg_data[addr] = value & 0x07;
419             break;
420         default:
421             fprintf(stderr, "%s: unknown register 0x%02x pc 0x%x\n",
422                     __FUNCTION__, addr, cpu_single_env->regs[15]);
423             break;
424     }
425 }
426
427
428 static int twl4030_49_tx(i2c_slave *i2c, uint8_t data)
429 {
430     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
431     /* Interpret register address byte */
432     if (s->firstbyte) {
433         s->reg = data;
434         s->firstbyte = 0;
435     } else
436         twl4030_49_write(s, s->reg++, data);
437         
438     return 0;
439 }
440
441 static int twl4030_49_rx(i2c_slave *i2c)
442 {
443     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
444         
445     return twl4030_49_read(s, s->reg++);
446 }
447
448 static void twl4030_49_reset(i2c_slave *i2c)
449 {
450     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
451     s->reg = 0x00;
452     memcpy(s->reg_data, addr_49_reset_values, 256);
453 }
454
455 static void twl4030_49_event(i2c_slave *i2c, enum i2c_event event)
456 {
457     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
458         
459     if (event == I2C_START_SEND)
460         s->firstbyte = 1;
461 }
462
463 static uint8_t twl4030_4a_read(void *opaque, uint8_t addr)
464 {
465     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
466         
467     TRACE("addr=0x%02x", addr);
468     switch (addr) {
469         /* MADC region */
470         case 0x00 ... 0x13:
471         case 0x61 ... 0x67:
472             return s->reg_data[addr];
473         case 0x17 ... 0x36: /* RT conversion registers */
474         case 0x37 ... 0x56: /* GP conversion registers */
475         case 0x57 ... 0x60: /* BCI conversion registers */
476             return (addr & 1) ? 0 : 0x60;
477         /* MAIN_CHARGE region */
478         case 0x74 ... 0xa6:
479             return s->reg_data[addr];
480         /* Interrupt region */
481         case 0xb9 ... 0xc6:
482             return s->reg_data[addr];
483         /* KEYPAD region */
484         case 0xd2 ... 0xe9:
485             return s->reg_data[addr];
486         /* LED region */
487         case 0xee: /* LEDEN */
488             return s->reg_data[addr];
489         /* PWMA region */
490         case 0xef: /* PWMAON */
491         case 0xf0: /* PWMAOFF */
492             return s->reg_data[addr];
493         /* PWMB region */
494         case 0xf1: /* PWMBON */
495         case 0xf2: /* PWMBOFF */
496             return s->reg_data[addr];
497         /* PWM0 region */
498         case 0xf8: /* PWM0ON */
499         case 0xf9: /* PWM0OFF */
500             return s->reg_data[addr];
501         /* PWM1 region */
502         case 0xfb: /* PWM1ON */
503         case 0xfc: /* PWM1OFF */
504             return s->reg_data[addr];
505         default:
506                 fprintf(stderr, "%s: unknown register 0x%02x pc 0x%x\n",
507                     __FUNCTION__, addr, cpu_single_env->regs[15] );
508             break;
509     }
510     return 0;
511 }
512
513 static void twl4030_4a_write(void *opaque, uint8_t addr, uint8_t value)
514 {
515     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
516
517     TRACE("addr=0x%02x, value=0x%02x", addr, value);
518     switch (addr) {
519         case 0x00: /* CTRL1 */
520             s->reg_data[addr] = value;
521             break;
522         case 0x06: /* SW1SELECT_LSB */
523         case 0x07: /* SW1SELECT_MSB */
524         case 0x08: /* SW1AVERAGE_LSB */
525         case 0x09: /* SW1AVERAGE_MSB */
526             s->reg_data[addr] = value;
527             break;
528         case 0x12: /* CTRL_SW1 */
529             s->reg_data[addr] = 0xde;
530             break;
531         case 0x61: /* MADC_ISR1 */
532             s->reg_data[addr] &= ~(value & 0x0f);
533             break;
534         case 0x62: /* MADC_IMR1 */
535             s->reg_data[addr] = value & 0x0f;
536             break;
537         case 0x97: /* BCICTL1 */
538             s->reg_data[addr] = value;
539             break;
540         case 0xb9: /* BCIISR1A */
541             s->reg_data[addr] &= ~value;
542             break;
543         case 0xba: /* BCIISR2A */
544             s->reg_data[addr] &= ~(value & 0x0f);
545             break;
546         case 0xbb: /* BCIIMR1A */
547             s->reg_data[addr] = value;
548             break;
549         case 0xbc: /* BCIIMR2A */
550             s->reg_data[addr] = value & 0x0f;
551             break;
552         case 0xd2: /* KEYP_CTRL_REG */
553             s->reg_data[addr] = value & 0x7f;
554             break;
555         case 0xe4: /* KEYP_IMR1 */
556             s->reg_data[addr] = value & 0x0f;
557             break;
558         case 0xe9: /* KEYP_SIH_CTRL */
559             s->reg_data[addr] = value & 0x07;
560             break;
561         case 0xee: /* LEDEN */
562             s->reg_data[addr] = value;
563             TRACE("LEDA power=%s/enable=%s, LEDB power=%s/enable=%s",
564                     value & 0x10 ? "on" : "off", value & 0x01 ? "yes" : "no",
565                     value & 0x20 ? "on" : "off", value & 0x02 ? "yes" : "no");
566             break;
567         case 0xef: /* PWMAON */
568         case 0xf8: /* PWM0ON */
569         case 0xfb: /* PWM1ON */
570             s->reg_data[addr] = value;
571             break;
572         case 0xf0: /* PWMAOFF */
573         case 0xf9: /* PWM0OFF */
574         case 0xfc: /* PWM1OFF */
575             s->reg_data[addr] = value & 0x7f;
576             break;
577         default:
578                 fprintf(stderr, "%s: unknown register 0x%02x pc 0x%x\n",
579                     __FUNCTION__, addr, cpu_single_env->regs[15]);
580             break;
581     }
582 }
583
584 static int twl4030_4a_tx(i2c_slave *i2c, uint8_t data)
585 {
586     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
587     /* Interpret register address byte */
588     if (s->firstbyte) {
589         s->reg = data;
590         s->firstbyte = 0;
591     } else
592         twl4030_4a_write(s, s->reg++, data);
593         
594     return 0;
595 }
596
597 static int twl4030_4a_rx(i2c_slave *i2c)
598 {
599     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
600         
601     return twl4030_4a_read(s, s->reg++);
602 }
603
604 static void twl4030_4a_reset(i2c_slave *i2c)
605 {
606     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
607     s->reg = 0x00;
608     memcpy(s->reg_data, addr_4a_reset_values, 256);
609 }
610
611 static void twl4030_4a_event(i2c_slave *i2c, enum i2c_event event)
612 {
613     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
614         
615     if (event == I2C_START_SEND)
616         s->firstbyte = 1;
617 }
618
619 static uint8_t twl4030_4b_read(void *opaque, uint8_t addr)
620 {
621     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
622
623         TRACE("addr=0x%02x", addr);
624     switch (addr) {
625         /* SECURED_REG region */
626         case 0x00 ... 0x13:
627             return s->reg_data[addr];
628         /* BACKUP_REG region */
629         case 0x14 ... 0x1b:
630             return s->reg_data[addr];
631         /* RTC region */
632         case 0x1c ... 0x2d:
633             return s->reg_data[addr];
634         /* INT region */
635         case 0x2e ... 0x35:
636             return s->reg_data[addr];
637         /* PM_MASTER region */
638         case 0x36 ... 0x44:
639             return s->reg_data[addr];
640         case 0x45: /* STS_HW_CONDITIONS - USB plugged, no VBUS -> host usb */
641             return 0x4;
642         case 0x46 ... 0x5a:
643             return s->reg_data[addr];
644         /* PM_RECEIVER region */
645         case 0x5b ... 0xf1: 
646             return s->reg_data[addr];
647         default:
648                 fprintf(stderr, "%s: unknown register 0x%02x pc 0x%x\n",
649                     __FUNCTION__, addr, cpu_single_env->regs[15] );
650             break;
651     }
652     return 0;
653 }
654
655
656 static void twl4030_4b_write(void *opaque, uint8_t addr, uint8_t value)
657 {
658     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
659     uint8_t seq_addr, seq_sub;
660
661         TRACE("addr=0x%02x, value=0x%02x", addr, value);
662     switch (addr) {
663         case 0x1c: /* SECONDS_REG */
664         case 0x1d: /* MINUTES_REG */
665         case 0x23: /* ALARM_SECONDS_REG */
666         case 0x24: /* ALARM_MINUTES_REG */
667             s->reg_data[addr] = value & 0x7f;
668             break;
669         case 0x1e: /* HOURS_REG */
670         case 0x25: /* ALARM_HOURS_REG */
671             s->reg_data[addr] = value & 0xbf;
672             break;
673         case 0x1f: /* DAYS_REG */
674         case 0x26: /* ALARM_DAYS_REG */
675             s->reg_data[addr] = value & 0x3f;
676             break;
677         case 0x20: /* MONTHS_REG */
678         case 0x27: /* ALARM_MONTHS_REG */
679             s->reg_data[addr] = value & 0x1f;
680             break;
681         case 0x21: /* YEARS_REG */
682         case 0x28: /* ALARM_YEARS_REG */
683             s->reg_data[addr] = value;
684             break;
685         case 0x22: /* WEEKS_REG */
686             s->reg_data[addr] = value & 0x07;
687             break;
688         case 0x29: /* RTC_CTRL_REG */
689             s->reg_data[addr] = value & 0x7f;
690             break;
691         case 0x2a: /* RTC_STATUS_REG */
692             s->reg_data[addr] = value & 0xfe;
693             break;
694         case 0x2b: /* RTC_INTERRUPTS_REG */
695             s->reg_data[addr] = value & 0x0f;
696             break;
697         case 0x2c: /* RTC_COMP_LSB_REG */
698         case 0x2d: /* RTC_COMP_MSB_REG */
699             s->reg_data[addr] = value;
700             break;
701         case 0x2e: /* PWR_ISR1 */
702         case 0x2f: /* PWR_IMR1 */
703             s->reg_data[addr] = value;
704             break;
705         case 0x33: /* PWR_EDR1 */
706         case 0x34: /* PWR_EDR2 */
707             s->reg_data[addr] = value;
708             break;
709         case 0x35: /* PWR_SIH_CTRL */
710             s->reg_data[addr] = value & 0x07;
711             break;
712         case 0x3b: /* CFG_BOOT */
713             if (s->twl4030->key_cfg)
714                 s->reg_data[addr] = (s->reg_data[addr] & 0x70) | (value & 0x8f);
715             break;
716         case 0x44: /* PROTECT_KEY */
717             s->twl4030->key_cfg = 0;
718             s->twl4030->key_tst = 0;
719             switch (value) {
720                 case 0x0C: 
721                     if (s->reg_data[addr] == 0xC0)
722                         s->twl4030->key_cfg = 1;
723                     break;
724                 case 0xE0:
725                     if (s->reg_data[addr] == 0x0E)
726                         s->twl4030->key_tst = 1;
727                     break;
728                 case 0xEC:
729                     if (s->reg_data[addr] == 0xCE) {
730                         s->twl4030->key_cfg = 1;
731                         s->twl4030->key_tst = 1;
732                     }
733                     break;
734                 default:
735                     break;
736             }
737             s->reg_data[addr] = value;
738             break;
739         case 0x46: /* P1_SW_EVENTS */
740         case 0x47: /* P2_SW_EVENTS */
741         case 0x48: /* P3_SW_EVENTS */
742             s->reg_data[addr] = value & 0x78;
743             break;
744         case 0x52: /* SEQ_ADD_W2P */
745         case 0x53: /* SEQ_ADD_P2A */
746         case 0x54: /* SEQ_ADD_A2W */
747         case 0x55: /* SEQ_ADD_A2S */
748         case 0x56: /* SEQ_ADD_S2A12 */
749         case 0x57: /* SEQ_ADD_S2A3 */
750         case 0x58: /* SEQ_ADD_WARM */
751             if (s->twl4030->key_cfg)
752                 s->reg_data[addr] = value & 0x3f;
753             break;
754         case 0x59: /* MEMORY_ADDRESS */
755             if (s->twl4030->key_cfg)
756                 s->reg_data[addr] = value;
757             break;
758         case 0x5a: /* MEMORY_DATA */
759             if (s->twl4030->key_cfg) {
760                 s->reg_data[addr] = value;
761                 seq_addr = s->reg_data[0x59];
762                 seq_sub = seq_addr & 3;
763                 seq_addr >>= 2;
764                 if ((seq_addr >= 0x2b && seq_addr <= 0x3e) ||
765                     (seq_addr <= 0x0e && seq_sub == 3))
766                     s->twl4030->seq_mem[seq_addr][seq_sub] = value;
767             }
768             /* TODO: check if autoincrement is write-protected as well */
769             s->reg_data[0x59]++; 
770             break;
771         case 0x68: /* MISC_CFG */
772             s->reg_data[addr] = value;
773             break;
774         case 0x7a: /* VAUX3_DEV_GRP */
775         case 0x82: /* VMMC1_DEV_GRP */
776         case 0x8e: /* VPLL2_DEV_GRP */
777         case 0x96: /* VDAC_DEV_GRP */
778         case 0xcc: /* VUSB1V5_DEV_GRP */
779         case 0xcf: /* VUSB1V8_DEV_GRP */
780         case 0xd2: /* VUSB3V1_DEV_GRP */
781         case 0xe6: /* HFCLKOUT_DEV_GRP */
782             s->reg_data[addr] = (s->reg_data[addr] & 0x0f) | (value & 0xf0); 
783             break;
784         case 0x75: /* VAUX1_DEDICATED */
785         case 0x7d: /* VAUX3_DEDICATED */
786             if (s->twl4030->key_tst)
787                 s->reg_data[addr] = value & 0x77;
788             else
789                 s->reg_data[addr] = (s->reg_data[addr] & 0x70) | (value & 0x07);
790             break;
791         case 0x79: /* VAUX2_DEDICATED */
792         case 0x81: /* VAUX4_DEDICATED */
793         case 0x91: /* VPLL2_DEDICATED */
794             if (s->twl4030->key_tst)
795                 s->reg_data[addr] = value & 0x7f;
796             else
797                 s->reg_data[addr] = (s->reg_data[addr] & 0x70) | (value & 0x0f);
798             break;
799         case 0x85: /* VMMC1_DEDICATED */
800         case 0x99: /* VDAC_DEDICATED */
801             if (s->twl4030->key_tst) 
802                 s->reg_data[addr] = value & 0x73;
803             else
804                 s->reg_data[addr] = (s->reg_data[addr] & 0x70) | (value & 0x03);
805             break;
806         case 0x74: /* VAUX1_REMAP */
807         case 0x78: /* VAUX2_REMAP */
808         case 0x7c: /* VAUX3_REMAP */
809         case 0x80: /* VAUX4_REMAP */
810         case 0x90: /* VPLL2_REMAP */
811             s->reg_data[addr] = value;
812             break;
813         case 0xcd: /* VUSB1V5_TYPE */
814         case 0xd0: /* VUSB1V8_TYPE */
815         case 0xd3: /* VUSB3V1_TYPE */
816             s->reg_data[addr] = value & 0x1f;
817             break;
818         case 0xd8: /* VUSB_DEDICATED1 */
819             s->reg_data[addr] = value & 0x1f;
820             break;
821         case 0xd9: /* VUSB_DEDICATED2 */
822             s->reg_data[addr] = value & 0x08;
823             break;
824             
825         default:
826                 fprintf(stderr,
827                     "%s: unknown register 0x%02x value 0x%02x pc 0x%x\n",
828                     __FUNCTION__, addr, value, cpu_single_env->regs[15]);
829             break;
830     }
831 }
832
833 static int twl4030_4b_tx(i2c_slave *i2c, uint8_t data)
834 {
835     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
836     /* Interpret register address byte */
837     if (s->firstbyte) {
838         s->reg = data;
839         s->firstbyte = 0;
840     } else
841         twl4030_4b_write(s, s->reg++, data);
842         
843     return 1;
844 }
845
846 static int twl4030_4b_rx(i2c_slave *i2c)
847 {
848     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
849         
850     return twl4030_4b_read(s, s->reg++);
851 }
852
853 static void twl4030_4b_reset(i2c_slave *i2c)
854 {
855     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
856     s->reg = 0x00;
857     memcpy(s->reg_data, addr_4b_reset_values, 256);
858     s->twl4030->key_cfg = 0;
859     s->twl4030->key_tst = 0;
860 }
861
862 static void twl4030_4b_event(i2c_slave *i2c, enum i2c_event event)
863 {
864     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
865         
866     if (event == I2C_START_SEND)
867         s->firstbyte = 1;
868 }
869
870 static void twl4030_save_state(QEMUFile *f, void *opaque)
871 {
872     struct twl4030_s *s = (struct twl4030_s *)opaque;
873     int i;
874     
875     qemu_put_sbe32(f, s->key_cfg);
876     qemu_put_sbe32(f, s->key_tst);
877     for (i = 0; i < 64; i++)
878         qemu_put_buffer(f, s->seq_mem[i], 4);
879     for (i = 0; i < 5; i++) {
880         qemu_put_sbe32(f, s->i2c[i]->firstbyte);
881         qemu_put_byte(f, s->i2c[i]->reg);
882         qemu_put_buffer(f, s->i2c[i]->reg_data, sizeof(s->i2c[i]->reg_data));
883     }
884 }
885
886 static int twl4030_load_state(QEMUFile *f, void *opaque, int version_id)
887 {
888     struct twl4030_s *s = (struct twl4030_s *)opaque;
889     int i;
890     
891     if (version_id)
892         return -EINVAL;
893     
894     s->key_cfg = qemu_get_sbe32(f);
895     s->key_tst = qemu_get_sbe32(f);
896     for (i = 0; i < 64; i++)
897         qemu_get_buffer(f, s->seq_mem[i], 4);
898     for (i = 0; i < 5; i++) {
899         s->i2c[i]->firstbyte = qemu_get_sbe32(f);
900         s->i2c[i]->reg = qemu_get_byte(f);
901         qemu_get_buffer(f, s->i2c[i]->reg_data, sizeof(s->i2c[i]->reg_data));
902     }
903     
904     return 0;
905 }
906
907 struct twl4030_s *twl4030_init(i2c_bus *bus, qemu_irq irq)
908 {
909     int i;
910         
911     struct twl4030_s *s = (struct twl4030_s *) qemu_mallocz(sizeof(*s));
912         
913     for (i = 0; i < 5; i++) {
914         s->i2c[i]=(struct twl4030_i2c_s *)i2c_slave_init(
915             bus, 0, sizeof(struct twl4030_i2c_s));
916         s->i2c[i]->irq = irq;
917         s->i2c[i]->twl4030 = s;
918     }
919     s->i2c[0]->i2c.event = twl4030_48_event;
920     s->i2c[0]->i2c.recv = twl4030_48_rx;
921     s->i2c[0]->i2c.send = twl4030_48_tx;
922     twl4030_48_reset(&s->i2c[0]->i2c);
923     i2c_set_slave_address((i2c_slave *)&s->i2c[0]->i2c,0x48);
924         
925     s->i2c[1]->i2c.event = twl4030_49_event;
926     s->i2c[1]->i2c.recv = twl4030_49_rx;
927     s->i2c[1]->i2c.send = twl4030_49_tx;
928     twl4030_49_reset(&s->i2c[1]->i2c);
929     i2c_set_slave_address((i2c_slave *)&s->i2c[1]->i2c,0x49);
930         
931     s->i2c[2]->i2c.event = twl4030_4a_event;
932     s->i2c[2]->i2c.recv = twl4030_4a_rx;
933     s->i2c[2]->i2c.send = twl4030_4a_tx;
934     twl4030_4a_reset(&s->i2c[2]->i2c);
935     i2c_set_slave_address((i2c_slave *)&s->i2c[2]->i2c,0x4a);
936         
937     s->i2c[3]->i2c.event = twl4030_4b_event;
938     s->i2c[3]->i2c.recv = twl4030_4b_rx;
939     s->i2c[3]->i2c.send = twl4030_4b_tx;
940     twl4030_4b_reset(&s->i2c[3]->i2c);
941     i2c_set_slave_address((i2c_slave *)&s->i2c[3]->i2c,0x4b);
942         
943     register_savevm("twl4030", -1, 0,
944                     twl4030_save_state, twl4030_load_state, s);
945
946     return s;
947 }