1 /* $Id: at91cf.c,v 1.2 2008/07/03 01:15:38 matt Exp $ */
5 * Copyright (c) 2007 Embedtronics Oy. All rights reserved.
7 * Based on arch/evbarm/ep93xx/eppcic.c,
8 * Copyright (c) 2005 HAMAJIMA Katsuomi. All rights reserved.
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 AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD$");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/malloc.h>
39 #include <sys/device.h>
40 #include <sys/kthread.h>
41 #include <uvm/uvm_param.h>
42 #include <machine/bus.h>
43 #include <dev/pcmcia/pcmciareg.h>
44 #include <dev/pcmcia/pcmciavar.h>
45 #include <dev/pcmcia/pcmciachip.h>
46 #include <arm/at91/at91reg.h>
47 #include <arm/at91/at91var.h>
48 #include <arm/at91/at91cfvar.h>
52 #error "at91cf requires at91pio"
56 int at91cf_debug
= AT91CF_DEBUG
;
57 #define DPRINTFN(n,x) if (at91cf_debug>(n)) printf x;
62 struct at91cf_handle
{
63 struct at91cf_softc
*ph_sc
;
65 int (*ph_ih_func
)(void *);
67 lwp_t
*ph_event_thread
;
68 int ph_type
; /* current access type */
69 int ph_run
; /* kthread running */
70 int ph_width
; /* 8 or 16 */
71 int ph_vcc
; /* 3 or 5 */
72 int ph_status
; /* combined cd1 and cd2 */
83 static int at91cf_intr_carddetect(void *);
84 static int at91cf_intr_socket(void *);
85 static int at91cf_print(void *, const char *);
86 static void at91cf_create_event_thread(void *);
87 static void at91cf_event_thread(void *);
88 void at91cf_shutdown(void *);
90 static int at91cf_mem_alloc(pcmcia_chipset_handle_t
, bus_size_t
,
91 struct pcmcia_mem_handle
*);
92 static void at91cf_mem_free(pcmcia_chipset_handle_t
,
93 struct pcmcia_mem_handle
*);
94 static int at91cf_mem_map(pcmcia_chipset_handle_t
, int, bus_addr_t
, bus_size_t
,
95 struct pcmcia_mem_handle
*, bus_size_t
*, int *);
96 static void at91cf_mem_unmap(pcmcia_chipset_handle_t
, int);
97 static int at91cf_io_alloc(pcmcia_chipset_handle_t
, bus_addr_t
, bus_size_t
,
98 bus_size_t
, struct pcmcia_io_handle
*);
99 static void at91cf_io_free(pcmcia_chipset_handle_t
, struct pcmcia_io_handle
*);
100 static int at91cf_io_map(pcmcia_chipset_handle_t
, int, bus_addr_t
, bus_size_t
,
101 struct pcmcia_io_handle
*, int *);
102 static void at91cf_io_unmap(pcmcia_chipset_handle_t
, int);
103 static void *at91cf_intr_establish(pcmcia_chipset_handle_t
,
104 struct pcmcia_function
*,
105 int, int (*)(void *), void *);
106 static void at91cf_intr_disestablish(pcmcia_chipset_handle_t
, void *);
107 static void at91cf_socket_enable(pcmcia_chipset_handle_t
);
108 static void at91cf_socket_disable(pcmcia_chipset_handle_t
);
109 static void at91cf_socket_settype(pcmcia_chipset_handle_t
, int);
111 static void at91cf_attach_socket(struct at91cf_handle
*);
112 static void at91cf_config_socket(struct at91cf_handle
*);
113 //static int at91cf_get_voltage(struct at91cf_handle *);
115 static struct pcmcia_chip_functions at91cf_functions
= {
116 at91cf_mem_alloc
, at91cf_mem_free
,
117 at91cf_mem_map
, at91cf_mem_unmap
,
118 at91cf_io_alloc
, at91cf_io_free
,
119 at91cf_io_map
, at91cf_io_unmap
,
120 at91cf_intr_establish
, at91cf_intr_disestablish
,
121 at91cf_socket_enable
, at91cf_socket_disable
,
122 at91cf_socket_settype
125 #define MEMORY_BASE 0
126 #define MEMORY_SIZE 0x1000
127 #define COMMON_BASE 0x400000
128 #define COMMON_SIZE 0x1000
129 #define IO_BASE 0x800000
130 #define IO_SIZE 0x1000
131 #define MIN_SIZE (IO_BASE + IO_SIZE)
134 at91cf_attach_common(device_t parent
, device_t self
, void *aux
,
135 at91cf_chipset_tag_t cscf
)
137 struct at91cf_softc
*sc
= device_private(self
);
138 struct at91bus_attach_args
*sa
= aux
;
139 struct at91cf_handle
*ph
;
141 if (sa
->sa_size
< MIN_SIZE
) {
142 printf("%s: it's not possible to map registers\n",
148 sc
->sc_iot
= sa
->sa_iot
;
152 if (bus_space_map(sa
->sa_iot
, sa
->sa_addr
+ MEMORY_BASE
,
153 MEMORY_SIZE
, 0, &sc
->sc_memory_ioh
)){
154 printf("%s: Cannot map memory space\n", device_xname(self
));
158 if (bus_space_map(sa
->sa_iot
, sa
->sa_addr
+ COMMON_BASE
,
159 COMMON_SIZE
, 0, &sc
->sc_common_ioh
)){
160 printf("%s: Cannot map common memory space\n",
162 bus_space_unmap(sa
->sa_iot
, sc
->sc_memory_ioh
, MEMORY_SIZE
);
166 if (bus_space_map(sa
->sa_iot
, sa
->sa_addr
+ IO_BASE
,
167 IO_SIZE
, 0, &sc
->sc_io_ioh
)){
168 printf("%s: Cannot map I/O space\n", device_xname(self
));
169 bus_space_unmap(sa
->sa_iot
, sc
->sc_memory_ioh
, MEMORY_SIZE
);
170 bus_space_unmap(sa
->sa_iot
, sc
->sc_common_ioh
, COMMON_SIZE
);
177 ph
= malloc(sizeof(struct at91cf_handle
), M_DEVBUF
, M_NOWAIT
|M_ZERO
);
179 printf("%s: Cannot allocate memory\n", device_xname(self
));
185 ph
->ph_space
[IO
].base
= sa
->sa_addr
+ IO_BASE
;
186 ph
->ph_space
[IO
].size
= IO_SIZE
;
187 ph
->ph_space
[COMMON
].base
= sa
->sa_addr
+ COMMON_BASE
;
188 ph
->ph_space
[COMMON
].size
= COMMON_SIZE
;
189 ph
->ph_space
[ATTRIBUTE
].base
= sa
->sa_addr
+ MEMORY_BASE
;
190 ph
->ph_space
[ATTRIBUTE
].size
= MEMORY_SIZE
;
191 at91cf_attach_socket(ph
);
193 // @@@ reset CF now? @@@@
195 at91cf_config_socket(sc
->sc_ph
);
199 at91cf_attach_socket(struct at91cf_handle
*ph
)
201 struct at91cf_softc
*sc
= ph
->ph_sc
;
202 at91cf_chipset_tag_t cscf
= sc
->sc_cscf
;
207 ph
->ph_event_thread
= NULL
;
209 ph
->ph_ih_func
= NULL
;
210 ph
->ph_ih_arg
= NULL
;
212 ph
->ph_status
= (*cscf
->card_detect
)(sc
);
214 wait
= (cscf
->power_ctl
)(sc
, POWER_OFF
);
216 wait
= (cscf
->power_ctl
)(sc
, POWER_ON
);
221 at91cf_config_socket(struct at91cf_handle
*ph
)
223 struct at91cf_softc
*sc
= ph
->ph_sc
;
224 at91cf_chipset_tag_t cscf
= sc
->sc_cscf
;
225 struct pcmciabus_attach_args paa
;
228 paa
.paa_busname
= "pcmcia";
229 paa
.pct
= (pcmcia_chipset_tag_t
)&at91cf_functions
;
230 paa
.pch
= (pcmcia_chipset_handle_t
)ph
;
231 paa
.iobase
= ph
->ph_space
[IO
].base
;
232 paa
.iosize
= ph
->ph_space
[IO
].size
;
233 ph
->ph_card
= config_found_ia(sc
->sc_dev
, "pcmciabus", &paa
,
236 (*cscf
->intr_establish
)(sc
, CD_IRQ
, IPL_BIO
, at91cf_intr_carddetect
, ph
);
237 wait
= (*cscf
->power_ctl
)(sc
, POWER_OFF
);
240 kthread_create(PRI_NONE
, 0, NULL
, at91cf_create_event_thread
, ph
,
241 &ph
->ph_event_thread
, "%s", device_xname(sc
->sc_dev
));
245 at91cf_print(void *arg
, const char *pnp
)
251 at91cf_create_event_thread(void *arg
)
253 struct at91cf_handle
*ph
= arg
;
254 struct at91cf_softc
*sc
= ph
->ph_sc
;
255 at91cf_chipset_tag_t cscf
= sc
->sc_cscf
;
257 ph
->ph_status
= (*cscf
->card_detect
)(sc
);
259 DPRINTFN(1, ("at91cf_create_event_thread: status=%d\n", ph
->ph_status
));
262 pcmcia_card_attach(ph
->ph_card
);
265 kthread_create(PRI_NONE
, 0, NULL
, at91cf_event_thread
, ph
,
266 &ph
->ph_event_thread
, "%s", device_xname(sc
->sc_dev
));
270 at91cf_event_thread(void *arg
)
272 struct at91cf_handle
*ph
= arg
;
276 status
= ph
->ph_status
;
277 tsleep(ph
, PWAIT
, "CSC wait", 0);
281 DPRINTFN(1, ("at91cf_event_thread: old status=%d, new status=%d\n", status
, ph
->ph_status
));
283 if (!status
&& ph
->ph_status
)
284 pcmcia_card_attach(ph
->ph_card
);
285 else if (status
&& !ph
->ph_status
)
286 pcmcia_card_detach(ph
->ph_card
, DETACH_FORCE
);
289 DPRINTFN(1, ("at91cf_event_thread: run=%d\n",ph
->ph_run
));
290 ph
->ph_event_thread
= NULL
;
295 at91cf_shutdown(void *arg
)
297 struct at91cf_handle
*ph
= arg
;
299 DPRINTFN(1, ("at91cf_shutdown\n"));
305 at91cf_intr_carddetect(void *arg
)
307 struct at91cf_handle
*ph
= arg
;
308 struct at91cf_softc
*sc
= ph
->ph_sc
;
309 at91cf_chipset_tag_t cscf
= sc
->sc_cscf
;
312 nstatus
= (*cscf
->card_detect
)(sc
);
314 DPRINTFN(1, ("at91cf_intr: nstatus=%#x, ostatus=%#x\n", nstatus
, ph
->ph_status
));
316 if (nstatus
!= ph
->ph_status
) {
317 ph
->ph_status
= nstatus
;
325 at91cf_mem_alloc(pcmcia_chipset_handle_t pch
, bus_size_t size
,
326 struct pcmcia_mem_handle
*pmh
)
328 struct at91cf_handle
*ph
= (struct at91cf_handle
*)pch
;
329 struct at91cf_softc
*sc
= ph
->ph_sc
;
331 DPRINTFN(1, ("at91cf_mem_alloc: size=%#x\n",(unsigned)size
));
333 pmh
->memt
= sc
->sc_iot
;
338 at91cf_mem_free(pcmcia_chipset_handle_t pch
, struct pcmcia_mem_handle
*pmh
)
340 DPRINTFN(1, ("at91cf_mem_free\n"));
344 at91cf_mem_map(pcmcia_chipset_handle_t pch
, int kind
, bus_addr_t addr
,
345 bus_size_t size
, struct pcmcia_mem_handle
*pmh
,
346 bus_size_t
*offsetp
, int *windowp
)
348 struct at91cf_handle
*ph
= (struct at91cf_handle
*)pch
;
349 struct at91cf_softc
*sc
= ph
->ph_sc
;
353 DPRINTFN(1, ("at91cf_mem_map: kind=%d, addr=%#x, size=%#x\n",kind
,(unsigned)addr
,(unsigned)size
));
357 size
= round_page(size
);
358 pmh
->realsize
= size
;
359 if (kind
& PCMCIA_WIDTH_MEM8
)
363 switch (kind
& ~PCMCIA_WIDTH_MEM_MASK
) {
364 case PCMCIA_MEM_ATTR
:
365 pa
+= ph
->ph_space
[ATTRIBUTE
].base
;
367 case PCMCIA_MEM_COMMON
:
368 pa
+= ph
->ph_space
[COMMON
].base
;
374 DPRINTFN(1, ("at91cf_mem_map: pa=%#x, *offsetp=%#x, size=%#x\n",(unsigned)pa
,(unsigned)addr
,(unsigned)size
));
376 if (!(err
= bus_space_map(sc
->sc_iot
, pa
, size
, 0, &pmh
->memh
)))
377 *windowp
= (int)pmh
->memh
;
382 at91cf_mem_unmap(pcmcia_chipset_handle_t pch
, int window
)
384 struct at91cf_handle
*ph
= (struct at91cf_handle
*)pch
;
385 struct at91cf_softc
*sc
= ph
->ph_sc
;
387 DPRINTFN(1, ("at91cf_mem_unmap: window=%#x\n",window
));
389 bus_space_unmap(sc
->sc_iot
, (bus_addr_t
)window
, 0x1000);
393 at91cf_io_alloc(pcmcia_chipset_handle_t pch
, bus_addr_t start
, bus_size_t size
,
394 bus_size_t align
, struct pcmcia_io_handle
*pih
)
396 struct at91cf_handle
*ph
= (struct at91cf_handle
*)pch
;
397 struct at91cf_softc
*sc
= ph
->ph_sc
;
400 DPRINTFN(1, ("at91cf_io_alloc: start=%#x, size=%#x, align=%#x\n",(unsigned)start
,(unsigned)size
,(unsigned)align
));
402 pih
->iot
= sc
->sc_iot
;
405 pa
= pih
->addr
+ ph
->ph_space
[IO
].base
;
406 return bus_space_map(sc
->sc_iot
, pa
, size
, 0, &pih
->ioh
);
410 at91cf_io_free(pcmcia_chipset_handle_t pch
, struct pcmcia_io_handle
*pih
)
412 struct at91cf_handle
*ph
= (struct at91cf_handle
*)pch
;
413 struct at91cf_softc
*sc
= ph
->ph_sc
;
415 DPRINTFN(1, ("at91cf_io_free\n"));
417 bus_space_unmap(sc
->sc_iot
, pih
->ioh
, pih
->size
);
421 at91cf_io_map(pcmcia_chipset_handle_t pch
, int width
, bus_addr_t offset
,
422 bus_size_t size
, struct pcmcia_io_handle
*pih
, int *windowp
)
424 struct at91cf_handle
*ph
= (struct at91cf_handle
*)pch
;
426 DPRINTFN(1, ("at91cf_io_map: offset=%#x, size=%#x, width=%d",(unsigned)offset
,(unsigned)size
,width
));
429 case PCMCIA_WIDTH_IO8
:
430 DPRINTFN(1, ("(8bit)\n"));
433 case PCMCIA_WIDTH_IO16
:
434 case PCMCIA_WIDTH_AUTO
: /* I don't understand how I check it */
435 DPRINTFN(1, ("(16bit)\n"));
439 DPRINTFN(1, ("(unknown)\n"));
442 *windowp
= 0; /* unused */
447 at91cf_io_unmap(pcmcia_chipset_handle_t pch
, int window
)
449 DPRINTFN(1, ("at91cf_io_unmap: window=%#x\n",window
));
453 at91cf_intr_establish(pcmcia_chipset_handle_t pch
, struct pcmcia_function
*pf
,
454 int ipl
, int (*ih_func
)(void *), void *ih_arg
)
456 struct at91cf_handle
*ph
= (struct at91cf_handle
*)pch
;
457 struct at91cf_softc
*sc
= ph
->ph_sc
;
458 at91cf_chipset_tag_t cscf
= sc
->sc_cscf
;
460 DPRINTFN(1, ("at91cf_intr_establish\n"));
465 ph
->ph_ih_func
= ih_func
;
466 ph
->ph_ih_arg
= ih_arg
;
468 return (*cscf
->intr_establish
)(sc
, CF_IRQ
, ipl
, at91cf_intr_socket
, ph
);
469 // return (*cscf->intr_establish)(sc, CF_IRQ, ipl, ih_func, ih_arg);
473 at91cf_intr_disestablish(pcmcia_chipset_handle_t pch
, void *ih
)
475 struct at91cf_handle
*ph
= (struct at91cf_handle
*)pch
;
476 struct at91cf_softc
*sc
= ph
->ph_sc
;
477 at91cf_chipset_tag_t cscf
= sc
->sc_cscf
;
479 DPRINTFN(1, ("at91cf_intr_disestablish\n"));
481 ph
->ph_ih_func
= NULL
;
482 ph
->ph_ih_arg
= NULL
;
484 (*cscf
->intr_disestablish
)(sc
, CF_IRQ
, ih
);
488 at91cf_intr_socket(void *arg
)
490 struct at91cf_handle
*ph
= arg
;
491 struct at91cf_softc
*sc
= ph
->ph_sc
;
492 at91cf_chipset_tag_t cscf
= sc
->sc_cscf
;
495 if (ph
->ph_ih_func
) {
496 irq
= (*cscf
->irq_line
)(sc
);
497 if (ph
->ph_type
== PCMCIA_IFTYPE_IO
)
500 err
= (*ph
->ph_ih_func
)(ph
->ph_ih_arg
);
502 DPRINTFN(2,("%s: other edge ignored\n", __FUNCTION__
));
509 at91cf_socket_enable(pcmcia_chipset_handle_t pch
)
511 struct at91cf_handle
*ph
= (struct at91cf_handle
*)pch
;
512 struct at91cf_softc
*sc
= ph
->ph_sc
;
513 at91cf_chipset_tag_t cscf
= sc
->sc_cscf
;
516 DPRINTFN(1, ("at91cf_socket_enable\n"));
518 wait
= (cscf
->power_ctl
)(sc
, POWER_ON
);
523 at91cf_socket_disable(pcmcia_chipset_handle_t pch
)
525 struct at91cf_handle
*ph
= (struct at91cf_handle
*)pch
;
526 struct at91cf_softc
*sc
= ph
->ph_sc
;
527 at91cf_chipset_tag_t cscf
= sc
->sc_cscf
;
530 DPRINTFN(1, ("at91cf_socket_disable\n"));
532 wait
= (cscf
->power_ctl
)(sc
, POWER_OFF
);
537 at91cf_socket_settype(pcmcia_chipset_handle_t pch
, int type
)
539 struct at91cf_handle
*ph
= (struct at91cf_handle
*)pch
;
541 DPRINTFN(1, ("at91cf_socket_settype: type=%d",type
));
546 case PCMCIA_IFTYPE_MEMORY
:
547 DPRINTFN(1, ("(Memory)\n"));
549 case PCMCIA_IFTYPE_IO
:
550 DPRINTFN(1, ("(I/O)\n"));
553 DPRINTFN(1, ("(unknown)\n"));
560 at91cf_get_voltage(struct at91cf_handle
*ph
)
562 struct at91cf_softc
*sc
= ph
->ph_sc
;
563 at91cf_chipset_tag_t cscf
= sc
->sc_cscf
;
566 cap
= (cscf
->power_capability
)(sc
);
567 if (eppio_read(sc
->sc_pio
, ph
->ph_port
, ph
->ph_vs
[0])) {
571 printf("%s: unsupported Vcc 5 Volts",
572 device_xname(sc
->sc_dev
));
577 printf("%s: unsupported Vcc 3.3 Volts",
578 device_xname(sc
->sc_dev
));
580 DPRINTFN(1, ("at91cf_get_voltage: vs1=%d, vs2=%d (%dV)\n",eppio_read_bit(sc
->sc_pio
, ph
->ph_port
, ph
->ph_vs
[0]),eppio_read_bit(sc
->sc_pio
, ph
->ph_port
, ph
->ph_vs
[1]),vcc
));