0001
0002
0003
0004
0005
0006
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
0026
0027
0028
0029 #define FG_INCRADDR_LPC 0x02
0030
0031 struct lpc_cycle_para {
0032 unsigned int opflags;
0033 unsigned int csize;
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
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
0051 #define LPC_REG_CMD 0x14
0052 #define LPC_REG_CMD_OP BIT(0)
0053 #define LPC_REG_CMD_SAMEADDR BIT(3)
0054 #define LPC_REG_ADDR 0x20
0055 #define LPC_REG_WDATA 0x24
0056 #define LPC_REG_RDATA 0x28
0057
0058
0059 #define LPC_NSEC_PERWAIT 100
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 #define LPC_MAX_WAITCNT 1300
0073
0074
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
0093
0094
0095
0096
0097
0098
0099
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;
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
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
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
0146
0147
0148
0149
0150
0151
0152
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
0167 cmd_word = LPC_REG_CMD_OP;
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
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
0201
0202
0203
0204
0205
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
0233
0234
0235
0236
0237
0238
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
0263
0264
0265
0266
0267
0268
0269
0270
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
0304
0305
0306
0307
0308
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
0362
0363
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
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
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
0416
0417
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
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
0506 {
0507 .hid = "IPI0001",
0508 .name = "hisi-lpc-ipmi",
0509 },
0510
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
0572
0573
0574
0575
0576
0577
0578
0579
0580 static int hisi_lpc_acpi_probe(struct device *hostdev)
0581 {
0582 int ret;
0583
0584
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
0607
0608
0609
0610
0611
0612
0613
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
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);