2 * TI TWL4030 for beagle board
4 * Copyright (C) 2008 yajin<yajin@vm-kernel.org>
5 * Copyright (C) 2009 Nokia Corporation
7 * Register implementation based on TPS65950 ES1.0 specification.
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.
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.
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,
26 #include "qemu-timer.h"
33 #define TRACEW(regname, value) fprintf(stderr, "%s: %s = 0x%02x\n", __FUNCTION__, regname, value);
35 //extern CPUState *cpu_single_env;
37 struct twl4030_i2c_s {
43 struct twl4030_s *twl4030;
47 struct twl4030_i2c_s *i2c[5];
52 uint8_t seq_mem[64][4]; /* power-management sequencing memory */
55 static const uint8_t addr_48_reset_values[256] = {
56 0x51, 0x04, 0x02, 0xc0, 0x41, 0x41, 0x41, 0x10, /* 0x00...0x07 */
57 0x10, 0x10, 0x06, 0x06, 0x06, 0x1f, 0x1f, 0x1f, /* 0x08...0x0f */
58 0x1f, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10...0x17 */
59 0x00, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, /* 0x18...0x1f */
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0a, 0x03, /* 0x20...0x27 */
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28...0x2f */
62 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00, /* 0x30...0x37 */
63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38...0x3f */
64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40...0x47 */
65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48...0x4f */
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50...0x57 */
67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58...0x5f */
68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60...0x67 */
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68...0x6f */
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70...0x77 */
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78...0x7f */
72 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, /* 0x80...0x87 */
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88...0x8f */
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90...0x97 */
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98...0x9f */
76 0x00, 0x10, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 0xa0...0xa7 */
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8...0xaf */
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0...0xb7 */
79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8...0xb8 */
80 0xa0, 0xa0, 0x64, 0x7f, 0x6c, 0x75, 0x64, 0x20, /* 0xc0...0xc7 */
81 0x01, 0x17, 0x01, 0x02, 0x00, 0x36, 0x44, 0x07, /* 0xc8...0xcf */
82 0x3b, 0x17, 0x6b, 0x04, 0x00, 0x00, 0x00, 0x00, /* 0xd0...0xd7 */
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8...0xdf */
84 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0...0xe7 */
85 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 0xe8...0xef */
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0...0xf7 */
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00 /* 0xf8...0xff */
90 static const uint8_t addr_49_reset_values[256] = {
91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00...0x07 */
92 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, /* 0x08...0x0f */
93 0x3f, 0x3f, 0x3f, 0x3f, 0x25, 0x00, 0x00, 0x00, /* 0x10...0x17 */
94 0x00, 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x55, /* 0x18...0x1f */
95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20...0x27 */
96 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, /* 0x28...0x2f */
97 0x13, 0x00, 0x00, 0x00, 0x00, 0x79, 0x11, 0x00, /* 0x30...0x37 */
98 0x00, 0x00, 0x06, 0x00, 0x44, 0x69, 0x00, 0x00, /* 0x38...0x3f */
99 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, /* 0x40...0x47 */
100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48...0x4f */
101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50...0x57 */
102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58...0x5f */
103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60...0x67 */
104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68...0x6f */
105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70...0x77 */
106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78...0x7f */
107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80...0x87 */
108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88...0x8f */
109 0x00, 0x90, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, /* 0x90...0x97 */
110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98...0x9f */
111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0...0xa7 */
112 0x00, 0x00, 0x04, 0x00, 0x55, 0x01, 0x55, 0x05, /* 0xa8...0xaf */
113 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, /* 0xb0...0xb7 */
114 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, /* 0xb8...0xbf */
115 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, /* 0xc0...0xc7 */
116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8...0xcf */
117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0...0xd7 */
118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8...0xdf */
119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0...0xe7 */
120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8...0xef */
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0...0xf7 */
122 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8...0xff */
125 static const uint8_t addr_4a_reset_values[256] = {
126 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00...0x07 */
127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08...0x0f */
128 0xc0, 0x8c, 0xde, 0xde, 0x00, 0x00, 0x00, 0x00, /* 0x10...0x17 */
129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18...0x1f */
130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20...0x27 */
131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28...0x2f */
132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30...0x37 */
133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38...0x3f */
134 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40...0x47 */
135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48...0x4f */
136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50...0x57 */
137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58...0x5f */
138 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x55, 0x07, /* 0x60...0x67 */
139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68...0x6f */
140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70...0x77 */
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78...0x7f */
142 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, /* 0x80...0x87 */
143 0x00, 0x68, 0x9b, 0x86, 0x48, 0x2a, 0x07, 0x28, /* 0x88...0x8f */
144 0x09, 0x69, 0x90, 0x00, 0x2a, 0x00, 0x02, 0x00, /* 0x90...0x97 */
145 0x10, 0xcd, 0x02, 0x68, 0x03, 0x00, 0x00, 0x00, /* 0x98...0x9f */
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0...0xa7 */
147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8...0xaf */
148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0...0xb7 */
149 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, /* 0xb8...0xbf */
150 0x0f, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x01, 0x00, /* 0xc0...0xc7 */
151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8...0xcf */
152 0x00, 0x00, 0x03, 0x00, 0x00, 0xe0, 0x00, 0x00, /* 0xd0...0xd7 */
153 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8...0xdf */
154 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x00, /* 0xe0...0xe7 */
155 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8...0xef */
156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0...0xf7 */
157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* 0xf8...0xff */
160 static const uint8_t addr_4b_reset_values[256] = {
161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00...0x07 */
162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08...0x0f */
163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10...0x17 */
164 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x18...0x1f */
165 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, /* 0x20...0x27 */
166 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28...0x2f */
167 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0xbf, 0xbf, /* 0x30...0x37 */
168 0xbf, 0xab, 0x00, 0x08, 0x3f, 0x15, 0x40, 0x0e, /* 0x38...0x3f */
169 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40...0x47 */
170 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, /* 0x48...0x4f */
171 0x00, 0x02, 0x00, 0x04, 0x0d, 0x00, 0x00, 0x00, /* 0x50...0x57 */
172 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58...0x5f */
173 0x00, 0x00, 0x2f, 0x18, 0x0f, 0x08, 0x0f, 0x08, /* 0x60...0x67 */
174 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68...0x6f */
175 0x00, 0x00, 0x00, 0x00, 0x08, 0x02, 0x80, 0x03, /* 0x70...0x77 */
176 0x08, 0x09, 0x00, 0x00, 0x08, 0x03, 0x80, 0x03, /* 0x78...0x7f */
177 0x08, 0x02, 0x00, 0x00, 0x08, 0x00, 0x80, 0x03, /* 0x80...0x87 */
178 0x08, 0x08, 0x20, 0x00, 0x00, 0x02, 0x80, 0x04, /* 0x88...0x8f */
179 0x08, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, /* 0x90...0x97 */
180 0x08, 0x02, 0xe0, 0x01, 0x08, 0x00, 0xe0, 0x00, /* 0x98...0x9f */
181 0x08, 0x01, 0xe0, 0x01, 0x08, 0x04, 0xe0, 0x03, /* 0xa0...0xa7 */
182 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8...0xaf */
183 0x20, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0...0xb7 */
184 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, /* 0xb8...0xbf */
185 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, /* 0xc0...0xc7 */
186 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, /* 0xc8...0xcf */
187 0x00, 0x08, 0xe0, 0x00, 0x08, 0x00, 0x00, 0x00, /* 0xd0...0xd7 */
188 0x14, 0x08, 0xe0, 0x02, 0x08, 0xe0, 0x00, 0x08, /* 0xd8...0xdf */
189 0xe0, 0x05, 0x08, 0xe0, 0x06, 0x08, 0xe0, 0x00, /* 0xe0...0xe7 */
190 0x08, 0xe0, 0x00, 0x08, 0xe0, 0x06, 0x06, 0xe0, /* 0xe8...0xef */
191 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0...0xf7 */
192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* 0xf8...0xff */
195 static uint8_t twl4030_48_read(void *opaque, uint8_t addr)
197 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
200 case 0x00: /* VENDOR_ID_LO */
201 case 0x01: /* VENDOR_ID_HI */
202 case 0x02: /* PRODUCT_ID_LO */
203 case 0x03: /* PRODUCT_ID_HI */
204 return s->reg_data[addr];
205 case 0x04: /* FUNC_CTRL */
206 case 0x05: /* FUNC_CRTL_SET */
207 case 0x06: /* FUNC_CRTL_CLR */
208 return s->reg_data[0x04];
209 case 0x07: /* IFC_CTRL */
210 case 0x08: /* IFC_CRTL_SET */
211 case 0x09: /* IFC_CRTL_CLR */
212 return s->reg_data[0x07];
213 case 0xac: /* POWER_CTRL */
214 case 0xad: /* POWER_SET */
215 case 0xae: /* POWER_CLR */
216 return s->reg_data[0xac];
217 case 0xfd: /* PHY_PWR_CTRL */
218 case 0xfe: /* PHY_CLK_CTRL */
219 return s->reg_data[addr];
220 case 0xff: /* PHY_CLK_CTRL */
221 return s->reg_data[0xfe] & 0x1;
224 printf("%s: unknown register %02x pc %x \n", __FUNCTION__, addr,cpu_single_env->regs[15] );
225 //printf("%s: unknown register %02x \n", __FUNCTION__, addr);
232 static void twl4030_48_write(void *opaque, uint8_t addr, uint8_t value)
234 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
237 case 0x04: /* IFC_CTRL */
238 s->reg_data[0x04] = value & 0x80;
240 case 0x05: /* IFC_CRTL_SET */
241 s->reg_data[0x04] = (s->reg_data[0x04] | value) & 0x80;
243 case 0x06: /* IFC_CRTL_CLEAR */
244 s->reg_data[0x04] = (s->reg_data[0x04] & ~value) & 0x80;
246 case 0x07: /* IFC_CTRL */
247 s->reg_data[0x07] = value & 0x61;
249 case 0x08: /* IFC_CRTL_SET */
250 s->reg_data[0x07] = (s->reg_data[0x07] | value) & 0x61;
252 case 0x09: /* IFC_CRTL_CLEAR */
253 s->reg_data[0x07] = (s->reg_data[0x07] & ~value) & 0x61;
255 case 0xac: /* POWER_CTRL */
256 s->reg_data[0xac] = value & 0x20;
258 case 0xad: /* POWER_SET */
259 s->reg_data[0xac] = (s->reg_data[0xac] | value) & 0x20;
261 case 0xae: /* POWER_CLEAR */
262 s->reg_data[0xac] = (s->reg_data[0xac] & ~value) & 0x20;
264 case 0xfd: /* PHY_PWR_CTRL */
265 s->reg_data[addr] = value & 0x1;
267 case 0xfe: /* PHY_CLK_CTRL */
268 s->reg_data[addr] = value & 0x7;
272 printf("%s: unknown register %02x pc %x \n", __FUNCTION__, addr,cpu_single_env->regs[15] );
273 //printf("%s: unknown register %02x \n", __FUNCTION__, addr);
280 static int twl4030_48_tx(i2c_slave *i2c, uint8_t data)
282 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
283 /* Interpret register address byte */
288 twl4030_48_write(s, s->reg++, data);
293 static int twl4030_48_rx(i2c_slave *i2c)
295 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
297 return twl4030_48_read(s, s->reg++);
300 static void twl4030_48_reset(i2c_slave *i2c)
302 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
304 memcpy(s->reg_data, addr_48_reset_values, 256);
307 static void twl4030_48_event(i2c_slave *i2c, enum i2c_event event)
309 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
311 if (event == I2C_START_SEND)
315 static uint8_t twl4030_49_read(void *opaque, uint8_t addr)
317 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
320 case 0x98: /* GPIO_DATAIN1 */
321 case 0x99: /* GPIO_DATAIN2 */
322 case 0x9a: /* GPIO_DATAIN3 */
323 case 0x9b: /* GPIO_DATADIR1 */
324 case 0x9c: /* GPIO_DATADIR2 */
325 case 0x9d: /* GPIO_DATADIR3 */
326 case 0xb1: /* GPIO_ISR1A */
327 case 0xb2: /* GPIO_ISR2A */
328 case 0xb3: /* GPIO_ISR3A */
329 case 0xc0: /* GPIO_EDR1 */
330 case 0xc1: /* GPIO_EDR2 */
331 case 0xc2: /* GPIO_EDR3 */
332 case 0xc3: /* GPIO_EDR4 */
333 case 0xc4: /* GPIO_EDR5 */
334 return s->reg_data[addr];
337 fprintf(stderr, "%s: unknown register %02x pc %x\n",
338 __FUNCTION__, addr,cpu_single_env->regs[15]);
344 static void twl4030_49_write(void *opaque, uint8_t addr, uint8_t value)
346 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
349 case 0x9b: /* GPIODATADIR1 */
350 case 0x9c: /* GPIODATADIR2 */
351 case 0x9d: /* GPIODATADIR3 */
352 case 0x9e: /* GPIODATAOUT1 */
353 case 0x9f: /* GPIODATAOUT2 */
354 case 0xa0: /* GPIODATAOUT3 */
355 case 0xa1: /* CLEARGPIODATAOUT1 */
356 case 0xa2: /* CLEARGPIODATAOUT2 */
357 case 0xa3: /* CLEARGPIODATAOUT3 */
358 case 0xa4: /* SETGPIODATAOUT1 */
359 case 0xa5: /* SETGPIODATAOUT2 */
360 case 0xa6: /* SETGPIODATAOUT3 */
361 case 0xa7: /* GPIO_DEBEN1 */
362 case 0xa8: /* GPIO_DEBEN2 */
363 case 0xa9: /* GPIO_DEBEN3 */
364 case 0xaa: /* GPIO_CTRL */
365 case 0xab: /* GPIOPUPDCTR1 */
366 case 0xac: /* GPIOPUPDCTR2 */
367 case 0xad: /* GPIOPUPDCTR3 */
368 case 0xae: /* GPIOPUPDCTR4 */
369 s->reg_data[addr] = value;
371 case 0xaf: /* GPIOPUPDCTR5 */
372 s->reg_data[addr] = value & 0x0f;
374 case 0xb4: /* GPIO_IMR1A */
375 case 0xb5: /* GPIO_IMR2A */
376 s->reg_data[addr] = value;
378 case 0xb6: /* GPIO_IMR3A */
379 s->reg_data[addr] = value & 0x03;
381 case 0xc0: /* GPIO_EDR1 */
382 case 0xc1: /* GPIO_EDR2 */
383 case 0xc2: /* GPIO_EDR3 */
384 case 0xc3: /* GPIO_EDR4 */
385 case 0xc4: /* GPIO_EDR5 */
386 s->reg_data[addr] = value;
388 case 0xc5: /* GPIO_SIH_CTRL */
389 s->reg_data[addr] = value & 0x07;
393 printf("%s: unknown register %02x pc %x \n", __FUNCTION__, addr,
394 cpu_single_env->regs[15]);
395 //printf("%s: unknown register %02x \n", __FUNCTION__, addr);
403 static int twl4030_49_tx(i2c_slave *i2c, uint8_t data)
405 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
406 /* Interpret register address byte */
411 twl4030_49_write(s, s->reg++, data);
416 static int twl4030_49_rx(i2c_slave *i2c)
418 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
420 return twl4030_49_read(s, s->reg++);
423 static void twl4030_49_reset(i2c_slave *i2c)
425 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
427 memcpy(s->reg_data, addr_49_reset_values, 256);
430 static void twl4030_49_event(i2c_slave *i2c, enum i2c_event event)
432 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
434 if (event == I2C_START_SEND)
438 static uint8_t twl4030_4a_read(void *opaque, uint8_t addr)
440 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
443 case 0x61: /* MADC_ISR1 */
444 case 0xb9: /* BCIISR1A */
445 case 0xba: /* BCIISR2A */
446 case 0xe3: /* KEYP_ISR1 */
447 case 0xee: /* LEDEN */
448 return s->reg_data[addr];
451 printf("%s: unknown register %02x pc %x \n", __FUNCTION__, addr,cpu_single_env->regs[15] );
458 static void twl4030_4a_write(void *opaque, uint8_t addr, uint8_t value)
460 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
463 case 0x61: /* MADC_ISR1 */
464 s->reg_data[value] &= ~(value & 0x0f);
466 case 0x62: /* MADC_IMR1 */
467 s->reg_data[value] = value & 0x0f;
469 case 0xb9: /* BCIISR1A */
470 s->reg_data[value] &= ~value;
472 case 0xba: /* BCIISR2A */
473 s->reg_data[value] &= ~(value & 0x0f);
475 case 0xbb: /* BCIIMR1A */
476 s->reg_data[addr] = value;
478 case 0xbc: /* BCIIMR2A */
479 s->reg_data[addr] = value & 0x0f;
481 case 0xe4: /* KEYP_IMR1 */
482 s->reg_data[addr] = value & 0x0f;
484 case 0xe9: /* KEYP_SIH_CTRL */
485 s->reg_data[addr] = value & 0x07;
487 case 0xee: /* LEDEN */
488 s->reg_data[addr] = value;
490 fprintf(stderr, "%s: LEDA power=%s/enable=%s, LEDB power=%s/enable=%s\n", __FUNCTION__,
491 value & 0x10 ? "on" : "off", value & 0x01 ? "yes" : "no",
492 value & 0x20 ? "on" : "off", value & 0x02 ? "yes" : "no");
495 case 0xef: /* PWMAON */
496 s->reg_data[addr] = value;
498 case 0xf0: /* PWMAOFF */
499 s->reg_data[addr] = value & 0x7f;
503 printf("%s: unknown register %02x pc %x \n", __FUNCTION__, addr,cpu_single_env->regs[15] );
510 static int twl4030_4a_tx(i2c_slave *i2c, uint8_t data)
512 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
513 /* Interpret register address byte */
518 twl4030_4a_write(s, s->reg++, data);
523 static int twl4030_4a_rx(i2c_slave *i2c)
525 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
527 return twl4030_4a_read(s, s->reg++);
530 static void twl4030_4a_reset(i2c_slave *i2c)
532 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
534 memcpy(s->reg_data, addr_4a_reset_values, 256);
537 static void twl4030_4a_event(i2c_slave *i2c, enum i2c_event event)
539 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
541 if (event == I2C_START_SEND)
545 static uint8_t twl4030_4b_read(void *opaque, uint8_t addr)
547 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
567 case 0x2d: /*RTC end */
568 case 0x2e: /* PWR_ISR1 */
569 case 0x33: /* PWR_EDR1 */
570 case 0x34: /* PWR_EDR2 */
571 return s->reg_data[addr];
572 case 0x45: /* STS_HW_CONDITIONS - USB plugged, no VBUS -> host usb */
576 printf("%s: unknown register %02x pc %x \n", __FUNCTION__, addr,cpu_single_env->regs[15] );
577 //printf("%s: unknown register %02x \n", __FUNCTION__, addr);
585 static void twl4030_4b_write(void *opaque, uint8_t addr, uint8_t value)
587 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
588 uint8_t seq_addr, seq_sub;
591 case 0x1c: /* SECONDS_REG */
592 case 0x1d: /* MINUTES_REG */
593 case 0x23: /* ALARM_SECONDS_REG */
594 case 0x24: /* ALARM_MINUTES_REG */
595 s->reg_data[addr] = value & 0x7f;
597 case 0x1e: /* HOURS_REG */
598 case 0x25: /* ALARM_HOURS_REG */
599 s->reg_data[addr] = value & 0xbf;
601 case 0x1f: /* DAYS_REG */
602 case 0x26: /* ALARM_DAYS_REG */
603 s->reg_data[addr] = value & 0x3f;
605 case 0x20: /* MONTHS_REG */
606 case 0x27: /* ALARM_MONTHS_REG */
607 s->reg_data[addr] = value & 0x1f;
609 case 0x21: /* YEARS_REG */
610 case 0x28: /* ALARM_YEARS_REG */
611 s->reg_data[addr] = value;
613 case 0x22: /* WEEKS_REG */
614 s->reg_data[addr] = value & 0x07;
616 case 0x29: /* RTC_CTRL_REG */
617 s->reg_data[addr] = value & 0x7f;
619 case 0x2a: /* RTC_STATUS_REG */
620 s->reg_data[addr] = value & 0xfe;
622 case 0x2b: /* RTC_INTERRUPTS_REG */
623 s->reg_data[addr] = value & 0x0f;
625 case 0x2c: /* RTC_COMP_LSB_REG */
626 case 0x2d: /* RTC_COMP_MSB_REG */
627 s->reg_data[addr] = value;
629 case 0x33: /* PWR_EDR1 */
630 case 0x34: /* PWR_EDR2 */
631 s->reg_data[addr] = value;
633 case 0x46: /* P1_SW_EVENTS */
634 case 0x47: /* P2_SW_EVENTS */
635 case 0x48: /* P3_SW_EVENTS */
636 s->reg_data[addr] = value & 0x78;
638 case 0x52: /* SEQ_ADD_W2P */
639 case 0x53: /* SEQ_ADD_P2A */
640 case 0x54: /* SEQ_ADD_A2W */
641 case 0x55: /* SEQ_ADD_A2S */
642 case 0x56: /* SEQ_ADD_S2A12 */
643 case 0x57: /* SEQ_ADD_S2A3 */
644 case 0x58: /* SEQ_ADD_WARM */
645 if (s->twl4030->key_cfg)
646 s->reg_data[addr] = value & 0x3f;
648 case 0x59: /* MEMORY_ADDRESS */
649 if (s->twl4030->key_cfg)
650 s->reg_data[addr] = value;
652 case 0x5a: /* MEMORY_DATA */
653 if (s->twl4030->key_cfg) {
654 s->reg_data[addr] = value;
655 seq_addr = s->reg_data[0x59];
656 seq_sub = seq_addr & 3;
658 if ((seq_addr >= 0x2b && seq_addr <= 0x3e) || (seq_addr <= 0x0e && seq_sub == 3))
659 s->twl4030->seq_mem[seq_addr][seq_sub] = value;
661 s->reg_data[0x59]++; /* TODO: check if autoincrement is write-protected as well */
663 case 0x7a: /* VAUX3_DEV_GRP */
664 case 0x82: /* VMMC1_DEV_GRP */
665 case 0x8e: /* VPLL2_DEV_GRP */
666 case 0x96: /* VDAC_DEV_GRP */
667 case 0xcc: /* VUSB1V5_DEV_GRP */
668 case 0xcf: /* VUSB1V8_DEV_GRP */
669 case 0xd2: /* VUSB3V1_DEV_GRP */
670 case 0xe6: /* HFCLKOUT_DEV_GRP */
671 s->reg_data[addr] = (s->reg_data[addr] & 0x0f) | (value & 0xf0);
673 case 0x2f: /* PWR_IMR1 */
674 s->reg_data[addr] = value;
676 case 0x35: /* PWR_SIH_CTRL */
677 s->reg_data[addr] = value & 0x07;
679 case 0x3b: /* CFG_BOOT */
680 if (s->twl4030->key_cfg)
681 s->reg_data[addr] = (s->reg_data[addr] & 0x70) | (value & 0x8f);
683 case 0x44: /* PROTECT_KEY */
684 s->twl4030->key_cfg = 0;
685 s->twl4030->key_tst = 0;
688 if (s->reg_data[addr] == 0xC0)
689 s->twl4030->key_cfg = 1;
692 if (s->reg_data[addr] == 0x0E)
693 s->twl4030->key_tst = 1;
696 if (s->reg_data[addr] == 0xCE) {
697 s->twl4030->key_cfg = 1;
698 s->twl4030->key_tst = 1;
704 s->reg_data[addr] = value;
706 case 0x7d: /* VAUX3_DEDICATED */
707 if (s->twl4030->key_tst)
708 s->reg_data[addr] = value & 0x77;
710 s->reg_data[addr] = (s->reg_data[addr] & 0x70) | (value & 0x07);
712 case 0x85: /* VMMC1_DEDICATED */
713 case 0x99: /* VDAC_DEDICATED */
714 if (s->twl4030->key_tst)
715 s->reg_data[addr] = value & 0x73;
717 s->reg_data[addr] = (s->reg_data[addr] & 0x70) | (value & 0x03);
719 case 0x91: /* VPLL2_DEDICATED */
720 if (s->twl4030->key_tst)
721 s->reg_data[addr] = value & 0x7f;
723 s->reg_data[addr] = (s->reg_data[addr] & 0x70) | (value & 0x0f);
725 case 0xcd: /* VUSB1V5_TYPE */
726 case 0xd0: /* VUSB1V8_TYPE */
727 case 0xd3: /* VUSB3V1_TYPE */
728 s->reg_data[addr] = value & 0x1f;
730 case 0xd8: /* VUSB_DEDICATED1 */
731 s->reg_data[addr] = value & 0x1f;
733 case 0xd9: /* VUSB_DEDICATED2 */
734 s->reg_data[addr] = value & 0x08;
738 fprintf(stderr, "%s: unknown register %02x value %0x pc %x \n", __FUNCTION__,
739 addr, value, cpu_single_env->regs[15]);
745 static int twl4030_4b_tx(i2c_slave *i2c, uint8_t data)
747 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
748 /* Interpret register address byte */
753 twl4030_4b_write(s, s->reg++, data);
758 static int twl4030_4b_rx(i2c_slave *i2c)
760 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
762 return twl4030_4b_read(s, s->reg++);
765 static void twl4030_4b_reset(i2c_slave *i2c)
767 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
769 memcpy(s->reg_data, addr_4b_reset_values, 256);
770 s->twl4030->key_cfg = 0;
771 s->twl4030->key_tst = 0;
774 static void twl4030_4b_event(i2c_slave *i2c, enum i2c_event event)
776 struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
778 if (event == I2C_START_SEND)
782 struct twl4030_s *twl4030_init(i2c_bus *bus, qemu_irq irq)
786 struct twl4030_s *s = (struct twl4030_s *) qemu_mallocz(sizeof(*s));
790 fprintf(stderr,"can not alloc memory space for twl4030_s \n");
795 s->i2c[i]=(struct twl4030_i2c_s *)i2c_slave_init(bus, 0, sizeof(struct twl4030_i2c_s));
796 s->i2c[i]->irq = irq;
797 s->i2c[i]->twl4030 = s;
799 s->i2c[0]->i2c.event = twl4030_48_event;
800 s->i2c[0]->i2c.recv = twl4030_48_rx;
801 s->i2c[0]->i2c.send = twl4030_48_tx;
802 twl4030_48_reset(&s->i2c[0]->i2c);
803 i2c_set_slave_address((i2c_slave *)&s->i2c[0]->i2c,0x48);
805 s->i2c[1]->i2c.event = twl4030_49_event;
806 s->i2c[1]->i2c.recv = twl4030_49_rx;
807 s->i2c[1]->i2c.send = twl4030_49_tx;
808 twl4030_49_reset(&s->i2c[1]->i2c);
809 i2c_set_slave_address((i2c_slave *)&s->i2c[1]->i2c,0x49);
811 s->i2c[2]->i2c.event = twl4030_4a_event;
812 s->i2c[2]->i2c.recv = twl4030_4a_rx;
813 s->i2c[2]->i2c.send = twl4030_4a_tx;
814 twl4030_4a_reset(&s->i2c[2]->i2c);
815 i2c_set_slave_address((i2c_slave *)&s->i2c[2]->i2c,0x4a);
817 s->i2c[3]->i2c.event = twl4030_4b_event;
818 s->i2c[3]->i2c.recv = twl4030_4b_rx;
819 s->i2c[3]->i2c.send = twl4030_4b_tx;
820 twl4030_4b_reset(&s->i2c[3]->i2c);
821 i2c_set_slave_address((i2c_slave *)&s->i2c[3]->i2c,0x4b);
825 //register_savevm("menelaus", -1, 0, menelaus_save, menelaus_load, s);
830 static uint8_t twl4030_read(void *opaque, uint8_t addr)
832 // struct twl4030_s *s = (struct twl4030_s *) opaque;
835 printf("twl4030_read addr %x\n",addr);
841 printf("%s: unknown register %02x\n", __FUNCTION__, addr);
849 static void twl4030_write(void *opaque, uint8_t addr, uint8_t value)
851 // struct twl4030_s *s = (struct twl4030_s *) opaque;
856 printf("twl4030_write addr %x value %x \n",addr,value);
866 printf("%s: unknown register %02x\n", __FUNCTION__, addr);
874 static int twl4030_tx(i2c_slave *i2c, uint8_t data)
876 struct twl4030_s *s = (struct twl4030_s *) i2c;
877 /* Interpret register address byte */
882 twl4030_write(s, s->reg ++, data);
887 static int twl4030_rx(i2c_slave *i2c)
889 struct twl4030_s *s = (struct twl4030_s *) i2c;
891 return twl4030_read(s, s->reg ++);
894 static void twl4030_reset(i2c_slave *i2c)
896 struct twl4030_s *s = (struct twl4030_s *) i2c;
900 static void twl4030_event(i2c_slave *i2c, enum i2c_event event)
902 struct twl4030_s *s = (struct twl4030_s *) i2c;
904 if (event == I2C_START_SEND)
908 i2c_slave *twl4030_init(i2c_bus *bus, qemu_irq irq)
910 struct twl4030_s *s = (struct twl4030_s *)
911 i2c_slave_init(bus, 0, sizeof(struct twl4030_s));
913 s->i2c.event = twl4030_event;
914 s->i2c.recv = twl4030_rx;
915 s->i2c.send = twl4030_tx;
918 //s->rtc.hz_tm = qemu_new_timer(rt_clock, menelaus_rtc_hz, s);
919 //s->in = qemu_allocate_irqs(menelaus_gpio_set, s, 3);
920 //s->pwrbtn = qemu_allocate_irqs(menelaus_pwrbtn_set, s, 1)[0];
922 twl4030_reset(&s->i2c);
924 //register_savevm("menelaus", -1, 0, menelaus_save, menelaus_load, s);