add missing dependency
[openwrt.git] / package / broadcom-mmc / src / mmc.c
1 #include <linux/delay.h>
2 #include <linux/timer.h>
3
4 #include <linux/module.h>
5 #include <linux/mm.h>
6 #include <linux/init.h>
7 #include <linux/fs.h>
8 #include <linux/blkpg.h>
9 #include <linux/hdreg.h>
10 #include <linux/major.h>
11 #include <asm/uaccess.h>
12 #include <asm/io.h>
13
14 #define DEVICE_NAME "mmc"
15 #define DEVICE_NR(device) (MINOR(device))
16 #define DEVICE_ON(device)
17 #define DEVICE_OFF(device)
18 #define MAJOR_NR 121
19
20 #include <linux/blk.h>
21
22 MODULE_AUTHOR("Madsuk/Rohde");
23 MODULE_DESCRIPTION("Driver MMC/SD-Cards");
24 MODULE_SUPPORTED_DEVICE("WRT54G");
25 MODULE_LICENSE("GPL");
26
27 #define SD_DI 0x20
28 #define SD_DO 0x10
29 #define SD_CLK 0x08
30 #define SD_CS 0x80
31
32 /* we have only one device */
33 static int hd_sizes[1<<6];
34 static int hd_blocksizes[1<<6];
35 static int hd_hardsectsizes[1<<6];
36 static int hd_maxsect[1<<6];
37 static struct hd_struct hd[1<<6];
38
39 static struct timer_list mmc_timer;
40 static int mmc_media_detect = 0;
41 static int mmc_media_changed = 1;
42
43 typedef unsigned int uint32;
44
45 static unsigned char port_state = 0x00;
46 static volatile uint32 *gpioaddr_input = (uint32 *)0xb8000060;
47 static volatile uint32 *gpioaddr_output = (uint32 *)0xb8000064;
48 static volatile uint32 *gpioaddr_enable = (uint32 *)0xb8000068;
49 static volatile uint32 *gpioaddr_control = (uint32 *)0xb800006c;
50
51 static void mmc_spi_cs_low(void)
52 {
53 port_state &= ~(SD_CS);
54 *gpioaddr_output = port_state;
55 }
56
57 static void mmc_spi_cs_high(void)
58 {
59 port_state |= SD_CS;
60 *gpioaddr_output = port_state;
61 }
62
63 static unsigned char mmc_spi_io(unsigned char data_out)
64 {
65 int i;
66 unsigned char result = 0, tmp_data = 0;
67
68 for(i=0; i<8; i++) {
69 if(data_out & (0x01 << (7-i)))
70 port_state |= SD_DI;
71 else
72 port_state &= ~SD_DI;
73
74 *gpioaddr_output = port_state;
75 port_state |= SD_CLK;
76 *gpioaddr_output = port_state;
77
78 tmp_data = *gpioaddr_input;
79
80 port_state &= ~SD_CLK;
81 *gpioaddr_output = port_state;
82
83 result <<= 1;
84
85 if(tmp_data & SD_DO)
86 result |= 1;
87 }
88
89 return(result);
90 }
91
92 static int mmc_write_block(unsigned int dest_addr, unsigned char *data)
93 {
94 unsigned int address;
95 unsigned char r = 0;
96 unsigned char ab0, ab1, ab2, ab3;
97 int i;
98
99 address = dest_addr;
100
101 ab3 = 0xff & (address >> 24);
102 ab2 = 0xff & (address >> 16);
103 ab1 = 0xff & (address >> 8);
104 ab0 = 0xff & address;
105 mmc_spi_cs_low();
106 for (i = 0; i < 4; i++) mmc_spi_io(0xff);
107 mmc_spi_io(0x58);
108 mmc_spi_io(ab3); /* msb */
109 mmc_spi_io(ab2);
110 mmc_spi_io(ab1);
111 mmc_spi_io(ab0); /* lsb */
112 mmc_spi_io(0xff);
113 for (i = 0; i < 8; i++)
114 {
115 r = mmc_spi_io(0xff);
116 if (r == 0x00) break;
117 }
118 if (r != 0x00)
119 {
120 mmc_spi_cs_high();
121 mmc_spi_io(0xff);
122 return(1);
123 }
124
125 mmc_spi_io(0xfe);
126 for (i = 0; i < 512; i++) mmc_spi_io(data[i]);
127 for (i = 0; i < 2; i++) mmc_spi_io(0xff);
128
129 for (i = 0; i < 1000000; i++)
130 {
131 r = mmc_spi_io(0xff);
132 if (r == 0xff) break;
133 }
134 if (r != 0xff)
135 {
136 mmc_spi_cs_high();
137 mmc_spi_io(0xff);
138 return(3);
139 }
140 mmc_spi_cs_high();
141 mmc_spi_io(0xff);
142 return(0);
143 }
144
145 static int mmc_read_block(unsigned char *data, unsigned int src_addr)
146 {
147 unsigned int address;
148 unsigned char r = 0;
149 unsigned char ab0, ab1, ab2, ab3;
150 int i;
151
152 address = src_addr;
153
154 ab3 = 0xff & (address >> 24);
155 ab2 = 0xff & (address >> 16);
156 ab1 = 0xff & (address >> 8);
157 ab0 = 0xff & address;
158
159 mmc_spi_cs_low();
160 for (i = 0; i < 4; i++) mmc_spi_io(0xff);
161 mmc_spi_io(0x51);
162 mmc_spi_io(ab3); /* msb */
163 mmc_spi_io(ab2);
164 mmc_spi_io(ab1);
165 mmc_spi_io(ab0); /* lsb */
166
167 mmc_spi_io(0xff);
168 for (i = 0; i < 8; i++)
169 {
170 r = mmc_spi_io(0xff);
171 if (r == 0x00) break;
172 }
173 if (r != 0x00)
174 {
175 mmc_spi_cs_high();
176 mmc_spi_io(0xff);
177 return(1);
178 }
179 for (i = 0; i < 100000; i++)
180 {
181 r = mmc_spi_io(0xff);
182 if (r == 0xfe) break;
183 }
184 if (r != 0xfe)
185 {
186 mmc_spi_cs_high();
187 mmc_spi_io(0xff);
188 return(2);
189 }
190 for (i = 0; i < 512; i++)
191 {
192 r = mmc_spi_io(0xff);
193 data[i] = r;
194 }
195 for (i = 0; i < 2; i++)
196 {
197 r = mmc_spi_io(0xff);
198 }
199 mmc_spi_cs_high();
200 mmc_spi_io(0xff);
201
202 return(0);
203 }
204
205 static void mmc_request(request_queue_t *q)
206 {
207 unsigned int mmc_address;
208 unsigned char *buffer_address;
209 int nr_sectors;
210 int i;
211 int cmd;
212 int rc, code;
213
214 (void)q;
215 while (1)
216 {
217 code = 1; // Default is success
218 INIT_REQUEST;
219 mmc_address = (CURRENT->sector + hd[MINOR(CURRENT->rq_dev)].start_sect) * hd_hardsectsizes[0];
220 buffer_address = CURRENT->buffer;
221 nr_sectors = CURRENT->current_nr_sectors;
222 cmd = CURRENT->cmd;
223 if (((CURRENT->sector + CURRENT->current_nr_sectors + hd[MINOR(CURRENT->rq_dev)].start_sect) > hd[0].nr_sects) || (mmc_media_detect == 0))
224 {
225 code = 0;
226 }
227 else if (cmd == READ)
228 {
229 spin_unlock_irq(&io_request_lock);
230 for (i = 0; i < nr_sectors; i++)
231 {
232 rc = mmc_read_block(buffer_address, mmc_address);
233 if (rc != 0)
234 {
235 printk("mmc: error in mmc_read_block (%d)\n", rc);
236 code = 0;
237 break;
238 }
239 else
240 {
241 mmc_address += hd_hardsectsizes[0];
242 buffer_address += hd_hardsectsizes[0];
243 }
244 }
245 spin_lock_irq(&io_request_lock);
246 }
247 else if (cmd == WRITE)
248 {
249 spin_unlock_irq(&io_request_lock);
250 for (i = 0; i < nr_sectors; i++)
251 {
252 rc = mmc_write_block(mmc_address, buffer_address);
253 if (rc != 0)
254 {
255 printk("mmc: error in mmc_write_block (%d)\n", rc);
256 code = 0;
257 break;
258 }
259 else
260 {
261 mmc_address += hd_hardsectsizes[0];
262 buffer_address += hd_hardsectsizes[0];
263 }
264 }
265 spin_lock_irq(&io_request_lock);
266 }
267 else
268 {
269 code = 0;
270 }
271 end_request(code);
272 }
273 }
274
275
276 static int mmc_open(struct inode *inode, struct file *filp)
277 {
278 int device;
279 (void)filp;
280
281 if (mmc_media_detect == 0) return -ENODEV;
282
283 #if defined(MODULE)
284 MOD_INC_USE_COUNT;
285 #endif
286 return 0;
287 }
288
289 static int mmc_release(struct inode *inode, struct file *filp)
290 {
291 (void)filp;
292 fsync_dev(inode->i_rdev);
293 invalidate_buffers(inode->i_rdev);
294
295 #if defined(MODULE)
296 MOD_DEC_USE_COUNT;
297 #endif
298 return 0;
299 }
300
301 extern struct gendisk hd_gendisk;
302 static int mmc_revalidate(kdev_t dev)
303 {
304 int target, max_p, start, i;
305 if (mmc_media_detect == 0) return -ENODEV;
306
307 target = DEVICE_NR(dev);
308
309 max_p = hd_gendisk.max_p;
310 start = target << 6;
311 for (i = max_p - 1; i >= 0; i--) {
312 int minor = start + i;
313 invalidate_device(MKDEV(MAJOR_NR, minor), 1);
314 hd_gendisk.part[minor].start_sect = 0;
315 hd_gendisk.part[minor].nr_sects = 0;
316 }
317
318 grok_partitions(&hd_gendisk, target, 1 << 6,
319 hd_sizes[0] * 2);
320
321 return 0;
322 }
323
324 static int mmc_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
325 {
326 if (!inode || !inode->i_rdev)
327 return -EINVAL;
328
329 switch(cmd) {
330 case BLKGETSIZE:
331 return put_user(hd[MINOR(inode->i_rdev)].nr_sects, (unsigned long *)arg);
332 case BLKGETSIZE64:
333 return put_user((u64)hd[MINOR(inode->i_rdev)].
334 nr_sects, (u64 *) arg);
335 case BLKRRPART:
336 if (!capable(CAP_SYS_ADMIN))
337 return -EACCES;
338
339 return mmc_revalidate(inode->i_rdev);
340 case HDIO_GETGEO:
341 {
342 struct hd_geometry *loc, g;
343 loc = (struct hd_geometry *) arg;
344 if (!loc)
345 return -EINVAL;
346 g.heads = 4;
347 g.sectors = 16;
348 g.cylinders = hd[0].nr_sects / (4 * 16);
349 g.start = hd[MINOR(inode->i_rdev)].start_sect;
350 return copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0;
351 }
352 default:
353 return blk_ioctl(inode->i_rdev, cmd, arg);
354 }
355 }
356
357 static int mmc_card_init(void)
358 {
359 unsigned char r = 0;
360 short i, j;
361 unsigned long flags;
362
363 save_flags(flags);
364 cli();
365
366 printk("mmc Card init\n");
367 mmc_spi_cs_high();
368 for (i = 0; i < 20; i++) mmc_spi_io(0xff);
369
370 mmc_spi_cs_low();
371
372 mmc_spi_io(0x40);
373 for (i = 0; i < 4; i++) mmc_spi_io(0x00);
374 mmc_spi_io(0x95);
375 for (i = 0; i < 8; i++)
376 {
377 r = mmc_spi_io(0xff);
378 if (r == 0x01) break;
379 }
380 mmc_spi_cs_high();
381 mmc_spi_io(0xff);
382 if (r != 0x01)
383 {
384 restore_flags(flags);
385 return(1);
386 }
387
388 printk("mmc Card init *1*\n");
389 for (j = 0; j < 10000; j++)
390 {
391 mmc_spi_cs_low();
392
393 mmc_spi_io(0x41);
394 for (i = 0; i < 4; i++) mmc_spi_io(0x00);
395 mmc_spi_io(0xff);
396 for (i = 0; i < 8; i++)
397 {
398 r = mmc_spi_io(0xff);
399 if (r == 0x00) break;
400 }
401 mmc_spi_cs_high();
402 mmc_spi_io(0xff);
403 if (r == 0x00)
404 {
405 restore_flags(flags);
406 printk("mmc Card init *2*\n");
407 return(0);
408 }
409 }
410 restore_flags(flags);
411
412 return(2);
413 }
414
415 static int mmc_card_config(void)
416 {
417 unsigned char r = 0;
418 short i;
419 unsigned char csd[32];
420 unsigned int c_size;
421 unsigned int c_size_mult;
422 unsigned int mult;
423 unsigned int read_bl_len;
424 unsigned int blocknr = 0;
425 unsigned int block_len = 0;
426 unsigned int size = 0;
427
428 mmc_spi_cs_low();
429 for (i = 0; i < 4; i++) mmc_spi_io(0xff);
430 mmc_spi_io(0x49);
431 for (i = 0; i < 4; i++) mmc_spi_io(0x00);
432 mmc_spi_io(0xff);
433 for (i = 0; i < 8; i++)
434 {
435 r = mmc_spi_io(0xff);
436 if (r == 0x00) break;
437 }
438 if (r != 0x00)
439 {
440 mmc_spi_cs_high();
441 mmc_spi_io(0xff);
442 return(1);
443 }
444 for (i = 0; i < 8; i++)
445 {
446 r = mmc_spi_io(0xff);
447 if (r == 0xfe) break;
448 }
449 if (r != 0xfe)
450 {
451 mmc_spi_cs_high();
452 mmc_spi_io(0xff);
453 return(2);
454 }
455 for (i = 0; i < 16; i++)
456 {
457 r = mmc_spi_io(0xff);
458 csd[i] = r;
459 }
460 for (i = 0; i < 2; i++)
461 {
462 r = mmc_spi_io(0xff);
463 }
464 mmc_spi_cs_high();
465 mmc_spi_io(0xff);
466 if (r == 0x00) return(3);
467
468 c_size = csd[8] + csd[7] * 256 + (csd[6] & 0x03) * 256 * 256;
469 c_size >>= 6;
470 c_size_mult = csd[10] + (csd[9] & 0x03) * 256;
471 c_size_mult >>= 7;
472 read_bl_len = csd[5] & 0x0f;
473 mult = 1;
474 mult <<= c_size_mult + 2;
475 blocknr = (c_size + 1) * mult;
476 block_len = 1;
477 block_len <<= read_bl_len;
478 size = block_len * blocknr;
479 size >>= 10;
480
481 for(i=0; i<(1<<6); i++) {
482 hd_blocksizes[i] = 1024;
483 hd_hardsectsizes[i] = block_len;
484 hd_maxsect[i] = 256;
485 }
486 hd_sizes[0] = size;
487 hd[0].nr_sects = blocknr;
488
489
490 printk("Size = %d, hardsectsize = %d, sectors = %d\n",
491 size, block_len, blocknr);
492
493 return 0;
494 }
495
496 static int mmc_hardware_init(void)
497 {
498 unsigned char gpio_outen;
499
500 // Set inputs/outputs here
501 printk("mmc Hardware init\n");
502 gpio_outen = *gpioaddr_enable;
503
504 gpio_outen = (gpio_outen | SD_DI | SD_CLK | SD_CS) & ~SD_DO;
505 *gpioaddr_enable = gpio_outen;
506
507 port_state = *gpioaddr_input;
508
509 // Clock low
510 port_state &= ~(SD_CLK | SD_DI | SD_CS);
511 *gpioaddr_output = port_state;
512
513 return 0;
514 }
515
516 static int mmc_check_media_change(kdev_t dev)
517 {
518 (void)dev;
519 if (mmc_media_changed == 1)
520 {
521 mmc_media_changed = 0;
522 return 1;
523 }
524 else return 0;
525 }
526
527 static struct block_device_operations mmc_bdops =
528 {
529 open: mmc_open,
530 release: mmc_release,
531 ioctl: mmc_ioctl,
532 #if 0
533 check_media_change: mmc_check_media_change,
534 revalidate: mmc_revalidate,
535 #endif
536 };
537
538 static struct gendisk hd_gendisk = {
539 major: MAJOR_NR,
540 major_name: DEVICE_NAME,
541 minor_shift: 6,
542 max_p: 1 << 6,
543 part: hd,
544 sizes: hd_sizes,
545 fops: &mmc_bdops,
546 };
547
548 static int mmc_init(void)
549 {
550 int rc;
551
552 rc = mmc_hardware_init();
553
554 if ( rc != 0)
555 {
556 printk("mmc: error in mmc_hardware_init (%d)\n", rc);
557 return -1;
558 }
559
560 rc = mmc_card_init();
561 if ( rc != 0)
562 {
563 // Give it an extra shot
564 rc = mmc_card_init();
565 if ( rc != 0)
566 {
567 printk("mmc: error in mmc_card_init (%d)\n", rc);
568 return -1;
569 }
570 }
571
572 memset(hd_sizes, 0, sizeof(hd_sizes));
573 rc = mmc_card_config();
574 if ( rc != 0)
575 {
576 printk("mmc: error in mmc_card_config (%d)\n", rc);
577 return -1;
578 }
579
580
581 blk_size[MAJOR_NR] = hd_sizes;
582
583 memset(hd, 0, sizeof(hd));
584 hd[0].nr_sects = hd_sizes[0]*2;
585
586 blksize_size[MAJOR_NR] = hd_blocksizes;
587 hardsect_size[MAJOR_NR] = hd_hardsectsizes;
588 max_sectors[MAJOR_NR] = hd_maxsect;
589
590 hd_gendisk.nr_real = 1;
591
592 register_disk(&hd_gendisk, MKDEV(MAJOR_NR,0), 1<<6,
593 &mmc_bdops, hd_sizes[0]*2);
594
595 return 0;
596 }
597
598 static void mmc_exit(void)
599 {
600 blk_size[MAJOR_NR] = NULL;
601 blksize_size[MAJOR_NR] = NULL;
602 hardsect_size[MAJOR_NR] = NULL;
603 max_sectors[MAJOR_NR] = NULL;
604 hd[0].nr_sects = 0;
605 }
606
607 static void mmc_check_media(void)
608 {
609 int old_state;
610 int rc;
611
612 old_state = mmc_media_detect;
613
614 // TODO: Add card detection here
615 mmc_media_detect = 1;
616 if (old_state != mmc_media_detect)
617 {
618 mmc_media_changed = 1;
619 if (mmc_media_detect == 1)
620 {
621 rc = mmc_init();
622 if (rc != 0) printk("mmc: error in mmc_init (%d)\n", rc);
623 }
624 else
625 {
626 mmc_exit();
627 }
628 }
629
630 /* del_timer(&mmc_timer);
631 mmc_timer.expires = jiffies + 10*HZ;
632 add_timer(&mmc_timer); */
633 }
634
635 static int __init mmc_driver_init(void)
636 {
637 int rc;
638
639 rc = devfs_register_blkdev(MAJOR_NR, DEVICE_NAME, &mmc_bdops);
640 if (rc < 0)
641 {
642 printk(KERN_WARNING "mmc: can't get major %d\n", MAJOR_NR);
643 return rc;
644 }
645
646 blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), mmc_request);
647
648 read_ahead[MAJOR_NR] = 8;
649 add_gendisk(&hd_gendisk);
650
651 mmc_check_media();
652
653 /*init_timer(&mmc_timer);
654 mmc_timer.expires = jiffies + HZ;
655 mmc_timer.function = (void *)mmc_check_media;
656 add_timer(&mmc_timer);*/
657
658 return 0;
659 }
660
661 static void __exit mmc_driver_exit(void)
662 {
663 int i;
664 del_timer(&mmc_timer);
665
666 for (i = 0; i < (1 << 6); i++)
667 fsync_dev(MKDEV(MAJOR_NR, i));
668
669 blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
670 del_gendisk(&hd_gendisk);
671 devfs_unregister_blkdev(MAJOR_NR, DEVICE_NAME);
672 mmc_exit();
673 }
674
675 module_init(mmc_driver_init);
676 module_exit(mmc_driver_exit);
This page took 0.076738 seconds and 5 git commands to generate.