1*8bf5e849SAlexander Usyskin // SPDX-License-Identifier: GPL-2.0 2*8bf5e849SAlexander Usyskin /* Copyright (C) 2023-2026 Intel Corporation */ 3*8bf5e849SAlexander Usyskin #include <linux/device.h> 4*8bf5e849SAlexander Usyskin #include <linux/dev_printk.h> 5*8bf5e849SAlexander Usyskin #include <linux/dma-mapping.h> 6*8bf5e849SAlexander Usyskin #include <linux/err.h> 7*8bf5e849SAlexander Usyskin #include <linux/interrupt.h> 8*8bf5e849SAlexander Usyskin #include <linux/module.h> 9*8bf5e849SAlexander Usyskin #include <linux/pci.h> 10*8bf5e849SAlexander Usyskin #include <linux/pm.h> 11*8bf5e849SAlexander Usyskin 12*8bf5e849SAlexander Usyskin #include "cdev.h" 13*8bf5e849SAlexander Usyskin #include "hw_heci.h" 14*8bf5e849SAlexander Usyskin #include "hw_heci_regs.h" 15*8bf5e849SAlexander Usyskin 16*8bf5e849SAlexander Usyskin static int issei_heci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 17*8bf5e849SAlexander Usyskin { 18*8bf5e849SAlexander Usyskin struct device *dev = &pdev->dev; 19*8bf5e849SAlexander Usyskin const struct hw_heci_cfg *cfg; 20*8bf5e849SAlexander Usyskin struct issei_device *idev; 21*8bf5e849SAlexander Usyskin struct issei_heci_hw *hw; 22*8bf5e849SAlexander Usyskin char __iomem *registers; 23*8bf5e849SAlexander Usyskin int err; 24*8bf5e849SAlexander Usyskin 25*8bf5e849SAlexander Usyskin cfg = issei_heci_get_cfg(ent->driver_data); 26*8bf5e849SAlexander Usyskin if (!cfg) 27*8bf5e849SAlexander Usyskin return dev_err_probe(dev, -ENODEV, "no usable configuration.\n"); 28*8bf5e849SAlexander Usyskin 29*8bf5e849SAlexander Usyskin err = pcim_enable_device(pdev); 30*8bf5e849SAlexander Usyskin if (err) 31*8bf5e849SAlexander Usyskin return dev_err_probe(dev, err, "failed to enable pci device.\n"); 32*8bf5e849SAlexander Usyskin 33*8bf5e849SAlexander Usyskin pci_set_master(pdev); 34*8bf5e849SAlexander Usyskin 35*8bf5e849SAlexander Usyskin registers = pcim_iomap_region(pdev, 0, KBUILD_MODNAME); 36*8bf5e849SAlexander Usyskin if (IS_ERR(registers)) 37*8bf5e849SAlexander Usyskin return dev_err_probe(dev, PTR_ERR(registers), "failed to get pci region.\n"); 38*8bf5e849SAlexander Usyskin 39*8bf5e849SAlexander Usyskin err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); 40*8bf5e849SAlexander Usyskin if (err) 41*8bf5e849SAlexander Usyskin return dev_err_probe(dev, err, "no usable DMA configuration.\n"); 42*8bf5e849SAlexander Usyskin 43*8bf5e849SAlexander Usyskin idev = issei_register(sizeof(*hw), dev, &cfg->dma_length, issei_heci_get_ops()); 44*8bf5e849SAlexander Usyskin if (IS_ERR(idev)) 45*8bf5e849SAlexander Usyskin return dev_err_probe(dev, PTR_ERR(idev), "register failure.\n"); 46*8bf5e849SAlexander Usyskin 47*8bf5e849SAlexander Usyskin issei_heci_dev_init(idev, registers, cfg); 48*8bf5e849SAlexander Usyskin 49*8bf5e849SAlexander Usyskin pci_set_drvdata(pdev, idev); 50*8bf5e849SAlexander Usyskin 51*8bf5e849SAlexander Usyskin err = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI); 52*8bf5e849SAlexander Usyskin if (err < 0) { 53*8bf5e849SAlexander Usyskin dev_err_probe(dev, err, "pci_alloc_irq_vectors failure.\n"); 54*8bf5e849SAlexander Usyskin goto deregister; 55*8bf5e849SAlexander Usyskin } 56*8bf5e849SAlexander Usyskin 57*8bf5e849SAlexander Usyskin hw = to_heci_hw(idev); 58*8bf5e849SAlexander Usyskin hw->irq = pci_irq_vector(pdev, 0); 59*8bf5e849SAlexander Usyskin 60*8bf5e849SAlexander Usyskin err = request_threaded_irq(hw->irq, 61*8bf5e849SAlexander Usyskin issei_heci_irq_quick_handler, 62*8bf5e849SAlexander Usyskin NULL, 63*8bf5e849SAlexander Usyskin IRQF_SHARED, KBUILD_MODNAME, idev); 64*8bf5e849SAlexander Usyskin if (err) 65*8bf5e849SAlexander Usyskin goto release_irq; 66*8bf5e849SAlexander Usyskin 67*8bf5e849SAlexander Usyskin err = issei_start(idev); 68*8bf5e849SAlexander Usyskin if (err) { 69*8bf5e849SAlexander Usyskin dev_err_probe(dev, err, "init hw failure.\n"); 70*8bf5e849SAlexander Usyskin goto free_irq; 71*8bf5e849SAlexander Usyskin } 72*8bf5e849SAlexander Usyskin 73*8bf5e849SAlexander Usyskin return 0; 74*8bf5e849SAlexander Usyskin 75*8bf5e849SAlexander Usyskin free_irq: 76*8bf5e849SAlexander Usyskin idev->ops->irq_disable(idev); 77*8bf5e849SAlexander Usyskin free_irq(hw->irq, idev); 78*8bf5e849SAlexander Usyskin release_irq: 79*8bf5e849SAlexander Usyskin pci_free_irq_vectors(pdev); 80*8bf5e849SAlexander Usyskin deregister: 81*8bf5e849SAlexander Usyskin issei_deregister(idev); 82*8bf5e849SAlexander Usyskin return err; 83*8bf5e849SAlexander Usyskin } 84*8bf5e849SAlexander Usyskin 85*8bf5e849SAlexander Usyskin static void issei_heci_shutdown(struct pci_dev *pdev) 86*8bf5e849SAlexander Usyskin { 87*8bf5e849SAlexander Usyskin struct issei_device *idev = pci_get_drvdata(pdev); 88*8bf5e849SAlexander Usyskin struct issei_heci_hw *hw = to_heci_hw(idev); 89*8bf5e849SAlexander Usyskin 90*8bf5e849SAlexander Usyskin issei_stop(idev); 91*8bf5e849SAlexander Usyskin 92*8bf5e849SAlexander Usyskin idev->ops->irq_disable(idev); 93*8bf5e849SAlexander Usyskin free_irq(hw->irq, idev); 94*8bf5e849SAlexander Usyskin pci_free_irq_vectors(pdev); 95*8bf5e849SAlexander Usyskin } 96*8bf5e849SAlexander Usyskin 97*8bf5e849SAlexander Usyskin static void issei_heci_remove(struct pci_dev *pdev) 98*8bf5e849SAlexander Usyskin { 99*8bf5e849SAlexander Usyskin issei_heci_shutdown(pdev); 100*8bf5e849SAlexander Usyskin 101*8bf5e849SAlexander Usyskin issei_deregister(pci_get_drvdata(pdev)); 102*8bf5e849SAlexander Usyskin } 103*8bf5e849SAlexander Usyskin 104*8bf5e849SAlexander Usyskin static int issei_heci_pm_suspend(struct device *device) 105*8bf5e849SAlexander Usyskin { 106*8bf5e849SAlexander Usyskin struct issei_device *idev = dev_get_drvdata(device); 107*8bf5e849SAlexander Usyskin 108*8bf5e849SAlexander Usyskin issei_stop(idev); 109*8bf5e849SAlexander Usyskin idev->ops->irq_disable(idev); 110*8bf5e849SAlexander Usyskin 111*8bf5e849SAlexander Usyskin return 0; 112*8bf5e849SAlexander Usyskin } 113*8bf5e849SAlexander Usyskin 114*8bf5e849SAlexander Usyskin static int issei_heci_pm_resume(struct device *device) 115*8bf5e849SAlexander Usyskin { 116*8bf5e849SAlexander Usyskin struct issei_device *idev = dev_get_drvdata(device); 117*8bf5e849SAlexander Usyskin 118*8bf5e849SAlexander Usyskin return issei_start(idev); 119*8bf5e849SAlexander Usyskin } 120*8bf5e849SAlexander Usyskin 121*8bf5e849SAlexander Usyskin static const struct dev_pm_ops issei_heci_pm_ops = { 122*8bf5e849SAlexander Usyskin SYSTEM_SLEEP_PM_OPS(issei_heci_pm_suspend, issei_heci_pm_resume) 123*8bf5e849SAlexander Usyskin }; 124*8bf5e849SAlexander Usyskin 125*8bf5e849SAlexander Usyskin static const struct pci_device_id heci_pci_tbl[] = { 126*8bf5e849SAlexander Usyskin {PCI_VDEVICE(INTEL, 0xA85D)}, /* Lunar Lake M */ 127*8bf5e849SAlexander Usyskin {PCI_VDEVICE(INTEL, 0xE35D)}, /* Panther Lake H */ 128*8bf5e849SAlexander Usyskin {PCI_VDEVICE(INTEL, 0xE45D)}, /* Panther Lake P */ 129*8bf5e849SAlexander Usyskin {PCI_VDEVICE(INTEL, 0xD470)}, /* Nova Lake S */ 130*8bf5e849SAlexander Usyskin {PCI_VDEVICE(INTEL, 0xD358)}, /* Nova Lake H */ 131*8bf5e849SAlexander Usyskin {PCI_VDEVICE(INTEL, 0x4D5D)}, /* Wildcat Lake */ 132*8bf5e849SAlexander Usyskin {} 133*8bf5e849SAlexander Usyskin }; 134*8bf5e849SAlexander Usyskin MODULE_DEVICE_TABLE(pci, heci_pci_tbl); 135*8bf5e849SAlexander Usyskin 136*8bf5e849SAlexander Usyskin static struct pci_driver issei_heci_driver = { 137*8bf5e849SAlexander Usyskin .name = KBUILD_MODNAME, 138*8bf5e849SAlexander Usyskin .id_table = heci_pci_tbl, 139*8bf5e849SAlexander Usyskin .probe = issei_heci_probe, 140*8bf5e849SAlexander Usyskin .remove = issei_heci_remove, 141*8bf5e849SAlexander Usyskin .shutdown = issei_heci_shutdown, 142*8bf5e849SAlexander Usyskin .driver = { 143*8bf5e849SAlexander Usyskin .pm = &issei_heci_pm_ops, 144*8bf5e849SAlexander Usyskin .probe_type = PROBE_PREFER_ASYNCHRONOUS, 145*8bf5e849SAlexander Usyskin }, 146*8bf5e849SAlexander Usyskin }; 147*8bf5e849SAlexander Usyskin module_pci_driver(issei_heci_driver); 148*8bf5e849SAlexander Usyskin 149*8bf5e849SAlexander Usyskin MODULE_DESCRIPTION("Intel(R) Silicon Security Engine Interface - HECI"); 150*8bf5e849SAlexander Usyskin MODULE_LICENSE("GPL"); 151*8bf5e849SAlexander Usyskin MODULE_IMPORT_NS("INTEL_SSEI"); 152