1 //==========================================================================
3 // devs/eth/frv/frv400/..../include/devs_eth_frv400.inl
5 // FRV400 ethernet I/O definitions.
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
43 // Author(s): jskov, hmt, gthomas
44 // Contributors: jskov
46 // Purpose: FRV400 ethernet defintions
47 //####DESCRIPTIONEND####
48 //==========================================================================
50 #include <cyg/hal/hal_intr.h> // CYGNUM_HAL_INTERRUPT_ETHR
51 #include <cyg/hal/hal_if.h>
52 #include <cyg/io/pci.h>
56 #define CYGHWR_NS_DP83902A_PLF_RESET(_dp_) \
59 HAL_READ_UINT8(_dp_->reset, _t); \
60 CYGACC_CALL_IF_DELAY_US(10); \
61 HAL_WRITE_UINT8(_dp_->reset, _t); \
62 CYGACC_CALL_IF_DELAY_US(10000); \
65 #define DP_IN(_b_, _o_, _d_) \
67 HAL_READ_UINT8(((cyg_addrword_t)(_b_)+(_o_))^0x03, (_d_)); \
70 #define DP_OUT(_b_, _o_, _d_) \
72 HAL_WRITE_UINT8(((cyg_addrword_t)(_b_)+(_o_))^0x03, (_d_)); \
75 #define DP_IN_DATA(_b_, _d_) \
77 HAL_READ_UINT16((cyg_addrword_t)(_b_)^0x02, (_d_)); \
80 #define DP_OUT_DATA(_b_, _d_) \
82 HAL_WRITE_UINT16((cyg_addrword_t)(_b_)^0x02, (_d_)); \
85 //#define CYGHWR_NS_DP83902A_PLF_16BIT_DATA
86 //#define CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA
88 #endif // __WANT_CONFIG
92 #if defined(CYGSEM_DEVS_ETH_FRV400_ETH0_SET_ESA)
93 #if defined(CYGPKG_REDBOOT)
94 #include <pkgconf/redboot.h>
95 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
97 #include <flash_config.h>
98 RedBoot_config_option("Network hardware address [MAC]",
100 ALWAYS_ENABLED, true,
103 #endif // CYGSEM_REDBOOT_FLASH_CONFIG
104 #endif // CYGPKG_REDBOOT
105 #include <cyg/hal/hal_if.h>
112 find_rtl8029_match_func( cyg_uint16 v, cyg_uint16 d, cyg_uint32 c, void *p )
114 return ((v == 0x10EC) && (d == 0x8029));
118 _frv400_eth_init(dp83902a_priv_data_t *dp)
120 cyg_pci_device_id devid;
121 cyg_pci_device dev_info;
122 #if defined(CYGSEM_DEVS_ETH_FRV400_ETH0_SET_ESA)
124 unsigned char _esa[6];
126 unsigned char prom[32];
130 devid = CYG_PCI_NULL_DEVID;
131 if (cyg_pci_find_matching( &find_rtl8029_match_func, NULL, &devid )) {
132 cyg_pci_get_device_info(devid, &dev_info);
133 cyg_pci_translate_interrupt(&dev_info, &dp->interrupt);
134 dp->base = (cyg_uint8 *)(dev_info.base_map[0] & ~1);
135 dp->data = dp->base + 0x10;
136 dp->reset = dp->base + 0x1F;
137 diag_printf("RTL8029 at %p, interrupt: %x\n", dp->base, dp->interrupt);
138 #if defined(CYGSEM_DEVS_ETH_FRV400_ETH0_SET_ESA)
139 esa_ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
140 "lan_esa", _esa, CONFIG_ESA);
142 memcpy(dp->esa, _esa, sizeof(_esa));
145 // Read ESA from EEPROM
146 DP_OUT(dp->base, DP_DCR, 0x48); // Bytewide access
147 DP_OUT(dp->base, DP_RBCH, 0); // Remote byte count
148 DP_OUT(dp->base, DP_RBCL, 0);
149 DP_OUT(dp->base, DP_ISR, 0xFF); // Clear any pending interrupts
150 DP_OUT(dp->base, DP_IMR, 0x00); // Mask all interrupts
151 DP_OUT(dp->base, DP_RCR, 0x20); // Monitor
152 DP_OUT(dp->base, DP_TCR, 0x02); // loopback
153 DP_OUT(dp->base, DP_RBCH, 32); // Remote byte count
154 DP_OUT(dp->base, DP_RBCL, 0);
155 DP_OUT(dp->base, DP_RSAL, 0); // Remote address
156 DP_OUT(dp->base, DP_RSAH, 0);
157 DP_OUT(dp->base, DP_CR, DP_CR_START|DP_CR_RDMA); // Read data
158 for (i = 0; i < 32; i++) {
160 HAL_READ_UINT16(dp->data, _val);
164 DP_OUT(dp->base, DP_CR, DP_CR_NODMA | DP_CR_PAGE1); // Select page 1
165 for (i = 0; i < 6; i++) {
166 DP_OUT(dp->base, DP_P1_PAR0+i, prom[i]);
168 DP_OUT(dp->base, DP_CR, DP_CR_NODMA | DP_CR_PAGE0); // Select page 0
173 #define CYGHWR_NS_DP83902A_PLF_INIT(dp) _frv400_eth_init(dp)
175 #ifndef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
177 _frv400_eth_int_clear(dp83902a_priv_data_t *dp)
179 cyg_drv_interrupt_acknowledge(dp->interrupt);
182 #define CYGHWR_NS_DP83902A_PLF_INT_CLEAR(dp) _frv400_eth_int_clear(dp)
185 #ifdef CYGPKG_DEVS_ETH_FRV400_ETH0
187 static dp83902a_priv_data_t dp83902a_eth0_priv_data = {
188 base : (cyg_uint8*) 0, //
189 data : (cyg_uint8*) 0, // Filled in at runtime
190 reset: (cyg_uint8*) 0, //
193 tx_buf2: 0x48, // Buffer layout - change with care
194 rx_buf_start: 0x50, //
196 #ifdef CYGSEM_DEVS_ETH_FRV400_ETH0_SET_ESA
197 esa : CYGDAT_DEVS_ETH_FRV400_ETH0_ESA,
198 hardwired_esa : true,
200 hardwired_esa : false,
204 ETH_DRV_SC(dp83902a_sc,
205 &dp83902a_eth0_priv_data, // Driver specific data
206 CYGDAT_DEVS_ETH_FRV400_ETH0_NAME,
213 dp83902a_deliver, // "pseudoDSR" called from fast net thread
214 dp83902a_poll, // poll function, encapsulates ISR and DSR
215 dp83902a_int_vector);
217 NETDEVTAB_ENTRY(dp83902a_netdev,
218 "dp83902a_" CYGDAT_DEVS_ETH_FRV400_ETH0_NAME,
223 #ifdef CYGPKG_REDBOOT
226 #define EECS (0x80|(1<<3))
230 #define dprintf(x...) do { } while(0)
233 static int eeprom_cmd(dp83902a_priv_data_t *dp, int cmd, int cmd_len)
237 DP_OUT(dp->base, 1, EECS);
238 CYGACC_CALL_IF_DELAY_US(2000);
240 dprintf("Enabled for %08x (%d bits)\n", cmd, cmd_len);
242 DP_OUT(dp->base, 1, EECS | EESK);
243 CYGACC_CALL_IF_DELAY_US(2000);
247 /* Shift the command bits out. */
249 short databit = (cmd & (1 << cmd_len)) ? EEDI : 0;
250 unsigned char tmp, tmp2;
251 DP_OUT(dp->base, 1, EECS | databit);
252 CYGACC_CALL_IF_DELAY_US(2000);
253 dprintf("Bit %d ... ", !!(cmd&(1<<cmd_len)));
254 DP_OUT(dp->base, 1, EECS | databit | EESK);
255 CYGACC_CALL_IF_DELAY_US(2000);
257 DP_IN(dp->base, 0, tmp2);
258 DP_IN(dp->base, 1, tmp);
259 CYGACC_CALL_IF_DELAY_US(2000);
260 retval = (retval << 1) | !!(tmp & EEDO);
262 dprintf("Got bit %d (%02x %02x)\n", retval & 1, tmp2, tmp);
263 } while (--cmd_len >= 0);
264 DP_OUT(dp->base, 1, EECS);
265 CYGACC_CALL_IF_DELAY_US(2000);
266 dprintf("Last enb...\n");
268 /* Terminate the EEPROM access. */
269 DP_OUT(dp->base, 1, 0x80);
270 CYGACC_CALL_IF_DELAY_US(2000);
271 dprintf("Bye. retval %x\n", retval);
275 static void setmac(dp83902a_priv_data_t *dp, unsigned short *newmac)
277 unsigned char old_cr, old_ee;
280 DP_IN(dp->base, DP_CR, old_cr);
281 DP_OUT(dp->base, DP_CR, old_cr | 0xc0); // Select page 3.
282 CYGACC_CALL_IF_DELAY_US(2000);
284 DP_IN(dp->base, 1, old_ee);
285 DP_OUT(dp->base, 1, 0x80);
286 CYGACC_CALL_IF_DELAY_US(2000);
289 eeprom_cmd(dp, (4<<6) + (0x30), 8);
291 for (i=0; i<3; i++) {
294 // eeprom_cmd(dp, (7<<6) + (adr), 8);
296 eeprom_cmd(dp, (5<<22) + (adr<<16) + newmac[i], 24);
300 eeprom_cmd(dp, (4<<6), 8);
303 unsigned long words[16];
304 for (i=0; i<15; i++) {
305 unsigned long cmd = (6<<22) + (i<<16);
306 words[i] = eeprom_cmd(dp, cmd /*6<<23 + (i<<16)*/, 24);
309 for (i=0; i<15; i++) {
310 diag_printf("Words[%d] %08x\n", i, words[i]);
313 DP_OUT(dp->base, 1, old_ee);
314 CYGACC_CALL_IF_DELAY_US(2000);
315 DP_OUT(dp->base, DP_CR, old_cr);
316 CYGACC_CALL_IF_DELAY_US(2000);
321 static void do_setmac(int argc, char *argv[]);
322 RedBoot_cmd("setmac",
323 "Set Ethernet MAC address",
324 "<xx:xx:xx:xx:xx:xx>",
329 do_setmac(int argc, char *argv[])
331 unsigned char *mac = NULL;
332 unsigned char mac_nybble[12];
333 unsigned short mac_word[3];
336 if (!scan_opts(argc, argv, 1, NULL, 0, (void *)&mac,
337 OPTION_ARG_TYPE_STR, "<MAC address>"))
341 diag_printf("Must supply MAC address\n");
344 for (c=n=0; n<12; c++) {
345 if (mac[c] == ':' && !((c+1) % 3))
346 /* Colon in an allowed place */
349 if (mac[c] >= '0' && mac[c] <= '9')
350 mac_nybble[n] = mac[c] - '0';
351 else if (mac[c] >= 'A' && mac[c] <= 'F')
352 mac_nybble[n] = mac[c] - 'A' + 10;
353 else if (mac[c] >= 'a' && mac[c] <= 'f')
354 mac_nybble[n] = mac[c] - 'a' + 10;
356 diag_printf("Invalid MAC address bad char %x\n", mac[c]);
362 if (mac[c] || n!=12 || (mac_nybble[1]&1)) {
363 diag_printf("Invalid MAC address\n");
366 mac_word[0] = (mac_nybble[2] << 12) |
367 (mac_nybble[3] << 8) |
368 (mac_nybble[0] << 4) |
370 mac_word[1] = (mac_nybble[6] << 12) |
371 (mac_nybble[7] << 8) |
372 (mac_nybble[4] << 4) |
374 mac_word[2] = (mac_nybble[10] << 12) |
375 (mac_nybble[11] << 8) |
376 (mac_nybble[8] << 4) |
379 diag_printf("Setting MAC address...");
381 setmac(&dp83902a_eth0_priv_data, mac_word);
382 diag_printf("... done. Reset to take effect.\n");
385 #endif /* CYGPKG_REDBOOT */
386 #endif // CYGPKG_DEVS_ETH_FRV400_ETH0
388 #endif // __WANT_DEVS
390 // --------------------------------------------------------------
392 // EOF devs_eth_frv400.inl