/*
* Copyright (c) 2011-2016 Synaptics Incorporated
* Copyright (c) 2011 Unixphere
*
* This driver provides the core support for a single RMI4-based device.
*
* The RMI4 specification can be found here (URL split for line length):
*
* http://www.synaptics.com/sites/default/files/
* 511-000136-01-Rev-E-RMI4-Interfacing-Guide.pdf
*
* 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/bitmap.h>
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/kconfig.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <uapi/linux/input.h>
#include <linux/rmi.h>
#include "rmi_bus.h"
#include "rmi_driver.h"
#define HAS_NONSTANDARD_PDT_MASK 0x40
#define RMI4_MAX_PAGE 0xff
#define RMI4_PAGE_SIZE 0x100
#define RMI4_PAGE_MASK 0xFF00
#define RMI_DEVICE_RESET_CMD 0x01
#define DEFAULT_RESET_DELAY_MS 100
static void rmi_free_function_list(struct rmi_device *rmi_dev)
{
struct rmi_function *fn, *tmp;
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
data->f01_container = NULL;
/* Doing it in the reverse order so F01 will be removed last */
list_for_each_entry_safe_reverse(fn, tmp,
&data->function_list, node) {
list_del(&fn->node);
rmi_unregister_function(fn);
}
}
static int reset_one_function(struct rmi_function *fn)
{
struct rmi_function_handler *fh;
int retval = 0;
if (!fn || !fn->dev.driver)
return 0;
fh = to_rmi_function_handler(fn->dev.driver);
if (fh->reset) {
retval = fh->reset(fn);
if (retval < 0)
dev_err(&fn->dev, "Reset failed with code %d.\n",
retval);
}
return retval;
}
static int configure_one_function(struct rmi_function *fn)
{
struct rmi_function_handler *fh;
int retval = 0;
if (!fn || !fn->dev.driver)
return 0;
fh = to_rmi_function_handler(fn->dev.driver);
if (fh->config) {
retval = fh->config(fn);
if (retval < 0)
dev_err(&fn->dev, "Config failed with code %d.\n",
retval);
}
return retval;
}
static int rmi_driver_process_reset_requests(struct rmi_device *rmi_dev)
{
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
struct rmi_function *entry;
int retval;
list_for_each_entry(entry, &data->function_list, node) {
retval = reset_one_function(entry);
if (retval < 0)
return retval;
}
return 0;
}
static int rmi_driver_process_config_requests(struct rmi_device *rmi_dev)
{
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
struct rmi_function *entry;
int retval;
list_for_each_entry(entry, &data->function_list, node) {
retval = configure_one_function(entry);
if (retval < 0)
return retval;
}
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);
}
}
int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
{
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
struct device *dev = &rmi_dev->dev;
struct rmi_function *entry;
<