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_lpc.c (18450B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
      4 * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
      5 * Author: Zou Rongrong <zourongrong@huawei.com>
      6 * Author: John Garry <john.garry@huawei.com>
      7 */
      8
      9#include <linux/acpi.h>
     10#include <linux/console.h>
     11#include <linux/delay.h>
     12#include <linux/io.h>
     13#include <linux/logic_pio.h>
     14#include <linux/module.h>
     15#include <linux/of.h>
     16#include <linux/of_address.h>
     17#include <linux/of_platform.h>
     18#include <linux/pci.h>
     19#include <linux/serial_8250.h>
     20#include <linux/slab.h>
     21
     22#define DRV_NAME "hisi-lpc"
     23
     24/*
     25 * Setting this bit means each IO operation will target a different port
     26 * address; 0 means repeated IO operations will use the same port,
     27 * such as BT.
     28 */
     29#define FG_INCRADDR_LPC		0x02
     30
     31struct lpc_cycle_para {
     32	unsigned int opflags;
     33	unsigned int csize; /* data length of each operation */
     34};
     35
     36struct hisi_lpc_dev {
     37	spinlock_t cycle_lock;
     38	void __iomem  *membase;
     39	struct logic_pio_hwaddr *io_host;
     40};
     41
     42/* The max IO cycle counts supported is four per operation at maximum */
     43#define LPC_MAX_DWIDTH	4
     44
     45#define LPC_REG_STARTUP_SIGNAL		0x00
     46#define LPC_REG_STARTUP_SIGNAL_START	BIT(0)
     47#define LPC_REG_OP_STATUS		0x04
     48#define LPC_REG_OP_STATUS_IDLE		BIT(0)
     49#define LPC_REG_OP_STATUS_FINISHED	BIT(1)
     50#define LPC_REG_OP_LEN			0x10 /* LPC cycles count per start */
     51#define LPC_REG_CMD			0x14
     52#define LPC_REG_CMD_OP			BIT(0) /* 0: read, 1: write */
     53#define LPC_REG_CMD_SAMEADDR		BIT(3)
     54#define LPC_REG_ADDR			0x20 /* target address */
     55#define LPC_REG_WDATA			0x24 /* write FIFO */
     56#define LPC_REG_RDATA			0x28 /* read FIFO */
     57
     58/* The minimal nanosecond interval for each query on LPC cycle status */
     59#define LPC_NSEC_PERWAIT	100
     60
     61/*
     62 * The maximum waiting time is about 128us.  It is specific for stream I/O,
     63 * such as ins.
     64 *
     65 * The fastest IO cycle time is about 390ns, but the worst case will wait
     66 * for extra 256 lpc clocks, so (256 + 13) * 30ns = 8 us. The maximum burst
     67 * cycles is 16. So, the maximum waiting time is about 128us under worst
     68 * case.
     69 *
     70 * Choose 1300 as the maximum.
     71 */
     72#define LPC_MAX_WAITCNT		1300
     73
     74/* About 10us. This is specific for single IO operations, such as inb */
     75#define LPC_PEROP_WAITCNT	100
     76
     77static int wait_lpc_idle(void __iomem *mbase, unsigned int waitcnt)
     78{
     79	u32 status;
     80
     81	do {
     82		status = readl(mbase + LPC_REG_OP_STATUS);
     83		if (status & LPC_REG_OP_STATUS_IDLE)
     84			return (status & LPC_REG_OP_STATUS_FINISHED) ? 0 : -EIO;
     85		ndelay(LPC_NSEC_PERWAIT);
     86	} while (--waitcnt);
     87
     88	return -ETIME;
     89}
     90
     91/*
     92 * hisi_lpc_target_in - trigger a series of LPC cycles for read operation
     93 * @lpcdev: pointer to hisi lpc device
     94 * @para: some parameters used to control the lpc I/O operations
     95 * @addr: the lpc I/O target port address
     96 * @buf: where the read back data is stored
     97 * @opcnt: how many I/O operations required, i.e. data width
     98 *
     99 * Returns 0 on success, non-zero on fail.
    100 */
    101static int hisi_lpc_target_in(struct hisi_lpc_dev *lpcdev,
    102			      struct lpc_cycle_para *para, unsigned long addr,
    103			      unsigned char *buf, unsigned long opcnt)
    104{
    105	unsigned int cmd_word;
    106	unsigned int waitcnt;
    107	unsigned long flags;
    108	int ret;
    109
    110	if (!buf || !opcnt || !para || !para->csize || !lpcdev)
    111		return -EINVAL;
    112
    113	cmd_word = 0; /* IO mode, Read */
    114	waitcnt = LPC_PEROP_WAITCNT;
    115	if (!(para->opflags & FG_INCRADDR_LPC)) {
    116		cmd_word |= LPC_REG_CMD_SAMEADDR;
    117		waitcnt = LPC_MAX_WAITCNT;
    118	}
    119
    120	/* whole operation must be atomic */
    121	spin_lock_irqsave(&lpcdev->cycle_lock, flags);
    122
    123	writel_relaxed(opcnt, lpcdev->membase + LPC_REG_OP_LEN);
    124	writel_relaxed(cmd_word, lpcdev->membase + LPC_REG_CMD);
    125	writel_relaxed(addr, lpcdev->membase + LPC_REG_ADDR);
    126
    127	writel(LPC_REG_STARTUP_SIGNAL_START,
    128	       lpcdev->membase + LPC_REG_STARTUP_SIGNAL);
    129
    130	/* whether the operation is finished */
    131	ret = wait_lpc_idle(lpcdev->membase, waitcnt);
    132	if (ret) {
    133		spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
    134		return ret;
    135	}
    136
    137	readsb(lpcdev->membase + LPC_REG_RDATA, buf, opcnt);
    138
    139	spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
    140
    141	return 0;
    142}
    143
    144/*
    145 * hisi_lpc_target_out - trigger a series of LPC cycles for write operation
    146 * @lpcdev: pointer to hisi lpc device
    147 * @para: some parameters used to control the lpc I/O operations
    148 * @addr: the lpc I/O target port address
    149 * @buf: where the data to be written is stored
    150 * @opcnt: how many I/O operations required, i.e. data width
    151 *
    152 * Returns 0 on success, non-zero on fail.
    153 */
    154static int hisi_lpc_target_out(struct hisi_lpc_dev *lpcdev,
    155			       struct lpc_cycle_para *para, unsigned long addr,
    156			       const unsigned char *buf, unsigned long opcnt)
    157{
    158	unsigned int waitcnt;
    159	unsigned long flags;
    160	u32 cmd_word;
    161	int ret;
    162
    163	if (!buf || !opcnt || !para || !lpcdev)
    164		return -EINVAL;
    165
    166	/* default is increasing address */
    167	cmd_word = LPC_REG_CMD_OP; /* IO mode, write */
    168	waitcnt = LPC_PEROP_WAITCNT;
    169	if (!(para->opflags & FG_INCRADDR_LPC)) {
    170		cmd_word |= LPC_REG_CMD_SAMEADDR;
    171		waitcnt = LPC_MAX_WAITCNT;
    172	}
    173
    174	spin_lock_irqsave(&lpcdev->cycle_lock, flags);
    175
    176	writel_relaxed(opcnt, lpcdev->membase + LPC_REG_OP_LEN);
    177	writel_relaxed(cmd_word, lpcdev->membase + LPC_REG_CMD);
    178	writel_relaxed(addr, lpcdev->membase + LPC_REG_ADDR);
    179
    180	writesb(lpcdev->membase + LPC_REG_WDATA, buf, opcnt);
    181
    182	writel(LPC_REG_STARTUP_SIGNAL_START,
    183	       lpcdev->membase + LPC_REG_STARTUP_SIGNAL);
    184
    185	/* whether the operation is finished */
    186	ret = wait_lpc_idle(lpcdev->membase, waitcnt);
    187
    188	spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
    189
    190	return ret;
    191}
    192
    193static unsigned long hisi_lpc_pio_to_addr(struct hisi_lpc_dev *lpcdev,
    194					  unsigned long pio)
    195{
    196	return pio - lpcdev->io_host->io_start + lpcdev->io_host->hw_start;
    197}
    198
    199/*
    200 * hisi_lpc_comm_in - input the data in a single operation
    201 * @hostdata: pointer to the device information relevant to LPC controller
    202 * @pio: the target I/O port address
    203 * @dwidth: the data length required to read from the target I/O port
    204 *
    205 * When success, data is returned. Otherwise, ~0 is returned.
    206 */
    207static u32 hisi_lpc_comm_in(void *hostdata, unsigned long pio, size_t dwidth)
    208{
    209	struct hisi_lpc_dev *lpcdev = hostdata;
    210	struct lpc_cycle_para iopara;
    211	unsigned long addr;
    212	__le32 rd_data = 0;
    213	int ret;
    214
    215	if (!lpcdev || !dwidth || dwidth > LPC_MAX_DWIDTH)
    216		return ~0;
    217
    218	addr = hisi_lpc_pio_to_addr(lpcdev, pio);
    219
    220	iopara.opflags = FG_INCRADDR_LPC;
    221	iopara.csize = dwidth;
    222
    223	ret = hisi_lpc_target_in(lpcdev, &iopara, addr,
    224				 (unsigned char *)&rd_data, dwidth);
    225	if (ret)
    226		return ~0;
    227
    228	return le32_to_cpu(rd_data);
    229}
    230
    231/*
    232 * hisi_lpc_comm_out - output the data in a single operation
    233 * @hostdata: pointer to the device information relevant to LPC controller
    234 * @pio: the target I/O port address
    235 * @val: a value to be output from caller, maximum is four bytes
    236 * @dwidth: the data width required writing to the target I/O port
    237 *
    238 * This function corresponds to out(b,w,l) only.
    239 */
    240static void hisi_lpc_comm_out(void *hostdata, unsigned long pio,
    241			      u32 val, size_t dwidth)
    242{
    243	struct hisi_lpc_dev *lpcdev = hostdata;
    244	struct lpc_cycle_para iopara;
    245	const unsigned char *buf;
    246	unsigned long addr;
    247	__le32 _val = cpu_to_le32(val);
    248
    249	if (!lpcdev || !dwidth || dwidth > LPC_MAX_DWIDTH)
    250		return;
    251
    252	buf = (const unsigned char *)&_val;
    253	addr = hisi_lpc_pio_to_addr(lpcdev, pio);
    254
    255	iopara.opflags = FG_INCRADDR_LPC;
    256	iopara.csize = dwidth;
    257
    258	hisi_lpc_target_out(lpcdev, &iopara, addr, buf, dwidth);
    259}
    260
    261/*
    262 * hisi_lpc_comm_ins - input the data in the buffer in multiple operations
    263 * @hostdata: pointer to the device information relevant to LPC controller
    264 * @pio: the target I/O port address
    265 * @buffer: a buffer where read/input data bytes are stored
    266 * @dwidth: the data width required writing to the target I/O port
    267 * @count: how many data units whose length is dwidth will be read
    268 *
    269 * When success, the data read back is stored in buffer pointed by buffer.
    270 * Returns 0 on success, -errno otherwise.
    271 */
    272static u32 hisi_lpc_comm_ins(void *hostdata, unsigned long pio, void *buffer,
    273			     size_t dwidth, unsigned int count)
    274{
    275	struct hisi_lpc_dev *lpcdev = hostdata;
    276	unsigned char *buf = buffer;
    277	struct lpc_cycle_para iopara;
    278	unsigned long addr;
    279
    280	if (!lpcdev || !buf || !count || !dwidth || dwidth > LPC_MAX_DWIDTH)
    281		return -EINVAL;
    282
    283	iopara.opflags = 0;
    284	if (dwidth > 1)
    285		iopara.opflags |= FG_INCRADDR_LPC;
    286	iopara.csize = dwidth;
    287
    288	addr = hisi_lpc_pio_to_addr(lpcdev, pio);
    289
    290	do {
    291		int ret;
    292
    293		ret = hisi_lpc_target_in(lpcdev, &iopara, addr, buf, dwidth);
    294		if (ret)
    295			return ret;
    296		buf += dwidth;
    297	} while (--count);
    298
    299	return 0;
    300}
    301
    302/*
    303 * hisi_lpc_comm_outs - output the data in the buffer in multiple operations
    304 * @hostdata: pointer to the device information relevant to LPC controller
    305 * @pio: the target I/O port address
    306 * @buffer: a buffer where write/output data bytes are stored
    307 * @dwidth: the data width required writing to the target I/O port
    308 * @count: how many data units whose length is dwidth will be written
    309 */
    310static void hisi_lpc_comm_outs(void *hostdata, unsigned long pio,
    311			       const void *buffer, size_t dwidth,
    312			       unsigned int count)
    313{
    314	struct hisi_lpc_dev *lpcdev = hostdata;
    315	struct lpc_cycle_para iopara;
    316	const unsigned char *buf = buffer;
    317	unsigned long addr;
    318
    319	if (!lpcdev || !buf || !count || !dwidth || dwidth > LPC_MAX_DWIDTH)
    320		return;
    321
    322	iopara.opflags = 0;
    323	if (dwidth > 1)
    324		iopara.opflags |= FG_INCRADDR_LPC;
    325	iopara.csize = dwidth;
    326
    327	addr = hisi_lpc_pio_to_addr(lpcdev, pio);
    328	do {
    329		if (hisi_lpc_target_out(lpcdev, &iopara, addr, buf, dwidth))
    330			break;
    331		buf += dwidth;
    332	} while (--count);
    333}
    334
    335static const struct logic_pio_host_ops hisi_lpc_ops = {
    336	.in = hisi_lpc_comm_in,
    337	.out = hisi_lpc_comm_out,
    338	.ins = hisi_lpc_comm_ins,
    339	.outs = hisi_lpc_comm_outs,
    340};
    341
    342#ifdef CONFIG_ACPI
    343static int hisi_lpc_acpi_xlat_io_res(struct acpi_device *adev,
    344				     struct acpi_device *host,
    345				     struct resource *res)
    346{
    347	unsigned long sys_port;
    348	resource_size_t len = resource_size(res);
    349
    350	sys_port = logic_pio_trans_hwaddr(&host->fwnode, res->start, len);
    351	if (sys_port == ~0UL)
    352		return -EFAULT;
    353
    354	res->start = sys_port;
    355	res->end = sys_port + len;
    356
    357	return 0;
    358}
    359
    360/*
    361 * Released firmware describes the IO port max address as 0x3fff, which is
    362 * the max host bus address. Fixup to a proper range. This will probably
    363 * never be fixed in firmware.
    364 */
    365static void hisi_lpc_acpi_fixup_child_resource(struct device *hostdev,
    366					       struct resource *r)
    367{
    368	if (r->end != 0x3fff)
    369		return;
    370
    371	if (r->start == 0xe4)
    372		r->end = 0xe4 + 0x04 - 1;
    373	else if (r->start == 0x2f8)
    374		r->end = 0x2f8 + 0x08 - 1;
    375	else
    376		dev_warn(hostdev, "unrecognised resource %pR to fixup, ignoring\n",
    377			 r);
    378}
    379
    380/*
    381 * hisi_lpc_acpi_set_io_res - set the resources for a child
    382 * @child: the device node to be updated the I/O resource
    383 * @hostdev: the device node associated with host controller
    384 * @res: double pointer to be set to the address of translated resources
    385 * @num_res: pointer to variable to hold the number of translated resources
    386 *
    387 * Returns 0 when successful, and a negative value for failure.
    388 *
    389 * For a given host controller, each child device will have an associated
    390 * host-relative address resource.  This function will return the translated
    391 * logical PIO addresses for each child devices resources.
    392 */
    393static int hisi_lpc_acpi_set_io_res(struct device *child,
    394				    struct device *hostdev,
    395				    const struct resource **res, int *num_res)
    396{
    397	struct acpi_device *adev;
    398	struct acpi_device *host;
    399	struct resource_entry *rentry;
    400	LIST_HEAD(resource_list);
    401	struct resource *resources;
    402	int count;
    403	int i;
    404
    405	if (!child || !hostdev)
    406		return -EINVAL;
    407
    408	host = to_acpi_device(hostdev);
    409	adev = to_acpi_device(child);
    410
    411	if (!adev->status.present) {
    412		dev_dbg(child, "device is not present\n");
    413		return -EIO;
    414	}
    415
    416	if (acpi_device_enumerated(adev)) {
    417		dev_dbg(child, "has been enumerated\n");
    418		return -EIO;
    419	}
    420
    421	/*
    422	 * The following code segment to retrieve the resources is common to
    423	 * acpi_create_platform_device(), so consider a common helper function
    424	 * in future.
    425	 */
    426	count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
    427	if (count <= 0) {
    428		dev_dbg(child, "failed to get resources\n");
    429		return count ? count : -EIO;
    430	}
    431
    432	resources = devm_kcalloc(hostdev, count, sizeof(*resources),
    433				 GFP_KERNEL);
    434	if (!resources) {
    435		dev_warn(hostdev, "could not allocate memory for %d resources\n",
    436			 count);
    437		acpi_dev_free_resource_list(&resource_list);
    438		return -ENOMEM;
    439	}
    440	count = 0;
    441	list_for_each_entry(rentry, &resource_list, node) {
    442		resources[count] = *rentry->res;
    443		hisi_lpc_acpi_fixup_child_resource(hostdev, &resources[count]);
    444		count++;
    445	}
    446
    447	acpi_dev_free_resource_list(&resource_list);
    448
    449	/* translate the I/O resources */
    450	for (i = 0; i < count; i++) {
    451		int ret;
    452
    453		if (!(resources[i].flags & IORESOURCE_IO))
    454			continue;
    455		ret = hisi_lpc_acpi_xlat_io_res(adev, host, &resources[i]);
    456		if (ret) {
    457			dev_err(child, "translate IO range %pR failed (%d)\n",
    458				&resources[i], ret);
    459			return ret;
    460		}
    461	}
    462	*res = resources;
    463	*num_res = count;
    464
    465	return 0;
    466}
    467
    468static int hisi_lpc_acpi_remove_subdev(struct device *dev, void *unused)
    469{
    470	platform_device_unregister(to_platform_device(dev));
    471	return 0;
    472}
    473
    474struct hisi_lpc_acpi_cell {
    475	const char *hid;
    476	const char *name;
    477	void *pdata;
    478	size_t pdata_size;
    479};
    480
    481static void hisi_lpc_acpi_remove(struct device *hostdev)
    482{
    483	struct acpi_device *adev = ACPI_COMPANION(hostdev);
    484	struct acpi_device *child;
    485
    486	device_for_each_child(hostdev, NULL, hisi_lpc_acpi_remove_subdev);
    487
    488	list_for_each_entry(child, &adev->children, node)
    489		acpi_device_clear_enumerated(child);
    490}
    491
    492/*
    493 * hisi_lpc_acpi_probe - probe children for ACPI FW
    494 * @hostdev: LPC host device pointer
    495 *
    496 * Returns 0 when successful, and a negative value for failure.
    497 *
    498 * Create a platform device per child, fixing up the resources
    499 * from bus addresses to Logical PIO addresses.
    500 *
    501 */
    502static int hisi_lpc_acpi_probe(struct device *hostdev)
    503{
    504	struct acpi_device *adev = ACPI_COMPANION(hostdev);
    505	struct acpi_device *child;
    506	int ret;
    507
    508	/* Only consider the children of the host */
    509	list_for_each_entry(child, &adev->children, node) {
    510		const char *hid = acpi_device_hid(child);
    511		const struct hisi_lpc_acpi_cell *cell;
    512		struct platform_device *pdev;
    513		const struct resource *res;
    514		bool found = false;
    515		int num_res;
    516
    517		ret = hisi_lpc_acpi_set_io_res(&child->dev, &adev->dev, &res,
    518					       &num_res);
    519		if (ret) {
    520			dev_warn(hostdev, "set resource fail (%d)\n", ret);
    521			goto fail;
    522		}
    523
    524		cell = (struct hisi_lpc_acpi_cell []){
    525			/* ipmi */
    526			{
    527				.hid = "IPI0001",
    528				.name = "hisi-lpc-ipmi",
    529			},
    530			/* 8250-compatible uart */
    531			{
    532				.hid = "HISI1031",
    533				.name = "serial8250",
    534				.pdata = (struct plat_serial8250_port []) {
    535					{
    536						.iobase = res->start,
    537						.uartclk = 1843200,
    538						.iotype = UPIO_PORT,
    539						.flags = UPF_BOOT_AUTOCONF,
    540					},
    541					{}
    542				},
    543				.pdata_size = 2 *
    544					sizeof(struct plat_serial8250_port),
    545			},
    546			{}
    547		};
    548
    549		for (; cell && cell->name; cell++) {
    550			if (!strcmp(cell->hid, hid)) {
    551				found = true;
    552				break;
    553			}
    554		}
    555
    556		if (!found) {
    557			dev_warn(hostdev,
    558				 "could not find cell for child device (%s), discarding\n",
    559				 hid);
    560			continue;
    561		}
    562
    563		pdev = platform_device_alloc(cell->name, PLATFORM_DEVID_AUTO);
    564		if (!pdev) {
    565			ret = -ENOMEM;
    566			goto fail;
    567		}
    568
    569		pdev->dev.parent = hostdev;
    570		ACPI_COMPANION_SET(&pdev->dev, child);
    571
    572		ret = platform_device_add_resources(pdev, res, num_res);
    573		if (ret)
    574			goto fail;
    575
    576		ret = platform_device_add_data(pdev, cell->pdata,
    577					       cell->pdata_size);
    578		if (ret)
    579			goto fail;
    580
    581		ret = platform_device_add(pdev);
    582		if (ret)
    583			goto fail;
    584
    585		acpi_device_set_enumerated(child);
    586	}
    587
    588	return 0;
    589
    590fail:
    591	hisi_lpc_acpi_remove(hostdev);
    592	return ret;
    593}
    594
    595static const struct acpi_device_id hisi_lpc_acpi_match[] = {
    596	{"HISI0191"},
    597	{}
    598};
    599#else
    600static int hisi_lpc_acpi_probe(struct device *dev)
    601{
    602	return -ENODEV;
    603}
    604
    605static void hisi_lpc_acpi_remove(struct device *hostdev)
    606{
    607}
    608#endif // CONFIG_ACPI
    609
    610/*
    611 * hisi_lpc_probe - the probe callback function for hisi lpc host,
    612 *		   will finish all the initialization.
    613 * @pdev: the platform device corresponding to hisi lpc host
    614 *
    615 * Returns 0 on success, non-zero on fail.
    616 */
    617static int hisi_lpc_probe(struct platform_device *pdev)
    618{
    619	struct device *dev = &pdev->dev;
    620	struct acpi_device *acpi_device = ACPI_COMPANION(dev);
    621	struct logic_pio_hwaddr *range;
    622	struct hisi_lpc_dev *lpcdev;
    623	resource_size_t io_end;
    624	struct resource *res;
    625	int ret;
    626
    627	lpcdev = devm_kzalloc(dev, sizeof(*lpcdev), GFP_KERNEL);
    628	if (!lpcdev)
    629		return -ENOMEM;
    630
    631	spin_lock_init(&lpcdev->cycle_lock);
    632
    633	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    634	lpcdev->membase = devm_ioremap_resource(dev, res);
    635	if (IS_ERR(lpcdev->membase))
    636		return PTR_ERR(lpcdev->membase);
    637
    638	range = devm_kzalloc(dev, sizeof(*range), GFP_KERNEL);
    639	if (!range)
    640		return -ENOMEM;
    641
    642	range->fwnode = dev->fwnode;
    643	range->flags = LOGIC_PIO_INDIRECT;
    644	range->size = PIO_INDIRECT_SIZE;
    645	range->hostdata = lpcdev;
    646	range->ops = &hisi_lpc_ops;
    647	lpcdev->io_host = range;
    648
    649	ret = logic_pio_register_range(range);
    650	if (ret) {
    651		dev_err(dev, "register IO range failed (%d)!\n", ret);
    652		return ret;
    653	}
    654
    655	/* register the LPC host PIO resources */
    656	if (acpi_device)
    657		ret = hisi_lpc_acpi_probe(dev);
    658	else
    659		ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
    660	if (ret) {
    661		logic_pio_unregister_range(range);
    662		return ret;
    663	}
    664
    665	dev_set_drvdata(dev, lpcdev);
    666
    667	io_end = lpcdev->io_host->io_start + lpcdev->io_host->size;
    668	dev_info(dev, "registered range [%pa - %pa]\n",
    669		 &lpcdev->io_host->io_start, &io_end);
    670
    671	return ret;
    672}
    673
    674static int hisi_lpc_remove(struct platform_device *pdev)
    675{
    676	struct device *dev = &pdev->dev;
    677	struct acpi_device *acpi_device = ACPI_COMPANION(dev);
    678	struct hisi_lpc_dev *lpcdev = dev_get_drvdata(dev);
    679	struct logic_pio_hwaddr *range = lpcdev->io_host;
    680
    681	if (acpi_device)
    682		hisi_lpc_acpi_remove(dev);
    683	else
    684		of_platform_depopulate(dev);
    685
    686	logic_pio_unregister_range(range);
    687
    688	return 0;
    689}
    690
    691static const struct of_device_id hisi_lpc_of_match[] = {
    692	{ .compatible = "hisilicon,hip06-lpc", },
    693	{ .compatible = "hisilicon,hip07-lpc", },
    694	{}
    695};
    696
    697static struct platform_driver hisi_lpc_driver = {
    698	.driver = {
    699		.name           = DRV_NAME,
    700		.of_match_table = hisi_lpc_of_match,
    701		.acpi_match_table = ACPI_PTR(hisi_lpc_acpi_match),
    702	},
    703	.probe = hisi_lpc_probe,
    704	.remove = hisi_lpc_remove,
    705};
    706builtin_platform_driver(hisi_lpc_driver);