archkw.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. /*
  2. * stuff specific to marvell's kirkwood architecture
  3. * as seen in the sheevaplug
  4. */
  5. #include "u.h"
  6. #include "../port/lib.h"
  7. #include "mem.h"
  8. #include "dat.h"
  9. #include "fns.h"
  10. #include "../port/error.h"
  11. #include "io.h"
  12. #include "../port/netif.h"
  13. #include "etherif.h"
  14. // #include "../port/flashif.h"
  15. #include "arm.h"
  16. #define SDRAMDREG ((SDramdReg*)AddrSDramd)
  17. enum {
  18. L2writeback = 1,
  19. Debug = 0,
  20. };
  21. typedef struct GpioReg GpioReg;
  22. struct GpioReg {
  23. ulong dataout;
  24. ulong dataoutena;
  25. ulong blinkena;
  26. ulong datainpol;
  27. ulong datain;
  28. ulong intrcause;
  29. ulong intrmask;
  30. ulong intrlevelmask;
  31. };
  32. typedef struct L2uncache L2uncache;
  33. typedef struct L2win L2win;
  34. struct L2uncache {
  35. struct L2win {
  36. ulong base; /* phys addr */
  37. ulong size;
  38. } win[4];
  39. };
  40. enum {
  41. /* L2win->base bits */
  42. L2enable = 1<<0,
  43. };
  44. typedef struct Dramctl Dramctl;
  45. struct Dramctl {
  46. ulong ctl;
  47. ulong ddrctllo;
  48. struct {
  49. ulong lo;
  50. ulong hi;
  51. } time;
  52. ulong addrctl;
  53. ulong opagectl;
  54. ulong oper;
  55. ulong mode;
  56. ulong extmode;
  57. ulong ddrctlhi;
  58. ulong ddr2timelo;
  59. ulong operctl;
  60. struct {
  61. ulong lo;
  62. ulong hi;
  63. } mbusctl;
  64. ulong mbustimeout;
  65. ulong ddrtimehi;
  66. ulong sdinitctl;
  67. ulong extsdmode1;
  68. ulong extsdmode2;
  69. struct {
  70. ulong lo;
  71. ulong hi;
  72. } odtctl;
  73. ulong ddrodtctl;
  74. ulong rbuffsel;
  75. ulong accalib;
  76. ulong dqcalib;
  77. ulong dqscalib;
  78. };
  79. typedef struct SDramdReg SDramdReg;
  80. struct SDramdReg {
  81. struct {
  82. ulong base;
  83. ulong size;
  84. } win[4];
  85. };
  86. typedef struct Addrmap Addrmap;
  87. typedef struct Addrwin Addrwin;
  88. struct Addrmap {
  89. struct Addrwin {
  90. ulong ctl;
  91. ulong base;
  92. ulong remaplo;
  93. ulong remaphi;
  94. } win[8];
  95. ulong dirba; /* device internal reg's base addr.: PHYSIO */
  96. };
  97. enum {
  98. /* Addrwin->ctl bits */
  99. Winenable = 1<<0,
  100. };
  101. /*
  102. * u-boot leaves us with this address map:
  103. *
  104. * 0 targ 4 attr 0xe8 size 256MB addr 0x9:: remap addr 0x9:: pci mem
  105. * 1 targ 1 attr 0x2f size 8MB addr 0xf9:: remap addr 0xf9:: nand flash
  106. * 2 targ 4 attr 0xe0 size 16MB addr 0xf:: remap addr 0xc:: pci i/o
  107. * 3 targ 1 attr 0x1e size 16MB addr 0xf8:: remap addr 0x0 spi flash
  108. * 4 targ 1 attr 0x1d size 16MB addr 0xff:: boot rom
  109. * 5 targ 1 attr 0x1e size 128MB addr 0xe8:: disabled spi flash
  110. * 6 targ 1 attr 0x1d size 128MB addr 0xf:: disabled boot rom
  111. * 7 targ 3 attr 0x1 size 64K addr 0xfb:: crypto sram
  112. */
  113. #define WINTARG(ctl) (((ctl) >> 4) & 017)
  114. #define WINATTR(ctl) (((ctl) >> 8) & 0377)
  115. #define WIN64KSIZE(ctl) (((ctl) >> 16) + 1)
  116. static void
  117. praddrwin(Addrwin *win, int i)
  118. {
  119. ulong ctl, targ, attr, size64k;
  120. if (!Debug) {
  121. USED(win, i);
  122. return;
  123. }
  124. ctl = win->ctl;
  125. targ = WINTARG(ctl);
  126. attr = WINATTR(ctl);
  127. size64k = WIN64KSIZE(ctl);
  128. print("cpu addr map: %s window %d: targ %ld attr %#lux size %,ld addr %#lux",
  129. ctl & Winenable? "enabled": "disabled", i, targ, attr,
  130. size64k * 64*1024, win->base);
  131. if (i < 4)
  132. print(" remap addr %#llux", (uvlong)win->remaphi<<32 |
  133. win->remaplo);
  134. print("\n");
  135. }
  136. static void
  137. fixaddrmap(void)
  138. {
  139. int i, sawspi;
  140. ulong ctl, targ, attr, size64k;
  141. Addrmap *map;
  142. Addrwin *win;
  143. sawspi = 0;
  144. map = (Addrmap *)AddrWin;
  145. for (i = 0; i < nelem(map->win); i++) {
  146. win = &map->win[i];
  147. ctl = win->ctl;
  148. targ = WINTARG(ctl);
  149. attr = WINATTR(ctl);
  150. size64k = WIN64KSIZE(ctl);
  151. if (targ == Targflash && attr == Attrspi &&
  152. size64k == 16*MB/(64*1024)) {
  153. win->ctl &= ~Winenable;
  154. coherence();
  155. if (i < 4) {
  156. // TODO set the remap addr; it's 0 now
  157. }
  158. praddrwin(win, i);
  159. } else if (targ == Targflash && attr == Attrspi &&
  160. size64k == 128*MB/(64*1024)) {
  161. sawspi = 1;
  162. if (!(ctl & Winenable)) {
  163. win->ctl |= Winenable;
  164. coherence();
  165. praddrwin(win, i);
  166. }
  167. } else if (targ == Targcesasram) {
  168. win->ctl |= Winenable;
  169. win->base = PHYSCESASRAM;
  170. coherence();
  171. praddrwin(win, i);
  172. }
  173. }
  174. if (!sawspi)
  175. panic("cpu address map: no existing window for spi");
  176. if (map->dirba != PHYSIO)
  177. panic("dirba not %#ux", PHYSIO);
  178. }
  179. static void
  180. praddrmap(void)
  181. {
  182. int i;
  183. Addrmap *map;
  184. map = (Addrmap *)AddrWin;
  185. for (i = 0; i < nelem(map->win); i++)
  186. praddrwin(&map->win[i], i);
  187. }
  188. int
  189. ispow2(uvlong ul)
  190. {
  191. /* see Hacker's Delight if this isn't obvious */
  192. return (ul & (ul - 1)) == 0;
  193. }
  194. /*
  195. * return exponent of smallest power of 2 ≥ n
  196. */
  197. int
  198. log2(ulong n)
  199. {
  200. int i;
  201. for(i = 0; (1 << i) < n; i++)
  202. ;
  203. return i;
  204. }
  205. void
  206. cacheinfo(int level, int kind, Memcache *cp) /* l1 only */
  207. {
  208. uint len, assoc, size;
  209. ulong setsways;
  210. /* get cache types & sizes (read-only reg) */
  211. setsways = cprdsc(0, CpID, CpIDidct, CpIDct);
  212. cp->level = level;
  213. cp->kind = kind;
  214. if ((setsways & (1<<24)) == 0)
  215. kind = Unified;
  216. if (kind != Icache)
  217. setsways >>= 12;
  218. assoc = (setsways >> 3) & MASK(3);
  219. cp->nways = 1 << assoc;
  220. size = (setsways >> 6) & MASK(4);
  221. cp->size = 1 << (size + 9);
  222. len = setsways & MASK(2);
  223. cp->log2linelen = len + 3;
  224. cp->linelen = 1 << cp->log2linelen;
  225. cp->setsways = setsways;
  226. cp->nsets = 1 << (size + 6 - assoc - len);
  227. cp->setsh = cp->log2linelen;
  228. cp->waysh = 32 - log2(cp->nways);
  229. }
  230. static char *
  231. wbtype(uint type)
  232. {
  233. static char *types[] = {
  234. "write-through",
  235. "read data block",
  236. "reg 7 ops, no lock-down",
  237. [06] "reg 7 ops, format A",
  238. [07] "reg 7 ops, format B deprecated",
  239. [016] "reg 7 ops, format C",
  240. [05] "reg 7 ops, format D",
  241. };
  242. if (type >= nelem(types) || types[type] == nil)
  243. return "GOK";
  244. return types[type];
  245. }
  246. static void
  247. prcache(Memcache *mcp)
  248. {
  249. int type;
  250. char id;
  251. if (mcp->kind == Unified)
  252. id = 'U';
  253. else if (mcp->kind == Icache)
  254. id = 'I';
  255. else if (mcp->kind == Dcache)
  256. id = 'D';
  257. else
  258. id = '?';
  259. print("l%d %c: %d bytes, %d ways %d sets %d bytes/line",
  260. mcp->level, id, mcp->size, mcp->nways, mcp->nsets,
  261. mcp->linelen);
  262. if (mcp->linelen != CACHELINESZ)
  263. print(" *should* be %d", CACHELINESZ);
  264. type = (mcp->setsways >> 25) & MASK(4);
  265. if (type == 0)
  266. print("; write-through only");
  267. else
  268. print("; write-back type `%s' (%#o) possible",
  269. wbtype(type), type);
  270. if (mcp->setsways & (1<<11))
  271. print("; page table mapping restrictions apply");
  272. if (mcp->setsways & (1<<2))
  273. print("; M bit is set in cache type reg");
  274. print("\n");
  275. }
  276. static void
  277. prcachecfg(void)
  278. {
  279. Memcache mc;
  280. cacheinfo(1, Dcache, &mc);
  281. prcache(&mc);
  282. cacheinfo(1, Icache, &mc);
  283. prcache(&mc);
  284. }
  285. void
  286. l2cacheon(void)
  287. {
  288. ulong cfg;
  289. CpucsReg *cpu;
  290. L2uncache *l2p;
  291. cacheuwbinv();
  292. l2cacheuwbinv();
  293. l1cachesoff(); /* turns off L2 as a side effect */
  294. cpwrsc(CpDef, CpCLD, 0, 0, 0); /* GL-CPU-100: set D cache lockdown reg. */
  295. /* marvell guideline GL-CPU-130 */
  296. cpu = CPUCSREG;
  297. cfg = cpu->cpucfg | L2exists | L2ecc | Cfgiprefetch | Cfgdprefetch;
  298. if (L2writeback)
  299. cfg &= ~L2writethru; /* see PTE Cached & Buffered bits */
  300. else
  301. cfg |= L2writethru;
  302. cpu->l2cfg = cfg;
  303. coherence(); /* force l2 cache to pay attention */
  304. cpu->l2tm1 = cpu->l2tm0 = 0x66666666; /* marvell guideline GL-CPU-120 */
  305. coherence();
  306. cpwrsc(CpL2, CpTESTCFG, CpTCl2waylck, CpTCl2waylock, 0);
  307. cachedinv();
  308. l2cacheuinv();
  309. /* disable l2 caching of i/o registers */
  310. l2p = (L2uncache *)Addrl2cache;
  311. memset(l2p, 0, sizeof *l2p);
  312. /*
  313. * l2: don't cache upper half of address space.
  314. * the L2 cache is PIPT, so the addresses are physical.
  315. */
  316. l2p->win[0].base = 0x80000000 | L2enable; /* 64K multiple */
  317. l2p->win[0].size = (32*1024-1) << 16; /* 64K multiples */
  318. coherence();
  319. l2cachecfgon();
  320. l1cacheson(); /* turns L2 on as a side effect */
  321. print("l2 cache: 256K or 512K: 4 ways, 32-byte lines, write-%s, sdram only\n",
  322. cpu->l2cfg & L2writethru? "through": "back");
  323. }
  324. /* called late in main */
  325. void
  326. archconfinit(void)
  327. {
  328. m->cpuhz = 1200*1000*1000;
  329. m->delayloop = m->cpuhz/2000; /* initial estimate */
  330. fixaddrmap();
  331. // praddrmap();
  332. prcachecfg();
  333. l2cacheon();
  334. }
  335. void
  336. archkwlink(void)
  337. {
  338. }
  339. int
  340. archether(unsigned ctlno, Ether *ether)
  341. {
  342. if(ctlno >= 2)
  343. return -1;
  344. ether->type = "kirkwood";
  345. ether->port = ctlno;
  346. // ether->mbps = 1000;
  347. return 1;
  348. }
  349. /* LED/USB gpios */
  350. enum {
  351. /*
  352. * the bit assignments are MPP pin numbers from the last page of the
  353. * sheevaplug 6.0.1 schematic.
  354. */
  355. KWOEValHigh = 1<<(49-32), /* pin 49: LED pin */
  356. KWOEValLow = 1<<29, /* pin 29: USB_PWEN, pin 28: usb_pwerr */
  357. KWOELow = ~0,
  358. KWOEHigh = ~0,
  359. };
  360. /* called early in main */
  361. void
  362. archreset(void)
  363. {
  364. ulong clocks;
  365. CpucsReg *cpu;
  366. Dramctl *dram;
  367. clockshutdown(); /* watchdog disabled */
  368. /* configure gpios */
  369. ((GpioReg*)AddrGpio0)->dataout = KWOEValLow;
  370. coherence();
  371. ((GpioReg*)AddrGpio0)->dataoutena = KWOELow;
  372. ((GpioReg*)AddrGpio1)->dataout = KWOEValHigh;
  373. coherence();
  374. ((GpioReg*)AddrGpio1)->dataoutena = KWOEHigh;
  375. coherence();
  376. cpu = CPUCSREG;
  377. cpu->mempm = 0; /* turn everything on */
  378. coherence();
  379. clocks = MASK(10);
  380. clocks |= MASK(21) & ~MASK(14);
  381. clocks &= ~(1<<18 | 1<<1); /* reserved bits */
  382. cpu->clockgate |= clocks; /* enable all the clocks */
  383. cpu->l2cfg |= L2exists; /* when L2exists is 0, the l2 ignores us */
  384. coherence();
  385. dram = (Dramctl *)AddrSDramc;
  386. dram->ddrctllo &= ~(1<<6); /* marvell guideline GL-MEM-70 */
  387. *(ulong *)AddrAnalog = 0x68; /* marvell guideline GL-MISC-40 */
  388. coherence();
  389. }
  390. void
  391. archreboot(void)
  392. {
  393. iprint("reset!\n");
  394. delay(10);
  395. CPUCSREG->rstout = RstoutSoft;
  396. CPUCSREG->softreset = ResetSystem;
  397. coherence();
  398. CPUCSREG->cpucsr = Reset;
  399. coherence();
  400. delay(500);
  401. splhi();
  402. iprint("waiting...");
  403. for(;;)
  404. idlehands();
  405. }
  406. void
  407. archconsole(void)
  408. {
  409. // uartconsole(0, "b115200");
  410. //serialputs("uart0 console @ 115200\n", strlen("uart0 console @ 115200\n"));
  411. }
  412. #ifdef USE_FLASH
  413. void
  414. archflashwp(Flash*, int)
  415. {
  416. }
  417. /*
  418. * for ../port/devflash.c:/^flashreset
  419. * retrieve flash type, virtual base and length and return 0;
  420. * return -1 on error (no flash)
  421. */
  422. int
  423. archflashreset(int bank, Flash *f)
  424. {
  425. if(bank != 0)
  426. return -1;
  427. f->type = "nand";
  428. f->addr = (void*)PHYSNAND;
  429. f->size = 0; /* done by probe */
  430. f->width = 1;
  431. f->interleave = 0;
  432. return 0;
  433. }
  434. #endif