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  *  Sreehari Kancharla <sreehari.kancharla@intel.com>
0009  *
0010  * Contributors:
0011  *  Amir Hanania <amir.hanania@intel.com>
0012  *  Ricardo Martinez <ricardo.martinez@linux.intel.com>
0013  */
0014 
0015 #include <linux/bits.h>
0016 #include <linux/completion.h>
0017 #include <linux/dev_printk.h>
0018 #include <linux/io.h>
0019 #include <linux/irqreturn.h>
0020 
0021 #include "t7xx_mhccif.h"
0022 #include "t7xx_modem_ops.h"
0023 #include "t7xx_pci.h"
0024 #include "t7xx_pcie_mac.h"
0025 #include "t7xx_reg.h"
0026 
0027 #define D2H_INT_SR_ACK      (D2H_INT_SUSPEND_ACK |      \
0028                  D2H_INT_RESUME_ACK |       \
0029                  D2H_INT_SUSPEND_ACK_AP |   \
0030                  D2H_INT_RESUME_ACK_AP)
0031 
0032 static void t7xx_mhccif_clear_interrupts(struct t7xx_pci_dev *t7xx_dev, u32 mask)
0033 {
0034     void __iomem *mhccif_pbase = t7xx_dev->base_addr.mhccif_rc_base;
0035 
0036     /* Clear level 2 interrupt */
0037     iowrite32(mask, mhccif_pbase + REG_EP2RC_SW_INT_ACK);
0038     /* Ensure write is complete */
0039     t7xx_mhccif_read_sw_int_sts(t7xx_dev);
0040     /* Clear level 1 interrupt */
0041     t7xx_pcie_mac_clear_int_status(t7xx_dev, MHCCIF_INT);
0042 }
0043 
0044 static irqreturn_t t7xx_mhccif_isr_thread(int irq, void *data)
0045 {
0046     struct t7xx_pci_dev *t7xx_dev = data;
0047     u32 int_status, val;
0048 
0049     val = T7XX_L1_1_BIT(1) | T7XX_L1_2_BIT(1);
0050     iowrite32(val, IREG_BASE(t7xx_dev) + DISABLE_ASPM_LOWPWR);
0051 
0052     int_status = t7xx_mhccif_read_sw_int_sts(t7xx_dev);
0053     if (int_status & D2H_SW_INT_MASK) {
0054         int ret = t7xx_pci_mhccif_isr(t7xx_dev);
0055 
0056         if (ret)
0057             dev_err(&t7xx_dev->pdev->dev, "PCI MHCCIF ISR failure: %d", ret);
0058     }
0059 
0060     t7xx_mhccif_clear_interrupts(t7xx_dev, int_status);
0061 
0062     if (int_status & D2H_INT_DS_LOCK_ACK)
0063         complete_all(&t7xx_dev->sleep_lock_acquire);
0064 
0065     if (int_status & D2H_INT_SR_ACK)
0066         complete(&t7xx_dev->pm_sr_ack);
0067 
0068     iowrite32(T7XX_L1_BIT(1), IREG_BASE(t7xx_dev) + ENABLE_ASPM_LOWPWR);
0069 
0070     int_status = t7xx_mhccif_read_sw_int_sts(t7xx_dev);
0071     if (!int_status) {
0072         val = T7XX_L1_1_BIT(1) | T7XX_L1_2_BIT(1);
0073         iowrite32(val, IREG_BASE(t7xx_dev) + ENABLE_ASPM_LOWPWR);
0074     }
0075 
0076     t7xx_pcie_mac_set_int(t7xx_dev, MHCCIF_INT);
0077     return IRQ_HANDLED;
0078 }
0079 
0080 u32 t7xx_mhccif_read_sw_int_sts(struct t7xx_pci_dev *t7xx_dev)
0081 {
0082     return ioread32(t7xx_dev->base_addr.mhccif_rc_base + REG_EP2RC_SW_INT_STS);
0083 }
0084 
0085 void t7xx_mhccif_mask_set(struct t7xx_pci_dev *t7xx_dev, u32 val)
0086 {
0087     iowrite32(val, t7xx_dev->base_addr.mhccif_rc_base + REG_EP2RC_SW_INT_EAP_MASK_SET);
0088 }
0089 
0090 void t7xx_mhccif_mask_clr(struct t7xx_pci_dev *t7xx_dev, u32 val)
0091 {
0092     iowrite32(val, t7xx_dev->base_addr.mhccif_rc_base + REG_EP2RC_SW_INT_EAP_MASK_CLR);
0093 }
0094 
0095 u32 t7xx_mhccif_mask_get(struct t7xx_pci_dev *t7xx_dev)
0096 {
0097     return ioread32(t7xx_dev->base_addr.mhccif_rc_base + REG_EP2RC_SW_INT_EAP_MASK);
0098 }
0099 
0100 static irqreturn_t t7xx_mhccif_isr_handler(int irq, void *data)
0101 {
0102     return IRQ_WAKE_THREAD;
0103 }
0104 
0105 void t7xx_mhccif_init(struct t7xx_pci_dev *t7xx_dev)
0106 {
0107     t7xx_dev->base_addr.mhccif_rc_base = t7xx_dev->base_addr.pcie_ext_reg_base +
0108                         MHCCIF_RC_DEV_BASE -
0109                         t7xx_dev->base_addr.pcie_dev_reg_trsl_addr;
0110 
0111     t7xx_dev->intr_handler[MHCCIF_INT] = t7xx_mhccif_isr_handler;
0112     t7xx_dev->intr_thread[MHCCIF_INT] = t7xx_mhccif_isr_thread;
0113     t7xx_dev->callback_param[MHCCIF_INT] = t7xx_dev;
0114 }
0115 
0116 void t7xx_mhccif_h2d_swint_trigger(struct t7xx_pci_dev *t7xx_dev, u32 channel)
0117 {
0118     void __iomem *mhccif_pbase = t7xx_dev->base_addr.mhccif_rc_base;
0119 
0120     iowrite32(BIT(channel), mhccif_pbase + REG_RC2EP_SW_BSY);
0121     iowrite32(channel, mhccif_pbase + REG_RC2EP_SW_TCHNUM);
0122 }