2 * TI TWL4030 for beagle board
3 * register implementation based on TPS65950 ES1.0 specification
5 * Copyright (C) 2008 yajin<yajin@vm-kernel.org>
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.
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.
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,
24 #include "qemu-timer.h"
31 #define TRACEW(regname, value) fprintf(stderr, "%s: %s = 0x%02x\n", __FUNCTION__, regname, value);
33 //extern CPUState *cpu_single_env;
35 struct twl4030_i2c_s {
41 struct twl4030_s *twl4030;
45 struct twl4030_i2c_s *i2c[5];
50 uint8_t seq_mem[64][4]; /* power-management sequencing memory */
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 */
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 */
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 */
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 */
193 static uint8_t twl4030_48_read(void *opaque, uint8_t addr)
195 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
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;
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);
230 static void twl4030_48_write(void *opaque, uint8_t addr, uint8_t value)
232 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
235 case 0x04: /* IFC_CTRL */
236 s->reg_data[0x04] = value & 0x80;
238 case 0x05: /* IFC_CRTL_SET */
239 s->reg_data[0x04] = (s->reg_data[0x04] | value) & 0x80;
241 case 0x06: /* IFC_CRTL_CLEAR */
242 s->reg_data[0x04] = (s->reg_data[0x04] & ~value) & 0x80;
244 case 0x07: /* IFC_CTRL */
245 s->reg_data[0x07] = value & 0x61;
247 case 0x08: /* IFC_CRTL_SET */
248 s->reg_data[0x07] = (s->reg_data[0x07] | value) & 0x61;
250 case 0x09: /* IFC_CRTL_CLEAR */
251 s->reg_data[0x07] = (s->reg_data[0x07] & ~value) & 0x61;
253 case 0xac: /* POWER_CTRL */
254 s->reg_data[0xac] = value & 0x20;
256 case 0xad: /* POWER_SET */
257 s->reg_data[0xac] = (s->reg_data[0xac] | value) & 0x20;
259 case 0xae: /* POWER_CLEAR */
260 s->reg_data[0xac] = (s->reg_data[0xac] & ~value) & 0x20;
262 case 0xfd: /* PHY_PWR_CTRL */
263 s->reg_data[addr] = value & 0x1;
265 case 0xfe: /* PHY_CLK_CTRL */
266 s->reg_data[addr] = value & 0x7;
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);
278 static int twl4030_48_tx(i2c_slave *i2c, uint8_t data)
280 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
281 /* Interpret register address byte */
286 twl4030_48_write(s, s->reg++, data);
291 static int twl4030_48_rx(i2c_slave *i2c)
293 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
295 return twl4030_48_read(s, s->reg++);
298 static void twl4030_48_reset(i2c_slave *i2c)
300 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
302 memcpy(s->reg_data, addr_48_reset_values, 256);
305 static void twl4030_48_event(i2c_slave *i2c, enum i2c_event event)
307 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
309 if (event == I2C_START_SEND)
313 static uint8_t twl4030_49_read(void *opaque, uint8_t addr)
315 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
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];
335 fprintf(stderr, "%s: unknown register %02x pc %x\n",
336 __FUNCTION__, addr,cpu_single_env->regs[15]);
342 static void twl4030_49_write(void *opaque, uint8_t addr, uint8_t value)
344 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
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;
369 case 0xaf: /* GPIOPUPDCTR5 */
370 s->reg_data[addr] = value & 0x0f;
372 case 0xb4: /* GPIO_IMR1A */
373 case 0xb5: /* GPIO_IMR2A */
374 s->reg_data[addr] = value;
376 case 0xb6: /* GPIO_IMR3A */
377 s->reg_data[addr] = value & 0x03;
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;
386 case 0xc5: /* GPIO_SIH_CTRL */
387 s->reg_data[addr] = value & 0x07;
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);
401 static int twl4030_49_tx(i2c_slave *i2c, uint8_t data)
403 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
404 /* Interpret register address byte */
409 twl4030_49_write(s, s->reg++, data);
414 static int twl4030_49_rx(i2c_slave *i2c)
416 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
418 return twl4030_49_read(s, s->reg++);
421 static void twl4030_49_reset(i2c_slave *i2c)
423 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
425 memcpy(s->reg_data, addr_49_reset_values, 256);
428 static void twl4030_49_event(i2c_slave *i2c, enum i2c_event event)
430 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
432 if (event == I2C_START_SEND)
436 static uint8_t twl4030_4a_read(void *opaque, uint8_t addr)
438 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
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];
449 printf("%s: unknown register %02x pc %x \n", __FUNCTION__, addr,cpu_single_env->regs[15] );
456 static void twl4030_4a_write(void *opaque, uint8_t addr, uint8_t value)
458 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
461 case 0x61: /* MADC_ISR1 */
462 s->reg_data[value] &= ~(value & 0x0f);
464 case 0x62: /* MADC_IMR1 */
465 s->reg_data[value] = value & 0x0f;
467 case 0xb9: /* BCIISR1A */
468 s->reg_data[value] &= ~value;
470 case 0xba: /* BCIISR2A */
471 s->reg_data[value] &= ~(value & 0x0f);
473 case 0xbb: /* BCIIMR1A */
474 s->reg_data[addr] = value;
476 case 0xbc: /* BCIIMR2A */
477 s->reg_data[addr] = value & 0x0f;
479 case 0xe4: /* KEYP_IMR1 */
480 s->reg_data[addr] = value & 0x0f;
482 case 0xe9: /* KEYP_SIH_CTRL */
483 s->reg_data[addr] = value & 0x07;
485 case 0xee: /* LEDEN */
486 s->reg_data[addr] = value;
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");
493 case 0xef: /* PWMAON */
494 s->reg_data[addr] = value;
496 case 0xf0: /* PWMAOFF */
497 s->reg_data[addr] = value & 0x7f;
501 printf("%s: unknown register %02x pc %x \n", __FUNCTION__, addr,cpu_single_env->regs[15] );
508 static int twl4030_4a_tx(i2c_slave *i2c, uint8_t data)
510 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
511 /* Interpret register address byte */
516 twl4030_4a_write(s, s->reg++, data);
521 static int twl4030_4a_rx(i2c_slave *i2c)
523 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
525 return twl4030_4a_read(s, s->reg++);
528 static void twl4030_4a_reset(i2c_slave *i2c)
530 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
532 memcpy(s->reg_data, addr_4a_reset_values, 256);
535 static void twl4030_4a_event(i2c_slave *i2c, enum i2c_event event)
537 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
539 if (event == I2C_START_SEND)
543 static uint8_t twl4030_4b_read(void *opaque, uint8_t addr)
545 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
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];
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);
582 static void twl4030_4b_write(void *opaque, uint8_t addr, uint8_t value)
584 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
585 uint8_t seq_addr, seq_sub;
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;
594 case 0x1e: /* HOURS_REG */
595 case 0x25: /* ALARM_HOURS_REG */
596 s->reg_data[addr] = value & 0xbf;
598 case 0x1f: /* DAYS_REG */
599 case 0x26: /* ALARM_DAYS_REG */
600 s->reg_data[addr] = value & 0x3f;
602 case 0x20: /* MONTHS_REG */
603 case 0x27: /* ALARM_MONTHS_REG */
604 s->reg_data[addr] = value & 0x1f;
606 case 0x21: /* YEARS_REG */
607 case 0x28: /* ALARM_YEARS_REG */
608 s->reg_data[addr] = value;
610 case 0x22: /* WEEKS_REG */
611 s->reg_data[addr] = value & 0x07;
613 case 0x29: /* RTC_CTRL_REG */
614 s->reg_data[addr] = value & 0x7f;
616 case 0x2a: /* RTC_STATUS_REG */
617 s->reg_data[addr] = value & 0xfe;
619 case 0x2b: /* RTC_INTERRUPTS_REG */
620 s->reg_data[addr] = value & 0x0f;
622 case 0x2c: /* RTC_COMP_LSB_REG */
623 case 0x2d: /* RTC_COMP_MSB_REG */
624 s->reg_data[addr] = value;
626 case 0x33: /* PWR_EDR1 */
627 case 0x34: /* PWR_EDR2 */
628 s->reg_data[addr] = value;
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;
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;
645 case 0x59: /* MEMORY_ADDRESS */
646 if (s->twl4030->key_cfg)
647 s->reg_data[addr] = value;
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;
655 if ((seq_addr >= 0x2b && seq_addr <= 0x3e) || (seq_addr <= 0x0e && seq_sub == 3))
656 s->twl4030->seq_mem[seq_addr][seq_sub] = value;
658 s->reg_data[0x59]++; /* TODO: check if autoincrement is write-protected as well */
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);
670 case 0x2f: /* PWR_IMR1 */
671 s->reg_data[addr] = value;
673 case 0x35: /* PWR_SIH_CTRL */
674 s->reg_data[addr] = value & 0x07;
676 case 0x3b: /* CFG_BOOT */
677 if (s->twl4030->key_cfg)
678 s->reg_data[addr] = (s->reg_data[addr] & 0x70) | (value & 0x8f);
680 case 0x44: /* PROTECT_KEY */
681 s->twl4030->key_cfg = 0;
682 s->twl4030->key_tst = 0;
685 if (s->reg_data[addr] == 0xC0)
686 s->twl4030->key_cfg = 1;
689 if (s->reg_data[addr] == 0x0E)
690 s->twl4030->key_tst = 1;
693 if (s->reg_data[addr] == 0xCE) {
694 s->twl4030->key_cfg = 1;
695 s->twl4030->key_tst = 1;
701 s->reg_data[addr] = value;
703 case 0x7d: /* VAUX3_DEDICATED */
704 if (s->twl4030->key_tst)
705 s->reg_data[addr] = value & 0x77;
707 s->reg_data[addr] = (s->reg_data[addr] & 0x70) | (value & 0x07);
709 case 0x85: /* VMMC1_DEDICATED */
710 case 0x99: /* VDAC_DEDICATED */
711 if (s->twl4030->key_tst)
712 s->reg_data[addr] = value & 0x73;
714 s->reg_data[addr] = (s->reg_data[addr] & 0x70) | (value & 0x03);
716 case 0x91: /* VPLL2_DEDICATED */
717 if (s->twl4030->key_tst)
718 s->reg_data[addr] = value & 0x7f;
720 s->reg_data[addr] = (s->reg_data[addr] & 0x70) | (value & 0x0f);
722 case 0xcd: /* VUSB1V5_TYPE */
723 case 0xd0: /* VUSB1V8_TYPE */
724 case 0xd3: /* VUSB3V1_TYPE */
725 s->reg_data[addr] = value & 0x1f;
727 case 0xd8: /* VUSB_DEDICATED1 */
728 s->reg_data[addr] = value & 0x1f;
730 case 0xd9: /* VUSB_DEDICATED2 */
731 s->reg_data[addr] = value & 0x08;
735 fprintf(stderr, "%s: unknown register %02x value %0x pc %x \n", __FUNCTION__,
736 addr, value, cpu_single_env->regs[15]);
742 static int twl4030_4b_tx(i2c_slave *i2c, uint8_t data)
744 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
745 /* Interpret register address byte */
750 twl4030_4b_write(s, s->reg++, data);
755 static int twl4030_4b_rx(i2c_slave *i2c)
757 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
759 return twl4030_4b_read(s, s->reg++);
762 static void twl4030_4b_reset(i2c_slave *i2c)
764 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
766 memcpy(s->reg_data, addr_4b_reset_values, 256);
767 s->twl4030->key_cfg = 0;
768 s->twl4030->key_tst = 0;
771 static void twl4030_4b_event(i2c_slave *i2c, enum i2c_event event)
773 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
775 if (event == I2C_START_SEND)
779 struct twl4030_s *twl4030_init(i2c_bus *bus, qemu_irq irq)
783 struct twl4030_s *s = (struct twl4030_s *) qemu_mallocz(sizeof(*s));
787 fprintf(stderr,"can not alloc memory space for twl4030_s \n");
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;
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);
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);
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);
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);
822 //register_savevm("menelaus", -1, 0, menelaus_save, menelaus_load, s);
827 static uint8_t twl4030_read(void *opaque, uint8_t addr)
829 // struct twl4030_s *s = (struct twl4030_s *) opaque;
832 printf("twl4030_read addr %x\n",addr);
838 printf("%s: unknown register %02x\n", __FUNCTION__, addr);
846 static void twl4030_write(void *opaque, uint8_t addr, uint8_t value)
848 // struct twl4030_s *s = (struct twl4030_s *) opaque;
853 printf("twl4030_write addr %x value %x \n",addr,value);
863 printf("%s: unknown register %02x\n", __FUNCTION__, addr);
871 static int twl4030_tx(i2c_slave *i2c, uint8_t data)
873 struct twl4030_s *s = (struct twl4030_s *) i2c;
874 /* Interpret register address byte */
879 twl4030_write(s, s->reg ++, data);
884 static int twl4030_rx(i2c_slave *i2c)
886 struct twl4030_s *s = (struct twl4030_s *) i2c;
888 return twl4030_read(s, s->reg ++);
891 static void twl4030_reset(i2c_slave *i2c)
893 struct twl4030_s *s = (struct twl4030_s *) i2c;
897 static void twl4030_event(i2c_slave *i2c, enum i2c_event event)
899 struct twl4030_s *s = (struct twl4030_s *) i2c;
901 if (event == I2C_START_SEND)
905 i2c_slave *twl4030_init(i2c_bus *bus, qemu_irq irq)
907 struct twl4030_s *s = (struct twl4030_s *)
908 i2c_slave_init(bus, 0, sizeof(struct twl4030_s));
910 s->i2c.event = twl4030_event;
911 s->i2c.recv = twl4030_rx;
912 s->i2c.send = twl4030_tx;
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];
919 twl4030_reset(&s->i2c);
921 //register_savevm("menelaus", -1, 0, menelaus_save, menelaus_load, s);