2018-11-06 14:11:42 +02:00
// SPDX-License-Identifier: GPL-2.0
2016-07-08 14:08:23 +03:00
/*
* Intel Merrifield SoC GPIO driver
*
2023-02-16 20:34:19 +02:00
* Copyright ( c ) 2016 , 2023 Intel Corporation .
2016-07-08 14:08:23 +03:00
* Author : Andy Shevchenko < andriy . shevchenko @ linux . intel . com >
*/
2018-01-05 18:09:34 +02:00
# include <linux/acpi.h>
2016-07-08 14:08:23 +03:00
# include <linux/bitops.h>
2023-02-16 20:34:19 +02:00
# include <linux/device.h>
# include <linux/err.h>
2016-07-08 14:08:23 +03:00
# include <linux/io.h>
# include <linux/module.h>
# include <linux/pci.h>
2023-02-16 20:34:19 +02:00
# include <linux/types.h>
2016-07-08 14:08:23 +03:00
2023-02-16 20:34:19 +02:00
# include "gpio-tangier.h"
2016-07-08 14:08:23 +03:00
/* Intel Merrifield has 192 GPIO pins */
# define MRFLD_NGPIO 192
2023-02-16 20:34:19 +02:00
static const struct tng_gpio_pinrange mrfld_gpio_ranges [ ] = {
2016-07-08 14:08:23 +03:00
GPIO_PINRANGE ( 0 , 11 , 146 ) ,
GPIO_PINRANGE ( 12 , 13 , 144 ) ,
GPIO_PINRANGE ( 14 , 15 , 35 ) ,
GPIO_PINRANGE ( 16 , 16 , 164 ) ,
GPIO_PINRANGE ( 17 , 18 , 105 ) ,
GPIO_PINRANGE ( 19 , 22 , 101 ) ,
GPIO_PINRANGE ( 23 , 30 , 107 ) ,
GPIO_PINRANGE ( 32 , 43 , 67 ) ,
GPIO_PINRANGE ( 44 , 63 , 195 ) ,
GPIO_PINRANGE ( 64 , 67 , 140 ) ,
GPIO_PINRANGE ( 68 , 69 , 165 ) ,
GPIO_PINRANGE ( 70 , 71 , 65 ) ,
GPIO_PINRANGE ( 72 , 76 , 228 ) ,
GPIO_PINRANGE ( 77 , 86 , 37 ) ,
GPIO_PINRANGE ( 87 , 87 , 48 ) ,
GPIO_PINRANGE ( 88 , 88 , 47 ) ,
GPIO_PINRANGE ( 89 , 96 , 49 ) ,
GPIO_PINRANGE ( 97 , 97 , 34 ) ,
GPIO_PINRANGE ( 102 , 119 , 83 ) ,
GPIO_PINRANGE ( 120 , 123 , 79 ) ,
GPIO_PINRANGE ( 124 , 135 , 115 ) ,
GPIO_PINRANGE ( 137 , 142 , 158 ) ,
GPIO_PINRANGE ( 154 , 163 , 24 ) ,
GPIO_PINRANGE ( 164 , 176 , 215 ) ,
GPIO_PINRANGE ( 177 , 189 , 127 ) ,
GPIO_PINRANGE ( 190 , 191 , 178 ) ,
} ;
2023-02-16 20:34:19 +02:00
static const char * mrfld_gpio_get_pinctrl_dev_name ( struct tng_gpio * priv )
2018-01-05 18:09:34 +02:00
{
2023-02-16 20:03:42 +02:00
struct device * dev = priv - > dev ;
2019-03-28 19:17:22 +02:00
struct acpi_device * adev ;
const char * name ;
adev = acpi_dev_get_first_match_dev ( " INTC1002 " , NULL , - 1 ) ;
if ( adev ) {
2023-02-16 20:03:42 +02:00
name = devm_kstrdup ( dev , acpi_dev_name ( adev ) , GFP_KERNEL ) ;
2019-04-12 23:19:11 +08:00
acpi_dev_put ( adev ) ;
2019-03-28 19:17:22 +02:00
} else {
name = " pinctrl-merrifield " ;
}
return name ;
2018-01-05 18:09:34 +02:00
}
2019-11-04 19:07:30 +02:00
static int mrfld_gpio_probe ( struct pci_dev * pdev , const struct pci_device_id * id )
{
2023-02-16 20:34:19 +02:00
struct device * dev = & pdev - > dev ;
struct tng_gpio * priv ;
2016-07-08 14:08:23 +03:00
u32 gpio_base , irq_base ;
void __iomem * base ;
int retval ;
retval = pcim_enable_device ( pdev ) ;
if ( retval )
return retval ;
retval = pcim_iomap_regions ( pdev , BIT ( 1 ) | BIT ( 0 ) , pci_name ( pdev ) ) ;
2023-01-16 15:44:46 +01:00
if ( retval )
return dev_err_probe ( dev , retval , " I/O memory mapping error \n " ) ;
2016-07-08 14:08:23 +03:00
base = pcim_iomap_table ( pdev ) [ 1 ] ;
2020-04-08 18:41:55 +03:00
irq_base = readl ( base + 0 * sizeof ( u32 ) ) ;
gpio_base = readl ( base + 1 * sizeof ( u32 ) ) ;
2016-07-08 14:08:23 +03:00
/* Release the IO mapping, since we already get the info from BAR1 */
pcim_iounmap_regions ( pdev , BIT ( 1 ) ) ;
2023-02-16 20:03:42 +02:00
priv = devm_kzalloc ( dev , sizeof ( * priv ) , GFP_KERNEL ) ;
2018-02-11 13:30:14 +01:00
if ( ! priv )
2016-07-08 14:08:23 +03:00
return - ENOMEM ;
2023-02-16 20:03:42 +02:00
priv - > dev = dev ;
2016-07-08 14:08:23 +03:00
priv - > reg_base = pcim_iomap_table ( pdev ) [ 0 ] ;
2023-02-16 20:34:19 +02:00
priv - > pin_info . pin_ranges = mrfld_gpio_ranges ;
priv - > pin_info . nranges = ARRAY_SIZE ( mrfld_gpio_ranges ) ;
priv - > pin_info . name = mrfld_gpio_get_pinctrl_dev_name ( priv ) ;
if ( ! priv - > pin_info . name )
return - ENOMEM ;
2016-07-08 14:08:23 +03:00
2023-02-16 20:34:19 +02:00
priv - > info . base = gpio_base ;
priv - > info . ngpio = MRFLD_NGPIO ;
priv - > info . first = irq_base ;
2016-07-08 14:08:23 +03:00
2020-04-08 18:41:54 +03:00
retval = pci_alloc_irq_vectors ( pdev , 1 , 1 , PCI_IRQ_ALL_TYPES ) ;
if ( retval < 0 )
return retval ;
2023-02-16 20:34:19 +02:00
priv - > irq = pci_irq_vector ( pdev , 0 ) ;
2019-11-04 19:10:10 +02:00
2023-02-16 20:34:19 +02:00
priv - > wake_regs . gwmr = GWMR_MRFLD ;
priv - > wake_regs . gwsr = GWSR_MRFLD ;
priv - > wake_regs . gsir = GSIR_MRFLD ;
retval = devm_tng_gpio_probe ( dev , priv ) ;
if ( retval )
return dev_err_probe ( dev , retval , " tng_gpio_probe error \n " ) ;
2016-07-08 14:08:23 +03:00
2019-11-04 19:07:30 +02:00
pci_set_drvdata ( pdev , priv ) ;
2016-07-08 14:08:23 +03:00
return 0 ;
}
static const struct pci_device_id mrfld_gpio_ids [ ] = {
{ PCI_VDEVICE ( INTEL , 0x1199 ) } ,
{ }
} ;
MODULE_DEVICE_TABLE ( pci , mrfld_gpio_ids ) ;
static struct pci_driver mrfld_gpio_driver = {
. name = " gpio-merrifield " ,
. id_table = mrfld_gpio_ids ,
. probe = mrfld_gpio_probe ,
} ;
module_pci_driver ( mrfld_gpio_driver ) ;
MODULE_AUTHOR ( " Andy Shevchenko <andriy.shevchenko@linux.intel.com> " ) ;
MODULE_DESCRIPTION ( " Intel Merrifield SoC GPIO driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
2023-02-16 20:34:19 +02:00
MODULE_IMPORT_NS ( GPIO_TANGIER ) ;