2015-03-24 20:58:51 +03:00
/*
* ACPI GSI IRQ layer
*
* Copyright ( C ) 2015 ARM Ltd .
* Author : Lorenzo Pieralisi < lorenzo . pieralisi @ arm . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/acpi.h>
# include <linux/irq.h>
# include <linux/irqdomain.h>
2015-10-13 14:51:37 +03:00
# include <linux/of.h>
2015-03-24 20:58:51 +03:00
enum acpi_irq_model_id acpi_irq_model ;
2015-10-13 14:51:37 +03:00
static struct fwnode_handle * acpi_gsi_domain_id ;
2015-03-24 20:58:51 +03:00
/**
* acpi_gsi_to_irq ( ) - Retrieve the linux irq number for a given GSI
* @ gsi : GSI IRQ number to map
* @ irq : pointer where linux IRQ number is stored
*
* irq location updated with irq value [ > 0 on success , 0 on failure ]
*
* Returns : linux IRQ number on success ( > 0 )
* - EINVAL on failure
*/
int acpi_gsi_to_irq ( u32 gsi , unsigned int * irq )
{
2015-10-13 14:51:37 +03:00
struct irq_domain * d = irq_find_matching_fwnode ( acpi_gsi_domain_id ,
DOMAIN_BUS_ANY ) ;
* irq = irq_find_mapping ( d , gsi ) ;
2015-03-24 20:58:51 +03:00
/*
* * irq = = 0 means no mapping , that should
* be reported as a failure
*/
return ( * irq > 0 ) ? * irq : - EINVAL ;
}
EXPORT_SYMBOL_GPL ( acpi_gsi_to_irq ) ;
/**
* acpi_register_gsi ( ) - Map a GSI to a linux IRQ number
* @ dev : device for which IRQ has to be mapped
* @ gsi : GSI IRQ number
* @ trigger : trigger type of the GSI number to be mapped
* @ polarity : polarity of the GSI to be mapped
*
* Returns : a valid linux IRQ number on success
* - EINVAL on failure
*/
int acpi_register_gsi ( struct device * dev , u32 gsi , int trigger ,
int polarity )
{
2015-10-13 14:51:42 +03:00
struct irq_fwspec fwspec ;
2015-03-24 20:58:51 +03:00
2015-10-13 14:51:42 +03:00
if ( WARN_ON ( ! acpi_gsi_domain_id ) ) {
pr_warn ( " GSI: No registered irqchip, giving up \n " ) ;
return - EINVAL ;
2015-10-13 14:51:38 +03:00
}
2015-03-24 20:58:51 +03:00
2015-10-13 14:51:42 +03:00
fwspec . fwnode = acpi_gsi_domain_id ;
fwspec . param [ 0 ] = gsi ;
2015-12-24 01:25:33 +03:00
fwspec . param [ 1 ] = acpi_dev_get_irq_type ( trigger , polarity ) ;
2015-10-13 14:51:42 +03:00
fwspec . param_count = 2 ;
return irq_create_fwspec_mapping ( & fwspec ) ;
2015-03-24 20:58:51 +03:00
}
EXPORT_SYMBOL_GPL ( acpi_register_gsi ) ;
/**
* acpi_unregister_gsi ( ) - Free a GSI < - > linux IRQ number mapping
* @ gsi : GSI IRQ number
*/
void acpi_unregister_gsi ( u32 gsi )
{
2015-10-13 14:51:37 +03:00
struct irq_domain * d = irq_find_matching_fwnode ( acpi_gsi_domain_id ,
DOMAIN_BUS_ANY ) ;
int irq = irq_find_mapping ( d , gsi ) ;
2015-03-24 20:58:51 +03:00
irq_dispose_mapping ( irq ) ;
}
EXPORT_SYMBOL_GPL ( acpi_unregister_gsi ) ;
2015-10-13 14:51:38 +03:00
/**
* acpi_set_irq_model - Setup the GSI irqdomain information
* @ model : the value assigned to acpi_irq_model
* @ fwnode : the irq_domain identifier for mapping and looking up
* GSI interrupts
*/
void __init acpi_set_irq_model ( enum acpi_irq_model_id model ,
struct fwnode_handle * fwnode )
{
acpi_irq_model = model ;
acpi_gsi_domain_id = fwnode ;
}