| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2022-12-06 GuEe-GUI first version
- */
- #include "dev_sdio_dm.h"
- #define DBG_TAG "SDIO"
- #ifdef RT_SDIO_DEBUG
- #define DBG_LVL DBG_LOG
- #else
- #define DBG_LVL DBG_INFO
- #endif /* RT_SDIO_DEBUG */
- #include <rtdbg.h>
- static rt_err_t ocrbitnum_to_vdd(int vdd_bit, int *min_uvolt, int *max_uvolt)
- {
- int tmp;
- if (!vdd_bit)
- {
- return -RT_EINVAL;
- }
- tmp = vdd_bit - rt_ilog2(VDD_165_195);
- if (tmp == 0)
- {
- *min_uvolt = 1650 * 1000;
- *max_uvolt = 1950 * 1000;
- }
- else
- {
- *min_uvolt = 1900 * 1000 + tmp * 100 * 1000;
- *max_uvolt = *min_uvolt + 100 * 1000;
- }
- return 0;
- }
- rt_err_t sdio_regulator_set_ocr(struct rt_mmcsd_host *host,
- struct rt_regulator *supply, rt_uint16_t vdd_bit)
- {
- rt_err_t err = RT_EOK;
- if (!host)
- {
- return -RT_EINVAL;
- }
- if (rt_is_err_or_null(supply))
- {
- return RT_EOK;
- }
- if (vdd_bit)
- {
- int min_uvolt, max_uvolt;
- ocrbitnum_to_vdd(vdd_bit, &min_uvolt, &max_uvolt);
- err = rt_regulator_set_voltage(supply, min_uvolt, max_uvolt);
- if (!err && host->supply.regulator_enabled)
- {
- err = rt_regulator_enable(supply);
- if (!err)
- {
- host->supply.regulator_enabled = RT_TRUE;
- }
- }
- }
- else if (host->supply.regulator_enabled)
- {
- err = rt_regulator_disable(supply);
- if (!err)
- {
- host->supply.regulator_enabled = RT_FALSE;
- }
- }
- if (err)
- {
- LOG_E("Set regulator OCR %d error = %s", vdd_bit, rt_strerror(err));
- }
- return err;
- }
- static int regulator_set_voltage_if_supported(struct rt_regulator *regulator,
- int min_uvolt, int target_uvolt, int max_uvolt)
- {
- if (!rt_regulator_is_supported_voltage(regulator, min_uvolt, max_uvolt))
- {
- return -RT_EINVAL;
- }
- if (rt_regulator_get_voltage(regulator) == target_uvolt)
- {
- return RT_EOK;
- }
- return rt_regulator_set_voltage_triplet(regulator, min_uvolt, target_uvolt,
- max_uvolt);
- }
- rt_err_t sdio_regulator_set_vqmmc(struct rt_mmcsd_host *host,
- struct rt_mmcsd_io_cfg *ios)
- {
- rt_err_t err;
- int uvolt, min_uvolt, max_uvolt;
- if (rt_is_err_or_null(host->supply.vqmmc))
- {
- return -RT_EINVAL;
- }
- switch (ios->signal_voltage)
- {
- case MMCSD_SIGNAL_VOLTAGE_120:
- return regulator_set_voltage_if_supported(host->supply.vqmmc,
- 1100000, 1200000, 1300000);
- case MMCSD_SIGNAL_VOLTAGE_180:
- return regulator_set_voltage_if_supported(host->supply.vqmmc,
- 1700000, 1800000, 1950000);
- case MMCSD_SIGNAL_VOLTAGE_330:
- err = ocrbitnum_to_vdd(host->io_cfg.vdd, &uvolt, &max_uvolt);
- if (err)
- {
- return err;
- }
- min_uvolt = rt_max(uvolt - 300000, 2700000);
- max_uvolt = rt_min(max_uvolt + 200000, 3600000);
- err = regulator_set_voltage_if_supported(host->supply.vqmmc,
- min_uvolt, uvolt, max_uvolt);
- if (err >= 0)
- {
- return err;
- }
- return regulator_set_voltage_if_supported(host->supply.vqmmc,
- 2700000, uvolt, 3600000);
- default:
- return -RT_EINVAL;
- }
- }
- rt_err_t sdio_regulator_get_supply(struct rt_device *dev, struct rt_mmcsd_host *host)
- {
- rt_err_t err;
- if (!dev || !host)
- {
- return -RT_EINVAL;
- }
- host->supply.vmmc = rt_regulator_get(dev, "vmmc");
- host->supply.vqmmc = rt_regulator_get(dev, "vqmmc");
- if (!rt_is_err(host->supply.vmmc))
- {
- if (!host->supply.vmmc)
- {
- LOG_D("%s: No %s regulator found", rt_dm_dev_get_name(dev), "vmmc");
- }
- }
- else
- {
- err = rt_ptr_err(host->supply.vmmc);
- goto _fail;
- }
- if (!rt_is_err(host->supply.vqmmc))
- {
- if (!host->supply.vqmmc)
- {
- LOG_D("%s: No %s regulator found", rt_dm_dev_get_name(dev), "vqmmc");
- }
- }
- else
- {
- err = rt_ptr_err(host->supply.vqmmc);
- goto _fail;
- }
- return RT_EOK;
- _fail:
- if (!rt_is_err_or_null(host->supply.vmmc))
- {
- rt_regulator_put(host->supply.vmmc);
- host->supply.vmmc = RT_NULL;
- }
- if (!rt_is_err_or_null(host->supply.vqmmc))
- {
- rt_regulator_put(host->supply.vqmmc);
- host->supply.vqmmc = RT_NULL;
- }
- return err;
- }
- rt_err_t sdio_regulator_enable_vqmmc(struct rt_mmcsd_host *host)
- {
- struct rt_mmcsd_supply *supply;
- if (!host)
- {
- return -RT_EINVAL;
- }
- supply = &host->supply;
- if (!rt_is_err_or_null(supply->vqmmc) && !supply->vqmmc_enabled)
- {
- rt_err_t err = rt_regulator_enable(supply->vqmmc);
- if (err)
- {
- LOG_E("Enabling vqmmc regulator failed error = %s", rt_strerror(err));
- }
- else
- {
- supply->vqmmc_enabled = RT_TRUE;
- }
- }
- return RT_EOK;
- }
- void sdio_regulator_disable_vqmmc(struct rt_mmcsd_host *host)
- {
- struct rt_mmcsd_supply *supply;
- if (!host)
- {
- return;
- }
- supply = &host->supply;
- if (!rt_is_err_or_null(supply->vqmmc) && supply->vqmmc_enabled)
- {
- rt_regulator_disable(supply->vqmmc);
- supply->vqmmc_enabled = RT_FALSE;
- }
- }
|