static int qfprom_reg_write()

in qfprom.c [257:319]


static int qfprom_reg_write(void *context, unsigned int reg, void *_val,
			    size_t bytes)
{
	struct qfprom_priv *priv = context;
	struct qfprom_touched_values old;
	int words = bytes / 4;
	u32 *value = _val;
	u32 blow_status;
	int ret;
	int i;

	dev_dbg(priv->dev,
		"Writing to raw qfprom region : %#010x of size: %zu\n",
		reg, bytes);

	/*
	 * The hardware only allows us to write word at a time, but we can
	 * read byte at a time.  Until the nvmem framework allows a separate
	 * word_size and stride for reading vs. writing, we'll enforce here.
	 */
	if (bytes % 4) {
		dev_err(priv->dev,
			"%zu is not an integral number of words\n", bytes);
		return -EINVAL;
	}
	if (reg % 4) {
		dev_err(priv->dev,
			"Invalid offset: %#x.  Must be word aligned\n", reg);
		return -EINVAL;
	}

	ret = qfprom_enable_fuse_blowing(priv, &old);
	if (ret)
		return ret;

	ret = readl_relaxed_poll_timeout(
		priv->qfpconf + QFPROM_BLOW_STATUS_OFFSET,
		blow_status, blow_status == QFPROM_BLOW_STATUS_READY,
		QFPROM_FUSE_BLOW_POLL_US, QFPROM_FUSE_BLOW_TIMEOUT_US);

	if (ret) {
		dev_err(priv->dev,
			"Timeout waiting for initial ready; aborting.\n");
		goto exit_enabled_fuse_blowing;
	}

	for (i = 0; i < words; i++)
		writel(value[i], priv->qfpraw + reg + (i * 4));

	ret = readl_relaxed_poll_timeout(
		priv->qfpconf + QFPROM_BLOW_STATUS_OFFSET,
		blow_status, blow_status == QFPROM_BLOW_STATUS_READY,
		QFPROM_FUSE_BLOW_POLL_US, QFPROM_FUSE_BLOW_TIMEOUT_US);

	/* Give an error, but not much we can do in this case */
	if (ret)
		dev_err(priv->dev, "Timeout waiting for finish.\n");

exit_enabled_fuse_blowing:
	qfprom_disable_fuse_blowing(priv, &old);

	return ret;
}