brintos

brintos / linux-shallow public Read only

0
0
Text · 10.7 KiB · 1a7e4e5 Raw
444 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (C) 2019 Spreadtrum Communications Inc.3 4#include <linux/clk.h>5#include <linux/delay.h>6#include <linux/hwspinlock.h>7#include <linux/io.h>8#include <linux/module.h>9#include <linux/nvmem-provider.h>10#include <linux/of.h>11#include <linux/platform_device.h>12 13#define SPRD_EFUSE_ENABLE		0x2014#define SPRD_EFUSE_ERR_FLAG		0x2415#define SPRD_EFUSE_ERR_CLR		0x2816#define SPRD_EFUSE_MAGIC_NUM		0x2c17#define SPRD_EFUSE_FW_CFG		0x5018#define SPRD_EFUSE_PW_SWT		0x5419#define SPRD_EFUSE_MEM(val)		(0x1000 + ((val) << 2))20 21#define SPRD_EFUSE_VDD_EN		BIT(0)22#define SPRD_EFUSE_AUTO_CHECK_EN	BIT(1)23#define SPRD_EFUSE_DOUBLE_EN		BIT(2)24#define SPRD_EFUSE_MARGIN_RD_EN		BIT(3)25#define SPRD_EFUSE_LOCK_WR_EN		BIT(4)26 27#define SPRD_EFUSE_ERR_CLR_MASK		GENMASK(13, 0)28 29#define SPRD_EFUSE_ENK1_ON		BIT(0)30#define SPRD_EFUSE_ENK2_ON		BIT(1)31#define SPRD_EFUSE_PROG_EN		BIT(2)32 33#define SPRD_EFUSE_MAGIC_NUMBER		0x881034 35/* Block width (bytes) definitions */36#define SPRD_EFUSE_BLOCK_WIDTH		437 38/*39 * The Spreadtrum AP efuse contains 2 parts: normal efuse and secure efuse,40 * and we can only access the normal efuse in kernel. So define the normal41 * block offset index and normal block numbers.42 */43#define SPRD_EFUSE_NORMAL_BLOCK_NUMS	2444#define SPRD_EFUSE_NORMAL_BLOCK_OFFSET	7245 46/* Timeout (ms) for the trylock of hardware spinlocks */47#define SPRD_EFUSE_HWLOCK_TIMEOUT	500048 49/*50 * Since different Spreadtrum SoC chip can have different normal block numbers51 * and offset. And some SoC can support block double feature, which means52 * when reading or writing data to efuse memory, the controller can save double53 * data in case one data become incorrect after a long period.54 *55 * Thus we should save them in the device data structure.56 */57struct sprd_efuse_variant_data {58	u32 blk_nums;59	u32 blk_offset;60	bool blk_double;61};62 63struct sprd_efuse {64	struct device *dev;65	struct clk *clk;66	struct hwspinlock *hwlock;67	struct mutex mutex;68	void __iomem *base;69	const struct sprd_efuse_variant_data *data;70};71 72static const struct sprd_efuse_variant_data ums312_data = {73	.blk_nums = SPRD_EFUSE_NORMAL_BLOCK_NUMS,74	.blk_offset = SPRD_EFUSE_NORMAL_BLOCK_OFFSET,75	.blk_double = false,76};77 78/*79 * On Spreadtrum platform, we have multi-subsystems will access the unique80 * efuse controller, so we need one hardware spinlock to synchronize between81 * the multiple subsystems.82 */83static int sprd_efuse_lock(struct sprd_efuse *efuse)84{85	int ret;86 87	mutex_lock(&efuse->mutex);88 89	ret = hwspin_lock_timeout_raw(efuse->hwlock,90				      SPRD_EFUSE_HWLOCK_TIMEOUT);91	if (ret) {92		dev_err(efuse->dev, "timeout get the hwspinlock\n");93		mutex_unlock(&efuse->mutex);94		return ret;95	}96 97	return 0;98}99 100static void sprd_efuse_unlock(struct sprd_efuse *efuse)101{102	hwspin_unlock_raw(efuse->hwlock);103	mutex_unlock(&efuse->mutex);104}105 106static void sprd_efuse_set_prog_power(struct sprd_efuse *efuse, bool en)107{108	u32 val = readl(efuse->base + SPRD_EFUSE_PW_SWT);109 110	if (en)111		val &= ~SPRD_EFUSE_ENK2_ON;112	else113		val &= ~SPRD_EFUSE_ENK1_ON;114 115	writel(val, efuse->base + SPRD_EFUSE_PW_SWT);116 117	/* Open or close efuse power need wait 1000us to make power stable. */118	usleep_range(1000, 1200);119 120	if (en)121		val |= SPRD_EFUSE_ENK1_ON;122	else123		val |= SPRD_EFUSE_ENK2_ON;124 125	writel(val, efuse->base + SPRD_EFUSE_PW_SWT);126 127	/* Open or close efuse power need wait 1000us to make power stable. */128	usleep_range(1000, 1200);129}130 131static void sprd_efuse_set_read_power(struct sprd_efuse *efuse, bool en)132{133	u32 val = readl(efuse->base + SPRD_EFUSE_ENABLE);134 135	if (en)136		val |= SPRD_EFUSE_VDD_EN;137	else138		val &= ~SPRD_EFUSE_VDD_EN;139 140	writel(val, efuse->base + SPRD_EFUSE_ENABLE);141 142	/* Open or close efuse power need wait 1000us to make power stable. */143	usleep_range(1000, 1200);144}145 146static void sprd_efuse_set_prog_lock(struct sprd_efuse *efuse, bool en)147{148	u32 val = readl(efuse->base + SPRD_EFUSE_ENABLE);149 150	if (en)151		val |= SPRD_EFUSE_LOCK_WR_EN;152	else153		val &= ~SPRD_EFUSE_LOCK_WR_EN;154 155	writel(val, efuse->base + SPRD_EFUSE_ENABLE);156}157 158static void sprd_efuse_set_auto_check(struct sprd_efuse *efuse, bool en)159{160	u32 val = readl(efuse->base + SPRD_EFUSE_ENABLE);161 162	if (en)163		val |= SPRD_EFUSE_AUTO_CHECK_EN;164	else165		val &= ~SPRD_EFUSE_AUTO_CHECK_EN;166 167	writel(val, efuse->base + SPRD_EFUSE_ENABLE);168}169 170static void sprd_efuse_set_data_double(struct sprd_efuse *efuse, bool en)171{172	u32 val = readl(efuse->base + SPRD_EFUSE_ENABLE);173 174	if (en)175		val |= SPRD_EFUSE_DOUBLE_EN;176	else177		val &= ~SPRD_EFUSE_DOUBLE_EN;178 179	writel(val, efuse->base + SPRD_EFUSE_ENABLE);180}181 182static void sprd_efuse_set_prog_en(struct sprd_efuse *efuse, bool en)183{184	u32 val = readl(efuse->base + SPRD_EFUSE_PW_SWT);185 186	if (en)187		val |= SPRD_EFUSE_PROG_EN;188	else189		val &= ~SPRD_EFUSE_PROG_EN;190 191	writel(val, efuse->base + SPRD_EFUSE_PW_SWT);192}193 194static int sprd_efuse_raw_prog(struct sprd_efuse *efuse, u32 blk, bool doub,195			       bool lock, u32 *data)196{197	u32 status;198	int ret = 0;199 200	/*201	 * We need set the correct magic number before writing the efuse to202	 * allow programming, and block other programming until we clear the203	 * magic number.204	 */205	writel(SPRD_EFUSE_MAGIC_NUMBER,206	       efuse->base + SPRD_EFUSE_MAGIC_NUM);207 208	/*209	 * Power on the efuse, enable programme and enable double data210	 * if asked.211	 */212	sprd_efuse_set_prog_power(efuse, true);213	sprd_efuse_set_prog_en(efuse, true);214	sprd_efuse_set_data_double(efuse, doub);215 216	/*217	 * Enable the auto-check function to validate if the programming is218	 * successful.219	 */220	if (lock)221		sprd_efuse_set_auto_check(efuse, true);222 223	writel(*data, efuse->base + SPRD_EFUSE_MEM(blk));224 225	/* Disable auto-check and data double after programming */226	if (lock)227		sprd_efuse_set_auto_check(efuse, false);228	sprd_efuse_set_data_double(efuse, false);229 230	/*231	 * Check the efuse error status, if the programming is successful,232	 * we should lock this efuse block to avoid programming again.233	 */234	status = readl(efuse->base + SPRD_EFUSE_ERR_FLAG);235	if (status) {236		dev_err(efuse->dev,237			"write error status %u of block %d\n", status, blk);238 239		writel(SPRD_EFUSE_ERR_CLR_MASK,240		       efuse->base + SPRD_EFUSE_ERR_CLR);241		ret = -EBUSY;242	} else if (lock) {243		sprd_efuse_set_prog_lock(efuse, lock);244		writel(0, efuse->base + SPRD_EFUSE_MEM(blk));245		sprd_efuse_set_prog_lock(efuse, false);246	}247 248	sprd_efuse_set_prog_power(efuse, false);249	writel(0, efuse->base + SPRD_EFUSE_MAGIC_NUM);250 251	return ret;252}253 254static int sprd_efuse_raw_read(struct sprd_efuse *efuse, int blk, u32 *val,255			       bool doub)256{257	u32 status;258 259	/*260	 * Need power on the efuse before reading data from efuse, and will261	 * power off the efuse after reading process.262	 */263	sprd_efuse_set_read_power(efuse, true);264 265	/* Enable double data if asked */266	sprd_efuse_set_data_double(efuse, doub);267 268	/* Start to read data from efuse block */269	*val = readl(efuse->base + SPRD_EFUSE_MEM(blk));270 271	/* Disable double data */272	sprd_efuse_set_data_double(efuse, false);273 274	/* Power off the efuse */275	sprd_efuse_set_read_power(efuse, false);276 277	/*278	 * Check the efuse error status and clear them if there are some279	 * errors occurred.280	 */281	status = readl(efuse->base + SPRD_EFUSE_ERR_FLAG);282	if (status) {283		dev_err(efuse->dev,284			"read error status %d of block %d\n", status, blk);285 286		writel(SPRD_EFUSE_ERR_CLR_MASK,287		       efuse->base + SPRD_EFUSE_ERR_CLR);288		return -EBUSY;289	}290 291	return 0;292}293 294static int sprd_efuse_read(void *context, u32 offset, void *val, size_t bytes)295{296	struct sprd_efuse *efuse = context;297	bool blk_double = efuse->data->blk_double;298	u32 index = offset / SPRD_EFUSE_BLOCK_WIDTH + efuse->data->blk_offset;299	u32 blk_offset = (offset % SPRD_EFUSE_BLOCK_WIDTH) * BITS_PER_BYTE;300	u32 data;301	int ret;302 303	ret = sprd_efuse_lock(efuse);304	if (ret)305		return ret;306 307	ret = clk_prepare_enable(efuse->clk);308	if (ret)309		goto unlock;310 311	ret = sprd_efuse_raw_read(efuse, index, &data, blk_double);312	if (!ret) {313		data >>= blk_offset;314		memcpy(val, &data, bytes);315	}316 317	clk_disable_unprepare(efuse->clk);318 319unlock:320	sprd_efuse_unlock(efuse);321	return ret;322}323 324static int sprd_efuse_write(void *context, u32 offset, void *val, size_t bytes)325{326	struct sprd_efuse *efuse = context;327	bool blk_double = efuse->data->blk_double;328	bool lock;329	int ret;330 331	ret = sprd_efuse_lock(efuse);332	if (ret)333		return ret;334 335	ret = clk_prepare_enable(efuse->clk);336	if (ret)337		goto unlock;338 339	/*340	 * If the writing bytes are equal with the block width, which means the341	 * whole block will be programmed. For this case, we should not allow342	 * this block to be programmed again by locking this block.343	 *344	 * If the block was programmed partially, we should allow this block to345	 * be programmed again.346	 */347	if (bytes < SPRD_EFUSE_BLOCK_WIDTH)348		lock = false;349	else350		lock = true;351 352	ret = sprd_efuse_raw_prog(efuse, offset, blk_double, lock, val);353 354	clk_disable_unprepare(efuse->clk);355 356unlock:357	sprd_efuse_unlock(efuse);358	return ret;359}360 361static int sprd_efuse_probe(struct platform_device *pdev)362{363	struct device_node *np = pdev->dev.of_node;364	struct nvmem_device *nvmem;365	struct nvmem_config econfig = { };366	struct sprd_efuse *efuse;367	const struct sprd_efuse_variant_data *pdata;368	int ret;369 370	pdata = of_device_get_match_data(&pdev->dev);371	if (!pdata) {372		dev_err(&pdev->dev, "No matching driver data found\n");373		return -EINVAL;374	}375 376	efuse = devm_kzalloc(&pdev->dev, sizeof(*efuse), GFP_KERNEL);377	if (!efuse)378		return -ENOMEM;379 380	efuse->base = devm_platform_ioremap_resource(pdev, 0);381	if (IS_ERR(efuse->base))382		return PTR_ERR(efuse->base);383 384	ret = of_hwspin_lock_get_id(np, 0);385	if (ret < 0) {386		dev_err(&pdev->dev, "failed to get hwlock id\n");387		return ret;388	}389 390	efuse->hwlock = devm_hwspin_lock_request_specific(&pdev->dev, ret);391	if (!efuse->hwlock) {392		dev_err(&pdev->dev, "failed to request hwlock\n");393		return -ENXIO;394	}395 396	efuse->clk = devm_clk_get(&pdev->dev, "enable");397	if (IS_ERR(efuse->clk)) {398		dev_err(&pdev->dev, "failed to get enable clock\n");399		return PTR_ERR(efuse->clk);400	}401 402	mutex_init(&efuse->mutex);403	efuse->dev = &pdev->dev;404	efuse->data = pdata;405 406	econfig.stride = 1;407	econfig.word_size = 1;408	econfig.read_only = false;409	econfig.name = "sprd-efuse";410	econfig.size = efuse->data->blk_nums * SPRD_EFUSE_BLOCK_WIDTH;411	econfig.add_legacy_fixed_of_cells = true;412	econfig.reg_read = sprd_efuse_read;413	econfig.reg_write = sprd_efuse_write;414	econfig.priv = efuse;415	econfig.dev = &pdev->dev;416	nvmem = devm_nvmem_register(&pdev->dev, &econfig);417	if (IS_ERR(nvmem)) {418		dev_err(&pdev->dev, "failed to register nvmem\n");419		return PTR_ERR(nvmem);420	}421 422	return 0;423}424 425static const struct of_device_id sprd_efuse_of_match[] = {426	{ .compatible = "sprd,ums312-efuse", .data = &ums312_data },427	{ }428};429MODULE_DEVICE_TABLE(of, sprd_efuse_of_match);430 431static struct platform_driver sprd_efuse_driver = {432	.probe = sprd_efuse_probe,433	.driver = {434		.name = "sprd-efuse",435		.of_match_table = sprd_efuse_of_match,436	},437};438 439module_platform_driver(sprd_efuse_driver);440 441MODULE_AUTHOR("Freeman Liu <freeman.liu@spreadtrum.com>");442MODULE_DESCRIPTION("Spreadtrum AP efuse driver");443MODULE_LICENSE("GPL v2");444