617 lines
16 KiB
C
617 lines
16 KiB
C
/**
|
|
*
|
|
* Synaptics Register Mapped Interface (RMI4) SPI Physical Layer Driver.
|
|
* Copyright (C) 2008-2011, Synaptics Incorporated
|
|
*
|
|
*/
|
|
/*
|
|
* This file is licensed under the GPL2 license.
|
|
*
|
|
*############################################################################
|
|
* GPL
|
|
*
|
|
* 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.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* for more details.
|
|
*
|
|
*############################################################################
|
|
*/
|
|
|
|
#include <linux/delay.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/spi/spi.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/semaphore.h>
|
|
#include <linux/spi/spi.h>
|
|
#include <linux/input/rmi_platformdata.h>
|
|
#include "rmi_spi.h"
|
|
#include "rmi_drvr.h"
|
|
|
|
#define COMM_DEBUG 1 /* Set to 1 to dump transfers. */
|
|
|
|
/* 65 microseconds inter-byte delay between bytes for RMI chip*/
|
|
#define RMI_DEFAULT_BYTE_DELAY_US 0 /* 65 */
|
|
#define SPI_BUFFER_SIZE 32
|
|
|
|
static u8 *buf;
|
|
|
|
/* This is the data kept on a per instance (client) basis. This data is
|
|
* always accessible by using the container_of() macro of the various elements
|
|
* inside.
|
|
*/
|
|
struct spi_device_instance_data {
|
|
int instance_no;
|
|
int irq;
|
|
unsigned int byte_delay_us;
|
|
struct rmi_phys_driver rpd;
|
|
struct spi_device *spidev;
|
|
struct rmi_spi_platformdata *platformdata;
|
|
};
|
|
|
|
static int spi_xfer(struct spi_device_instance_data *instance_data,
|
|
const u8 *txbuf, unsigned n_tx, u8 *rxbuf, unsigned n_rx)
|
|
{
|
|
struct spi_device *spi = instance_data->spidev;
|
|
#if COMM_DEBUG
|
|
int i;
|
|
#endif
|
|
int status;
|
|
struct spi_message message;
|
|
struct spi_transfer *xfer_list;
|
|
u8 *local_buf;
|
|
int nXfers = 0;
|
|
int xfer_index = 0;
|
|
|
|
if ((n_tx + n_rx) > SPI_BUFFER_SIZE)
|
|
return -EINVAL;
|
|
|
|
if (n_tx)
|
|
nXfers += 1;
|
|
if (n_rx) {
|
|
if (instance_data->byte_delay_us)
|
|
nXfers += n_rx;
|
|
else
|
|
nXfers += 1;
|
|
}
|
|
|
|
xfer_list = kcalloc(nXfers, sizeof(struct spi_transfer), GFP_KERNEL);
|
|
if (!xfer_list)
|
|
return -ENOMEM;
|
|
|
|
/* ... unless someone else is using the pre-allocated buffer */
|
|
local_buf = kzalloc(SPI_BUFFER_SIZE, GFP_KERNEL);
|
|
if (!local_buf) {
|
|
kfree(xfer_list);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
spi_message_init(&message);
|
|
|
|
if (n_tx) {
|
|
memset(&xfer_list[0], 0, sizeof(struct spi_transfer));
|
|
xfer_list[0].len = n_tx;
|
|
xfer_list[0].delay_usecs = instance_data->byte_delay_us;
|
|
spi_message_add_tail(&xfer_list[0], &message);
|
|
memcpy(local_buf, txbuf, n_tx);
|
|
xfer_list[0].tx_buf = local_buf;
|
|
xfer_index++;
|
|
}
|
|
if (n_rx) {
|
|
if (instance_data->byte_delay_us) {
|
|
int buffer_offset = n_tx;
|
|
for (; xfer_index < nXfers; xfer_index++) {
|
|
memset(&xfer_list[xfer_index], 0,
|
|
sizeof(struct spi_transfer));
|
|
xfer_list[xfer_index].len = 1;
|
|
xfer_list[xfer_index].delay_usecs =
|
|
instance_data->byte_delay_us;
|
|
xfer_list[xfer_index].rx_buf =
|
|
local_buf + buffer_offset;
|
|
buffer_offset++;
|
|
spi_message_add_tail(&xfer_list[xfer_index],
|
|
&message);
|
|
#ifdef CONFIG_ARCH_OMAP
|
|
printk(KERN_INFO "%s: Did you compensate for
|
|
ARCH_OMAP?", __func__);
|
|
/* x[1].len = n_rx-1; */ /* since OMAP has one dummy byte. */
|
|
#else
|
|
/* x[1].len = n_rx; */
|
|
#endif
|
|
}
|
|
} else {
|
|
memset(&xfer_list[xfer_index], 0, sizeof(struct
|
|
spi_transfer));
|
|
#ifdef CONFIG_ARCH_OMAP
|
|
/* since OMAP has one dummy byte. */
|
|
xfer_list[xfer_index].len = n_rx-1;
|
|
#else
|
|
xfer_list[xfer_index].len = n_rx;
|
|
#endif
|
|
xfer_list[xfer_index].rx_buf = local_buf + n_tx;
|
|
spi_message_add_tail(&xfer_list[xfer_index],
|
|
&message);
|
|
xfer_index++;
|
|
}
|
|
}
|
|
printk(KERN_INFO "%s: Ready to go, xfer_index = %d, nXfers = %d.",
|
|
__func__, xfer_index, nXfers);
|
|
#if COMM_DEBUG
|
|
printk(KERN_INFO "%s: SPI transmits %d bytes...", __func__, n_tx);
|
|
for (i = 0; i < n_tx; i++)
|
|
printk(KERN_INFO " 0x%02X", local_buf[i]);
|
|
#endif
|
|
|
|
/* do the i/o */
|
|
status = spi_sync(spi, &message);
|
|
if (status == 0) {
|
|
memcpy(rxbuf, local_buf + n_tx, n_rx);
|
|
status = message.status;
|
|
#if COMM_DEBUG
|
|
if (n_rx) {
|
|
printk(KERN_INFO "%s: SPI received %d bytes...",
|
|
__func__, n_rx);
|
|
for (i = 0; i < n_rx; i++)
|
|
printk(KERN_INFO " 0x%02X", rxbuf[i]);
|
|
}
|
|
#endif
|
|
} else {
|
|
printk(KERN_ERR "%s: spi_sync failed with error code %d.",
|
|
__func__, status);
|
|
}
|
|
|
|
kfree(local_buf);
|
|
kfree(xfer_list);
|
|
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* Read a single register through spi.
|
|
* \param[in] pd
|
|
* \param[in] address The address at which to start the data read.
|
|
* \param[out] valp Pointer to the buffer where the data will be stored.
|
|
* \return zero upon success (with the byte read in valp),non-zero upon error.
|
|
*/
|
|
static int
|
|
rmi_spi_read(struct rmi_phys_driver *pd, unsigned short address, char *valp)
|
|
{
|
|
struct spi_device_instance_data *id =
|
|
container_of(pd, struct spi_device_instance_data, rpd);
|
|
|
|
char rxbuf[2];
|
|
int retval;
|
|
unsigned short addr = address;
|
|
|
|
addr = ((addr & 0xff00) >> 8);
|
|
address = ((address & 0x00ff) << 8);
|
|
addr |= address;
|
|
addr |= 0x80; /* High bit set indicates read. */
|
|
|
|
retval = spi_xfer(id, (u8 *)&addr, 2, rxbuf, 1);
|
|
|
|
*valp = rxbuf[0];
|
|
|
|
return retval;
|
|
}
|
|
|
|
/**
|
|
* Same as rmi_spi_read, except that multiple bytes are allowed to be read.
|
|
* \param[in] pd
|
|
* \param[in] address The address at which to start the data read.
|
|
* \param[out] valp Pointer to the buffer where the data will be stored. This
|
|
* buffer must be at least size bytes long.
|
|
* \param[in] size The number of bytes to be read.
|
|
* \return zero upon success(with the byte read in valp), non-zero upon error.
|
|
*/
|
|
static int
|
|
rmi_spi_read_multiple(struct rmi_phys_driver *pd, unsigned short address,
|
|
char *valp, int size)
|
|
{
|
|
struct spi_device_instance_data *id =
|
|
container_of(pd, struct spi_device_instance_data, rpd);
|
|
int retval;
|
|
|
|
unsigned short addr = address;
|
|
|
|
addr = ((addr & 0xff00) >> 8);
|
|
address = ((address & 0x00ff) << 8);
|
|
addr |= address;
|
|
addr |= 0x80; /* High bit set indicates read. */
|
|
|
|
retval = spi_xfer(id, (u8 *)&addr, 2, valp, size);
|
|
|
|
return retval;
|
|
}
|
|
|
|
/**
|
|
* Write a single register through spi.
|
|
* You can write multiple registers at once, but I made the functions for that
|
|
* seperate for performance reasons. Writing multiple requires allocation and
|
|
* freeing.
|
|
* \param[in] pd
|
|
* \param[in] address The address at which to start the write.
|
|
* \param[in] data The data to be written.
|
|
* \return one upon success, something else upon error.
|
|
*/
|
|
static int
|
|
rmi_spi_write(struct rmi_phys_driver *pd, unsigned short address, char data)
|
|
{
|
|
struct spi_device_instance_data *id =
|
|
container_of(pd, struct spi_device_instance_data, rpd);
|
|
unsigned char txbuf[4];
|
|
int retval;
|
|
|
|
txbuf[2] = data;
|
|
txbuf[1] = address;
|
|
txbuf[0] = address>>8;
|
|
|
|
retval = spi_xfer(id, txbuf, 3, NULL, 0);
|
|
return retval ? 0 : 1;
|
|
}
|
|
|
|
/**
|
|
* Write multiple registers.
|
|
* \param[in] pd
|
|
* \param[in] address The address at which to start the write.
|
|
* \param[in] valp A pointer to a buffer containing the data to be written.
|
|
* \param[in] size The number of bytes to write.
|
|
* \return one upon success, something else upon error.
|
|
*/
|
|
static int
|
|
rmi_spi_write_multiple(struct rmi_phys_driver *pd, unsigned short address,
|
|
char *valp, int size)
|
|
{
|
|
struct spi_device_instance_data *id =
|
|
container_of(pd, struct spi_device_instance_data, rpd);
|
|
unsigned char txbuf[32];
|
|
int retval;
|
|
int i;
|
|
|
|
txbuf[1] = address;
|
|
txbuf[0] = address>>8;
|
|
|
|
for (i = 0; i < size; i++)
|
|
txbuf[i + 2] = valp[i];
|
|
|
|
retval = spi_xfer(id, txbuf, size+2, NULL, 0);
|
|
|
|
return retval ? 0 : 1;
|
|
}
|
|
|
|
/**
|
|
* This is the Interrupt Service Routine.
|
|
* It just notifies the physical device
|
|
* that attention is required.
|
|
*/
|
|
static irqreturn_t spi_attn_isr(int irq, void *info)
|
|
{
|
|
struct spi_device_instance_data *instance_data = info;
|
|
disable_irq_nosync(instance_data->irq);
|
|
if (instance_data->rpd.attention)
|
|
instance_data->rpd.attention(&instance_data->rpd,
|
|
instance_data->instance_no);
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
/* TODO: Move this to rmi_bus, and call a function to get the next sensorID
|
|
*/
|
|
static int sensor_count;
|
|
|
|
static int __devinit rmi_spi_probe(struct spi_device *spi)
|
|
{
|
|
struct spi_device_instance_data *instance_data;
|
|
int retval;
|
|
struct rmi_spi_platformdata *platformdata;
|
|
struct rmi_sensordata *sensordata;
|
|
int irqtype = 0;
|
|
|
|
printk(KERN_INFO "Probing RMI4 SPI device\n");
|
|
|
|
/* This should have already been set up in the board file,
|
|
shouldn't it? */
|
|
spi->bits_per_word = 8;
|
|
|
|
spi->mode = SPI_MODE_3;
|
|
|
|
retval = spi_setup(spi);
|
|
if (retval < 0) {
|
|
printk(KERN_ERR "%s: spi_setup failed with %d.", __func__,
|
|
retval);
|
|
return retval;
|
|
}
|
|
|
|
buf = kzalloc(SPI_BUFFER_SIZE, GFP_KERNEL);
|
|
if (!buf) {
|
|
printk(KERN_ERR "%s: Failed to allocate memory for spi
|
|
buffer.", __func__);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
instance_data = kzalloc(sizeof(*instance_data), GFP_KERNEL);
|
|
if (!instance_data) {
|
|
printk(KERN_ERR "%s: Failer to allocate memory for instance
|
|
data.", __func__);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
instance_data->byte_delay_us = RMI_DEFAULT_BYTE_DELAY_US;
|
|
instance_data->spidev = spi;
|
|
instance_data->rpd.name = RMI4_SPI_DRIVER_NAME;
|
|
instance_data->rpd.write = rmi_spi_write;
|
|
instance_data->rpd.read = rmi_spi_read;
|
|
instance_data->rpd.write_multiple = rmi_spi_write_multiple;
|
|
instance_data->rpd.read_multiple = rmi_spi_read_multiple;
|
|
instance_data->rpd.module = THIS_MODULE;
|
|
/* default to polling if irq not used */
|
|
instance_data->rpd.polling_required = true;
|
|
|
|
platformdata = spi->dev.platform_data;
|
|
if (platformdata == NULL) {
|
|
printk(KERN_ERR "%s: CONFIGURATION ERROR - platform data
|
|
is NULL.", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
instance_data->platformdata = platformdata;
|
|
sensordata = platformdata->sensordata;
|
|
|
|
/* Call the platform setup routine, to do any setup that is required
|
|
* before
|
|
* interacting with the device.
|
|
*/
|
|
if (sensordata && sensordata->rmi_sensor_setup) {
|
|
retval = sensordata->rmi_sensor_setup();
|
|
if (retval) {
|
|
printk(KERN_ERR "%s: sensor setup failed with
|
|
code %d.", __func__, retval);
|
|
kfree(instance_data);
|
|
return retval;
|
|
}
|
|
}
|
|
|
|
/* TODO: I think this if is no longer required. */
|
|
if (platformdata->chip == RMI_SUPPORT) {
|
|
instance_data->instance_no = sensor_count;
|
|
sensor_count++;
|
|
|
|
/* set the device name using the instance_no
|
|
* appended to DEVICE_NAME to make a unique name
|
|
*/
|
|
dev_set_name(&spi->dev, "%s%d", RMI4_SPI_DEVICE_NAME,
|
|
instance_data->instance_no);
|
|
/*
|
|
* Determine if we need to poll (inefficient) or
|
|
* use interrupts.
|
|
*/
|
|
if (platformdata->irq) {
|
|
switch (platformdata->irq_type) {
|
|
case IORESOURCE_IRQ_HIGHEDGE:
|
|
irqtype = IRQF_TRIGGER_RISING;
|
|
break;
|
|
case IORESOURCE_IRQ_LOWEDGE:
|
|
irqtype = IRQF_TRIGGER_FALLING;
|
|
break;
|
|
case IORESOURCE_IRQ_HIGHLEVEL:
|
|
irqtype = IRQF_TRIGGER_HIGH;
|
|
break;
|
|
case IORESOURCE_IRQ_LOWLEVEL:
|
|
irqtype = IRQF_TRIGGER_LOW;
|
|
break;
|
|
default:
|
|
dev_warn(&spi->dev, "%s: Invalid IRQ flags
|
|
in platform data.", __func__);
|
|
retval = -ENXIO;
|
|
goto error_exit;
|
|
}
|
|
/*
|
|
retval = request_irq(instance_data->irq, spi_attn_isr,
|
|
irqtype, "rmi_spi", instance_data);
|
|
if (retval) {
|
|
dev_info(&spi->dev, "%s: Unable to get attn
|
|
irq %d. Reverting to polling. ", __func__,
|
|
instance_data->irq);
|
|
instance_data->rpd.polling_required = true;
|
|
} else {
|
|
dev_dbg(&spi->dev, "%s: got irq", __func__);
|
|
instance_data->rpd.polling_required = false;
|
|
instance_data->rpd.irq = instance_data->irq;
|
|
}
|
|
*/
|
|
instance_data->rpd.polling_required = false;
|
|
} else {
|
|
instance_data->rpd.polling_required = true;
|
|
dev_info(&spi->dev, "%s: No IRQ info given.
|
|
Polling required.", __func__);
|
|
}
|
|
}
|
|
|
|
/* Store instance data for later access. */
|
|
if (instance_data)
|
|
spi_set_drvdata(spi, instance_data);
|
|
|
|
/* Register the sensor driver -
|
|
* which will trigger a scan of the PDT.
|
|
*/
|
|
retval = rmi_register_sensor(&instance_data->rpd,
|
|
platformdata->sensordata);
|
|
if (retval) {
|
|
printk(KERN_ERR "%s: sensor registration failed with code
|
|
%d.", __func__, retval);
|
|
goto error_exit;
|
|
}
|
|
|
|
if (instance_data->rpd.polling_required == false) {
|
|
instance_data->irq = platformdata->irq;
|
|
retval = request_irq(platformdata->irq, spi_attn_isr,
|
|
irqtype, dev_name(&spi->dev), instance_data);
|
|
if (retval) {
|
|
dev_err(&spi->dev, "%s: failed to obtain IRQ %d.
|
|
Result: %d.", __func__,
|
|
platformdata->irq, retval);
|
|
dev_info(&spi->dev, "%s: Reverting to polling.\n",
|
|
__func__);
|
|
instance_data->rpd.polling_required = true;
|
|
instance_data->irq = 0;
|
|
/* TODO: Need to revert back to polling
|
|
* - create and start timer.
|
|
*/
|
|
} else {
|
|
dev_dbg(&spi->dev, "%s: got irq.\n", __func__);
|
|
instance_data->rpd.irq = instance_data->irq;
|
|
}
|
|
}
|
|
|
|
printk(KERN_INFO "%s: Successfully Registered %s.",
|
|
__func__, instance_data->rpd.name);
|
|
|
|
return 0;
|
|
|
|
error_exit:
|
|
if (sensordata && sensordata->rmi_sensor_teardown)
|
|
sensordata->rmi_sensor_teardown();
|
|
if (instance_data->irq)
|
|
free_irq(instance_data->irq, instance_data);
|
|
kfree(instance_data);
|
|
return retval;
|
|
}
|
|
|
|
static int rmi_spi_suspend(struct spi_device *spi, pm_message_t message)
|
|
{
|
|
printk(KERN_INFO "%s: Suspending...", __func__);
|
|
return 0;
|
|
}
|
|
|
|
static int rmi_spi_resume(struct spi_device *spi)
|
|
{
|
|
printk(KERN_INFO "%s: Resuming...", __func__);
|
|
return 0;
|
|
}
|
|
|
|
static int __devexit rmi_spi_remove(struct spi_device *spi)
|
|
{
|
|
struct spi_device_instance_data *id = spi_get_drvdata(spi);
|
|
|
|
printk(KERN_INFO "%s: RMI SPI device removed.", __func__);
|
|
|
|
rmi_spi_suspend(spi, PMSG_SUSPEND);
|
|
|
|
rmi_unregister_sensors(&id->rpd);
|
|
|
|
if (id) {
|
|
if (id->irq)
|
|
free_irq(id->irq, id);
|
|
kfree(id);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct spi_driver rmi_spi_driver = {
|
|
.driver = {
|
|
.name = RMI4_SPI_DRIVER_NAME,
|
|
.bus = &spi_bus_type,
|
|
.owner = THIS_MODULE,
|
|
},
|
|
.probe = rmi_spi_probe,
|
|
.remove = __devexit_p(rmi_spi_remove),
|
|
.suspend = rmi_spi_suspend,
|
|
.resume = rmi_spi_resume,
|
|
};
|
|
|
|
/**
|
|
* The Platform Driver probe function. We just tell the spi subsystem about
|
|
* ourselves in this call.
|
|
*/
|
|
static int
|
|
rmi_spi_plat_probe(struct platform_device *dev)
|
|
{
|
|
struct rmi_spi_platformdata *platform_data = dev->dev.platform_data;
|
|
|
|
printk(KERN_INFO "%s: Platform driver probe.", __func__);
|
|
|
|
if (!platform_data) {
|
|
printk(KERN_ERR "A platform device must contain
|
|
rmi_spi_platformdata\n");
|
|
return -ENXIO;
|
|
}
|
|
|
|
return spi_register_driver(&rmi_spi_driver);
|
|
}
|
|
|
|
/**
|
|
* Tell the spi subsystem that we're done.
|
|
* \param[in] dev
|
|
* \return Always returns 0.
|
|
*/
|
|
static int
|
|
rmi_spi_plat_remove(struct platform_device *dev)
|
|
{
|
|
printk(KERN_INFO "%s: Platform driver removed.", __func__);
|
|
spi_unregister_driver(&rmi_spi_driver);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Structure used to tell the Platform Driver subsystem about us.
|
|
*/
|
|
static struct platform_driver rmi_spi_platform_driver = {
|
|
.driver = {
|
|
.name = RMI4_SPI_DRIVER_NAME,
|
|
.owner = THIS_MODULE,
|
|
},
|
|
.probe = rmi_spi_plat_probe,
|
|
.remove = __devexit_p(rmi_spi_plat_remove),
|
|
};
|
|
|
|
static int __init rmi_spi_init(void)
|
|
{
|
|
int retval;
|
|
|
|
printk(KERN_INFO "%s: RMI SPI physical layer initialization.",
|
|
__func__);
|
|
retval = spi_register_driver(&rmi_spi_driver);
|
|
if (retval < 0) {
|
|
printk(KERN_ERR "%s: Failed to register spi driver, code
|
|
= %d.", __func__, retval);
|
|
return retval;
|
|
}
|
|
/*
|
|
#else
|
|
retval = platform_driver_register(&rmi_spi_platform_driver);
|
|
if (retval < 0) {
|
|
printk(KERN_ERR "%s: Failed to register platform driver,
|
|
code = %d.", __func__, retval);
|
|
return retval;
|
|
}
|
|
#endif
|
|
*/
|
|
printk(KERN_INFO "%s: result = %d", __func__, retval);
|
|
return retval;
|
|
}
|
|
module_init(rmi_spi_init);
|
|
|
|
static void __exit rmi_spi_exit(void)
|
|
{
|
|
printk(KERN_INFO "%s: RMI SPI physical layer exits.", __func__);
|
|
kfree(buf);
|
|
buf = NULL;
|
|
platform_driver_unregister(&rmi_spi_platform_driver);
|
|
}
|
|
module_exit(rmi_spi_exit);
|
|
|
|
/** Standard driver module information - the author of the module.
|
|
*/
|
|
MODULE_AUTHOR("Synaptics, Inc.");
|
|
/** Standard driver module information - a summary description of this module.
|
|
*/
|
|
MODULE_DESCRIPTION("RMI4 Driver SPI Physical Layer");
|
|
/** Standard driver module information - the license under which this module
|
|
* is included in the kernel.
|
|
*/
|
|
MODULE_LICENSE("GPL");
|