Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2021, MediaTek Inc.
0004  * Copyright (c) 2021-2022, Intel Corporation.
0005  *
0006  * Authors:
0007  *  Haijun Liu <haijun.liu@mediatek.com>
0008  *  Moises Veleta <moises.veleta@intel.com>
0009  *  Sreehari Kancharla <sreehari.kancharla@intel.com>
0010  *
0011  * Contributors:
0012  *  Amir Hanania <amir.hanania@intel.com>
0013  *  Chiranjeevi Rapolu <chiranjeevi.rapolu@intel.com>
0014  *  Ricardo Martinez <ricardo.martinez@linux.intel.com>
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         /* No address conversion is performed */
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         /* HW calculates the address translation space as 2^(atr_size + 1) */
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     /* Ensure ATR is set */
0125     ioread64(reg);
0126     return 0;
0127 }
0128 
0129 /**
0130  * t7xx_pcie_mac_atr_init() - Initialize address translation.
0131  * @t7xx_dev: MTK device.
0132  *
0133  * Setup ATR for ports & device.
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     /* Disable for all ports */
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     /* Config ATR for RC to access device's register */
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     /* Config ATR for EP to access RC's memory */
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  * t7xx_pcie_mac_enable_disable_int() - Enable/disable interrupts.
0173  * @t7xx_dev: MTK device.
0174  * @enable: Enable/disable.
0175  *
0176  * Enable or disable device interrupts.
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  * t7xx_pcie_mac_clear_set_int() - Clear/set interrupt by type.
0204  * @t7xx_dev: MTK device.
0205  * @int_type: Interrupt type.
0206  * @clear: Clear/set.
0207  *
0208  * Clear or set device interrupt by type.
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  * t7xx_pcie_mac_clear_int_status() - Clear interrupt status by type.
0237  * @t7xx_dev: MTK device.
0238  * @int_type: Interrupt type.
0239  *
0240  * Enable or disable device interrupts' status by type.
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  * t7xx_pcie_set_mac_msix_cfg() - Write MSIX control configuration.
0252  * @t7xx_dev: MTK device.
0253  * @irq_count: Number of MSIX IRQ vectors.
0254  *
0255  * Write IRQ count to device.
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 }