3 * Gary Jennejohn, DENX Software Engineering GmbH, garyj@denx.de.
5 * Based in part on arch/powerpc/cpu/mpc8xx/scc.c.
7 * See file CREDITS for list of people who contributed to this
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.
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.
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,
26 #include <common.h> /* commproc.h is included here */
30 #ifdef CONFIG_KEYMILE_HDLC_ENET
32 #include "../common/keymile_hdlc_enet.h"
34 char keymile_slot; /* our slot number in the backplane */
37 * Since, except during initialization, ethact is always HDLC
38 * while we're in the driver, just use serial_printf() everywhere for
39 * output. This avoids possible conflicts when netconsole is being
42 #define dprintf(fmt, args...) serial_printf(fmt, ##args)
44 static int already_inited;
47 * SCC Ethernet Tx and Rx buffer descriptors allocated at the
48 * immr->udata_bd address on Dual-Port RAM
49 * Provide for Double Buffering
51 typedef volatile struct CommonBufferDescriptor {
52 cbd_t txbd; /* Tx BD */
53 cbd_t rxbd[HDLC_PKTBUFSRX]; /* Rx BD */
58 int keymile_hdlc_enet_init(struct eth_device *, bd_t *);
59 void keymile_hdlc_enet_halt(struct eth_device *);
60 extern void keymile_hdlc_enet_init_bds(RTXBD *);
61 extern void initCachedNumbers(int);
64 #define MGS_CPM_CR_HDLC CPM_CR_CH_SCC4
65 #define MGS_PROFF_HDLC PROFF_SCC4
66 #define MGS_SCC_HDLC 3 /* Index, not number! */
68 int keymile_hdlc_enet_init(struct eth_device *dev, bd_t *bis)
71 /* volatile cbd_t *bdp; */
72 volatile cpm8xx_t *cp;
74 volatile hdlc_pram_t *hpr;
75 volatile iop8xx_t *iop;
80 cp = (cpm8xx_t *)&(((volatile immap_t *)CONFIG_SYS_IMMR)->im_cpm);
81 hpr = (hdlc_pram_t *)(&cp->cp_dparam[MGS_PROFF_HDLC]);
82 sccp = (volatile scc_t *)(&cp->cp_scc[MGS_SCC_HDLC]);
83 iop = (iop8xx_t *)&(((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport);
86 * Disable receive and transmit just in case.
88 sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
90 #ifndef CONFIG_SYS_ALLOC_DPRAM
91 #error "CONFIG_SYS_ALLOC_DPRAM must be defined"
94 * Avoid exhausting DPRAM, which would cause a panic.
95 * Actually this isn't really necessary, but leave it here
99 rtx = (RTXBD *) (cp->cp_dpmem +
100 dpram_alloc_align(sizeof(RTXBD), 8));
101 if (rtx == (RTXBD *)CPM_DP_NOSPACE)
103 memset((void *)rtx, 0, sizeof(RTXBD));
105 #endif /* !CONFIG_SYS_ALLOC_DPRAM */
107 /* We need the slot number for addressing. */
108 keymile_slot = *(char *)(CONFIG_SYS_SLOT_ID_BASE +
109 CONFIG_SYS_SLOT_ID_OFF) & CONFIG_SYS_SLOT_ID_MASK;
111 * Be consistent with the Linux driver and set
114 * Always add 1 to the slot number so that
115 * there are no problems with an ethaddr which
116 * is all 0s. This should be acceptable because
117 * a board should never have a slot number of 255,
118 * which is the broadcast address. The HDLC addressing
119 * uses only the slot number.
121 dev->enetaddr[0] = keymile_slot + 1;
124 dprintf("slot %d\n", keymile_slot);
127 /* use pa8, pa9 pins for TXD4, RXD4 respectively */
128 iop->iop_papar |= ((0x8000 >> 8) | (0x8000 >> 9));
129 iop->iop_padir &= ~((0x8000 >> 8) | (0x8000 >> 9));
130 iop->iop_paodr &= ~((0x8000 >> 8) | (0x8000 >> 9));
132 /* also use pa0 as CLK8 */
133 iop->iop_papar |= 0x8000;
134 iop->iop_padir &= ~0x8000;
135 iop->iop_paodr &= ~0x8000;
137 /* use pc5 as CTS4 */
138 iop->iop_pcpar &= ~(0x8000 >> 5);
139 iop->iop_pcdir &= ~(0x8000 >> 5);
140 iop->iop_pcso |= (0x8000 >> 5);
145 * this also connects SCC4 to NMSI
147 cp->cp_sicr = (cp->cp_sicr & ~0xff000000) | 0x3f000000;
149 /* keymile_rxIdx = 0; */
152 * Initialize function code registers for big-endian.
158 * Set maximum bytes per receive buffer.
160 hpr->mrblr = MAX_FRAME_LENGTH;
162 /* Setup CRC generator values for HDLC */
163 hpr->c_mask = 0x0000F0B8;
164 hpr->c_pres = 0x0000FFFF;
166 /* Initialize all error counters to 0 */
173 /* Set maximum frame length size */
174 hpr->mflr = MAX_FRAME_LENGTH;
176 /* set to 1 for per frame processing change later if needed */
181 hpr->haddr2 = SET_HDLC_UUA(keymile_slot);
182 hpr->haddr3 = hpr->haddr2;
183 hpr->haddr4 = hpr->haddr2;
185 hpr->haddr1 = HDLC_BCAST;
187 hpr->rbase = (unsigned int) &rtx->rxbd[0];
188 hpr->tbase = (unsigned int) &rtx->txbd;
192 * Initialize the buffer descriptors.
196 bdp->cbd_bufaddr = 0;
197 bdp->cbd_sc = BD_SC_WRAP;
200 * Setup RX packet buffers, aligned correctly.
201 * Borrowed from net/net.c.
203 MyRxPackets[0] = &MyPktBuf[0] + (PKTALIGN - 1);
204 MyRxPackets[0] -= (ulong)MyRxPackets[0] % PKTALIGN;
205 for (i = 1; i < HDLC_PKTBUFSRX; i++)
206 MyRxPackets[i] = MyRxPackets[0] + i * PKT_MAXBLR_SIZE;
209 for (i = 0; i < HDLC_PKTBUFSRX; i++) {
210 bdp->cbd_sc = BD_SC_EMPTY;
211 /* Leave space at the start for INET header. */
212 bdp->cbd_bufaddr = (unsigned int)(MyRxPackets[i] +
217 bdp->cbd_sc |= BD_SC_WRAP;
219 keymile_hdlc_enet_init_bds(rtx);
222 /* Let's re-initialize the channel now. We have to do it later
223 * than the manual describes because we have just now finished
224 * the BD initialization.
226 cp->cp_cpcr = mk_cr_cmd(MGS_CPM_CR_HDLC, CPM_CR_INIT_TRX) | CPM_CR_FLG;
227 while (cp->cp_cpcr & CPM_CR_FLG);
229 sccp->scc_gsmrl = SCC_GSMRL_MODE_HDLC;
231 sccp->scc_gsmrh = SCC_GSMRH_CTSS;
232 /* NOF=0, RTE=1, DRT=0, BUS=1 */
233 sccp->scc_psmr = ((0x8000 >> 6) | (0x8000 >> 10));
235 /* loopback for local testing */
237 dprintf("LOOPBACK!\n");
238 sccp->scc_gsmrl |= SCC_GSMRL_DIAG_LOOP;
242 * Disable all interrupts and clear all pending
246 sccp->scc_scce = 0xffff;
249 * And last, enable the transmit and receive processing.
251 sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
253 dprintf("%s: HDLC ENET Version 0.3 on SCC%d\n", dev->name,
257 * We may not get an ARP packet because ARP was already done on
258 * a different interface, so initialize the cached values now.
260 initCachedNumbers(1);
267 void keymile_hdlc_enet_halt(struct eth_device *dev)
269 #if 0 /* just return, but keep this for reference */
270 volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
272 /* maybe should do a graceful stop here? */
273 immr->im_cpm.cp_scc[MGS_SCC_HDLC].scc_gsmrl &=
274 ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
278 #endif /* CONFIG_KEYMILE_HDLC_ENET */