X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fmmc%2Fdavinci_mmc.c;h=0d63279db00afbb31f23149b1ff3285f9211c1cc;hb=7035ec3cb35c593a492cb929ba8fe9d991d0416d;hp=5aa218426f4948eb12f686b0b6099ce58ba9d376;hpb=e6c7f86f03b0ad25e9ef70df3ee1989b6b789d7c;p=oweals%2Fu-boot.git diff --git a/drivers/mmc/davinci_mmc.c b/drivers/mmc/davinci_mmc.c index 5aa218426f..0d63279db0 100644 --- a/drivers/mmc/davinci_mmc.c +++ b/drivers/mmc/davinci_mmc.c @@ -1,31 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Davinci MMC Controller Driver * * Copyright (C) 2010 Texas Instruments Incorporated - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include -#include +#include +#include #include +#include #include #include #include #include +#include #define DAVINCI_MAX_BLOCKS (32) #define WATCHDOG_COUNT (100000) @@ -35,17 +25,47 @@ #define set_bit(addr, val) set_val((addr), (get_val(addr) | (val))) #define clear_bit(addr, val) set_val((addr), (get_val(addr) & ~(val))) +#ifdef CONFIG_DM_MMC +struct davinci_of_data { + const char *name; + u8 version; +}; + +/* Davinci MMC board definitions */ +struct davinci_mmc_priv { + struct davinci_mmc_regs *reg_base; /* Register base address */ + uint input_clk; /* Input clock to MMC controller */ + uint version; /* MMC Controller version */ + struct gpio_desc cd_gpio; /* Card Detect GPIO */ + struct gpio_desc wp_gpio; /* Write Protect GPIO */ +}; + +struct davinci_mmc_plat +{ + struct mmc_config cfg; + struct mmc mmc; +}; +#endif + /* Set davinci clock prescalar value based on the required clock in HZ */ +#if !CONFIG_IS_ENABLED(DM_MMC) static void dmmc_set_clock(struct mmc *mmc, uint clock) { struct davinci_mmc *host = mmc->priv; +#else + +static void davinci_mmc_set_clock(struct udevice *dev, uint clock) +{ + struct davinci_mmc_priv *host = dev_get_priv(dev); + struct mmc *mmc = mmc_get_mmc_dev(dev); +#endif struct davinci_mmc_regs *regs = host->reg_base; uint clkrt, sysclk2, act_clock; - if (clock < mmc->f_min) - clock = mmc->f_min; - if (clock > mmc->f_max) - clock = mmc->f_max; + if (clock < mmc->cfg->f_min) + clock = mmc->cfg->f_min; + if (clock > mmc->cfg->f_max) + clock = mmc->cfg->f_max; set_val(®s->mmcclk, 0); sysclk2 = host->input_clk; @@ -78,7 +98,7 @@ dmmc_wait_fifo_status(volatile struct davinci_mmc_regs *regs, uint status) udelay(100); if (wdog == 0) - return COMM_ERR; + return -ECOMM; return 0; } @@ -92,7 +112,7 @@ static int dmmc_busy_wait(volatile struct davinci_mmc_regs *regs) udelay(10); if (wdog == 0) - return COMM_ERR; + return -ECOMM; return 0; } @@ -111,7 +131,7 @@ static int dmmc_check_status(volatile struct davinci_mmc_regs *regs, return 0; } else if (mmcstatus & st_error) { if (mmcstatus & MMCST0_TOUTRS) - return TIMEOUT; + return -ETIMEDOUT; printf("[ ST0 ERROR %x]\n", mmcstatus); /* * Ignore CRC errors as some MMC cards fail to @@ -119,7 +139,7 @@ static int dmmc_check_status(volatile struct davinci_mmc_regs *regs, */ if (mmcstatus & MMCST0_CRCRS) return 0; - return COMM_ERR; + return -ECOMM; } udelay(10); @@ -128,17 +148,23 @@ static int dmmc_check_status(volatile struct davinci_mmc_regs *regs, printf("Status %x Timeout ST0:%x ST1:%x\n", st_ready, mmcstatus, get_val(®s->mmcst1)); - return COMM_ERR; + return -ECOMM; } /* - * Sends a command out on the bus. Takes the mmc pointer, + * Sends a command out on the bus. Takes the device pointer, * a command pointer, and an optional data pointer. */ -static int -dmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) +#if !CONFIG_IS_ENABLED(DM_MMC) +static int dmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { struct davinci_mmc *host = mmc->priv; +#else +static int +davinci_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, struct mmc_data *data) +{ + struct davinci_mmc_priv *host = dev_get_priv(dev); +#endif volatile struct davinci_mmc_regs *regs = host->reg_base; uint mmcstatus, status_rdy, status_err; uint i, cmddata, bytes_left = 0; @@ -324,9 +350,15 @@ dmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) } /* Initialize Davinci MMC controller */ +#if !CONFIG_IS_ENABLED(DM_MMC) static int dmmc_init(struct mmc *mmc) { struct davinci_mmc *host = mmc->priv; +#else +static int davinci_dm_mmc_init(struct udevice *dev) +{ + struct davinci_mmc_priv *host = dev_get_priv(dev); +#endif struct davinci_mmc_regs *regs = host->reg_base; /* Clear status registers explicitly - soft reset doesn't clear it @@ -358,12 +390,20 @@ static int dmmc_init(struct mmc *mmc) return 0; } -/* Set buswidth or clock as indicated by the GENERIC_MMC framework */ -static void dmmc_set_ios(struct mmc *mmc) +/* Set buswidth or clock as indicated by the MMC framework */ +#if !CONFIG_IS_ENABLED(DM_MMC) +static int dmmc_set_ios(struct mmc *mmc) { struct davinci_mmc *host = mmc->priv; struct davinci_mmc_regs *regs = host->reg_base; +#else +static int davinci_mmc_set_ios(struct udevice *dev) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); + struct davinci_mmc_priv *host = dev_get_priv(dev); + struct davinci_mmc_regs *regs = host->reg_base; +#endif /* Set the bus width */ if (mmc->bus_width == 4) set_bit(®s->mmcctl, MMCCTL_WIDTH_4_BIT); @@ -371,36 +411,158 @@ static void dmmc_set_ios(struct mmc *mmc) clear_bit(®s->mmcctl, MMCCTL_WIDTH_4_BIT); /* Set clock speed */ - if (mmc->clock) + if (mmc->clock) { +#if !CONFIG_IS_ENABLED(DM_MMC) dmmc_set_clock(mmc, mmc->clock); +#else + davinci_mmc_set_clock(dev, mmc->clock); +#endif + } + return 0; +} + +#if !CONFIG_IS_ENABLED(DM_MMC) +static const struct mmc_ops dmmc_ops = { + .send_cmd = dmmc_send_cmd, + .set_ios = dmmc_set_ios, + .init = dmmc_init, +}; +#else + +static int davinci_mmc_getcd(struct udevice *dev) +{ + int value = -1; +#if CONFIG_IS_ENABLED(DM_GPIO) + struct davinci_mmc_priv *priv = dev_get_priv(dev); + value = dm_gpio_get_value(&priv->cd_gpio); +#endif + /* if no CD return as 1 */ + if (value < 0) + return 1; + + return value; +} + +static int davinci_mmc_getwp(struct udevice *dev) +{ + int value = -1; +#if CONFIG_IS_ENABLED(DM_GPIO) + struct davinci_mmc_priv *priv = dev_get_priv(dev); + + value = dm_gpio_get_value(&priv->wp_gpio); +#endif + /* if no WP return as 0 */ + if (value < 0) + return 0; + + return value; } +static const struct dm_mmc_ops davinci_mmc_ops = { + .send_cmd = davinci_mmc_send_cmd, + .set_ios = davinci_mmc_set_ios, + .get_cd = davinci_mmc_getcd, + .get_wp = davinci_mmc_getwp, +}; +#endif + +#if !CONFIG_IS_ENABLED(DM_MMC) /* Called from board_mmc_init during startup. Can be called multiple times - * depending on the number of slots available on board and controller - */ +* depending on the number of slots available on board and controller +*/ int davinci_mmc_init(bd_t *bis, struct davinci_mmc *host) { - struct mmc *mmc; + host->cfg.name = "davinci"; + host->cfg.ops = &dmmc_ops; + host->cfg.f_min = 200000; + host->cfg.f_max = 25000000; + host->cfg.voltages = host->voltages; + host->cfg.host_caps = host->host_caps; - mmc = malloc(sizeof(struct mmc)); - memset(mmc, 0, sizeof(struct mmc)); + host->cfg.b_max = DAVINCI_MAX_BLOCKS; - sprintf(mmc->name, "davinci"); - mmc->priv = host; - mmc->send_cmd = dmmc_send_cmd; - mmc->set_ios = dmmc_set_ios; - mmc->init = dmmc_init; - mmc->getcd = NULL; - mmc->getwp = NULL; + mmc_create(&host->cfg, host); - mmc->f_min = 200000; - mmc->f_max = 25000000; - mmc->voltages = host->voltages; - mmc->host_caps = host->host_caps; + return 0; +} +#else - mmc->b_max = DAVINCI_MAX_BLOCKS; - mmc_register(mmc); +static int davinci_mmc_probe(struct udevice *dev) +{ + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct davinci_mmc_plat *plat = dev_get_platdata(dev); + struct davinci_mmc_priv *priv = dev_get_priv(dev); + struct mmc_config *cfg = &plat->cfg; + struct davinci_of_data *data = + (struct davinci_of_data *)dev_get_driver_data(dev); + cfg->f_min = 200000; + cfg->f_max = 25000000; + cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34, + cfg->host_caps = MMC_MODE_4BIT, /* DA850 supports only 4-bit SD/MMC */ + cfg->b_max = DAVINCI_MAX_BLOCKS; - return 0; + if (data) { + cfg->name = data->name; + priv->version = data->version; + } + + priv->reg_base = (struct davinci_mmc_regs *)dev_read_addr(dev); + priv->input_clk = clk_get(DAVINCI_MMCSD_CLKID); + +#if CONFIG_IS_ENABLED(DM_GPIO) + /* These GPIOs are optional */ + gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, GPIOD_IS_IN); + gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio, GPIOD_IS_IN); +#endif + + upriv->mmc = &plat->mmc; + + return davinci_dm_mmc_init(dev); } + +static int davinci_mmc_bind(struct udevice *dev) +{ + struct davinci_mmc_plat *plat = dev_get_platdata(dev); + + return mmc_bind(dev, &plat->mmc, &plat->cfg); +} + + +const struct davinci_of_data davinci_mmc_host_info[] = { + { + .name = "dm6441-mmc", + .version = MMC_CTLR_VERSION_1, + }, + { + .name = "da830-mmc", + .version = MMC_CTLR_VERSION_2, + }, + {}, +}; + +static const struct udevice_id davinci_mmc_ids[] = { + { + .compatible = "ti,dm6441-mmc", + .data = (ulong) &davinci_mmc_host_info[MMC_CTLR_VERSION_1] + }, + { + .compatible = "ti,da830-mmc", + .data = (ulong) &davinci_mmc_host_info[MMC_CTLR_VERSION_2] + }, + {}, +}; + +U_BOOT_DRIVER(davinci_mmc_drv) = { + .name = "davinci_mmc", + .id = UCLASS_MMC, + .of_match = davinci_mmc_ids, +#if CONFIG_BLK + .bind = davinci_mmc_bind, +#endif + .probe = davinci_mmc_probe, + .ops = &davinci_mmc_ops, + .platdata_auto_alloc_size = sizeof(struct davinci_mmc_plat), + .priv_auto_alloc_size = sizeof(struct davinci_mmc_priv), +}; +#endif