// SPDX-License-Identifier: GPL-2.0
/*
 * OTP Memory controller
 *
 * Copyright (C) 2022 Microchip Technology Inc. and its subsidiaries
 *
 * Author: Claudiu Beznea <claudiu.beznea@microchip.com>
 */

#include <linux/bitfield.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/nvmem-provider.h>
#include <linux/of.h>
#include <linux/platform_device.h>

#define MCHP_OTPC_CR			(0x0)
#define MCHP_OTPC_CR_READ		BIT(6)
#define MCHP_OTPC_MR			(0x4)
#define MCHP_OTPC_MR_ADDR		GENMASK(31, 16)
#define MCHP_OTPC_AR			(0x8)
#define MCHP_OTPC_SR			(0xc)
#define MCHP_OTPC_SR_READ		BIT(6)
#define MCHP_OTPC_HR			(0x20)
#define MCHP_OTPC_HR_SIZE		GENMASK(15, 8)
#define MCHP_OTPC_DR			(0x24)

#define MCHP_OTPC_NAME			"mchp-otpc"
#define MCHP_OTPC_SIZE			(11 * 1024)

/**
 * struct mchp_otpc - OTPC private data structure
 * @base: base address
 * @dev: struct device pointer
 * @packets: list of packets in OTP memory
 * @npackets: number of packets in OTP memory
 */
struct mchp_otpc {
	void __iomem *base;
	struct device *dev;
	struct list_head packets;
	u32 npackets;
};

/**
 * struct mchp_otpc_packet - OTPC packet data structure
 * @list: list head
 * @id: packet ID
 * @offset: packet offset (in words) in OTP memory
 */
struct mchp_otpc_packet {
	struct list_head list;
	u32 id;
	u32 offset;
};

static struct mchp_otpc_packet *mchp_otpc_id_to_packet(struct mchp_otpc *otpc,
						       u32 id)
{
	struct mchp_otpc_packet *packet;

	if (id >= otpc->npackets)
		return NULL;

	list_for_each_entry(packet, &otpc->packets, list) {
		if (packet->id == id)
			return packet;
	}

	return NULL;
}

static int mchp_otpc_prepare_read(struct mchp_otpc *otpc,
				  unsigned int offset)
{
	u32 tmp;

	/* Set address. */
	tmp = readl_relaxed(otpc->base + MCHP_OTPC_MR);
	tmp &= ~MCHP_OTPC_MR_ADDR;
	tmp |= FIELD_PREP(MCHP_OTPC_MR_ADDR, offset);
	writel_relaxed(tmp, otpc->base + MCHP_OTPC_MR);

	/* Set read. */
	tmp = readl_relaxed(otpc->base + MCHP_OTPC_CR);
	tmp |= MCHP_OTPC_CR_READ;
	writel_relaxed(tmp, otpc->base + MCHP_OTPC_CR);

	/* Wait for packet to be transferred into temporary buffers. */
	return read_poll_timeout(readl_relaxed, tmp, !(tmp & MCHP_OTPC_SR_READ),
				 10000, 2000, false, otpc->base + MCHP_OTPC_SR);
}

/*
 * OTPC memory is organized into packets. Each packets contains a header and
 * a payload. Header is 4 bytes long and contains the size of the payload.
 * Payload size varies. The memory footprint is something as follows:
 *
 * Memory offset  Memory footprint     Packet ID
 * -------------  ----------------     ---------
 *
 * 0x0            +------------+   <-- packet 0
 *                | header  0  |
 * 0x4            +------------+
 *                | payload 0  |
 *                .            .
 *                .    ...     .
 *                .            .
 * offset1        +------------+   <-- packet 1
 *                | header  1  |
 * offset1 + 0x4  +------------+
 *                | payload 1  |
 *                .            .
 *                .    ...     .
 *                .            .
 * offset2        +------------+   <-- packet 2
 *                .            .
 *                .    ...     .
 *                .            .
 * offsetN        +------------+   <-- packet N
 *                | header  N  |
 * offsetN + 0x4  +------------+
 *                | payload N  |
 *                .            .
 *                .    ...     .
 *                .            .
 *                +------------+
 *
 * where offset1, offset2, offsetN depends on the size of payload 0, payload 1,
 * payload N-1.
 *
 * The access to memory is done on a per packet basis: the control registers
 * need to be updated with an offset address (within a packet range) and the
 * data registers will be update by controller with information contained by
 * that packet. E.g. if control registers are updated with any address within
 * the range [offset1, offset2) the data registers are updated by controller
 * with packet 1. Header data is accessible though MCHP_OTPC_HR register.
 * Payload data is accessible though MCHP_OTPC_DR and MCHP_OTPC_AR registers.
 * There is no direct mapping b/w the offset requested by software and the
 * offset returned by hardware.
 *
 * For this, the read function will return the first requested bytes in the
 * packet. The user will have to be aware of the memory footprint before doing
 * the read request.
 */
static int mchp_otpc_read(void *priv, unsigned int off, void *val,
			  size_t bytes)
{
	struct mchp_otpc *otpc = priv;
	struct mchp_otpc_packet *packet;
	u32 *buf = val;
	u32 offset;
	size_t len = 0;
	int ret, payload_size;

	/*
	 * We reach this point with off being multiple of stride = 4 to
	 * be able to cross the subsystem. Inside the driver we use continuous
	 * unsigned integer numbers for packet id, thus devide off by 4
	 * before passing it to mchp_otpc_id_to_packet().
	 */
	packet = mchp_otpc_id_to_packet(otpc, off / 4);
	if (!packet)
		return -EINVAL;
	offset = packet->offset;

	while (len < bytes) {
		ret = mchp_otpc_prepare_read(otpc, offset);
		if (ret)
			return ret;

		/* Read and save header content. */
		*buf++ = readl_relaxed(otpc->base + MCHP_OTPC_HR);
		len += sizeof(*buf);
		offset++;
		if (len >= bytes)
			break;

		/* Read and save payload content. */
		payload_size = FIELD_GET(MCHP_OTPC_HR_SIZE, *(buf - 1));
		writel_relaxed(0UL, otpc->base + MCHP_OTPC_AR);
		do {
			*buf++ = readl_relaxed(otpc->base + MCHP_OTPC_DR);
			len += sizeof(*buf);
			offset++;
			payload_size--;
		} while (payload_size >= 0 && len < bytes);
	}

	return 0;
}

static int mchp_otpc_init_packets_list(struct mchp_otpc *otpc, u32 *size)
{
	struct mchp_otpc_packet *packet;
	u32 word, word_pos = 0, id = 0, npackets = 0, payload_size;
	int ret;

	INIT_LIST_HEAD(&otpc->packets);
	*size = 0;

	while (*size < MCHP_OTPC_SIZE) {
		ret = mchp_otpc_prepare_read(otpc, word_pos);
		if (ret)
			return ret;

		word = readl_relaxed(otpc->base + MCHP_OTPC_HR);
		payload_size = FIELD_GET(MCHP_OTPC_HR_SIZE, word);
		if (!payload_size)
			break;

		packet = devm_kzalloc(otpc->dev, sizeof(*packet), GFP_KERNEL);
		if (!packet)
			return -ENOMEM;

		packet->id = id++;
		packet->offset = word_pos;
		INIT_LIST_HEAD(&packet->list);
		list_add_tail(&packet->list, &otpc->packets);

		/* Count size by adding header and paload sizes. */
		*size += 4 * (payload_size + 1);
		/* Next word: this packet (header, payload) position + 1. */
		word_pos += payload_size + 2;

		npackets++;
	}

	otpc->npackets = npackets;

	return 0;
}

static struct nvmem_config mchp_nvmem_config = {
	.name = MCHP_OTPC_NAME,
	.type = NVMEM_TYPE_OTP,
	.read_only = true,
	.word_size = 4,
	.stride = 4,
	.reg_read = mchp_otpc_read,
};

static int mchp_otpc_probe(struct platform_device *pdev)
{
	struct nvmem_device *nvmem;
	struct mchp_otpc *otpc;
	u32 size;
	int ret;

	otpc = devm_kzalloc(&pdev->dev, sizeof(*otpc), GFP_KERNEL);
	if (!otpc)
		return -ENOMEM;

	otpc->base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(otpc->base))
		return PTR_ERR(otpc->base);

	otpc->dev = &pdev->dev;
	ret = mchp_otpc_init_packets_list(otpc, &size);
	if (ret)
		return ret;

	mchp_nvmem_config.dev = otpc->dev;
	mchp_nvmem_config.size = size;
	mchp_nvmem_config.priv = otpc;
	nvmem = devm_nvmem_register(&pdev->dev, &mchp_nvmem_config);

	return PTR_ERR_OR_ZERO(nvmem);
}

static const struct of_device_id __maybe_unused mchp_otpc_ids[] = {
	{ .compatible = "microchip,sama7g5-otpc", },
	{ },
};
MODULE_DEVICE_TABLE(of, mchp_otpc_ids);

static struct platform_driver mchp_otpc_driver = {
	.probe = mchp_otpc_probe,
	.driver = {
		.name = MCHP_OTPC_NAME,
		.of_match_table = of_match_ptr(mchp_otpc_ids),
	},
};
module_platform_driver(mchp_otpc_driver);

MODULE_AUTHOR("Claudiu Beznea <claudiu.beznea@microchip.com>");
MODULE_DESCRIPTION("Microchip SAMA7G5 OTPC driver");
MODULE_LICENSE("GPL");
