193374b76SAndy Shevchenko // SPDX-License-Identifier: GPL-2.0 2ccf6fd6dSAndy Shevchenko /* 3ccf6fd6dSAndy Shevchenko * Intel Merrifield SoC GPIO driver 4ccf6fd6dSAndy Shevchenko * 534840be5SPandith N * Copyright (c) 2016, 2023 Intel Corporation. 6ccf6fd6dSAndy Shevchenko * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> 7ccf6fd6dSAndy Shevchenko */ 8ccf6fd6dSAndy Shevchenko 9dd1dbf94SAndy Shevchenko #include <linux/acpi.h> 10ccf6fd6dSAndy Shevchenko #include <linux/bitops.h> 1134840be5SPandith N #include <linux/device.h> 1234840be5SPandith N #include <linux/err.h> 13ccf6fd6dSAndy Shevchenko #include <linux/io.h> 14ccf6fd6dSAndy Shevchenko #include <linux/module.h> 15ccf6fd6dSAndy Shevchenko #include <linux/pci.h> 1634840be5SPandith N #include <linux/types.h> 17ccf6fd6dSAndy Shevchenko 1834840be5SPandith N #include "gpio-tangier.h" 19ccf6fd6dSAndy Shevchenko 20ccf6fd6dSAndy Shevchenko /* Intel Merrifield has 192 GPIO pins */ 21ccf6fd6dSAndy Shevchenko #define MRFLD_NGPIO 192 22ccf6fd6dSAndy Shevchenko 2334840be5SPandith N static const struct tng_gpio_pinrange mrfld_gpio_ranges[] = { 24ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(0, 11, 146), 25ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(12, 13, 144), 26ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(14, 15, 35), 27ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(16, 16, 164), 28ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(17, 18, 105), 29ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(19, 22, 101), 30ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(23, 30, 107), 31ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(32, 43, 67), 32ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(44, 63, 195), 33ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(64, 67, 140), 34ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(68, 69, 165), 35ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(70, 71, 65), 36ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(72, 76, 228), 37ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(77, 86, 37), 38ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(87, 87, 48), 39ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(88, 88, 47), 40ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(89, 96, 49), 41ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(97, 97, 34), 42ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(102, 119, 83), 43ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(120, 123, 79), 44ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(124, 135, 115), 45ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(137, 142, 158), 46ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(154, 163, 24), 47ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(164, 176, 215), 48ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(177, 189, 127), 49ccf6fd6dSAndy Shevchenko GPIO_PINRANGE(190, 191, 178), 50ccf6fd6dSAndy Shevchenko }; 51ccf6fd6dSAndy Shevchenko 5234840be5SPandith N static const char *mrfld_gpio_get_pinctrl_dev_name(struct tng_gpio *priv) 53dd1dbf94SAndy Shevchenko { 54*dc537030SAndy Shevchenko struct device *dev = priv->dev; 55d00d2109SAndy Shevchenko struct acpi_device *adev; 56d00d2109SAndy Shevchenko const char *name; 57d00d2109SAndy Shevchenko 58d00d2109SAndy Shevchenko adev = acpi_dev_get_first_match_dev("INTC1002", NULL, -1); 59d00d2109SAndy Shevchenko if (adev) { 60*dc537030SAndy Shevchenko name = devm_kstrdup(dev, acpi_dev_name(adev), GFP_KERNEL); 61fe066621SYueHaibing acpi_dev_put(adev); 62d00d2109SAndy Shevchenko } else { 63d00d2109SAndy Shevchenko name = "pinctrl-merrifield"; 64d00d2109SAndy Shevchenko } 65d00d2109SAndy Shevchenko 66d00d2109SAndy Shevchenko return name; 67dd1dbf94SAndy Shevchenko } 68dd1dbf94SAndy Shevchenko 69cd242b33SAndy Shevchenko static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id) 70cd242b33SAndy Shevchenko { 7134840be5SPandith N struct device *dev = &pdev->dev; 7234840be5SPandith N struct tng_gpio *priv; 73ccf6fd6dSAndy Shevchenko u32 gpio_base, irq_base; 74ccf6fd6dSAndy Shevchenko void __iomem *base; 75ccf6fd6dSAndy Shevchenko int retval; 76ccf6fd6dSAndy Shevchenko 77ccf6fd6dSAndy Shevchenko retval = pcim_enable_device(pdev); 78ccf6fd6dSAndy Shevchenko if (retval) 79ccf6fd6dSAndy Shevchenko return retval; 80ccf6fd6dSAndy Shevchenko 81ccf6fd6dSAndy Shevchenko retval = pcim_iomap_regions(pdev, BIT(1) | BIT(0), pci_name(pdev)); 82dd0ccef2SAndy Shevchenko if (retval) 83dd0ccef2SAndy Shevchenko return dev_err_probe(dev, retval, "I/O memory mapping error\n"); 84ccf6fd6dSAndy Shevchenko 85ccf6fd6dSAndy Shevchenko base = pcim_iomap_table(pdev)[1]; 86ccf6fd6dSAndy Shevchenko 877e73aa90SAndy Shevchenko irq_base = readl(base + 0 * sizeof(u32)); 887e73aa90SAndy Shevchenko gpio_base = readl(base + 1 * sizeof(u32)); 89ccf6fd6dSAndy Shevchenko 90ccf6fd6dSAndy Shevchenko /* Release the IO mapping, since we already get the info from BAR1 */ 91ccf6fd6dSAndy Shevchenko pcim_iounmap_regions(pdev, BIT(1)); 92ccf6fd6dSAndy Shevchenko 93*dc537030SAndy Shevchenko priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 944b7edaefSMarkus Elfring if (!priv) 95ccf6fd6dSAndy Shevchenko return -ENOMEM; 96ccf6fd6dSAndy Shevchenko 97*dc537030SAndy Shevchenko priv->dev = dev; 98ccf6fd6dSAndy Shevchenko priv->reg_base = pcim_iomap_table(pdev)[0]; 99ccf6fd6dSAndy Shevchenko 10034840be5SPandith N priv->pin_info.pin_ranges = mrfld_gpio_ranges; 10134840be5SPandith N priv->pin_info.nranges = ARRAY_SIZE(mrfld_gpio_ranges); 10234840be5SPandith N priv->pin_info.name = mrfld_gpio_get_pinctrl_dev_name(priv); 10334840be5SPandith N if (!priv->pin_info.name) 10434840be5SPandith N return -ENOMEM; 105ccf6fd6dSAndy Shevchenko 10634840be5SPandith N priv->info.base = gpio_base; 10734840be5SPandith N priv->info.ngpio = MRFLD_NGPIO; 10834840be5SPandith N priv->info.first = irq_base; 109ccf6fd6dSAndy Shevchenko 1106b1c7837SAndy Shevchenko retval = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); 1116b1c7837SAndy Shevchenko if (retval < 0) 1126b1c7837SAndy Shevchenko return retval; 1136b1c7837SAndy Shevchenko 11434840be5SPandith N priv->irq = pci_irq_vector(pdev, 0); 1154a5e0f9eSAndy Shevchenko 11634840be5SPandith N priv->wake_regs.gwmr = GWMR_MRFLD; 11734840be5SPandith N priv->wake_regs.gwsr = GWSR_MRFLD; 11834840be5SPandith N priv->wake_regs.gsir = GSIR_MRFLD; 11934840be5SPandith N 12034840be5SPandith N retval = devm_tng_gpio_probe(dev, priv); 12134840be5SPandith N if (retval) 12234840be5SPandith N return dev_err_probe(dev, retval, "tng_gpio_probe error\n"); 123ccf6fd6dSAndy Shevchenko 124cd242b33SAndy Shevchenko pci_set_drvdata(pdev, priv); 125ccf6fd6dSAndy Shevchenko return 0; 126ccf6fd6dSAndy Shevchenko } 127ccf6fd6dSAndy Shevchenko 128ccf6fd6dSAndy Shevchenko static const struct pci_device_id mrfld_gpio_ids[] = { 129ccf6fd6dSAndy Shevchenko { PCI_VDEVICE(INTEL, 0x1199) }, 130ccf6fd6dSAndy Shevchenko { } 131ccf6fd6dSAndy Shevchenko }; 132ccf6fd6dSAndy Shevchenko MODULE_DEVICE_TABLE(pci, mrfld_gpio_ids); 133ccf6fd6dSAndy Shevchenko 134ccf6fd6dSAndy Shevchenko static struct pci_driver mrfld_gpio_driver = { 135ccf6fd6dSAndy Shevchenko .name = "gpio-merrifield", 136ccf6fd6dSAndy Shevchenko .id_table = mrfld_gpio_ids, 137ccf6fd6dSAndy Shevchenko .probe = mrfld_gpio_probe, 138ccf6fd6dSAndy Shevchenko }; 139ccf6fd6dSAndy Shevchenko module_pci_driver(mrfld_gpio_driver); 140ccf6fd6dSAndy Shevchenko 141ccf6fd6dSAndy Shevchenko MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); 142ccf6fd6dSAndy Shevchenko MODULE_DESCRIPTION("Intel Merrifield SoC GPIO driver"); 143ccf6fd6dSAndy Shevchenko MODULE_LICENSE("GPL v2"); 14434840be5SPandith N MODULE_IMPORT_NS(GPIO_TANGIER); 145