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"
|
|
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 }
|