0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/delay.h>
0013 #include <linux/init.h>
0014 #include <linux/kernel.h>
0015 #include <linux/pci.h>
0016 #include <linux/platform_device.h>
0017
0018 #include "pcie-mobiveil.h"
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 static void mobiveil_pcie_sel_page(struct mobiveil_pcie *pcie, u8 pg_idx)
0029 {
0030 u32 val;
0031
0032 val = readl(pcie->csr_axi_slave_base + PAB_CTRL);
0033 val &= ~(PAGE_SEL_MASK << PAGE_SEL_SHIFT);
0034 val |= (pg_idx & PAGE_SEL_MASK) << PAGE_SEL_SHIFT;
0035
0036 writel(val, pcie->csr_axi_slave_base + PAB_CTRL);
0037 }
0038
0039 static void __iomem *mobiveil_pcie_comp_addr(struct mobiveil_pcie *pcie,
0040 u32 off)
0041 {
0042 if (off < PAGED_ADDR_BNDRY) {
0043
0044 mobiveil_pcie_sel_page(pcie, 0);
0045 return pcie->csr_axi_slave_base + off;
0046 }
0047
0048 mobiveil_pcie_sel_page(pcie, OFFSET_TO_PAGE_IDX(off));
0049 return pcie->csr_axi_slave_base + OFFSET_TO_PAGE_ADDR(off);
0050 }
0051
0052 static int mobiveil_pcie_read(void __iomem *addr, int size, u32 *val)
0053 {
0054 if ((uintptr_t)addr & (size - 1)) {
0055 *val = 0;
0056 return PCIBIOS_BAD_REGISTER_NUMBER;
0057 }
0058
0059 switch (size) {
0060 case 4:
0061 *val = readl(addr);
0062 break;
0063 case 2:
0064 *val = readw(addr);
0065 break;
0066 case 1:
0067 *val = readb(addr);
0068 break;
0069 default:
0070 *val = 0;
0071 return PCIBIOS_BAD_REGISTER_NUMBER;
0072 }
0073
0074 return PCIBIOS_SUCCESSFUL;
0075 }
0076
0077 static int mobiveil_pcie_write(void __iomem *addr, int size, u32 val)
0078 {
0079 if ((uintptr_t)addr & (size - 1))
0080 return PCIBIOS_BAD_REGISTER_NUMBER;
0081
0082 switch (size) {
0083 case 4:
0084 writel(val, addr);
0085 break;
0086 case 2:
0087 writew(val, addr);
0088 break;
0089 case 1:
0090 writeb(val, addr);
0091 break;
0092 default:
0093 return PCIBIOS_BAD_REGISTER_NUMBER;
0094 }
0095
0096 return PCIBIOS_SUCCESSFUL;
0097 }
0098
0099 u32 mobiveil_csr_read(struct mobiveil_pcie *pcie, u32 off, size_t size)
0100 {
0101 void __iomem *addr;
0102 u32 val;
0103 int ret;
0104
0105 addr = mobiveil_pcie_comp_addr(pcie, off);
0106
0107 ret = mobiveil_pcie_read(addr, size, &val);
0108 if (ret)
0109 dev_err(&pcie->pdev->dev, "read CSR address failed\n");
0110
0111 return val;
0112 }
0113
0114 void mobiveil_csr_write(struct mobiveil_pcie *pcie, u32 val, u32 off,
0115 size_t size)
0116 {
0117 void __iomem *addr;
0118 int ret;
0119
0120 addr = mobiveil_pcie_comp_addr(pcie, off);
0121
0122 ret = mobiveil_pcie_write(addr, size, val);
0123 if (ret)
0124 dev_err(&pcie->pdev->dev, "write CSR address failed\n");
0125 }
0126
0127 bool mobiveil_pcie_link_up(struct mobiveil_pcie *pcie)
0128 {
0129 if (pcie->ops->link_up)
0130 return pcie->ops->link_up(pcie);
0131
0132 return (mobiveil_csr_readl(pcie, LTSSM_STATUS) &
0133 LTSSM_STATUS_L0_MASK) == LTSSM_STATUS_L0;
0134 }
0135
0136 void program_ib_windows(struct mobiveil_pcie *pcie, int win_num,
0137 u64 cpu_addr, u64 pci_addr, u32 type, u64 size)
0138 {
0139 u32 value;
0140 u64 size64 = ~(size - 1);
0141
0142 if (win_num >= pcie->ppio_wins) {
0143 dev_err(&pcie->pdev->dev,
0144 "ERROR: max inbound windows reached !\n");
0145 return;
0146 }
0147
0148 value = mobiveil_csr_readl(pcie, PAB_PEX_AMAP_CTRL(win_num));
0149 value &= ~(AMAP_CTRL_TYPE_MASK << AMAP_CTRL_TYPE_SHIFT | WIN_SIZE_MASK);
0150 value |= type << AMAP_CTRL_TYPE_SHIFT | 1 << AMAP_CTRL_EN_SHIFT |
0151 (lower_32_bits(size64) & WIN_SIZE_MASK);
0152 mobiveil_csr_writel(pcie, value, PAB_PEX_AMAP_CTRL(win_num));
0153
0154 mobiveil_csr_writel(pcie, upper_32_bits(size64),
0155 PAB_EXT_PEX_AMAP_SIZEN(win_num));
0156
0157 mobiveil_csr_writel(pcie, lower_32_bits(cpu_addr),
0158 PAB_PEX_AMAP_AXI_WIN(win_num));
0159 mobiveil_csr_writel(pcie, upper_32_bits(cpu_addr),
0160 PAB_EXT_PEX_AMAP_AXI_WIN(win_num));
0161
0162 mobiveil_csr_writel(pcie, lower_32_bits(pci_addr),
0163 PAB_PEX_AMAP_PEX_WIN_L(win_num));
0164 mobiveil_csr_writel(pcie, upper_32_bits(pci_addr),
0165 PAB_PEX_AMAP_PEX_WIN_H(win_num));
0166
0167 pcie->ib_wins_configured++;
0168 }
0169
0170
0171
0172
0173 void program_ob_windows(struct mobiveil_pcie *pcie, int win_num,
0174 u64 cpu_addr, u64 pci_addr, u32 type, u64 size)
0175 {
0176 u32 value;
0177 u64 size64 = ~(size - 1);
0178
0179 if (win_num >= pcie->apio_wins) {
0180 dev_err(&pcie->pdev->dev,
0181 "ERROR: max outbound windows reached !\n");
0182 return;
0183 }
0184
0185
0186
0187
0188
0189 value = mobiveil_csr_readl(pcie, PAB_AXI_AMAP_CTRL(win_num));
0190 value &= ~(WIN_TYPE_MASK << WIN_TYPE_SHIFT | WIN_SIZE_MASK);
0191 value |= 1 << WIN_ENABLE_SHIFT | type << WIN_TYPE_SHIFT |
0192 (lower_32_bits(size64) & WIN_SIZE_MASK);
0193 mobiveil_csr_writel(pcie, value, PAB_AXI_AMAP_CTRL(win_num));
0194
0195 mobiveil_csr_writel(pcie, upper_32_bits(size64),
0196 PAB_EXT_AXI_AMAP_SIZE(win_num));
0197
0198
0199
0200
0201
0202 mobiveil_csr_writel(pcie,
0203 lower_32_bits(cpu_addr) & (~AXI_WINDOW_ALIGN_MASK),
0204 PAB_AXI_AMAP_AXI_WIN(win_num));
0205 mobiveil_csr_writel(pcie, upper_32_bits(cpu_addr),
0206 PAB_EXT_AXI_AMAP_AXI_WIN(win_num));
0207
0208 mobiveil_csr_writel(pcie, lower_32_bits(pci_addr),
0209 PAB_AXI_AMAP_PEX_WIN_L(win_num));
0210 mobiveil_csr_writel(pcie, upper_32_bits(pci_addr),
0211 PAB_AXI_AMAP_PEX_WIN_H(win_num));
0212
0213 pcie->ob_wins_configured++;
0214 }
0215
0216 int mobiveil_bringup_link(struct mobiveil_pcie *pcie)
0217 {
0218 int retries;
0219
0220
0221 for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
0222 if (mobiveil_pcie_link_up(pcie))
0223 return 0;
0224
0225 usleep_range(LINK_WAIT_MIN, LINK_WAIT_MAX);
0226 }
0227
0228 dev_err(&pcie->pdev->dev, "link never came up\n");
0229
0230 return -ETIMEDOUT;
0231 }