cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hisi-spmi-controller.c (9901B)


      1// SPDX-License-Identifier: GPL-2.0
      2
      3#include <linux/delay.h>
      4#include <linux/err.h>
      5#include <linux/interrupt.h>
      6#include <linux/io.h>
      7#include <linux/kernel.h>
      8#include <linux/module.h>
      9#include <linux/of.h>
     10#include <linux/platform_device.h>
     11#include <linux/seq_file.h>
     12#include <linux/slab.h>
     13#include <linux/spmi.h>
     14
     15/*
     16 * SPMI register addr
     17 */
     18#define SPMI_CHANNEL_OFFSET				0x0300
     19#define SPMI_SLAVE_OFFSET				0x20
     20
     21#define SPMI_APB_SPMI_CMD_BASE_ADDR			0x0100
     22
     23#define SPMI_APB_SPMI_WDATA0_BASE_ADDR			0x0104
     24#define SPMI_APB_SPMI_WDATA1_BASE_ADDR			0x0108
     25#define SPMI_APB_SPMI_WDATA2_BASE_ADDR			0x010c
     26#define SPMI_APB_SPMI_WDATA3_BASE_ADDR			0x0110
     27
     28#define SPMI_APB_SPMI_STATUS_BASE_ADDR			0x0200
     29
     30#define SPMI_APB_SPMI_RDATA0_BASE_ADDR			0x0204
     31#define SPMI_APB_SPMI_RDATA1_BASE_ADDR			0x0208
     32#define SPMI_APB_SPMI_RDATA2_BASE_ADDR			0x020c
     33#define SPMI_APB_SPMI_RDATA3_BASE_ADDR			0x0210
     34
     35#define SPMI_PER_DATAREG_BYTE				4
     36/*
     37 * SPMI cmd register
     38 */
     39#define SPMI_APB_SPMI_CMD_EN				BIT(31)
     40#define SPMI_APB_SPMI_CMD_TYPE_OFFSET			24
     41#define SPMI_APB_SPMI_CMD_LENGTH_OFFSET			20
     42#define SPMI_APB_SPMI_CMD_SLAVEID_OFFSET		16
     43#define SPMI_APB_SPMI_CMD_ADDR_OFFSET			0
     44
     45/* Command Opcodes */
     46
     47enum spmi_controller_cmd_op_code {
     48	SPMI_CMD_REG_ZERO_WRITE = 0,
     49	SPMI_CMD_REG_WRITE = 1,
     50	SPMI_CMD_REG_READ = 2,
     51	SPMI_CMD_EXT_REG_WRITE = 3,
     52	SPMI_CMD_EXT_REG_READ = 4,
     53	SPMI_CMD_EXT_REG_WRITE_L = 5,
     54	SPMI_CMD_EXT_REG_READ_L = 6,
     55	SPMI_CMD_REG_RESET = 7,
     56	SPMI_CMD_REG_SLEEP = 8,
     57	SPMI_CMD_REG_SHUTDOWN = 9,
     58	SPMI_CMD_REG_WAKEUP = 10,
     59};
     60
     61/*
     62 * SPMI status register
     63 */
     64#define SPMI_APB_TRANS_DONE			BIT(0)
     65#define SPMI_APB_TRANS_FAIL			BIT(2)
     66
     67/* Command register fields */
     68#define SPMI_CONTROLLER_CMD_MAX_BYTE_COUNT	16
     69
     70/* Maximum number of support PMIC peripherals */
     71#define SPMI_CONTROLLER_TIMEOUT_US		1000
     72#define SPMI_CONTROLLER_MAX_TRANS_BYTES		16
     73
     74struct spmi_controller_dev {
     75	struct spmi_controller	*controller;
     76	struct device		*dev;
     77	void __iomem		*base;
     78	spinlock_t		lock;
     79	u32			channel;
     80};
     81
     82static int spmi_controller_wait_for_done(struct device *dev,
     83					 struct spmi_controller_dev *ctrl_dev,
     84					 void __iomem *base, u8 sid, u16 addr)
     85{
     86	u32 timeout = SPMI_CONTROLLER_TIMEOUT_US;
     87	u32 status, offset;
     88
     89	offset  = SPMI_APB_SPMI_STATUS_BASE_ADDR;
     90	offset += SPMI_CHANNEL_OFFSET * ctrl_dev->channel + SPMI_SLAVE_OFFSET * sid;
     91
     92	do {
     93		status = readl(base + offset);
     94
     95		if (status & SPMI_APB_TRANS_DONE) {
     96			if (status & SPMI_APB_TRANS_FAIL) {
     97				dev_err(dev, "%s: transaction failed (0x%x)\n",
     98					__func__, status);
     99				return -EIO;
    100			}
    101			dev_dbg(dev, "%s: status 0x%x\n", __func__, status);
    102			return 0;
    103		}
    104		udelay(1);
    105	} while (timeout--);
    106
    107	dev_err(dev, "%s: timeout, status 0x%x\n", __func__, status);
    108	return -ETIMEDOUT;
    109}
    110
    111static int spmi_read_cmd(struct spmi_controller *ctrl,
    112			 u8 opc, u8 slave_id, u16 slave_addr, u8 *__buf, size_t bc)
    113{
    114	struct spmi_controller_dev *spmi_controller = dev_get_drvdata(&ctrl->dev);
    115	u32 chnl_ofst = SPMI_CHANNEL_OFFSET * spmi_controller->channel;
    116	unsigned long flags;
    117	u8 *buf = __buf;
    118	u32 cmd, data;
    119	int rc;
    120	u8 op_code, i;
    121
    122	if (bc > SPMI_CONTROLLER_MAX_TRANS_BYTES) {
    123		dev_err(&ctrl->dev,
    124			"spmi_controller supports 1..%d bytes per trans, but:%zu requested\n",
    125			SPMI_CONTROLLER_MAX_TRANS_BYTES, bc);
    126		return  -EINVAL;
    127	}
    128
    129	switch (opc) {
    130	case SPMI_CMD_READ:
    131		op_code = SPMI_CMD_REG_READ;
    132		break;
    133	case SPMI_CMD_EXT_READ:
    134		op_code = SPMI_CMD_EXT_REG_READ;
    135		break;
    136	case SPMI_CMD_EXT_READL:
    137		op_code = SPMI_CMD_EXT_REG_READ_L;
    138		break;
    139	default:
    140		dev_err(&ctrl->dev, "invalid read cmd 0x%x\n", opc);
    141		return -EINVAL;
    142	}
    143
    144	cmd = SPMI_APB_SPMI_CMD_EN |
    145	     (op_code << SPMI_APB_SPMI_CMD_TYPE_OFFSET) |
    146	     ((bc - 1) << SPMI_APB_SPMI_CMD_LENGTH_OFFSET) |
    147	     ((slave_id & 0xf) << SPMI_APB_SPMI_CMD_SLAVEID_OFFSET) |  /* slvid */
    148	     ((slave_addr & 0xffff)  << SPMI_APB_SPMI_CMD_ADDR_OFFSET); /* slave_addr */
    149
    150	spin_lock_irqsave(&spmi_controller->lock, flags);
    151
    152	writel(cmd, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_CMD_BASE_ADDR);
    153
    154	rc = spmi_controller_wait_for_done(&ctrl->dev, spmi_controller,
    155					   spmi_controller->base, slave_id, slave_addr);
    156	if (rc)
    157		goto done;
    158
    159	for (i = 0; bc > i * SPMI_PER_DATAREG_BYTE; i++) {
    160		data = readl(spmi_controller->base + chnl_ofst +
    161			     SPMI_SLAVE_OFFSET * slave_id +
    162			     SPMI_APB_SPMI_RDATA0_BASE_ADDR +
    163			     i * SPMI_PER_DATAREG_BYTE);
    164		data = be32_to_cpu((__be32 __force)data);
    165		if ((bc - i * SPMI_PER_DATAREG_BYTE) >> 2) {
    166			memcpy(buf, &data, sizeof(data));
    167			buf += sizeof(data);
    168		} else {
    169			memcpy(buf, &data, bc % SPMI_PER_DATAREG_BYTE);
    170			buf += (bc % SPMI_PER_DATAREG_BYTE);
    171		}
    172	}
    173
    174done:
    175	spin_unlock_irqrestore(&spmi_controller->lock, flags);
    176	if (rc)
    177		dev_err(&ctrl->dev,
    178			"spmi read wait timeout op:0x%x slave_id:%d slave_addr:0x%x bc:%zu\n",
    179			opc, slave_id, slave_addr, bc + 1);
    180	else
    181		dev_dbg(&ctrl->dev, "%s: id:%d slave_addr:0x%x, read value: %*ph\n",
    182			__func__, slave_id, slave_addr, (int)bc, __buf);
    183
    184	return rc;
    185}
    186
    187static int spmi_write_cmd(struct spmi_controller *ctrl,
    188			  u8 opc, u8 slave_id, u16 slave_addr, const u8 *__buf, size_t bc)
    189{
    190	struct spmi_controller_dev *spmi_controller = dev_get_drvdata(&ctrl->dev);
    191	u32 chnl_ofst = SPMI_CHANNEL_OFFSET * spmi_controller->channel;
    192	const u8 *buf = __buf;
    193	unsigned long flags;
    194	u32 cmd, data;
    195	int rc;
    196	u8 op_code, i;
    197
    198	if (bc > SPMI_CONTROLLER_MAX_TRANS_BYTES) {
    199		dev_err(&ctrl->dev,
    200			"spmi_controller supports 1..%d bytes per trans, but:%zu requested\n",
    201			SPMI_CONTROLLER_MAX_TRANS_BYTES, bc);
    202		return  -EINVAL;
    203	}
    204
    205	switch (opc) {
    206	case SPMI_CMD_WRITE:
    207		op_code = SPMI_CMD_REG_WRITE;
    208		break;
    209	case SPMI_CMD_EXT_WRITE:
    210		op_code = SPMI_CMD_EXT_REG_WRITE;
    211		break;
    212	case SPMI_CMD_EXT_WRITEL:
    213		op_code = SPMI_CMD_EXT_REG_WRITE_L;
    214		break;
    215	default:
    216		dev_err(&ctrl->dev, "invalid write cmd 0x%x\n", opc);
    217		return -EINVAL;
    218	}
    219
    220	cmd = SPMI_APB_SPMI_CMD_EN |
    221	      (op_code << SPMI_APB_SPMI_CMD_TYPE_OFFSET) |
    222	      ((bc - 1) << SPMI_APB_SPMI_CMD_LENGTH_OFFSET) |
    223	      ((slave_id & 0xf) << SPMI_APB_SPMI_CMD_SLAVEID_OFFSET) |
    224	      ((slave_addr & 0xffff)  << SPMI_APB_SPMI_CMD_ADDR_OFFSET);
    225
    226	/* Write data to FIFOs */
    227	spin_lock_irqsave(&spmi_controller->lock, flags);
    228
    229	for (i = 0; bc > i * SPMI_PER_DATAREG_BYTE; i++) {
    230		data = 0;
    231		if ((bc - i * SPMI_PER_DATAREG_BYTE) >> 2) {
    232			memcpy(&data, buf, sizeof(data));
    233			buf += sizeof(data);
    234		} else {
    235			memcpy(&data, buf, bc % SPMI_PER_DATAREG_BYTE);
    236			buf += (bc % SPMI_PER_DATAREG_BYTE);
    237		}
    238
    239		writel((u32 __force)cpu_to_be32(data),
    240		       spmi_controller->base + chnl_ofst +
    241		       SPMI_APB_SPMI_WDATA0_BASE_ADDR +
    242		       SPMI_PER_DATAREG_BYTE * i);
    243	}
    244
    245	/* Start the transaction */
    246	writel(cmd, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_CMD_BASE_ADDR);
    247
    248	rc = spmi_controller_wait_for_done(&ctrl->dev, spmi_controller,
    249					   spmi_controller->base, slave_id,
    250					   slave_addr);
    251	spin_unlock_irqrestore(&spmi_controller->lock, flags);
    252
    253	if (rc)
    254		dev_err(&ctrl->dev, "spmi write wait timeout op:0x%x slave_id:%d slave_addr:0x%x bc:%zu\n",
    255			opc, slave_id, slave_addr, bc);
    256	else
    257		dev_dbg(&ctrl->dev, "%s: id:%d slave_addr:0x%x, wrote value: %*ph\n",
    258			__func__, slave_id, slave_addr, (int)bc, __buf);
    259
    260	return rc;
    261}
    262
    263static int spmi_controller_probe(struct platform_device *pdev)
    264{
    265	struct spmi_controller_dev *spmi_controller;
    266	struct spmi_controller *ctrl;
    267	struct resource *iores;
    268	int ret;
    269
    270	ctrl = spmi_controller_alloc(&pdev->dev, sizeof(*spmi_controller));
    271	if (!ctrl) {
    272		dev_err(&pdev->dev, "can not allocate spmi_controller data\n");
    273		return -ENOMEM;
    274	}
    275	spmi_controller = spmi_controller_get_drvdata(ctrl);
    276	spmi_controller->controller = ctrl;
    277
    278	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    279	if (!iores) {
    280		dev_err(&pdev->dev, "can not get resource!\n");
    281		ret = -EINVAL;
    282		goto err_put_controller;
    283	}
    284
    285	spmi_controller->base = devm_ioremap(&pdev->dev, iores->start,
    286					     resource_size(iores));
    287	if (!spmi_controller->base) {
    288		dev_err(&pdev->dev, "can not remap base addr!\n");
    289		ret = -EADDRNOTAVAIL;
    290		goto err_put_controller;
    291	}
    292
    293	ret = of_property_read_u32(pdev->dev.of_node, "hisilicon,spmi-channel",
    294				   &spmi_controller->channel);
    295	if (ret) {
    296		dev_err(&pdev->dev, "can not get channel\n");
    297		ret = -ENODEV;
    298		goto err_put_controller;
    299	}
    300
    301	platform_set_drvdata(pdev, spmi_controller);
    302	dev_set_drvdata(&ctrl->dev, spmi_controller);
    303
    304	spin_lock_init(&spmi_controller->lock);
    305
    306	ctrl->nr = spmi_controller->channel;
    307	ctrl->dev.parent = pdev->dev.parent;
    308	ctrl->dev.of_node = of_node_get(pdev->dev.of_node);
    309
    310	/* Callbacks */
    311	ctrl->read_cmd = spmi_read_cmd;
    312	ctrl->write_cmd = spmi_write_cmd;
    313
    314	ret = spmi_controller_add(ctrl);
    315	if (ret) {
    316		dev_err(&pdev->dev, "spmi_controller_add failed with error %d!\n", ret);
    317		goto err_put_controller;
    318	}
    319
    320	return 0;
    321
    322err_put_controller:
    323	spmi_controller_put(ctrl);
    324	return ret;
    325}
    326
    327static int spmi_del_controller(struct platform_device *pdev)
    328{
    329	struct spmi_controller *ctrl = platform_get_drvdata(pdev);
    330
    331	spmi_controller_remove(ctrl);
    332	spmi_controller_put(ctrl);
    333	return 0;
    334}
    335
    336static const struct of_device_id spmi_controller_match_table[] = {
    337	{
    338		.compatible = "hisilicon,kirin970-spmi-controller",
    339	},
    340	{}
    341};
    342MODULE_DEVICE_TABLE(of, spmi_controller_match_table);
    343
    344static struct platform_driver spmi_controller_driver = {
    345	.probe		= spmi_controller_probe,
    346	.remove		= spmi_del_controller,
    347	.driver		= {
    348		.name	= "hisi_spmi_controller",
    349		.of_match_table = spmi_controller_match_table,
    350	},
    351};
    352
    353static int __init spmi_controller_init(void)
    354{
    355	return platform_driver_register(&spmi_controller_driver);
    356}
    357postcore_initcall(spmi_controller_init);
    358
    359static void __exit spmi_controller_exit(void)
    360{
    361	platform_driver_unregister(&spmi_controller_driver);
    362}
    363module_exit(spmi_controller_exit);
    364
    365MODULE_LICENSE("GPL v2");
    366MODULE_VERSION("1.0");
    367MODULE_ALIAS("platform:spmi_controller");