mgcoge_hdlc_enet.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /*
  2. * (C) Copyright 2008
  3. * Gary Jennejohn, DENX Software Engineering GmbH, garyj@denx.de.
  4. *
  5. * Based in part on cpu/mpc8260/ether_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>
  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 SCC1 */
  54. #define CPM_CR_SCC_PAGE CPM_CR_SCC1_PAGE
  55. #define CPM_CR_SCC_SBLOCK CPM_CR_SCC1_SBLOCK
  56. #define CMXSCR_MASK (CMXSCR_GR1|CMXSCR_SC1|\
  57. CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
  58. #define CMXSCR_VALUE (CMXSCR_RS1CS_CLK11|CMXSCR_TS1CS_CLK11)
  59. #define MGC_PROFF_HDLC PROFF_SCC1
  60. #define MGC_SCC_HDLC 0 /* Index, not number! */
  61. int keymile_hdlc_enet_init(struct eth_device *dev, bd_t *bis)
  62. {
  63. /* int i; */
  64. uint dpr;
  65. /* volatile cbd_t *bdp; */
  66. volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
  67. volatile cpm8260_t *cp = &(im->im_cpm);
  68. volatile scc_t *sccp;
  69. volatile scc_hdlc_t *hpr;
  70. volatile iop8260_t *iop;
  71. if (already_inited)
  72. return 0;
  73. hpr = (scc_hdlc_t *)(&im->im_dprambase[MGC_PROFF_HDLC]);
  74. sccp = (scc_t *)(&im->im_scc[MGC_SCC_HDLC]);
  75. iop = &im->im_ioport;
  76. /*
  77. * Disable receive and transmit just in case.
  78. */
  79. sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
  80. /*
  81. * Avoid exhausting DPRAM, which would cause a panic.
  82. */
  83. if (rtx == NULL) {
  84. /* dpr is an offset into dpram */
  85. dpr = m8260_cpm_dpalloc(sizeof(RTXBD), 8);
  86. rtx = (RTXBD *)&im->im_dprambase[dpr];
  87. }
  88. /* We need the slot number for addressing. */
  89. keymile_slot = *(char *)(CONFIG_SYS_SLOT_ID_BASE +
  90. CONFIG_SYS_SLOT_ID_OFF) & CONFIG_SYS_SLOT_ID_MASK;
  91. /*
  92. * Be consistent with the Linux driver and set
  93. * only enetaddr[0].
  94. *
  95. * Always add 1 to the slot number so that
  96. * there are no problems with an ethaddr which
  97. * is all 0s. This should be acceptable because
  98. * a board should never have a slot number of 255,
  99. * which is the broadcast address. The HDLC addressing
  100. * uses only the slot number.
  101. */
  102. dev->enetaddr[0] = keymile_slot + 1;
  103. #ifdef TEST_IT
  104. dprintf("slot %d\n", keymile_slot);
  105. #endif
  106. /* use pd30, pd31 pins for TXD1, RXD1 respectively */
  107. iop->iop_ppard |= (0x80000000 >> 30) | (0x80000000 >> 31);
  108. iop->iop_pdird |= (0x80000000 >> 30);
  109. iop->iop_psord |= (0x80000000 >> 30);
  110. /* use pc21 as CLK11 */
  111. iop->iop_pparc |= (0x80000000 >> 21);
  112. iop->iop_pdirc &= ~(0x80000000 >> 21);
  113. iop->iop_psorc &= ~(0x80000000 >> 21);
  114. /* use pc15 as CTS1 */
  115. iop->iop_pparc |= (0x80000000 >> 15);
  116. iop->iop_pdirc &= ~(0x80000000 >> 15);
  117. iop->iop_psorc &= ~(0x80000000 >> 15);
  118. /*
  119. * SI clock routing
  120. * use CLK11
  121. * this also connects SCC1 to NMSI
  122. */
  123. im->im_cpmux.cmx_scr = (im->im_cpmux.cmx_scr & ~CMXSCR_MASK) |
  124. CMXSCR_VALUE;
  125. /* keymile_rxIdx = 0; */
  126. /*
  127. * Initialize function code registers for big-endian.
  128. */
  129. hpr->sh_genscc.scc_rfcr = CPMFCR_EB;
  130. hpr->sh_genscc.scc_tfcr = CPMFCR_EB;
  131. /*
  132. * Set maximum bytes per receive buffer.
  133. */
  134. hpr->sh_genscc.scc_mrblr = MAX_FRAME_LENGTH;
  135. /* Setup CRC generator values for HDLC */
  136. hpr->sh_cmask = 0x0000F0B8;
  137. hpr->sh_cpres = 0x0000FFFF;
  138. /* Initialize all error counters to 0 */
  139. hpr->sh_disfc = 0;
  140. hpr->sh_crcec = 0;
  141. hpr->sh_abtsc = 0;
  142. hpr->sh_nmarc = 0;
  143. hpr->sh_retrc = 0;
  144. /* Set maximum frame length size */
  145. hpr->sh_mflr = MAX_FRAME_LENGTH;
  146. /* set to 1 for per frame processing change later if needed */
  147. hpr->sh_rfthr = 1;
  148. hpr->sh_hmask = 0xff;
  149. hpr->sh_haddr2 = SET_HDLC_UUA(keymile_slot);
  150. hpr->sh_haddr3 = hpr->sh_haddr2;
  151. hpr->sh_haddr4 = hpr->sh_haddr2;
  152. /* broadcast */
  153. hpr->sh_haddr1 = HDLC_BCAST;
  154. hpr->sh_genscc.scc_rbase = (unsigned int) &rtx->rxbd[0];
  155. hpr->sh_genscc.scc_tbase = (unsigned int) &rtx->txbd;
  156. #if 0
  157. /*
  158. * Initialize the buffer descriptors.
  159. */
  160. bdp = &rtx->txbd;
  161. bdp->cbd_sc = 0;
  162. bdp->cbd_bufaddr = 0;
  163. bdp->cbd_sc = BD_SC_WRAP;
  164. /*
  165. * Setup RX packet buffers, aligned correctly.
  166. * Borrowed from net/net.c.
  167. */
  168. MyRxPackets[0] = &MyPktBuf[0] + (PKTALIGN - 1);
  169. MyRxPackets[0] -= (ulong)MyRxPackets[0] % PKTALIGN;
  170. for (i = 1; i < HDLC_PKTBUFSRX; i++)
  171. MyRxPackets[i] = MyRxPackets[0] + i * PKT_MAXBLR_SIZE;
  172. bdp = &rtx->rxbd[0];
  173. for (i = 0; i < HDLC_PKTBUFSRX; i++) {
  174. bdp->cbd_sc = BD_SC_EMPTY;
  175. /* Leave space at the start for INET header. */
  176. bdp->cbd_bufaddr = (unsigned int)(MyRxPackets[i] +
  177. INET_HDR_ALIGN);
  178. bdp++;
  179. }
  180. bdp--;
  181. bdp->cbd_sc |= BD_SC_WRAP;
  182. #else
  183. keymile_hdlc_enet_init_bds(rtx);
  184. #endif
  185. /* Let's re-initialize the channel now. We have to do it later
  186. * than the manual describes because we have just now finished
  187. * the BD initialization.
  188. */
  189. cp->cp_cpcr = mk_cr_cmd(CPM_CR_SCC_PAGE, CPM_CR_SCC_SBLOCK,
  190. 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
  191. while (cp->cp_cpcr & CPM_CR_FLG);
  192. sccp->scc_gsmrl = SCC_GSMRL_MODE_HDLC;
  193. /* CTSS=1 */
  194. sccp->scc_gsmrh = SCC_GSMRH_CTSS;
  195. /* NOF=0, RTE=1, DRT=0, BUS=1 */
  196. sccp->scc_psmr = ((0x8000 >> 6) | (0x8000 >> 10));
  197. /* loopback for local testing */
  198. #ifdef GJTEST
  199. dprintf("LOOPBACK!\n");
  200. sccp->scc_gsmrl |= SCC_GSMRL_DIAG_LOOP;
  201. #endif
  202. /*
  203. * Disable all interrupts and clear all pending
  204. * events.
  205. */
  206. sccp->scc_sccm = 0;
  207. sccp->scc_scce = 0xffff;
  208. /*
  209. * And last, enable the transmit and receive processing.
  210. */
  211. sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
  212. dprintf("%s: HDLC ENET Version 0.3 on SCC%d\n", dev->name,
  213. MGC_SCC_HDLC + 1);
  214. /*
  215. * We may not get an ARP packet because ARP was already done on
  216. * a different interface, so initialize the cached values now.
  217. */
  218. initCachedNumbers(1);
  219. already_inited = 1;
  220. return 0;
  221. }
  222. void keymile_hdlc_enet_halt(struct eth_device *dev)
  223. {
  224. #if 0 /* just return, but keep this for reference */
  225. volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
  226. /* maybe should do a graceful stop here? */
  227. immr->im_scc[MGC_SCC_HDLC].scc_gsmrl &=
  228. ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
  229. #endif
  230. }
  231. #endif /* CONFIG_MGCOGE_HDLC_ENET */