|
@@ -21,6 +21,7 @@
|
|
#include <linux/pm.h>
|
|
#include <linux/pm.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/of.h>
|
|
#include <linux/of.h>
|
|
|
|
+#include <linux/irqdomain.h>
|
|
#include <uapi/linux/input.h>
|
|
#include <uapi/linux/input.h>
|
|
#include <linux/rmi.h>
|
|
#include <linux/rmi.h>
|
|
#include "rmi_bus.h"
|
|
#include "rmi_bus.h"
|
|
@@ -127,28 +128,11 @@ static int rmi_driver_process_config_requests(struct rmi_device *rmi_dev)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static void process_one_interrupt(struct rmi_driver_data *data,
|
|
|
|
- struct rmi_function *fn)
|
|
|
|
-{
|
|
|
|
- struct rmi_function_handler *fh;
|
|
|
|
-
|
|
|
|
- if (!fn || !fn->dev.driver)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- fh = to_rmi_function_handler(fn->dev.driver);
|
|
|
|
- if (fh->attention) {
|
|
|
|
- bitmap_and(data->fn_irq_bits, data->irq_status, fn->irq_mask,
|
|
|
|
- data->irq_count);
|
|
|
|
- if (!bitmap_empty(data->fn_irq_bits, data->irq_count))
|
|
|
|
- fh->attention(fn, data->fn_irq_bits);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
|
|
static int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
|
|
{
|
|
{
|
|
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
|
|
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
|
|
struct device *dev = &rmi_dev->dev;
|
|
struct device *dev = &rmi_dev->dev;
|
|
- struct rmi_function *entry;
|
|
|
|
|
|
+ int i;
|
|
int error;
|
|
int error;
|
|
|
|
|
|
if (!data)
|
|
if (!data)
|
|
@@ -173,16 +157,8 @@ static int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
|
|
*/
|
|
*/
|
|
mutex_unlock(&data->irq_mutex);
|
|
mutex_unlock(&data->irq_mutex);
|
|
|
|
|
|
- /*
|
|
|
|
- * It would be nice to be able to use irq_chip to handle these
|
|
|
|
- * nested IRQs. Unfortunately, most of the current customers for
|
|
|
|
- * this driver are using older kernels (3.0.x) that don't support
|
|
|
|
- * the features required for that. Once they've shifted to more
|
|
|
|
- * recent kernels (say, 3.3 and higher), this should be switched to
|
|
|
|
- * use irq_chip.
|
|
|
|
- */
|
|
|
|
- list_for_each_entry(entry, &data->function_list, node)
|
|
|
|
- process_one_interrupt(data, entry);
|
|
|
|
|
|
+ for_each_set_bit(i, data->irq_status, data->irq_count)
|
|
|
|
+ handle_nested_irq(irq_find_mapping(data->irqdomain, i));
|
|
|
|
|
|
if (data->input)
|
|
if (data->input)
|
|
input_sync(data->input);
|
|
input_sync(data->input);
|
|
@@ -1001,9 +977,13 @@ EXPORT_SYMBOL_GPL(rmi_driver_resume);
|
|
static int rmi_driver_remove(struct device *dev)
|
|
static int rmi_driver_remove(struct device *dev)
|
|
{
|
|
{
|
|
struct rmi_device *rmi_dev = to_rmi_device(dev);
|
|
struct rmi_device *rmi_dev = to_rmi_device(dev);
|
|
|
|
+ struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
|
|
|
|
|
|
rmi_disable_irq(rmi_dev, false);
|
|
rmi_disable_irq(rmi_dev, false);
|
|
|
|
|
|
|
|
+ irq_domain_remove(data->irqdomain);
|
|
|
|
+ data->irqdomain = NULL;
|
|
|
|
+
|
|
rmi_f34_remove_sysfs(rmi_dev);
|
|
rmi_f34_remove_sysfs(rmi_dev);
|
|
rmi_free_function_list(rmi_dev);
|
|
rmi_free_function_list(rmi_dev);
|
|
|
|
|
|
@@ -1035,7 +1015,8 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
|
|
{
|
|
{
|
|
struct rmi_device *rmi_dev = data->rmi_dev;
|
|
struct rmi_device *rmi_dev = data->rmi_dev;
|
|
struct device *dev = &rmi_dev->dev;
|
|
struct device *dev = &rmi_dev->dev;
|
|
- int irq_count;
|
|
|
|
|
|
+ struct fwnode_handle *fwnode = rmi_dev->xport->dev->fwnode;
|
|
|
|
+ int irq_count = 0;
|
|
size_t size;
|
|
size_t size;
|
|
int retval;
|
|
int retval;
|
|
|
|
|
|
@@ -1046,7 +1027,6 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
|
|
* being accessed.
|
|
* being accessed.
|
|
*/
|
|
*/
|
|
rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Counting IRQs.\n", __func__);
|
|
rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Counting IRQs.\n", __func__);
|
|
- irq_count = 0;
|
|
|
|
data->bootloader_mode = false;
|
|
data->bootloader_mode = false;
|
|
|
|
|
|
retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_count_irqs);
|
|
retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_count_irqs);
|
|
@@ -1058,6 +1038,15 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
|
|
if (data->bootloader_mode)
|
|
if (data->bootloader_mode)
|
|
dev_warn(dev, "Device in bootloader mode.\n");
|
|
dev_warn(dev, "Device in bootloader mode.\n");
|
|
|
|
|
|
|
|
+ /* Allocate and register a linear revmap irq_domain */
|
|
|
|
+ data->irqdomain = irq_domain_create_linear(fwnode, irq_count,
|
|
|
|
+ &irq_domain_simple_ops,
|
|
|
|
+ data);
|
|
|
|
+ if (!data->irqdomain) {
|
|
|
|
+ dev_err(&rmi_dev->dev, "Failed to create IRQ domain\n");
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+ }
|
|
|
|
+
|
|
data->irq_count = irq_count;
|
|
data->irq_count = irq_count;
|
|
data->num_of_irq_regs = (data->irq_count + 7) / 8;
|
|
data->num_of_irq_regs = (data->irq_count + 7) / 8;
|
|
|
|
|
|
@@ -1080,10 +1069,9 @@ int rmi_init_functions(struct rmi_driver_data *data)
|
|
{
|
|
{
|
|
struct rmi_device *rmi_dev = data->rmi_dev;
|
|
struct rmi_device *rmi_dev = data->rmi_dev;
|
|
struct device *dev = &rmi_dev->dev;
|
|
struct device *dev = &rmi_dev->dev;
|
|
- int irq_count;
|
|
|
|
|
|
+ int irq_count = 0;
|
|
int retval;
|
|
int retval;
|
|
|
|
|
|
- irq_count = 0;
|
|
|
|
rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Creating functions.\n", __func__);
|
|
rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Creating functions.\n", __func__);
|
|
retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_create_function);
|
|
retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_create_function);
|
|
if (retval < 0) {
|
|
if (retval < 0) {
|