]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/drivers-frst/nand/src/gpmc.cc
update
[l4.git] / l4 / pkg / drivers-frst / nand / src / gpmc.cc
1 #include <stdio.h>
2
3 #include "l4/drivers-frst/lib_nand.h"
4
5 #include "nand.h"
6 #include "gpmc.h"
7
8 Gpmc::Gpmc(addr base_addr)
9   : _reg((Reg *)base_addr)
10 {
11   for (int i = 0; i < Num_cs; ++i)
12     {
13       /* Check if NAND type is set */
14       if (((_reg->cs[i].config1) & 0xc00) == 0x800)
15         {
16           //printf("found NAND chip\n");
17           /* Found it!! */
18           break;
19         }
20     }
21
22   // XXX just scan for one chip
23   scan(1);
24
25   // disable write protection
26   u32 config = _reg->config;
27   config |= 0x10;
28   _reg->config = config;
29
30   // enable interrupts
31   _reg->irqstatus = 256;
32   _reg->irqenable = 256;
33 }
34
35 void Gpmc::add(Nand_chip *chip)
36 {
37   chip->add_options(Opt_no_padding | Opt_cacheprg | Opt_no_autoincr);
38   if ((_reg->cs[0].config1 & 0x3000) == 0x1000)
39     chip->add_options(Opt_buswidth_16);
40   //chip->delay = 100;
41
42   _chips[0] = chip;
43 }
44
45 Nand_chip *Gpmc::select(loff_t /*addr*/)
46 {
47   // XXX hack:we currently have only one chip
48   return _chips[0];
49 }
50
51 void Gpmc::wr_cmd(u8 c)
52 { *((volatile u8 *)&_reg->cs[0].nand_cmd) = c; }
53
54 void Gpmc::wr_adr(u8 a)
55 { *((volatile u8 *)&_reg->cs[0].nand_adr) = a; }
56
57 void Gpmc::wr_dat(u8 d)
58 { *((volatile u8 *)&_reg->cs[0].nand_dat) = d; }
59
60 u8 Gpmc::rd_dat()
61 { return (u8)(*((volatile u16 *)&_reg->cs[0].nand_dat)); }
62
63 void Gpmc::rd_dat(const u8 *buf, unsigned len)
64 {
65   u16 *p = (u16 *)buf;
66   len >>= 1;
67
68   for (unsigned i = 0; i < len; i++)
69     p[i] = *((volatile u16 *)&_reg->cs[0].nand_dat);
70
71 #if 0
72   for (int i = 0; i < len; i+=4)
73     {
74       p[i] = *((volatile u16 *)&_reg->cs[0].nand_dat);
75       p[i+1] = *((volatile u16 *)&_reg->cs[0].nand_dat);
76       p[i+2] = *((volatile u16 *)&_reg->cs[0].nand_dat);
77       p[i+3] = *((volatile u16 *)&_reg->cs[0].nand_dat);
78     }
79 #endif
80 }
81
82 void Gpmc::wr_dat(const u8 *buf, unsigned len)
83 {
84   u16 *p = (u16 *)buf;
85   len >>= 1;
86
87   for (unsigned i = 0; i < len; i++)
88     *((volatile u16 *)&_reg->cs[0].nand_dat) = p[i];
89 }
90
91 int Gpmc::handle_irq()
92 {
93   int ret = 0;
94   u32 v = _reg->irqstatus;
95   u32 v2 = _reg->irqstatus;
96   if (v & 256)
97     {
98       ret = _chips[0]->handle_irq();
99       _reg->irqstatus = 256;
100     }
101   else
102     {
103       printf("spurious interrupt\n");
104       printf("irqstatus:%x %x\n", v, v2);
105       return -1;
106     }
107   
108   return ret;
109 }
110
111 class Gpmc_drv : public Nand_drv
112 {
113 public:
114   Gpmc_drv()
115     { arm_nand_register_driver(this); }
116   
117   int probe(const char *configstr)
118     { return (strcmp(configstr, "GPMC")) ? 0 : 1; }
119   
120   Nand_ctrl *create(addr base)
121     { return new Gpmc(base); }
122 };
123
124 static Gpmc_drv gpmc_drv;