diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2018-03-30 19:50:56 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2018-03-30 19:50:56 +0000 |
commit | f26cbba045fc5f6cee25c4d8eb2a5aca0a41fec7 (patch) | |
tree | 2e1b767a8b06ed84774b4268bde4cbc3583510dd /sys/arch/armv7/imx | |
parent | 62072e13906237c4a9eb183889fc7e892638a695 (diff) |
Move imxesdhc(4) to sys/dev/fdt.
Diffstat (limited to 'sys/arch/armv7/imx')
-rw-r--r-- | sys/arch/armv7/imx/files.imx | 6 | ||||
-rw-r--r-- | sys/arch/armv7/imx/imxesdhc.c | 1210 |
2 files changed, 1 insertions, 1215 deletions
diff --git a/sys/arch/armv7/imx/files.imx b/sys/arch/armv7/imx/files.imx index bc56cbb8f25..cb86c895b60 100644 --- a/sys/arch/armv7/imx/files.imx +++ b/sys/arch/armv7/imx/files.imx @@ -1,4 +1,4 @@ -# $OpenBSD: files.imx,v 1.24 2018/03/30 19:38:00 patrick Exp $ +# $OpenBSD: files.imx,v 1.25 2018/03/30 19:50:55 patrick Exp $ device imxccm attach imxccm at fdt @@ -28,10 +28,6 @@ device imxehci: usbus attach imxehci at fdt file arch/armv7/imx/imxehci.c imxehci -device imxesdhc: sdmmcbus -attach imxesdhc at fdt -file arch/armv7/imx/imxesdhc.c imxesdhc - device imxahci: scsi, atascsi attach imxahci at fdt file arch/armv7/imx/imxahci.c imxahci diff --git a/sys/arch/armv7/imx/imxesdhc.c b/sys/arch/armv7/imx/imxesdhc.c deleted file mode 100644 index 15152fe42e0..00000000000 --- a/sys/arch/armv7/imx/imxesdhc.c +++ /dev/null @@ -1,1210 +0,0 @@ -/* $OpenBSD: imxesdhc.c,v 1.39 2018/02/16 07:37:48 patrick Exp $ */ -/* - * Copyright (c) 2009 Dale Rahn <drahn@openbsd.org> - * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org> - * Copyright (c) 2012-2013 Patrick Wildt <patrick@blueri.se> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* i.MX SD/MMC support derived from /sys/dev/sdmmc/sdhc.c */ - -#include <sys/param.h> -#include <sys/device.h> -#include <sys/kernel.h> -#include <sys/kthread.h> -#include <sys/malloc.h> -#include <sys/systm.h> -#include <machine/bus.h> -#include <machine/fdt.h> - -#include <dev/sdmmc/sdmmcchip.h> -#include <dev/sdmmc/sdmmcvar.h> - -#include <dev/ofw/openfirm.h> -#include <dev/ofw/ofw_clock.h> -#include <dev/ofw/ofw_gpio.h> -#include <dev/ofw/ofw_pinctrl.h> -#include <dev/ofw/ofw_regulator.h> -#include <dev/ofw/fdt.h> - -/* registers */ -#define SDHC_DS_ADDR 0x00 -#define SDHC_BLK_ATT 0x04 -#define SDHC_CMD_ARG 0x08 -#define SDHC_CMD_XFR_TYP 0x0c -#define SDHC_CMD_RSP0 0x10 -#define SDHC_CMD_RSP1 0x14 -#define SDHC_CMD_RSP2 0x18 -#define SDHC_CMD_RSP3 0x1c -#define SDHC_DATA_BUFF_ACC_PORT 0x20 -#define SDHC_PRES_STATE 0x24 -#define SDHC_PROT_CTRL 0x28 -#define SDHC_SYS_CTRL 0x2c -#define SDHC_INT_STATUS 0x30 -#define SDHC_INT_STATUS_EN 0x34 -#define SDHC_INT_SIGNAL_EN 0x38 -#define SDHC_AUTOCMD12_ERR_STATUS 0x3c -#define SDHC_HOST_CTRL_CAP 0x40 -#define SDHC_WTMK_LVL 0x44 -#define SDHC_MIX_CTRL 0x48 -#define SDHC_FORCE_EVENT 0x50 -#define SDHC_ADMA_ERR_STATUS 0x54 -#define SDHC_ADMA_SYS_ADDR 0x58 -#define SDHC_DLL_CTRL 0x60 -#define SDHC_DLL_STATUS 0x64 -#define SDHC_CLK_TUNE_CTRL_STATUS 0x68 -#define SDHC_VEND_SPEC 0xc0 -#define SDHC_MMC_BOOT 0xc4 -#define SDHC_VEND_SPEC2 0xc8 -#define SDHC_HOST_CTRL_VER 0xfc - -/* bits and bytes */ -#define SDHC_BLK_ATT_BLKCNT_MAX 0xffff -#define SDHC_BLK_ATT_BLKCNT_SHIFT 16 -#define SDHC_BLK_ATT_BLKSIZE_SHIFT 0 -#define SDHC_CMD_XFR_TYP_CMDINDX_SHIFT 24 -#define SDHC_CMD_XFR_TYP_CMDINDX_SHIFT_MASK (0x3f << SDHC_CMD_XFR_TYP_CMDINDX_SHIFT) -#define SDHC_CMD_XFR_TYP_CMDTYP_SHIFT 22 -#define SDHC_CMD_XFR_TYP_DPSEL_SHIFT 21 -#define SDHC_CMD_XFR_TYP_DPSEL (1 << SDHC_CMD_XFR_TYP_DPSEL_SHIFT) -#define SDHC_CMD_XFR_TYP_CICEN_SHIFT 20 -#define SDHC_CMD_XFR_TYP_CICEN (1 << SDHC_CMD_XFR_TYP_CICEN_SHIFT) -#define SDHC_CMD_XFR_TYP_CCCEN_SHIFT 19 -#define SDHC_CMD_XFR_TYP_CCCEN (1 << SDHC_CMD_XFR_TYP_CCCEN_SHIFT) -#define SDHC_CMD_XFR_TYP_RSPTYP_SHIFT 16 -#define SDHC_CMD_XFR_TYP_RSP_NONE (0x0 << SDHC_CMD_XFR_TYP_RSPTYP_SHIFT) -#define SDHC_CMD_XFR_TYP_RSP136 (0x1 << SDHC_CMD_XFR_TYP_RSPTYP_SHIFT) -#define SDHC_CMD_XFR_TYP_RSP48 (0x2 << SDHC_CMD_XFR_TYP_RSPTYP_SHIFT) -#define SDHC_CMD_XFR_TYP_RSP48B (0x3 << SDHC_CMD_XFR_TYP_RSPTYP_SHIFT) -#define SDHC_PRES_STATE_WPSPL (1 << 19) -#define SDHC_PRES_STATE_BREN (1 << 11) -#define SDHC_PRES_STATE_BWEN (1 << 10) -#define SDHC_PRES_STATE_SDSTB (1 << 3) -#define SDHC_PRES_STATE_DLA (1 << 2) -#define SDHC_PRES_STATE_CDIHB (1 << 1) -#define SDHC_PRES_STATE_CIHB (1 << 0) -#define SDHC_SYS_CTRL_RSTA (1 << 24) -#define SDHC_SYS_CTRL_RSTC (1 << 25) -#define SDHC_SYS_CTRL_RSTD (1 << 26) -#define SDHC_SYS_CTRL_CLOCK_MASK (0xfff << 4) -#define SDHC_SYS_CTRL_CLOCK_DIV_SHIFT 4 -#define SDHC_SYS_CTRL_CLOCK_PRE_SHIFT 8 -#define SDHC_SYS_CTRL_DTOCV_SHIFT 16 -#define SDHC_INT_STATUS_CC (1 << 0) -#define SDHC_INT_STATUS_TC (1 << 1) -#define SDHC_INT_STATUS_BGE (1 << 2) -#define SDHC_INT_STATUS_DINT (1 << 3) -#define SDHC_INT_STATUS_BWR (1 << 4) -#define SDHC_INT_STATUS_BRR (1 << 5) -#define SDHC_INT_STATUS_CINS (1 << 6) -#define SDHC_INT_STATUS_CRM (1 << 7) -#define SDHC_INT_STATUS_CINT (1 << 8) -#define SDHC_INT_STATUS_CTOE (1 << 16) -#define SDHC_INT_STATUS_CCE (1 << 17) -#define SDHC_INT_STATUS_CEBE (1 << 18) -#define SDHC_INT_STATUS_CIC (1 << 19) -#define SDHC_INT_STATUS_DTOE (1 << 20) -#define SDHC_INT_STATUS_DCE (1 << 21) -#define SDHC_INT_STATUS_DEBE (1 << 22) -#define SDHC_INT_STATUS_DMAE (1 << 28) -#define SDHC_INT_STATUS_CMD_ERR (SDHC_INT_STATUS_CIC | SDHC_INT_STATUS_CEBE | SDHC_INT_STATUS_CCE) -#define SDHC_INT_STATUS_ERR (SDHC_INT_STATUS_CTOE | SDHC_INT_STATUS_CCE | SDHC_INT_STATUS_CEBE | \ - SDHC_INT_STATUS_CIC | SDHC_INT_STATUS_DTOE | SDHC_INT_STATUS_DCE | \ - SDHC_INT_STATUS_DEBE | SDHC_INT_STATUS_DMAE) -#define SDHC_MIX_CTRL_DMAEN (1 << 0) -#define SDHC_MIX_CTRL_BCEN (1 << 1) -#define SDHC_MIX_CTRL_AC12EN (1 << 2) -#define SDHC_MIX_CTRL_DTDSEL (1 << 4) -#define SDHC_MIX_CTRL_MSBSEL (1 << 5) -#define SDHC_PROT_CTRL_DTW_MASK (0x3 << 1) -#define SDHC_PROT_CTRL_DTW_4BIT (1 << 1) -#define SDHC_PROT_CTRL_DTW_8BIT (1 << 2) -#define SDHC_PROT_CTRL_DMASEL_MASK (0x3 << 8) -#define SDHC_PROT_CTRL_DMASEL_SDMA (0x0 << 8) -#define SDHC_PROT_CTRL_DMASEL_ADMA1 (0x1 << 8) -#define SDHC_PROT_CTRL_DMASEL_ADMA2 (0x2 << 8) -#define SDHC_HOST_CTRL_CAP_MBL_SHIFT 16 -#define SDHC_HOST_CTRL_CAP_MBL_MASK 0x7 -#define SDHC_HOST_CTRL_CAP_ADMAS (1 << 20) -#define SDHC_HOST_CTRL_CAP_HSS (1 << 21) -#define SDHC_HOST_CTRL_CAP_VS33 (1 << 24) -#define SDHC_HOST_CTRL_CAP_VS30 (1 << 25) -#define SDHC_HOST_CTRL_CAP_VS18 (1 << 26) -#define SDHC_VEND_SPEC_FRC_SDCLK_ON (1 << 8) -#define SDHC_WTMK_LVL_RD_WML_SHIFT 0 -#define SDHC_WTMK_LVL_RD_BRST_LEN_SHIFT 8 -#define SDHC_WTMK_LVL_WR_WML_SHIFT 16 -#define SDHC_WTMK_LVL_WR_BRST_LEN_SHIFT 24 - -#define SDHC_COMMAND_TIMEOUT hz -#define SDHC_BUFFER_TIMEOUT hz -#define SDHC_TRANSFER_TIMEOUT hz -#define SDHC_DMA_TIMEOUT (3 * hz) - -#define SDHC_ADMA2_VALID (1 << 0) -#define SDHC_ADMA2_END (1 << 1) -#define SDHC_ADMA2_INT (1 << 2) -#define SDHC_ADMA2_ACT (3 << 4) -#define SDHC_ADMA2_ACT_NOP (0 << 4) -#define SDHC_ADMA2_ACT_TRANS (2 << 4) -#define SDHC_ADMA2_ACT_LINK (3 << 4) - -struct sdhc_adma2_descriptor32 { - uint16_t attribute; - uint16_t length; - uint32_t address; -} __packed; - - -int imxesdhc_match(struct device *, void *, void *); -void imxesdhc_attach(struct device *, struct device *, void *); - -struct imxesdhc_softc { - struct device sc_dev; - bus_space_tag_t sc_iot; - bus_space_handle_t sc_ioh; - bus_dma_tag_t sc_dmat; - void *sc_ih; /* interrupt handler */ - int sc_node; - uint32_t sc_gpio[3]; - uint32_t sc_vmmc; - uint32_t sc_pwrseq; - uint32_t sc_vdd; - u_int sc_flags; - - struct device *sdmmc; /* generic SD/MMC device */ - int clockbit; /* clock control bit */ - u_int clkbase; /* base clock freq. in KHz */ - int maxblklen; /* maximum block length */ - int flags; /* flags for this host */ - uint32_t ocr; /* OCR value from caps */ - uint32_t intr_status; /* soft interrupt status */ - uint32_t intr_error_status; - - bus_dmamap_t adma_map; - bus_dma_segment_t adma_segs[1]; - caddr_t adma2; -}; - -/* Host controller functions called by the attachment driver. */ -int imxesdhc_intr(void *); - -void imxesdhc_clock_enable(uint32_t); -void imxesdhc_pwrseq_pre(uint32_t); -void imxesdhc_pwrseq_post(uint32_t); - -/* RESET MODES */ -#define MMC_RESET_DAT 1 -#define MMC_RESET_CMD 2 -#define MMC_RESET_ALL (MMC_RESET_CMD|MMC_RESET_DAT) - -#define HDEVNAME(sc) ((sc)->sc_dev.dv_xname) - -/* flag values */ -#define SHF_USE_DMA 0x0001 - -/* SDHC should only be accessed with 4 byte reads or writes. */ -#define HREAD4(sc, reg) \ - (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) -#define HWRITE4(sc, reg, val) \ - bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) -#define HSET4(sc, reg, bits) \ - HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits)) -#define HCLR4(sc, reg, bits) \ - HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits)) - -int imxesdhc_host_reset(sdmmc_chipset_handle_t); -uint32_t imxesdhc_host_ocr(sdmmc_chipset_handle_t); -int imxesdhc_host_maxblklen(sdmmc_chipset_handle_t); -int imxesdhc_card_detect(sdmmc_chipset_handle_t); -int imxesdhc_bus_power(sdmmc_chipset_handle_t, uint32_t); -int imxesdhc_bus_clock(sdmmc_chipset_handle_t, int, int); -int imxesdhc_bus_width(sdmmc_chipset_handle_t, int); -void imxesdhc_card_intr_mask(sdmmc_chipset_handle_t, int); -void imxesdhc_card_intr_ack(sdmmc_chipset_handle_t); -void imxesdhc_exec_command(sdmmc_chipset_handle_t, struct sdmmc_command *); -int imxesdhc_start_command(struct imxesdhc_softc *, struct sdmmc_command *); -int imxesdhc_wait_state(struct imxesdhc_softc *, uint32_t, uint32_t); -int imxesdhc_soft_reset(struct imxesdhc_softc *, int); -int imxesdhc_wait_intr(struct imxesdhc_softc *, int, int); -void imxesdhc_transfer_data(struct imxesdhc_softc *, struct sdmmc_command *); -void imxesdhc_read_data(struct imxesdhc_softc *, u_char *, int); -void imxesdhc_write_data(struct imxesdhc_softc *, u_char *, int); - -//#define SDHC_DEBUG -#ifdef SDHC_DEBUG -int imxesdhcdebug = 20; -#define DPRINTF(n,s) do { if ((n) <= imxesdhcdebug) printf s; } while (0) -#else -#define DPRINTF(n,s) do {} while(0) -#endif - -struct sdmmc_chip_functions imxesdhc_functions = { - /* host controller reset */ - imxesdhc_host_reset, - /* host controller capabilities */ - imxesdhc_host_ocr, - imxesdhc_host_maxblklen, - /* card detection */ - imxesdhc_card_detect, - /* bus power and clock frequency */ - imxesdhc_bus_power, - imxesdhc_bus_clock, - imxesdhc_bus_width, - /* command execution */ - imxesdhc_exec_command, - /* card interrupt */ - imxesdhc_card_intr_mask, - imxesdhc_card_intr_ack -}; - -struct cfdriver imxesdhc_cd = { - NULL, "imxesdhc", DV_DULL -}; - -struct cfattach imxesdhc_ca = { - sizeof(struct imxesdhc_softc), imxesdhc_match, imxesdhc_attach -}; - -int -imxesdhc_match(struct device *parent, void *match, void *aux) -{ - struct fdt_attach_args *faa = aux; - - return OF_is_compatible(faa->fa_node, "fsl,imx6q-usdhc") || - OF_is_compatible(faa->fa_node, "fsl,imx6sx-usdhc"); -} - -void -imxesdhc_attach(struct device *parent, struct device *self, void *aux) -{ - struct imxesdhc_softc *sc = (struct imxesdhc_softc *) self; - struct fdt_attach_args *faa = aux; - struct sdmmcbus_attach_args saa; - int error = 1; - uint32_t caps; - uint32_t width; - - if (faa->fa_nreg < 1) - return; - - sc->sc_node = faa->fa_node; - sc->sc_dmat = faa->fa_dmat; - sc->sc_iot = faa->fa_iot; - if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, - faa->fa_reg[0].size, 0, &sc->sc_ioh)) - panic("imxesdhc_attach: bus_space_map failed!"); - - printf("\n"); - - pinctrl_byname(faa->fa_node, "default"); - - sc->sc_ih = arm_intr_establish_fdt(faa->fa_node, IPL_SDMMC, - imxesdhc_intr, sc, sc->sc_dev.dv_xname); - - OF_getpropintarray(sc->sc_node, "cd-gpios", sc->sc_gpio, - sizeof(sc->sc_gpio)); - gpio_controller_config_pin(sc->sc_gpio, GPIO_CONFIG_INPUT); - - sc->sc_vmmc = OF_getpropint(sc->sc_node, "vmmc-supply", 0); - sc->sc_pwrseq = OF_getpropint(sc->sc_node, "mmc-pwrseq", 0); - - /* - * Reset the host controller and enable interrupts. - */ - if (imxesdhc_host_reset(sc)) - return; - - /* Determine host capabilities. */ - caps = HREAD4(sc, SDHC_HOST_CTRL_CAP); - if (OF_is_compatible(sc->sc_node, "fsl,imx6sx-usdhc")) - caps &= 0xffff0000; - - /* Use DMA if the host system and the controller support it. */ - if (ISSET(caps, SDHC_HOST_CTRL_CAP_ADMAS)) - SET(sc->flags, SHF_USE_DMA); - - /* - * Determine the base clock frequency. (2.2.24) - */ - sc->clkbase = clock_get_frequency(faa->fa_node, "per") / 1000; - - printf("%s: %d MHz base clock\n", DEVNAME(sc), sc->clkbase / 1000); - - /* - * Determine SD bus voltage levels supported by the controller. - */ - if (caps & SDHC_HOST_CTRL_CAP_VS18) - SET(sc->ocr, MMC_OCR_1_65V_1_95V); - if (caps & SDHC_HOST_CTRL_CAP_VS30) - SET(sc->ocr, MMC_OCR_2_9V_3_0V | MMC_OCR_3_0V_3_1V); - if (caps & SDHC_HOST_CTRL_CAP_VS33) - SET(sc->ocr, MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V); - - /* - * Determine max block size. - */ - switch ((caps >> SDHC_HOST_CTRL_CAP_MBL_SHIFT) - & SDHC_HOST_CTRL_CAP_MBL_MASK) { - case 0: - sc->maxblklen = 512; - break; - case 1: - sc->maxblklen = 1024; - break; - case 2: - sc->maxblklen = 2048; - break; - case 3: - sc->maxblklen = 4096; - break; - default: - sc->maxblklen = 512; - printf("invalid capability blocksize in capa %08x," - " trying 512\n", caps); - } - - /* somewhere this blksize might be used instead of the device's */ - sc->maxblklen = 512; - - if (ISSET(sc->flags, SHF_USE_DMA)) { - int rseg; - - /* Allocate ADMA2 descriptor memory */ - error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE, - PAGE_SIZE, sc->adma_segs, 1, &rseg, - BUS_DMA_WAITOK | BUS_DMA_ZERO); - if (error) - goto adma_done; - error = bus_dmamem_map(sc->sc_dmat, sc->adma_segs, rseg, - PAGE_SIZE, &sc->adma2, BUS_DMA_WAITOK | BUS_DMA_COHERENT); - if (error) { - bus_dmamem_free(sc->sc_dmat, sc->adma_segs, rseg); - goto adma_done; - } - error = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, - 0, BUS_DMA_WAITOK, &sc->adma_map); - if (error) { - bus_dmamem_unmap(sc->sc_dmat, sc->adma2, PAGE_SIZE); - bus_dmamem_free(sc->sc_dmat, sc->adma_segs, rseg); - goto adma_done; - } - error = bus_dmamap_load(sc->sc_dmat, sc->adma_map, - sc->adma2, PAGE_SIZE, NULL, - BUS_DMA_WAITOK | BUS_DMA_WRITE); - if (error) { - bus_dmamap_destroy(sc->sc_dmat, sc->adma_map); - bus_dmamem_unmap(sc->sc_dmat, sc->adma2, PAGE_SIZE); - bus_dmamem_free(sc->sc_dmat, sc->adma_segs, rseg); - goto adma_done; - } - - adma_done: - if (error) { - printf("%s: can't allocate DMA descriptor table\n", - DEVNAME(sc)); - CLR(sc->flags, SHF_USE_DMA); - } - } - - /* - * Attach the generic SD/MMC bus driver. (The bus driver must - * not invoke any chipset functions before it is attached.) - */ - bzero(&saa, sizeof(saa)); - saa.saa_busname = "sdmmc"; - saa.sct = &imxesdhc_functions; - saa.sch = sc; - saa.dmat = sc->sc_dmat; - if (ISSET(sc->flags, SHF_USE_DMA)) - saa.caps |= SMC_CAPS_DMA; - - if (caps & SDHC_HOST_CTRL_CAP_HSS) - saa.caps |= SMC_CAPS_MMC_HIGHSPEED; - - width = OF_getpropint(sc->sc_node, "bus-width", 1); - if (width >= 8) - saa.caps |= SMC_CAPS_8BIT_MODE; - if (width >= 4) - saa.caps |= SMC_CAPS_4BIT_MODE; - - sc->sdmmc = config_found(&sc->sc_dev, &saa, NULL); - if (sc->sdmmc == NULL) { - error = 0; - return; - } -} - -void -imxesdhc_clock_enable(uint32_t phandle) -{ - uint32_t gpios[3]; - int node; - - node = OF_getnodebyphandle(phandle); - if (node == 0) - return; - - if (!OF_is_compatible(node, "gpio-gate-clock")) - return; - - pinctrl_byname(node, "default"); - - OF_getpropintarray(node, "enable-gpios", gpios, sizeof(gpios)); - gpio_controller_config_pin(&gpios[0], GPIO_CONFIG_OUTPUT); - gpio_controller_set_pin(&gpios[0], 1); -} - -void -imxesdhc_pwrseq_pre(uint32_t phandle) -{ - uint32_t *gpios, *gpio; - uint32_t clocks; - int node; - int len; - - node = OF_getnodebyphandle(phandle); - if (node == 0) - return; - - if (!OF_is_compatible(node, "mmc-pwrseq-simple")) - return; - - pinctrl_byname(node, "default"); - - clocks = OF_getpropint(node, "clocks", 0); - if (clocks) - imxesdhc_clock_enable(clocks); - - len = OF_getproplen(node, "reset-gpios"); - if (len <= 0) - return; - - gpios = malloc(len, M_TEMP, M_WAITOK); - OF_getpropintarray(node, "reset-gpios", gpios, len); - - gpio = gpios; - while (gpio && gpio < gpios + (len / sizeof(uint32_t))) { - gpio_controller_config_pin(gpio, GPIO_CONFIG_OUTPUT); - gpio_controller_set_pin(gpio, 1); - gpio = gpio_controller_next_pin(gpio); - } - - free(gpios, M_TEMP, len); -} - -void -imxesdhc_pwrseq_post(uint32_t phandle) -{ - uint32_t *gpios, *gpio; - int node; - int len; - - node = OF_getnodebyphandle(phandle); - if (node == 0) - return; - - if (!OF_is_compatible(node, "mmc-pwrseq-simple")) - return; - - len = OF_getproplen(node, "reset-gpios"); - if (len <= 0) - return; - - gpios = malloc(len, M_TEMP, M_WAITOK); - OF_getpropintarray(node, "reset-gpios", gpios, len); - - gpio = gpios; - while (gpio && gpio < gpios + (len / sizeof(uint32_t))) { - gpio_controller_set_pin(gpio, 0); - gpio = gpio_controller_next_pin(gpio); - } - - free(gpios, M_TEMP, len); -} - -/* - * Reset the host controller. Called during initialization, when - * cards are removed, upon resume, and during error recovery. - */ -int -imxesdhc_host_reset(sdmmc_chipset_handle_t sch) -{ - struct imxesdhc_softc *sc = sch; - u_int32_t imask; - int error; - int s; - - s = splsdmmc(); - - /* Disable all interrupts. */ - HWRITE4(sc, SDHC_INT_STATUS_EN, 0); - HWRITE4(sc, SDHC_INT_SIGNAL_EN, 0); - - /* - * Reset the entire host controller and wait up to 100ms for - * the controller to clear the reset bit. - */ - if ((error = imxesdhc_soft_reset(sc, SDHC_SYS_CTRL_RSTA)) != 0) { - splx(s); - return (error); - } - - /* Set data timeout counter value to max for now. */ - HSET4(sc, SDHC_SYS_CTRL, 0xe << SDHC_SYS_CTRL_DTOCV_SHIFT); - - /* Enable interrupts. */ - imask = SDHC_INT_STATUS_CC | SDHC_INT_STATUS_TC | - SDHC_INT_STATUS_BGE | SDHC_INT_STATUS_DINT | - SDHC_INT_STATUS_BRR | SDHC_INT_STATUS_BWR; - - imask |= SDHC_INT_STATUS_CTOE | SDHC_INT_STATUS_CCE | - SDHC_INT_STATUS_CEBE | SDHC_INT_STATUS_CIC | - SDHC_INT_STATUS_DTOE | SDHC_INT_STATUS_DCE | - SDHC_INT_STATUS_DEBE | SDHC_INT_STATUS_DMAE; - - HWRITE4(sc, SDHC_INT_STATUS_EN, imask); - HWRITE4(sc, SDHC_INT_SIGNAL_EN, imask); - - /* Switch back to no-DMA/SDMA. */ - HCLR4(sc, SDHC_PROT_CTRL, SDHC_PROT_CTRL_DMASEL_MASK); - - /* Switch back to 1-bit bus. */ - HCLR4(sc, SDHC_PROT_CTRL, SDHC_PROT_CTRL_DTW_MASK); - - /* Set watermarks and burst lengths to something sane. */ - HWRITE4(sc, SDHC_WTMK_LVL, - (64 << SDHC_WTMK_LVL_RD_WML_SHIFT) | - (16 << SDHC_WTMK_LVL_RD_BRST_LEN_SHIFT) | - (64 << SDHC_WTMK_LVL_WR_WML_SHIFT) | - (16 << SDHC_WTMK_LVL_WR_BRST_LEN_SHIFT)); - - splx(s); - return 0; -} - -uint32_t -imxesdhc_host_ocr(sdmmc_chipset_handle_t sch) -{ - struct imxesdhc_softc *sc = sch; - - return sc->ocr; -} - -int -imxesdhc_host_maxblklen(sdmmc_chipset_handle_t sch) -{ - struct imxesdhc_softc *sc = sch; - - return sc->maxblklen; -} - -/* - * Return non-zero if the card is currently inserted. - */ -int -imxesdhc_card_detect(sdmmc_chipset_handle_t sch) -{ - struct imxesdhc_softc *sc = sch; - - if (OF_getproplen(sc->sc_node, "non-removable") == 0) - return 1; - - return gpio_controller_get_pin(sc->sc_gpio); -} - -/* - * Set or change SD bus voltage and enable or disable SD bus power. - * Return zero on success. - */ -int -imxesdhc_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr) -{ - struct imxesdhc_softc *sc = sch; - uint32_t vdd = 0; - - ocr &= sc->ocr; - if (ISSET(ocr, MMC_OCR_3_2V_3_3V|MMC_OCR_3_3V_3_4V)) - vdd = 3300000; - else if (ISSET(ocr, MMC_OCR_2_9V_3_0V|MMC_OCR_3_0V_3_1V)) - vdd = 3000000; - else if (ISSET(ocr, MMC_OCR_1_65V_1_95V)) - vdd = 1800000; - - if (sc->sc_vdd == 0 && vdd > 0) - imxesdhc_pwrseq_pre(sc->sc_pwrseq); - - /* enable mmc power */ - if (sc->sc_vmmc && vdd > 0) - regulator_enable(sc->sc_vmmc); - - if (sc->sc_vdd == 0 && vdd > 0) - imxesdhc_pwrseq_post(sc->sc_pwrseq); - - sc->sc_vdd = vdd; - return 0; -} - -/* - * Set or change SDCLK frequency or disable the SD clock. - * Return zero on success. - */ -int -imxesdhc_bus_clock(sdmmc_chipset_handle_t sch, int freq, int timing) -{ - struct imxesdhc_softc *sc = sch; - int div, pre_div, cur_freq, s; - int error = 0; - - s = splsdmmc(); - - if (sc->clkbase / 16 > freq) { - for (pre_div = 2; pre_div < 256; pre_div *= 2) - if ((sc->clkbase / pre_div) <= (freq * 16)) - break; - } else - pre_div = 2; - - if (sc->clkbase == freq) - pre_div = 1; - - for (div = 1; div <= 16; div++) - if ((sc->clkbase / (div * pre_div)) <= freq) - break; - - div -= 1; - pre_div >>= 1; - - cur_freq = sc->clkbase / (pre_div * 2) / (div + 1); - - /* disable force CLK ouput active */ - HCLR4(sc, SDHC_VEND_SPEC, SDHC_VEND_SPEC_FRC_SDCLK_ON); - - /* wait while clock is unstable */ - if ((error = imxesdhc_wait_state(sc, - SDHC_PRES_STATE_SDSTB, SDHC_PRES_STATE_SDSTB)) != 0) - goto ret; - - HCLR4(sc, SDHC_SYS_CTRL, SDHC_SYS_CTRL_CLOCK_MASK); - HSET4(sc, SDHC_SYS_CTRL, - (div << SDHC_SYS_CTRL_CLOCK_DIV_SHIFT) | - (pre_div << SDHC_SYS_CTRL_CLOCK_PRE_SHIFT)); - - /* wait while clock is unstable */ - if ((error = imxesdhc_wait_state(sc, - SDHC_PRES_STATE_SDSTB, SDHC_PRES_STATE_SDSTB)) != 0) - goto ret; - -ret: - splx(s); - return error; -} - -int -imxesdhc_bus_width(sdmmc_chipset_handle_t sch, int width) -{ - struct imxesdhc_softc *sc = sch; - uint32_t reg; - int s; - - if (width != 1 && width != 4 && width != 8) - return (1); - - s = splsdmmc(); - - reg = HREAD4(sc, SDHC_PROT_CTRL) & ~SDHC_PROT_CTRL_DTW_MASK; - if (width == 4) - reg |= SDHC_PROT_CTRL_DTW_4BIT; - else if (width == 8) - reg |= SDHC_PROT_CTRL_DTW_8BIT; - HWRITE4(sc, SDHC_PROT_CTRL, reg); - - splx(s); - - return (0); -} - -void -imxesdhc_card_intr_mask(sdmmc_chipset_handle_t sch, int enable) -{ - struct imxesdhc_softc *sc = sch; - - if (enable) { - HSET4(sc, SDHC_INT_STATUS_EN, SDHC_INT_STATUS_CINT); - HSET4(sc, SDHC_INT_SIGNAL_EN, SDHC_INT_STATUS_CINT); - } else { - HCLR4(sc, SDHC_INT_STATUS_EN, SDHC_INT_STATUS_CINT); - HCLR4(sc, SDHC_INT_SIGNAL_EN, SDHC_INT_STATUS_CINT); - } -} - -void -imxesdhc_card_intr_ack(sdmmc_chipset_handle_t sch) -{ - struct imxesdhc_softc *sc = sch; - - HSET4(sc, SDHC_INT_STATUS_EN, SDHC_INT_STATUS_CINT); -} - -int -imxesdhc_wait_state(struct imxesdhc_softc *sc, uint32_t mask, uint32_t value) -{ - uint32_t state; - int timeout; - - state = HREAD4(sc, SDHC_PRES_STATE); - DPRINTF(3,("%s: wait_state %x %x %x)\n", - HDEVNAME(sc), mask, value, state)); - for (timeout = 1000; timeout > 0; timeout--) { - if (((state = HREAD4(sc, SDHC_PRES_STATE)) & mask) == value) - return 0; - delay(10); - } - DPRINTF(0,("%s: timeout waiting for %x, state %x\n", - HDEVNAME(sc), value, state)); - - return ETIMEDOUT; -} - -void -imxesdhc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd) -{ - struct imxesdhc_softc *sc = sch; - int error; - - /* - * Start the command, or mark `cmd' as failed and return. - */ - error = imxesdhc_start_command(sc, cmd); - if (error != 0) { - cmd->c_error = error; - SET(cmd->c_flags, SCF_ITSDONE); - return; - } - - /* - * Wait until the command phase is done, or until the command - * is marked done for any other reason. - */ - if (!imxesdhc_wait_intr(sc, SDHC_INT_STATUS_CC, SDHC_COMMAND_TIMEOUT)) { - cmd->c_error = ETIMEDOUT; - SET(cmd->c_flags, SCF_ITSDONE); - return; - } - - /* - * The host controller removes bits [0:7] from the response - * data (CRC) and we pass the data up unchanged to the bus - * driver (without padding). - */ - if (cmd->c_error == 0 && ISSET(cmd->c_flags, SCF_RSP_PRESENT)) { - if (ISSET(cmd->c_flags, SCF_RSP_136)) { - cmd->c_resp[0] = HREAD4(sc, SDHC_CMD_RSP0); - cmd->c_resp[1] = HREAD4(sc, SDHC_CMD_RSP1); - cmd->c_resp[2] = HREAD4(sc, SDHC_CMD_RSP2); - cmd->c_resp[3] = HREAD4(sc, SDHC_CMD_RSP3); -#ifdef SDHC_DEBUG - printf("resp[0] 0x%08x\nresp[1] 0x%08x\n" - "resp[2] 0x%08x\nresp[3] 0x%08x\n", - cmd->c_resp[0], - cmd->c_resp[1], - cmd->c_resp[2], - cmd->c_resp[3]); -#endif - } else { - cmd->c_resp[0] = HREAD4(sc, SDHC_CMD_RSP0); -#ifdef SDHC_DEBUG - printf("resp[0] 0x%08x\n", cmd->c_resp[0]); -#endif - } - } - - /* - * If the command has data to transfer in any direction, - * execute the transfer now. - */ - if (cmd->c_error == 0 && cmd->c_data) - imxesdhc_transfer_data(sc, cmd); - - DPRINTF(1,("%s: cmd %u done (flags=%#x error=%d)\n", - HDEVNAME(sc), cmd->c_opcode, cmd->c_flags, cmd->c_error)); - SET(cmd->c_flags, SCF_ITSDONE); -} - -int -imxesdhc_start_command(struct imxesdhc_softc *sc, struct sdmmc_command *cmd) -{ - struct sdhc_adma2_descriptor32 *desc = (void *)sc->adma2; - u_int32_t blksize = 0; - u_int32_t blkcount = 0; - u_int32_t command; - int error; - int seg; - int s; - - DPRINTF(1,("%s: start cmd %u arg=%#x data=%p dlen=%d flags=%#x " - "proc=\"%s\"\n", HDEVNAME(sc), cmd->c_opcode, cmd->c_arg, - cmd->c_data, cmd->c_datalen, cmd->c_flags, curproc ? - curproc->p_p->ps_comm : "")); - - /* - * The maximum block length for commands should be the minimum - * of the host buffer size and the card buffer size. (1.7.2) - */ - - /* Fragment the data into proper blocks. */ - if (cmd->c_datalen > 0) { - blksize = MIN(cmd->c_datalen, cmd->c_blklen); - blkcount = cmd->c_datalen / blksize; - if (cmd->c_datalen % blksize > 0) { - /* XXX: Split this command. (1.7.4) */ - printf("%s: data not a multiple of %d bytes\n", - HDEVNAME(sc), blksize); - return EINVAL; - } - } - - /* Check limit imposed by 9-bit block count. (1.7.2) */ - if (blkcount > SDHC_BLK_ATT_BLKCNT_MAX) { - printf("%s: too much data\n", HDEVNAME(sc)); - return EINVAL; - } - - /* Check for write protection. */ - if (!ISSET(cmd->c_flags, SCF_CMD_READ)) { - if (!(HREAD4(sc, SDHC_PRES_STATE) & SDHC_PRES_STATE_WPSPL)) { - printf("%s: card is write protected\n", - HDEVNAME(sc)); - return EINVAL; - } - } - - /* Prepare transfer mode register value. (2.2.5) */ - command = 0; - - if (ISSET(cmd->c_flags, SCF_CMD_READ)) - command |= SDHC_MIX_CTRL_DTDSEL; - if (blkcount > 0) { - command |= SDHC_MIX_CTRL_BCEN; - if (blkcount > 1) { - command |= SDHC_MIX_CTRL_MSBSEL; - command |= SDHC_MIX_CTRL_AC12EN; - } - } - if (cmd->c_dmamap && cmd->c_datalen > 0 && - ISSET(sc->flags, SHF_USE_DMA)) - command |= SDHC_MIX_CTRL_DMAEN; - - command |= (cmd->c_opcode << SDHC_CMD_XFR_TYP_CMDINDX_SHIFT) & - SDHC_CMD_XFR_TYP_CMDINDX_SHIFT_MASK; - - if (ISSET(cmd->c_flags, SCF_RSP_CRC)) - command |= SDHC_CMD_XFR_TYP_CCCEN; - if (ISSET(cmd->c_flags, SCF_RSP_IDX)) - command |= SDHC_CMD_XFR_TYP_CICEN; - if (cmd->c_data != NULL) - command |= SDHC_CMD_XFR_TYP_DPSEL; - - if (!ISSET(cmd->c_flags, SCF_RSP_PRESENT)) - command |= SDHC_CMD_XFR_TYP_RSP_NONE; - else if (ISSET(cmd->c_flags, SCF_RSP_136)) - command |= SDHC_CMD_XFR_TYP_RSP136; - else if (ISSET(cmd->c_flags, SCF_RSP_BSY)) - command |= SDHC_CMD_XFR_TYP_RSP48B; - else - command |= SDHC_CMD_XFR_TYP_RSP48; - - /* Wait until command and data inhibit bits are clear. (1.5) */ - if ((error = imxesdhc_wait_state(sc, SDHC_PRES_STATE_CIHB, 0)) != 0) - return error; - - s = splsdmmc(); - - /* Set DMA start address if SHF_USE_DMA is set. */ - if (cmd->c_dmamap && ISSET(sc->flags, SHF_USE_DMA)) { - for (seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) { - bus_addr_t paddr = - cmd->c_dmamap->dm_segs[seg].ds_addr; - uint16_t len = - cmd->c_dmamap->dm_segs[seg].ds_len == 65536 ? - 0 : cmd->c_dmamap->dm_segs[seg].ds_len; - uint16_t attr; - - attr = SDHC_ADMA2_VALID | SDHC_ADMA2_ACT_TRANS; - if (seg == cmd->c_dmamap->dm_nsegs - 1) - attr |= SDHC_ADMA2_END; - - desc[seg].attribute = htole16(attr); - desc[seg].length = htole16(len); - desc[seg].address = htole32(paddr); - } - - desc[cmd->c_dmamap->dm_nsegs].attribute = htole16(0); - - bus_dmamap_sync(sc->sc_dmat, sc->adma_map, 0, PAGE_SIZE, - BUS_DMASYNC_PREWRITE); - - HCLR4(sc, SDHC_PROT_CTRL, SDHC_PROT_CTRL_DMASEL_MASK); - HSET4(sc, SDHC_PROT_CTRL, SDHC_PROT_CTRL_DMASEL_ADMA2); - - HWRITE4(sc, SDHC_ADMA_SYS_ADDR, - sc->adma_map->dm_segs[0].ds_addr); - } - - /* - * Start a CPU data transfer. Writing to the high order byte - * of the SDHC_COMMAND register triggers the SD command. (1.5) - */ - HWRITE4(sc, SDHC_BLK_ATT, blkcount << SDHC_BLK_ATT_BLKCNT_SHIFT | - blksize << SDHC_BLK_ATT_BLKSIZE_SHIFT); - HWRITE4(sc, SDHC_CMD_ARG, cmd->c_arg); - HWRITE4(sc, SDHC_MIX_CTRL, - (HREAD4(sc, SDHC_MIX_CTRL) & (0xf << 22)) | (command & 0xffff)); - HWRITE4(sc, SDHC_CMD_XFR_TYP, command); - - splx(s); - return 0; -} - -void -imxesdhc_transfer_data(struct imxesdhc_softc *sc, struct sdmmc_command *cmd) -{ - u_char *datap = cmd->c_data; - int i, datalen; - int mask; - int error; - - if (cmd->c_dmamap) { - int status; - - error = 0; - for (;;) { - status = imxesdhc_wait_intr(sc, - SDHC_INT_STATUS_DINT|SDHC_INT_STATUS_TC, - SDHC_DMA_TIMEOUT); - if (status & SDHC_INT_STATUS_TC) - break; - if (!status) { - error = ETIMEDOUT; - break; - } - } - - bus_dmamap_sync(sc->sc_dmat, sc->adma_map, 0, PAGE_SIZE, - BUS_DMASYNC_POSTWRITE); - goto done; - } - - mask = ISSET(cmd->c_flags, SCF_CMD_READ) ? - SDHC_PRES_STATE_BREN : SDHC_PRES_STATE_BWEN; - error = 0; - datalen = cmd->c_datalen; - - DPRINTF(1,("%s: resp=%#x datalen=%d\n", - HDEVNAME(sc), MMC_R1(cmd->c_resp), datalen)); - - while (datalen > 0) { - if (!imxesdhc_wait_intr(sc, - SDHC_INT_STATUS_BRR | SDHC_INT_STATUS_BWR, - SDHC_BUFFER_TIMEOUT)) { - error = ETIMEDOUT; - break; - } - - if ((error = imxesdhc_wait_state(sc, mask, mask)) != 0) - break; - - /* FIXME: wait a bit, else it fails */ - delay(100); - i = MIN(datalen, cmd->c_blklen); - if (ISSET(cmd->c_flags, SCF_CMD_READ)) - imxesdhc_read_data(sc, datap, i); - else - imxesdhc_write_data(sc, datap, i); - - datap += i; - datalen -= i; - } - - if (error == 0 && !imxesdhc_wait_intr(sc, SDHC_INT_STATUS_TC, - SDHC_TRANSFER_TIMEOUT)) - error = ETIMEDOUT; - -done: - if (error != 0) - cmd->c_error = error; - SET(cmd->c_flags, SCF_ITSDONE); - - DPRINTF(1,("%s: data transfer done (error=%d)\n", - HDEVNAME(sc), cmd->c_error)); -} - -void -imxesdhc_read_data(struct imxesdhc_softc *sc, u_char *datap, int datalen) -{ - while (datalen > 3) { - *(uint32_t *)datap = HREAD4(sc, SDHC_DATA_BUFF_ACC_PORT); - datap += 4; - datalen -= 4; - } - if (datalen > 0) { - uint32_t rv = HREAD4(sc, SDHC_DATA_BUFF_ACC_PORT); - do { - *datap++ = rv & 0xff; - rv = rv >> 8; - } while (--datalen > 0); - } -} - -void -imxesdhc_write_data(struct imxesdhc_softc *sc, u_char *datap, int datalen) -{ - while (datalen > 3) { - DPRINTF(3,("%08x\n", *(uint32_t *)datap)); - HWRITE4(sc, SDHC_DATA_BUFF_ACC_PORT, *((uint32_t *)datap)); - datap += 4; - datalen -= 4; - } - if (datalen > 0) { - uint32_t rv = *datap++; - if (datalen > 1) - rv |= *datap++ << 8; - if (datalen > 2) - rv |= *datap++ << 16; - DPRINTF(3,("rv %08x\n", rv)); - HWRITE4(sc, SDHC_DATA_BUFF_ACC_PORT, rv); - } -} - -/* Prepare for another command. */ -int -imxesdhc_soft_reset(struct imxesdhc_softc *sc, int mask) -{ - int timo; - - DPRINTF(1,("%s: software reset reg=%#x\n", HDEVNAME(sc), mask)); - - /* disable force CLK ouput active */ - HCLR4(sc, SDHC_VEND_SPEC, SDHC_VEND_SPEC_FRC_SDCLK_ON); - - /* reset */ - HSET4(sc, SDHC_SYS_CTRL, mask); - delay(10); - - for (timo = 1000; timo > 0; timo--) { - if (!ISSET(HREAD4(sc, SDHC_SYS_CTRL), mask)) - break; - delay(10); - } - if (timo == 0) { - DPRINTF(1,("%s: timeout reg=%#x\n", HDEVNAME(sc), - HREAD4(sc, SDHC_SYS_CTRL))); - return ETIMEDOUT; - } - - return 0; -} - -int -imxesdhc_wait_intr(struct imxesdhc_softc *sc, int mask, int timo) -{ - int status; - int s; - - mask |= SDHC_INT_STATUS_ERR; - s = splsdmmc(); - - /* enable interrupts for brr and bwr */ - if (mask & (SDHC_INT_STATUS_BRR | SDHC_INT_STATUS_BWR)) - HSET4(sc, SDHC_INT_SIGNAL_EN, - (SDHC_INT_STATUS_BRR | SDHC_INT_STATUS_BWR)); - - status = sc->intr_status & mask; - while (status == 0) { - if (tsleep(&sc->intr_status, PWAIT, "hcintr", timo) - == EWOULDBLOCK) { - status |= SDHC_INT_STATUS_ERR; - break; - } - status = sc->intr_status & mask; - } - sc->intr_status &= ~status; - DPRINTF(2,("%s: intr status %#x error %#x\n", HDEVNAME(sc), status, - sc->intr_error_status)); - - /* Command timeout has higher priority than command complete. */ - if (ISSET(status, SDHC_INT_STATUS_ERR)) { - sc->intr_error_status = 0; - (void)imxesdhc_soft_reset(sc, - SDHC_SYS_CTRL_RSTC | SDHC_SYS_CTRL_RSTD); - status = 0; - } - - splx(s); - return status; -} - -/* - * Established by attachment driver at interrupt priority IPL_SDMMC. - */ -int -imxesdhc_intr(void *arg) -{ - struct imxesdhc_softc *sc = arg; - - u_int32_t status; - - /* Find out which interrupts are pending. */ - status = HREAD4(sc, SDHC_INT_STATUS); - - /* disable interrupts for brr and bwr, else we get flooded */ - if (status & (SDHC_INT_STATUS_BRR | SDHC_INT_STATUS_BWR)) - HCLR4(sc, SDHC_INT_SIGNAL_EN, - (SDHC_INT_STATUS_BRR | SDHC_INT_STATUS_BWR)); - - /* Acknowledge the interrupts we are about to handle. */ - HWRITE4(sc, SDHC_INT_STATUS, status); - DPRINTF(2,("%s: interrupt status=0x%08x\n", HDEVNAME(sc), status)); - - /* - * Service error interrupts. - */ - if (ISSET(status, SDHC_INT_STATUS_CMD_ERR | - SDHC_INT_STATUS_CTOE | SDHC_INT_STATUS_DTOE)) { - sc->intr_status |= status; - sc->intr_error_status |= status & 0xffff0000; - wakeup(&sc->intr_status); - } - - /* - * Wake up the blocking process to service command - * related interrupt(s). - */ - if (ISSET(status, SDHC_INT_STATUS_BRR | SDHC_INT_STATUS_BWR | - SDHC_INT_STATUS_TC | SDHC_INT_STATUS_CC)) { - sc->intr_status |= status; - wakeup(&sc->intr_status); - } - - /* - * Service SD card interrupts. - */ - if (ISSET(status, SDHC_INT_STATUS_CINT)) { - DPRINTF(0,("%s: card interrupt\n", HDEVNAME(sc))); - HCLR4(sc, SDHC_INT_STATUS_EN, SDHC_INT_STATUS_CINT); - sdmmc_card_intr(sc->sdmmc); - } - - return 1; -} |