1 /* $NetBSD: sa1111.c,v 1.22 2008/04/28 20:23:14 martin Exp $ */
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by IWAMOTO Toshihiro.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND 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 THE FOUNDATION OR CONTRIBUTORS
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.
34 * - introduce bus abstraction to support SA-1101
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: sa1111.c,v 1.22 2008/04/28 20:23:14 martin Exp $");
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/types.h>
44 #include <sys/device.h>
45 #include <sys/kernel.h>
46 #include <sys/malloc.h>
49 #include <machine/bus.h>
50 #include <machine/intr.h>
52 #include <arm/sa11x0/sa11x0_reg.h>
53 #include <arm/sa11x0/sa11x0_var.h>
54 #include <arm/sa11x0/sa11x0_gpioreg.h>
55 #include <arm/sa11x0/sa1111_reg.h>
56 #include <arm/sa11x0/sa1111_var.h>
60 static int sa1111_print(void *, const char *);
62 static void sacc_intr_calculatemasks(struct sacc_softc
*);
63 static void sacc_intr_setpolarity(sacc_chipset_tag_t
*, int , int);
66 #define DPRINTF(arg) printf arg
72 sacc_probe(device_t parent
, cfdata_t match
, void *aux
)
74 struct sa11x0_attach_args
*sa
= aux
;
75 bus_space_handle_t ioh
;
78 if (bus_space_map(sa
->sa_iot
, sa
->sa_addr
, sa
->sa_size
, 0, &ioh
))
81 skid
= bus_space_read_4(sa
->sa_iot
, ioh
, SACCSBI_SKID
);
82 bus_space_unmap(sa
->sa_iot
, ioh
, sa
->sa_size
);
84 if ((skid
& 0xffffff00) != 0x690cc200)
92 sa1111_search(device_t parent
, cfdata_t cf
, const int *ldesc
,
95 struct sa1111_attach_args aa
;
97 aa
.sa_addr
= cf
->cf_loc
[SACCCF_ADDR
];
98 aa
.sa_size
= cf
->cf_loc
[SACCCF_SIZE
];
99 aa
.sa_intr
= cf
->cf_loc
[SACCCF_INTR
];
101 aa
.sa_membase
= cf
->cf_loc
[SACCCF_MEMBASE
];
102 aa
.sa_memsize
= cf
->cf_loc
[SACCCF_MEMSIZE
];
105 if (config_match(parent
, cf
, &aa
) > 0)
106 config_attach(parent
, cf
, &aa
, sa1111_print
);
112 sa1111_print(void *aux
, const char *name
)
120 sacc_intr_establish(sacc_chipset_tag_t
*ic
, int irq
, int type
, int level
,
121 int (*ih_fun
)(void *), void *ih_arg
)
124 struct sacc_softc
*sc
= (struct sacc_softc
*)ic
;
125 struct sacc_intrhand
**p
, *ih
;
127 /* no point in sleeping unless someone can free memory. */
128 ih
= malloc(sizeof *ih
, M_DEVBUF
, cold
? M_NOWAIT
: M_WAITOK
);
130 panic("sacc_intr_establish: can't malloc handler info");
132 if (irq
< 0 || irq
> SACCIC_LEN
||
133 !(type
== IST_EDGE_RAISE
|| type
== IST_EDGE_FALL
))
134 panic("sacc_intr_establish: bogus irq or type");
136 if (sc
->sc_intrhand
[irq
] == NULL
) {
137 sacc_intr_setpolarity(ic
, irq
, type
);
138 sc
->sc_intrtype
[irq
] = type
;
139 } else if (sc
->sc_intrtype
[irq
] != type
)
140 /* XXX we should be able to share raising and
141 * falling edge intrs */
142 panic("sacc_intr_establish: type must be unique");
144 /* install intr handler */
145 /* map interrupt level to appropriate softinterrupt level */
146 level
= SOFTINT_SERIAL
;
147 ih
->ih_soft
= softint_establish(level
, (void (*)(void *)) ih_fun
,
153 for (p
= &sc
->sc_intrhand
[irq
]; *p
; p
= &(*p
)->ih_next
)
158 sacc_intr_calculatemasks(sc
);
165 sacc_intr_disestablish(sacc_chipset_tag_t
*ic
, void *arg
)
168 struct sacc_softc
*sc
= (struct sacc_softc
*)ic
;
169 struct sacc_intrhand
*ih
, **p
;
171 ih
= (struct sacc_intrhand
*)arg
;
175 if (irq
< 0 || irq
> SACCIC_LEN
)
176 panic("sacc_intr_disestablish: bogus irq");
181 for (p
= &sc
->sc_intrhand
[irq
];; p
= &(*p
)->ih_next
) {
183 panic("sacc_intr_disestablish: handler not registered");
189 sacc_intr_calculatemasks(sc
);
196 sacc_intr_setpolarity(sacc_chipset_tag_t
*ic
, int irq
, int type
)
198 struct sacc_softc
*sc
= (struct sacc_softc
*)ic
;
204 addr
= SACCIC_INTPOL1
;
207 addr
= SACCIC_INTPOL0
;
212 pol
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, addr
);
213 if (type
== IST_EDGE_RAISE
)
217 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, addr
, pol
);
222 sacc_intr_calculatemasks(struct sacc_softc
*sc
)
228 for (irq
= 0; irq
< 32; irq
++)
229 if (sc
->sc_intrhand
[irq
])
230 sc
->sc_imask
.lo
|= (1 << irq
);
231 for (irq
= 0; irq
< SACCIC_LEN
- 32; irq
++)
232 if (sc
->sc_intrhand
[irq
+ 32])
233 sc
->sc_imask
.hi
|= (1 << irq
);
236 /* XXX this should not be done here */
237 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, SACCIC_INTEN0
,
239 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, SACCIC_INTEN1
,
241 DPRINTF(("sacc_intr_calculatemasks: %x %x\n", sc
->sc_imask
.lo
,