~ubuntu-branches/ubuntu/maverick/u-boot-omap3/maverick

« back to all changes in this revision

Viewing changes to board/keymile/mgcoge/mgcoge_hdlc_enet.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2010-03-22 15:06:23 UTC
  • Revision ID: james.westby@ubuntu.com-20100322150623-i21g8rgiyl5dohag
Tags: upstream-2010.3git20100315
ImportĀ upstreamĀ versionĀ 2010.3git20100315

Show diffs side-by-side

added added

removed removed

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