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