1*8a8166e5SBartlomiej Grzesik /* 2*8a8166e5SBartlomiej Grzesik * Copyright 2019 Emmanuel Vadot <manu@freebsd.org> 3*8a8166e5SBartlomiej Grzesik * Copyright (c) 2017 Ian Lepore <ian@freebsd.org> All rights reserved. 4*8a8166e5SBartlomiej Grzesik * 5*8a8166e5SBartlomiej Grzesik * Redistribution and use in source and binary forms, with or without 6*8a8166e5SBartlomiej Grzesik * modification, are permitted provided that the following conditions are 7*8a8166e5SBartlomiej Grzesik * met: 8*8a8166e5SBartlomiej Grzesik * 9*8a8166e5SBartlomiej Grzesik * 1. Redistributions of source code must retain the above copyright 10*8a8166e5SBartlomiej Grzesik * notice, this list of conditions and the following disclaimer. 11*8a8166e5SBartlomiej Grzesik * 2. Redistributions in binary form must reproduce the above copyright 12*8a8166e5SBartlomiej Grzesik * notice, this list of conditions and the following disclaimer in the 13*8a8166e5SBartlomiej Grzesik * documentation and/or other materials provided with the distribution. 14*8a8166e5SBartlomiej Grzesik * 15*8a8166e5SBartlomiej Grzesik * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16*8a8166e5SBartlomiej Grzesik * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17*8a8166e5SBartlomiej Grzesik * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18*8a8166e5SBartlomiej Grzesik * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 19*8a8166e5SBartlomiej Grzesik * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20*8a8166e5SBartlomiej Grzesik * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21*8a8166e5SBartlomiej Grzesik * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 22*8a8166e5SBartlomiej Grzesik * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23*8a8166e5SBartlomiej Grzesik * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24*8a8166e5SBartlomiej Grzesik * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25*8a8166e5SBartlomiej Grzesik * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26*8a8166e5SBartlomiej Grzesik */ 27*8a8166e5SBartlomiej Grzesik 28*8a8166e5SBartlomiej Grzesik #include <sys/cdefs.h> 29*8a8166e5SBartlomiej Grzesik __FBSDID("$FreeBSD$"); 30*8a8166e5SBartlomiej Grzesik 31*8a8166e5SBartlomiej Grzesik #include <sys/param.h> 32*8a8166e5SBartlomiej Grzesik #include <sys/bus.h> 33*8a8166e5SBartlomiej Grzesik #include <sys/kernel.h> 34*8a8166e5SBartlomiej Grzesik #include <sys/gpio.h> 35*8a8166e5SBartlomiej Grzesik #include <sys/taskqueue.h> 36*8a8166e5SBartlomiej Grzesik 37*8a8166e5SBartlomiej Grzesik #include <dev/mmc/bridge.h> 38*8a8166e5SBartlomiej Grzesik #include <dev/mmc/mmc_helpers.h> 39*8a8166e5SBartlomiej Grzesik 40*8a8166e5SBartlomiej Grzesik static inline void 41*8a8166e5SBartlomiej Grzesik mmc_parse_sd_speed(device_t dev, struct mmc_host *host) 42*8a8166e5SBartlomiej Grzesik { 43*8a8166e5SBartlomiej Grzesik bool no_18v = false; 44*8a8166e5SBartlomiej Grzesik 45*8a8166e5SBartlomiej Grzesik /* 46*8a8166e5SBartlomiej Grzesik * Parse SD supported modes 47*8a8166e5SBartlomiej Grzesik * All UHS-I modes requires 1.8V signaling. 48*8a8166e5SBartlomiej Grzesik */ 49*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "no-1-8-v")) 50*8a8166e5SBartlomiej Grzesik no_18v = true; 51*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "cap-sd-highspeed")) 52*8a8166e5SBartlomiej Grzesik host->caps |= MMC_CAP_HSPEED; 53*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "sd-uhs-sdr12") && !no_18v) 54*8a8166e5SBartlomiej Grzesik host->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_SIGNALING_180; 55*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "sd-uhs-sdr25") && !no_18v) 56*8a8166e5SBartlomiej Grzesik host->caps |= MMC_CAP_UHS_SDR25 | MMC_CAP_SIGNALING_180; 57*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "sd-uhs-sdr50") && !no_18v) 58*8a8166e5SBartlomiej Grzesik host->caps |= MMC_CAP_UHS_SDR50 | MMC_CAP_SIGNALING_180; 59*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "sd-uhs-sdr104") && !no_18v) 60*8a8166e5SBartlomiej Grzesik host->caps |= MMC_CAP_UHS_SDR104 | MMC_CAP_SIGNALING_180; 61*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "sd-uhs-ddr50") && !no_18v) 62*8a8166e5SBartlomiej Grzesik host->caps |= MMC_CAP_UHS_DDR50 | MMC_CAP_SIGNALING_180; 63*8a8166e5SBartlomiej Grzesik } 64*8a8166e5SBartlomiej Grzesik 65*8a8166e5SBartlomiej Grzesik static inline void 66*8a8166e5SBartlomiej Grzesik mmc_parse_mmc_speed(device_t dev, struct mmc_host *host) 67*8a8166e5SBartlomiej Grzesik { 68*8a8166e5SBartlomiej Grzesik /* Parse eMMC supported modes */ 69*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "cap-mmc-highspeed")) 70*8a8166e5SBartlomiej Grzesik host->caps |= MMC_CAP_HSPEED; 71*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "mmc-ddr-1_2v")) 72*8a8166e5SBartlomiej Grzesik host->caps |= MMC_CAP_MMC_DDR52_120 | MMC_CAP_SIGNALING_120; 73*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "mmc-ddr-1_8v")) 74*8a8166e5SBartlomiej Grzesik host->caps |= MMC_CAP_MMC_DDR52_180 | MMC_CAP_SIGNALING_180; 75*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "mmc-ddr-3_3v")) 76*8a8166e5SBartlomiej Grzesik host->caps |= MMC_CAP_SIGNALING_330; 77*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "mmc-hs200-1_2v")) 78*8a8166e5SBartlomiej Grzesik host->caps |= MMC_CAP_MMC_HS200_120 | MMC_CAP_SIGNALING_120; 79*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "mmc-hs200-1_8v")) 80*8a8166e5SBartlomiej Grzesik host->caps |= MMC_CAP_MMC_HS200_180 | MMC_CAP_SIGNALING_180; 81*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "mmc-hs400-1_2v")) 82*8a8166e5SBartlomiej Grzesik host->caps |= MMC_CAP_MMC_HS400_120 | MMC_CAP_SIGNALING_120; 83*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "mmc-hs400-1_8v")) 84*8a8166e5SBartlomiej Grzesik host->caps |= MMC_CAP_MMC_HS400_180 | MMC_CAP_SIGNALING_180; 85*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "mmc-hs400-enhanced-strobe")) 86*8a8166e5SBartlomiej Grzesik host->caps |= MMC_CAP_MMC_ENH_STROBE; 87*8a8166e5SBartlomiej Grzesik } 88*8a8166e5SBartlomiej Grzesik 89*8a8166e5SBartlomiej Grzesik int 90*8a8166e5SBartlomiej Grzesik mmc_parse(device_t dev, struct mmc_helper *helper, struct mmc_host *host) 91*8a8166e5SBartlomiej Grzesik { 92*8a8166e5SBartlomiej Grzesik uint64_t bus_width, max_freq; 93*8a8166e5SBartlomiej Grzesik 94*8a8166e5SBartlomiej Grzesik bus_width = 0; 95*8a8166e5SBartlomiej Grzesik if (device_get_property(dev, "bus-width", &bus_width, sizeof(uint64_t)) <= 0) 96*8a8166e5SBartlomiej Grzesik bus_width = 1; 97*8a8166e5SBartlomiej Grzesik 98*8a8166e5SBartlomiej Grzesik if (bus_width >= 4) 99*8a8166e5SBartlomiej Grzesik host->caps |= MMC_CAP_4_BIT_DATA; 100*8a8166e5SBartlomiej Grzesik if (bus_width >= 8) 101*8a8166e5SBartlomiej Grzesik host->caps |= MMC_CAP_8_BIT_DATA; 102*8a8166e5SBartlomiej Grzesik 103*8a8166e5SBartlomiej Grzesik /* 104*8a8166e5SBartlomiej Grzesik * max-frequency is optional, drivers should tweak this value 105*8a8166e5SBartlomiej Grzesik * if it's not present based on the clock that the mmc controller 106*8a8166e5SBartlomiej Grzesik * operates on 107*8a8166e5SBartlomiej Grzesik */ 108*8a8166e5SBartlomiej Grzesik max_freq = 0; 109*8a8166e5SBartlomiej Grzesik device_get_property(dev, "max-frequency", &max_freq, sizeof(uint64_t)); 110*8a8166e5SBartlomiej Grzesik host->f_max = max_freq; 111*8a8166e5SBartlomiej Grzesik 112*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "broken-cd")) 113*8a8166e5SBartlomiej Grzesik helper->props |= MMC_PROP_BROKEN_CD; 114*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "non-removable")) 115*8a8166e5SBartlomiej Grzesik helper->props |= MMC_PROP_NON_REMOVABLE; 116*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "wp-inverted")) 117*8a8166e5SBartlomiej Grzesik helper->props |= MMC_PROP_WP_INVERTED; 118*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "cd-inverted")) 119*8a8166e5SBartlomiej Grzesik helper->props |= MMC_PROP_CD_INVERTED; 120*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "no-sdio")) 121*8a8166e5SBartlomiej Grzesik helper->props |= MMC_PROP_NO_SDIO; 122*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "no-sd")) 123*8a8166e5SBartlomiej Grzesik helper->props |= MMC_PROP_NO_SD; 124*8a8166e5SBartlomiej Grzesik if (device_has_property(dev, "no-mmc")) 125*8a8166e5SBartlomiej Grzesik helper->props |= MMC_PROP_NO_MMC; 126*8a8166e5SBartlomiej Grzesik 127*8a8166e5SBartlomiej Grzesik if (!(helper->props & MMC_PROP_NO_SD)) 128*8a8166e5SBartlomiej Grzesik mmc_parse_sd_speed(dev, host); 129*8a8166e5SBartlomiej Grzesik 130*8a8166e5SBartlomiej Grzesik if (!(helper->props & MMC_PROP_NO_MMC)) 131*8a8166e5SBartlomiej Grzesik mmc_parse_mmc_speed(dev, host); 132*8a8166e5SBartlomiej Grzesik 133*8a8166e5SBartlomiej Grzesik return (0); 134*8a8166e5SBartlomiej Grzesik } 135