Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Copyright (C) 2017 Hisilicon Limited, All Rights Reserved.
0004  * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
0005  * Author: Zou Rongrong <zourongrong@huawei.com>
0006  * Author: John Garry <john.garry@huawei.com>
0007  */
0008 
0009 #include <linux/acpi.h>
0010 #include <linux/console.h>
0011 #include <linux/delay.h>
0012 #include <linux/io.h>
0013 #include <linux/logic_pio.h>
0014 #include <linux/module.h>
0015 #include <linux/of.h>
0016 #include <linux/of_address.h>
0017 #include <linux/of_platform.h>
0018 #include <linux/pci.h>
0019 #include <linux/serial_8250.h>
0020 #include <linux/slab.h>
0021 
0022 #define DRV_NAME "hisi-lpc"
0023 
0024 /*
0025  * Setting this bit means each IO operation will target a different port
0026  * address; 0 means repeated IO operations will use the same port,
0027  * such as BT.
0028  */
0029 #define FG_INCRADDR_LPC     0x02
0030 
0031 struct lpc_cycle_para {
0032     unsigned int opflags;
0033     unsigned int csize; /* data length of each operation */
0034 };
0035 
0036 struct hisi_lpc_dev {
0037     spinlock_t cycle_lock;
0038     void __iomem  *membase;
0039     struct logic_pio_hwaddr *io_host;
0040 };
0041 
0042 /* The max IO cycle counts supported is four per operation at maximum */
0043 #define LPC_MAX_DWIDTH  4
0044 
0045 #define LPC_REG_STARTUP_SIGNAL      0x00
0046 #define LPC_REG_STARTUP_SIGNAL_START    BIT(0)
0047 #define LPC_REG_OP_STATUS       0x04
0048 #define LPC_REG_OP_STATUS_IDLE      BIT(0)
0049 #define LPC_REG_OP_STATUS_FINISHED  BIT(1)
0050 #define LPC_REG_OP_LEN          0x10 /* LPC cycles count per start */
0051 #define LPC_REG_CMD         0x14
0052 #define LPC_REG_CMD_OP          BIT(0) /* 0: read, 1: write */
0053 #define LPC_REG_CMD_SAMEADDR        BIT(3)
0054 #define LPC_REG_ADDR            0x20 /* target address */
0055 #define LPC_REG_WDATA           0x24 /* write FIFO */
0056 #define LPC_REG_RDATA           0x28 /* read FIFO */
0057 
0058 /* The minimal nanosecond interval for each query on LPC cycle status */
0059 #define LPC_NSEC_PERWAIT    100
0060 
0061 /*
0062  * The maximum waiting time is about 128us.  It is specific for stream I/O,
0063  * such as ins.
0064  *
0065  * The fastest IO cycle time is about 390ns, but the worst case will wait
0066  * for extra 256 lpc clocks, so (256 + 13) * 30ns = 8 us. The maximum burst
0067  * cycles is 16. So, the maximum waiting time is about 128us under worst
0068  * case.
0069  *
0070  * Choose 1300 as the maximum.
0071  */
0072 #define LPC_MAX_WAITCNT     1300
0073 
0074 /* About 10us. This is specific for single IO operations, such as inb */
0075 #define LPC_PEROP_WAITCNT   100
0076 
0077 static int wait_lpc_idle(void __iomem *mbase, unsigned int waitcnt)
0078 {
0079     u32 status;
0080 
0081     do {
0082         status = readl(mbase + LPC_REG_OP_STATUS);
0083         if (status & LPC_REG_OP_STATUS_IDLE)
0084             return (status & LPC_REG_OP_STATUS_FINISHED) ? 0 : -EIO;
0085         ndelay(LPC_NSEC_PERWAIT);
0086     } while (--waitcnt);
0087 
0088     return -ETIME;
0089 }
0090 
0091 /*
0092  * hisi_lpc_target_in - trigger a series of LPC cycles for read operation
0093  * @lpcdev: pointer to hisi lpc device
0094  * @para: some parameters used to control the lpc I/O operations
0095  * @addr: the lpc I/O target port address
0096  * @buf: where the read back data is stored
0097  * @opcnt: how many I/O operations required, i.e. data width
0098  *
0099  * Returns 0 on success, non-zero on fail.
0100  */
0101 static int hisi_lpc_target_in(struct hisi_lpc_dev *lpcdev,
0102                   struct lpc_cycle_para *para, unsigned long addr,
0103                   unsigned char *buf, unsigned long opcnt)
0104 {
0105     unsigned int cmd_word;
0106     unsigned int waitcnt;
0107     unsigned long flags;
0108     int ret;
0109 
0110     if (!buf || !opcnt || !para || !para->csize || !lpcdev)
0111         return -EINVAL;
0112 
0113     cmd_word = 0; /* IO mode, Read */
0114     waitcnt = LPC_PEROP_WAITCNT;
0115     if (!(para->opflags & FG_INCRADDR_LPC)) {
0116         cmd_word |= LPC_REG_CMD_SAMEADDR;
0117         waitcnt = LPC_MAX_WAITCNT;
0118     }
0119 
0120     /* whole operation must be atomic */
0121     spin_lock_irqsave(&lpcdev->cycle_lock, flags);
0122 
0123     writel_relaxed(opcnt, lpcdev->membase + LPC_REG_OP_LEN);
0124     writel_relaxed(cmd_word, lpcdev->membase + LPC_REG_CMD);
0125     writel_relaxed(addr, lpcdev->membase + LPC_REG_ADDR);
0126 
0127     writel(LPC_REG_STARTUP_SIGNAL_START,
0128            lpcdev->membase + LPC_REG_STARTUP_SIGNAL);
0129 
0130     /* whether the operation is finished */
0131     ret = wait_lpc_idle(lpcdev->membase, waitcnt);
0132     if (ret) {
0133         spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
0134         return ret;
0135     }
0136 
0137     readsb(lpcdev->membase + LPC_REG_RDATA, buf, opcnt);
0138 
0139     spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
0140 
0141     return 0;
0142 }
0143 
0144 /*
0145  * hisi_lpc_target_out - trigger a series of LPC cycles for write operation
0146  * @lpcdev: pointer to hisi lpc device
0147  * @para: some parameters used to control the lpc I/O operations
0148  * @addr: the lpc I/O target port address
0149  * @buf: where the data to be written is stored
0150  * @opcnt: how many I/O operations required, i.e. data width
0151  *
0152  * Returns 0 on success, non-zero on fail.
0153  */
0154 static int hisi_lpc_target_out(struct hisi_lpc_dev *lpcdev,
0155                    struct lpc_cycle_para *para, unsigned long addr,
0156                    const unsigned char *buf, unsigned long opcnt)
0157 {
0158     unsigned int waitcnt;
0159     unsigned long flags;
0160     u32 cmd_word;
0161     int ret;
0162 
0163     if (!buf || !opcnt || !para || !lpcdev)
0164         return -EINVAL;
0165 
0166     /* default is increasing address */
0167     cmd_word = LPC_REG_CMD_OP; /* IO mode, write */
0168     waitcnt = LPC_PEROP_WAITCNT;
0169     if (!(para->opflags & FG_INCRADDR_LPC)) {
0170         cmd_word |= LPC_REG_CMD_SAMEADDR;
0171         waitcnt = LPC_MAX_WAITCNT;
0172     }
0173 
0174     spin_lock_irqsave(&lpcdev->cycle_lock, flags);
0175 
0176     writel_relaxed(opcnt, lpcdev->membase + LPC_REG_OP_LEN);
0177     writel_relaxed(cmd_word, lpcdev->membase + LPC_REG_CMD);
0178     writel_relaxed(addr, lpcdev->membase + LPC_REG_ADDR);
0179 
0180     writesb(lpcdev->membase + LPC_REG_WDATA, buf, opcnt);
0181 
0182     writel(LPC_REG_STARTUP_SIGNAL_START,
0183            lpcdev->membase + LPC_REG_STARTUP_SIGNAL);
0184 
0185     /* whether the operation is finished */
0186     ret = wait_lpc_idle(lpcdev->membase, waitcnt);
0187 
0188     spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
0189 
0190     return ret;
0191 }
0192 
0193 static unsigned long hisi_lpc_pio_to_addr(struct hisi_lpc_dev *lpcdev,
0194                       unsigned long pio)
0195 {
0196     return pio - lpcdev->io_host->io_start + lpcdev->io_host->hw_start;
0197 }
0198 
0199 /*
0200  * hisi_lpc_comm_in - input the data in a single operation
0201  * @hostdata: pointer to the device information relevant to LPC controller
0202  * @pio: the target I/O port address
0203  * @dwidth: the data length required to read from the target I/O port
0204  *
0205  * When success, data is returned. Otherwise, ~0 is returned.
0206  */
0207 static u32 hisi_lpc_comm_in(void *hostdata, unsigned long pio, size_t dwidth)
0208 {
0209     struct hisi_lpc_dev *lpcdev = hostdata;
0210     struct lpc_cycle_para iopara;
0211     unsigned long addr;
0212     __le32 rd_data = 0;
0213     int ret;
0214 
0215     if (!lpcdev || !dwidth || dwidth > LPC_MAX_DWIDTH)
0216         return ~0;
0217 
0218     addr = hisi_lpc_pio_to_addr(lpcdev, pio);
0219 
0220     iopara.opflags = FG_INCRADDR_LPC;
0221     iopara.csize = dwidth;
0222 
0223     ret = hisi_lpc_target_in(lpcdev, &iopara, addr,
0224                  (unsigned char *)&rd_data, dwidth);
0225     if (ret)
0226         return ~0;
0227 
0228     return le32_to_cpu(rd_data);
0229 }
0230 
0231 /*
0232  * hisi_lpc_comm_out - output the data in a single operation
0233  * @hostdata: pointer to the device information relevant to LPC controller
0234  * @pio: the target I/O port address
0235  * @val: a value to be output from caller, maximum is four bytes
0236  * @dwidth: the data width required writing to the target I/O port
0237  *
0238  * This function corresponds to out(b,w,l) only.
0239  */
0240 static void hisi_lpc_comm_out(void *hostdata, unsigned long pio,
0241                   u32 val, size_t dwidth)
0242 {
0243     struct hisi_lpc_dev *lpcdev = hostdata;
0244     struct lpc_cycle_para iopara;
0245     const unsigned char *buf;
0246     unsigned long addr;
0247     __le32 _val = cpu_to_le32(val);
0248 
0249     if (!lpcdev || !dwidth || dwidth > LPC_MAX_DWIDTH)
0250         return;
0251 
0252     buf = (const unsigned char *)&_val;
0253     addr = hisi_lpc_pio_to_addr(lpcdev, pio);
0254 
0255     iopara.opflags = FG_INCRADDR_LPC;
0256     iopara.csize = dwidth;
0257 
0258     hisi_lpc_target_out(lpcdev, &iopara, addr, buf, dwidth);
0259 }
0260 
0261 /*
0262  * hisi_lpc_comm_ins - input the data in the buffer in multiple operations
0263  * @hostdata: pointer to the device information relevant to LPC controller
0264  * @pio: the target I/O port address
0265  * @buffer: a buffer where read/input data bytes are stored
0266  * @dwidth: the data width required writing to the target I/O port
0267  * @count: how many data units whose length is dwidth will be read
0268  *
0269  * When success, the data read back is stored in buffer pointed by buffer.
0270  * Returns 0 on success, -errno otherwise.
0271  */
0272 static u32 hisi_lpc_comm_ins(void *hostdata, unsigned long pio, void *buffer,
0273                  size_t dwidth, unsigned int count)
0274 {
0275     struct hisi_lpc_dev *lpcdev = hostdata;
0276     unsigned char *buf = buffer;
0277     struct lpc_cycle_para iopara;
0278     unsigned long addr;
0279 
0280     if (!lpcdev || !buf || !count || !dwidth || dwidth > LPC_MAX_DWIDTH)
0281         return -EINVAL;
0282 
0283     iopara.opflags = 0;
0284     if (dwidth > 1)
0285         iopara.opflags |= FG_INCRADDR_LPC;
0286     iopara.csize = dwidth;
0287 
0288     addr = hisi_lpc_pio_to_addr(lpcdev, pio);
0289 
0290     do {
0291         int ret;
0292 
0293         ret = hisi_lpc_target_in(lpcdev, &iopara, addr, buf, dwidth);
0294         if (ret)
0295             return ret;
0296         buf += dwidth;
0297     } while (--count);
0298 
0299     return 0;
0300 }
0301 
0302 /*
0303  * hisi_lpc_comm_outs - output the data in the buffer in multiple operations
0304  * @hostdata: pointer to the device information relevant to LPC controller
0305  * @pio: the target I/O port address
0306  * @buffer: a buffer where write/output data bytes are stored
0307  * @dwidth: the data width required writing to the target I/O port
0308  * @count: how many data units whose length is dwidth will be written
0309  */
0310 static void hisi_lpc_comm_outs(void *hostdata, unsigned long pio,
0311                    const void *buffer, size_t dwidth,
0312                    unsigned int count)
0313 {
0314     struct hisi_lpc_dev *lpcdev = hostdata;
0315     struct lpc_cycle_para iopara;
0316     const unsigned char *buf = buffer;
0317     unsigned long addr;
0318 
0319     if (!lpcdev || !buf || !count || !dwidth || dwidth > LPC_MAX_DWIDTH)
0320         return;
0321 
0322     iopara.opflags = 0;
0323     if (dwidth > 1)
0324         iopara.opflags |= FG_INCRADDR_LPC;
0325     iopara.csize = dwidth;
0326 
0327     addr = hisi_lpc_pio_to_addr(lpcdev, pio);
0328     do {
0329         if (hisi_lpc_target_out(lpcdev, &iopara, addr, buf, dwidth))
0330             break;
0331         buf += dwidth;
0332     } while (--count);
0333 }
0334 
0335 static const struct logic_pio_host_ops hisi_lpc_ops = {
0336     .in = hisi_lpc_comm_in,
0337     .out = hisi_lpc_comm_out,
0338     .ins = hisi_lpc_comm_ins,
0339     .outs = hisi_lpc_comm_outs,
0340 };
0341 
0342 #ifdef CONFIG_ACPI
0343 static int hisi_lpc_acpi_xlat_io_res(struct acpi_device *adev,
0344                      struct acpi_device *host,
0345                      struct resource *res)
0346 {
0347     unsigned long sys_port;
0348     resource_size_t len = resource_size(res);
0349 
0350     sys_port = logic_pio_trans_hwaddr(&host->fwnode, res->start, len);
0351     if (sys_port == ~0UL)
0352         return -EFAULT;
0353 
0354     res->start = sys_port;
0355     res->end = sys_port + len;
0356 
0357     return 0;
0358 }
0359 
0360 /*
0361  * Released firmware describes the IO port max address as 0x3fff, which is
0362  * the max host bus address. Fixup to a proper range. This will probably
0363  * never be fixed in firmware.
0364  */
0365 static void hisi_lpc_acpi_fixup_child_resource(struct device *hostdev,
0366                            struct resource *r)
0367 {
0368     if (r->end != 0x3fff)
0369         return;
0370 
0371     if (r->start == 0xe4)
0372         r->end = 0xe4 + 0x04 - 1;
0373     else if (r->start == 0x2f8)
0374         r->end = 0x2f8 + 0x08 - 1;
0375     else
0376         dev_warn(hostdev, "unrecognised resource %pR to fixup, ignoring\n",
0377              r);
0378 }
0379 
0380 /*
0381  * hisi_lpc_acpi_set_io_res - set the resources for a child
0382  * @adev: ACPI companion of the device node to be updated the I/O resource
0383  * @hostdev: the device node associated with host controller
0384  * @res: double pointer to be set to the address of translated resources
0385  * @num_res: pointer to variable to hold the number of translated resources
0386  *
0387  * Returns 0 when successful, and a negative value for failure.
0388  *
0389  * For a given host controller, each child device will have an associated
0390  * host-relative address resource.  This function will return the translated
0391  * logical PIO addresses for each child devices resources.
0392  */
0393 static int hisi_lpc_acpi_set_io_res(struct acpi_device *adev,
0394                     struct device *hostdev,
0395                     const struct resource **res, int *num_res)
0396 {
0397     struct acpi_device *host = to_acpi_device(adev->dev.parent);
0398     struct resource_entry *rentry;
0399     LIST_HEAD(resource_list);
0400     struct resource *resources;
0401     int count;
0402     int i;
0403 
0404     if (!adev->status.present) {
0405         dev_dbg(&adev->dev, "device is not present\n");
0406         return -EIO;
0407     }
0408 
0409     if (acpi_device_enumerated(adev)) {
0410         dev_dbg(&adev->dev, "has been enumerated\n");
0411         return -EIO;
0412     }
0413 
0414     /*
0415      * The following code segment to retrieve the resources is common to
0416      * acpi_create_platform_device(), so consider a common helper function
0417      * in future.
0418      */
0419     count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
0420     if (count <= 0) {
0421         dev_dbg(&adev->dev, "failed to get resources\n");
0422         return count ? count : -EIO;
0423     }
0424 
0425     resources = devm_kcalloc(hostdev, count, sizeof(*resources),
0426                  GFP_KERNEL);
0427     if (!resources) {
0428         dev_warn(hostdev, "could not allocate memory for %d resources\n",
0429              count);
0430         acpi_dev_free_resource_list(&resource_list);
0431         return -ENOMEM;
0432     }
0433     count = 0;
0434     list_for_each_entry(rentry, &resource_list, node) {
0435         resources[count] = *rentry->res;
0436         hisi_lpc_acpi_fixup_child_resource(hostdev, &resources[count]);
0437         count++;
0438     }
0439 
0440     acpi_dev_free_resource_list(&resource_list);
0441 
0442     /* translate the I/O resources */
0443     for (i = 0; i < count; i++) {
0444         int ret;
0445 
0446         if (!(resources[i].flags & IORESOURCE_IO))
0447             continue;
0448         ret = hisi_lpc_acpi_xlat_io_res(adev, host, &resources[i]);
0449         if (ret) {
0450             dev_err(&adev->dev, "translate IO range %pR failed (%d)\n",
0451                 &resources[i], ret);
0452             return ret;
0453         }
0454     }
0455     *res = resources;
0456     *num_res = count;
0457 
0458     return 0;
0459 }
0460 
0461 static int hisi_lpc_acpi_remove_subdev(struct device *dev, void *unused)
0462 {
0463     platform_device_unregister(to_platform_device(dev));
0464     return 0;
0465 }
0466 
0467 static int hisi_lpc_acpi_clear_enumerated(struct acpi_device *adev, void *not_used)
0468 {
0469     acpi_device_clear_enumerated(adev);
0470     return 0;
0471 }
0472 
0473 struct hisi_lpc_acpi_cell {
0474     const char *hid;
0475     const char *name;
0476     void *pdata;
0477     size_t pdata_size;
0478 };
0479 
0480 static void hisi_lpc_acpi_remove(struct device *hostdev)
0481 {
0482     device_for_each_child(hostdev, NULL, hisi_lpc_acpi_remove_subdev);
0483     acpi_dev_for_each_child(ACPI_COMPANION(hostdev),
0484                 hisi_lpc_acpi_clear_enumerated, NULL);
0485 }
0486 
0487 static int hisi_lpc_acpi_add_child(struct acpi_device *child, void *data)
0488 {
0489     const char *hid = acpi_device_hid(child);
0490     struct device *hostdev = data;
0491     const struct hisi_lpc_acpi_cell *cell;
0492     struct platform_device *pdev;
0493     const struct resource *res;
0494     bool found = false;
0495     int num_res;
0496     int ret;
0497 
0498     ret = hisi_lpc_acpi_set_io_res(child, hostdev, &res, &num_res);
0499     if (ret) {
0500         dev_warn(hostdev, "set resource fail (%d)\n", ret);
0501         return ret;
0502     }
0503 
0504     cell = (struct hisi_lpc_acpi_cell []){
0505         /* ipmi */
0506         {
0507             .hid = "IPI0001",
0508             .name = "hisi-lpc-ipmi",
0509         },
0510         /* 8250-compatible uart */
0511         {
0512             .hid = "HISI1031",
0513             .name = "serial8250",
0514             .pdata = (struct plat_serial8250_port []) {
0515                 {
0516                     .iobase = res->start,
0517                     .uartclk = 1843200,
0518                     .iotype = UPIO_PORT,
0519                     .flags = UPF_BOOT_AUTOCONF,
0520                 },
0521                 {}
0522             },
0523             .pdata_size = 2 *
0524                 sizeof(struct plat_serial8250_port),
0525         },
0526         {}
0527     };
0528 
0529     for (; cell && cell->name; cell++) {
0530         if (!strcmp(cell->hid, hid)) {
0531             found = true;
0532             break;
0533         }
0534     }
0535 
0536     if (!found) {
0537         dev_warn(hostdev,
0538              "could not find cell for child device (%s), discarding\n",
0539              hid);
0540         return 0;
0541     }
0542 
0543     pdev = platform_device_alloc(cell->name, PLATFORM_DEVID_AUTO);
0544     if (!pdev)
0545         return -ENOMEM;
0546 
0547     pdev->dev.parent = hostdev;
0548     ACPI_COMPANION_SET(&pdev->dev, child);
0549 
0550     ret = platform_device_add_resources(pdev, res, num_res);
0551     if (ret)
0552         goto fail;
0553 
0554     ret = platform_device_add_data(pdev, cell->pdata, cell->pdata_size);
0555     if (ret)
0556         goto fail;
0557 
0558     ret = platform_device_add(pdev);
0559     if (ret)
0560         goto fail;
0561 
0562     acpi_device_set_enumerated(child);
0563     return 0;
0564 
0565 fail:
0566     platform_device_put(pdev);
0567     return ret;
0568 }
0569 
0570 /*
0571  * hisi_lpc_acpi_probe - probe children for ACPI FW
0572  * @hostdev: LPC host device pointer
0573  *
0574  * Returns 0 when successful, and a negative value for failure.
0575  *
0576  * Create a platform device per child, fixing up the resources
0577  * from bus addresses to Logical PIO addresses.
0578  *
0579  */
0580 static int hisi_lpc_acpi_probe(struct device *hostdev)
0581 {
0582     int ret;
0583 
0584     /* Only consider the children of the host */
0585     ret = acpi_dev_for_each_child(ACPI_COMPANION(hostdev),
0586                       hisi_lpc_acpi_add_child, hostdev);
0587     if (ret)
0588         hisi_lpc_acpi_remove(hostdev);
0589 
0590     return ret;
0591 }
0592 
0593 static const struct acpi_device_id hisi_lpc_acpi_match[] = {
0594     {"HISI0191"},
0595     {}
0596 };
0597 #else
0598 static int hisi_lpc_acpi_probe(struct device *dev)
0599 {
0600     return -ENODEV;
0601 }
0602 
0603 static void hisi_lpc_acpi_remove(struct device *hostdev)
0604 {
0605 }
0606 #endif // CONFIG_ACPI
0607 
0608 /*
0609  * hisi_lpc_probe - the probe callback function for hisi lpc host,
0610  *         will finish all the initialization.
0611  * @pdev: the platform device corresponding to hisi lpc host
0612  *
0613  * Returns 0 on success, non-zero on fail.
0614  */
0615 static int hisi_lpc_probe(struct platform_device *pdev)
0616 {
0617     struct device *dev = &pdev->dev;
0618     struct acpi_device *acpi_device = ACPI_COMPANION(dev);
0619     struct logic_pio_hwaddr *range;
0620     struct hisi_lpc_dev *lpcdev;
0621     resource_size_t io_end;
0622     struct resource *res;
0623     int ret;
0624 
0625     lpcdev = devm_kzalloc(dev, sizeof(*lpcdev), GFP_KERNEL);
0626     if (!lpcdev)
0627         return -ENOMEM;
0628 
0629     spin_lock_init(&lpcdev->cycle_lock);
0630 
0631     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0632     lpcdev->membase = devm_ioremap_resource(dev, res);
0633     if (IS_ERR(lpcdev->membase))
0634         return PTR_ERR(lpcdev->membase);
0635 
0636     range = devm_kzalloc(dev, sizeof(*range), GFP_KERNEL);
0637     if (!range)
0638         return -ENOMEM;
0639 
0640     range->fwnode = dev->fwnode;
0641     range->flags = LOGIC_PIO_INDIRECT;
0642     range->size = PIO_INDIRECT_SIZE;
0643     range->hostdata = lpcdev;
0644     range->ops = &hisi_lpc_ops;
0645     lpcdev->io_host = range;
0646 
0647     ret = logic_pio_register_range(range);
0648     if (ret) {
0649         dev_err(dev, "register IO range failed (%d)!\n", ret);
0650         return ret;
0651     }
0652 
0653     /* register the LPC host PIO resources */
0654     if (acpi_device)
0655         ret = hisi_lpc_acpi_probe(dev);
0656     else
0657         ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
0658     if (ret) {
0659         logic_pio_unregister_range(range);
0660         return ret;
0661     }
0662 
0663     dev_set_drvdata(dev, lpcdev);
0664 
0665     io_end = lpcdev->io_host->io_start + lpcdev->io_host->size;
0666     dev_info(dev, "registered range [%pa - %pa]\n",
0667          &lpcdev->io_host->io_start, &io_end);
0668 
0669     return ret;
0670 }
0671 
0672 static int hisi_lpc_remove(struct platform_device *pdev)
0673 {
0674     struct device *dev = &pdev->dev;
0675     struct acpi_device *acpi_device = ACPI_COMPANION(dev);
0676     struct hisi_lpc_dev *lpcdev = dev_get_drvdata(dev);
0677     struct logic_pio_hwaddr *range = lpcdev->io_host;
0678 
0679     if (acpi_device)
0680         hisi_lpc_acpi_remove(dev);
0681     else
0682         of_platform_depopulate(dev);
0683 
0684     logic_pio_unregister_range(range);
0685 
0686     return 0;
0687 }
0688 
0689 static const struct of_device_id hisi_lpc_of_match[] = {
0690     { .compatible = "hisilicon,hip06-lpc", },
0691     { .compatible = "hisilicon,hip07-lpc", },
0692     {}
0693 };
0694 
0695 static struct platform_driver hisi_lpc_driver = {
0696     .driver = {
0697         .name           = DRV_NAME,
0698         .of_match_table = hisi_lpc_of_match,
0699         .acpi_match_table = ACPI_PTR(hisi_lpc_acpi_match),
0700     },
0701     .probe = hisi_lpc_probe,
0702     .remove = hisi_lpc_remove,
0703 };
0704 builtin_platform_driver(hisi_lpc_driver);