2 * Copyright 2013-2015 John Wehle <john@feith.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * Amlogic aml8726 MMC host controller driver.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
34 #include <sys/param.h>
35 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/module.h>
41 #include <sys/mutex.h>
42 #include <sys/resource.h>
47 #include <machine/bus.h>
48 #include <machine/cpu.h>
50 #include <dev/fdt/fdt_common.h>
51 #include <dev/ofw/ofw_bus.h>
52 #include <dev/ofw/ofw_bus_subr.h>
54 #include <dev/mmc/bridge.h>
55 #include <dev/mmc/mmcreg.h>
56 #include <dev/mmc/mmcbrvar.h>
58 #include <arm/amlogic/aml8726/aml8726_mmc.h>
63 struct aml8726_mmc_gpio {
69 struct aml8726_mmc_softc {
71 struct resource *res[2];
75 unsigned int ref_freq;
76 struct aml8726_mmc_gpio pwr_en;
78 struct aml8726_mmc_gpio vselect;
84 struct mmc_command *cmd;
85 uint32_t stop_timeout;
88 static struct resource_spec aml8726_mmc_spec[] = {
89 { SYS_RES_MEMORY, 0, RF_ACTIVE },
90 { SYS_RES_IRQ, 0, RF_ACTIVE },
94 #define AML_MMC_LOCK(sc) mtx_lock(&(sc)->mtx)
95 #define AML_MMC_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
96 #define AML_MMC_LOCK_ASSERT(sc) mtx_assert(&(sc)->mtx, MA_OWNED)
97 #define AML_MMC_LOCK_INIT(sc) \
98 mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \
100 #define AML_MMC_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx);
102 #define CSR_WRITE_4(sc, reg, val) bus_write_4((sc)->res[0], reg, (val))
103 #define CSR_READ_4(sc, reg) bus_read_4((sc)->res[0], reg)
104 #define CSR_BARRIER(sc, reg) bus_barrier((sc)->res[0], reg, 4, \
105 (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE))
107 #define PWR_ON_FLAG(pol) ((pol) == 0 ? GPIO_PIN_LOW : \
109 #define PWR_OFF_FLAG(pol) ((pol) == 0 ? GPIO_PIN_HIGH : \
112 #define MSECS_TO_TICKS(ms) (((ms)*hz)/1000 + 1)
114 static void aml8726_mmc_timeout(void *arg);
117 aml8726_mmc_clk(phandle_t node)
123 len = OF_getencprop(node, "clocks", &prop, sizeof(prop));
124 if ((len / sizeof(prop)) != 1 || prop == 0 ||
125 (clk_node = OF_node_from_xref(prop)) == 0)
128 len = OF_getencprop(clk_node, "clock-frequency", &prop, sizeof(prop));
129 if ((len / sizeof(prop)) != 1 || prop == 0)
132 return ((unsigned int)prop);
136 aml8726_mmc_freq(struct aml8726_mmc_softc *sc, uint32_t divisor)
139 return (sc->ref_freq / ((divisor + 1) * 2));
143 aml8726_mmc_div(struct aml8726_mmc_softc *sc, uint32_t desired_freq)
147 divisor = sc->ref_freq / (desired_freq * 2);
154 if (aml8726_mmc_freq(sc, divisor) > desired_freq)
157 if (divisor > (AML_MMC_CONFIG_CMD_CLK_DIV_MASK >>
158 AML_MMC_CONFIG_CMD_CLK_DIV_SHIFT)) {
159 divisor = AML_MMC_CONFIG_CMD_CLK_DIV_MASK >>
160 AML_MMC_CONFIG_CMD_CLK_DIV_SHIFT;
167 aml8726_mmc_mapmem(void *arg, bus_dma_segment_t *segs, int nseg, int error)
169 bus_addr_t *busaddrp;
172 * There should only be one bus space address since
173 * bus_dma_tag_create was called with nsegments = 1.
176 busaddrp = (bus_addr_t *)arg;
177 *busaddrp = segs->ds_addr;
181 aml8726_mmc_power_off(struct aml8726_mmc_softc *sc)
184 if (sc->pwr_en.dev == NULL)
187 return (GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin,
188 PWR_OFF_FLAG(sc->pwr_en.pol)));
192 aml8726_mmc_power_on(struct aml8726_mmc_softc *sc)
195 if (sc->pwr_en.dev == NULL)
198 return (GPIO_PIN_SET(sc->pwr_en.dev, sc->pwr_en.pin,
199 PWR_ON_FLAG(sc->pwr_en.pol)));
203 aml8726_mmc_soft_reset(struct aml8726_mmc_softc *sc, boolean_t enable_irq)
207 icr = AML_MMC_IRQ_CONFIG_SOFT_RESET;
209 if (enable_irq == true)
210 icr |= AML_MMC_IRQ_CONFIG_CMD_DONE_EN;
212 CSR_WRITE_4(sc, AML_MMC_IRQ_CONFIG_REG, icr);
213 CSR_BARRIER(sc, AML_MMC_IRQ_CONFIG_REG);
217 aml8726_mmc_start_command(struct aml8726_mmc_softc *sc, struct mmc_command *cmd)
219 struct mmc_ios *ios = &sc->host.ios;
226 uint32_t nbits_per_pkg;
229 struct mmc_data *data;
231 if (cmd->opcode > 0x3f)
232 return (MMC_ERR_INVALID);
235 * Ensure the hardware state machine is in a known state.
237 aml8726_mmc_soft_reset(sc, true);
240 * Start and transmission bits are per section 4.7.2 of the:
242 * SD Specifications Part 1
243 * Physicaly Layer Simplified Specification
246 cmdr = AML_MMC_CMD_START_BIT | AML_MMC_CMD_TRANS_BIT_HOST | cmd->opcode;
250 timeout = AML_MMC_CMD_TIMEOUT;
253 * If this is a linked command, then use the previous timeout.
255 if (cmd == cmd->mrq->stop && sc->stop_timeout)
256 timeout = sc->stop_timeout;
257 sc->stop_timeout = 0;
259 if ((cmd->flags & MMC_RSP_136) != 0) {
260 cmdr |= AML_MMC_CMD_RESP_CRC7_FROM_8;
261 cmdr |= (133 << AML_MMC_CMD_RESP_BITS_SHIFT);
262 } else if ((cmd->flags & MMC_RSP_PRESENT) != 0)
263 cmdr |= (45 << AML_MMC_CMD_RESP_BITS_SHIFT);
265 if ((cmd->flags & MMC_RSP_CRC) == 0)
266 cmdr |= AML_MMC_CMD_RESP_NO_CRC7;
268 if ((cmd->flags & MMC_RSP_BUSY) != 0)
269 cmdr |= AML_MMC_CMD_CHECK_DAT0_BUSY;
273 if (data && data->len &&
274 (data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)) != 0) {
275 block_size = data->len;
277 if ((data->flags & MMC_DATA_MULTI) != 0) {
278 block_size = MMC_SECTOR_SIZE;
279 if ((data->len % block_size) != 0)
280 return (MMC_ERR_INVALID);
283 cmdr |= (((data->len / block_size) - 1) <<
284 AML_MMC_CMD_REP_PKG_CNT_SHIFT);
286 mcfgr |= (data->flags & MMC_DATA_STREAM) ?
287 AML_MMC_MULT_CONFIG_STREAM_EN : 0;
290 * The number of bits per package equals the number
291 * of data bits + the number of CRC bits. There are
292 * 16 bits of CRC calculate per bus line.
294 * A completed package appears to be detected by when
295 * a counter decremented by the width underflows, thus
296 * a value of zero always transfers 1 (or 4 bits depending
297 * on the mode) which is why bus_width is subtracted.
299 bus_width = (ios->bus_width == bus_width_4) ? 4 : 1;
300 nbits_per_pkg = block_size * 8 + 16 * bus_width - bus_width;
301 if (nbits_per_pkg > 0x3fff)
302 return (MMC_ERR_INVALID);
304 extr |= (nbits_per_pkg << AML_MMC_EXTENSION_PKT_SIZE_SHIFT);
306 error = bus_dmamap_load(sc->dmatag, sc->dmamap,
307 data->data, data->len, aml8726_mmc_mapmem, &baddr,
310 return (MMC_ERR_NO_MEMORY);
312 if ((data->flags & MMC_DATA_READ) != 0) {
313 cmdr |= AML_MMC_CMD_RESP_HAS_DATA;
314 bus_dmamap_sync(sc->dmatag, sc->dmamap,
315 BUS_DMASYNC_PREREAD);
316 timeout = AML_MMC_READ_TIMEOUT *
317 (data->len / block_size);
319 cmdr |= AML_MMC_CMD_CMD_HAS_DATA;
320 bus_dmamap_sync(sc->dmatag, sc->dmamap,
321 BUS_DMASYNC_PREWRITE);
322 timeout = AML_MMC_WRITE_TIMEOUT *
323 (data->len / block_size);
327 * Stop terminates a multiblock read / write and thus
328 * can take as long to execute as an actual read / write.
330 if (cmd->mrq->stop != NULL)
331 sc->stop_timeout = timeout;
336 cmd->error = MMC_ERR_NONE;
338 if (timeout > AML_MMC_MAX_TIMEOUT)
339 timeout = AML_MMC_MAX_TIMEOUT;
341 callout_reset(&sc->ch, MSECS_TO_TICKS(timeout),
342 aml8726_mmc_timeout, sc);
344 CSR_WRITE_4(sc, AML_MMC_CMD_ARGUMENT_REG, cmd->arg);
345 CSR_WRITE_4(sc, AML_MMC_MULT_CONFIG_REG, mcfgr);
346 CSR_WRITE_4(sc, AML_MMC_EXTENSION_REG, extr);
347 CSR_WRITE_4(sc, AML_MMC_DMA_ADDR_REG, (uint32_t)baddr);
349 CSR_WRITE_4(sc, AML_MMC_CMD_SEND_REG, cmdr);
350 CSR_BARRIER(sc, AML_MMC_CMD_SEND_REG);
352 return (MMC_ERR_NONE);
356 aml8726_mmc_finish_command(struct aml8726_mmc_softc *sc, int mmc_error)
359 struct mmc_command *cmd;
360 struct mmc_command *stop_cmd;
361 struct mmc_data *data;
363 AML_MMC_LOCK_ASSERT(sc);
365 /* Clear all interrupts since the request is no longer in flight. */
366 CSR_WRITE_4(sc, AML_MMC_IRQ_STATUS_REG, AML_MMC_IRQ_STATUS_CLEAR_IRQ);
367 CSR_BARRIER(sc, AML_MMC_IRQ_STATUS_REG);
369 /* In some cases (e.g. finish called via timeout) this is a NOP. */
370 callout_stop(&sc->ch);
375 cmd->error = mmc_error;
379 if (data && data->len &&
380 (data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)) != 0) {
381 if ((data->flags & MMC_DATA_READ) != 0)
382 bus_dmamap_sync(sc->dmatag, sc->dmamap,
383 BUS_DMASYNC_POSTREAD);
385 bus_dmamap_sync(sc->dmatag, sc->dmamap,
386 BUS_DMASYNC_POSTWRITE);
387 bus_dmamap_unload(sc->dmatag, sc->dmamap);
391 * If there's a linked stop command, then start the stop command.
392 * In order to establish a known state attempt the stop command
393 * even if the original request encountered an error.
396 stop_cmd = (cmd->mrq->stop != cmd) ? cmd->mrq->stop : NULL;
398 if (stop_cmd != NULL) {
399 mmc_stop_error = aml8726_mmc_start_command(sc, stop_cmd);
400 if (mmc_stop_error == MMC_ERR_NONE) {
404 stop_cmd->error = mmc_stop_error;
409 /* Execute the callback after dropping the lock. */
411 cmd->mrq->done(cmd->mrq);
415 aml8726_mmc_timeout(void *arg)
417 struct aml8726_mmc_softc *sc = (struct aml8726_mmc_softc *)arg;
420 * The command failed to complete in time so forcefully
423 aml8726_mmc_soft_reset(sc, false);
426 * Ensure the command has terminated before continuing on
427 * to things such as bus_dmamap_sync / bus_dmamap_unload.
429 while ((CSR_READ_4(sc, AML_MMC_IRQ_STATUS_REG) &
430 AML_MMC_IRQ_STATUS_CMD_BUSY) != 0)
433 aml8726_mmc_finish_command(sc, MMC_ERR_TIMEOUT);
437 aml8726_mmc_intr(void *arg)
439 struct aml8726_mmc_softc *sc = (struct aml8726_mmc_softc *)arg;
443 uint32_t previous_byte;
450 isr = CSR_READ_4(sc, AML_MMC_IRQ_STATUS_REG);
451 cmdr = CSR_READ_4(sc, AML_MMC_CMD_SEND_REG);
456 mmc_error = MMC_ERR_NONE;
458 if ((isr & AML_MMC_IRQ_STATUS_CMD_DONE_IRQ) != 0) {
459 /* Check for CRC errors if the command has completed. */
460 if ((cmdr & AML_MMC_CMD_RESP_NO_CRC7) == 0 &&
461 (isr & AML_MMC_IRQ_STATUS_RESP_CRC7_OK) == 0)
462 mmc_error = MMC_ERR_BADCRC;
463 if ((cmdr & AML_MMC_CMD_RESP_HAS_DATA) != 0 &&
464 (isr & AML_MMC_IRQ_STATUS_RD_CRC16_OK) == 0)
465 mmc_error = MMC_ERR_BADCRC;
466 if ((cmdr & AML_MMC_CMD_CMD_HAS_DATA) != 0 &&
467 (isr & AML_MMC_IRQ_STATUS_WR_CRC16_OK) == 0)
468 mmc_error = MMC_ERR_BADCRC;
473 * Clear spurious interrupts while leaving intacted any
474 * interrupts that may have occurred after we read the
475 * interrupt status register.
478 CSR_WRITE_4(sc, AML_MMC_IRQ_STATUS_REG,
479 (AML_MMC_IRQ_STATUS_CLEAR_IRQ & isr));
480 CSR_BARRIER(sc, AML_MMC_IRQ_STATUS_REG);
485 if ((cmdr & AML_MMC_CMD_RESP_BITS_MASK) != 0) {
487 mcfgr |= AML_MMC_MULT_CONFIG_RESP_READOUT_EN;
488 CSR_WRITE_4(sc, AML_MMC_MULT_CONFIG_REG, mcfgr);
490 if ((cmdr & AML_MMC_CMD_RESP_CRC7_FROM_8) != 0) {
493 * Controller supplies 135:8 instead of
494 * 127:0 so discard the leading 8 bits
495 * and provide a trailing 8 zero bits
496 * where the CRC belongs.
501 for (i = 0; i < 4; i++) {
502 resp = CSR_READ_4(sc, AML_MMC_CMD_ARGUMENT_REG);
503 sc->cmd->resp[3 - i] = (resp << 8) |
505 previous_byte = (resp >> 24) & 0xff;
508 sc->cmd->resp[0] = CSR_READ_4(sc,
509 AML_MMC_CMD_ARGUMENT_REG);
512 if ((isr & AML_MMC_IRQ_STATUS_CMD_BUSY) != 0 &&
514 * A multiblock operation may keep the hardware
515 * busy until stop transmission is executed.
517 (isr & AML_MMC_IRQ_STATUS_CMD_DONE_IRQ) == 0) {
518 if (mmc_error == MMC_ERR_NONE)
519 mmc_error = MMC_ERR_FAILED;
522 * Issue a soft reset to terminate the command.
524 * Ensure the command has terminated before continuing on
525 * to things such as bus_dmamap_sync / bus_dmamap_unload.
528 aml8726_mmc_soft_reset(sc, false);
530 while ((CSR_READ_4(sc, AML_MMC_IRQ_STATUS_REG) &
531 AML_MMC_IRQ_STATUS_CMD_BUSY) != 0)
535 aml8726_mmc_finish_command(sc, mmc_error);
539 aml8726_mmc_probe(device_t dev)
542 if (!ofw_bus_status_okay(dev))
545 if (!ofw_bus_is_compatible(dev, "amlogic,aml8726-mmc"))
548 device_set_desc(dev, "Amlogic aml8726 MMC");
550 return (BUS_PROBE_DEFAULT);
554 aml8726_mmc_attach(device_t dev)
556 struct aml8726_mmc_softc *sc = device_get_softc(dev);
569 node = ofw_bus_get_node(dev);
571 sc->ref_freq = aml8726_mmc_clk(node);
573 if (sc->ref_freq == 0) {
574 device_printf(dev, "missing clocks attribute in FDT\n");
579 * The pins must be specified as part of the device in order
580 * to know which port to used.
583 len = OF_getencprop(node, "pinctrl-0", prop, sizeof(prop));
585 if ((len / sizeof(prop[0])) != 1 || prop[0] == 0) {
586 device_printf(dev, "missing pinctrl-0 attribute in FDT\n");
590 len = OF_getprop_alloc(OF_node_from_xref(prop[0]), "amlogic,function",
591 sizeof(char), (void **)&function_name);
595 "missing amlogic,function attribute in FDT\n");
599 if (strncmp("sdio-a", function_name, len) == 0)
600 sc->port = AML_MMC_MULT_CONFIG_PORT_A;
601 else if (strncmp("sdio-b", function_name, len) == 0)
602 sc->port = AML_MMC_MULT_CONFIG_PORT_B;
603 else if (strncmp("sdio-c", function_name, len) == 0)
604 sc->port = AML_MMC_MULT_CONFIG_PORT_C;
606 device_printf(dev, "unknown function attribute %.*s in FDT\n",
608 free(function_name, M_OFWPROP);
612 free(function_name, M_OFWPROP);
614 sc->pwr_en.dev = NULL;
616 len = OF_getencprop(node, "mmc-pwr-en", prop, sizeof(prop));
618 if ((len / sizeof(prop[0])) == 3) {
619 sc->pwr_en.dev = OF_device_from_xref(prop[0]);
620 sc->pwr_en.pin = prop[1];
621 sc->pwr_en.pol = prop[2];
624 if (sc->pwr_en.dev == NULL) {
626 "unable to process mmc-pwr-en attribute in FDT\n");
630 /* Turn off power and then configure the output driver. */
631 if (aml8726_mmc_power_off(sc) != 0 ||
632 GPIO_PIN_SETFLAGS(sc->pwr_en.dev, sc->pwr_en.pin,
633 GPIO_PIN_OUTPUT) != 0) {
635 "could not use gpio to control power\n");
640 len = OF_getprop_alloc(node, "mmc-voltages",
641 sizeof(char), (void **)&voltages);
644 device_printf(dev, "missing mmc-voltages attribute in FDT\n");
654 while (len && nvoltages < 2) {
655 if (strncmp("1.8", voltage, len) == 0)
656 sc->voltages[nvoltages] = MMC_OCR_LOW_VOLTAGE;
657 else if (strncmp("3.3", voltage, len) == 0)
658 sc->voltages[nvoltages] = MMC_OCR_320_330 |
662 "unknown voltage attribute %.*s in FDT\n",
664 free(voltages, M_OFWPROP);
670 /* queue up next string */
671 while (*voltage && len) {
681 free(voltages, M_OFWPROP);
683 sc->vselect.dev = NULL;
685 len = OF_getencprop(node, "mmc-vselect", prop, sizeof(prop));
687 if ((len / sizeof(prop[0])) == 2) {
688 sc->vselect.dev = OF_device_from_xref(prop[0]);
689 sc->vselect.pin = prop[1];
693 if (sc->vselect.dev == NULL) {
695 "unable to process mmc-vselect attribute in FDT\n");
700 * With the power off select voltage 0 and then
701 * configure the output driver.
703 if (GPIO_PIN_SET(sc->vselect.dev, sc->vselect.pin, 0) != 0 ||
704 GPIO_PIN_SETFLAGS(sc->vselect.dev, sc->vselect.pin,
705 GPIO_PIN_OUTPUT) != 0) {
707 "could not use gpio to set voltage\n");
712 if (nvoltages == 0) {
713 device_printf(dev, "no voltages in FDT\n");
715 } else if (nvoltages == 1 && sc->vselect.dev != NULL) {
716 device_printf(dev, "only one voltage in FDT\n");
718 } else if (nvoltages == 2 && sc->vselect.dev == NULL) {
719 device_printf(dev, "too many voltages in FDT\n");
723 if (bus_alloc_resources(dev, aml8726_mmc_spec, sc->res)) {
724 device_printf(dev, "could not allocate resources for device\n");
728 AML_MMC_LOCK_INIT(sc);
730 error = bus_dma_tag_create(bus_get_dma_tag(dev), AML_MMC_ALIGN_DMA, 0,
731 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
732 AML_MMC_MAX_DMA, 1, AML_MMC_MAX_DMA, 0, NULL, NULL, &sc->dmatag);
736 error = bus_dmamap_create(sc->dmatag, 0, &sc->dmamap);
741 error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC | INTR_MPSAFE,
742 NULL, aml8726_mmc_intr, sc, &sc->ih_cookie);
744 device_printf(dev, "could not setup interrupt handler\n");
748 callout_init_mtx(&sc->ch, &sc->mtx, CALLOUT_RETURNUNLOCKED);
750 sc->host.f_min = aml8726_mmc_freq(sc, aml8726_mmc_div(sc, 200000));
751 sc->host.f_max = aml8726_mmc_freq(sc, aml8726_mmc_div(sc, 50000000));
752 sc->host.host_ocr = sc->voltages[0] | sc->voltages[1];
753 sc->host.caps = MMC_CAP_4_BIT_DATA | MMC_CAP_HSPEED;
755 child = device_add_child(dev, "mmc", -1);
758 device_printf(dev, "could not add mmc\n");
763 error = device_probe_and_attach(child);
766 device_printf(dev, "could not attach mmc\n");
774 bus_teardown_intr(dev, sc->res[1], sc->ih_cookie);
777 bus_dmamap_destroy(sc->dmatag, sc->dmamap);
780 bus_dma_tag_destroy(sc->dmatag);
782 AML_MMC_LOCK_DESTROY(sc);
784 aml8726_mmc_power_off(sc);
786 bus_release_resources(dev, aml8726_mmc_spec, sc->res);
792 aml8726_mmc_detach(device_t dev)
794 struct aml8726_mmc_softc *sc = device_get_softc(dev);
798 if (sc->cmd != NULL) {
804 * Turn off the power, reset the hardware state machine,
805 * disable the interrupts, and clear the interrupts.
807 (void)aml8726_mmc_power_off(sc);
808 aml8726_mmc_soft_reset(sc, false);
809 CSR_WRITE_4(sc, AML_MMC_IRQ_STATUS_REG, AML_MMC_IRQ_STATUS_CLEAR_IRQ);
811 /* This should be a NOP since no command was in flight. */
812 callout_stop(&sc->ch);
816 bus_generic_detach(dev);
818 bus_teardown_intr(dev, sc->res[1], sc->ih_cookie);
820 bus_dmamap_destroy(sc->dmatag, sc->dmamap);
822 bus_dma_tag_destroy(sc->dmatag);
824 AML_MMC_LOCK_DESTROY(sc);
826 bus_release_resources(dev, aml8726_mmc_spec, sc->res);
832 aml8726_mmc_shutdown(device_t dev)
834 struct aml8726_mmc_softc *sc = device_get_softc(dev);
837 * Turn off the power, reset the hardware state machine,
838 * disable the interrupts, and clear the interrupts.
840 (void)aml8726_mmc_power_off(sc);
841 aml8726_mmc_soft_reset(sc, false);
842 CSR_WRITE_4(sc, AML_MMC_IRQ_STATUS_REG, AML_MMC_IRQ_STATUS_CLEAR_IRQ);
848 aml8726_mmc_update_ios(device_t bus, device_t child)
850 struct aml8726_mmc_softc *sc = device_get_softc(bus);
851 struct mmc_ios *ios = &sc->host.ios;
856 cfgr = (2 << AML_MMC_CONFIG_WR_CRC_STAT_SHIFT) |
857 (2 << AML_MMC_CONFIG_WR_DELAY_SHIFT) |
858 AML_MMC_CONFIG_DMA_ENDIAN_SBW |
859 (39 << AML_MMC_CONFIG_CMD_ARG_BITS_SHIFT);
861 switch (ios->bus_width) {
863 cfgr |= AML_MMC_CONFIG_BUS_WIDTH_4;
866 cfgr |= AML_MMC_CONFIG_BUS_WIDTH_1;
872 cfgr |= aml8726_mmc_div(sc, ios->clock) <<
873 AML_MMC_CONFIG_CMD_CLK_DIV_SHIFT;
875 CSR_WRITE_4(sc, AML_MMC_CONFIG_REG, cfgr);
879 switch (ios->power_mode) {
882 * Configure and power on the regulator so that the
883 * voltage stabilizes prior to powering on the card.
885 if (sc->vselect.dev != NULL) {
886 for (i = 0; i < 2; i++)
887 if ((sc->voltages[i] & (1 << ios->vdd)) != 0)
891 error = GPIO_PIN_SET(sc->vselect.dev,
896 error = aml8726_mmc_power_on(sc);
899 error = aml8726_mmc_power_off(sc);
909 aml8726_mmc_request(device_t bus, device_t child, struct mmc_request *req)
911 struct aml8726_mmc_softc *sc = device_get_softc(bus);
916 if (sc->cmd != NULL) {
921 mmc_error = aml8726_mmc_start_command(sc, req->cmd);
925 /* Execute the callback after dropping the lock. */
926 if (mmc_error != MMC_ERR_NONE) {
927 req->cmd->error = mmc_error;
935 aml8726_mmc_read_ivar(device_t bus, device_t child,
936 int which, uintptr_t *result)
938 struct aml8726_mmc_softc *sc = device_get_softc(bus);
941 case MMCBR_IVAR_BUS_MODE:
942 *(int *)result = sc->host.ios.bus_mode;
944 case MMCBR_IVAR_BUS_WIDTH:
945 *(int *)result = sc->host.ios.bus_width;
947 case MMCBR_IVAR_CHIP_SELECT:
948 *(int *)result = sc->host.ios.chip_select;
950 case MMCBR_IVAR_CLOCK:
951 *(int *)result = sc->host.ios.clock;
953 case MMCBR_IVAR_F_MIN:
954 *(int *)result = sc->host.f_min;
956 case MMCBR_IVAR_F_MAX:
957 *(int *)result = sc->host.f_max;
959 case MMCBR_IVAR_HOST_OCR:
960 *(int *)result = sc->host.host_ocr;
962 case MMCBR_IVAR_MODE:
963 *(int *)result = sc->host.mode;
966 *(int *)result = sc->host.ocr;
968 case MMCBR_IVAR_POWER_MODE:
969 *(int *)result = sc->host.ios.power_mode;
972 *(int *)result = sc->host.ios.vdd;
974 case MMCBR_IVAR_CAPS:
975 *(int *)result = sc->host.caps;
977 case MMCBR_IVAR_MAX_DATA:
978 *(int *)result = AML_MMC_MAX_DMA / MMC_SECTOR_SIZE;
988 aml8726_mmc_write_ivar(device_t bus, device_t child,
989 int which, uintptr_t value)
991 struct aml8726_mmc_softc *sc = device_get_softc(bus);
994 case MMCBR_IVAR_BUS_MODE:
995 sc->host.ios.bus_mode = value;
997 case MMCBR_IVAR_BUS_WIDTH:
998 sc->host.ios.bus_width = value;
1000 case MMCBR_IVAR_CHIP_SELECT:
1001 sc->host.ios.chip_select = value;
1003 case MMCBR_IVAR_CLOCK:
1004 sc->host.ios.clock = value;
1006 case MMCBR_IVAR_MODE:
1007 sc->host.mode = value;
1009 case MMCBR_IVAR_OCR:
1010 sc->host.ocr = value;
1012 case MMCBR_IVAR_POWER_MODE:
1013 sc->host.ios.power_mode = value;
1015 case MMCBR_IVAR_VDD:
1016 sc->host.ios.vdd = value;
1018 /* These are read-only */
1019 case MMCBR_IVAR_CAPS:
1020 case MMCBR_IVAR_HOST_OCR:
1021 case MMCBR_IVAR_F_MIN:
1022 case MMCBR_IVAR_F_MAX:
1023 case MMCBR_IVAR_MAX_DATA:
1032 aml8726_mmc_get_ro(device_t bus, device_t child)
1039 aml8726_mmc_acquire_host(device_t bus, device_t child)
1041 struct aml8726_mmc_softc *sc = device_get_softc(bus);
1045 while (sc->bus_busy)
1046 mtx_sleep(sc, &sc->mtx, PZERO, "mmc", hz / 5);
1055 aml8726_mmc_release_host(device_t bus, device_t child)
1057 struct aml8726_mmc_softc *sc = device_get_softc(bus);
1069 static device_method_t aml8726_mmc_methods[] = {
1070 /* Device interface */
1071 DEVMETHOD(device_probe, aml8726_mmc_probe),
1072 DEVMETHOD(device_attach, aml8726_mmc_attach),
1073 DEVMETHOD(device_detach, aml8726_mmc_detach),
1074 DEVMETHOD(device_shutdown, aml8726_mmc_shutdown),
1077 DEVMETHOD(bus_read_ivar, aml8726_mmc_read_ivar),
1078 DEVMETHOD(bus_write_ivar, aml8726_mmc_write_ivar),
1080 /* MMC bridge interface */
1081 DEVMETHOD(mmcbr_update_ios, aml8726_mmc_update_ios),
1082 DEVMETHOD(mmcbr_request, aml8726_mmc_request),
1083 DEVMETHOD(mmcbr_get_ro, aml8726_mmc_get_ro),
1084 DEVMETHOD(mmcbr_acquire_host, aml8726_mmc_acquire_host),
1085 DEVMETHOD(mmcbr_release_host, aml8726_mmc_release_host),
1090 static driver_t aml8726_mmc_driver = {
1092 aml8726_mmc_methods,
1093 sizeof(struct aml8726_mmc_softc),
1096 static devclass_t aml8726_mmc_devclass;
1098 DRIVER_MODULE(aml8726_mmc, simplebus, aml8726_mmc_driver,
1099 aml8726_mmc_devclass, 0, 0);
1100 MODULE_DEPEND(aml8726_mmc, aml8726_gpio, 1, 1, 1);