km8xx_hdlc_enet.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /*
  2. * (C) Copyright 2008
  3. * Gary Jennejohn, DENX Software Engineering GmbH, garyj@denx.de.
  4. *
  5. * Based in part on cpu/mpc8xx/scc.c.
  6. *
  7. * See file CREDITS for list of people who contributed to this
  8. * project.
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License as
  12. * published by the Free Software Foundation; either version 2 of
  13. * the License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  23. * MA 02111-1307 USA
  24. */
  25. #include <common.h> /* commproc.h is included here */
  26. #include <malloc.h>
  27. #include <net.h>
  28. #ifdef CONFIG_KEYMILE_HDLC_ENET
  29. #include "../common/keymile_hdlc_enet.h"
  30. char keymile_slot; /* our slot number in the backplane */
  31. /*
  32. * Since, except during initialization, ethact is always HDLC ETHERNET
  33. * while we're in the driver, just use serial_printf() everywhere for
  34. * output. This avoids possible conflicts when netconsole is being
  35. * used.
  36. */
  37. #define dprintf(fmt, args...) serial_printf(fmt, ##args)
  38. static int already_inited;
  39. /*
  40. * SCC Ethernet Tx and Rx buffer descriptors allocated at the
  41. * immr->udata_bd address on Dual-Port RAM
  42. * Provide for Double Buffering
  43. */
  44. typedef volatile struct CommonBufferDescriptor {
  45. cbd_t txbd; /* Tx BD */
  46. cbd_t rxbd[HDLC_PKTBUFSRX]; /* Rx BD */
  47. } RTXBD;
  48. static RTXBD *rtx;
  49. int keymile_hdlc_enet_init(struct eth_device *, bd_t *);
  50. void keymile_hdlc_enet_halt(struct eth_device *);
  51. extern void keymile_hdlc_enet_init_bds(RTXBD *);
  52. extern void initCachedNumbers(int);
  53. /* Use SCC4 */
  54. #define MGS_CPM_CR_HDLC CPM_CR_CH_SCC4
  55. #define MGS_PROFF_HDLC PROFF_SCC4
  56. #define MGS_SCC_HDLC 3 /* Index, not number! */
  57. int keymile_hdlc_enet_init(struct eth_device *dev, bd_t *bis)
  58. {
  59. /* int i; */
  60. /* volatile cbd_t *bdp; */
  61. volatile cpm8xx_t *cp;
  62. volatile scc_t *sccp;
  63. volatile hdlc_pram_t *hpr;
  64. volatile iop8xx_t *iop;
  65. if (already_inited)
  66. return 0;
  67. cp = (cpm8xx_t *)&(((volatile immap_t *)CONFIG_SYS_IMMR)->im_cpm);
  68. hpr = (hdlc_pram_t *)(&cp->cp_dparam[MGS_PROFF_HDLC]);
  69. sccp = (volatile scc_t *)(&cp->cp_scc[MGS_SCC_HDLC]);
  70. iop = (iop8xx_t *)&(((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport);
  71. /*
  72. * Disable receive and transmit just in case.
  73. */
  74. sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
  75. #ifndef CONFIG_SYS_ALLOC_DPRAM
  76. #error "CONFIG_SYS_ALLOC_DPRAM must be defined"
  77. #else
  78. /*
  79. * Avoid exhausting DPRAM, which would cause a panic.
  80. * Actually this isn't really necessary, but leave it here
  81. * for safety's sake.
  82. */
  83. if (rtx == NULL) {
  84. rtx = (RTXBD *) (cp->cp_dpmem +
  85. dpram_alloc_align(sizeof(RTXBD), 8));
  86. if (rtx == (RTXBD *)CPM_DP_NOSPACE)
  87. return -1;
  88. memset((void *)rtx, 0, sizeof(RTXBD));
  89. }
  90. #endif /* !CONFIG_SYS_ALLOC_DPRAM */
  91. /* We need the slot number for addressing. */
  92. keymile_slot = *(char *)(CONFIG_SYS_SLOT_ID_BASE +
  93. CONFIG_SYS_SLOT_ID_OFF) & CONFIG_SYS_SLOT_ID_MASK;
  94. /*
  95. * Be consistent with the Linux driver and set
  96. * only enetaddr[0].
  97. *
  98. * Always add 1 to the slot number so that
  99. * there are no problems with an ethaddr which
  100. * is all 0s. This should be acceptable because
  101. * a board should never have a slot number of 255,
  102. * which is the broadcast address. The HDLC addressing
  103. * uses only the slot number.
  104. */
  105. dev->enetaddr[0] = keymile_slot + 1;
  106. #ifdef TEST_IT
  107. dprintf("slot %d\n", keymile_slot);
  108. #endif
  109. /* use pa8, pa9 pins for TXD4, RXD4 respectively */
  110. iop->iop_papar |= ((0x8000 >> 8) | (0x8000 >> 9));
  111. iop->iop_padir &= ~((0x8000 >> 8) | (0x8000 >> 9));
  112. iop->iop_paodr &= ~((0x8000 >> 8) | (0x8000 >> 9));
  113. /* also use pa0 as CLK8 */
  114. iop->iop_papar |= 0x8000;
  115. iop->iop_padir &= ~0x8000;
  116. iop->iop_paodr &= ~0x8000;
  117. /* use pc5 as CTS4 */
  118. iop->iop_pcpar &= ~(0x8000 >> 5);
  119. iop->iop_pcdir &= ~(0x8000 >> 5);
  120. iop->iop_pcso |= (0x8000 >> 5);
  121. /*
  122. * SI clock routing
  123. * use CLK8
  124. * this also connects SCC4 to NMSI
  125. */
  126. cp->cp_sicr = (cp->cp_sicr & ~0xff000000) | 0x3f000000;
  127. /* keymile_rxIdx = 0; */
  128. /*
  129. * Initialize function code registers for big-endian.
  130. */
  131. hpr->rfcr = SCC_EB;
  132. hpr->tfcr = SCC_EB;
  133. /*
  134. * Set maximum bytes per receive buffer.
  135. */
  136. hpr->mrblr = MAX_FRAME_LENGTH;
  137. /* Setup CRC generator values for HDLC */
  138. hpr->c_mask = 0x0000F0B8;
  139. hpr->c_pres = 0x0000FFFF;
  140. /* Initialize all error counters to 0 */
  141. hpr->disfc = 0;
  142. hpr->crcec = 0;
  143. hpr->abtsc = 0;
  144. hpr->nmarc = 0;
  145. hpr->retrc = 0;
  146. /* Set maximum frame length size */
  147. hpr->mflr = MAX_FRAME_LENGTH;
  148. /* set to 1 for per frame processing change later if needed */
  149. hpr->rfthr = 1;
  150. hpr->hmask = 0xff;
  151. hpr->haddr2 = SET_HDLC_UUA(keymile_slot);
  152. hpr->haddr3 = hpr->haddr2;
  153. hpr->haddr4 = hpr->haddr2;
  154. /* broadcast */
  155. hpr->haddr1 = HDLC_BCAST;
  156. hpr->rbase = (unsigned int) &rtx->rxbd[0];
  157. hpr->tbase = (unsigned int) &rtx->txbd;
  158. #if 0
  159. /*
  160. * Initialize the buffer descriptors.
  161. */
  162. bdp = &rtx->txbd;
  163. bdp->cbd_sc = 0;
  164. bdp->cbd_bufaddr = 0;
  165. bdp->cbd_sc = BD_SC_WRAP;
  166. /*
  167. * Setup RX packet buffers, aligned correctly.
  168. * Borrowed from net/net.c.
  169. */
  170. MyRxPackets[0] = &MyPktBuf[0] + (PKTALIGN - 1);
  171. MyRxPackets[0] -= (ulong)MyRxPackets[0] % PKTALIGN;
  172. for (i = 1; i < HDLC_PKTBUFSRX; i++)
  173. MyRxPackets[i] = MyRxPackets[0] + i * PKT_MAXBLR_SIZE;
  174. bdp = &rtx->rxbd[0];
  175. for (i = 0; i < HDLC_PKTBUFSRX; i++) {
  176. bdp->cbd_sc = BD_SC_EMPTY;
  177. /* Leave space at the start for INET header. */
  178. bdp->cbd_bufaddr = (unsigned int)(MyRxPackets[i] +
  179. INET_HDR_ALIGN);
  180. bdp++;
  181. }
  182. bdp--;
  183. bdp->cbd_sc |= BD_SC_WRAP;
  184. #else
  185. keymile_hdlc_enet_init_bds(rtx);
  186. #endif
  187. /* Let's re-initialize the channel now. We have to do it later
  188. * than the manual describes because we have just now finished
  189. * the BD initialization.
  190. */
  191. cp->cp_cpcr = mk_cr_cmd(MGS_CPM_CR_HDLC, CPM_CR_INIT_TRX) | CPM_CR_FLG;
  192. while (cp->cp_cpcr & CPM_CR_FLG);
  193. sccp->scc_gsmrl = SCC_GSMRL_MODE_HDLC;
  194. /* CTSS=1 */
  195. sccp->scc_gsmrh = SCC_GSMRH_CTSS;
  196. /* NOF=0, RTE=1, DRT=0, BUS=1 */
  197. sccp->scc_psmr = ((0x8000 >> 6) | (0x8000 >> 10));
  198. /* loopback for local testing */
  199. #ifdef GJTEST
  200. dprintf("LOOPBACK!\n");
  201. sccp->scc_gsmrl |= SCC_GSMRL_DIAG_LOOP;
  202. #endif
  203. /*
  204. * Disable all interrupts and clear all pending
  205. * events.
  206. */
  207. sccp->scc_sccm = 0;
  208. sccp->scc_scce = 0xffff;
  209. /*
  210. * And last, enable the transmit and receive processing.
  211. */
  212. sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
  213. dprintf("%s: HDLC ENET Version 0.3 on SCC%d\n", dev->name,
  214. MGS_SCC_HDLC + 1);
  215. /*
  216. * We may not get an ARP packet because ARP was already done on
  217. * a different interface, so initialize the cached values now.
  218. */
  219. initCachedNumbers(1);
  220. already_inited = 1;
  221. return 0;
  222. }
  223. void keymile_hdlc_enet_halt(struct eth_device *dev)
  224. {
  225. #if 0 /* just return, but keep this for reference */
  226. volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
  227. /* maybe should do a graceful stop here? */
  228. immr->im_cpm.cp_scc[MGS_SCC_HDLC].scc_gsmrl &=
  229. ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
  230. #endif
  231. }
  232. #endif /* CONFIG_KEYMILE_HDLC_ENET */