archkw.c 11 KB

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