.. | .. |
---|
81 | 81 | #define PCIE_CLIENT_HOT_RESET_CTRL 0x180 |
---|
82 | 82 | #define PCIE_CLIENT_LTSSM_STATUS 0x300 |
---|
83 | 83 | #define PCIE_CLIENT_INTR_MASK 0x24 |
---|
| 84 | +#define PCIE_LTSSM_APP_DLY1_EN BIT(0) |
---|
| 85 | +#define PCIE_LTSSM_APP_DLY2_EN BIT(1) |
---|
| 86 | +#define PCIE_LTSSM_APP_DLY1_DONE BIT(2) |
---|
| 87 | +#define PCIE_LTSSM_APP_DLY2_DONE BIT(3) |
---|
84 | 88 | #define PCIE_LTSSM_ENABLE_ENHANCE BIT(4) |
---|
85 | 89 | #define PCIE_CLIENT_MSI_GEN_CON 0x38 |
---|
86 | 90 | |
---|
.. | .. |
---|
106 | 110 | #define PCIE_EP_OBJ_INFO_DRV_VERSION 0x00000001 |
---|
107 | 111 | |
---|
108 | 112 | #define PCIE_BAR_MAX_NUM 6 |
---|
| 113 | +#define PCIE_HOTRESET_TMOUT_US 10000 |
---|
109 | 114 | |
---|
110 | 115 | struct rockchip_pcie { |
---|
111 | 116 | struct dw_pcie pci; |
---|
.. | .. |
---|
130 | 135 | phys_addr_t dbi_base_physical; |
---|
131 | 136 | struct pcie_ep_obj_info *obj_info; |
---|
132 | 137 | enum pcie_ep_mmap_resource cur_mmap_res; |
---|
| 138 | + struct workqueue_struct *hot_rst_wq; |
---|
| 139 | + struct work_struct hot_rst_work; |
---|
133 | 140 | }; |
---|
134 | 141 | |
---|
135 | 142 | struct rockchip_pcie_misc_dev { |
---|
.. | .. |
---|
586 | 593 | |
---|
587 | 594 | /* LTSSM EN ctrl mode */ |
---|
588 | 595 | val = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_HOT_RESET_CTRL); |
---|
589 | | - val |= PCIE_LTSSM_ENABLE_ENHANCE | (PCIE_LTSSM_ENABLE_ENHANCE << 16); |
---|
| 596 | + val |= (PCIE_LTSSM_ENABLE_ENHANCE | PCIE_LTSSM_APP_DLY2_EN) | |
---|
| 597 | + ((PCIE_LTSSM_ENABLE_ENHANCE | PCIE_LTSSM_APP_DLY2_EN) << 16); |
---|
590 | 598 | rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL); |
---|
591 | 599 | } |
---|
592 | 600 | |
---|
.. | .. |
---|
642 | 650 | u32 chn; |
---|
643 | 651 | union int_status wr_status, rd_status; |
---|
644 | 652 | union int_clear clears; |
---|
645 | | - u32 reg, val, mask; |
---|
| 653 | + u32 reg, mask; |
---|
646 | 654 | bool sigio = false; |
---|
647 | 655 | |
---|
648 | 656 | /* ELBI helper, only check the valid bits, and discard the rest interrupts */ |
---|
.. | .. |
---|
713 | 721 | } |
---|
714 | 722 | |
---|
715 | 723 | reg = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_STATUS_MISC); |
---|
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 | | - } |
---|
| 724 | + if (reg & BIT(2)) |
---|
| 725 | + queue_work(rockchip->hot_rst_wq, &rockchip->hot_rst_work); |
---|
724 | 726 | |
---|
725 | 727 | rockchip_pcie_writel_apb(rockchip, reg, PCIE_CLIENT_INTR_STATUS_MISC); |
---|
726 | 728 | |
---|
.. | .. |
---|
868 | 870 | table->weilo.weight0 = 0x0; |
---|
869 | 871 | table->start.stop = 0x0; |
---|
870 | 872 | table->start.chnl = table->chn; |
---|
| 873 | +} |
---|
| 874 | + |
---|
| 875 | +static void rockchip_pcie_hot_rst_work(struct work_struct *work) |
---|
| 876 | +{ |
---|
| 877 | + struct rockchip_pcie *rockchip = container_of(work, struct rockchip_pcie, hot_rst_work); |
---|
| 878 | + u32 status; |
---|
| 879 | + int ret; |
---|
| 880 | + |
---|
| 881 | + if (rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_HOT_RESET_CTRL) & PCIE_LTSSM_APP_DLY2_EN) { |
---|
| 882 | + ret = readl_poll_timeout(rockchip->apb_base + PCIE_CLIENT_LTSSM_STATUS, |
---|
| 883 | + status, ((status & 0x3F) == 0), 100, PCIE_HOTRESET_TMOUT_US); |
---|
| 884 | + if (ret) |
---|
| 885 | + dev_err(rockchip->pci.dev, "wait for detect quiet failed!\n"); |
---|
| 886 | + |
---|
| 887 | + rockchip_pcie_writel_apb(rockchip, (PCIE_LTSSM_APP_DLY2_DONE) | ((PCIE_LTSSM_APP_DLY2_DONE) << 16), |
---|
| 888 | + PCIE_CLIENT_HOT_RESET_CTRL); |
---|
| 889 | + } |
---|
871 | 890 | } |
---|
872 | 891 | |
---|
873 | 892 | static int rockchip_pcie_get_dma_status(struct dma_trx_obj *obj, u8 chn, enum dma_dir dir) |
---|
.. | .. |
---|
1121 | 1140 | struct rockchip_pcie *rockchip; |
---|
1122 | 1141 | int ret; |
---|
1123 | 1142 | int retry, i; |
---|
| 1143 | + u32 reg; |
---|
1124 | 1144 | |
---|
1125 | 1145 | rockchip = devm_kzalloc(dev, sizeof(*rockchip), GFP_KERNEL); |
---|
1126 | 1146 | if (!rockchip) |
---|
.. | .. |
---|
1182 | 1202 | rockchip_pcie_start_link(&rockchip->pci); |
---|
1183 | 1203 | rockchip_pcie_devmode_update(rockchip, RKEP_MODE_KERNEL, RKEP_SMODE_LNKRDY); |
---|
1184 | 1204 | |
---|
| 1205 | + rockchip->hot_rst_wq = create_singlethread_workqueue("rkep_hot_rst_wq"); |
---|
| 1206 | + if (!rockchip->hot_rst_wq) { |
---|
| 1207 | + dev_err(dev, "failed to create hot_rst workqueue\n"); |
---|
| 1208 | + ret = -ENOMEM; |
---|
| 1209 | + goto deinit_phy; |
---|
| 1210 | + } |
---|
| 1211 | + INIT_WORK(&rockchip->hot_rst_work, rockchip_pcie_hot_rst_work); |
---|
| 1212 | + |
---|
| 1213 | + reg = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_STATUS_MISC); |
---|
| 1214 | + if ((reg & BIT(2)) && |
---|
| 1215 | + (rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_HOT_RESET_CTRL) & PCIE_LTSSM_APP_DLY2_EN)) { |
---|
| 1216 | + rockchip_pcie_writel_apb(rockchip, PCIE_LTSSM_APP_DLY2_DONE | (PCIE_LTSSM_APP_DLY2_DONE << 16), |
---|
| 1217 | + PCIE_CLIENT_HOT_RESET_CTRL); |
---|
| 1218 | + dev_info(dev, "hot reset ever\n"); |
---|
| 1219 | + } |
---|
| 1220 | + rockchip_pcie_writel_apb(rockchip, reg, PCIE_CLIENT_INTR_STATUS_MISC); |
---|
| 1221 | + |
---|
| 1222 | + /* Enable client reset or link down interrupt */ |
---|
| 1223 | + rockchip_pcie_writel_apb(rockchip, 0x40000, PCIE_CLIENT_INTR_MASK); |
---|
| 1224 | + |
---|
1185 | 1225 | for (retry = 0; retry < 10000; retry++) { |
---|
1186 | 1226 | if (dw_pcie_link_up(&rockchip->pci)) { |
---|
1187 | 1227 | /* |
---|