1*a0c83150SRaag Jadav // SPDX-License-Identifier: GPL-2.0-only 2*a0c83150SRaag Jadav /* 3*a0c83150SRaag Jadav * Intel Elkhart Lake Programmable Service Engine (PSE) I/O 4*a0c83150SRaag Jadav * 5*a0c83150SRaag Jadav * Copyright (c) 2025 Intel Corporation. 6*a0c83150SRaag Jadav * 7*a0c83150SRaag Jadav * Author: Raag Jadav <raag.jadav@intel.com> 8*a0c83150SRaag Jadav */ 9*a0c83150SRaag Jadav 10*a0c83150SRaag Jadav #include <linux/auxiliary_bus.h> 11*a0c83150SRaag Jadav #include <linux/device/devres.h> 12*a0c83150SRaag Jadav #include <linux/errno.h> 13*a0c83150SRaag Jadav #include <linux/gfp_types.h> 14*a0c83150SRaag Jadav #include <linux/ioport.h> 15*a0c83150SRaag Jadav #include <linux/mod_devicetable.h> 16*a0c83150SRaag Jadav #include <linux/module.h> 17*a0c83150SRaag Jadav #include <linux/pci.h> 18*a0c83150SRaag Jadav #include <linux/sizes.h> 19*a0c83150SRaag Jadav #include <linux/types.h> 20*a0c83150SRaag Jadav 21*a0c83150SRaag Jadav #include <linux/ehl_pse_io_aux.h> 22*a0c83150SRaag Jadav 23*a0c83150SRaag Jadav #define EHL_PSE_IO_DEV_SIZE SZ_4K 24*a0c83150SRaag Jadav 25*a0c83150SRaag Jadav static int ehl_pse_io_dev_create(struct pci_dev *pci, const char *name, int idx) 26*a0c83150SRaag Jadav { 27*a0c83150SRaag Jadav struct device *dev = &pci->dev; 28*a0c83150SRaag Jadav struct auxiliary_device *adev; 29*a0c83150SRaag Jadav struct ehl_pse_io_data *data; 30*a0c83150SRaag Jadav resource_size_t start, offset; 31*a0c83150SRaag Jadav u32 id; 32*a0c83150SRaag Jadav 33*a0c83150SRaag Jadav data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 34*a0c83150SRaag Jadav if (!data) 35*a0c83150SRaag Jadav return -ENOMEM; 36*a0c83150SRaag Jadav 37*a0c83150SRaag Jadav id = (pci_domain_nr(pci->bus) << 16) | pci_dev_id(pci); 38*a0c83150SRaag Jadav start = pci_resource_start(pci, 0); 39*a0c83150SRaag Jadav offset = EHL_PSE_IO_DEV_SIZE * idx; 40*a0c83150SRaag Jadav 41*a0c83150SRaag Jadav data->mem = DEFINE_RES_MEM(start + offset, EHL_PSE_IO_DEV_SIZE); 42*a0c83150SRaag Jadav data->irq = pci_irq_vector(pci, idx); 43*a0c83150SRaag Jadav 44*a0c83150SRaag Jadav adev = __devm_auxiliary_device_create(dev, EHL_PSE_IO_NAME, name, data, id); 45*a0c83150SRaag Jadav 46*a0c83150SRaag Jadav return adev ? 0 : -ENODEV; 47*a0c83150SRaag Jadav } 48*a0c83150SRaag Jadav 49*a0c83150SRaag Jadav static int ehl_pse_io_probe(struct pci_dev *pci, const struct pci_device_id *id) 50*a0c83150SRaag Jadav { 51*a0c83150SRaag Jadav int ret; 52*a0c83150SRaag Jadav 53*a0c83150SRaag Jadav ret = pcim_enable_device(pci); 54*a0c83150SRaag Jadav if (ret) 55*a0c83150SRaag Jadav return ret; 56*a0c83150SRaag Jadav 57*a0c83150SRaag Jadav pci_set_master(pci); 58*a0c83150SRaag Jadav 59*a0c83150SRaag Jadav ret = pci_alloc_irq_vectors(pci, 2, 2, PCI_IRQ_MSI); 60*a0c83150SRaag Jadav if (ret < 0) 61*a0c83150SRaag Jadav return ret; 62*a0c83150SRaag Jadav 63*a0c83150SRaag Jadav ret = ehl_pse_io_dev_create(pci, EHL_PSE_GPIO_NAME, 0); 64*a0c83150SRaag Jadav if (ret) 65*a0c83150SRaag Jadav return ret; 66*a0c83150SRaag Jadav 67*a0c83150SRaag Jadav return ehl_pse_io_dev_create(pci, EHL_PSE_TIO_NAME, 1); 68*a0c83150SRaag Jadav } 69*a0c83150SRaag Jadav 70*a0c83150SRaag Jadav static const struct pci_device_id ehl_pse_io_ids[] = { 71*a0c83150SRaag Jadav { PCI_VDEVICE(INTEL, 0x4b88) }, 72*a0c83150SRaag Jadav { PCI_VDEVICE(INTEL, 0x4b89) }, 73*a0c83150SRaag Jadav { } 74*a0c83150SRaag Jadav }; 75*a0c83150SRaag Jadav MODULE_DEVICE_TABLE(pci, ehl_pse_io_ids); 76*a0c83150SRaag Jadav 77*a0c83150SRaag Jadav static struct pci_driver ehl_pse_io_driver = { 78*a0c83150SRaag Jadav .name = EHL_PSE_IO_NAME, 79*a0c83150SRaag Jadav .id_table = ehl_pse_io_ids, 80*a0c83150SRaag Jadav .probe = ehl_pse_io_probe, 81*a0c83150SRaag Jadav }; 82*a0c83150SRaag Jadav module_pci_driver(ehl_pse_io_driver); 83*a0c83150SRaag Jadav 84*a0c83150SRaag Jadav MODULE_AUTHOR("Raag Jadav <raag.jadav@intel.com>"); 85*a0c83150SRaag Jadav MODULE_DESCRIPTION("Intel Elkhart Lake PSE I/O driver"); 86*a0c83150SRaag Jadav MODULE_LICENSE("GPL"); 87