1254559Sian/*-
2254559Sian * Copyright (c) 2013 Ian Lepore <ian@freebsd.org>
3254559Sian * Copyright (c) 2011 Ben Gray <ben.r.gray@gmail.com>.
4254559Sian * All rights reserved.
5254559Sian *
6254559Sian * Redistribution and use in source and binary forms, with or without
7254559Sian * modification, are permitted provided that the following conditions
8254559Sian * are met:
9254559Sian * 1. Redistributions of source code must retain the above copyright
10254559Sian *    notice, this list of conditions and the following disclaimer.
11254559Sian * 2. Redistributions in binary form must reproduce the above copyright
12254559Sian *    notice, this list of conditions and the following disclaimer in the
13254559Sian *    documentation and/or other materials provided with the distribution.
14254559Sian *
15254559Sian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16254559Sian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17254559Sian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18254559Sian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19254559Sian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20254559Sian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21254559Sian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22254559Sian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23254559Sian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24254559Sian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25254559Sian * SUCH DAMAGE.
26254559Sian *
27254559Sian */
28254559Sian#include <sys/cdefs.h>
29254559Sian__FBSDID("$FreeBSD$");
30254559Sian
31254559Sian#include <sys/param.h>
32254559Sian#include <sys/systm.h>
33254559Sian#include <sys/bus.h>
34254559Sian#include <sys/gpio.h>
35254559Sian#include <sys/kernel.h>
36254559Sian#include <sys/malloc.h>
37254559Sian#include <sys/module.h>
38254559Sian#include <sys/resource.h>
39254559Sian#include <sys/rman.h>
40254559Sian#include <sys/taskqueue.h>
41254559Sian
42254559Sian#include <machine/bus.h>
43254559Sian#include <machine/resource.h>
44254559Sian#include <machine/intr.h>
45254559Sian
46254559Sian#include <dev/fdt/fdt_common.h>
47254559Sian#include <dev/ofw/ofw_bus.h>
48254559Sian#include <dev/ofw/ofw_bus_subr.h>
49254559Sian
50254559Sian#include <dev/mmc/bridge.h>
51254559Sian#include <dev/mmc/mmcreg.h>
52254559Sian#include <dev/mmc/mmcbrvar.h>
53254559Sian
54254559Sian#include <dev/sdhci/sdhci.h>
55254559Sian#include "sdhci_if.h"
56254559Sian
57254559Sian#include <arm/ti/ti_cpuid.h>
58254559Sian#include <arm/ti/ti_prcm.h>
59254559Sian#include "gpio_if.h"
60254559Sian
61254559Sianstruct ti_sdhci_softc {
62254559Sian	device_t		dev;
63254559Sian	device_t		gpio_dev;
64254559Sian	struct resource *	mem_res;
65254559Sian	struct resource *	irq_res;
66254559Sian	void *			intr_cookie;
67254559Sian	struct sdhci_slot	slot;
68254559Sian	uint32_t		mmchs_device_id;
69254559Sian	uint32_t		mmchs_reg_off;
70254559Sian	uint32_t		sdhci_reg_off;
71254559Sian	uint32_t		baseclk_hz;
72254559Sian	uint32_t		wp_gpio_pin;
73254559Sian	uint32_t		cmd_and_mode;
74254559Sian	uint32_t		sdhci_clkdiv;
75254559Sian};
76254559Sian
77254559Sian/*
78254559Sian * The MMCHS hardware has a few control and status registers at the beginning of
79254559Sian * the device's memory map, followed by the standard sdhci register block.
80254559Sian * Different SoCs have the register blocks at different offsets from the
81254559Sian * beginning of the device.  Define some constants to map out the registers we
82254559Sian * access, and the various per-SoC offsets.  The SDHCI_REG_OFFSET is how far
83254559Sian * beyond the MMCHS block the SDHCI block is found; it's the same on all SoCs.
84254559Sian */
85254559Sian#define	OMAP3_MMCHS_REG_OFFSET		0x000
86254559Sian#define	OMAP4_MMCHS_REG_OFFSET		0x100
87254559Sian#define	AM335X_MMCHS_REG_OFFSET		0x100
88254559Sian#define	SDHCI_REG_OFFSET		0x100
89254559Sian
90254559Sian#define	MMCHS_SYSCONFIG			0x010
91254559Sian#define	  MMCHS_SYSCONFIG_RESET		  (1 << 1)
92254559Sian#define	MMCHS_SYSSTATUS			0x014
93254559Sian#define	MMCHS_CON			0x02C
94254559Sian#define	  MMCHS_CON_DW8			  (1 << 5)
95254559Sian#define	  MMCHS_CON_DVAL_8_4MS		  (3 << 9)
96254559Sian
97254559Sianstatic inline uint32_t
98254559Sianti_mmchs_read_4(struct ti_sdhci_softc *sc, bus_size_t off)
99254559Sian{
100254559Sian
101254559Sian	return (bus_read_4(sc->mem_res, off + sc->mmchs_reg_off));
102254559Sian}
103254559Sian
104254559Sianstatic inline void
105254559Sianti_mmchs_write_4(struct ti_sdhci_softc *sc, bus_size_t off, uint32_t val)
106254559Sian{
107254559Sian
108254559Sian	bus_write_4(sc->mem_res, off + sc->mmchs_reg_off, val);
109254559Sian}
110254559Sian
111254559Sianstatic inline uint32_t
112254559SianRD4(struct ti_sdhci_softc *sc, bus_size_t off)
113254559Sian{
114254559Sian
115254559Sian	return (bus_read_4(sc->mem_res, off + sc->sdhci_reg_off));
116254559Sian}
117254559Sian
118254559Sianstatic inline void
119254559SianWR4(struct ti_sdhci_softc *sc, bus_size_t off, uint32_t val)
120254559Sian{
121254559Sian
122254559Sian	bus_write_4(sc->mem_res, off + sc->sdhci_reg_off, val);
123254559Sian}
124254559Sian
125254559Sianstatic uint8_t
126254559Sianti_sdhci_read_1(device_t dev, struct sdhci_slot *slot, bus_size_t off)
127254559Sian{
128254559Sian	struct ti_sdhci_softc *sc = device_get_softc(dev);
129254559Sian
130254559Sian	return ((RD4(sc, off & ~3) >> (off & 3) * 8) & 0xff);
131254559Sian}
132254559Sian
133254559Sianstatic uint16_t
134254559Sianti_sdhci_read_2(device_t dev, struct sdhci_slot *slot, bus_size_t off)
135254559Sian{
136254559Sian	struct ti_sdhci_softc *sc = device_get_softc(dev);
137254559Sian	uint32_t clkdiv, val32;
138254559Sian
139254559Sian	/*
140254559Sian	 * The MMCHS hardware has a non-standard interpretation of the sdclock
141254559Sian	 * divisor bits.  It uses the same bit positions as SDHCI 3.0 (15..6)
142254559Sian	 * but doesn't split them into low:high fields.  Instead they're a
143254559Sian	 * single number in the range 0..1023 and the number is exactly the
144254559Sian	 * clock divisor (with 0 and 1 both meaning divide by 1).  The SDHCI
145254559Sian	 * driver code expects a v2.0 divisor (value N is power of two in the
146254559Sian	 * range 0..128 and clock is divided by 2N).  The shifting and masking
147254559Sian	 * here extracts the MMCHS representation from the hardware word, cleans
148254559Sian	 * those bits out, applies the 2N adjustment, and plugs that into the
149254559Sian	 * bit positions for the 2.0 divisor in the returned register value. The
150254559Sian	 * ti_sdhci_write_2() routine performs the opposite transformation when
151254559Sian	 * the SDHCI driver writes to the register.
152254559Sian	 */
153254559Sian	if (off == SDHCI_CLOCK_CONTROL) {
154254559Sian		val32 = RD4(sc, SDHCI_CLOCK_CONTROL);
155254559Sian		clkdiv = (val32 >> SDHCI_DIVIDER_HI_SHIFT) & 0xff;
156254559Sian		val32 &= ~(0xff << SDHCI_DIVIDER_HI_SHIFT);
157254559Sian		val32 |= (clkdiv / 2) << SDHCI_DIVIDER_SHIFT;
158254559Sian		return (val32 & 0xffff);
159254559Sian	}
160254559Sian
161254559Sian	/*
162254559Sian	 * Standard 32-bit handling of command and transfer mode.
163254559Sian	 */
164254559Sian	if (off == SDHCI_TRANSFER_MODE) {
165254559Sian		return (sc->cmd_and_mode >> 16);
166254559Sian	} else if (off == SDHCI_COMMAND_FLAGS) {
167254559Sian		return (sc->cmd_and_mode & 0x0000ffff);
168254559Sian	}
169254559Sian
170254559Sian	return ((RD4(sc, off & ~3) >> (off & 3) * 8) & 0xffff);
171254559Sian}
172254559Sian
173254559Sianstatic uint32_t
174254559Sianti_sdhci_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off)
175254559Sian{
176254559Sian	struct ti_sdhci_softc *sc = device_get_softc(dev);
177254559Sian
178254559Sian	return (RD4(sc, off));
179254559Sian}
180254559Sian
181254559Sianstatic void
182254559Sianti_sdhci_read_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off,
183254559Sian    uint32_t *data, bus_size_t count)
184254559Sian{
185254559Sian	struct ti_sdhci_softc *sc = device_get_softc(dev);
186254559Sian
187254559Sian	bus_read_multi_4(sc->mem_res, off + sc->sdhci_reg_off, data, count);
188254559Sian}
189254559Sian
190254559Sianstatic void
191254559Sianti_sdhci_write_1(device_t dev, struct sdhci_slot *slot, bus_size_t off,
192254559Sian    uint8_t val)
193254559Sian{
194254559Sian	struct ti_sdhci_softc *sc = device_get_softc(dev);
195254559Sian	uint32_t val32;
196254559Sian
197254559Sian	val32 = RD4(sc, off & ~3);
198254559Sian	val32 &= ~(0xff << (off & 3) * 8);
199254559Sian	val32 |= (val << (off & 3) * 8);
200254559Sian
201254559Sian	WR4(sc, off & ~3, val32);
202254559Sian}
203254559Sian
204254559Sianstatic void
205254559Sianti_sdhci_write_2(device_t dev, struct sdhci_slot *slot, bus_size_t off,
206254559Sian    uint16_t val)
207254559Sian{
208254559Sian	struct ti_sdhci_softc *sc = device_get_softc(dev);
209254559Sian	uint32_t clkdiv, val32;
210254559Sian
211254559Sian	/*
212254559Sian	 * Translate between the hardware and SDHCI 2.0 representations of the
213254559Sian	 * clock divisor.  See the comments in ti_sdhci_read_2() for details.
214254559Sian	 */
215254559Sian	if (off == SDHCI_CLOCK_CONTROL) {
216254559Sian		clkdiv = (val >> SDHCI_DIVIDER_SHIFT) & SDHCI_DIVIDER_MASK;
217254559Sian		val32 = RD4(sc, SDHCI_CLOCK_CONTROL);
218254559Sian		val32 &= 0xffff0000;
219254559Sian		val32 |= val & ~(SDHCI_DIVIDER_MASK << SDHCI_DIVIDER_SHIFT);
220254559Sian		val32 |= (clkdiv * 2) << SDHCI_DIVIDER_HI_SHIFT;
221254559Sian		WR4(sc, SDHCI_CLOCK_CONTROL, val32);
222254559Sian		return;
223254559Sian	}
224254559Sian
225254559Sian	/*
226254559Sian	 * Standard 32-bit handling of command and transfer mode.
227254559Sian	 */
228254559Sian	if (off == SDHCI_TRANSFER_MODE) {
229254559Sian		sc->cmd_and_mode = (sc->cmd_and_mode & 0xffff0000) |
230254559Sian		    ((uint32_t)val & 0x0000ffff);
231254559Sian		return;
232254559Sian	} else if (off == SDHCI_COMMAND_FLAGS) {
233254559Sian		sc->cmd_and_mode = (sc->cmd_and_mode & 0x0000ffff) |
234254559Sian		    ((uint32_t)val << 16);
235254559Sian		WR4(sc, SDHCI_TRANSFER_MODE, sc->cmd_and_mode);
236254559Sian		return;
237254559Sian	}
238254559Sian
239254559Sian	val32 = RD4(sc, off & ~3);
240254559Sian	val32 &= ~(0xffff << (off & 3) * 8);
241254559Sian	val32 |= ((val & 0xffff) << (off & 3) * 8);
242254559Sian	WR4(sc, off & ~3, val32);
243254559Sian}
244254559Sian
245254559Sianstatic void
246254559Sianti_sdhci_write_4(device_t dev, struct sdhci_slot *slot, bus_size_t off,
247254559Sian    uint32_t val)
248254559Sian{
249254559Sian	struct ti_sdhci_softc *sc = device_get_softc(dev);
250254559Sian
251254559Sian	WR4(sc, off, val);
252254559Sian}
253254559Sian
254254559Sianstatic void
255254559Sianti_sdhci_write_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off,
256254559Sian    uint32_t *data, bus_size_t count)
257254559Sian{
258254559Sian	struct ti_sdhci_softc *sc = device_get_softc(dev);
259254559Sian
260254559Sian	bus_write_multi_4(sc->mem_res, off + sc->sdhci_reg_off, data, count);
261254559Sian}
262254559Sian
263254559Sianstatic void
264254559Sianti_sdhci_intr(void *arg)
265254559Sian{
266254559Sian	struct ti_sdhci_softc *sc = arg;
267254559Sian
268254559Sian	sdhci_generic_intr(&sc->slot);
269254559Sian}
270254559Sian
271254559Sianstatic int
272254559Sianti_sdhci_update_ios(device_t brdev, device_t reqdev)
273254559Sian{
274254559Sian	struct ti_sdhci_softc *sc = device_get_softc(brdev);
275254559Sian	struct sdhci_slot *slot;
276254559Sian	struct mmc_ios *ios;
277254559Sian	uint32_t val32;
278254559Sian
279254559Sian	slot = device_get_ivars(reqdev);
280254559Sian	ios = &slot->host.ios;
281254559Sian
282254559Sian	/*
283254559Sian	 * There is an 8-bit-bus bit in the MMCHS control register which, when
284254559Sian	 * set, overrides the 1 vs 4 bit setting in the standard SDHCI
285254559Sian	 * registers.  Set that bit first according to whether an 8-bit bus is
286254559Sian	 * requested, then let the standard driver handle everything else.
287254559Sian	 */
288254559Sian	val32 = ti_mmchs_read_4(sc, MMCHS_CON);
289254559Sian	if (ios->bus_width == bus_width_8)
290254559Sian		ti_mmchs_write_4(sc, MMCHS_CON, val32 | MMCHS_CON_DW8);
291254559Sian	else
292254559Sian		ti_mmchs_write_4(sc, MMCHS_CON, val32 & ~MMCHS_CON_DW8);
293254559Sian
294254559Sian	return (sdhci_generic_update_ios(brdev, reqdev));
295254559Sian}
296254559Sian
297254559Sianstatic int
298254559Sianti_sdhci_get_ro(device_t brdev, device_t reqdev)
299254559Sian{
300254559Sian	struct ti_sdhci_softc *sc = device_get_softc(brdev);
301254559Sian	unsigned int readonly = 0;
302254559Sian
303254559Sian	/* If a gpio pin is configured, read it. */
304254559Sian	if (sc->gpio_dev != NULL) {
305254559Sian		GPIO_PIN_GET(sc->gpio_dev, sc->wp_gpio_pin, &readonly);
306254559Sian	}
307254559Sian
308254559Sian	return (readonly);
309254559Sian}
310254559Sian
311254559Sianstatic int
312254559Sianti_sdhci_detach(device_t dev)
313254559Sian{
314254559Sian
315254559Sian	return (EBUSY);
316254559Sian}
317254559Sian
318254559Sianstatic void
319254559Sianti_sdhci_hw_init(device_t dev)
320254559Sian{
321254559Sian	struct ti_sdhci_softc *sc = device_get_softc(dev);
322254559Sian	clk_ident_t clk;
323254559Sian	unsigned long timeout;
324254559Sian
325254559Sian	/* Enable the controller and interface/functional clocks */
326254559Sian	clk = MMC0_CLK + sc->mmchs_device_id;
327254559Sian	if (ti_prcm_clk_enable(clk) != 0) {
328254559Sian		device_printf(dev, "Error: failed to enable MMC clock\n");
329254559Sian		return;
330254559Sian	}
331254559Sian
332254559Sian	/* Get the frequency of the source clock */
333254559Sian	if (ti_prcm_clk_get_source_freq(clk, &sc->baseclk_hz) != 0) {
334254559Sian		device_printf(dev, "Error: failed to get source clock freq\n");
335254559Sian		return;
336254559Sian	}
337254559Sian
338254559Sian	/* Issue a softreset to the controller */
339254559Sian	ti_mmchs_write_4(sc, MMCHS_SYSCONFIG, MMCHS_SYSCONFIG_RESET);
340254559Sian	timeout = 1000;
341254559Sian	while ((ti_mmchs_read_4(sc, MMCHS_SYSSTATUS) & MMCHS_SYSCONFIG_RESET)) {
342254559Sian		if (--timeout == 0) {
343254559Sian			device_printf(dev, "Error: Controller reset operation timed out\n");
344254559Sian			break;
345254559Sian		}
346254559Sian		DELAY(100);
347254559Sian	}
348254559Sian
349254559Sian	/* Reset both the command and data state machines */
350254559Sian	ti_sdhci_write_1(dev, NULL, SDHCI_SOFTWARE_RESET, SDHCI_RESET_ALL);
351254559Sian	timeout = 1000;
352254559Sian	while ((ti_sdhci_read_1(dev, NULL, SDHCI_SOFTWARE_RESET) & SDHCI_RESET_ALL)) {
353254559Sian		if (--timeout == 0) {
354254559Sian			device_printf(dev, "Error: Software reset operation timed out\n");
355254559Sian			break;
356254559Sian		}
357254559Sian		DELAY(100);
358254559Sian	}
359254559Sian
360254559Sian	/* Set initial host configuration (1-bit, std speed, pwr off). */
361254559Sian	ti_sdhci_write_1(dev, NULL, SDHCI_HOST_CONTROL, 0);
362254559Sian	ti_sdhci_write_1(dev, NULL, SDHCI_POWER_CONTROL, 0);
363254559Sian
364254559Sian	/* Set the initial controller configuration. */
365254559Sian	ti_mmchs_write_4(sc, MMCHS_CON, MMCHS_CON_DVAL_8_4MS);
366254559Sian}
367254559Sian
368254559Sianstatic int
369254559Sianti_sdhci_attach(device_t dev)
370254559Sian{
371254559Sian	struct ti_sdhci_softc *sc = device_get_softc(dev);
372254559Sian	int rid, err;
373254559Sian	pcell_t prop;
374254559Sian	phandle_t node;
375254559Sian
376254559Sian	sc->dev = dev;
377254559Sian
378254559Sian	/*
379254559Sian	 * Get the MMCHS device id from FDT.  If it's not there use the newbus
380254559Sian	 * unit number (which will work as long as the devices are in order and
381254559Sian	 * none are skipped in the fdt).
382254559Sian	 */
383254559Sian	node = ofw_bus_get_node(dev);
384254559Sian	if ((OF_getprop(node, "mmchs-device-id", &prop, sizeof(prop))) <= 0) {
385254559Sian		sc->mmchs_device_id = device_get_unit(dev);
386254559Sian		device_printf(dev, "missing mmchs-device-id attribute in FDT, "
387254559Sian		    "using unit number (%d)", sc->mmchs_device_id);
388254559Sian	} else
389254559Sian		sc->mmchs_device_id = fdt32_to_cpu(prop);
390254559Sian
391254559Sian	/* See if we've got a GPIO-based write detect pin. */
392254559Sian	if ((OF_getprop(node, "mmchs-wp-gpio-pin", &prop, sizeof(prop))) <= 0)
393254559Sian		sc->wp_gpio_pin = 0xffffffff;
394254559Sian	else
395254559Sian		sc->wp_gpio_pin = fdt32_to_cpu(prop);
396254559Sian
397254559Sian	if (sc->wp_gpio_pin != 0xffffffff) {
398254559Sian		sc->gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
399254559Sian		if (sc->gpio_dev == NULL)
400254559Sian			device_printf(dev, "Error: No GPIO device, "
401254559Sian			    "Write Protect pin will not function\n");
402254559Sian		else
403254559Sian			GPIO_PIN_SETFLAGS(sc->gpio_dev, sc->wp_gpio_pin,
404254559Sian			                  GPIO_PIN_INPUT);
405254559Sian	}
406254559Sian
407254559Sian	/*
408254559Sian	 * Set the offset from the device's memory start to the MMCHS registers.
409254559Sian	 *
410254559Sian	 * XXX A better way to handle this would be to have separate memory
411254559Sian	 * resources for the sdhci registers and the mmchs registers.  That
412254559Sian	 * requires changing everyone's DTS files.
413254559Sian	 */
414254559Sian	if (ti_chip() == CHIP_OMAP_3)
415254559Sian		sc->mmchs_reg_off = OMAP3_MMCHS_REG_OFFSET;
416254559Sian	else if (ti_chip() == CHIP_OMAP_4)
417254559Sian		sc->mmchs_reg_off = OMAP4_MMCHS_REG_OFFSET;
418254559Sian	else if (ti_chip() == CHIP_AM335X)
419254559Sian		sc->mmchs_reg_off = AM335X_MMCHS_REG_OFFSET;
420254559Sian	else
421254559Sian		panic("Unknown OMAP device\n");
422254559Sian
423254559Sian	/*
424254559Sian	 * The standard SDHCI registers are at a fixed offset (the same on all
425254559Sian	 * SoCs) beyond the MMCHS registers.
426254559Sian	 */
427254559Sian	sc->sdhci_reg_off = sc->mmchs_reg_off + SDHCI_REG_OFFSET;
428254559Sian
429254559Sian	/* Resource setup. */
430254559Sian	rid = 0;
431254559Sian	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
432254559Sian	    RF_ACTIVE);
433254559Sian	if (!sc->mem_res) {
434254559Sian		device_printf(dev, "cannot allocate memory window\n");
435254559Sian		err = ENXIO;
436254559Sian		goto fail;
437254559Sian	}
438254559Sian
439254559Sian	rid = 0;
440254559Sian	sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
441254559Sian	    RF_ACTIVE);
442254559Sian	if (!sc->irq_res) {
443254559Sian		device_printf(dev, "cannot allocate interrupt\n");
444254559Sian		err = ENXIO;
445254559Sian		goto fail;
446254559Sian	}
447254559Sian
448254559Sian	if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
449254559Sian	    NULL, ti_sdhci_intr, sc, &sc->intr_cookie)) {
450254559Sian		device_printf(dev, "cannot setup interrupt handler\n");
451254559Sian		err = ENXIO;
452254559Sian		goto fail;
453254559Sian	}
454254559Sian
455254559Sian	/* Initialise the MMCHS hardware. */
456254559Sian	ti_sdhci_hw_init(dev);
457254559Sian
458254559Sian	/*
459254559Sian	 * The capabilities register can only express base clock frequencies in
460254559Sian	 * the range of 0-63MHz for a v2.0 controller.  Since our clock runs
461254559Sian	 * faster than that, the hardware sets the frequency to zero in the
462254559Sian	 * register.  When the register contains zero, the sdhci driver expects
463254559Sian	 * slot.max_clk to already have the right value in it.
464254559Sian	 */
465254559Sian	sc->slot.max_clk = sc->baseclk_hz;
466254559Sian
467254559Sian	/*
468254559Sian	 * The MMCHS timeout counter is based on the output sdclock.  Tell the
469254559Sian	 * sdhci driver to recalculate the timeout clock whenever the output
470254559Sian	 * sdclock frequency changes.
471254559Sian	 */
472254559Sian	sc->slot.quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK;
473254559Sian
474254559Sian	/*
475254559Sian	 * The MMCHS hardware shifts the 136-bit response data (in violation of
476254559Sian	 * the spec), so tell the sdhci driver not to do the same in software.
477254559Sian	 */
478254559Sian	sc->slot.quirks |= SDHCI_QUIRK_DONT_SHIFT_RESPONSE;
479254559Sian
480254559Sian	/*
481254559Sian	 * DMA is not really broken, I just haven't implemented it yet.
482254559Sian	 */
483254559Sian	sc->slot.quirks |= SDHCI_QUIRK_BROKEN_DMA;
484254559Sian
485254559Sian	/* Set up the hardware and go. */
486254559Sian	sdhci_init_slot(dev, &sc->slot, 0);
487254559Sian
488254559Sian	/*
489254559Sian	 * The SDHCI controller doesn't realize it, but we support 8-bit even
490254559Sian	 * though we're not a v3.0 controller.  Advertise the ability.
491254559Sian	 */
492254559Sian	sc->slot.host.caps |= MMC_CAP_8_BIT_DATA;
493254559Sian
494254559Sian	bus_generic_probe(dev);
495254559Sian	bus_generic_attach(dev);
496254559Sian
497254559Sian	sdhci_start_slot(&sc->slot);
498254559Sian
499254559Sian	return (0);
500254559Sian
501254559Sianfail:
502254559Sian	if (sc->intr_cookie)
503254559Sian		bus_teardown_intr(dev, sc->irq_res, sc->intr_cookie);
504254559Sian	if (sc->irq_res)
505254559Sian		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
506254559Sian	if (sc->mem_res)
507254559Sian		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
508254559Sian
509254559Sian	return (err);
510254559Sian}
511254559Sian
512254559Sianstatic int
513254559Sianti_sdhci_probe(device_t dev)
514254559Sian{
515254559Sian
516254559Sian	if (!ofw_bus_is_compatible(dev, "ti,mmchs")) {
517254559Sian		return (ENXIO);
518254559Sian	}
519254559Sian
520254559Sian	device_set_desc(dev, "TI MMCHS (SDHCI 2.0)");
521254559Sian
522254559Sian	return (BUS_PROBE_DEFAULT);
523254559Sian}
524254559Sian
525254559Sianstatic device_method_t ti_sdhci_methods[] = {
526254559Sian	/* Device interface */
527254559Sian	DEVMETHOD(device_probe,		ti_sdhci_probe),
528254559Sian	DEVMETHOD(device_attach,	ti_sdhci_attach),
529254559Sian	DEVMETHOD(device_detach,	ti_sdhci_detach),
530254559Sian
531254559Sian	/* Bus interface */
532254559Sian	DEVMETHOD(bus_read_ivar,	sdhci_generic_read_ivar),
533254559Sian	DEVMETHOD(bus_write_ivar,	sdhci_generic_write_ivar),
534254559Sian	DEVMETHOD(bus_print_child,	bus_generic_print_child),
535254559Sian
536254559Sian	/* MMC bridge interface */
537254559Sian	DEVMETHOD(mmcbr_update_ios,	ti_sdhci_update_ios),
538254559Sian	DEVMETHOD(mmcbr_request,	sdhci_generic_request),
539254559Sian	DEVMETHOD(mmcbr_get_ro,		ti_sdhci_get_ro),
540254559Sian	DEVMETHOD(mmcbr_acquire_host,	sdhci_generic_acquire_host),
541254559Sian	DEVMETHOD(mmcbr_release_host,	sdhci_generic_release_host),
542254559Sian
543254559Sian	/* SDHCI registers accessors */
544254559Sian	DEVMETHOD(sdhci_read_1,		ti_sdhci_read_1),
545254559Sian	DEVMETHOD(sdhci_read_2,		ti_sdhci_read_2),
546254559Sian	DEVMETHOD(sdhci_read_4,		ti_sdhci_read_4),
547254559Sian	DEVMETHOD(sdhci_read_multi_4,	ti_sdhci_read_multi_4),
548254559Sian	DEVMETHOD(sdhci_write_1,	ti_sdhci_write_1),
549254559Sian	DEVMETHOD(sdhci_write_2,	ti_sdhci_write_2),
550254559Sian	DEVMETHOD(sdhci_write_4,	ti_sdhci_write_4),
551254559Sian	DEVMETHOD(sdhci_write_multi_4,	ti_sdhci_write_multi_4),
552254559Sian
553254559Sian	DEVMETHOD_END
554254559Sian};
555254559Sian
556254559Sianstatic devclass_t ti_sdhci_devclass;
557254559Sian
558254559Sianstatic driver_t ti_sdhci_driver = {
559254559Sian	"sdhci_ti",
560254559Sian	ti_sdhci_methods,
561254559Sian	sizeof(struct ti_sdhci_softc),
562254559Sian};
563254559Sian
564254559SianDRIVER_MODULE(sdhci_ti, simplebus, ti_sdhci_driver, ti_sdhci_devclass, 0, 0);
565254559SianMODULE_DEPEND(sdhci_ti, sdhci, 1, 1, 1);
566