1 /*
2 * bcm2835 i2c controller
3 *
4 * Only i2c1 is supported.
5 * i2c2 is reserved for HDMI.
6 * i2c0 SDA0/SCL0 pins are not routed to P1 connector (except for early Rev 0 boards)
7 *
8 * maybe hardware problems lurking, see: https://github.com/raspberrypi/linux/issues/254
9 */
10
11 #include "u.h"
12 #include "../port/lib.h"
13 #include "../port/error.h"
14 #include "mem.h"
15 #include "dat.h"
16 #include "fns.h"
17 #include "io.h"
18
19 #define I2CREGS (VIRTIO+0x804000)
20 #define SDA0Pin 2
21 #define SCL0Pin 3
22 #define Alt0 0x4
23
24 typedef struct I2c I2c;
25 typedef struct Bsc Bsc;
26
27 /*
28 * Registers for Broadcom Serial Controller (i2c compatible)
29 */
30 struct Bsc {
31 u32int ctrl;
32 u32int stat;
33 u32int dlen;
34 u32int addr;
35 u32int fifo;
36 u32int clkdiv; /* default 1500 => 100 KHz assuming 150Mhz input clock */
37 u32int delay; /* default (48<<16)|48 falling:rising edge */
38 u32int clktimeout; /* default 64 */
39 };
40
41 /*
42 * Per-controller info
43 */
44 struct I2c {
45 QLock lock;
46 Lock reglock;
47 Rendez r;
48 Bsc *regs;
49 };
50
51 static I2c i2c;
52
53 enum {
54 /* ctrl */
55 I2cen = 1<<15, /* I2c enable */
56 Intr = 1<<10, /* interrupt on reception */
57 Intt = 1<<9, /* interrupt on transmission */
58 Intd = 1<<8, /* interrupt on done */
59 Start = 1<<7, /* aka ST, start a transfer */
60 Clear = 1<<4, /* clear fifo */
61 Read = 1<<0, /* read transfer */
62 Write = 0<<0, /* write transfer */
63
64 /* stat */
65 Clkt = 1<<9, /* clock stretch timeout */
66 Err = 1<<8, /* NAK */
67 Rxf = 1<<7, /* RX fifo full */
68 Txe = 1<<6, /* TX fifo full */
69 Rxd = 1<<5, /* RX fifo has data */
70 Txd = 1<<4, /* TX fifo has space */
71 Rxr = 1<<3, /* RX fiio needs reading */
72 Txw = 1<<2, /* TX fifo needs writing */
73 Done = 1<<1, /* transfer done */
74 Ta = 1<<0, /* Transfer active */
75
76 /* maximum I2C I/O (can change) */
77 MaxIO = 128,
78 MaxSA = 2, /* longest subaddress */
79 Bufsize = (MaxIO+MaxSA+1+4)&~3, /* extra space for subaddress/clock bytes and alignment */
80
81 Chatty = 0,
82 };
83
84 static void
i2cinterrupt(Ureg *,void *)85 i2cinterrupt(Ureg*, void*)
86 {
87 Bsc *r;
88 int st;
89
90 r = i2c.regs;
91 st = 0;
92 if((r->ctrl & Intr) && (r->stat & Rxd))
93 st |= Intr;
94 if((r->ctrl & Intt) && (r->stat & Txd))
95 st |= Intt;
96 if(r->stat & Done)
97 st |= Intd;
98 if(st){
99 r->ctrl &= ~st;
100 wakeup(&i2c.r);
101 }
102 }
103
104 static int
i2cready(void * st)105 i2cready(void *st)
106 {
107 return (i2c.regs->stat & (uintptr)st);
108 }
109
110 static void
i2cinit(void)111 i2cinit(void)
112 {
113 i2c.regs = (Bsc*)I2CREGS;
114 i2c.regs->clkdiv = 2500;
115
116 gpiosel(SDA0Pin, Alt0);
117 gpiosel(SCL0Pin, Alt0);
118 gpiopullup(SDA0Pin);
119 gpiopullup(SCL0Pin);
120
121 intrenable(IRQi2c, i2cinterrupt, 0, 0, "i2c");
122 }
123
124 /*
125 * To do subaddressing avoiding a STOP condition between the address and payload.
126 * - write the subaddress,
127 * - poll until the transfer starts,
128 * - overwrite the registers for the payload transfer, before the subaddress
129 * transaction has completed.
130 *
131 * FIXME: neither 10bit adressing nor 100Khz transfers implemented yet.
132 */
133 static void
i2cio(int rw,int tenbit,uint addr,void * buf,int len,int salen,uint subaddr)134 i2cio(int rw, int tenbit, uint addr, void *buf, int len, int salen, uint subaddr)
135 {
136 Bsc *r;
137 uchar *p;
138 int st;
139
140 if(tenbit)
141 error("10bit addressing not supported");
142 if(salen == 0 && subaddr) /* default subaddress len == 1byte */
143 salen = 1;
144
145 qlock(&i2c.lock);
146 r = i2c.regs;
147 r->ctrl = I2cen | Clear;
148 r->addr = addr;
149 r->stat = Clkt|Err|Done;
150
151 if(salen){
152 r->dlen = salen;
153 r->ctrl = I2cen | Start | Write;
154 while((r->stat & Ta) == 0) {
155 if(r->stat & (Err|Clkt)) {
156 qunlock(&i2c.lock);
157 error(Eio);
158 }
159 }
160 r->dlen = len;
161 r->ctrl = I2cen | Start | Intd | rw;
162 for(; salen > 0; salen--)
163 r->fifo = subaddr >> ((salen-1)*8);
164 /*
165 * Adapted from Linux code...uses undocumented
166 * status information.
167 */
168 if(rw == Read) {
169 do {
170 if(r->stat & (Err|Clkt)) {
171 qunlock(&i2c.lock);
172 error(Eio);
173 }
174 st = r->stat >> 28;
175 } while(st != 0 && st != 4 && st != 5);
176 }
177 }
178 else {
179 r->dlen = len;
180 r->ctrl = I2cen | Start | Intd | rw;
181 }
182
183 p = buf;
184 st = rw == Read? Rxd : Txd;
185 while(len > 0){
186 while((r->stat & (st|Done)) == 0){
187 r->ctrl |= rw == Read? Intr : Intt;
188 sleep(&i2c.r, i2cready, (void*)(st|Done));
189 }
190 if(r->stat & (Err|Clkt)){
191 qunlock(&i2c.lock);
192 error(Eio);
193 }
194 if(rw == Read){
195 do{
196 *p++ = r->fifo;
197 len--;
198 }while ((r->stat & Rxd) && len > 0);
199 }else{
200 do{
201 r->fifo = *p++;
202 len--;
203 }while((r->stat & Txd) && len > 0);
204 }
205 }
206 while((r->stat & Done) == 0)
207 sleep(&i2c.r, i2cready, (void*)Done);
208 if(r->stat & (Err|Clkt)){
209 qunlock(&i2c.lock);
210 error(Eio);
211 }
212 r->ctrl = 0;
213 qunlock(&i2c.lock);
214 }
215
216
217 void
i2csetup(int)218 i2csetup(int)
219 {
220 //print("i2csetup\n");
221 i2cinit();
222 }
223
224 long
i2csend(I2Cdev * d,void * buf,long len,ulong offset)225 i2csend(I2Cdev *d, void *buf, long len, ulong offset)
226 {
227 i2cio(Write, d->tenbit, d->addr, buf, len, d->salen, offset);
228 return len;
229 }
230
231 long
i2crecv(I2Cdev * d,void * buf,long len,ulong offset)232 i2crecv(I2Cdev *d, void *buf, long len, ulong offset)
233 {
234 i2cio(Read, d->tenbit, d->addr, buf, len, d->salen, offset);
235 return len;
236 }
237