1/*	$NetBSD: g42xxeb_mci.c,v 1.2 2010/06/26 07:51:45 bsh Exp $ */
2
3/*-
4 * Copyright (c) 2009  Genetec Corporation.  All rights reserved.
5 * Written by Hiroyuki Bessho for Genetec Corporation.
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
13 *    copyright notice, this list of conditions and the following
14 *    disclaimer in the documentation and/or other materials provided
15 *    with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
27 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31/* derived from zaurus/dev/zmci.c */
32
33/*-
34 * Copyright (C) 2006-2008 NONAKA Kimihiro <nonaka@netbsd.org>
35 * All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 *    notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 *    notice, this list of conditions and the following disclaimer in the
44 *    documentation and/or other materials provided with the distribution.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
50 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
51 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
52 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
53 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
54 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
55 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56 */
57
58#include <sys/cdefs.h>
59__KERNEL_RCSID(0, "$NetBSD: g42xxeb_mci.c,v 1.2 2010/06/26 07:51:45 bsh Exp $");
60
61#include <sys/param.h>
62#include <sys/device.h>
63#include <sys/systm.h>
64#include <sys/bus.h>
65#include <sys/pmf.h>
66
67#include <machine/intr.h>
68
69#include <arm/xscale/pxa2x0cpu.h>
70#include <arm/xscale/pxa2x0reg.h>
71#include <arm/xscale/pxa2x0var.h>
72#include <arm/xscale/pxa2x0_gpio.h>
73#include <arm/xscale/pxa2x0_mci.h>
74
75#include <dev/sdmmc/sdmmcreg.h>
76
77#include <arm/xscale/pxa2x0var.h>
78#include <evbarm/g42xxeb/g42xxeb_var.h>
79
80struct g42xxeb_mci_softc {
81	struct pxamci_softc sc_mci;
82
83	bus_space_tag_t sc_obio_iot;
84	bus_space_handle_t sc_obio_ioh;
85
86	void *sc_detect_ih;
87};
88
89static int pxamci_match(device_t, cfdata_t, void *);
90static void pxamci_attach(device_t, device_t, void *);
91
92CFATTACH_DECL_NEW(pxamci_obio, sizeof(struct g42xxeb_mci_softc),
93    pxamci_match, pxamci_attach, NULL, NULL);
94
95static int g42xxeb_mci_intr(void *arg);
96
97static uint32_t	g42xxeb_mci_get_ocr(void *);
98static int g42xxeb_mci_set_power(void *, uint32_t);
99static int g42xxeb_mci_card_detect(void *);
100static int g42xxeb_mci_write_protect(void *);
101
102static int
103pxamci_match(device_t parent, cfdata_t cf, void *aux)
104{
105
106	if (strcmp(cf->cf_name, "pxamci") == 0)
107		return 1;
108	return 0;
109}
110
111struct pxa2x0_gpioconf g42xxeb_pxamci_gpioconf[] = {
112	{  6, GPIO_CLR | GPIO_ALT_FN_1_OUT },	/* MMCCLK */
113	{  8, GPIO_CLR | GPIO_ALT_FN_1_OUT },	/* MMCCS0 */
114	{  9, GPIO_CLR | GPIO_ALT_FN_1_OUT },	/* MMCCS1 */
115	{  -1 }
116};
117
118
119static void
120pxamci_attach(device_t parent, device_t self, void *aux)
121{
122	struct g42xxeb_mci_softc *sc = device_private(self);
123	struct obio_attach_args *oba = aux;
124	struct obio_softc *osc = device_private(parent);
125	struct pxaip_attach_args pxa;
126	struct pxa2x0_gpioconf *gpioconf[] = {
127		g42xxeb_pxamci_gpioconf,
128		NULL
129	};
130
131	bus_space_tag_t iot = oba->oba_iot;
132
133	sc->sc_mci.sc_dev = self;
134
135	pxa2x0_gpio_config(gpioconf);
136
137	/* Establish card detect interrupt */
138	sc->sc_detect_ih = obio_intr_establish(osc, G42XXEB_INT_MMCSD,
139	    IPL_BIO, IST_EDGE_BOTH, g42xxeb_mci_intr, sc);
140	if (sc->sc_detect_ih == NULL) {
141		aprint_error_dev(self,
142		    "unable to establish SD detect interrupt\n");
143		return;
144	}
145
146	sc->sc_mci.sc_tag.cookie = sc;
147	sc->sc_mci.sc_tag.get_ocr = g42xxeb_mci_get_ocr;
148	sc->sc_mci.sc_tag.set_power = g42xxeb_mci_set_power;
149	sc->sc_mci.sc_tag.card_detect = g42xxeb_mci_card_detect;
150	sc->sc_mci.sc_tag.write_protect = g42xxeb_mci_write_protect;
151	sc->sc_mci.sc_caps = 0;
152
153	pxa.pxa_iot = iot; 	/* actually, here we want I/O tag for
154				   pxaip, not for obio. */
155
156#if 0
157	/* pxamci_attach_sub() ignores following values and uses
158	 * constants. */
159	pxa.pxa_addr = PXA2X0_MMC_BASE;
160	pxa.pxa_size = PXA2X0_MMC_SIZE;
161	pxa.pxa_intr = PXA2X0_INT_MMC;
162#endif
163
164	/* disable DMA for sdmmc for now. */
165	SET(sc->sc_mci.sc_caps, PMC_CAPS_NO_DMA);
166
167	if (pxamci_attach_sub(self, &pxa)) {
168		aprint_error_dev(self,
169		    "unable to attach MMC controller\n");
170		goto free_intr;
171	}
172
173	if (!pmf_device_register(self, NULL, NULL)) {
174		aprint_error_dev(self,
175		    "couldn't establish power handler\n");
176	}
177
178	sc->sc_obio_iot = iot;
179	sc->sc_obio_ioh = osc->sc_obioreg_ioh;
180
181	return;
182
183free_intr:
184	obio_intr_disestablish(osc, G42XXEB_INT_MMCSD, sc->sc_detect_ih);
185	sc->sc_detect_ih = NULL;
186}
187
188static int
189g42xxeb_mci_intr(void *arg)
190{
191	struct g42xxeb_mci_softc *sc = (struct g42xxeb_mci_softc *)arg;
192
193	pxamci_card_detect_event(&sc->sc_mci);
194
195	return 1;
196}
197
198static uint32_t
199g42xxeb_mci_get_ocr(void *arg)
200{
201
202	return MMC_OCR_3_2V_3_3V;
203}
204
205static int
206g42xxeb_mci_set_power(void *arg, uint32_t ocr)
207{
208	/* nothing to do */
209	return 0;
210}
211
212/*
213 * Return non-zero if the card is currently inserted.
214 */
215static int
216g42xxeb_mci_card_detect(void *arg)
217{
218	struct g42xxeb_mci_softc *sc = (struct g42xxeb_mci_softc *)arg;
219	uint16_t reg;
220
221	reg = bus_space_read_2(sc->sc_obio_iot, sc->sc_obio_ioh,
222	    G42XXEB_INTSTS2);
223
224	return !(reg & (1<<G42XXEB_INT_MMCSD));
225}
226
227/*
228 * Return non-zero if the card is currently write-protected.
229 */
230static int
231g42xxeb_mci_write_protect(void *arg)
232{
233	struct g42xxeb_mci_softc *sc = (struct g42xxeb_mci_softc *)arg;
234	uint16_t reg;
235
236	reg = bus_space_read_2(sc->sc_obio_iot, sc->sc_obio_ioh,
237	    G42XXEB_WP);
238
239	return reg & 1;
240}
241