1/*	$NetBSD: if_ne_obio.c,v 1.6 2008/03/16 16:08:57 he Exp $ */
2
3/*
4 * Copyright (c) 2002, 2003  Genetec corp.  All rights reserved.
5 * Written by Hiroyuki Bessho for Genetec corp.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. The name of Genetec corp. may not be used to endorse
16 *    or promote products derived from this software without specific prior
17 *    written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY GENETEC CORP. ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORP.
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: if_ne_obio.c,v 1.6 2008/03/16 16:08:57 he Exp $");
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/mbuf.h>
38#include <sys/socket.h>
39#include <sys/ioctl.h>
40#include <sys/errno.h>
41#include <sys/syslog.h>
42#include <sys/select.h>
43#include <sys/device.h>
44
45#include <net/if.h>
46#include <net/if_dl.h>
47#include <net/if_ether.h>
48#include <net/if_media.h>
49
50#include <machine/intr.h>
51#include <sys/bus.h>
52
53#include <dev/mii/mii.h>
54#include <dev/mii/miivar.h>
55
56#include <dev/ic/dp8390reg.h>
57#include <dev/ic/dp8390var.h>
58#include <dev/ic/ne2000reg.h>
59#include <dev/ic/ne2000var.h>
60
61#include <evbarm/g42xxeb/g42xxeb_var.h>
62#include <arm/xscale/pxa2x0var.h>
63
64struct ne_obio_softc {
65	struct ne2000_softc nsc;
66
67	void  *sc_ih;			/* interrupt handler */
68	int  intr_no;
69};
70
71int	ne_obio_match(device_t, cfdata_t , void *);
72void	ne_obio_attach(device_t, device_t, void *);
73
74
75CFATTACH_DECL_NEW(ne_obio, sizeof (struct ne_obio_softc), ne_obio_match,
76    ne_obio_attach, NULL, NULL);
77
78//#define DEBUG_GPIO  2
79//#define DEBUG_GPIO2  5
80
81#if 1
82#define	intr_handler	dp8390_intr
83#else
84#define	intr_handler	ne_obio_intr
85
86static int
87ne_obio_intr(void *arg)
88{
89	int rv=1;
90
91#ifdef DEBUG_GPIO
92	//printf( "ne_obio_intr arg=%p\n", arg );
93	bus_space_write_4( pxa2x0_softc->saip.sc_iot,
94	    pxa2x0_softc->saip.sc_gpioh,
95	    GPIO_GPSR0, 1U<<DEBUG_GPIO );
96#endif
97
98#if 0
99	while( (rv = dp8390_intr(arg)) != 0)
100		/*continue*/;
101#else
102	rv = dp8390_intr(arg);
103#endif
104
105#ifdef DEBUG_GPIO
106	bus_space_write_4( pxa2x0_softc->saip.sc_iot,
107	    pxa2x0_softc->saip.sc_gpioh,
108	    GPIO_GPCR0, 1U<<DEBUG_GPIO );
109#endif
110	return rv;
111}
112#endif
113
114static int
115ne_obio_enable(struct dp8390_softc *dsc)
116{
117	struct ne_obio_softc *sc = (struct ne_obio_softc *)dsc;
118	struct obio_softc *psc;
119
120	aprint_normal_dev(dsc->sc_dev, "enabled\n");
121
122	psc = device_private(device_parent(dsc->sc_dev));
123
124	/* Establish the interrupt handler. */
125	sc->sc_ih = obio_intr_establish(psc, sc->intr_no, IPL_NET,
126	    IST_LEVEL_LOW,
127	    intr_handler,
128	    sc);
129
130	return 0;
131}
132
133
134int
135ne_obio_match(device_t parent, cfdata_t match, void *aux )
136{
137	/* XXX: probe? */
138	return 1;
139}
140
141void
142ne_obio_attach(device_t parent, device_t self, void *aux )
143{
144	struct ne_obio_softc *sc = device_private(self);
145	struct obio_attach_args *oba = aux;
146	bus_space_tag_t iot = oba->oba_iot;
147	bus_space_handle_t  nioh, aioh;
148	uint8_t my_ea[ETHER_ADDR_LEN];
149	int i;
150
151	aprint_normal("\n");
152	sc->nsc.sc_dp8390.sc_dev = self;
153
154	/* Map i/o space. */
155	if (bus_space_map(iot, oba->oba_addr, NE2000_NPORTS, 0, &nioh))
156		return;
157
158	if (bus_space_subregion(iot, nioh, NE2000_ASIC_OFFSET,
159	    NE2000_ASIC_NPORTS, &aioh))
160		goto out2;
161
162	sc->nsc.sc_dp8390.sc_regt = iot;
163	sc->nsc.sc_dp8390.sc_regh = nioh;
164
165	sc->nsc.sc_asict = iot;
166	sc->nsc.sc_asich = aioh;
167
168	/*
169	 * XXX:
170	 * AX88796's reset register doesn't seem to work, and
171	 * ne2000_detect() fails.  We hardcord NIC type here.
172	 */
173	sc->nsc.sc_type = NE2000_TYPE_NE2000; /* XXX _AX88796 ? */
174	sc->nsc.sc_dp8390.sc_flags = DP8390_NO_REMOTE_DMA_COMPLETE;
175	/* DP8390_NO_MULTI_BUFFERING; XXX */
176
177	/* G4250EBX doesn't have EEPROM hooked to AX88796.  Read MAC
178	 * address set by Redboot and don't let ne2000_atthch() try to
179	 * read MAC from hardware.  (current ne2000 driver doesn't
180	 * support AX88796's EEPROM interface)
181	 */
182
183	bus_space_write_1( iot, nioh, ED_P0_CR, ED_CR_RD2|ED_CR_PAGE_1 );
184
185	for( i=0; i < ETHER_ADDR_LEN; ++i )
186		my_ea[i] = bus_space_read_1( iot, nioh, ED_P1_PAR0+i );
187
188	bus_space_write_1( iot, nioh, ED_P0_CR, ED_CR_RD2|ED_CR_PAGE_0 );
189
190	/* disable all interrupts */
191	bus_space_write_1(iot, nioh, ED_P0_IMR, 0);
192
193#ifdef DEBUG_GPIO
194	bus_space_write_4( pxa2x0_softc->saip.sc_iot,
195	    pxa2x0_softc->saip.sc_gpioh,
196	    GPIO_GPDR0, (0x01<<DEBUG_GPIO) | (0x01<<DEBUG_GPIO2) |
197	    bus_space_read_4(pxa2x0_softc->saip.sc_iot, pxa2x0_softc->saip.sc_gpioh,
198		GPIO_GPDR0));
199
200#endif
201	/* delay intr_establish until this IF is enabled
202	   to avoid spurious interrupts. */
203	sc->nsc.sc_dp8390.sc_enabled = 0;
204	sc->nsc.sc_dp8390.sc_enable = ne_obio_enable;
205	sc->intr_no = oba->oba_intr;
206
207	if( ne2000_attach( &sc->nsc, my_ea ) )
208		goto out;
209
210#ifndef ED_DCR_RDCR
211#define ED_DCR_RDCR 0
212#endif
213
214	bus_space_write_1(iot, nioh, ED_P0_DCR, ED_DCR_RDCR|ED_DCR_WTS);
215
216	return;
217
218 out:
219	bus_space_unmap( iot, aioh, NE2000_ASIC_NPORTS );
220 out2:
221	bus_space_unmap( iot, nioh, NE2000_NPORTS );
222	return;
223}
224
225#if 0
226void debug_obio_ne(struct dp8390_softc *);
227void
228debug_obio_ne(struct dp8390_softc *sc)
229{
230	struct obio_softc *osc =
231	    (struct obio_softc *)device_parent(&sc->sc_dev);
232	struct pxa2x0_softc *psc =
233	    (struct pxa2x0_softc *)device_parent(&osc->sc_dev);
234
235	printf( "ISR=%02x obio: pending=(%x,%x) mask=%x pending=%x mask=%x\n",
236	    bus_space_read_1(sc->sc_regt, sc->sc_regh,
237		ED_P0_ISR ),
238	    bus_space_read_2(osc->sc_iot, osc->sc_obioreg_ioh, G4250EBX_INTSTS1),
239	    bus_space_read_2(osc->sc_iot, osc->sc_obioreg_ioh, G4250EBX_INTSTS2),
240	    bus_space_read_2(osc->sc_iot, osc->sc_obioreg_ioh, G4250EBX_INTMASK),
241	    osc->sc_intr_pending,
242	    osc->sc_intr_mask );
243
244	printf( "intc: mask=%08x pending=%08x\n",
245	    bus_space_read_4(psc->saip.sc_iot, psc->saip.sc_ioh, SAIPIC_MR ),
246	    bus_space_read_4(psc->saip.sc_iot, psc->saip.sc_ioh, SAIPIC_IP ) );
247}
248#endif
249
250#ifdef DEBUG_GPIO2
251void dp8390_debug_overrun(void);
252void dp8390_debug_overrun(void)
253{
254	static int toggle=0;
255
256	//printf( "ne_obio_intr arg=%p\n", arg );
257	bus_space_write_4( pxa2x0_softc->saip.sc_iot,
258	    pxa2x0_softc->saip.sc_gpioh,
259	    toggle ? GPIO_GPCR0 : GPIO_GPSR0,
260			   1U<<DEBUG_GPIO2 );
261	toggle ^= 1;
262
263}
264#endif
265