/* * Copyright (c) 2011 Synaptics Incorporated * Copyright (c) 2011 Unixphere * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include #define COMMS_DEBUG 0 #define IRQ_DEBUG 0 #define RMI_PAGE_SELECT_REGISTER 0xff #define RMI_I2C_PAGE(addr) (((addr) >> 8) & 0xff) static char *phys_proto_name = "i2c"; struct rmi_i2c_data { struct mutex page_mutex; int page; int enabled; int irq; int irq_flags; struct rmi_phys_device *phys; }; static irqreturn_t rmi_i2c_irq_thread(int irq, void *p) { struct rmi_phys_device *phys = p; struct rmi_device *rmi_dev = phys->rmi_dev; struct rmi_driver *driver = rmi_dev->driver; struct rmi_device_platform_data *pdata = phys->dev->platform_data; #if IRQ_DEBUG dev_dbg(phys->dev, "ATTN gpio, value: %d.\n", gpio_get_value(irq_to_gpio(irq))); #endif if (gpio_get_value(irq_to_gpio(irq)) == pdata->irq_polarity) { phys->info.attn_count++; if (driver && driver->irq_handler && rmi_dev) driver->irq_handler(rmi_dev, irq); } return IRQ_HANDLED; } /* * rmi_set_page - Set RMI page * @phys: The pointer to the rmi_phys_device struct * @page: The new page address. * * RMI devices have 16-bit addressing, but some of the physical * implementations (like SMBus) only have 8-bit addressing. So RMI implements * a page address at 0xff of every page so we can reliable page addresses * every 256 registers. * * The page_mutex lock must be held when this function is entered. * * Returns zero on success, non-zero on failure. */ static int rmi_set_page(struct rmi_phys_device *phys, unsigned int page) { struct i2c_client *client = to_i2c_client(phys->dev); struct rmi_i2c_data *data = phys->data; char txbuf[2] = {RMI_PAGE_SELECT_REGISTER, page}; int retval; #if COMMS_DEBUG dev_dbg(&client->dev, "RMI4 I2C writes 3 bytes: %02x %02x\n", txbuf[0], txbuf[1]); #endif phys->info.tx_count++; phys->info.tx_bytes += sizeof(txbuf); retval = i2c_master_send(client, txbuf, sizeof(txbuf)); if (retval != sizeof(txbuf)) { phys->info.tx_errs++; dev_err(&client->dev, "%s: set page failed: %d.", __func__, retval); return (retval < 0) ? retval : -EIO; } data->page = page; return 0; } static int rmi_i2c_write_block(struct rmi_phys_device *phys, u16 addr, u8 *buf, int len) { struct i2c_client *client = to_i2c_client(phys->dev); struct rmi_i2c_data *data = phys->data; u8 txbuf[len + 1]; int retval; #if COMMS_DEBUG int i; #endif txbuf[0] = addr & 0xff; memcpy(txbuf + 1, buf, len); mutex_lock(&data->page_mutex); if (RMI_I2C_PAGE(addr) != data->page) { retval = rmi_set_page(phys, RMI_I2C_PAGE(addr)); if (retval < 0) goto exit; } #if COMMS_DEBUG dev_dbg(&client->dev, "RMI4 I2C writes %d bytes: ", sizeof(txbuf)); for (i = 0; i < sizeof(txbuf); i++) dev_dbg(&client->dev, "%02x ", txbuf[i]); dev_dbg(&client->dev, "\n"); #endif phys->info.tx_count++; phys->info.tx_bytes += sizeof(txbuf); retval = i2c_master_send(client, txbuf, sizeof(txbuf)); if (retval < 0) phys->info.tx_errs++; exit: mutex_unlock(&data->page_mutex); return retval; } static int rmi_i2c_write(struct rmi_phys_device *phys, u16 addr, u8 data) { int retval = rmi_i2c_write_block(phys, addr, &data, 1); return (retval < 0) ? retval : 0; } static int rmi_i2c_read_block(struct rmi_phys_device *phys, u16 addr, u8 *buf, int len) { struct i2c_client *client = to_i2c_client(phys->dev); struct rmi_i2c_data *data = phys->data; u8 txbuf[1] = {addr & 0xff}; int retval; #if COMMS_DEBUG int i; #endif mutex_lock(&data->page_mutex); if (RMI_I2C_PAGE(addr) != data->page) { retval = rmi_set_page(phys, RMI_I2C_PAGE(addr)); if (retval < 0) goto exit; } #if COMMS_DEBUG dev_dbg(&client->dev, "RMI4 I2C writes 1 bytes: %02x\n", txbuf[0]); #endif phys->info.tx_count++; phys->info.tx_bytes += sizeof(txbuf); retval = i2c_master_send(client, txbuf, sizeof(txbuf)); if (retval != sizeof(txbuf)) { phys->info.tx_errs++; retval = (retval < 0) ? retval : -EIO; goto exit; } retval = i2c_master_recv(client, buf, len); phys->info.rx_count++; phys->info.rx_bytes += len; if (retval < 0) phys->info.rx_errs++; #if COMMS_DEBUG else { dev_dbg(&client->dev, "RMI4 I2C received %d bytes: ", len); for (i = 0; i < len; i++) dev_dbg(&client->dev, "%02x ", buf[i]); dev_dbg(&client->dev, "\n"); } #endif exit: mutex_unlock(&data->page_mutex); return retval; } static int rmi_i2c_read(struct rmi_phys_device *phys, u16 addr, u8 *buf) { int retval = rmi_i2c_read_block(phys, addr, buf, 1); return (retval < 0) ? retval : 0; } static int acquire_attn_irq(struct rmi_i2c_data *data) { return request_threaded_irq(data->irq, NULL, rmi_i2c_irq_thread, data->irq_flags, dev_name(data->phys->dev), data->phys); } static int enable_device(struct rmi_phys_device *phys) { int retval = 0; struct rmi_i2c_data *data = phys->data; if (data->enabled) return 0; retval = acquire_attn_irq(data); if (retval) goto error_exit; data->enabled = true; dev_dbg(phys->dev, "Physical device enabled.\n"); return 0; error_exit: dev_err(phys->dev, "Failed to enable physical device. Code=%d.\n", retval); return retval; } static void disable_device(struct rmi_phys_device *phys) { struct rmi_i2c_data *data = phys->data; if (!data->enabled) return; disable_irq(data->irq); free_irq(data->irq, data->phys); dev_dbg(phys->dev, "Physical device disabled.\n"); data->enabled = false; } static int __devinit rmi_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct rmi_phys_device *rmi_phys; struct rmi_i2c_data *data; struct rmi_device_platform_data *pdata = client->dev.platform_data; int error; if (!pdata) { dev_err(&client->dev, "no platform data\n"); return -EINVAL; } if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { dev_err(&client->dev, "i2c_check_functionality error\n"); return -EIO; } rmi_phys = kzalloc(sizeof(struct rmi_phys_device), GFP_KERNEL); if (!rmi_phys) return -ENOMEM; data = kzalloc(sizeof(struct rmi_i2c_data), GFP_KERNEL); if (!data) { error = -ENOMEM; goto err_phys; } data->enabled = true; /* We plan to come up enabled. */ data->irq = gpio_to_irq(pdata->irq); data->irq_flags = (pdata->irq_polarity == RMI_IRQ_ACTIVE_HIGH) ? IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING; data->phys = rmi_phys; rmi_phys->data = data; rmi_phys->dev = &client->dev; rmi_phys->write = rmi_i2c_write; rmi_phys->write_block = rmi_i2c_write_block; rmi_phys->read = rmi_i2c_read; rmi_phys->read_block = rmi_i2c_read_block; rmi_phys->enable_device = enable_device; rmi_phys->disable_device = disable_device; rmi_phys->info.proto = phys_proto_name; mutex_init(&data->page_mutex); /* Setting the page to zero will (a) make sure the PSR is in a * known state, and (b) make sure we can talk to the device. */ error = rmi_set_page(rmi_phys, 0); if (error) { dev_err(&client->dev, "Failed to set page select to 0.\n"); goto err_data; } if (pdata->gpio_config) { error = pdata->gpio_config(&client->dev, true); if (error < 0) { dev_err(&client->dev, "failed to setup irq %d\n", pdata->irq); goto err_data; } } error = rmi_register_phys_device(rmi_phys); if (error) { dev_err(&client->dev, "failed to register physical driver at 0x%.2X.\n", client->addr); goto err_data; } i2c_set_clientdata(client, rmi_phys); if (pdata->irq > 0) { error = acquire_attn_irq(data); if (error < 0) { dev_err(&client->dev, "request_threaded_irq failed %d\n", pdata->irq); goto err_unregister; } } #if defined(CONFIG_RMI4_DEV) error = gpio_export(pdata->irq, false); if (error) { dev_warn(&client->dev, "%s: WARNING: Failed to " "export ATTN gpio!\n", __func__); error = 0; } else { error = gpio_export_link(&(rmi_phys->rmi_dev->dev), "attn", pdata->irq); if (error) { dev_warn(&(rmi_phys->rmi_dev->dev), "%s: WARNING: " "Failed to symlink ATTN gpio!\n", __func__); error = 0; } else { dev_info(&(rmi_phys->rmi_dev->dev), "%s: Exported GPIO %d.", __func__, pdata->irq); } } #endif /* CONFIG_RMI4_DEV */ dev_info(&client->dev, "registered rmi i2c driver at 0x%.2X.\n", client->addr); return 0; err_unregister: rmi_unregister_phys_device(rmi_phys); err_data: kfree(data); err_phys: kfree(rmi_phys); return error; } static int __devexit rmi_i2c_remove(struct i2c_client *client) { struct rmi_phys_device *phys = i2c_get_clientdata(client); struct rmi_device_platform_data *pd = client->dev.platform_data; rmi_unregister_phys_device(phys); kfree(phys->data); kfree(phys); if (pd->gpio_config) pd->gpio_config(&client->dev, false); return 0; } static const struct i2c_device_id rmi_id[] = { { "rmi", 0 }, { "rmi-i2c", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, rmi_id); static struct i2c_driver rmi_i2c_driver = { .driver = { .owner = THIS_MODULE, .name = "rmi-i2c" }, .id_table = rmi_id, .probe = rmi_i2c_probe, .remove = __devexit_p(rmi_i2c_remove), }; static int __init rmi_i2c_init(void) { return i2c_add_driver(&rmi_i2c_driver); } static void __exit rmi_i2c_exit(void) { i2c_del_driver(&rmi_i2c_driver); } MODULE_AUTHOR("Christopher Heiny "); MODULE_AUTHOR("Eric Andersson "); MODULE_DESCRIPTION("RMI i2c driver"); MODULE_LICENSE("GPL"); module_init(rmi_i2c_init); module_exit(rmi_i2c_exit);