if_robo.c
上传用户:yuanda199
上传日期:2022-06-26
资源大小:412k
文件大小:12k
源码类别:

VxWorks

开发平台:

C/C++

  1. /*
  2.  * BCM53xx RoboSwitch utility functions
  3.  *
  4.  * Copyright (C) 2002 Broadcom Corporation
  5.  *
  6.  * $Id: if_robo.c,v 1.1 Broadcom SDK $
  7.  */
  8. #if 0
  9. #include <typedefs.h>
  10. #include <osl.h>
  11. #include <sbutils.h>
  12. #include <nvutils.h>
  13. #include <proto/ethernet.h>
  14. #include <etc53xx.h>
  15. #include "if_robo.h"
  16. #endif
  17. /* Missing Defines */
  18. #define OSL_IN_INTERRUPT()    1
  19. #define OSL_SLEEP(a) udelay((a))
  20. void
  21. udelay(uint usec)
  22. {
  23.     volatile int i;
  24.     for(i = 0; i < 5*usec; i++);
  25. }
  26. /* Missing Defines */
  27. int clkLen = 20;
  28. void *robo = 0;
  29. void *hSb = 0;
  30. #define robo_debug   0
  31. #if 1
  32. #undef OSL_DELAY
  33. #define OSL_DELAY(a) udelay(a)
  34. #endif
  35. robo_driver_t *robo_driver;
  36. robo_driver_t drv_table[] = {
  37.   { NULL, robosw_rreg, robosw_wreg },  
  38.   { NULL, NULL, NULL }
  39. };
  40. #define ROBO_POLL_DELAY_US 200000
  41. /* Get access to the RoboSwitch */
  42. robo_info_t *
  43. robosw_attach(void *sbh, uint32 reset, uint32 ssl, uint32 clk, uint32 mosi, uint32 miso)
  44. {
  45. robo_info_t *robo;
  46. #if 0
  47.   unsigned int flags = atoi(nvram_safe_get("boardflags"));
  48. #endif
  49.   /* set up type of register access based on board type */
  50. #if 0
  51.   if (flags & ENET_SPI) {
  52.     robo_driver = &drv_table[0];
  53.   } else if (flags & ENET_PMII) {
  54.     robo_driver = &drv_table[1];
  55.   } else {
  56. #endif
  57.     /* default to SPI*/
  58.     robo_driver = &drv_table[0];
  59. #if 0
  60.   }
  61. #endif
  62.   /* Allocate private state */
  63. if (!(robo = MALLOC(sizeof(robo_info_t)))) {
  64. printf("robo_attach: out of memory");
  65. return NULL;
  66. }
  67. bzero((char *) robo, sizeof(robo_info_t));
  68. robo->reset = reset; 
  69. robo->sbh = sbh;
  70. robo->ssl = ssl;
  71. robo->clk = clk;
  72. robo->mosi = mosi;
  73. robo->miso = miso;
  74. robo->cid = robo->page = -1;
  75. /* Initialize GPIO outputs */
  76. sb_gpioout(robo->sbh, robo->reset|robo->ssl | robo->clk | robo->mosi,
  77.    robo->ssl|robo->reset);
  78. sb_gpioouten(robo->sbh, robo->reset|robo->ssl | robo->clk | robo->mosi 
  79. | robo->miso, robo->reset|robo->ssl | robo->clk | robo->mosi);
  80. #ifdef _KERNEL_
  81. /* Initialize lock */
  82. spin_lock_init(&robo->lock);
  83. #endif
  84. return robo;
  85. }
  86. /* Release access to the RoboSwitch */
  87. void
  88. robosw_detach(robo_info_t *robo)
  89. {
  90. /* Disable GPIO outputs */
  91. sb_gpioouten(robo->sbh, robo->reset|robo->ssl | robo->clk | robo->mosi, 0);
  92. /* Free private state */
  93. MFREE(robo, sizeof(robo_info_t));
  94. }
  95. /* Enable serial access to the chip */
  96. static void
  97. robo_enable(robo_info_t *robo)
  98. {
  99. void *regs;
  100. /* Save current core index */
  101. robo->coreidx = sb_coreidx(robo->sbh);
  102. /* Switch to GPIO core for faster access */
  103. regs = sb_gpiosetcore(robo->sbh);
  104. ASSERT(regs);
  105. }
  106. /* Disable serial access to the chip */
  107. static void
  108. robo_disable(robo_info_t *robo)
  109. {
  110. /* Switch back to original core */
  111. sb_setcoreidx(robo->sbh, robo->coreidx);
  112. }
  113. /* Write a byte stream to the chip */
  114. static void
  115. robo_write(robo_info_t *robo, uint8 *buf, uint len)
  116. {
  117. uint i;
  118. uint8 mask;
  119. if (robo_debug) {
  120.     printf("%s: ", __FUNCTION__);
  121.     for (i=0; i<len ; i++) printf("0x%02X ", buf[i]);
  122.         printf("n");
  123. }
  124. for (i = 0; i < len; i++) {
  125. /* Bit bang from MSB to LSB */
  126. for (mask = 0x80; mask; mask >>= 1) {
  127. /* Clock low */
  128. sb_gpioout(robo->sbh, robo->clk, 0);
  129. OSL_DELAY(clkLen);
  130. /* Output on rising edge */
  131. if (mask & buf[i])
  132. sb_gpioout(robo->sbh, robo->mosi, robo->mosi);
  133. else
  134. sb_gpioout(robo->sbh, robo->mosi, 0);
  135. /* Clock high */
  136. sb_gpioout(robo->sbh, robo->clk, robo->clk);
  137. OSL_DELAY(clkLen);
  138. }
  139. }
  140. }
  141. /* Handy macros for writing fixed length values */
  142. #define robo_write8(robo, b) { uint8 val = (uint8) (b); robo_write((robo), &val, sizeof(val)); }
  143. #define robo_write16(robo, w) { uint16 val = (uint16) (w); robo_write((robo), &val, sizeof(val)); }
  144. #define robo_write32(robo, l) { uint32 val = (uint32) (l); robo_write((robo), &val, sizeof(val)); }
  145. /* Read a byte stream from the chip */
  146. static void
  147. robo_read(robo_info_t *robo, uint8 *buf, uint len)
  148. {
  149. uint i;
  150. uint8 rack, mask, byte;
  151. for (i = 0, rack = 0; i < len;) {
  152. /* Bit bang from MSB to LSB */
  153. for (mask = 0x80, byte = 0; mask; mask >>= 1) {
  154. /* Clock low */
  155. sb_gpioout(robo->sbh, robo->clk, 0);
  156. OSL_DELAY(clkLen);
  157.     sb_gpioout(robo->sbh, robo->mosi, 0);
  158. /* Sample */
  159. if (sb_gpioin(robo->sbh) & robo->miso)
  160. byte |= mask;
  161. /* Clock high */
  162. sb_gpioout(robo->sbh, robo->clk, robo->clk);
  163. OSL_DELAY(clkLen);
  164. }
  165.    buf[i] = byte;
  166.    i++;
  167. }
  168. if (robo_debug) {
  169.     for (; i>0; i--) printf("0x%02x ", buf[i-1]);
  170.     printf("n");
  171. }
  172. }
  173. /* poll for RACK */
  174. static int
  175. robo_poll_for_RACK(robo_info_t *robo)
  176. {
  177. uint i, timeout;
  178. uint8 byte;
  179. /* Timeout after 100 tries without RACK */
  180. for (i = 0, timeout = 100; timeout;) {
  181.     robo_read(robo, &byte, sizeof(byte));
  182. /* RACK when bit 0 is high */
  183. if (byte & 0x01)
  184. break;
  185. else
  186. {
  187.     timeout--;
  188.     /* sleep, unless in interrupt mode */
  189.     if (OSL_IN_INTERRUPT())
  190.     {
  191. #ifndef _CFE_
  192.         udelay(ROBO_POLL_DELAY_US);
  193. #else
  194. et_delay(ROBO_POLL_DELAY_US);
  195. #endif
  196. /*             OSL_DELAY(ROBO_POLL_DELAY_US);   */
  197.     }
  198.     else
  199.     {
  200.         OSL_SLEEP(ROBO_POLL_DELAY_US);
  201.          }
  202.         }
  203. }
  204. if (timeout == 0) {
  205. printf("robo_read: timeout");
  206. return -1;
  207. }
  208. return 0;
  209. }
  210. /* poll for MDIO_START low */
  211. static int
  212. robo_poll_for_MDIO_START(robo_info_t *robo, uint8 cid)
  213. {
  214. uint i, timeout;
  215. uint8 byte;
  216. uint data;
  217. /* Timeout after 100 tries without MDIO_START low */
  218. for (i = 0, timeout = 100; timeout;) {
  219.      sb_gpioout(robo->sbh, robo->ssl, 0);
  220.      robo_write8(robo, 0x60 | ((cid & 0x7) << 1));
  221.      robo_write8(robo, 0xfe);
  222.      robo_read((robo), &byte, sizeof(char));
  223.      sb_gpioout(robo->sbh, robo->ssl, robo->ssl);
  224. /* MDIO_START is bit 2 of SPI_STS */
  225. if (!(byte & 0x4))
  226. break;
  227. else
  228. {
  229.     timeout--;
  230.     data = (uint)byte;
  231.     /* sleep, unless in interrupt mode */
  232.     if (OSL_IN_INTERRUPT())
  233.     {
  234. #ifndef _CFE_
  235.         udelay(ROBO_POLL_DELAY_US);
  236. #else
  237. et_delay(ROBO_POLL_DELAY_US);
  238. #endif
  239. /*             OSL_DELAY(ROBO_POLL_DELAY_US); */
  240.     }
  241.     else
  242.     {
  243.         OSL_SLEEP(ROBO_POLL_DELAY_US);
  244.          }
  245.         }
  246. }
  247. if (timeout == 0) {
  248. printf("robo_read: timeout");
  249. return -1;
  250. }
  251. return 0;
  252. }
  253. /* Handy macros for reading fixed length values */
  254. #define robo_read8(robo) { uint8 val; robo_read((robo), &val, sizeof(val)); val; }
  255. #define robo_read16(robo) { uint16 val; robo_read((robo), &val, sizeof(val)); val; }
  256. #define robo_read32(robo) { uint32 val; robo_read((robo), &val, sizeof(val)); val; }
  257. /* Select new chip and page */
  258. static void
  259. robo_select(robo_info_t *robo, uint8 cid, uint8 page)
  260. {
  261. /* Chip and page already selected */
  262. if (robo->cid == (int) cid && robo->page == (int) page)
  263. return;
  264. robo->cid = (int) cid;
  265. robo->page = (int) page;
  266. /* Enable CS */
  267. sb_gpioout(robo->sbh, robo->ssl, 0);
  268. OSL_DELAY(clkLen);
  269. /* Select new chip */
  270. robo_write8(robo, 0x61 | ((cid & 0x7) << 1));
  271. /* Select new page */
  272. robo_write8(robo, 0xff);
  273. robo_write8(robo, page);
  274. /* Disable CS */
  275. sb_gpioout(robo->sbh, robo->ssl, robo->ssl);
  276. OSL_DELAY(clkLen);
  277. }
  278. /* Write chip register */
  279. void
  280. robosw_wreg(robo_info_t *robo, uint8 cid, uint8 page, uint8 addr, uint8 *buf, uint len)
  281. {
  282. #ifdef _KERNEL_
  283.         unsigned long flags;
  284. spin_lock_irqsave(&robo->lock, flags);
  285. #endif
  286.     
  287. robo_enable(robo);
  288.   if (robo_poll_for_MDIO_START(robo, cid))
  289.   {
  290.       /* timeout */
  291.     robo_select(robo, cid, page);
  292.       return;
  293.   }
  294. /* Select chip and page */
  295. robo_select(robo, cid, page);
  296. /* Enable CS */
  297. sb_gpioout(robo->sbh, robo->ssl, 0);
  298. OSL_DELAY(clkLen);
  299. /* Write */
  300. robo_write8(robo, 0x61 | ((cid & 0x7) << 1));
  301. robo_write8(robo, addr);
  302. robo_write(robo, buf, len);
  303. /* Disable CS */
  304. sb_gpioout(robo->sbh, robo->ssl, robo->ssl);
  305. OSL_DELAY(clkLen);
  306. robo_disable(robo);
  307. #ifdef _KERNEL_
  308. spin_unlock_irqrestore(&robo->lock, flags);
  309. #endif
  310. }
  311. /* Read chip register */
  312. void
  313. robosw_rreg(robo_info_t *robo, uint8 cid, uint8 page, uint8 addr, uint8 *buf, uint len)
  314. {
  315. #ifdef _KERNEL_
  316.         unsigned long flags;
  317. spin_lock_irqsave(&robo->lock, flags);
  318. #endif
  319.   robo_enable(robo);
  320.   
  321.   if (robo_poll_for_MDIO_START(robo,cid))
  322.       /* timeout */
  323.       return;
  324. /* Select chip and page */
  325. robo_select(robo, cid, page);
  326. /* Enable CS */
  327. sb_gpioout(robo->sbh, robo->ssl, 0);
  328.         /*delay so uP have sufficient time to prepare data */
  329. OSL_DELAY(clkLen);    
  330. /* Fast read */
  331. robo_write8(robo, 0x10 | ((cid & 0x7) << 1));
  332. OSL_DELAY(clkLen);
  333. robo_write8(robo, addr);
  334. OSL_DELAY(clkLen);
  335. if (robo_poll_for_RACK(robo))
  336.     /* timeout */
  337.     return;
  338.   robo_read(robo, buf, len);
  339. /* Disable CS */
  340. sb_gpioout(robo->sbh, robo->ssl, robo->ssl);
  341. OSL_DELAY(clkLen);
  342. robo_disable(robo);
  343. #ifdef _KERNEL_
  344. spin_unlock_irqrestore(&robo->lock, flags);
  345. #endif
  346. }
  347. #define sb_doattach(a, b, c, d, e, f)  sb_attach((a), (b), (c), (e), (f))
  348. /* generic kernel variant of sb_attach() */
  349. void*
  350. sb_robo_kattach()
  351. {
  352. #if 0
  353.     char *unused;
  354.     int varsz;
  355.     return (sb_doattach(BCM4710_DEVICE_ID, NULL, (void*)REG_MAP(SB_ENUM_BASE, SB_CORE_SIZE),
  356.         SB_BUS, &unused, &varsz));
  357. #else
  358.     return (sb_kattach (BCM4710_DEVICE_ID, 0));
  359. #endif
  360. }
  361. /*
  362.  * Init API
  363.  */
  364. void *
  365. bcm_robo_api_init()
  366. {
  367.     if (!(hSb = sb_robo_kattach()))
  368.         return 0;
  369.     if (!(robo = robosw_attach(hSb, 1, (1 << 2), (1 << 3), (1 << 4), (1 << 5))))
  370.         return 0;
  371.     /* sema_init (&robo_sema, 1);*/
  372.     return robo;
  373. }
  374. uint8 tr_buf[256];
  375. int
  376. tr_wreg(uint8 cid, uint8 page, uint8 addr, uint len)
  377. {
  378.     int i;
  379.     uint8 *buf;
  380.     if (robo == NULL) { bcm_robo_api_init(); }
  381.     buf = tr_buf;
  382.     robosw_wreg(robo, cid, page, addr, buf, len);
  383.     printf("robo = %p cid = %d page = %d addr = %02x len = %dn",
  384.             robo, cid, page, addr, len);
  385.     for(i = 0; i < len; i++) {
  386.         if (!(i % 16)) printf("n");
  387.         printf(" %02X", (unsigned int)buf[i] & 0xFF);
  388.     }
  389.     return(0);
  390. }
  391. int
  392. tr_rreg(uint8 cid, uint8 page, uint8 addr, uint len)
  393. {
  394.     uint8 buf[256];
  395.     int i;
  396.     if (robo == NULL) { bcm_robo_api_init(); }
  397.     robosw_rreg(robo, cid, page, addr, buf, len);
  398.     printf("robo = %p cid = %d page = %d addr = %02x len = %dn",
  399.             robo, cid, page, addr, len);
  400.     for(i = 0; i < len; i++) {
  401.         if (!(i % 16)) printf("n");
  402.         printf(" %02X", (unsigned int)buf[i] & 0xFF);
  403.     }
  404.     return(0);
  405. }
  406. int
  407. robo_tcl_wreg(uint8 cid, uint8 page, uint8 addr, uint8 *buf, uint len)
  408. {
  409.     int i;
  410.     if (robo == NULL) { bcm_robo_api_init(); }
  411.     if (gSPIEnable)
  412.         robosw_wreg(robo, cid, page, addr, buf, len);
  413.     else 
  414. robo_mdio_wreg(cid, page, addr, buf, len);
  415.     if (robo_debug) {
  416.         printf("Write Reg: robo = %p cid = %d page = %d addr = %02x len = %dn",
  417.                 robo, cid, page, addr, len);
  418.         for(i = 0; i < len; i++) {
  419.             if (!(i % 16)) printf("n");
  420.             printf(" %02X", (unsigned int)buf[i] & 0xFF);
  421.         }
  422.     }
  423.     return(0);
  424. }
  425. int
  426. robo_tcl_rreg(uint8 cid, uint8 page, uint8 addr, uint8* buf, uint len)
  427. {
  428.     int i;
  429.     if (robo == NULL) { bcm_robo_api_init(); }
  430.     if (gSPIEnable)
  431.         robosw_rreg(robo, cid, page, addr, buf, len);
  432.     else
  433.    robo_mdio_rreg(cid, page, addr, buf, len);
  434.     if (robo_debug) {
  435.         printf("Read Reg: robo = %p cid = %d page = %d addr = %02x len = %dn",
  436.                 robo, cid, page, addr, len);
  437.         for(i = 0; i < len; i++) {
  438.             if (!(i % 16)) printf("n");
  439.             printf(" %02X", (unsigned int)buf[i] & 0xFF);
  440.         }
  441.     }
  442.     return(0);
  443. }
  444. /* reset robo chips*/
  445. int robo_reset(void)
  446. { robo_info_t *p ;
  447. if (robo == NULL) {
  448.     if (!bcm_robo_api_init()) {
  449. printf("Err: unable to attach to robo devicen"); 
  450. return (1);
  451.     }
  452. }
  453. p = (robo_info_t *) robo;
  454. sb_gpioout(p->sbh, p->reset, p->reset);
  455. OSL_DELAY(10);
  456. sb_gpioout(p->sbh, p->reset, 0);
  457. OSL_DELAY(10);
  458. sb_gpioout(p->sbh, p->reset, p->reset);
  459. robosw_detach(robo);
  460. robo = 0;
  461. robo_mdio_reset();
  462. return(0);
  463. }