linux/drivers/bus/hisi_lpc.c
<<
>>
Prefs
   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);
 707