changelog shortlog tags branches changeset files revisions annotate raw help

Mercurial > hg > plan9front / sys/src/9/pc/pmmc.c

changeset 4350: 1f9d7811d546
parent: fe1aabe276b5
child: 1bb543d577e1
author: cinap_lenrek@felloff.net
date: Mon, 16 Mar 2015 05:46:08 +0100
permissions: -rw-r--r--
description: kernel: get rid of auxpage() and preserve cache index bits in Page.va in mount cache

the mount cache uses Page.va to store cached range offset and
limit, but mips kernel uses cache index bits from Page.va to
maintain page coloring. Page.va was not initialized by auxpage().

this change removes auxpage() which was primarily used only
by the mount cache and use newpage() with cache file offset
page as va so we will get a page of the right color.

mount cache keeps the index bits intact by only using the top
and buttom PGSHIFT bits of Page.va for the range offset/limit.
1 /*
2  * pci mmc controller.
3  *
4  * initially written for X230 Ricoh MMC controller.
5  * cmdinfo[] table stolen from bcm/emmc.c, thanks richard.
6  *
7  * for sdhc documentation see: https://www.sdcard.org/
8  */
9 #include "u.h"
10 #include "../port/lib.h"
11 #include "../port/error.h"
12 #include "mem.h"
13 #include "dat.h"
14 #include "fns.h"
15 #include "io.h"
16 #include "../port/sd.h"
17 
18 /* registers */
19 enum {
20  Rsdma = 0x00,
21  Rbsize = 0x04,
22  Rbcount = 0x06,
23  Rarg = 0x08,
24  Rmode = 0x0C,
25  Rcmd = 0x0E,
26  Rresp0 = 0x10,
27  Rresp1 = 0x14,
28  Rresp2 = 0x18,
29  Rresp3 = 0x1C,
30  Rdat0 = 0x20,
31  Rdat1 = 0x22,
32  Rpres = 0x24,
33  Rhc = 0x28,
34  Rpwr = 0x29,
35  Rbgc = 0x2A,
36  Rwkc = 0x2B,
37  Rclc = 0x2C,
38  Rtmc = 0x2E,
39  Rsrst = 0x2F,
40  Rnis = 0x30,
41  Reis = 0x32,
42  Rnie = 0x34,
43  Reie = 0x36,
44  Rnise = 0x38,
45  Reise = 0x3A,
46  Ra12 = 0x3C,
47  Rcap = 0x40,
48  Rrcap = 0x44,
49  Rxcap = 0x48,
50  Rrxcap = 0x4C,
51  Rfea12 = 0x50,
52  Rfeei = 0x52,
53  Radmasr = 0x54,
54  Radmaba = 0x58,
55  Rsists = 0xFC,
56  Rhcver = 0xFE,
57 };
58 
59 /* sts bits */
60 enum {
61  Seint = 1<<15,
62  Snint = 1<<8,
63  Srem = 1<<7,
64  Sins = 1<<6,
65  Srrdy = 1<<5,
66  Swrdy = 1<<4,
67  Sdint = 1<<3,
68  Sbge = 1<<2,
69  Strac = 1<<1,
70  Scmdc = 1<<0,
71 
72  Smask = 0x81ff,
73 };
74 
75 /* err bits */
76 enum {
77  Ea12 = 1<<8,
78  Elimit = 1<<7,
79  Edebit = 1<<6,
80  Edcrc = 1<<5,
81  Edtmo = 1<<4,
82  Ecidx = 1<<3,
83  Ecebit = 1<<2,
84  Eccrc = 1<<1,
85  Ectmo = 1<<0,
86 
87  Emask = 0x1ff,
88 };
89 
90 /* present bits */
91 enum {
92  Plsig = 1<<24,
93  Pldat3 = 1<<23,
94  Pldat2 = 1<<22,
95  Pldat1 = 1<<21,
96  Pldat0 = 1<<20,
97 
98  Ppswit = 1<<19,
99  Pcrddt = 1<<18,
100  Pcrdst = 1<<17,
101  Pcrdin = 1<<16,
102 
103  Pbufrd = 1<<11,
104  Pbufwr = 1<<10,
105  Ptrard = 1<<9,
106  Ptrawr = 1<<8,
107  Pdat = 1<<2,
108 
109  Pinhbc = 1<<1,
110  Pinhbd = 1<<0,
111 };
112 
113 /* Rmode bits */
114 enum {
115  Mblk = 1<<5,
116  Mrd = 1<<4,
117  Mwr = 0<<4,
118  Ma12 = 1<<2,
119  Mcnt = 1<<1,
120  Mdma = 1<<0,
121 };
122 
123 /* command bits */
124 enum {
125  Abort = 3<<6,
126  Isdata = 1<<5,
127  Ixchken = 1<<4,
128  Crcchken = 1<<3,
129 
130  Respmask = 3,
131  Respnone = 0,
132  Resp48busy = 3,
133  Resp48 = 2,
134  Resp136 = 1,
135 };
136 
137 /* fake for cmdinfo */
138 enum {
139  Blkcnten = Mblk << 8,
140  Multiblock = Mcnt << 8,
141  Card2host = Mrd << 8,
142  Host2card = Mwr << 8,
143 };
144 
145 int cmdinfo[64] = {
146 [0] Ixchken,
147 [2] Resp136,
148 [3] Resp48 | Ixchken | Crcchken,
149 [6] Resp48 | Ixchken | Crcchken,
150 [7] Resp48busy | Ixchken | Crcchken,
151 [8] Resp48 | Ixchken | Crcchken,
152 [9] Resp136,
153 [12] Resp48busy | Ixchken | Crcchken,
154 [13] Resp48 | Ixchken | Crcchken,
155 [16] Resp48,
156 [17] Resp48 | Isdata | Card2host | Ixchken | Crcchken,
157 [18] Resp48 | Isdata | Card2host | Multiblock | Blkcnten | Ixchken | Crcchken,
158 [24] Resp48 | Isdata | Host2card | Ixchken | Crcchken,
159 [25] Resp48 | Isdata | Host2card | Multiblock | Blkcnten | Ixchken | Crcchken,
160 [41] Resp48,
161 [55] Resp48 | Ixchken | Crcchken,
162 };
163 
164 typedef struct Ctlr Ctlr;
165 struct Ctlr {
166  Lock;
167 
168  Pcidev *pdev;
169  u8int *mmio;
170 
171  int change;
172 
173  u32int waitsts;
174  u32int waitmsk;
175  Rendez r;
176 
177  struct {
178  int bcount;
179  int bsize;
180  } io;
181 };
182 
183 static Ctlr pmmc[1];
184 
185 #define CR8(c, off) *((u8int*)(c->mmio + off))
186 #define CR16(c, off) *((u16int*)(c->mmio + off))
187 #define CR32(c, off) *((u32int*)(c->mmio + off))
188 
189 static void
190 mmcinterrupt(Ureg*, void *arg)
191 {
192  u16int nis, eis;
193  Ctlr *c;
194 
195  c = arg;
196  nis = CR16(c, Rnis);
197  if((nis & Smask) == 0)
198  return; /* not for us */
199 
200  CR16(c, Rnis) = nis; /* ack */
201  ilock(c);
202  eis = 0;
203  if((nis & Seint) != 0){
204  eis = CR16(c, Reis);
205  CR16(c, Reis) = eis; /* ack */
206  }
207  if((nis & Snint) != 0)
208  CR16(c, Rnie) |= Snint; /* ack */
209  if((nis & (Srem|Sins)) != 0)
210  c->change = 1;
211  c->waitsts |= nis | (eis << 16);
212  if((c->waitsts & c->waitmsk) != 0)
213  wakeup(&c->r);
214  iunlock(c);
215 }
216 
217 static int
218 pmmcinit(void)
219 {
220  Pcidev *p;
221 
222  p = nil;
223  while((p = pcimatch(p, 0, 0)) != nil){
224  if(p->ccrb == 8 && p->ccru == 5)
225  break;
226  if(p->vid == 0x1180){ /* Ricoh */
227  if(p->did == 0xe822) /* 5U822 SD/MMC */
228  break;
229  if(p->did == 0xe823) /* 5U823 SD/MMC */
230  break;
231  }
232  }
233 
234  if(p == nil || p->mem[0].size < 256)
235  return -1;
236 
237  if(p->did == 0x1180 && p->vid == 0xe823){ /* Ricoh */
238  /* Enable SD2.0 mode. */
239  pcicfgw8(p, 0xf9, 0xfc);
240  pcicfgw8(p, 0x150, 0x10);
241  pcicfgw8(p, 0xf9, 0x00);
242 
243  /*
244  * Some SD/MMC cards don't work with the default base
245  * clock frequency of 200MHz. Lower it to 50Hz.
246  */
247  pcicfgw8(p, 0xfc, 0x01);
248  pcicfgw8(p, 0xe1, 50);
249  pcicfgw8(p, 0xfc, 0x00);
250  }
251 
252  pmmc->mmio = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);
253  if(pmmc->mmio == nil)
254  return -1;
255  pmmc->pdev = p;
256  return 0;
257 }
258 
259 static int
260 pmmcinquiry(char *inquiry, int inqlen)
261 {
262  return snprint(inquiry, inqlen, "MMC Host Controller");
263 }
264 
265 static void
266 softreset(Ctlr *c, int all)
267 {
268  int i, m;
269 
270  m = all ? 1 : 6;
271  CR8(c, Rsrst) = m;
272  for(i=10; i>=0; i--){
273  if((CR8(c, Rsrst) & m) == 0)
274  break;
275  delay(10);
276  CR8(c, Rsrst) = 0;
277  }
278  if(i < 0) iprint("mmc: didnt reset\n");
279 }
280 
281 static void
282 setpower(Ctlr *c, int on)
283 {
284  enum {
285  Vcap18 = 1<<26, Vset18 = 0x05,
286  Vcap30 = 1<<25, Vset30 = 0x06,
287  Vcap33 = 1<<24, Vset33 = 0x07,
288  };
289  u32int cap, v;
290 
291  cap = CR32(c, Rcap);
292  v = Vset18;
293  if(cap & Vcap30)
294  v = Vset30;
295  if(cap & Vcap33)
296  v = Vset33;
297  CR8(c, Rpwr) = on ? ((v<<1) | 1) : 0;
298 }
299 
300 static void
301 setclkfreq(Ctlr *c, int khz)
302 {
303  u32int caps, intfreq;
304  int i, div;
305 
306  if(khz == 0){
307  CR16(c, Rclc) |= ~4; /* sd clock disable */
308  return;
309  }
310 
311  caps = CR32(c, Rcap);
312  intfreq = 1000*((caps >> 8) & 0x3f);
313  for(div = 1; div <= 256; div <<= 1){
314  if((intfreq / div) <= khz){
315  div >>= 1;
316  break;
317  }
318  }
319  CR16(c, Rclc) = 0;
320  CR16(c, Rclc) = div<<8;
321  CR16(c, Rclc) |= 1; /* int clock enable */
322  for(i=1000; i>=0; i--){
323  if(CR16(c, Rclc) & 2) /* int clock stable */
324  break;
325  delay(10);
326  }
327  if(i < 0) iprint("mmc: clock didnt stabilize\n");
328  CR16(c, Rclc) |= 4; /* sd clock enable */
329 }
330 
331 static void
332 resetctlr(Ctlr *c)
333 {
334  u32int m;
335 
336  ilock(c);
337  CR16(c, Rnise) = 0; /* interrupts off */
338 
339  c->change = 0;
340  c->waitmsk = c->waitsts = 0;
341  softreset(c, 1);
342 
343  /* set timeout */
344  CR8(c, Rtmc) = 0x0e;
345 
346  m = Srem | Sins | Srrdy | Swrdy | Sdint | Sbge | Strac | Scmdc;
347  CR16(c, Rnie) = m;
348  CR16(c, Reie) = Emask;
349  CR16(c, Rnise) = m;
350  CR16(c, Reise) = Emask;
351 
352  setpower(c, 1);
353  setclkfreq(c, 400);
354  iunlock(c);
355 }
356 
357 static int
358 waitcond(void *arg)
359 {
360  Ctlr *c;
361 
362  c = arg;
363  return (c->waitsts & c->waitmsk) != 0;
364 }
365 
366 static u32int
367 intrwait(Ctlr *c, u32int mask, int tmo)
368 {
369  u32int status;
370 
371  ilock(c);
372  c->waitmsk = Seint | mask;
373  iunlock(c);
374  do {
375  if(!waserror()){
376  tsleep(&c->r, waitcond, c, 100);
377  poperror();
378  }
379  mmcinterrupt(nil, c);
380  if(waitcond(c))
381  break;
382  tmo -= 100;
383  } while(tmo > 0);
384  ilock(c);
385  c->waitmsk = 0;
386  status = c->waitsts;
387  c->waitsts &= ~(status & mask);
388  if((status & mask) == 0 || (status & Seint) != 0){
389  /* abort command on timeout/error interrupt */
390  softreset(c, 0);
391  c->waitsts = 0;
392  status = 0;
393  }
394  iunlock(c);
395 
396  return status & mask;
397 }
398 
399 
400 static void
401 pmmcenable(void)
402 {
403  Pcidev *p;
404  Ctlr *c;
405 
406  c = pmmc;
407  p = c->pdev;
408  resetctlr(c);
409  intrenable(p->intl, mmcinterrupt, c, p->tbdf, "mmc");
410 }
411 
412 static int
413 pmmccmd(u32int cmd, u32int arg, u32int *resp)
414 {
415  u32int status;
416  int i, mode;
417  Ctlr *c;
418 
419  if(cmd >= nelem(cmdinfo) || cmdinfo[cmd] == 0)
420  error(Egreg);
421  mode = cmdinfo[cmd] >> 8;
422  cmd = (cmd << 8) | (cmdinfo[cmd] & 0xFF);
423 
424  c = pmmc;
425 
426  if(c->change)
427  resetctlr(c);
428  if((CR32(c, Rpres) & Pcrdin) == 0)
429  error("no card");
430 
431  status = Pinhbc;
432  if((cmd & Isdata) != 0 || (cmd & Respmask) == Resp48busy)
433  status |= Pinhbd;
434  for(i=1000; (CR32(c, Rpres) & status) != 0 && i>=0; i--)
435  delay(1);
436  if(i < 0)
437  error(Eio);
438 
439  ilock(c);
440  if((mode & (Mcnt|Mblk)) == (Mcnt|Mblk)){
441  CR16(c, Rbsize) = c->io.bsize;
442  CR16(c, Rbcount) = c->io.bcount;
443  }
444  CR32(c, Rarg) = arg;
445  CR16(c, Rmode) = mode;
446  CR16(c, Rcmd) = cmd;
447  iunlock(c);
448 
449  if(!intrwait(c, Scmdc, 1000))
450  error(Eio);
451 
452  switch(cmd & Respmask){
453  case Resp48busy:
454  resp[0] = CR32(c, Rresp0);
455  if(!intrwait(c, Strac, 3000))
456  error(Eio);
457  break;
458  case Resp48:
459  resp[0] = CR32(c, Rresp0);
460  break;
461  case Resp136:
462  resp[0] = CR32(c, Rresp0)<<8;
463  resp[1] = CR32(c, Rresp0)>>24 | CR32(c, Rresp1)<<8;
464  resp[2] = CR32(c, Rresp1)>>24 | CR32(c, Rresp2)<<8;
465  resp[3] = CR32(c, Rresp2)>>24 | CR32(c, Rresp3)<<8;
466  break;
467  case Respnone:
468  resp[0] = 0;
469  break;
470  }
471 
472  cmd >>= 8;
473  if(cmd == 0x06){ /* buswidth */
474  switch(arg){
475  case 0:
476  CR8(c, Rhc) &= ~2;
477  break;
478  case 2:
479  CR8(c, Rhc) |= 2;
480  break;
481  }
482  }
483 
484  return 0;
485 }
486 
487 static void
488 pmmciosetup(int write, void *buf, int bsize, int bcount)
489 {
490  Ctlr *c;
491 
492  USED(write);
493  USED(buf);
494 
495  if(bsize == 0 || (bsize & 3) != 0)
496  error(Egreg);
497 
498  c = pmmc;
499  c->io.bsize = bsize;
500  c->io.bcount = bcount;
501 }
502 
503 static void
504 readblock(Ctlr *c, uchar *buf, int len)
505 {
506  for(len >>= 2; len > 0; len--){
507  *((u32int*)buf) = CR32(c, Rdat0);
508  buf += 4;
509  }
510 }
511 
512 static void
513 writeblock(Ctlr *c, uchar *buf, int len)
514 {
515  for(len >>= 2; len > 0; len--){
516  CR32(c, Rdat0) = *((u32int*)buf);
517  buf += 4;
518  }
519 }
520 
521 static void
522 pmmcio(int write, uchar *buf, int len)
523 {
524  Ctlr *c;
525  int n;
526 
527  c = pmmc;
528  if(len != c->io.bsize*c->io.bcount)
529  error(Egreg);
530  while(len > 0){
531  if(!intrwait(c, write ? Swrdy : Srrdy, 3000))
532  error(Eio);
533  n = len;
534  if(n > c->io.bsize)
535  n = c->io.bsize;
536  if(write)
537  writeblock(c, buf, n);
538  else
539  readblock(c, buf, n);
540  len -= n;
541  buf += n;
542  }
543  if(!intrwait(c, Strac, 1000))
544  error(Eio);
545 }
546 
547 SDio sdio = {
548  "pmmc",
549  pmmcinit,
550  pmmcenable,
551  pmmcinquiry,
552  pmmccmd,
553  pmmciosetup,
554  pmmcio,
555 };