1/*	$Id: mpcsa_cf.c,v 1.3 2012/10/27 17:17:48 chs Exp $	*/
2/*	$NetBSD: mpcsa_cf.c,v 1.2 2008/07/03 01:15:39 matt Exp $	*/
3
4/*
5 * Copyright (c) 2007 Embedtronics Oy. All rights reserved.
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 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: mpcsa_cf.c,v 1.2 2008/07/03 01:15:39 matt Exp $");
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/kernel.h>
35#include <sys/device.h>
36#include <arm/at91/at91reg.h>
37#include <arm/at91/at91var.h>
38#include <arm/at91/at91cfvar.h>
39#include <arm/at91/at91piovar.h>
40
41#ifdef MPCA_CF_DEBUG
42int mpcsa_cf_debug = MPCA_CF_DEBUG;
43#define DPRINTFN(n,x)	if (mpcsa_cf_debug>(n)) printf x;
44#else
45#define DPRINTFN(n,x)
46#endif
47
48struct at91_gpio_softc;
49
50struct mpcsa_cf_softc {
51	struct at91cf_softc	sc_dev;
52	struct at91pio_softc	*sc_pioc;
53};
54
55static int mpcsa_cf_match(device_t, cfdata_t, void *);
56static void mpcsa_cf_attach(device_t, device_t, void *);
57
58CFATTACH_DECL_NEW(mpcsa_cf, sizeof(struct mpcsa_cf_softc),
59	      mpcsa_cf_match, mpcsa_cf_attach, NULL, NULL);
60
61static int	mpcsa_cf_power_ctl(void *self, int onoff);
62static int	mpcsa_cf_card_detect(void *self);
63static int	mpcsa_cf_irq_line(void *self);
64static void *	mpcsa_cf_intr_establish(void *self, int which, int ipl, int (*ih_func)(void *), void *arg);
65static void	mpcsa_cf_intr_disestablish(void *self, int which, void *cookie);
66
67struct at91cf_chipset_tag mpcsa_cf_tag = {
68	mpcsa_cf_power_ctl,
69	mpcsa_cf_card_detect,
70	mpcsa_cf_irq_line,
71	mpcsa_cf_intr_establish,
72	mpcsa_cf_intr_disestablish
73};
74
75static int
76mpcsa_cf_match(device_t parent, cfdata_t match, void *aux)
77{
78	if (strcmp(match->cf_name, "at91cf") == 0 && strcmp(match->cf_atname, "mpcsa_cf") == 0)
79		return 2;
80	return 0;
81}
82
83static void
84mpcsa_cf_attach(device_t parent, device_t self, void *aux)
85{
86	struct mpcsa_cf_softc *sc = device_private(self);
87//	at91cf_chipset_tag_t cscf = sc->sc_dev.sc_cscf;
88	struct at91pio_softc *pioc;
89
90	if ((pioc = at91pio_sc(AT91_PIOC)) == NULL) {
91		printf("no PIOC!\n");
92		return;
93	}
94
95	// configure PIO!
96	sc->sc_pioc = pioc;
97	at91pio_in(sc->sc_pioc, 3);	// CFIRQ
98	at91pio_in(sc->sc_pioc, 4);	// CFCD
99	at91pio_out(sc->sc_pioc, 5);	// CFRESET
100
101	// and call common routine
102	at91cf_attach_common(parent, self, aux, &mpcsa_cf_tag);
103}
104
105static int
106mpcsa_cf_power_ctl(void *self, int onoff)
107{
108	struct mpcsa_cf_softc *sc = self;
109	if (onoff) {
110		at91pio_set(sc->sc_pioc, 5);
111		return 20000;
112	} else {
113		at91pio_clear(sc->sc_pioc, 5);
114		return 20000;
115	}
116}
117
118static int	mpcsa_cf_card_detect(void *self)
119{
120	struct mpcsa_cf_softc *sc = self;
121	return at91pio_read(sc->sc_pioc, 4) == 0;
122}
123
124static int	mpcsa_cf_irq_line(void *self)
125{
126	struct mpcsa_cf_softc *sc = self;
127	return at91pio_read(sc->sc_pioc, 3);
128}
129
130static void *	mpcsa_cf_intr_establish(void *self, int which, int ipl, int (*ih_func)(void *), void *ih_arg)
131{
132	struct mpcsa_cf_softc *sc = self;
133	return at91pio_intr_establish(sc->sc_pioc, which == CD_IRQ ? 4 : 3,
134					ipl, ih_func, ih_arg);
135}
136
137static void	mpcsa_cf_intr_disestablish(void *self, int which, void *cookie)
138{
139	struct mpcsa_cf_softc *sc = self;
140	at91pio_intr_disestablish(sc->sc_pioc, which == CD_IRQ ? 4 : 3, cookie);
141}
142
143