forked from mirrors/linux
		
	gpio: langwell: add Intel Merrifield support
This patch implements a better way to handle multiple SoC's and adds Intel Merrifield support to gpio-langwell. It was based on previous work from Ning Li <ning.li@intel.com> Signed-off-by: David Cohen <david.a.cohen@linux.intel.com> Signed-off-by: Fei Yang <fei.yang@intel.com> Signed-off-by: Ning Li <ning.li@intel.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
		
							parent
							
								
									70b5341138
								
							
						
					
					
						commit
						d56d6b3d7d
					
				
					 1 changed files with 82 additions and 11 deletions
				
			
		| 
						 | 
					@ -37,6 +37,9 @@
 | 
				
			||||||
#include <linux/pm_runtime.h>
 | 
					#include <linux/pm_runtime.h>
 | 
				
			||||||
#include <linux/irqdomain.h>
 | 
					#include <linux/irqdomain.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LNW_IRQ_TYPE_EDGE	(1 << 0)
 | 
				
			||||||
 | 
					#define LNW_IRQ_TYPE_LEVEL	(1 << 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Langwell chip has 64 pins and thus there are 2 32bit registers to control
 | 
					 * Langwell chip has 64 pins and thus there are 2 32bit registers to control
 | 
				
			||||||
 * each feature, while Penwell chip has 96 pins for each block, and need 3 32bit
 | 
					 * each feature, while Penwell chip has 96 pins for each block, and need 3 32bit
 | 
				
			||||||
| 
						 | 
					@ -62,6 +65,16 @@ enum GPIO_REG {
 | 
				
			||||||
	GAFR,		/* alt function */
 | 
						GAFR,		/* alt function */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* langwell gpio driver data */
 | 
				
			||||||
 | 
					struct lnw_gpio_ddata {
 | 
				
			||||||
 | 
						u16 ngpio;		/* number of gpio pins */
 | 
				
			||||||
 | 
						u32 gplr_offset;	/* offset of first GPLR register from base */
 | 
				
			||||||
 | 
						u32 flis_base;		/* base address of FLIS registers */
 | 
				
			||||||
 | 
						u32 flis_len;		/* length of FLIS registers */
 | 
				
			||||||
 | 
						u32 (*get_flis_offset)(int gpio);
 | 
				
			||||||
 | 
						u32 chip_irq_type;	/* chip interrupt type */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct lnw_gpio {
 | 
					struct lnw_gpio {
 | 
				
			||||||
	struct gpio_chip		chip;
 | 
						struct gpio_chip		chip;
 | 
				
			||||||
	void __iomem			*reg_base;
 | 
						void __iomem			*reg_base;
 | 
				
			||||||
| 
						 | 
					@ -227,13 +240,71 @@ static struct irq_chip lnw_irqchip = {
 | 
				
			||||||
	.irq_set_type	= lnw_irq_type,
 | 
						.irq_set_type	= lnw_irq_type,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = {   /* pin number */
 | 
					static const struct lnw_gpio_ddata gpio_lincroft = {
 | 
				
			||||||
	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f), .driver_data = 64 },
 | 
						.ngpio = 64,
 | 
				
			||||||
	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f), .driver_data = 96 },
 | 
					};
 | 
				
			||||||
	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a), .driver_data = 96 },
 | 
					
 | 
				
			||||||
	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08eb), .driver_data = 96 },
 | 
					static const struct lnw_gpio_ddata gpio_penwell_aon = {
 | 
				
			||||||
	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08f7), .driver_data = 96 },
 | 
						.ngpio = 96,
 | 
				
			||||||
	{ 0, }
 | 
						.chip_irq_type = LNW_IRQ_TYPE_EDGE,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct lnw_gpio_ddata gpio_penwell_core = {
 | 
				
			||||||
 | 
						.ngpio = 96,
 | 
				
			||||||
 | 
						.chip_irq_type = LNW_IRQ_TYPE_EDGE,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct lnw_gpio_ddata gpio_cloverview_aon = {
 | 
				
			||||||
 | 
						.ngpio = 96,
 | 
				
			||||||
 | 
						.chip_irq_type = LNW_IRQ_TYPE_EDGE | LNW_IRQ_TYPE_LEVEL,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct lnw_gpio_ddata gpio_cloverview_core = {
 | 
				
			||||||
 | 
						.ngpio = 96,
 | 
				
			||||||
 | 
						.chip_irq_type = LNW_IRQ_TYPE_EDGE,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct lnw_gpio_ddata gpio_tangier = {
 | 
				
			||||||
 | 
						.ngpio = 192,
 | 
				
			||||||
 | 
						.gplr_offset = 4,
 | 
				
			||||||
 | 
						.flis_base = 0xff0c0000,
 | 
				
			||||||
 | 
						.flis_len = 0x8000,
 | 
				
			||||||
 | 
						.get_flis_offset = NULL,
 | 
				
			||||||
 | 
						.chip_irq_type = LNW_IRQ_TYPE_EDGE,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = {
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* Lincroft */
 | 
				
			||||||
 | 
							PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f),
 | 
				
			||||||
 | 
							.driver_data = (kernel_ulong_t)&gpio_lincroft,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* Penwell AON */
 | 
				
			||||||
 | 
							PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f),
 | 
				
			||||||
 | 
							.driver_data = (kernel_ulong_t)&gpio_penwell_aon,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* Penwell Core */
 | 
				
			||||||
 | 
							PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a),
 | 
				
			||||||
 | 
							.driver_data = (kernel_ulong_t)&gpio_penwell_core,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* Cloverview Aon */
 | 
				
			||||||
 | 
							PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08eb),
 | 
				
			||||||
 | 
							.driver_data = (kernel_ulong_t)&gpio_cloverview_aon,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* Cloverview Core */
 | 
				
			||||||
 | 
							PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08f7),
 | 
				
			||||||
 | 
							.driver_data = (kernel_ulong_t)&gpio_cloverview_core,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* Tangier */
 | 
				
			||||||
 | 
							PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1199),
 | 
				
			||||||
 | 
							.driver_data = (kernel_ulong_t)&gpio_tangier,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{ 0 }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
MODULE_DEVICE_TABLE(pci, lnw_gpio_ids);
 | 
					MODULE_DEVICE_TABLE(pci, lnw_gpio_ids);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -316,7 +387,7 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
 | 
				
			||||||
	u32 gpio_base;
 | 
						u32 gpio_base;
 | 
				
			||||||
	u32 irq_base;
 | 
						u32 irq_base;
 | 
				
			||||||
	int retval;
 | 
						int retval;
 | 
				
			||||||
	int ngpio = id->driver_data;
 | 
						struct lnw_gpio_ddata *ddata = (struct lnw_gpio_ddata *)id->driver_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	retval = pcim_enable_device(pdev);
 | 
						retval = pcim_enable_device(pdev);
 | 
				
			||||||
	if (retval)
 | 
						if (retval)
 | 
				
			||||||
| 
						 | 
					@ -351,14 +422,14 @@ static int lnw_gpio_probe(struct pci_dev *pdev,
 | 
				
			||||||
	lnw->chip.set = lnw_gpio_set;
 | 
						lnw->chip.set = lnw_gpio_set;
 | 
				
			||||||
	lnw->chip.to_irq = lnw_gpio_to_irq;
 | 
						lnw->chip.to_irq = lnw_gpio_to_irq;
 | 
				
			||||||
	lnw->chip.base = gpio_base;
 | 
						lnw->chip.base = gpio_base;
 | 
				
			||||||
	lnw->chip.ngpio = ngpio;
 | 
						lnw->chip.ngpio = ddata->ngpio;
 | 
				
			||||||
	lnw->chip.can_sleep = 0;
 | 
						lnw->chip.can_sleep = 0;
 | 
				
			||||||
	lnw->pdev = pdev;
 | 
						lnw->pdev = pdev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_init(&lnw->lock);
 | 
						spin_lock_init(&lnw->lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lnw->domain = irq_domain_add_simple(pdev->dev.of_node, ngpio, irq_base,
 | 
						lnw->domain = irq_domain_add_simple(pdev->dev.of_node, ddata->ngpio,
 | 
				
			||||||
					    &lnw_gpio_irq_ops, lnw);
 | 
										    irq_base, &lnw_gpio_irq_ops, lnw);
 | 
				
			||||||
	if (!lnw->domain)
 | 
						if (!lnw->domain)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue