comparison driver/pt1_i2c.c @ 0:67e8eca28a80

initial import
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Mon, 16 Feb 2009 15:41:49 +0900
parents
children 517e61637f7b
comparison
equal deleted inserted replaced
-1:000000000000 0:67e8eca28a80
1 /***************************************************************************/
2 /* I2C情報作成 */
3 /***************************************************************************/
4 #include <linux/module.h>
5 #include <linux/kernel.h>
6 #include <linux/errno.h>
7 #include <linux/pci.h>
8 #include <linux/init.h>
9 #include <linux/interrupt.h>
10 #include <linux/mutex.h>
11
12 #include <asm/system.h>
13 #include <asm/io.h>
14 #include <asm/irq.h>
15 #include <asm/uaccess.h>
16
17 #include "pt1_com.h"
18 #include "pt1_i2c.h"
19 #include "pt1_pci.h"
20
21 #define PROGRAM_ADDRESS 1024
22 static int state = STATE_STOP ;
23 static int i2c_lock(void __iomem *, __u32, __u32, __u32);
24 static int i2c_lock_one(void __iomem *, __u32, __u32);
25 static int i2c_unlock(void __iomem *, int);
26 static void writebits(void __iomem *, __u32 *, __u32, __u32);
27 static void begin_i2c(void __iomem *, __u32 *, __u32 *);
28 static void start_i2c(void __iomem *, __u32 *, __u32 *, __u32);
29 static void stop_i2c(void __iomem *, __u32 *, __u32 *, __u32, __u32);
30
31
32 // PCIに書き込むI2Cデータ生成
33 void makei2c(void __iomem *regs, __u32 base_addr, __u32 i2caddr, __u32 writemode, __u32 data_en, __u32 clock, __u32 busy)
34 {
35
36 __u32 val ;
37 val = ((base_addr << I2C_DATA) | (writemode << I2C_WRIET_MODE) |
38 ( data_en << I2C_DATA_EN) |
39 (clock << I2C_CLOCK) | (busy << I2C_BUSY) | i2caddr) ;
40 writel(val, regs + FIFO_ADDR);
41 }
42
43 int xc3s_init(void __iomem *regs)
44 {
45
46 __u32 val ;
47 int lp ;
48 int rc ;
49
50 /*
51 val = (1 << 19) | (1 << 27) | (1 << 16) | (1 << 24) | (1 << 17) | (1 << 25);
52 writel(WRITE_PULSE, regs);
53 BIT 19, 19+8 ON
54 BIT 16, 16+8 ON
55 BIT 17, 17+8 ON
56 */
57 // XC3S初期化
58 for(lp = 0 ; lp < PROGRAM_ADDRESS ; lp++){
59 makei2c(regs, lp, 0, READ_EN, DATA_DIS, CLOCK_DIS, BUSY_DIS);
60 }
61 // XC3S 初期化待ち (512 PCI Clocks)
62 for(lp = 0 ; lp < XC3S_PCI_CLOCK ; lp++){
63 makei2c(regs, 0, 0, READ_EN, DATA_DIS, CLOCK_DIS, BUSY_DIS);
64 }
65 // プロテクト解除
66 // これは何を意図しているんだろう?
67 // 元コードが良く判らない
68 for(lp = 0 ; lp < 57 ; lp++){
69 val = readl(regs);
70 if(val & I2C_READ_SYNC){
71 break ;
72 }
73 writel(WRITE_PULSE, regs);
74 }
75
76 for(lp = 0 ; lp < 57 ; lp++){
77 val = readl(regs);
78 if(val & READ_DATA){
79 break ;
80 }
81 writel(WRITE_PULSE, regs);
82 }
83
84 // UNLOCK
85 rc = i2c_unlock(regs, READ_UNLOCK);
86 if(rc < 0){
87 return rc ;
88 }
89
90 // Enable PCI
91 rc =i2c_lock(regs, (WRITE_PCI_RESET | WRITE_PCI_RESET_), WRITE_PCI_RESET_, PCI_LOCKED);
92 if(rc < 0){
93 return -EIO ;
94 }
95
96 // Enable RAM
97 rc =i2c_lock(regs, (WRITE_RAM_RESET | WRITE_RAM_RESET_), WRITE_RAM_RESET_, RAM_LOCKED);
98 if(rc){
99 return -EIO ;
100 }
101 for(lp = 0 ; lp < XC3S_PCI_CLOCK ; lp++){
102 rc = i2c_lock_one(regs, WRITE_RAM_ENABLE, RAM_SHIFT);
103 if(rc < 0){
104 printk(KERN_ERR "PT1:LOCK FALUT\n");
105 return rc ;
106 }
107 }
108
109 // ストリームごとの転送制御(OFF)
110 for(lp = 0 ; lp < MAX_CHANNEL ; lp++){
111 SetStream(regs, lp, 0);
112 SetStream(regs, lp, 0);
113 }
114 return 0 ;
115 }
116 //
117 //
118 //BIT 0. 1 : Tuner番号 (Enable/Disable)
119 //BIT 8. 9 : Tuner番号
120 //
121 //
122 void SetStream(void __iomem *regs, __u32 channel, __u32 enable)
123 {
124 __u32 val ;
125
126 val = (1 << (8 + channel));
127 if(enable){
128 val |= (1 << channel);
129 }
130 writel(val, regs + TS_TEST_ENABLE_ADDR);
131 }
132
133 static int i2c_lock(void __iomem *regs, __u32 firstval, __u32 secondval, __u32 lockval)
134 {
135
136 __u32 val ;
137 int lp ;
138
139 writel(firstval, regs);
140 writel(secondval, regs);
141
142 // RAMがロックされた?
143 for(lp = 0 ; lp < XC3S_PCI_CLOCK ; lp++){
144 val = readl(regs);
145 if((val & lockval)){
146 return 0 ;
147 }
148 schedule_timeout_interruptible(msecs_to_jiffies(1));
149 }
150 return -EIO ;
151 }
152
153 static int i2c_lock_one(void __iomem *regs, __u32 firstval, __u32 lockval)
154 {
155
156 __u32 val ;
157 __u32 val2 ;
158 int lp ;
159
160 val = (readl(regs) & lockval);
161 writel(firstval, regs);
162
163 // RAMがロックされた?
164 for(lp = 0 ; lp < 10 ; lp++){
165 for(lp = 0 ; lp < 1024 ; lp++){
166 val2 = readl(regs);
167 // 最初に取得したデータと逆になればOK
168 if(((val2 & lockval) != val)){
169 return 0 ;
170 }
171 }
172 schedule_timeout_interruptible(msecs_to_jiffies(1));
173 }
174 printk(KERN_INFO "PT1:Lock Fault(%x:%x)\n", val, val2);
175 return -EIO ;
176 }
177 static int i2c_unlock(void __iomem *regs, int lockval)
178 {
179 int lp ;
180 __u32 val ;
181
182 writel(WRITE_PULSE, regs);
183
184 for(lp = 0 ; lp < 3 ; lp++){
185 val = readl(regs);
186 if((val &lockval)){
187 return 0 ;
188 }
189 schedule_timeout_interruptible(msecs_to_jiffies(1));
190 }
191 return -EIO ;
192 }
193 void blockwrite(void __iomem *regs, WBLOCK *wblock)
194 {
195 int lp ;
196 int bitpos ;
197 __u32 bits ;
198 __u32 old_bits = 1 ;
199 __u32 address = 0;
200 __u32 clock = 0;
201
202 begin_i2c(regs, &address, &clock);
203 if(state == STATE_STOP){
204 start_i2c(regs, &address, &clock, old_bits);
205 old_bits = 0 ;
206 stop_i2c(regs, &address, &clock, old_bits, FALSE);
207 state = STATE_START ;
208 }
209 old_bits = 1 ;
210 start_i2c(regs, &address, &clock, old_bits);
211 old_bits = 0 ;
212
213 // まずアドレスを書く
214 for(bitpos = 0 ; bitpos < 7 ; bitpos++){
215 bits = ((wblock->addr >> (6 - bitpos)) & 1);
216 writebits(regs, &address, old_bits, bits);
217 old_bits = bits ;
218 }
219 // タイプ:WRT
220 writebits(regs, &address, old_bits, 0);
221 // ACK/NACK用(必ず1)
222 writebits(regs, &address, 0, 1);
223
224 old_bits = 1 ;
225 // 実際のデータを書く
226 for (lp = 0 ; lp < wblock->count ; lp++){
227 for(bitpos = 0 ; bitpos < 8 ; bitpos++){
228 bits = ((wblock->value[lp] >> (7 - bitpos)) & 1);
229 writebits(regs, &address, old_bits, bits);
230 old_bits = bits ;
231 }
232 // ACK/NACK用(必ず1)
233 writebits(regs, &address, old_bits, 1);
234 old_bits = 1 ;
235 }
236
237 // Clock negedge
238 makei2c(regs, address, address + 1, 0, (old_bits ^ 1), 1, 1);
239 clock = TRUE ;
240 address += 1 ;
241 stop_i2c(regs, &address, &clock, old_bits, TRUE);
242
243 }
244
245 void blockread(void __iomem *regs, WBLOCK *wblock, int count)
246 {
247 int lp ;
248 int bitpos ;
249 __u32 bits ;
250 __u32 old_bits = 1 ;
251 __u32 address = 0;
252 __u32 clock = 0;
253
254 begin_i2c(regs, &address, &clock);
255 if(state == STATE_STOP){
256 start_i2c(regs, &address, &clock, old_bits);
257 old_bits = 0 ;
258 stop_i2c(regs, &address, &clock, old_bits, FALSE);
259 state = STATE_START ;
260 }
261 old_bits = 1 ;
262 start_i2c(regs, &address, &clock, old_bits);
263 old_bits = 0 ;
264
265 // まずアドレスを書く
266 for(bitpos = 0 ; bitpos < 7 ; bitpos++){
267 bits = ((wblock->addr >> (6 - bitpos)) & 1);
268 writebits(regs, &address, old_bits, bits);
269 old_bits = bits ;
270 }
271 // タイプ:WRT
272 writebits(regs, &address, old_bits, 0);
273 // ACK/NACK用(必ず1)
274 writebits(regs, &address, 0, 1);
275
276 old_bits = 1 ;
277 // 実際のデータを書く
278 for (lp = 0 ; lp < wblock->count ; lp++){
279 for(bitpos = 0 ; bitpos < 8 ; bitpos++){
280 bits = ((wblock->value[lp] >> (7 - bitpos)) & 1);
281 writebits(regs, &address, old_bits, bits);
282 old_bits = bits ;
283 }
284 // ACK/NACK用(必ず1)
285 writebits(regs, &address, old_bits, 1);
286 old_bits = 1 ;
287 }
288
289 // Clock negedge
290 makei2c(regs, address, address + 1, 0, (old_bits ^ 1), 1, 1);
291 clock = TRUE ;
292 address += 1 ;
293
294 // ここから Read
295 start_i2c(regs, &address, &clock, old_bits);
296 old_bits = 0 ;
297 // まずアドレスを書く
298 for(bitpos = 0 ; bitpos < 7 ; bitpos++){
299 bits = ((wblock->addr >> (6 - bitpos)) & 1);
300 writebits(regs, &address, old_bits, bits);
301 old_bits = bits ;
302 }
303 // タイプ:RD
304 writebits(regs, &address, old_bits, 1);
305 // ACK/NACK用(必ず1)
306 writebits(regs, &address, 1, 1);
307
308 old_bits = 1 ;
309 // 実際のデータを書く
310 for (lp = 0 ; lp < count ; lp++){
311 for(bitpos = 0 ; bitpos < 8 ; bitpos++){
312 writebits(regs, &address, old_bits, 1);
313 // Read Mode Set
314 makei2c(regs, address, address + 1, 1, 0, 0, 1);
315 address += 1 ;
316 old_bits = 1 ;
317 }
318 if(lp >= (count - 1)){
319 // ACK/NACK用(必ず1)
320 writebits(regs, &address, old_bits, 1);
321 old_bits = 0 ;
322 }else{
323 // ACK/NACK用(必ず1)
324 writebits(regs, &address, old_bits, 0);
325 old_bits = 1 ;
326 }
327 }
328
329 // Clock negedge
330 makei2c(regs, address, address + 1, 0, 0, 1, 1);
331 clock = TRUE ;
332 address += 1 ;
333 old_bits = 1 ;
334 stop_i2c(regs, &address, &clock, old_bits, TRUE);
335
336 }
337 static void writebits(void __iomem *regs, __u32 *address, __u32 old_bits, __u32 bits)
338 {
339 // CLOCK UP
340 makei2c(regs, *address, *address + 1, 0, (old_bits ^ 1), 1, 1);
341 *address += 1 ;
342
343 // CLOCK UP
344 makei2c(regs, *address, *address + 1, 0, (bits ^ 1), 1, 1);
345 *address += 1 ;
346
347 // CLOCK DOWN
348 makei2c(regs, *address, *address + 1, 0, (bits ^ 1), 0, 1);
349 *address += 1 ;
350
351 }
352 static void begin_i2c(void __iomem *regs, __u32 *address, __u32 *clock)
353 {
354 // bus FREE
355 makei2c(regs, *address, *address, 0, 0, 0, 0);
356 *address += 1 ;
357
358 // bus busy
359 makei2c(regs, *address, *address + 1, 0, 0, 0, 1);
360 *address += 1 ;
361 *clock = FALSE ;
362 }
363
364 static void start_i2c(void __iomem *regs, __u32 *address, __u32 *clock, __u32 data)
365 {
366 // データが残っていなければデータを下げる
367 if(!data){
368 // CLOCKがあればCLOCKを下げる
369 if(*clock != TRUE){
370 *clock = TRUE ;
371 makei2c(regs, *address, *address + 1, 0, 1, 1, 1);
372 *address += 1 ;
373 }
374 makei2c(regs, *address, *address + 1, 0, 0, 1, 1);
375 *address += 1 ;
376 }
377
378 if(*clock != FALSE){
379 *clock = FALSE ;
380 makei2c(regs, *address, *address + 1, 0, 0, 0, 1);
381 *address += 1;
382 }
383 makei2c(regs, *address, *address + 1, 0, 1, 0, 1);
384 *address += 1;
385 *clock = FALSE ;
386 }
387
388 static void stop_i2c(void __iomem *regs, __u32 *address, __u32 *clock, __u32 data, __u32 end)
389 {
390 // データが残っていて
391 if(data){
392 // クロックがあれば
393 if(*clock != TRUE){
394 *clock = TRUE ;
395 makei2c(regs, *address, *address + 1, 0, 0, 1, 1);
396 *address += 1;
397 }
398 makei2c(regs, *address, *address + 1, 0, 1, 1, 1);
399 *address += 1 ;
400 }
401 // クロックが落ちていれば
402 if(*clock){
403 *clock = FALSE ;
404 makei2c(regs, *address, *address + 1, 0, 1, 0, 1);
405 *address += 1 ;
406 }
407
408 if(end){
409 makei2c(regs, *address, 0, 0, 0, 0, 1);
410 }else{
411 makei2c(regs, *address, *address + 1, 0, 0, 0, 1);
412 *address += 1 ;
413 }
414 }
415
416 void i2c_write(void __iomem *regs, struct mutex *lock, WBLOCK *wblock)
417 {
418
419 int lp;
420 __u32 val ;
421
422 // ロックする
423 mutex_lock(lock);
424 #if 0
425 printk(KERN_INFO "Addr=%x(%d)\n", wblock->addr, wblock->count);
426 for(lp = 0 ; lp < wblock->count ; lp++){
427 printk(KERN_INFO "%x\n", wblock->value[lp]);
428 }
429 printk(KERN_INFO "\n");
430 #endif
431
432 blockwrite(regs, wblock);
433 writel(FIFO_GO, regs + FIFO_GO_ADDR);
434 //とりあえずロックしないように。
435 for(lp = 0 ; lp < 100 ; lp++){
436 val = readl(regs + FIFO_RESULT_ADDR);
437 if(!(val & FIFO_DONE)){
438 break ;
439 }
440 schedule_timeout_interruptible(msecs_to_jiffies(1));
441 }
442 mutex_unlock(lock);
443 }
444
445 __u32 i2c_read(void __iomem *regs, struct mutex *lock, WBLOCK *wblock, int size)
446 {
447
448 int lp;
449 __u32 val ;
450
451 // ロックする
452 mutex_lock(lock);
453 #if 0
454 printk(KERN_INFO "Addr=%x:%d:%d\n", wblock->addr, wblock->count, size);
455 for(lp = 0 ; lp < wblock->count ; lp++){
456 printk(KERN_INFO "%x\n", wblock->value[lp]);
457 }
458 printk(KERN_INFO "\n");
459 #endif
460 blockread(regs, wblock, size);
461
462 writel(FIFO_GO, regs + FIFO_GO_ADDR);
463
464 for(lp = 0 ; lp < 100 ; lp++){
465 schedule_timeout_interruptible(msecs_to_jiffies(1));
466 val = readl(regs + FIFO_RESULT_ADDR);
467 if(!(val & FIFO_DONE)){
468 break ;
469 }
470 }
471
472 val = readl(regs + I2C_RESULT_ADDR);
473 mutex_unlock(lock);
474 return val ;
475 }