X-Git-Url: https://git.kernelconcepts.de/?a=blobdiff_plain;f=drivers%2Fmmc%2Ftegra_mmc.c;h=d555692f7fc0626c659e5e4712bc9666a7c726b5;hb=b6abcbe91215ee2dd4421399b8579fcaddd3a948;hp=e86bc680ff2806ef3b4d9f1169cf81c72f5956b1;hpb=2d348a1652f1d1211ab82cb0c7a57a3362830d71;p=karo-tx-uboot.git diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c index e86bc680ff..d555692f7f 100644 --- a/drivers/mmc/tegra_mmc.c +++ b/drivers/mmc/tegra_mmc.c @@ -4,19 +4,7 @@ * Jaehoon Chung * Portions Copyright 2011-2013 NVIDIA Corporation * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -25,13 +13,13 @@ #include #include #include +#include #include #include DECLARE_GLOBAL_DATA_PTR; -struct mmc mmc_dev[MAX_HOSTS]; -struct mmc_host mmc_host[MAX_HOSTS]; +struct mmc_host mmc_host[CONFIG_SYS_MMC_MAX_DEVICE]; #ifndef CONFIG_OF_CONTROL #error "Please enable device tree support to use this driver" @@ -157,7 +145,7 @@ static int mmc_wait_inhibit(struct mmc_host *host, static int mmc_send_cmd_bounced(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data, struct bounce_buffer *bbstate) { - struct mmc_host *host = (struct mmc_host *)mmc->priv; + struct mmc_host *host = mmc->priv; int flags, i; int result; unsigned int mask = 0; @@ -305,7 +293,7 @@ static int mmc_send_cmd_bounced(struct mmc *mmc, struct mmc_cmd *cmd, /* Transfer Complete */ debug("r/w is done\n"); break; - } else if (get_timer(start) > 2000UL) { + } else if (get_timer(start) > 8000UL) { writel(mask, &host->reg->norintsts); printf("%s: MMC Timeout\n" " Interrupt status 0x%08x\n" @@ -326,7 +314,7 @@ static int mmc_send_cmd_bounced(struct mmc *mmc, struct mmc_cmd *cmd, return 0; } -static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, +static int tegra_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { void *buf; @@ -408,7 +396,7 @@ out: host->clock = clock; } -static void mmc_set_ios(struct mmc *mmc) +static void tegra_mmc_set_ios(struct mmc *mmc) { struct mmc_host *host = mmc->priv; unsigned char ctrl; @@ -468,7 +456,7 @@ static void mmc_reset(struct mmc_host *host, struct mmc *mmc) } /* Set SD bus voltage & enable bus power */ - mmc_set_power(host, fls(mmc->voltages) - 1); + mmc_set_power(host, fls(mmc->cfg->voltages) - 1); debug("%s: power control = %02X, host control = %02X\n", __func__, readb(&host->reg->pwrcon), readb(&host->reg->hostctl)); @@ -476,9 +464,9 @@ static void mmc_reset(struct mmc_host *host, struct mmc *mmc) pad_init_mmc(host); } -static int mmc_core_init(struct mmc *mmc) +static int tegra_mmc_core_init(struct mmc *mmc) { - struct mmc_host *host = (struct mmc_host *)mmc->priv; + struct mmc_host *host = mmc->priv; unsigned int mask; debug(" mmc_core_init called\n"); @@ -521,22 +509,28 @@ static int mmc_core_init(struct mmc *mmc) return 0; } -int tegra_mmc_getcd(struct mmc *mmc) +static int tegra_mmc_getcd(struct mmc *mmc) { - struct mmc_host *host = (struct mmc_host *)mmc->priv; + struct mmc_host *host = mmc->priv; debug("tegra_mmc_getcd called\n"); - if (fdt_gpio_isvalid(&host->cd_gpio)) - return fdtdec_get_gpio(&host->cd_gpio); + if (dm_gpio_is_valid(&host->cd_gpio)) + return dm_gpio_get_value(&host->cd_gpio); return 1; } -static int do_mmc_init(int dev_index) +static const struct mmc_ops tegra_mmc_ops = { + .send_cmd = tegra_mmc_send_cmd, + .set_ios = tegra_mmc_set_ios, + .init = tegra_mmc_core_init, + .getcd = tegra_mmc_getcd, +}; + +static int do_mmc_init(int dev_index, bool removable) { struct mmc_host *host; - char gpusage[12]; /* "SD/MMCn PWR" or "SD/MMCn CD" */ struct mmc *mmc; /* DT should have been read & host config filled in */ @@ -544,45 +538,28 @@ static int do_mmc_init(int dev_index) if (!host->enabled) return -1; - debug(" do_mmc_init: index %d, bus width %d " - "pwr_gpio %d cd_gpio %d\n", - dev_index, host->width, - host->pwr_gpio.gpio, host->cd_gpio.gpio); + debug(" do_mmc_init: index %d, bus width %d pwr_gpio %d cd_gpio %d\n", + dev_index, host->width, gpio_get_number(&host->pwr_gpio), + gpio_get_number(&host->cd_gpio)); host->clock = 0; clock_start_periph_pll(host->mmc_id, CLOCK_ID_PERIPH, 20000000); - if (fdt_gpio_isvalid(&host->pwr_gpio)) { - sprintf(gpusage, "SD/MMC%d PWR", dev_index); - gpio_request(host->pwr_gpio.gpio, gpusage); - gpio_direction_output(host->pwr_gpio.gpio, 1); - debug(" Power GPIO name = %s\n", host->pwr_gpio.name); - } - - if (fdt_gpio_isvalid(&host->cd_gpio)) { - sprintf(gpusage, "SD/MMC%d CD", dev_index); - gpio_request(host->cd_gpio.gpio, gpusage); - gpio_direction_input(host->cd_gpio.gpio); - debug(" CD GPIO name = %s\n", host->cd_gpio.name); - } + if (dm_gpio_is_valid(&host->pwr_gpio)) + dm_gpio_set_value(&host->pwr_gpio, 1); - mmc = &mmc_dev[dev_index]; + memset(&host->cfg, 0, sizeof(host->cfg)); - sprintf(mmc->name, "Tegra SD/MMC"); - mmc->priv = host; - mmc->send_cmd = mmc_send_cmd; - mmc->set_ios = mmc_set_ios; - mmc->init = mmc_core_init; - mmc->getcd = tegra_mmc_getcd; - mmc->getwp = NULL; + host->cfg.name = "Tegra SD/MMC"; + host->cfg.ops = &tegra_mmc_ops; - mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; - mmc->host_caps = 0; + host->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; + host->cfg.host_caps = 0; if (host->width == 8) - mmc->host_caps |= MMC_MODE_8BIT; + host->cfg.host_caps |= MMC_MODE_8BIT; if (host->width >= 4) - mmc->host_caps |= MMC_MODE_4BIT; - mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC; + host->cfg.host_caps |= MMC_MODE_4BIT; + host->cfg.host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; /* * min freq is for card identification, and is the highest @@ -590,10 +567,15 @@ static int do_mmc_init(int dev_index) * max freq is highest HS eMMC clock as per the SD/MMC spec * (actually 52MHz) */ - mmc->f_min = 375000; - mmc->f_max = 48000000; + host->cfg.f_min = 375000; + host->cfg.f_max = 48000000; - mmc_register(mmc); + host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; + + mmc = mmc_create(&host->cfg, host); + mmc->block_dev.removable = removable; + if (mmc == NULL) + return -1; return 0; } @@ -605,7 +587,8 @@ static int do_mmc_init(int dev_index) * @param node Device index (0-3) * @param host Structure to fill in (reg, width, mmc_id) */ -static int mmc_get_config(const void *blob, int node, struct mmc_host *host) +static int mmc_get_config(const void *blob, int node, struct mmc_host *host, + bool *removablep) { debug("%s: node = %d\n", __func__, node); @@ -632,9 +615,13 @@ static int mmc_get_config(const void *blob, int node, struct mmc_host *host) debug("%s: no sdmmc width found\n", __func__); /* These GPIOs are optional */ - fdtdec_decode_gpio(blob, node, "cd-gpios", &host->cd_gpio); - fdtdec_decode_gpio(blob, node, "wp-gpios", &host->wp_gpio); - fdtdec_decode_gpio(blob, node, "power-gpios", &host->pwr_gpio); + gpio_request_by_name_nodev(blob, node, "cd-gpios", 0, &host->cd_gpio, + GPIOD_IS_IN); + gpio_request_by_name_nodev(blob, node, "wp-gpios", 0, &host->wp_gpio, + GPIOD_IS_IN); + gpio_request_by_name_nodev(blob, node, "power-gpios", 0, + &host->pwr_gpio, GPIOD_IS_OUT); + *removablep = !fdtdec_get_bool(blob, node, "non-removable"); debug("%s: found controller at %p, width = %d, periph_id = %d\n", __func__, host->reg, host->width, host->mmc_id); @@ -652,6 +639,7 @@ static int mmc_get_config(const void *blob, int node, struct mmc_host *host) static int process_nodes(const void *blob, int node_list[], int count) { struct mmc_host *host; + bool removable; int i, node; debug("%s: count = %d\n", __func__, count); @@ -665,24 +653,35 @@ static int process_nodes(const void *blob, int node_list[], int count) host = &mmc_host[i]; host->id = i; - if (mmc_get_config(blob, node, host)) { + if (mmc_get_config(blob, node, host, &removable)) { printf("%s: failed to decode dev %d\n", __func__, i); return -1; } - do_mmc_init(i); + do_mmc_init(i, removable); } return 0; } void tegra_mmc_init(void) { - int node_list[MAX_HOSTS], count; + int node_list[CONFIG_SYS_MMC_MAX_DEVICE], count; const void *blob = gd->fdt_blob; debug("%s entry\n", __func__); + /* See if any Tegra124 MMC controllers are present */ + count = fdtdec_find_aliases_for_id(blob, "sdhci", + COMPAT_NVIDIA_TEGRA124_SDMMC, node_list, + CONFIG_SYS_MMC_MAX_DEVICE); + debug("%s: count of Tegra124 sdhci nodes is %d\n", __func__, count); + if (process_nodes(blob, node_list, count)) { + printf("%s: Error processing T30 mmc node(s)!\n", __func__); + return; + } + /* See if any Tegra30 MMC controllers are present */ count = fdtdec_find_aliases_for_id(blob, "sdhci", - COMPAT_NVIDIA_TEGRA30_SDMMC, node_list, MAX_HOSTS); + COMPAT_NVIDIA_TEGRA30_SDMMC, node_list, + CONFIG_SYS_MMC_MAX_DEVICE); debug("%s: count of T30 sdhci nodes is %d\n", __func__, count); if (process_nodes(blob, node_list, count)) { printf("%s: Error processing T30 mmc node(s)!\n", __func__); @@ -691,7 +690,8 @@ void tegra_mmc_init(void) /* Now look for any Tegra20 MMC controllers */ count = fdtdec_find_aliases_for_id(blob, "sdhci", - COMPAT_NVIDIA_TEGRA20_SDMMC, node_list, MAX_HOSTS); + COMPAT_NVIDIA_TEGRA20_SDMMC, node_list, + CONFIG_SYS_MMC_MAX_DEVICE); debug("%s: count of T20 sdhci nodes is %d\n", __func__, count); if (process_nodes(blob, node_list, count)) { printf("%s: Error processing T20 mmc node(s)!\n", __func__);