Module Name: src Committed By: jmcneill Date: Sat Dec 26 23:13:50 UTC 2015
Modified Files: src/sys/arch/arm/samsung: files.exynos Added Files: src/sys/arch/arm/samsung: exynos_dwcmmc.c Log Message: Add dwcmmc glue To generate a diff of this commit: cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/samsung/exynos_dwcmmc.c cvs rdiff -u -r1.18 -r1.19 src/sys/arch/arm/samsung/files.exynos Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/samsung/files.exynos diff -u src/sys/arch/arm/samsung/files.exynos:1.18 src/sys/arch/arm/samsung/files.exynos:1.19 --- src/sys/arch/arm/samsung/files.exynos:1.18 Thu Dec 24 01:10:51 2015 +++ src/sys/arch/arm/samsung/files.exynos Sat Dec 26 23:13:50 2015 @@ -1,4 +1,4 @@ -# $NetBSD: files.exynos,v 1.18 2015/12/24 01:10:51 marty Exp $ +# $NetBSD: files.exynos,v 1.19 2015/12/26 23:13:50 jmcneill Exp $ # # Configuration info for Samsung Exynos SoC ARM Peripherals # @@ -94,6 +94,10 @@ attach ohci at exyousb with ohci_exyousb attach ehci at exyousb with ehci_exyousb file arch/arm/samsung/exynos_usb.c exyo_usb +# SD/MMC Host Controller +attach dwcmmc at fdt with exynos_dwcmmc +file arch/arm/samsung/exynos_dwcmmc.c exynos_dwcmmc + # I2C support, bitbanging through GPIO device exyoi2c: i2cbus, i2c_bitbang attach exyoi2c at fdt with exynos_i2c Added files: Index: src/sys/arch/arm/samsung/exynos_dwcmmc.c diff -u /dev/null src/sys/arch/arm/samsung/exynos_dwcmmc.c:1.1 --- /dev/null Sat Dec 26 23:13:50 2015 +++ src/sys/arch/arm/samsung/exynos_dwcmmc.c Sat Dec 26 23:13:50 2015 @@ -0,0 +1,198 @@ +/* $NetBSD: exynos_dwcmmc.c,v 1.1 2015/12/26 23:13:50 jmcneill Exp $ */ + +/*- + * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: exynos_dwcmmc.c,v 1.1 2015/12/26 23:13:50 jmcneill Exp $"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/device.h> +#include <sys/intr.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/mutex.h> +#include <sys/condvar.h> + +#include <arm/samsung/exynos_var.h> + +#include <dev/ic/dwc_mmc_var.h> +#include <dev/fdt/fdtvar.h> + +static int exynos_dwcmmc_match(device_t, cfdata_t, void *); +static void exynos_dwcmmc_attach(device_t, device_t, void *); + +static void exynos_dwcmmc_attach_i(device_t); + +static int exynos_dwcmmc_card_detect(struct dwc_mmc_softc *); + +struct exynos_dwcmmc_softc { + struct dwc_mmc_softc sc; + struct clk *sc_clk_biu; + struct clk *sc_clk_ciu; + struct fdtbus_gpio_pin *sc_pin_cd; +}; + +CFATTACH_DECL_NEW(exynos_dwcmmc, sizeof(struct dwc_mmc_softc), + exynos_dwcmmc_match, exynos_dwcmmc_attach, NULL, NULL); + +static const char * const exynos_dwcmmc_compat[] = { + "samsung,exynos5420-dw-mshc-smu", + "samsung,exynos5420-dw-mshc", + NULL +}; + +static int +exynos_dwcmmc_match(device_t parent, cfdata_t cf, void *aux) +{ + struct fdt_attach_args * const faa = aux; + + return of_match_compatible(faa->faa_phandle, exynos_dwcmmc_compat); +} + +static void +exynos_dwcmmc_attach(device_t parent, device_t self, void *aux) +{ + struct exynos_dwcmmc_softc *esc = device_private(self); + struct dwc_mmc_softc *sc = &esc->sc; + struct fdt_attach_args * const faa = aux; + const int phandle = faa->faa_phandle; + struct clk *clk_cpll; + char intrstr[128]; + bus_addr_t addr; + bus_size_t size; + u_int bus_width, ciu_div; + int error; + + if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { + aprint_error(": couldn't get registers\n"); + return; + } + + if (of_getprop_uint32(phandle, "bus-width", &bus_width)) { + bus_width = 4; + } + if (of_getprop_uint32(phandle, "samsung,dw-mshc-ciu-div", &ciu_div)) { + aprint_error(": missing samsung,dw-mshc-ciu-div property\n"); + return; + } + + clk_cpll = clk_get("sclk_cpll"); + if (clk_cpll == NULL) { + aprint_error(": clock \"sclk_cpll\" not found\n"); + return; + } + esc->sc_clk_biu = fdtbus_clock_get(phandle, "biu"); + if (esc->sc_clk_biu == NULL) { + aprint_error(": couldn't get clock biu\n"); + return; + } + error = clk_set_parent(esc->sc_clk_biu, clk_cpll); + if (error) { + aprint_error(": couldn't set clock biu parent: %d\n", error); + return; + } + + esc->sc_clk_ciu = fdtbus_clock_get(phandle, "ciu"); + if (esc->sc_clk_ciu == NULL) { + aprint_error(": couldn't get clock ciu\n"); + return; + } + error = clk_set_rate(esc->sc_clk_ciu, 666000000); + if (error) { + aprint_error(": couldn't set clock ciu rate: %d\n", error); + return; + } + error = clk_enable(esc->sc_clk_ciu); + if (error) { + aprint_error(": couldn't enable clock ciu: %d\n", error); + return; + } + + sc->sc_dev = self; + sc->sc_bst = faa->faa_bst; + sc->sc_dmat = faa->faa_dmat; + error = bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh); + if (error) { + aprint_error(": couldn't map %#llx: %d\n", + (uint64_t)addr, error); + return; + } + + sc->sc_flags |= DWC_MMC_F_USE_HOLD_REG; +#if 0 + sc->sc_flags = DWC_MMC_F_USE_HOLD_REG | DWC_MMC_F_PWREN_CLEAR | + DWC_MMC_F_FORCE_CLK; +#endif + + sc->sc_clock_freq = clk_get_rate(esc->sc_clk_ciu) / (ciu_div + 1); + sc->sc_fifo_depth = 64; + + esc->sc_pin_cd = fdtbus_gpio_acquire(phandle, "cd-gpios", + GPIO_PIN_INPUT); + if (esc->sc_pin_cd) { + sc->sc_card_detect = exynos_dwcmmc_card_detect; + } + + aprint_naive("\n"); + aprint_normal(": MHS (%u Hz)\n", sc->sc_clock_freq); + + if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) { + aprint_error_dev(self, "failed to decode interrupt\n"); + return; + } + + sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_BIO, 0, + dwc_mmc_intr, sc); + if (sc->sc_ih == NULL) { + aprint_error_dev(self, "couldn't establish interrupt on %s\n", + intrstr); + return; + } + aprint_normal_dev(self, "interrupting on %s\n", intrstr); + + config_interrupts(self, exynos_dwcmmc_attach_i); +} + +static void +exynos_dwcmmc_attach_i(device_t self) +{ + struct exynos_dwcmmc_softc *esc = device_private(self); + struct dwc_mmc_softc *sc = &esc->sc; + + dwc_mmc_init(sc); +} + +static int +exynos_dwcmmc_card_detect(struct dwc_mmc_softc *sc) +{ + struct exynos_dwcmmc_softc *esc = device_private(sc->sc_dev); + + KASSERT(esc->sc_pin_cd != NULL); + + return fdtbus_gpio_read(esc->sc_pin_cd); +}