2 /* NetBSD: if_sm_emifs.c,v 1.1.6.1 2007/02/24 19:03:14 snj Exp */
5 * OSK5912 SMC91Cxx wrapper, based on sys/arch/evbarm/viper/if_sm_pxaip.c
7 * Copyright (c) 2005 Antti Kantee. All Rights Reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by The NetBSD
20 * Foundation, Inc. and its contributors.
21 * 4. The name of the company nor the name of the author may be used to
22 * endorse or promote products derived from this software without specific
23 * prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
26 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: if_sm_gpmc.c,v 1.2 2008/04/27 18:58:47 matt Exp $");
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/device.h>
48 #include <net/if_ether.h>
49 #include <net/if_media.h>
51 #include <machine/intr.h>
52 #include <machine/bus.h>
54 #include <dev/mii/mii.h>
55 #include <dev/mii/miivar.h>
57 #include <dev/ic/smc91cxxreg.h>
58 #include <dev/ic/smc91cxxvar.h>
60 #include <arch/arm/omap/omap2_gpmcvar.h>
61 #include <arch/arm/omap/omap_gpio.h>
63 static int sm_gpmc_match(struct device
*, struct cfdata
*, void *);
64 static void sm_gpmc_attach(struct device
*, struct device
*, void *);
66 struct sm_gpmc_softc
{
67 struct smc91cxx_softc sc_sm
;
68 struct evcnt sc_incomplete_ev
;
69 struct evcnt sc_spurious_ev
;
73 CFATTACH_DECL(sm_gpmc
, sizeof(struct sm_gpmc_softc
), sm_gpmc_match
,
74 sm_gpmc_attach
, NULL
, NULL
);
77 sm_gpmc_match(struct device
*parent
, struct cfdata
*match
, void *aux
)
79 struct gpmc_attach_args
*gpmc
= aux
;
81 if (gpmc
->gpmc_addr
== GPMCCF_ADDR_DEFAULT
)
82 panic("sm must have addr specified in config.");
84 if (gpmc
->gpmc_intr
== GPMCCF_INTR_DEFAULT
)
85 panic("sm must have intr specified in config.");
87 /* Trust the config file. */
92 sm_gpmc_intr(void *arg
)
94 struct sm_gpmc_softc
* const gpmcsc
= (struct sm_gpmc_softc
*)arg
;
95 struct smc91cxx_softc
* const sc
= &gpmcsc
->sc_sm
;
97 if (bus_space_read_2(sc
->sc_bst
, sc
->sc_bsh
, 0x1a)) {
98 int rv
= smc91cxx_intr(sc
);
99 if (bus_space_read_2(sc
->sc_bst
, sc
->sc_bsh
, 0x1a))
100 gpmcsc
->sc_incomplete_ev
.ev_count
++;
103 gpmcsc
->sc_spurious_ev
.ev_count
++;
109 sm_gpmc_attach(struct device
*parent
, struct device
*self
, void *aux
)
111 struct sm_gpmc_softc
*gpmcsc
= (struct sm_gpmc_softc
*)self
;
112 struct smc91cxx_softc
*sc
= &gpmcsc
->sc_sm
;
113 struct gpmc_attach_args
*gpmc
= aux
;
115 bus_space_handle_t bsh
;
116 uint8_t enaddr
[ETHER_ADDR_LEN
];
117 unsigned int count
= 0;
119 bst
= gpmc
->gpmc_iot
;
122 if (bus_space_map(bst
, gpmc
->gpmc_addr
, SMC_IOSIZE
+ 16, 0, &bsh
) != 0) {
123 aprint_error(": sm_gpmc_attach: can't map i/o space");
129 /* fill in master sc */
133 /* register the interrupt handler */
134 gpmcsc
->ih
= intr_establish(gpmc
->gpmc_intr
, IPL_NET
, IST_LEVEL
,
135 sm_gpmc_intr
, gpmcsc
);
137 if (gpmcsc
->ih
== NULL
) {
138 aprint_error(": couldn't establish interrupt\n");
139 bus_space_unmap(bst
, bsh
, SMC_IOSIZE
+ 16);
143 evcnt_attach_dynamic(&gpmcsc
->sc_spurious_ev
, EVCNT_TYPE_INTR
, NULL
,
144 self
->dv_xname
, "spurious intr");
145 evcnt_attach_dynamic(&gpmcsc
->sc_incomplete_ev
, EVCNT_TYPE_INTR
, NULL
,
146 self
->dv_xname
, "incomplete intr");
148 SMC_SELECT_BANK(sc
, 1);
149 for (count
= 0; count
< ETHER_ADDR_LEN
; count
+= 2) {
151 tmp
= bus_space_read_2(bst
, bsh
, IAR_ADDR0_REG_W
+ count
);
152 enaddr
[count
+ 1] = (tmp
>> 8) & 0xff;
153 enaddr
[count
] = tmp
& 0xff;
159 bus_space_write_2(bst
, bsh
, 0x1c, 1);
161 bus_space_write_2(bst
, bsh
, 0x1c, 6);
164 * Wait for the reset to complete.
166 while (bus_space_read_2(bst
, bsh
, 0x1a) & 1) {
167 if (++count
> 1000) {
168 aprint_error(": didn't come out of reset\n");
173 /* Perform generic attach. */
174 sc
->sc_flags
|= SMC_FLAGS_ENABLED
;
175 smc91cxx_attach(sc
, enaddr
);