| .. | .. |
|---|
| 10 | 10 | |
|---|
| 11 | 11 | #include <linux/clk.h> |
|---|
| 12 | 12 | #include <linux/gpio/consumer.h> |
|---|
| 13 | | -#include <linux/iopoll.h> |
|---|
| 14 | 13 | #include <linux/miscdevice.h> |
|---|
| 15 | 14 | #include <linux/mfd/syscon.h> |
|---|
| 16 | 15 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 82 | 81 | #define PCIE_CLIENT_HOT_RESET_CTRL 0x180 |
|---|
| 83 | 82 | #define PCIE_CLIENT_LTSSM_STATUS 0x300 |
|---|
| 84 | 83 | #define PCIE_CLIENT_INTR_MASK 0x24 |
|---|
| 85 | | -#define PCIE_LTSSM_APP_DLY1_EN BIT(0) |
|---|
| 86 | | -#define PCIE_LTSSM_APP_DLY2_EN BIT(1) |
|---|
| 87 | | -#define PCIE_LTSSM_APP_DLY1_DONE BIT(2) |
|---|
| 88 | | -#define PCIE_LTSSM_APP_DLY2_DONE BIT(3) |
|---|
| 89 | 84 | #define PCIE_LTSSM_ENABLE_ENHANCE BIT(4) |
|---|
| 90 | 85 | #define PCIE_CLIENT_MSI_GEN_CON 0x38 |
|---|
| 91 | 86 | |
|---|
| .. | .. |
|---|
| 111 | 106 | #define PCIE_EP_OBJ_INFO_DRV_VERSION 0x00000001 |
|---|
| 112 | 107 | |
|---|
| 113 | 108 | #define PCIE_BAR_MAX_NUM 6 |
|---|
| 114 | | -#define PCIE_HOTRESET_TMOUT_US 10000 |
|---|
| 115 | 109 | |
|---|
| 116 | 110 | struct rockchip_pcie { |
|---|
| 117 | 111 | struct dw_pcie pci; |
|---|
| .. | .. |
|---|
| 136 | 130 | phys_addr_t dbi_base_physical; |
|---|
| 137 | 131 | struct pcie_ep_obj_info *obj_info; |
|---|
| 138 | 132 | enum pcie_ep_mmap_resource cur_mmap_res; |
|---|
| 139 | | - struct workqueue_struct *hot_rst_wq; |
|---|
| 140 | | - struct work_struct hot_rst_work; |
|---|
| 141 | 133 | }; |
|---|
| 142 | 134 | |
|---|
| 143 | 135 | struct rockchip_pcie_misc_dev { |
|---|
| .. | .. |
|---|
| 207 | 199 | struct device_node *np = dev->of_node; |
|---|
| 208 | 200 | void *addr; |
|---|
| 209 | 201 | struct resource *dbi_base; |
|---|
| 210 | | - struct resource *apb_base; |
|---|
| 211 | 202 | struct device_node *mem; |
|---|
| 212 | 203 | struct resource reg; |
|---|
| 213 | 204 | char name[8]; |
|---|
| .. | .. |
|---|
| 223 | 214 | rockchip->pci.dbi_base = devm_ioremap_resource(dev, dbi_base); |
|---|
| 224 | 215 | if (IS_ERR(rockchip->pci.dbi_base)) |
|---|
| 225 | 216 | return PTR_ERR(rockchip->pci.dbi_base); |
|---|
| 217 | + rockchip->pci.atu_base = rockchip->pci.dbi_base + DEFAULT_DBI_ATU_OFFSET; |
|---|
| 226 | 218 | rockchip->dbi_base_physical = dbi_base->start; |
|---|
| 227 | 219 | |
|---|
| 228 | | - apb_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
|---|
| 229 | | - "pcie-apb"); |
|---|
| 230 | | - if (!apb_base) { |
|---|
| 220 | + rockchip->apb_base = devm_platform_ioremap_resource_byname(pdev, "pcie-apb"); |
|---|
| 221 | + if (!rockchip->apb_base) { |
|---|
| 231 | 222 | dev_err(dev, "get pcie-apb failed\n"); |
|---|
| 232 | 223 | return -ENODEV; |
|---|
| 233 | 224 | } |
|---|
| 234 | | - rockchip->apb_base = devm_ioremap_resource(dev, apb_base); |
|---|
| 235 | | - if (IS_ERR(rockchip->apb_base)) |
|---|
| 236 | | - return PTR_ERR(rockchip->apb_base); |
|---|
| 237 | 225 | |
|---|
| 238 | 226 | rockchip->rst_gpio = devm_gpiod_get_optional(dev, "reset", |
|---|
| 239 | 227 | GPIOD_OUT_HIGH); |
|---|
| .. | .. |
|---|
| 580 | 568 | |
|---|
| 581 | 569 | as_type = DW_PCIE_AS_MEM; |
|---|
| 582 | 570 | |
|---|
| 583 | | - ret = dw_pcie_prog_inbound_atu(pci, free_win, bar, cpu_addr, as_type); |
|---|
| 571 | + ret = dw_pcie_prog_inbound_atu(pci, 0, free_win, bar, cpu_addr, as_type); |
|---|
| 584 | 572 | if (ret < 0) { |
|---|
| 585 | 573 | dev_err(pci->dev, "Failed to program IB window\n"); |
|---|
| 586 | 574 | return ret; |
|---|
| .. | .. |
|---|
| 598 | 586 | |
|---|
| 599 | 587 | /* LTSSM EN ctrl mode */ |
|---|
| 600 | 588 | val = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_HOT_RESET_CTRL); |
|---|
| 601 | | - val |= (PCIE_LTSSM_ENABLE_ENHANCE | PCIE_LTSSM_APP_DLY2_EN) | |
|---|
| 602 | | - ((PCIE_LTSSM_ENABLE_ENHANCE | PCIE_LTSSM_APP_DLY2_EN) << 16); |
|---|
| 589 | + val |= PCIE_LTSSM_ENABLE_ENHANCE | (PCIE_LTSSM_ENABLE_ENHANCE << 16); |
|---|
| 603 | 590 | rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL); |
|---|
| 604 | 591 | } |
|---|
| 605 | 592 | |
|---|
| .. | .. |
|---|
| 655 | 642 | u32 chn; |
|---|
| 656 | 643 | union int_status wr_status, rd_status; |
|---|
| 657 | 644 | union int_clear clears; |
|---|
| 658 | | - u32 reg, mask; |
|---|
| 645 | + u32 reg, val, mask; |
|---|
| 659 | 646 | bool sigio = false; |
|---|
| 660 | 647 | |
|---|
| 661 | 648 | /* ELBI helper, only check the valid bits, and discard the rest interrupts */ |
|---|
| .. | .. |
|---|
| 726 | 713 | } |
|---|
| 727 | 714 | |
|---|
| 728 | 715 | reg = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_STATUS_MISC); |
|---|
| 729 | | - if (reg & BIT(2)) |
|---|
| 730 | | - queue_work(rockchip->hot_rst_wq, &rockchip->hot_rst_work); |
|---|
| 716 | + if (reg & BIT(2)) { |
|---|
| 717 | + /* Setup command register */ |
|---|
| 718 | + val = dw_pcie_readl_dbi(pci, PCI_COMMAND); |
|---|
| 719 | + val &= 0xffff0000; |
|---|
| 720 | + val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | |
|---|
| 721 | + PCI_COMMAND_MASTER | PCI_COMMAND_SERR; |
|---|
| 722 | + dw_pcie_writel_dbi(pci, PCI_COMMAND, val); |
|---|
| 723 | + } |
|---|
| 731 | 724 | |
|---|
| 732 | 725 | rockchip_pcie_writel_apb(rockchip, reg, PCIE_CLIENT_INTR_STATUS_MISC); |
|---|
| 733 | 726 | |
|---|
| .. | .. |
|---|
| 875 | 868 | table->weilo.weight0 = 0x0; |
|---|
| 876 | 869 | table->start.stop = 0x0; |
|---|
| 877 | 870 | table->start.chnl = table->chn; |
|---|
| 878 | | -} |
|---|
| 879 | | - |
|---|
| 880 | | -static void rockchip_pcie_hot_rst_work(struct work_struct *work) |
|---|
| 881 | | -{ |
|---|
| 882 | | - struct rockchip_pcie *rockchip = container_of(work, struct rockchip_pcie, hot_rst_work); |
|---|
| 883 | | - u32 status; |
|---|
| 884 | | - int ret; |
|---|
| 885 | | - |
|---|
| 886 | | - if (rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_HOT_RESET_CTRL) & PCIE_LTSSM_APP_DLY2_EN) { |
|---|
| 887 | | - ret = readl_poll_timeout(rockchip->apb_base + PCIE_CLIENT_LTSSM_STATUS, |
|---|
| 888 | | - status, ((status & 0x3F) == 0), 100, PCIE_HOTRESET_TMOUT_US); |
|---|
| 889 | | - if (ret) |
|---|
| 890 | | - dev_err(rockchip->pci.dev, "wait for detect quiet failed!\n"); |
|---|
| 891 | | - |
|---|
| 892 | | - rockchip_pcie_writel_apb(rockchip, (PCIE_LTSSM_APP_DLY2_DONE) | ((PCIE_LTSSM_APP_DLY2_DONE) << 16), |
|---|
| 893 | | - PCIE_CLIENT_HOT_RESET_CTRL); |
|---|
| 894 | | - } |
|---|
| 895 | 871 | } |
|---|
| 896 | 872 | |
|---|
| 897 | 873 | static int rockchip_pcie_get_dma_status(struct dma_trx_obj *obj, u8 chn, enum dma_dir dir) |
|---|
| .. | .. |
|---|
| 1145 | 1121 | struct rockchip_pcie *rockchip; |
|---|
| 1146 | 1122 | int ret; |
|---|
| 1147 | 1123 | int retry, i; |
|---|
| 1148 | | - u32 reg; |
|---|
| 1149 | 1124 | |
|---|
| 1150 | 1125 | rockchip = devm_kzalloc(dev, sizeof(*rockchip), GFP_KERNEL); |
|---|
| 1151 | 1126 | if (!rockchip) |
|---|
| .. | .. |
|---|
| 1206 | 1181 | |
|---|
| 1207 | 1182 | rockchip_pcie_start_link(&rockchip->pci); |
|---|
| 1208 | 1183 | rockchip_pcie_devmode_update(rockchip, RKEP_MODE_KERNEL, RKEP_SMODE_LNKRDY); |
|---|
| 1209 | | - |
|---|
| 1210 | | - rockchip->hot_rst_wq = create_singlethread_workqueue("rkep_hot_rst_wq"); |
|---|
| 1211 | | - if (!rockchip->hot_rst_wq) { |
|---|
| 1212 | | - dev_err(dev, "failed to create hot_rst workqueue\n"); |
|---|
| 1213 | | - ret = -ENOMEM; |
|---|
| 1214 | | - goto deinit_phy; |
|---|
| 1215 | | - } |
|---|
| 1216 | | - INIT_WORK(&rockchip->hot_rst_work, rockchip_pcie_hot_rst_work); |
|---|
| 1217 | | - |
|---|
| 1218 | | - reg = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_STATUS_MISC); |
|---|
| 1219 | | - if ((reg & BIT(2)) && |
|---|
| 1220 | | - (rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_HOT_RESET_CTRL) & PCIE_LTSSM_APP_DLY2_EN)) { |
|---|
| 1221 | | - rockchip_pcie_writel_apb(rockchip, PCIE_LTSSM_APP_DLY2_DONE | (PCIE_LTSSM_APP_DLY2_DONE << 16), |
|---|
| 1222 | | - PCIE_CLIENT_HOT_RESET_CTRL); |
|---|
| 1223 | | - dev_info(dev, "hot reset ever\n"); |
|---|
| 1224 | | - } |
|---|
| 1225 | | - rockchip_pcie_writel_apb(rockchip, reg, PCIE_CLIENT_INTR_STATUS_MISC); |
|---|
| 1226 | | - |
|---|
| 1227 | | - /* Enable client reset or link down interrupt */ |
|---|
| 1228 | | - rockchip_pcie_writel_apb(rockchip, 0x40000, PCIE_CLIENT_INTR_MASK); |
|---|
| 1229 | 1184 | |
|---|
| 1230 | 1185 | for (retry = 0; retry < 10000; retry++) { |
|---|
| 1231 | 1186 | if (dw_pcie_link_up(&rockchip->pci)) { |
|---|