Blame view
drivers/mmc/nds32_mmc.c
3.45 KB
d41ce506b Initial Release, ... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
/* * Andestech ATFSDC010 SD/MMC driver * * (C) Copyright 2017 * Rick Chen, NDS32 Software Engineering, rick@andestech.com * SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> #include <clk.h> #include <dm.h> #include <dt-structs.h> #include <errno.h> #include <mapmem.h> #include <mmc.h> #include <pwrseq.h> #include <syscon.h> #include <linux/err.h> #include <faraday/ftsdc010.h> #include "ftsdc010_mci.h" DECLARE_GLOBAL_DATA_PTR; #if CONFIG_IS_ENABLED(OF_PLATDATA) struct nds_mmc { fdt32_t bus_width; bool cap_mmc_highspeed; bool cap_sd_highspeed; fdt32_t clock_freq_min_max[2]; struct phandle_2_cell clocks[4]; fdt32_t fifo_depth; fdt32_t reg[2]; }; #endif struct nds_mmc_plat { #if CONFIG_IS_ENABLED(OF_PLATDATA) struct nds_mmc dtplat; #endif struct mmc_config cfg; struct mmc mmc; }; struct ftsdc_priv { struct clk clk; struct ftsdc010_chip chip; int fifo_depth; bool fifo_mode; u32 minmax[2]; }; static int nds32_mmc_ofdata_to_platdata(struct udevice *dev) { #if !CONFIG_IS_ENABLED(OF_PLATDATA) struct ftsdc_priv *priv = dev_get_priv(dev); struct ftsdc010_chip *chip = &priv->chip; chip->name = dev->name; chip->ioaddr = (void *)devfdt_get_addr(dev); chip->buswidth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "bus-width", 4); chip->priv = dev; priv->fifo_depth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "fifo-depth", 0); priv->fifo_mode = fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev), "fifo-mode"); if (fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), "clock-freq-min-max", priv->minmax, 2)) { int val = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "max-frequency", -EINVAL); if (val < 0) return val; priv->minmax[0] = 400000; /* 400 kHz */ priv->minmax[1] = val; } else { debug("%s: 'clock-freq-min-max' property was deprecated. ", __func__); } #endif chip->sclk = priv->minmax[1]; chip->regs = chip->ioaddr; return 0; } static int nds32_mmc_probe(struct udevice *dev) { struct nds_mmc_plat *plat = dev_get_platdata(dev); struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct ftsdc_priv *priv = dev_get_priv(dev); struct ftsdc010_chip *chip = &priv->chip; struct udevice *pwr_dev __maybe_unused; #if CONFIG_IS_ENABLED(OF_PLATDATA) int ret; struct nds_mmc *dtplat = &plat->dtplat; chip->name = dev->name; chip->ioaddr = map_sysmem(dtplat->reg[0], dtplat->reg[1]); chip->buswidth = dtplat->bus_width; chip->priv = dev; chip->dev_index = 1; memcpy(priv->minmax, dtplat->clock_freq_min_max, sizeof(priv->minmax)); ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->clk); if (ret < 0) return ret; #endif ftsdc_setup_cfg(&plat->cfg, dev->name, chip->buswidth, chip->caps, priv->minmax[1] , priv->minmax[0]); chip->mmc = &plat->mmc; chip->mmc->priv = &priv->chip; chip->mmc->dev = dev; upriv->mmc = chip->mmc; return ftsdc010_probe(dev); } static int nds32_mmc_bind(struct udevice *dev) { struct nds_mmc_plat *plat = dev_get_platdata(dev); return ftsdc010_bind(dev, &plat->mmc, &plat->cfg); } static const struct udevice_id nds32_mmc_ids[] = { { .compatible = "andestech,atsdc010" }, { } }; U_BOOT_DRIVER(nds32_mmc_drv) = { .name = "nds32_mmc", .id = UCLASS_MMC, .of_match = nds32_mmc_ids, .ofdata_to_platdata = nds32_mmc_ofdata_to_platdata, .ops = &dm_ftsdc010_ops, .bind = nds32_mmc_bind, .probe = nds32_mmc_probe, .priv_auto_alloc_size = sizeof(struct ftsdc_priv), .platdata_auto_alloc_size = sizeof(struct nds_mmc_plat), }; |