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