brintos

brintos / linux-shallow public Read only

0
0
Text · 11.4 KiB · e8ee7c4 Raw
487 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (c) 2013 Linaro Ltd.4 * Copyright (c) 2013 HiSilicon Limited.5 */6 7#include <linux/bitops.h>8#include <linux/bitfield.h>9#include <linux/clk.h>10#include <linux/mfd/syscon.h>11#include <linux/mmc/host.h>12#include <linux/module.h>13#include <linux/of_address.h>14#include <linux/platform_device.h>15#include <linux/pm_runtime.h>16#include <linux/regmap.h>17#include <linux/regulator/consumer.h>18 19#include "dw_mmc.h"20#include "dw_mmc-pltfm.h"21 22/*23 * hi6220 sd only support io voltage 1.8v and 3v24 * Also need config AO_SCTRL_SEL18 accordingly25 */26#define AO_SCTRL_SEL18		BIT(10)27#define AO_SCTRL_CTRL3		0x40C28 29#define DWMMC_SDIO_ID 230 31#define SOC_SCTRL_SCPERCTRL5    (0x314)32#define SDCARD_IO_SEL18         BIT(2)33 34#define SDCARD_RD_THRESHOLD  (512)35 36#define GENCLK_DIV (7)37 38#define GPIO_CLK_ENABLE                   BIT(16)39#define GPIO_CLK_DIV_MASK                 GENMASK(11, 8)40#define GPIO_USE_SAMPLE_DLY_MASK          GENMASK(13, 13)41#define UHS_REG_EXT_SAMPLE_PHASE_MASK     GENMASK(20, 16)42#define UHS_REG_EXT_SAMPLE_DRVPHASE_MASK  GENMASK(25, 21)43#define UHS_REG_EXT_SAMPLE_DLY_MASK       GENMASK(30, 26)44 45#define TIMING_MODE     346#define TIMING_CFG_NUM 1047 48#define NUM_PHASES (40)49 50#define ENABLE_SHIFT_MIN_SMPL (4)51#define ENABLE_SHIFT_MAX_SMPL (12)52#define USE_DLY_MIN_SMPL (11)53#define USE_DLY_MAX_SMPL (14)54 55struct k3_priv {56	int ctrl_id;57	u32 cur_speed;58	struct regmap	*reg;59};60 61static unsigned long dw_mci_hi6220_caps[] = {62	MMC_CAP_CMD23,63	MMC_CAP_CMD23,64	065};66 67struct hs_timing {68	u32 drv_phase;69	u32 smpl_dly;70	u32 smpl_phase_max;71	u32 smpl_phase_min;72};73 74static struct hs_timing hs_timing_cfg[TIMING_MODE][TIMING_CFG_NUM] = {75	{ /* reserved */ },76	{ /* SD */77		{7, 0, 15, 15,},  /* 0: LEGACY 400k */78		{6, 0,  4,  4,},  /* 1: MMC_HS */79		{6, 0,  3,  3,},  /* 2: SD_HS */80		{6, 0, 15, 15,},  /* 3: SDR12 */81		{6, 0,  2,  2,},  /* 4: SDR25 */82		{4, 0, 11,  0,},  /* 5: SDR50 */83		{6, 4, 15,  0,},  /* 6: SDR104 */84		{0},              /* 7: DDR50 */85		{0},              /* 8: DDR52 */86		{0},              /* 9: HS200 */87	},88	{ /* SDIO */89		{7, 0, 15, 15,},  /* 0: LEGACY 400k */90		{0},              /* 1: MMC_HS */91		{6, 0, 15, 15,},  /* 2: SD_HS */92		{6, 0, 15, 15,},  /* 3: SDR12 */93		{6, 0,  0,  0,},  /* 4: SDR25 */94		{4, 0, 12,  0,},  /* 5: SDR50 */95		{5, 4, 15,  0,},  /* 6: SDR104 */96		{0},              /* 7: DDR50 */97		{0},              /* 8: DDR52 */98		{0},              /* 9: HS200 */99	}100};101 102static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)103{104	int ret;105 106	ret = clk_set_rate(host->ciu_clk, ios->clock);107	if (ret)108		dev_warn(host->dev, "failed to set rate %uHz\n", ios->clock);109 110	host->bus_hz = clk_get_rate(host->ciu_clk);111}112 113static const struct dw_mci_drv_data k3_drv_data = {114	.set_ios		= dw_mci_k3_set_ios,115};116 117static int dw_mci_hi6220_parse_dt(struct dw_mci *host)118{119	struct k3_priv *priv;120 121	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);122	if (!priv)123		return -ENOMEM;124 125	priv->reg = syscon_regmap_lookup_by_phandle(host->dev->of_node,126					 "hisilicon,peripheral-syscon");127	if (IS_ERR(priv->reg))128		priv->reg = NULL;129 130	priv->ctrl_id = of_alias_get_id(host->dev->of_node, "mshc");131	if (priv->ctrl_id < 0)132		priv->ctrl_id = 0;133 134	if (priv->ctrl_id >= TIMING_MODE)135		return -EINVAL;136 137	host->priv = priv;138	return 0;139}140 141static int dw_mci_hi6220_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios)142{143	struct dw_mci_slot *slot = mmc_priv(mmc);144	struct k3_priv *priv;145	struct dw_mci *host;146	int min_uv, max_uv;147	int ret;148 149	host = slot->host;150	priv = host->priv;151 152	if (!priv || !priv->reg)153		return 0;154 155	if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {156		ret = regmap_update_bits(priv->reg, AO_SCTRL_CTRL3,157					 AO_SCTRL_SEL18, 0);158		min_uv = 3000000;159		max_uv = 3000000;160	} else if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {161		ret = regmap_update_bits(priv->reg, AO_SCTRL_CTRL3,162					 AO_SCTRL_SEL18, AO_SCTRL_SEL18);163		min_uv = 1800000;164		max_uv = 1800000;165	} else {166		dev_dbg(host->dev, "voltage not supported\n");167		return -EINVAL;168	}169 170	if (ret) {171		dev_dbg(host->dev, "switch voltage failed\n");172		return ret;173	}174 175	if (IS_ERR_OR_NULL(mmc->supply.vqmmc))176		return 0;177 178	ret = regulator_set_voltage(mmc->supply.vqmmc, min_uv, max_uv);179	if (ret) {180		dev_dbg(host->dev, "Regulator set error %d: %d - %d\n",181				 ret, min_uv, max_uv);182		return ret;183	}184 185	return 0;186}187 188static void dw_mci_hi6220_set_ios(struct dw_mci *host, struct mmc_ios *ios)189{190	int ret;191	unsigned int clock;192 193	clock = (ios->clock <= 25000000) ? 25000000 : ios->clock;194 195	ret = clk_set_rate(host->biu_clk, clock);196	if (ret)197		dev_warn(host->dev, "failed to set rate %uHz\n", clock);198 199	host->bus_hz = clk_get_rate(host->biu_clk);200}201 202static int dw_mci_hi6220_execute_tuning(struct dw_mci_slot *slot, u32 opcode)203{204	return 0;205}206 207static const struct dw_mci_drv_data hi6220_data = {208	.caps			= dw_mci_hi6220_caps,209	.num_caps		= ARRAY_SIZE(dw_mci_hi6220_caps),210	.switch_voltage		= dw_mci_hi6220_switch_voltage,211	.set_ios		= dw_mci_hi6220_set_ios,212	.parse_dt		= dw_mci_hi6220_parse_dt,213	.execute_tuning		= dw_mci_hi6220_execute_tuning,214};215 216static void dw_mci_hs_set_timing(struct dw_mci *host, int timing,217				     int smpl_phase)218{219	u32 drv_phase;220	u32 smpl_dly;221	u32 use_smpl_dly = 0;222	u32 enable_shift = 0;223	u32 reg_value;224	int ctrl_id;225	struct k3_priv *priv;226 227	priv = host->priv;228	ctrl_id = priv->ctrl_id;229 230	drv_phase = hs_timing_cfg[ctrl_id][timing].drv_phase;231	smpl_dly   = hs_timing_cfg[ctrl_id][timing].smpl_dly;232	if (smpl_phase == -1)233		smpl_phase = (hs_timing_cfg[ctrl_id][timing].smpl_phase_max +234			     hs_timing_cfg[ctrl_id][timing].smpl_phase_min) / 2;235 236	switch (timing) {237	case MMC_TIMING_UHS_SDR104:238		if (smpl_phase >= USE_DLY_MIN_SMPL &&239				smpl_phase <= USE_DLY_MAX_SMPL)240			use_smpl_dly = 1;241		fallthrough;242	case MMC_TIMING_UHS_SDR50:243		if (smpl_phase >= ENABLE_SHIFT_MIN_SMPL &&244				smpl_phase <= ENABLE_SHIFT_MAX_SMPL)245			enable_shift = 1;246		break;247	}248 249	mci_writel(host, GPIO, 0x0);250	usleep_range(5, 10);251 252	reg_value = FIELD_PREP(UHS_REG_EXT_SAMPLE_PHASE_MASK, smpl_phase) |253		    FIELD_PREP(UHS_REG_EXT_SAMPLE_DLY_MASK, smpl_dly) |254		    FIELD_PREP(UHS_REG_EXT_SAMPLE_DRVPHASE_MASK, drv_phase);255	mci_writel(host, UHS_REG_EXT, reg_value);256 257	mci_writel(host, ENABLE_SHIFT, enable_shift);258 259	reg_value = FIELD_PREP(GPIO_CLK_DIV_MASK, GENCLK_DIV) |260			     FIELD_PREP(GPIO_USE_SAMPLE_DLY_MASK, use_smpl_dly);261	mci_writel(host, GPIO, (unsigned int)reg_value | GPIO_CLK_ENABLE);262 263	/* We should delay 1ms wait for timing setting finished. */264	usleep_range(1000, 2000);265}266 267static int dw_mci_hi3660_init(struct dw_mci *host)268{269	mci_writel(host, CDTHRCTL, SDMMC_SET_THLD(SDCARD_RD_THRESHOLD,270		    SDMMC_CARD_RD_THR_EN));271 272	dw_mci_hs_set_timing(host, MMC_TIMING_LEGACY, -1);273	host->bus_hz /= (GENCLK_DIV + 1);274 275	return 0;276}277 278static int dw_mci_set_sel18(struct dw_mci *host, bool set)279{280	int ret;281	unsigned int val;282	struct k3_priv *priv;283 284	priv = host->priv;285 286	val = set ? SDCARD_IO_SEL18 : 0;287	ret = regmap_update_bits(priv->reg, SOC_SCTRL_SCPERCTRL5,288				 SDCARD_IO_SEL18, val);289	if (ret) {290		dev_err(host->dev, "sel18 %u error\n", val);291		return ret;292	}293 294	return 0;295}296 297static void dw_mci_hi3660_set_ios(struct dw_mci *host, struct mmc_ios *ios)298{299	int ret;300	unsigned long wanted;301	unsigned long actual;302	struct k3_priv *priv = host->priv;303 304	if (!ios->clock || ios->clock == priv->cur_speed)305		return;306 307	wanted = ios->clock * (GENCLK_DIV + 1);308	ret = clk_set_rate(host->ciu_clk, wanted);309	if (ret) {310		dev_err(host->dev, "failed to set rate %luHz\n", wanted);311		return;312	}313	actual = clk_get_rate(host->ciu_clk);314 315	dw_mci_hs_set_timing(host, ios->timing, -1);316	host->bus_hz = actual / (GENCLK_DIV + 1);317	host->current_speed = 0;318	priv->cur_speed = host->bus_hz;319}320 321static int dw_mci_get_best_clksmpl(unsigned int sample_flag)322{323	int i;324	int interval;325	unsigned int v;326	unsigned int len;327	unsigned int range_start = 0;328	unsigned int range_length = 0;329	unsigned int middle_range = 0;330 331	if (!sample_flag)332		return -EIO;333 334	if (~sample_flag == 0)335		return 0;336 337	i = ffs(sample_flag) - 1;338 339	/*340	* A clock cycle is divided into 32 phases,341	* each of which is represented by a bit,342	* finding the optimal phase.343	*/344	while (i < 32) {345		v = ror32(sample_flag, i);346		len = ffs(~v) - 1;347 348		if (len > range_length) {349			range_length = len;350			range_start = i;351		}352 353		interval = ffs(v >> len) - 1;354		if (interval < 0)355			break;356 357		i += len + interval;358	}359 360	middle_range = range_start + range_length / 2;361	if (middle_range >= 32)362		middle_range %= 32;363 364	return middle_range;365}366 367static int dw_mci_hi3660_execute_tuning(struct dw_mci_slot *slot, u32 opcode)368{369	int i = 0;370	struct dw_mci *host = slot->host;371	struct mmc_host *mmc = slot->mmc;372	int smpl_phase = 0;373	u32 tuning_sample_flag = 0;374	int best_clksmpl = 0;375 376	for (i = 0; i < NUM_PHASES; ++i, ++smpl_phase) {377		smpl_phase %= 32;378 379		mci_writel(host, TMOUT, ~0);380		dw_mci_hs_set_timing(host, mmc->ios.timing, smpl_phase);381 382		if (!mmc_send_tuning(mmc, opcode, NULL))383			tuning_sample_flag |= (1 << smpl_phase);384		else385			tuning_sample_flag &= ~(1 << smpl_phase);386	}387 388	best_clksmpl = dw_mci_get_best_clksmpl(tuning_sample_flag);389	if (best_clksmpl < 0) {390		dev_err(host->dev, "All phases bad!\n");391		return -EIO;392	}393 394	dw_mci_hs_set_timing(host, mmc->ios.timing, best_clksmpl);395 396	dev_info(host->dev, "tuning ok best_clksmpl %u tuning_sample_flag %x\n",397		 best_clksmpl, tuning_sample_flag);398	return 0;399}400 401static int dw_mci_hi3660_switch_voltage(struct mmc_host *mmc,402					struct mmc_ios *ios)403{404	int ret = 0;405	struct dw_mci_slot *slot = mmc_priv(mmc);406	struct k3_priv *priv;407	struct dw_mci *host;408 409	host = slot->host;410	priv = host->priv;411 412	if (!priv || !priv->reg)413		return 0;414 415	if (priv->ctrl_id == DWMMC_SDIO_ID)416		return 0;417 418	if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330)419		ret = dw_mci_set_sel18(host, 0);420	else if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)421		ret = dw_mci_set_sel18(host, 1);422	if (ret)423		return ret;424 425	if (!IS_ERR(mmc->supply.vqmmc)) {426		ret = mmc_regulator_set_vqmmc(mmc, ios);427		if (ret < 0) {428			dev_err(host->dev, "Regulator set error %d\n", ret);429			return ret;430		}431	}432 433	return 0;434}435 436static const struct dw_mci_drv_data hi3660_data = {437	.init = dw_mci_hi3660_init,438	.set_ios = dw_mci_hi3660_set_ios,439	.parse_dt = dw_mci_hi6220_parse_dt,440	.execute_tuning = dw_mci_hi3660_execute_tuning,441	.switch_voltage  = dw_mci_hi3660_switch_voltage,442};443 444static const struct of_device_id dw_mci_k3_match[] = {445	{ .compatible = "hisilicon,hi3660-dw-mshc", .data = &hi3660_data, },446	{ .compatible = "hisilicon,hi4511-dw-mshc", .data = &k3_drv_data, },447	{ .compatible = "hisilicon,hi6220-dw-mshc", .data = &hi6220_data, },448	{},449};450MODULE_DEVICE_TABLE(of, dw_mci_k3_match);451 452static int dw_mci_k3_probe(struct platform_device *pdev)453{454	const struct dw_mci_drv_data *drv_data;455	const struct of_device_id *match;456 457	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);458	drv_data = match->data;459 460	return dw_mci_pltfm_register(pdev, drv_data);461}462 463static const struct dev_pm_ops dw_mci_k3_dev_pm_ops = {464	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,465				pm_runtime_force_resume)466	SET_RUNTIME_PM_OPS(dw_mci_runtime_suspend,467			   dw_mci_runtime_resume,468			   NULL)469};470 471static struct platform_driver dw_mci_k3_pltfm_driver = {472	.probe		= dw_mci_k3_probe,473	.remove_new	= dw_mci_pltfm_remove,474	.driver		= {475		.name		= "dwmmc_k3",476		.probe_type	= PROBE_PREFER_ASYNCHRONOUS,477		.of_match_table	= dw_mci_k3_match,478		.pm		= &dw_mci_k3_dev_pm_ops,479	},480};481 482module_platform_driver(dw_mci_k3_pltfm_driver);483 484MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension");485MODULE_LICENSE("GPL v2");486MODULE_ALIAS("platform:dwmmc_k3");487