0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <linux/bits.h>
0018 #include <linux/bitops.h>
0019 #include <linux/device.h>
0020 #include <linux/io-64-nonatomic-lo-hi.h>
0021 #include <linux/pci.h>
0022 #include <linux/string.h>
0023 #include <linux/types.h>
0024
0025 #include "t7xx_pci.h"
0026 #include "t7xx_pcie_mac.h"
0027 #include "t7xx_reg.h"
0028
0029 #define T7XX_PCIE_REG_BAR 2
0030 #define T7XX_PCIE_REG_PORT ATR_SRC_PCI_WIN0
0031 #define T7XX_PCIE_REG_TABLE_NUM 0
0032 #define T7XX_PCIE_REG_TRSL_PORT ATR_DST_AXIM_0
0033
0034 #define T7XX_PCIE_DEV_DMA_PORT_START ATR_SRC_AXIS_0
0035 #define T7XX_PCIE_DEV_DMA_PORT_END ATR_SRC_AXIS_2
0036 #define T7XX_PCIE_DEV_DMA_TABLE_NUM 0
0037 #define T7XX_PCIE_DEV_DMA_TRSL_ADDR 0
0038 #define T7XX_PCIE_DEV_DMA_SRC_ADDR 0
0039 #define T7XX_PCIE_DEV_DMA_TRANSPARENT 1
0040 #define T7XX_PCIE_DEV_DMA_SIZE 0
0041
0042 enum t7xx_atr_src_port {
0043 ATR_SRC_PCI_WIN0,
0044 ATR_SRC_PCI_WIN1,
0045 ATR_SRC_AXIS_0,
0046 ATR_SRC_AXIS_1,
0047 ATR_SRC_AXIS_2,
0048 ATR_SRC_AXIS_3,
0049 };
0050
0051 enum t7xx_atr_dst_port {
0052 ATR_DST_PCI_TRX,
0053 ATR_DST_PCI_CONFIG,
0054 ATR_DST_AXIM_0 = 4,
0055 ATR_DST_AXIM_1,
0056 ATR_DST_AXIM_2,
0057 ATR_DST_AXIM_3,
0058 };
0059
0060 struct t7xx_atr_config {
0061 u64 src_addr;
0062 u64 trsl_addr;
0063 u64 size;
0064 u32 port;
0065 u32 table;
0066 enum t7xx_atr_dst_port trsl_id;
0067 u32 transparent;
0068 };
0069
0070 static void t7xx_pcie_mac_atr_tables_dis(void __iomem *pbase, enum t7xx_atr_src_port port)
0071 {
0072 void __iomem *reg;
0073 int i, offset;
0074
0075 for (i = 0; i < ATR_TABLE_NUM_PER_ATR; i++) {
0076 offset = ATR_PORT_OFFSET * port + ATR_TABLE_OFFSET * i;
0077 reg = pbase + ATR_PCIE_WIN0_T0_ATR_PARAM_SRC_ADDR + offset;
0078 iowrite64(0, reg);
0079 }
0080 }
0081
0082 static int t7xx_pcie_mac_atr_cfg(struct t7xx_pci_dev *t7xx_dev, struct t7xx_atr_config *cfg)
0083 {
0084 struct device *dev = &t7xx_dev->pdev->dev;
0085 void __iomem *pbase = IREG_BASE(t7xx_dev);
0086 int atr_size, pos, offset;
0087 void __iomem *reg;
0088 u64 value;
0089
0090 if (cfg->transparent) {
0091
0092 atr_size = ATR_TRANSPARENT_SIZE;
0093 } else {
0094 if (cfg->src_addr & (cfg->size - 1)) {
0095 dev_err(dev, "Source address is not aligned to size\n");
0096 return -EINVAL;
0097 }
0098
0099 if (cfg->trsl_addr & (cfg->size - 1)) {
0100 dev_err(dev, "Translation address %llx is not aligned to size %llx\n",
0101 cfg->trsl_addr, cfg->size - 1);
0102 return -EINVAL;
0103 }
0104
0105 pos = __ffs64(cfg->size);
0106
0107
0108 atr_size = pos - 1;
0109 }
0110
0111 offset = ATR_PORT_OFFSET * cfg->port + ATR_TABLE_OFFSET * cfg->table;
0112
0113 reg = pbase + ATR_PCIE_WIN0_T0_TRSL_ADDR + offset;
0114 value = cfg->trsl_addr & ATR_PCIE_WIN0_ADDR_ALGMT;
0115 iowrite64(value, reg);
0116
0117 reg = pbase + ATR_PCIE_WIN0_T0_TRSL_PARAM + offset;
0118 iowrite32(cfg->trsl_id, reg);
0119
0120 reg = pbase + ATR_PCIE_WIN0_T0_ATR_PARAM_SRC_ADDR + offset;
0121 value = (cfg->src_addr & ATR_PCIE_WIN0_ADDR_ALGMT) | (atr_size << 1) | BIT(0);
0122 iowrite64(value, reg);
0123
0124
0125 ioread64(reg);
0126 return 0;
0127 }
0128
0129
0130
0131
0132
0133
0134
0135 void t7xx_pcie_mac_atr_init(struct t7xx_pci_dev *t7xx_dev)
0136 {
0137 struct t7xx_atr_config cfg;
0138 u32 i;
0139
0140
0141 for (i = ATR_SRC_PCI_WIN0; i <= ATR_SRC_AXIS_3; i++)
0142 t7xx_pcie_mac_atr_tables_dis(IREG_BASE(t7xx_dev), i);
0143
0144 memset(&cfg, 0, sizeof(cfg));
0145
0146 cfg.src_addr = pci_resource_start(t7xx_dev->pdev, T7XX_PCIE_REG_BAR);
0147 cfg.size = T7XX_PCIE_REG_SIZE_CHIP;
0148 cfg.trsl_addr = T7XX_PCIE_REG_TRSL_ADDR_CHIP;
0149 cfg.port = T7XX_PCIE_REG_PORT;
0150 cfg.table = T7XX_PCIE_REG_TABLE_NUM;
0151 cfg.trsl_id = T7XX_PCIE_REG_TRSL_PORT;
0152 t7xx_pcie_mac_atr_tables_dis(IREG_BASE(t7xx_dev), cfg.port);
0153 t7xx_pcie_mac_atr_cfg(t7xx_dev, &cfg);
0154
0155 t7xx_dev->base_addr.pcie_dev_reg_trsl_addr = T7XX_PCIE_REG_TRSL_ADDR_CHIP;
0156
0157
0158 for (i = T7XX_PCIE_DEV_DMA_PORT_START; i <= T7XX_PCIE_DEV_DMA_PORT_END; i++) {
0159 cfg.src_addr = T7XX_PCIE_DEV_DMA_SRC_ADDR;
0160 cfg.size = T7XX_PCIE_DEV_DMA_SIZE;
0161 cfg.trsl_addr = T7XX_PCIE_DEV_DMA_TRSL_ADDR;
0162 cfg.port = i;
0163 cfg.table = T7XX_PCIE_DEV_DMA_TABLE_NUM;
0164 cfg.trsl_id = ATR_DST_PCI_TRX;
0165 cfg.transparent = T7XX_PCIE_DEV_DMA_TRANSPARENT;
0166 t7xx_pcie_mac_atr_tables_dis(IREG_BASE(t7xx_dev), cfg.port);
0167 t7xx_pcie_mac_atr_cfg(t7xx_dev, &cfg);
0168 }
0169 }
0170
0171
0172
0173
0174
0175
0176
0177
0178 static void t7xx_pcie_mac_enable_disable_int(struct t7xx_pci_dev *t7xx_dev, bool enable)
0179 {
0180 u32 value;
0181
0182 value = ioread32(IREG_BASE(t7xx_dev) + ISTAT_HST_CTRL);
0183
0184 if (enable)
0185 value &= ~ISTAT_HST_CTRL_DIS;
0186 else
0187 value |= ISTAT_HST_CTRL_DIS;
0188
0189 iowrite32(value, IREG_BASE(t7xx_dev) + ISTAT_HST_CTRL);
0190 }
0191
0192 void t7xx_pcie_mac_interrupts_en(struct t7xx_pci_dev *t7xx_dev)
0193 {
0194 t7xx_pcie_mac_enable_disable_int(t7xx_dev, true);
0195 }
0196
0197 void t7xx_pcie_mac_interrupts_dis(struct t7xx_pci_dev *t7xx_dev)
0198 {
0199 t7xx_pcie_mac_enable_disable_int(t7xx_dev, false);
0200 }
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210 static void t7xx_pcie_mac_clear_set_int(struct t7xx_pci_dev *t7xx_dev,
0211 enum t7xx_int int_type, bool clear)
0212 {
0213 void __iomem *reg;
0214 u32 val;
0215
0216 if (clear)
0217 reg = IREG_BASE(t7xx_dev) + IMASK_HOST_MSIX_CLR_GRP0_0;
0218 else
0219 reg = IREG_BASE(t7xx_dev) + IMASK_HOST_MSIX_SET_GRP0_0;
0220
0221 val = BIT(EXT_INT_START + int_type);
0222 iowrite32(val, reg);
0223 }
0224
0225 void t7xx_pcie_mac_clear_int(struct t7xx_pci_dev *t7xx_dev, enum t7xx_int int_type)
0226 {
0227 t7xx_pcie_mac_clear_set_int(t7xx_dev, int_type, true);
0228 }
0229
0230 void t7xx_pcie_mac_set_int(struct t7xx_pci_dev *t7xx_dev, enum t7xx_int int_type)
0231 {
0232 t7xx_pcie_mac_clear_set_int(t7xx_dev, int_type, false);
0233 }
0234
0235
0236
0237
0238
0239
0240
0241
0242 void t7xx_pcie_mac_clear_int_status(struct t7xx_pci_dev *t7xx_dev, enum t7xx_int int_type)
0243 {
0244 void __iomem *reg = IREG_BASE(t7xx_dev) + MSIX_ISTAT_HST_GRP0_0;
0245 u32 val = BIT(EXT_INT_START + int_type);
0246
0247 iowrite32(val, reg);
0248 }
0249
0250
0251
0252
0253
0254
0255
0256
0257 void t7xx_pcie_set_mac_msix_cfg(struct t7xx_pci_dev *t7xx_dev, unsigned int irq_count)
0258 {
0259 u32 val = ffs(irq_count) * 2 - 1;
0260
0261 iowrite32(val, IREG_BASE(t7xx_dev) + T7XX_PCIE_CFG_MSIX);
0262 }