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