123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- /*
- * Copyright (c) 2006-2024 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-08-16 zhujiale first version
- */
- #include <rtthread.h>
- #include "sdhci.h"
- #include <rtdbg.h>
- #include <mmu.h>
- #include <drivers/core/dm.h>
- static void rt_plat_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
- {
- struct rt_mmc_host *mmc = (struct rt_mmc_host *)host;
- rt_uint32_t flags = req->cmd->flags;
- switch (flags & RESP_MASK)
- {
- case RESP_NONE:
- flags |= MMC_RSP_NONE;
- break;
- case RESP_R1:
- flags |= MMC_RSP_R1;
- break;
- case RESP_R1B:
- flags |= MMC_RSP_R1B;
- break;
- case RESP_R2:
- flags |= MMC_RSP_R2;
- break;
- case RESP_R3:
- flags |= MMC_RSP_R3;
- break;
- case RESP_R4:
- flags |= MMC_RSP_R4;
- break;
- case RESP_R5:
- flags |= MMC_RSP_R5;
- break;
- case RESP_R6:
- flags |= MMC_RSP_R6;
- break;
- case RESP_R7:
- flags |= MMC_RSP_R7;
- break;
- }
- if (req->data)
- {
- if ((rt_uint64_t)rt_kmem_v2p(req->data->buf) > 0xffffffff)
- {
- void *dma_buffer = rt_malloc(req->data->blks * req->data->blksize);
- void *req_buf = NULL;
- if (req->data->flags & DATA_DIR_WRITE)
- {
- rt_memcpy(dma_buffer, req->data->buf, req->data->blks * req->data->blksize);
- req_buf = req->data->buf;
- req->data->buf = dma_buffer;
- }
- else if (req->data->flags & DATA_DIR_READ)
- {
- req_buf = req->data->buf;
- req->data->buf = dma_buffer;
- }
- req->cmd->flags |= flags;
- mmc->ops->request(mmc, req);
- rt_sem_take(&host->sem_ack, RT_WAITING_FOREVER);
- if (req->data->flags & DATA_DIR_READ)
- {
- rt_memcpy(req_buf, dma_buffer, req->data->blksize * req->data->blks);
- req->data->buf = req_buf;
- }else{
- req->data->buf = req_buf;
- }
- rt_free(dma_buffer);
- rt_sem_release(&host->sem_ack);
- }
- else
- {
- req->cmd->flags |= flags;
- mmc->ops->request(mmc, req);
- }
- }
- else
- {
- req->cmd->flags |= flags;
- mmc->ops->request(mmc, req);
- }
- }
- static void rt_plat_set_ioconfig(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *iocfg)
- {
- struct rt_mmc_host *mmc = (struct rt_mmc_host *)host;
- LOG_D("clock:%d,width:%d,power:%d,vdd:%d,timing:%d\n",
- iocfg->clock, iocfg->bus_width,
- iocfg->power_mode, iocfg->vdd, iocfg->timing);
- mmc->ops->set_ios(mmc, iocfg);
- }
- static rt_int32_t rt_plat_get_card_status(struct rt_mmcsd_host *host)
- {
- struct rt_mmc_host *mmc = (struct rt_mmc_host *)host;
- return mmc->ops->get_cd(mmc);
- }
- static rt_int32_t rt_plat_execute_tuning(struct rt_mmcsd_host *host, rt_int32_t opcode)
- {
- struct rt_mmc_host *mmc = (struct rt_mmc_host *)host;
- return mmc->ops->execute_tuning(mmc, opcode);
- }
- static void rt_plat_enable_sdio_irq(struct rt_mmcsd_host *host, rt_int32_t en)
- {
- struct rt_mmc_host *mmc = (struct rt_mmc_host *)host;
- return mmc->ops->enable_sdio_irq(mmc, en);
- }
- static const struct rt_mmcsd_host_ops rt_mmcsd_ops = {
- .request = rt_plat_request,
- .set_iocfg = rt_plat_set_ioconfig,
- .get_card_status = rt_plat_get_card_status,
- .enable_sdio_irq = rt_plat_enable_sdio_irq,
- .execute_tuning = rt_plat_execute_tuning,
- };
- void rt_mmc_request_done(struct rt_mmc_host *host, struct rt_mmcsd_req *mrq)
- {
- mmcsd_req_complete(&host->rthost);
- }
- /*add host in rtt while sdhci complete*/
- int rt_mmc_add_host(struct rt_mmc_host *mmc)
- {
- mmc->rthost.ops = &rt_mmcsd_ops;
- mmc->rthost.flags = mmc->caps;
- mmc->rthost.freq_max = mmc->f_max;
- mmc->rthost.freq_min = 400000;
- mmc->rthost.max_dma_segs = mmc->max_segs;
- mmc->rthost.max_seg_size = mmc->max_seg_size;
- mmc->rthost.max_blk_size = mmc->max_blk_size;
- mmc->rthost.max_blk_count = mmc->max_blk_count;
- mmc->rthost.valid_ocr = VDD_165_195|VDD_20_21|VDD_21_22|VDD_22_23|VDD_24_25|VDD_25_26|VDD_26_27|VDD_27_28|VDD_28_29|VDD_29_30|VDD_30_31|VDD_32_33|VDD_33_34|VDD_34_35|VDD_35_36;
- mmcsd_change(&mmc->rthost);
- return 0;
- }
- struct rt_mmc_host *rt_mmc_alloc_host(int extra, struct rt_device *dev)
- {
- struct rt_mmc_host *mmc;
- mmc = rt_malloc(sizeof(*mmc) + extra);
- if (mmc)
- {
- rt_memset(mmc, 0, sizeof(*mmc) + extra);
- mmc->parent = dev;
- mmcsd_host_init(&mmc->rthost);
- }
- return mmc;
- }
- void rt_mmc_remove_host(struct rt_mmc_host *host)
- {
- rt_free(host);
- }
- int rt_mmc_abort_tuning(struct rt_mmc_host *host, rt_uint32_t opcode)
- {
- return 0;
- }
- int rt_mmc_gpio_get_cd(struct rt_mmc_host *host)
- {
- return -ENOSYS;
- }
- void rt_mmc_detect_change(struct rt_mmc_host *host, unsigned long delay)
- {
- }
- int rt_mmc_regulator_set_vqmmc(struct rt_mmc_host *mmc, struct rt_mmcsd_io_cfg *ios)
- {
- return 0;
- }
- rt_bool_t rt_mmc_can_gpio_ro(struct rt_mmc_host *host)
- {
- return RT_FALSE;
- }
- int rt_mmc_gpio_get_ro(struct rt_mmc_host *host)
- {
- return 0;
- }
- int rt_mmc_send_abort_tuning(struct rt_mmc_host *host, rt_uint32_t opcode)
- {
- return 0;
- }
- int rt_mmc_of_parse(struct rt_mmc_host *host)
- {
- struct rt_device *dev = host->parent;
- rt_uint32_t bus_width;
- if (!dev || !dev->ofw_node)
- return 0;
- /* "bus-width" is translated to MMC_CAP_*_BIT_DATA flags */
- if (rt_dm_dev_prop_read_u32(dev, "bus-width", &bus_width) < 0)
- {
- bus_width = 1;
- }
- switch (bus_width)
- {
- case 8:
- host->caps |= MMC_CAP_8_BIT_DATA;
- break; /* Hosts capable of 8-bit can also do 4 bits */
- case 4:
- host->caps |= MMC_CAP_4_BIT_DATA;
- break;
- case 1:
- break;
- default:
- return -EINVAL;
- }
- /* f_max is obtained from the optional "max-frequency" property */
- rt_dm_dev_prop_read_u32(dev, "max-frequency", &host->f_max);
- if (rt_dm_dev_prop_read_bool(dev, "cap-mmc-highspeed"))
- {
- host->caps |= MMC_CAP_MMC_HIGHSPEED;
- }
- if (rt_dm_dev_prop_read_bool(dev, "mmc-hs200-1_8v"))
- {
- host->caps |= MMC_CAP2_HS200_1_8V_SDR;
- }
- if (rt_dm_dev_prop_read_bool(dev, "non-removable"))
- {
- host->caps |= MMC_CAP_NONREMOVABLE;
- }
- if (rt_dm_dev_prop_read_bool(dev, "no-sdio"))
- {
- host->caps2 |= MMC_CAP2_NO_SDIO;
- }
- if (rt_dm_dev_prop_read_bool(dev, "no-sd"))
- {
- host->caps2 |= MMC_CAP2_NO_SD;
- }
- if (rt_dm_dev_prop_read_bool(dev, "mmc-ddr-3_3v"))
- {
- host->caps |= MMC_CAP_3_3V_DDR;
- }
- if (rt_dm_dev_prop_read_bool(dev, "mmc-ddr-1_8v"))
- {
- host->caps |= MMC_CAP_1_8V_DDR;
- }
- if (rt_dm_dev_prop_read_bool(dev, "mmc-ddr-1_2v"))
- {
- host->caps |= MMC_CAP_1_2V_DDR;
- }
- return 0;
- }
- void rt_mmc_free_host(struct rt_mmc_host *host)
- {
- }
- rt_bool_t rt_mmc_can_gpio_cd(struct rt_mmc_host *host)
- {
- return RT_FALSE;
- }
- int mmc_regulator_get_supply(struct rt_mmc_host *mmc)
- {
- mmc->supply.vmmc = -RT_NULL;
- mmc->supply.vqmmc = -RT_NULL;
- return 0;
- }
- int regulator_get_current_limit(struct regulator *regulator)
- {
- return 0;
- }
- int regulator_is_supported_voltage(struct regulator *regulator,
- int min_uV, int max_uV)
- {
- return 0;
- }
|