rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev, "Freeing function list\n");
- mutex_lock(&data->irq_mutex);
-
devm_kfree(&rmi_dev->dev, data->irq_memory);
data->irq_memory = NULL;
data->irq_status = NULL;
list_del(&fn->node);
rmi_unregister_function(fn);
}
-
- mutex_unlock(&data->irq_mutex);
}
-EXPORT_SYMBOL_GPL(rmi_free_function_list);
static int reset_one_function(struct rmi_function *fn)
{
if (!data)
return 0;
- mutex_lock(&data->irq_mutex);
- if (!data->irq_status || !data->f01_container) {
- mutex_unlock(&data->irq_mutex);
- return 0;
- }
-
- if (!rmi_dev->xport->attn_data) {
+ if (!data->attn_data.data) {
error = rmi_read_block(rmi_dev,
data->f01_container->fd.data_base_addr + 1,
data->irq_status, data->num_of_irq_regs);
if (error < 0) {
dev_err(dev, "Failed to read irqs, code=%d\n", error);
- mutex_unlock(&data->irq_mutex);
return error;
}
}
+ mutex_lock(&data->irq_mutex);
bitmap_and(data->irq_status, data->irq_status, data->current_irq_mask,
data->irq_count);
+ /*
+ * At this point, irq_status has all bits that are set in the
+ * interrupt status register and are enabled.
+ */
+ mutex_unlock(&data->irq_mutex);
/*
* It would be nice to be able to use irq_chip to handle these
if (data->input)
input_sync(data->input);
- mutex_unlock(&data->irq_mutex);
-
return 0;
}
+void rmi_set_attn_data(struct rmi_device *rmi_dev, unsigned long irq_status,
+ void *data, size_t size)
+{
+ struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
+ struct rmi4_attn_data attn_data;
+ void *fifo_data;
+
+ if (!drvdata->enabled)
+ return;
+
+ fifo_data = kmemdup(data, size, GFP_ATOMIC);
+ if (!fifo_data)
+ return;
+
+ attn_data.irq_status = irq_status;
+ attn_data.size = size;
+ attn_data.data = fifo_data;
+
+ kfifo_put(&drvdata->attn_fifo, attn_data);
+}
+EXPORT_SYMBOL_GPL(rmi_set_attn_data);
+
static irqreturn_t rmi_irq_fn(int irq, void *dev_id)
{
struct rmi_device *rmi_dev = dev_id;
- int ret;
+ struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
+ struct rmi4_attn_data attn_data = {0};
+ int ret, count;
+
+ count = kfifo_get(&drvdata->attn_fifo, &attn_data);
+ if (count) {
+ *(drvdata->irq_status) = attn_data.irq_status;
+ drvdata->attn_data = attn_data;
+ }
ret = rmi_process_interrupt_requests(rmi_dev);
if (ret)
rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev,
"Failed to process interrupt request: %d\n", ret);
+ if (count)
+ kfree(attn_data.data);
+
+ if (!kfifo_is_empty(&drvdata->attn_fifo))
+ return rmi_irq_fn(irq, dev_id);
+
return IRQ_HANDLED;
}
static int rmi_irq_init(struct rmi_device *rmi_dev)
{
struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
+ struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
int irq_flags = irq_get_trigger_type(pdata->irq);
int ret;
return ret;
}
+ data->enabled = true;
+
return 0;
}
struct rmi_function *entry;
int retval;
- mutex_lock(&data->irq_mutex);
-
list_for_each_entry(entry, &data->function_list, node) {
retval = suspend_one_function(entry);
- if (retval < 0) {
- mutex_unlock(&data->irq_mutex);
+ if (retval < 0)
return retval;
- }
}
- mutex_unlock(&data->irq_mutex);
-
return 0;
}
struct rmi_function *entry;
int retval;
- mutex_lock(&data->irq_mutex);
-
list_for_each_entry(entry, &data->function_list, node) {
retval = resume_one_function(entry);
- if (retval < 0) {
- mutex_unlock(&data->irq_mutex);
+ if (retval < 0)
return retval;
- }
}
- mutex_unlock(&data->irq_mutex);
-
return 0;
}
return rmi_process_interrupt_requests(rmi_dev);
}
-EXPORT_SYMBOL_GPL(rmi_enable_sensor);
/**
* rmi_driver_set_input_params - set input device id and other data.
return 0;
}
-int rmi_read_pdt_entry(struct rmi_device *rmi_dev, struct pdt_entry *entry,
- u16 pdt_address)
+static int rmi_read_pdt_entry(struct rmi_device *rmi_dev,
+ struct pdt_entry *entry, u16 pdt_address)
{
u8 buf[RMI_PDT_ENTRY_SIZE];
int error;
return 0;
}
-EXPORT_SYMBOL_GPL(rmi_read_pdt_entry);
static void rmi_driver_copy_pdt_to_fd(const struct pdt_entry *pdt,
struct rmi_function_descriptor *fd)
else
*empty_pages = 0;
- return (data->f01_bootloader_mode || *empty_pages >= 2) ?
+ return (data->bootloader_mode || *empty_pages >= 2) ?
RMI_SCAN_DONE : RMI_SCAN_CONTINUE;
}
return retval < 0 ? retval : 0;
}
-EXPORT_SYMBOL_GPL(rmi_scan_pdt);
int rmi_read_register_desc(struct rmi_device *d, u16 addr,
struct rmi_register_descriptor *rdesc)
kfree(struct_buf);
return ret;
}
-EXPORT_SYMBOL_GPL(rmi_read_register_desc);
const struct rmi_register_desc_item *rmi_get_register_desc_item(
struct rmi_register_descriptor *rdesc, u16 reg)
return NULL;
}
-EXPORT_SYMBOL_GPL(rmi_get_register_desc_item);
size_t rmi_register_desc_calc_size(struct rmi_register_descriptor *rdesc)
{
}
return size;
}
-EXPORT_SYMBOL_GPL(rmi_register_desc_calc_size);
/* Compute the register offset relative to the base address */
int rmi_register_desc_calc_reg_offset(
}
return -1;
}
-EXPORT_SYMBOL_GPL(rmi_register_desc_calc_reg_offset);
bool rmi_register_desc_has_subpacket(const struct rmi_register_desc_item *item,
u8 subpacket)
subpacket) == subpacket;
}
-/* Indicates that flash programming is enabled (bootloader mode). */
-#define RMI_F01_STATUS_BOOTLOADER(status) (!!((status) & 0x40))
-
-/*
- * Given the PDT entry for F01, read the device status register to determine
- * if we're stuck in bootloader mode or not.
- *
- */
static int rmi_check_bootloader_mode(struct rmi_device *rmi_dev,
const struct pdt_entry *pdt)
{
- int error;
- u8 device_status;
+ struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
+ int ret;
+ u8 status;
- error = rmi_read(rmi_dev, pdt->data_base_addr + pdt->page_start,
- &device_status);
- if (error) {
- dev_err(&rmi_dev->dev,
- "Failed to read device status: %d.\n", error);
- return error;
+ if (pdt->function_number == 0x34 && pdt->function_version > 1) {
+ ret = rmi_read(rmi_dev, pdt->data_base_addr, &status);
+ if (ret) {
+ dev_err(&rmi_dev->dev,
+ "Failed to read F34 status: %d.\n", ret);
+ return ret;
+ }
+
+ if (status & BIT(7))
+ data->bootloader_mode = true;
+ } else if (pdt->function_number == 0x01) {
+ ret = rmi_read(rmi_dev, pdt->data_base_addr, &status);
+ if (ret) {
+ dev_err(&rmi_dev->dev,
+ "Failed to read F01 status: %d.\n", ret);
+ return ret;
+ }
+
+ if (status & BIT(6))
+ data->bootloader_mode = true;
}
- return RMI_F01_STATUS_BOOTLOADER(device_status);
+ return 0;
}
static int rmi_count_irqs(struct rmi_device *rmi_dev,
void *ctx, const struct pdt_entry *pdt)
{
- struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
int *irq_count = ctx;
+ int ret;
*irq_count += pdt->interrupt_source_count;
- if (pdt->function_number == 0x01)
- data->f01_bootloader_mode =
- rmi_check_bootloader_mode(rmi_dev, pdt);
+
+ ret = rmi_check_bootloader_mode(rmi_dev, pdt);
+ if (ret < 0)
+ return ret;
return RMI_SCAN_CONTINUE;
}
/* F01 should always be on page 0. If we don't find it there, fail. */
return pdt->page_start == 0 ? RMI_SCAN_CONTINUE : -ENODEV;
}
-EXPORT_SYMBOL_GPL(rmi_initial_reset);
static int rmi_create_function(struct rmi_device *rmi_dev,
void *ctx, const struct pdt_entry *pdt)
{
struct device *dev = &rmi_dev->dev;
- struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
+ struct rmi_driver_data *data = dev_get_drvdata(dev);
int *current_irq_count = ctx;
struct rmi_function *fn;
int i;
return error;
}
-int rmi_driver_suspend(struct rmi_device *rmi_dev, bool enable_wake)
+void rmi_enable_irq(struct rmi_device *rmi_dev, bool clear_wake)
{
struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
+ struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
int irq = pdata->irq;
- int retval = 0;
+ int irq_flags;
+ int retval;
- retval = rmi_suspend_functions(rmi_dev);
- if (retval)
- dev_warn(&rmi_dev->dev, "Failed to suspend functions: %d\n",
- retval);
+ mutex_lock(&data->enabled_mutex);
+
+ if (data->enabled)
+ goto out;
+
+ enable_irq(irq);
+ data->enabled = true;
+ if (clear_wake && device_may_wakeup(rmi_dev->xport->dev)) {
+ retval = disable_irq_wake(irq);
+ if (!retval)
+ dev_warn(&rmi_dev->dev,
+ "Failed to disable irq for wake: %d\n",
+ retval);
+ }
+
+ /*
+ * Call rmi_process_interrupt_requests() after enabling irq,
+ * otherwise we may lose interrupt on edge-triggered systems.
+ */
+ irq_flags = irq_get_trigger_type(pdata->irq);
+ if (irq_flags & IRQ_TYPE_EDGE_BOTH)
+ rmi_process_interrupt_requests(rmi_dev);
+
+out:
+ mutex_unlock(&data->enabled_mutex);
+}
+
+void rmi_disable_irq(struct rmi_device *rmi_dev, bool enable_wake)
+{
+ struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
+ struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
+ struct rmi4_attn_data attn_data = {0};
+ int irq = pdata->irq;
+ int retval, count;
+ mutex_lock(&data->enabled_mutex);
+
+ if (!data->enabled)
+ goto out;
+
+ data->enabled = false;
disable_irq(irq);
if (enable_wake && device_may_wakeup(rmi_dev->xport->dev)) {
retval = enable_irq_wake(irq);
"Failed to enable irq for wake: %d\n",
retval);
}
+
+ /* make sure the fifo is clean */
+ while (!kfifo_is_empty(&data->attn_fifo)) {
+ count = kfifo_get(&data->attn_fifo, &attn_data);
+ if (count)
+ kfree(attn_data.data);
+ }
+
+out:
+ mutex_unlock(&data->enabled_mutex);
+}
+
+int rmi_driver_suspend(struct rmi_device *rmi_dev, bool enable_wake)
+{
+ int retval;
+
+ retval = rmi_suspend_functions(rmi_dev);
+ if (retval)
+ dev_warn(&rmi_dev->dev, "Failed to suspend functions: %d\n",
+ retval);
+
+ rmi_disable_irq(rmi_dev, enable_wake);
return retval;
}
EXPORT_SYMBOL_GPL(rmi_driver_suspend);
int rmi_driver_resume(struct rmi_device *rmi_dev, bool clear_wake)
{
- struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
- int irq = pdata->irq;
int retval;
- enable_irq(irq);
- if (clear_wake && device_may_wakeup(rmi_dev->xport->dev)) {
- retval = disable_irq_wake(irq);
- if (!retval)
- dev_warn(&rmi_dev->dev,
- "Failed to disable irq for wake: %d\n",
- retval);
- }
+ rmi_enable_irq(rmi_dev, clear_wake);
retval = rmi_resume_functions(rmi_dev);
if (retval)
static int rmi_driver_remove(struct device *dev)
{
struct rmi_device *rmi_dev = to_rmi_device(dev);
- struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
- int irq = pdata->irq;
- disable_irq(irq);
+ rmi_disable_irq(rmi_dev, false);
rmi_f34_remove_sysfs(rmi_dev);
rmi_free_function_list(rmi_dev);
*/
rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Counting IRQs.\n", __func__);
irq_count = 0;
+ data->bootloader_mode = false;
+
retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_count_irqs);
if (retval < 0) {
dev_err(dev, "IRQ counting failed with code %d.\n", retval);
return retval;
}
- if (data->f01_bootloader_mode)
- dev_warn(&rmi_dev->dev, "Device in bootloader mode.\n");
+ if (data->bootloader_mode)
+ dev_warn(dev, "Device in bootloader mode.\n");
data->irq_count = irq_count;
data->num_of_irq_regs = (data->irq_count + 7) / 8;
return retval;
}
-EXPORT_SYMBOL_GPL(rmi_probe_interrupts);
int rmi_init_functions(struct rmi_driver_data *data)
{
int irq_count;
int retval;
- mutex_lock(&data->irq_mutex);
-
irq_count = 0;
rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Creating functions.\n", __func__);
retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_create_function);
goto err_destroy_functions;
}
- mutex_unlock(&data->irq_mutex);
-
return 0;
err_destroy_functions:
rmi_free_function_list(rmi_dev);
- mutex_unlock(&data->irq_mutex);
return retval;
}
-EXPORT_SYMBOL_GPL(rmi_init_functions);
static int rmi_driver_probe(struct device *dev)
{
}
mutex_init(&data->irq_mutex);
+ mutex_init(&data->enabled_mutex);
retval = rmi_probe_interrupts(data);
if (retval)