PageRenderTime 29ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/drivers/ti1225/ti1225.c

http://www.minix3.org/
C | 434 lines | 329 code | 64 blank | 41 comment | 68 complexity | 4b03ea0391a5c0574f882b37bca1ee0f MD5 | raw file
Possible License(s): MIT, WTFPL, AGPL-1.0, BSD-3-Clause, GPL-3.0, LGPL-2.0, JSON, 0BSD
  1. /*
  2. ti1225.c
  3. Created: Dec 2005 by Philip Homburg
  4. */
  5. #include <minix/drivers.h>
  6. #include <minix/driver.h>
  7. #include <machine/pci.h>
  8. #include <machine/vm.h>
  9. #include <sys/mman.h>
  10. #include "ti1225.h"
  11. #include "i82365.h"
  12. /* The use of interrupts is not yet ready for prime time */
  13. #define USE_INTS 0
  14. static struct port
  15. {
  16. int p_devind;
  17. u8_t p_cb_busnr;
  18. u16_t p_exca_port;
  19. #if USE_INTS
  20. int p_irq;
  21. int p_hook;
  22. #endif
  23. volatile struct csr *csr_ptr;
  24. } port;
  25. static int instance;
  26. static int debug;
  27. static int hw_probe(int skip);
  28. static void hw_init(struct port *pp, int devind);
  29. static void do_int(struct port *pp);
  30. /* SEF functions and variables. */
  31. static void sef_local_startup(void);
  32. static int sef_cb_init_fresh(int type, sef_init_info_t *info);
  33. /*===========================================================================*
  34. * main *
  35. *===========================================================================*/
  36. int main(int argc, char *argv[])
  37. {
  38. int r;
  39. message m;
  40. int ipc_status;
  41. /* SEF local startup. */
  42. env_setargs(argc, argv);
  43. sef_local_startup();
  44. for (;;)
  45. {
  46. r= driver_receive(ANY, &m, &ipc_status);
  47. if (r != OK)
  48. panic("driver_receive failed: %d", r);
  49. printf("ti1225: got message %u from %d\n",
  50. m.m_type, m.m_source);
  51. }
  52. return 0;
  53. }
  54. /*===========================================================================*
  55. * sef_local_startup *
  56. *===========================================================================*/
  57. static void sef_local_startup()
  58. {
  59. /* Register init callbacks. */
  60. sef_setcb_init_fresh(sef_cb_init_fresh);
  61. sef_setcb_init_lu(sef_cb_init_fresh);
  62. sef_setcb_init_restart(sef_cb_init_fresh);
  63. /* Register live update callbacks. */
  64. sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
  65. sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard);
  66. /* Let SEF perform startup. */
  67. sef_startup();
  68. }
  69. /*===========================================================================*
  70. * sef_cb_init_fresh *
  71. *===========================================================================*/
  72. static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
  73. {
  74. /* Initialize the ti1225 driver. */
  75. int r, devind;
  76. long v;
  77. if((r=tsc_calibrate()) != OK)
  78. panic("tsc_calibrate failed: %d", r);
  79. v = 0;
  80. (void) env_parse("instance", "d", 0, &v, 0, 255);
  81. instance = (int) v;
  82. v = 0;
  83. (void) env_parse("debug", "d", 0, &v, 0, 1);
  84. debug = (int) v;
  85. devind = hw_probe(instance);
  86. if (devind < 0)
  87. return(ENODEV);
  88. hw_init(&port, devind);
  89. return(OK);
  90. }
  91. /*===========================================================================*
  92. * hw_probe *
  93. *===========================================================================*/
  94. static int hw_probe(int skip)
  95. {
  96. u16_t vid, did;
  97. int devind;
  98. pci_init();
  99. if (pci_first_dev(&devind, &vid, &did) != 1)
  100. return(-1);
  101. while (skip--)
  102. if (pci_next_dev(&devind, &vid, &did) != 1)
  103. return(-1);
  104. pci_reserve(devind);
  105. if (debug)
  106. printf("ti1225: found device %04x/%04x\n", vid, did);
  107. return(devind);
  108. }
  109. /*===========================================================================*
  110. * hw_init *
  111. *===========================================================================*/
  112. static void hw_init(struct port *pp, int devind)
  113. {
  114. u8_t v8;
  115. u16_t v16;
  116. u32_t v32;
  117. #if USE_INTS
  118. int r, irq;
  119. #endif
  120. pp->p_devind= devind;
  121. if (debug)
  122. printf("hw_init: devind = %d\n", devind);
  123. if (debug)
  124. {
  125. v16= pci_attr_r16(devind, PCI_CR);
  126. printf("ti1225: command register 0x%x\n", v16);
  127. }
  128. v32= pci_attr_r32(devind, TI_CB_BASEADDR);
  129. if (debug)
  130. printf("ti1225: Cardbus/ExCA base address 0x%x\n", v32);
  131. v32 &= PCI_BAR_MEM_MASK; /* Clear low order bits in base */
  132. pp->csr_ptr=
  133. (struct csr *) vm_map_phys(SELF, (void *) v32, PAGE_SIZE);
  134. if (pp->csr_ptr == MAP_FAILED)
  135. panic("hw_init: vm_map_phys failed");
  136. if (debug)
  137. {
  138. v8= pci_attr_r8(devind, TI_PCI_BUS_NR);
  139. printf("ti1225: PCI bus number %d\n", v8);
  140. }
  141. v8= pci_attr_r8(devind, TI_CB_BUS_NR);
  142. pp->p_cb_busnr= v8;
  143. if (debug)
  144. {
  145. printf("ti1225: CardBus bus number %d\n", v8);
  146. v8= pci_attr_r8(devind, TI_SO_BUS_NR);
  147. printf("ti1225: Subordinate bus number %d\n", v8);
  148. }
  149. #if USE_INTS
  150. irq= pci_attr_r8(devind, PCI_ILR);
  151. pp->p_irq= irq;
  152. printf("ti1225 using IRQ %d\n", irq);
  153. #endif
  154. v32= pci_attr_r32(devind, TI_LEGACY_BA);
  155. v32 &= ~1;
  156. if (debug)
  157. {
  158. printf("ti1225: PC Card 16-bit legacy-mode base address 0x%x\n",
  159. v32);
  160. }
  161. if (v32 == 0)
  162. panic("bad legacy-mode base address: %d", v32);
  163. pp->p_exca_port= v32;
  164. if (debug)
  165. {
  166. v32= pci_attr_r32(devind, TI_MF_ROUTE);
  167. printf("ti1225: Multifunction routing 0x%08x\n", v32);
  168. }
  169. #if USE_INTS
  170. pp->p_hook = pp->p_irq;
  171. r= sys_irqsetpolicy(pp->p_irq, 0, &pp->p_hook);
  172. if (r != OK)
  173. panic("sys_irqsetpolicy failed: %d", r);
  174. #endif
  175. /* Clear CBB_BC_INTEXCA */
  176. v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
  177. if (debug)
  178. printf("ti1225: Bridge control 0x%04x\n", v16);
  179. v16 &= ~CBB_BC_INTEXCA;
  180. pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
  181. if (debug)
  182. {
  183. v32= pci_attr_r32(devind, TI_SYSCTRL);
  184. printf("ti1225: System Control Register 0x%08x\n", v32);
  185. v8= pci_attr_r8(devind, TI_CARD_CTRL);
  186. printf("ti1225: Card Control 0x%02x\n", v8);
  187. v8= pci_attr_r8(devind, TI_DEV_CTRL);
  188. printf("ti1225: Device Control 0x%02x\n", v8);
  189. }
  190. /* Enable socket interrupts */
  191. pp->csr_ptr->csr_mask |= CM_PWRMASK | CM_CDMASK | CM_CSTSMASK;
  192. do_int(pp);
  193. #if USE_INTS
  194. r= sys_irqenable(&pp->p_hook);
  195. if (r != OK)
  196. panic("unable enable interrupts: %d", r);
  197. #endif
  198. }
  199. /*===========================================================================*
  200. * do_int *
  201. *===========================================================================*/
  202. static void do_int(struct port *pp)
  203. {
  204. int devind, vcc_5v, vcc_3v, vcc_Xv, vcc_Yv,
  205. socket_5v, socket_3v, socket_Xv, socket_Yv;
  206. spin_t spin;
  207. u32_t csr_event, csr_present, csr_control;
  208. u8_t v8;
  209. u16_t v16;
  210. #if USE_INTS
  211. int r;
  212. #endif
  213. devind= pp->p_devind;
  214. v8= pci_attr_r8(devind, TI_CARD_CTRL);
  215. if (v8 & TI_CCR_IFG)
  216. {
  217. printf("ti1225: got functional interrupt\n");
  218. pci_attr_w8(devind, TI_CARD_CTRL, v8);
  219. }
  220. if (debug)
  221. {
  222. printf("Socket event: 0x%x\n", pp->csr_ptr->csr_event);
  223. printf("Socket mask: 0x%x\n", pp->csr_ptr->csr_mask);
  224. }
  225. csr_present= pp->csr_ptr->csr_present;
  226. csr_control= pp->csr_ptr->csr_control;
  227. if ((csr_present & (CP_CDETECT1|CP_CDETECT2)) != 0)
  228. {
  229. if (debug)
  230. printf("do_int: no card present\n");
  231. return;
  232. }
  233. if (csr_present & CP_BADVCCREQ)
  234. {
  235. printf("do_int: Bad Vcc request\n");
  236. /* return; */
  237. }
  238. if (csr_present & CP_DATALOST)
  239. {
  240. /* Do we care? */
  241. if (debug)
  242. printf("do_int: Data lost\n");
  243. /* return; */
  244. }
  245. if (csr_present & CP_NOTACARD)
  246. {
  247. printf("do_int: Not a card\n");
  248. return;
  249. }
  250. if (debug)
  251. {
  252. if (csr_present & CP_CBCARD)
  253. printf("do_int: Cardbus card detected\n");
  254. if (csr_present & CP_16BITCARD)
  255. printf("do_int: 16-bit card detected\n");
  256. }
  257. if (csr_present & CP_PWRCYCLE)
  258. {
  259. if (debug)
  260. printf("do_int: powered up\n");
  261. return;
  262. }
  263. vcc_5v= !!(csr_present & CP_5VCARD);
  264. vcc_3v= !!(csr_present & CP_3VCARD);
  265. vcc_Xv= !!(csr_present & CP_XVCARD);
  266. vcc_Yv= !!(csr_present & CP_YVCARD);
  267. if (debug)
  268. {
  269. printf("do_int: card supports:%s%s%s%s\n",
  270. vcc_5v ? " 5V" : "", vcc_3v ? " 3V" : "",
  271. vcc_Xv ? " X.X V" : "", vcc_Yv ? " Y.Y V" : "");
  272. }
  273. socket_5v= !!(csr_present & CP_5VSOCKET);
  274. socket_3v= !!(csr_present & CP_3VSOCKET);
  275. socket_Xv= !!(csr_present & CP_XVSOCKET);
  276. socket_Yv= !!(csr_present & CP_YVSOCKET);
  277. if (debug)
  278. {
  279. printf("do_int: socket supports:%s%s%s%s\n",
  280. socket_5v ? " 5V" : "", socket_3v ? " 3V" : "",
  281. socket_Xv ? " X.X V" : "", socket_Yv ? " Y.Y V" : "");
  282. }
  283. if (vcc_5v && socket_5v)
  284. {
  285. csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_5V;
  286. pp->csr_ptr->csr_control= csr_control;
  287. if (debug)
  288. printf("do_int: applying 5V\n");
  289. }
  290. else if (vcc_3v && socket_3v)
  291. {
  292. csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_3V;
  293. pp->csr_ptr->csr_control= csr_control;
  294. if (debug)
  295. printf("do_int: applying 3V\n");
  296. }
  297. else if (vcc_Xv && socket_Xv)
  298. {
  299. csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_XV;
  300. pp->csr_ptr->csr_control= csr_control;
  301. printf("do_int: applying X.X V\n");
  302. }
  303. else if (vcc_Yv && socket_Yv)
  304. {
  305. csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_YV;
  306. pp->csr_ptr->csr_control= csr_control;
  307. printf("do_int: applying Y.Y V\n");
  308. }
  309. else
  310. {
  311. printf("do_int: socket and card are not compatible\n");
  312. return;
  313. }
  314. csr_event= pp->csr_ptr->csr_event;
  315. if (csr_event)
  316. {
  317. if (debug)
  318. printf("clearing socket event\n");
  319. pp->csr_ptr->csr_event= csr_event;
  320. if (debug)
  321. {
  322. printf("Socket event (cleared): 0x%x\n",
  323. pp->csr_ptr->csr_event);
  324. }
  325. }
  326. devind= pp->p_devind;
  327. v8= pci_attr_r8(devind, TI_CARD_CTRL);
  328. if (v8 & TI_CCR_IFG)
  329. {
  330. printf("ti1225: got functional interrupt\n");
  331. pci_attr_w8(devind, TI_CARD_CTRL, v8);
  332. }
  333. if (debug)
  334. {
  335. v8= pci_attr_r8(devind, TI_CARD_CTRL);
  336. printf("TI_CARD_CTRL: 0x%02x\n", v8);
  337. }
  338. spin_init(&spin, 100000);
  339. do {
  340. csr_present= pp->csr_ptr->csr_present;
  341. if (csr_present & CP_PWRCYCLE)
  342. break;
  343. } while (spin_check(&spin));
  344. if (!(csr_present & CP_PWRCYCLE))
  345. {
  346. printf("do_int: not powered up?\n");
  347. return;
  348. }
  349. /* Reset device */
  350. v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
  351. v16 |= CBB_BC_CRST;
  352. pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
  353. /* Wait one microsecond. Is this correct? What are the specs? */
  354. micro_delay(1);
  355. /* Clear CBB_BC_CRST */
  356. v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
  357. v16 &= ~CBB_BC_CRST;
  358. pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
  359. /* Wait one microsecond after clearing the reset line. Is this
  360. * correct? What are the specs?
  361. */
  362. micro_delay(1);
  363. pci_rescan_bus(pp->p_cb_busnr);
  364. #if USE_INTS
  365. r= sys_irqenable(&pp->p_hook);
  366. if (r != OK)
  367. panic("unable enable interrupts: %d", r);
  368. #endif
  369. }