root/drivers/bus/hisi_lpc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wait_lpc_idle
  2. hisi_lpc_target_in
  3. hisi_lpc_target_out
  4. hisi_lpc_pio_to_addr
  5. hisi_lpc_comm_in
  6. hisi_lpc_comm_out
  7. hisi_lpc_comm_ins
  8. hisi_lpc_comm_outs
  9. hisi_lpc_acpi_xlat_io_res
  10. hisi_lpc_acpi_set_io_res
  11. hisi_lpc_acpi_remove_subdev
  12. hisi_lpc_acpi_remove
  13. hisi_lpc_acpi_probe
  14. hisi_lpc_acpi_probe
  15. hisi_lpc_acpi_remove
  16. hisi_lpc_probe
  17. hisi_lpc_remove

   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 
  31 struct lpc_cycle_para {
  32         unsigned int opflags;
  33         unsigned int csize; /* data length of each operation */
  34 };
  35 
  36 struct 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 
  77 static int wait_lpc_idle(unsigned char *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  */
 101 static 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  */
 154 static 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 
 193 static 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  */
 207 static 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         u32 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  */
 240 static 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 
 248         if (!lpcdev || !dwidth || dwidth > LPC_MAX_DWIDTH)
 249                 return;
 250 
 251         val = cpu_to_le32(val);
 252 
 253         buf = (const unsigned char *)&val;
 254         addr = hisi_lpc_pio_to_addr(lpcdev, pio);
 255 
 256         iopara.opflags = FG_INCRADDR_LPC;
 257         iopara.csize = dwidth;
 258 
 259         hisi_lpc_target_out(lpcdev, &iopara, addr, buf, dwidth);
 260 }
 261 
 262 /*
 263  * hisi_lpc_comm_ins - input the data in the buffer in multiple operations
 264  * @hostdata: pointer to the device information relevant to LPC controller
 265  * @pio: the target I/O port address
 266  * @buffer: a buffer where read/input data bytes are stored
 267  * @dwidth: the data width required writing to the target I/O port
 268  * @count: how many data units whose length is dwidth will be read
 269  *
 270  * When success, the data read back is stored in buffer pointed by buffer.
 271  * Returns 0 on success, -errno otherwise.
 272  */
 273 static u32 hisi_lpc_comm_ins(void *hostdata, unsigned long pio, void *buffer,
 274                              size_t dwidth, unsigned int count)
 275 {
 276         struct hisi_lpc_dev *lpcdev = hostdata;
 277         unsigned char *buf = buffer;
 278         struct lpc_cycle_para iopara;
 279         unsigned long addr;
 280 
 281         if (!lpcdev || !buf || !count || !dwidth || dwidth > LPC_MAX_DWIDTH)
 282                 return -EINVAL;
 283 
 284         iopara.opflags = 0;
 285         if (dwidth > 1)
 286                 iopara.opflags |= FG_INCRADDR_LPC;
 287         iopara.csize = dwidth;
 288 
 289         addr = hisi_lpc_pio_to_addr(lpcdev, pio);
 290 
 291         do {
 292                 int ret;
 293 
 294                 ret = hisi_lpc_target_in(lpcdev, &iopara, addr, buf, dwidth);
 295                 if (ret)
 296                         return ret;
 297                 buf += dwidth;
 298         } while (--count);
 299 
 300         return 0;
 301 }
 302 
 303 /*
 304  * hisi_lpc_comm_outs - output the data in the buffer in multiple operations
 305  * @hostdata: pointer to the device information relevant to LPC controller
 306  * @pio: the target I/O port address
 307  * @buffer: a buffer where write/output data bytes are stored
 308  * @dwidth: the data width required writing to the target I/O port
 309  * @count: how many data units whose length is dwidth will be written
 310  */
 311 static void hisi_lpc_comm_outs(void *hostdata, unsigned long pio,
 312                                const void *buffer, size_t dwidth,
 313                                unsigned int count)
 314 {
 315         struct hisi_lpc_dev *lpcdev = hostdata;
 316         struct lpc_cycle_para iopara;
 317         const unsigned char *buf = buffer;
 318         unsigned long addr;
 319 
 320         if (!lpcdev || !buf || !count || !dwidth || dwidth > LPC_MAX_DWIDTH)
 321                 return;
 322 
 323         iopara.opflags = 0;
 324         if (dwidth > 1)
 325                 iopara.opflags |= FG_INCRADDR_LPC;
 326         iopara.csize = dwidth;
 327 
 328         addr = hisi_lpc_pio_to_addr(lpcdev, pio);
 329         do {
 330                 if (hisi_lpc_target_out(lpcdev, &iopara, addr, buf, dwidth))
 331                         break;
 332                 buf += dwidth;
 333         } while (--count);
 334 }
 335 
 336 static const struct logic_pio_host_ops hisi_lpc_ops = {
 337         .in = hisi_lpc_comm_in,
 338         .out = hisi_lpc_comm_out,
 339         .ins = hisi_lpc_comm_ins,
 340         .outs = hisi_lpc_comm_outs,
 341 };
 342 
 343 #ifdef CONFIG_ACPI
 344 static int hisi_lpc_acpi_xlat_io_res(struct acpi_device *adev,
 345                                      struct acpi_device *host,
 346                                      struct resource *res)
 347 {
 348         unsigned long sys_port;
 349         resource_size_t len = resource_size(res);
 350 
 351         sys_port = logic_pio_trans_hwaddr(&host->fwnode, res->start, len);
 352         if (sys_port == ~0UL)
 353                 return -EFAULT;
 354 
 355         res->start = sys_port;
 356         res->end = sys_port + len;
 357 
 358         return 0;
 359 }
 360 
 361 /*
 362  * hisi_lpc_acpi_set_io_res - set the resources for a child
 363  * @child: the device node to be updated the I/O resource
 364  * @hostdev: the device node associated with host controller
 365  * @res: double pointer to be set to the address of translated resources
 366  * @num_res: pointer to variable to hold the number of translated resources
 367  *
 368  * Returns 0 when successful, and a negative value for failure.
 369  *
 370  * For a given host controller, each child device will have an associated
 371  * host-relative address resource.  This function will return the translated
 372  * logical PIO addresses for each child devices resources.
 373  */
 374 static int hisi_lpc_acpi_set_io_res(struct device *child,
 375                                     struct device *hostdev,
 376                                     const struct resource **res, int *num_res)
 377 {
 378         struct acpi_device *adev;
 379         struct acpi_device *host;
 380         struct resource_entry *rentry;
 381         LIST_HEAD(resource_list);
 382         struct resource *resources;
 383         int count;
 384         int i;
 385 
 386         if (!child || !hostdev)
 387                 return -EINVAL;
 388 
 389         host = to_acpi_device(hostdev);
 390         adev = to_acpi_device(child);
 391 
 392         if (!adev->status.present) {
 393                 dev_dbg(child, "device is not present\n");
 394                 return -EIO;
 395         }
 396 
 397         if (acpi_device_enumerated(adev)) {
 398                 dev_dbg(child, "has been enumerated\n");
 399                 return -EIO;
 400         }
 401 
 402         /*
 403          * The following code segment to retrieve the resources is common to
 404          * acpi_create_platform_device(), so consider a common helper function
 405          * in future.
 406          */
 407         count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
 408         if (count <= 0) {
 409                 dev_dbg(child, "failed to get resources\n");
 410                 return count ? count : -EIO;
 411         }
 412 
 413         resources = devm_kcalloc(hostdev, count, sizeof(*resources),
 414                                  GFP_KERNEL);
 415         if (!resources) {
 416                 dev_warn(hostdev, "could not allocate memory for %d resources\n",
 417                          count);
 418                 acpi_dev_free_resource_list(&resource_list);
 419                 return -ENOMEM;
 420         }
 421         count = 0;
 422         list_for_each_entry(rentry, &resource_list, node)
 423                 resources[count++] = *rentry->res;
 424 
 425         acpi_dev_free_resource_list(&resource_list);
 426 
 427         /* translate the I/O resources */
 428         for (i = 0; i < count; i++) {
 429                 int ret;
 430 
 431                 if (!(resources[i].flags & IORESOURCE_IO))
 432                         continue;
 433                 ret = hisi_lpc_acpi_xlat_io_res(adev, host, &resources[i]);
 434                 if (ret) {
 435                         dev_err(child, "translate IO range %pR failed (%d)\n",
 436                                 &resources[i], ret);
 437                         return ret;
 438                 }
 439         }
 440         *res = resources;
 441         *num_res = count;
 442 
 443         return 0;
 444 }
 445 
 446 static int hisi_lpc_acpi_remove_subdev(struct device *dev, void *unused)
 447 {
 448         platform_device_unregister(to_platform_device(dev));
 449         return 0;
 450 }
 451 
 452 struct hisi_lpc_acpi_cell {
 453         const char *hid;
 454         const char *name;
 455         void *pdata;
 456         size_t pdata_size;
 457 };
 458 
 459 static void hisi_lpc_acpi_remove(struct device *hostdev)
 460 {
 461         struct acpi_device *adev = ACPI_COMPANION(hostdev);
 462         struct acpi_device *child;
 463 
 464         device_for_each_child(hostdev, NULL, hisi_lpc_acpi_remove_subdev);
 465 
 466         list_for_each_entry(child, &adev->children, node)
 467                 acpi_device_clear_enumerated(child);
 468 }
 469 
 470 /*
 471  * hisi_lpc_acpi_probe - probe children for ACPI FW
 472  * @hostdev: LPC host device pointer
 473  *
 474  * Returns 0 when successful, and a negative value for failure.
 475  *
 476  * Create a platform device per child, fixing up the resources
 477  * from bus addresses to Logical PIO addresses.
 478  *
 479  */
 480 static int hisi_lpc_acpi_probe(struct device *hostdev)
 481 {
 482         struct acpi_device *adev = ACPI_COMPANION(hostdev);
 483         struct acpi_device *child;
 484         int ret;
 485 
 486         /* Only consider the children of the host */
 487         list_for_each_entry(child, &adev->children, node) {
 488                 const char *hid = acpi_device_hid(child);
 489                 const struct hisi_lpc_acpi_cell *cell;
 490                 struct platform_device *pdev;
 491                 const struct resource *res;
 492                 bool found = false;
 493                 int num_res;
 494 
 495                 ret = hisi_lpc_acpi_set_io_res(&child->dev, &adev->dev, &res,
 496                                                &num_res);
 497                 if (ret) {
 498                         dev_warn(hostdev, "set resource fail (%d)\n", ret);
 499                         goto fail;
 500                 }
 501 
 502                 cell = (struct hisi_lpc_acpi_cell []){
 503                         /* ipmi */
 504                         {
 505                                 .hid = "IPI0001",
 506                                 .name = "hisi-lpc-ipmi",
 507                         },
 508                         /* 8250-compatible uart */
 509                         {
 510                                 .hid = "HISI1031",
 511                                 .name = "serial8250",
 512                                 .pdata = (struct plat_serial8250_port []) {
 513                                         {
 514                                                 .iobase = res->start,
 515                                                 .uartclk = 1843200,
 516                                                 .iotype = UPIO_PORT,
 517                                                 .flags = UPF_BOOT_AUTOCONF,
 518                                         },
 519                                         {}
 520                                 },
 521                                 .pdata_size = 2 *
 522                                         sizeof(struct plat_serial8250_port),
 523                         },
 524                         {}
 525                 };
 526 
 527                 for (; cell && cell->name; cell++) {
 528                         if (!strcmp(cell->hid, hid)) {
 529                                 found = true;
 530                                 break;
 531                         }
 532                 }
 533 
 534                 if (!found) {
 535                         dev_warn(hostdev,
 536                                  "could not find cell for child device (%s), discarding\n",
 537                                  hid);
 538                         continue;
 539                 }
 540 
 541                 pdev = platform_device_alloc(cell->name, PLATFORM_DEVID_AUTO);
 542                 if (!pdev) {
 543                         ret = -ENOMEM;
 544                         goto fail;
 545                 }
 546 
 547                 pdev->dev.parent = hostdev;
 548                 ACPI_COMPANION_SET(&pdev->dev, child);
 549 
 550                 ret = platform_device_add_resources(pdev, res, num_res);
 551                 if (ret)
 552                         goto fail;
 553 
 554                 ret = platform_device_add_data(pdev, cell->pdata,
 555                                                cell->pdata_size);
 556                 if (ret)
 557                         goto fail;
 558 
 559                 ret = platform_device_add(pdev);
 560                 if (ret)
 561                         goto fail;
 562 
 563                 acpi_device_set_enumerated(child);
 564         }
 565 
 566         return 0;
 567 
 568 fail:
 569         hisi_lpc_acpi_remove(hostdev);
 570         return ret;
 571 }
 572 
 573 static const struct acpi_device_id hisi_lpc_acpi_match[] = {
 574         {"HISI0191"},
 575         {}
 576 };
 577 #else
 578 static int hisi_lpc_acpi_probe(struct device *dev)
 579 {
 580         return -ENODEV;
 581 }
 582 
 583 static void hisi_lpc_acpi_remove(struct device *hostdev)
 584 {
 585 }
 586 #endif // CONFIG_ACPI
 587 
 588 /*
 589  * hisi_lpc_probe - the probe callback function for hisi lpc host,
 590  *                 will finish all the initialization.
 591  * @pdev: the platform device corresponding to hisi lpc host
 592  *
 593  * Returns 0 on success, non-zero on fail.
 594  */
 595 static int hisi_lpc_probe(struct platform_device *pdev)
 596 {
 597         struct device *dev = &pdev->dev;
 598         struct acpi_device *acpi_device = ACPI_COMPANION(dev);
 599         struct logic_pio_hwaddr *range;
 600         struct hisi_lpc_dev *lpcdev;
 601         resource_size_t io_end;
 602         struct resource *res;
 603         int ret;
 604 
 605         lpcdev = devm_kzalloc(dev, sizeof(*lpcdev), GFP_KERNEL);
 606         if (!lpcdev)
 607                 return -ENOMEM;
 608 
 609         spin_lock_init(&lpcdev->cycle_lock);
 610 
 611         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 612         lpcdev->membase = devm_ioremap_resource(dev, res);
 613         if (IS_ERR(lpcdev->membase))
 614                 return PTR_ERR(lpcdev->membase);
 615 
 616         range = devm_kzalloc(dev, sizeof(*range), GFP_KERNEL);
 617         if (!range)
 618                 return -ENOMEM;
 619 
 620         range->fwnode = dev->fwnode;
 621         range->flags = LOGIC_PIO_INDIRECT;
 622         range->size = PIO_INDIRECT_SIZE;
 623         range->hostdata = lpcdev;
 624         range->ops = &hisi_lpc_ops;
 625         lpcdev->io_host = range;
 626 
 627         ret = logic_pio_register_range(range);
 628         if (ret) {
 629                 dev_err(dev, "register IO range failed (%d)!\n", ret);
 630                 return ret;
 631         }
 632 
 633         /* register the LPC host PIO resources */
 634         if (acpi_device)
 635                 ret = hisi_lpc_acpi_probe(dev);
 636         else
 637                 ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
 638         if (ret) {
 639                 logic_pio_unregister_range(range);
 640                 return ret;
 641         }
 642 
 643         dev_set_drvdata(dev, lpcdev);
 644 
 645         io_end = lpcdev->io_host->io_start + lpcdev->io_host->size;
 646         dev_info(dev, "registered range [%pa - %pa]\n",
 647                  &lpcdev->io_host->io_start, &io_end);
 648 
 649         return ret;
 650 }
 651 
 652 static int hisi_lpc_remove(struct platform_device *pdev)
 653 {
 654         struct device *dev = &pdev->dev;
 655         struct acpi_device *acpi_device = ACPI_COMPANION(dev);
 656         struct hisi_lpc_dev *lpcdev = dev_get_drvdata(dev);
 657         struct logic_pio_hwaddr *range = lpcdev->io_host;
 658 
 659         if (acpi_device)
 660                 hisi_lpc_acpi_remove(dev);
 661         else
 662                 of_platform_depopulate(dev);
 663 
 664         logic_pio_unregister_range(range);
 665 
 666         return 0;
 667 }
 668 
 669 static const struct of_device_id hisi_lpc_of_match[] = {
 670         { .compatible = "hisilicon,hip06-lpc", },
 671         { .compatible = "hisilicon,hip07-lpc", },
 672         {}
 673 };
 674 
 675 static struct platform_driver hisi_lpc_driver = {
 676         .driver = {
 677                 .name           = DRV_NAME,
 678                 .of_match_table = hisi_lpc_of_match,
 679                 .acpi_match_table = ACPI_PTR(hisi_lpc_acpi_match),
 680         },
 681         .probe = hisi_lpc_probe,
 682         .remove = hisi_lpc_remove,
 683 };
 684 builtin_platform_driver(hisi_lpc_driver);

/* [<][>][^][v][top][bottom][index][help] */