diff options
Diffstat (limited to 'drivers/i2c/chips')
| -rw-r--r-- | drivers/i2c/chips/Kconfig | 141 | ||||
| -rw-r--r-- | drivers/i2c/chips/Makefile | 27 | ||||
| -rw-r--r-- | drivers/i2c/chips/ds1682.c | 260 | ||||
| -rw-r--r-- | drivers/i2c/chips/eeprom.c | 270 | ||||
| -rw-r--r-- | drivers/i2c/chips/isp1301_omap.c | 1650 | ||||
| -rw-r--r-- | drivers/i2c/chips/max6875.c | 273 | ||||
| -rw-r--r-- | drivers/i2c/chips/menelaus.c | 1278 | ||||
| -rw-r--r-- | drivers/i2c/chips/pca9539.c | 196 | ||||
| -rw-r--r-- | drivers/i2c/chips/pcf8574.c | 234 | ||||
| -rw-r--r-- | drivers/i2c/chips/pcf8575.c | 214 | ||||
| -rw-r--r-- | drivers/i2c/chips/pcf8591.c | 342 | ||||
| -rw-r--r-- | drivers/i2c/chips/tps65010.c | 969 | ||||
| -rw-r--r-- | drivers/i2c/chips/tsl2550.c | 481 |
13 files changed, 0 insertions, 6335 deletions
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig deleted file mode 100644 index b21593f9358..00000000000 --- a/drivers/i2c/chips/Kconfig +++ /dev/null @@ -1,141 +0,0 @@ -# -# Miscellaneous I2C chip drivers configuration -# - -menu "Miscellaneous I2C Chip support" - -config DS1682 - tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm" - depends on EXPERIMENTAL - help - If you say yes here you get support for Dallas Semiconductor - DS1682 Total Elapsed Time Recorder. - - This driver can also be built as a module. If so, the module - will be called ds1682. - -config SENSORS_EEPROM - tristate "EEPROM reader" - depends on EXPERIMENTAL - help - If you say yes here you get read-only access to the EEPROM data - available on modern memory DIMMs and Sony Vaio laptops. Such - EEPROMs could theoretically be available on other devices as well. - - This driver can also be built as a module. If so, the module - will be called eeprom. - -config SENSORS_PCF8574 - tristate "Philips PCF8574 and PCF8574A" - depends on EXPERIMENTAL - default n - help - If you say yes here you get support for Philips PCF8574 and - PCF8574A chips. These chips are 8-bit I/O expanders for the I2C bus. - - This driver can also be built as a module. If so, the module - will be called pcf8574. - - These devices are hard to detect and rarely found on mainstream - hardware. If unsure, say N. - -config PCF8575 - tristate "Philips PCF8575" - default n - help - If you say yes here you get support for Philips PCF8575 chip. - This chip is a 16-bit I/O expander for the I2C bus. Several other - chip manufacturers sell equivalent chips, e.g. Texas Instruments. - - This driver can also be built as a module. If so, the module - will be called pcf8575. - - This device is hard to detect and is rarely found on mainstream - hardware. If unsure, say N. - -config SENSORS_PCA9539 - tristate "Philips PCA9539 16-bit I/O port (DEPRECATED)" - depends on EXPERIMENTAL && GPIO_PCA9539 = "n" - help - If you say yes here you get support for the Philips PCA9539 - 16-bit I/O port. - - This driver can also be built as a module. If so, the module - will be called pca9539. - - This driver is deprecated and will be dropped soon. Use - drivers/gpio/pca9539.c instead. - -config SENSORS_PCF8591 - tristate "Philips PCF8591" - depends on EXPERIMENTAL - default n - help - If you say yes here you get support for Philips PCF8591 chips. - - This driver can also be built as a module. If so, the module - will be called pcf8591. - - These devices are hard to detect and rarely found on mainstream - hardware. If unsure, say N. - -config ISP1301_OMAP - tristate "Philips ISP1301 with OMAP OTG" - depends on ARCH_OMAP_OTG - help - If you say yes here you get support for the Philips ISP1301 - USB-On-The-Go transceiver working with the OMAP OTG controller. - The ISP1301 is used in products including H2 and H3 development - boards for Texas Instruments OMAP processors. - - This driver can also be built as a module. If so, the module - will be called isp1301_omap. - -config TPS65010 - tristate "TPS6501x Power Management chips" - default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK - help - If you say yes here you get support for the TPS6501x series of - Power Management chips. These include voltage regulators, - lithium ion/polymer battery charging, and other features that - are often used in portable devices like cell phones and cameras. - - This driver can also be built as a module. If so, the module - will be called tps65010. - -config SENSORS_MAX6875 - tristate "Maxim MAX6875 Power supply supervisor" - depends on EXPERIMENTAL - help - If you say yes here you get support for the Maxim MAX6875 - EEPROM-programmable, quad power-supply sequencer/supervisor. - - This provides an interface to program the EEPROM and reset the chip. - - This driver also supports the Maxim MAX6874 hex power-supply - sequencer/supervisor if found at a compatible address. - - This driver can also be built as a module. If so, the module - will be called max6875. - -config SENSORS_TSL2550 - tristate "Taos TSL2550 ambient light sensor" - depends on EXPERIMENTAL - help - If you say yes here you get support for the Taos TSL2550 - ambient light sensor. - - This driver can also be built as a module. If so, the module - will be called tsl2550. - -config MENELAUS - bool "TWL92330/Menelaus PM chip" - depends on I2C=y && ARCH_OMAP24XX - help - If you say yes here you get support for the Texas Instruments - TWL92330/Menelaus Power Management chip. This include voltage - regulators, Dual slot memory card tranceivers, real-time clock - and other features that are often used in portable devices like - cell phones and PDAs. - -endmenu diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile deleted file mode 100644 index e47aca0ca5a..00000000000 --- a/drivers/i2c/chips/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -# -# Makefile for miscellaneous I2C chip drivers. -# -# Think twice before you add a new driver to this directory. -# Device drivers are better grouped according to the functionality they -# implement rather than to the bus they are connected to. In particular: -# * Hardware monitoring chip drivers go to drivers/hwmon -# * RTC chip drivers go to drivers/rtc -# * I/O expander drivers go to drivers/gpio -# - -obj-$(CONFIG_DS1682) += ds1682.o -obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o -obj-$(CONFIG_SENSORS_MAX6875) += max6875.o -obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o -obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o -obj-$(CONFIG_PCF8575) += pcf8575.o -obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o -obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o -obj-$(CONFIG_TPS65010) += tps65010.o -obj-$(CONFIG_MENELAUS) += menelaus.o -obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o - -ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) -EXTRA_CFLAGS += -DDEBUG -endif - diff --git a/drivers/i2c/chips/ds1682.c b/drivers/i2c/chips/ds1682.c deleted file mode 100644 index 9e94542c18a..00000000000 --- a/drivers/i2c/chips/ds1682.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Dallas Semiconductor DS1682 Elapsed Time Recorder device driver - * - * Written by: Grant Likely <grant.likely@secretlab.ca> - * - * Copyright (C) 2007 Secret Lab Technologies Ltd. - * - * 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. - */ - -/* - * The DS1682 elapsed timer recorder is a simple device that implements - * one elapsed time counter, one event counter, an alarm signal and 10 - * bytes of general purpose EEPROM. - * - * This driver provides access to the DS1682 counters and user data via - * the sysfs. The following attributes are added to the device node: - * elapsed_time (u32): Total elapsed event time in ms resolution - * alarm_time (u32): When elapsed time exceeds the value in alarm_time, - * then the alarm pin is asserted. - * event_count (u16): number of times the event pin has gone low. - * eeprom (u8[10]): general purpose EEPROM - * - * Counter registers and user data are both read/write unless the device - * has been write protected. This driver does not support turning off write - * protection. Once write protection is turned on, it is impossible to - * turn it off again, so I have left the feature out of this driver to avoid - * accidental enabling, but it is trivial to add write protect support. - * - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/i2c.h> -#include <linux/string.h> -#include <linux/list.h> -#include <linux/sysfs.h> -#include <linux/ctype.h> -#include <linux/hwmon-sysfs.h> - -/* Device registers */ -#define DS1682_REG_CONFIG 0x00 -#define DS1682_REG_ALARM 0x01 -#define DS1682_REG_ELAPSED 0x05 -#define DS1682_REG_EVT_CNTR 0x09 -#define DS1682_REG_EEPROM 0x0b -#define DS1682_REG_RESET 0x1d -#define DS1682_REG_WRITE_DISABLE 0x1e -#define DS1682_REG_WRITE_MEM_DISABLE 0x1f - -#define DS1682_EEPROM_SIZE 10 - -/* - * Generic counter attributes - */ -static ssize_t ds1682_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - struct i2c_client *client = to_i2c_client(dev); - __le32 val = 0; - int rc; - - dev_dbg(dev, "ds1682_show() called on %s\n", attr->attr.name); - - /* Read the register */ - rc = i2c_smbus_read_i2c_block_data(client, sattr->index, sattr->nr, - (u8 *) & val); - if (rc < 0) - return -EIO; - - /* Special case: the 32 bit regs are time values with 1/4s - * resolution, scale them up to milliseconds */ - if (sattr->nr == 4) - return sprintf(buf, "%llu\n", - ((unsigned long long)le32_to_cpu(val)) * 250); - - /* Format the output string and return # of bytes */ - return sprintf(buf, "%li\n", (long)le32_to_cpu(val)); -} - -static ssize_t ds1682_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - struct i2c_client *client = to_i2c_client(dev); - char *endp; - u64 val; - __le32 val_le; - int rc; - - dev_dbg(dev, "ds1682_store() called on %s\n", attr->attr.name); - - /* Decode input */ - val = simple_strtoull(buf, &endp, 0); - if (buf == endp) { - dev_dbg(dev, "input string not a number\n"); - return -EINVAL; - } - - /* Special case: the 32 bit regs are time values with 1/4s - * resolution, scale input down to quarter-seconds */ - if (sattr->nr == 4) - do_div(val, 250); - - /* write out the value */ - val_le = cpu_to_le32(val); - rc = i2c_smbus_write_i2c_block_data(client, sattr->index, sattr->nr, - (u8 *) & val_le); - if (rc < 0) { - dev_err(dev, "register write failed; reg=0x%x, size=%i\n", - sattr->index, sattr->nr); - return -EIO; - } - - return count; -} - -/* - * Simple register attributes - */ -static SENSOR_DEVICE_ATTR_2(elapsed_time, S_IRUGO | S_IWUSR, ds1682_show, - ds1682_store, 4, DS1682_REG_ELAPSED); -static SENSOR_DEVICE_ATTR_2(alarm_time, S_IRUGO | S_IWUSR, ds1682_show, - ds1682_store, 4, DS1682_REG_ALARM); -static SENSOR_DEVICE_ATTR_2(event_count, S_IRUGO | S_IWUSR, ds1682_show, - ds1682_store, 2, DS1682_REG_EVT_CNTR); - -static const struct attribute_group ds1682_group = { - .attrs = (struct attribute *[]) { - &sensor_dev_attr_elapsed_time.dev_attr.attr, - &sensor_dev_attr_alarm_time.dev_attr.attr, - &sensor_dev_attr_event_count.dev_attr.attr, - NULL, - }, -}; - -/* - * User data attribute - */ -static ssize_t ds1682_eeprom_read(struct kobject *kobj, struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - struct i2c_client *client = kobj_to_i2c_client(kobj); - int rc; - - dev_dbg(&client->dev, "ds1682_eeprom_read(p=%p, off=%lli, c=%zi)\n", - buf, off, count); - - if (off >= DS1682_EEPROM_SIZE) - return 0; - - if (off + count > DS1682_EEPROM_SIZE) - count = DS1682_EEPROM_SIZE - off; - - rc = i2c_smbus_read_i2c_block_data(client, DS1682_REG_EEPROM + off, - count, buf); - if (rc < 0) - return -EIO; - - return count; -} - -static ssize_t ds1682_eeprom_write(struct kobject *kobj, struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - struct i2c_client *client = kobj_to_i2c_client(kobj); - - dev_dbg(&client->dev, "ds1682_eeprom_write(p=%p, off=%lli, c=%zi)\n", - buf, off, count); - - if (off >= DS1682_EEPROM_SIZE) - return -ENOSPC; - - if (off + count > DS1682_EEPROM_SIZE) - count = DS1682_EEPROM_SIZE - off; - - /* Write out to the device */ - if (i2c_smbus_write_i2c_block_data(client, DS1682_REG_EEPROM + off, - count, buf) < 0) - return -EIO; - - return count; -} - -static struct bin_attribute ds1682_eeprom_attr = { - .attr = { - .name = "eeprom", - .mode = S_IRUGO | S_IWUSR, - .owner = THIS_MODULE, - }, - .size = DS1682_EEPROM_SIZE, - .read = ds1682_eeprom_read, - .write = ds1682_eeprom_write, -}; - -/* - * Called when a ds1682 device is matched with this driver - */ -static int ds1682_probe(struct i2c_client *client) -{ - int rc; - - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_I2C_BLOCK)) { - dev_err(&client->dev, "i2c bus does not support the ds1682\n"); - rc = -ENODEV; - goto exit; - } - - rc = sysfs_create_group(&client->dev.kobj, &ds1682_group); - if (rc) - goto exit; - - rc = sysfs_create_bin_file(&client->dev.kobj, &ds1682_eeprom_attr); - if (rc) - goto exit_bin_attr; - - return 0; - - exit_bin_attr: - sysfs_remove_group(&client->dev.kobj, &ds1682_group); - exit: - return rc; -} - -static int ds1682_remove(struct i2c_client *client) -{ - sysfs_remove_bin_file(&client->dev.kobj, &ds1682_eeprom_attr); - sysfs_remove_group(&client->dev.kobj, &ds1682_group); - return 0; -} - -static struct i2c_driver ds1682_driver = { - .driver = { - .name = "ds1682", - }, - .probe = ds1682_probe, - .remove = ds1682_remove, -}; - -static int __init ds1682_init(void) -{ - return i2c_add_driver(&ds1682_driver); -} - -static void __exit ds1682_exit(void) -{ - i2c_del_driver(&ds1682_driver); -} - -MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>"); -MODULE_DESCRIPTION("DS1682 Elapsed Time Indicator driver"); -MODULE_LICENSE("GPL"); - -module_init(ds1682_init); -module_exit(ds1682_exit); diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c deleted file mode 100644 index 7dee001e513..00000000000 --- a/drivers/i2c/chips/eeprom.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - eeprom.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and - Philip Edelbrock <phil@netroedge.com> - Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com> - Copyright (C) 2003 IBM Corp. - - 2004-01-16 Jean Delvare <khali@linux-fr.org> - Divide the eeprom in 32-byte (arbitrary) slices. This significantly - speeds sensors up, as well as various scripts using the eeprom - module. - - 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 <linux/kernel.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/jiffies.h> -#include <linux/i2c.h> -#include <linux/mutex.h> - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, - 0x55, 0x56, 0x57, I2C_CLIENT_END }; - -/* Insmod parameters */ -I2C_CLIENT_INSMOD_1(eeprom); - - -/* Size of EEPROM in bytes */ -#define EEPROM_SIZE 256 - -/* possible types of eeprom devices */ -enum eeprom_nature { - UNKNOWN, - VAIO, -}; - -/* Each client has this additional data */ -struct eeprom_data { - struct i2c_client client; - struct mutex update_lock; - u8 valid; /* bitfield, bit!=0 if slice is valid */ - unsigned long last_updated[8]; /* In jiffies, 8 slices */ - u8 data[EEPROM_SIZE]; /* Register values */ - enum eeprom_nature nature; -}; - - -static int eeprom_attach_adapter(struct i2c_adapter *adapter); -static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind); -static int eeprom_detach_client(struct i2c_client *client); - -/* This is the driver that will be inserted */ -static struct i2c_driver eeprom_driver = { - .driver = { - .name = "eeprom", - }, - .attach_adapter = eeprom_attach_adapter, - .detach_client = eeprom_detach_client, -}; - -static void eeprom_update_client(struct i2c_client *client, u8 slice) -{ - struct eeprom_data *data = i2c_get_clientdata(client); - int i, j; - - mutex_lock(&data->update_lock); - - if (!(data->valid & (1 << slice)) || - time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { - dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); - - if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { - for (i = slice << 5; i < (slice + 1) << 5; i += 32) - if (i2c_smbus_read_i2c_block_data(client, i, - 32, data->data + i) - != 32) - goto exit; - } else { - if (i2c_smbus_write_byte(client, slice << 5)) { - dev_dbg(&client->dev, "eeprom read start has failed!\n"); - goto exit; - } - for (i = slice << 5; i < (slice + 1) << 5; i++) { - j = i2c_smbus_read_byte(client); - if (j < 0) - goto exit; - data->data[i] = (u8) j; - } - } - data->last_updated[slice] = jiffies; - data->valid |= (1 << slice); - } -exit: - mutex_unlock(&data->update_lock); -} - -static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); - struct eeprom_data *data = i2c_get_clientdata(client); - u8 slice; - - if (off > EEPROM_SIZE) - return 0; - if (off + count > EEPROM_SIZE) - count = EEPROM_SIZE - off; - - /* Only refresh slices which contain requested bytes */ - for (slice = off >> 5; slice <= (off + count - 1) >> 5; slice++) - eeprom_update_client(client, slice); - - /* Hide Vaio private settings to regular users: - - BIOS passwords: bytes 0x00 to 0x0f - - UUID: bytes 0x10 to 0x1f - - Serial number: 0xc0 to 0xdf */ - if (data->nature == VAIO && !capable(CAP_SYS_ADMIN)) { - int i; - - for (i = 0; i < count; i++) { - if ((off + i <= 0x1f) || - (off + i >= 0xc0 && off + i <= 0xdf)) - buf[i] = 0; - else - buf[i] = data->data[off + i]; - } - } else { - memcpy(buf, &data->data[off], count); - } - - return count; -} - -static struct bin_attribute eeprom_attr = { - .attr = { - .name = "eeprom", - .mode = S_IRUGO, - }, - .size = EEPROM_SIZE, - .read = eeprom_read, -}; - -static int eeprom_attach_adapter(struct i2c_adapter *adapter) -{ - return i2c_probe(adapter, &addr_data, eeprom_detect); -} - -/* This function is called by i2c_probe */ -static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) -{ - struct i2c_client *new_client; - struct eeprom_data *data; - int err = 0; - - /* There are three ways we can read the EEPROM data: - (1) I2C block reads (faster, but unsupported by most adapters) - (2) Consecutive byte reads (100% overhead) - (3) Regular byte data reads (200% overhead) - The third method is not implemented by this driver because all - known adapters support at least the second. */ - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA - | I2C_FUNC_SMBUS_BYTE)) - goto exit; - - if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - new_client = &data->client; - memset(data->data, 0xff, EEPROM_SIZE); - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &eeprom_driver; - new_client->flags = 0; - - /* Fill in the remaining client fields */ - strlcpy(new_client->name, "eeprom", I2C_NAME_SIZE); - data->valid = 0; - mutex_init(&data->update_lock); - data->nature = UNKNOWN; - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto exit_kfree; - - /* Detect the Vaio nature of EEPROMs. - We use the "PCG-" or "VGN-" prefix as the signature. */ - if (address == 0x57) { - char name[4]; - - name[0] = i2c_smbus_read_byte_data(new_client, 0x80); - name[1] = i2c_smbus_read_byte(new_client); - name[2] = i2c_smbus_read_byte(new_client); - name[3] = i2c_smbus_read_byte(new_client); - - if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) { - dev_info(&new_client->dev, "Vaio EEPROM detected, " - "enabling privacy protection\n"); - data->nature = VAIO; - } - } - - /* create the sysfs eeprom file */ - err = sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr); - if (err) - goto exit_detach; - - return 0; - -exit_detach: - i2c_detach_client(new_client); -exit_kfree: - kfree(data); -exit: - return err; -} - -static int eeprom_detach_client(struct i2c_client *client) -{ - int err; - - sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr); - - err = i2c_detach_client(client); - if (err) - return err; - - kfree(i2c_get_clientdata(client)); - - return 0; -} - -static int __init eeprom_init(void) -{ - return i2c_add_driver(&eeprom_driver); -} - -static void __exit eeprom_exit(void) -{ - i2c_del_driver(&eeprom_driver); -} - - -MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and " - "Philip Edelbrock <phil@netroedge.com> and " - "Greg Kroah-Hartman <greg@kroah.com>"); -MODULE_DESCRIPTION("I2C EEPROM driver"); -MODULE_LICENSE("GPL"); - -module_init(eeprom_init); -module_exit(eeprom_exit); diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c deleted file mode 100644 index 2a3160153f5..00000000000 --- a/drivers/i2c/chips/isp1301_omap.c +++ /dev/null @@ -1,1650 +0,0 @@ -/* - * isp1301_omap - ISP 1301 USB transceiver, talking to OMAP OTG controller - * - * Copyright (C) 2004 Texas Instruments - * Copyright (C) 2004 David Brownell - * - * 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 <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/usb/ch9.h> -#include <linux/usb/gadget.h> -#include <linux/usb.h> -#include <linux/usb/otg.h> -#include <linux/i2c.h> -#include <linux/workqueue.h> - -#include <asm/irq.h> -#include <asm/arch/usb.h> - - -#ifndef DEBUG -#undef VERBOSE -#endif - - -#define DRIVER_VERSION "24 August 2004" -#define DRIVER_NAME (isp1301_driver.driver.name) - -MODULE_DESCRIPTION("ISP1301 USB OTG Transceiver Driver"); -MODULE_LICENSE("GPL"); - -struct isp1301 { - struct otg_transceiver otg; - struct i2c_client client; - void (*i2c_release)(struct device *dev); - - int irq; - int irq_type; - - u32 last_otg_ctrl; - unsigned working:1; - - struct timer_list timer; - - /* use keventd context to change the state for us */ - struct work_struct work; - - unsigned long todo; -# define WORK_UPDATE_ISP 0 /* update ISP from OTG */ -# define WORK_UPDATE_OTG 1 /* update OTG from ISP */ -# define WORK_HOST_RESUME 4 /* resume host */ -# define WORK_TIMER 6 /* timer fired */ -# define WORK_STOP 7 /* don't resubmit */ -}; - - -/* bits in OTG_CTRL_REG */ - -#define OTG_XCEIV_OUTPUTS \ - (OTG_ASESSVLD|OTG_BSESSEND|OTG_BSESSVLD|OTG_VBUSVLD|OTG_ID) -#define OTG_XCEIV_INPUTS \ - (OTG_PULLDOWN|OTG_PULLUP|OTG_DRV_VBUS|OTG_PD_VBUS|OTG_PU_VBUS|OTG_PU_ID) -#define OTG_CTRL_BITS \ - (OTG_A_BUSREQ|OTG_A_SETB_HNPEN|OTG_B_BUSREQ|OTG_B_HNPEN|OTG_BUSDROP) - /* and OTG_PULLUP is sometimes written */ - -#define OTG_CTRL_MASK (OTG_DRIVER_SEL| \ - OTG_XCEIV_OUTPUTS|OTG_XCEIV_INPUTS| \ - OTG_CTRL_BITS) - - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_MACH_OMAP_H2 - -/* board-specific PM hooks */ - -#include <asm/gpio.h> -#include <asm/arch/mux.h> -#include <asm/mach-types.h> - - -#if defined(CONFIG_TPS65010) || defined(CONFIG_TPS65010_MODULE) - -#include <linux/i2c/tps65010.h> - -#else - -static inline int tps65010_set_vbus_draw(unsigned mA) -{ - pr_debug("tps65010: draw %d mA (STUB)\n", mA); - return 0; -} - -#endif - -static void enable_vbus_draw(struct isp1301 *isp, unsigned mA) -{ - int status = tps65010_set_vbus_draw(mA); - if (status < 0) - pr_debug(" VBUS %d mA error %d\n", mA, status); -} - -static void enable_vbus_source(struct isp1301 *isp) -{ - /* this board won't supply more than 8mA vbus power. - * some boards can switch a 100ma "unit load" (or more). - */ -} - - -/* products will deliver OTG messages with LEDs, GUI, etc */ -static inline void notresponding(struct isp1301 *isp) -{ - printk(KERN_NOTICE "OTG device not responding.\n"); -} - - -#endif - -/*-------------------------------------------------------------------------*/ - -/* only two addresses possible */ -#define ISP_BASE 0x2c -static unsigned short normal_i2c[] = { - ISP_BASE, ISP_BASE + 1, - I2C_CLIENT_END }; - -I2C_CLIENT_INSMOD; - -static struct i2c_driver isp1301_driver; - -/* smbus apis are used for portability */ - -static inline u8 -isp1301_get_u8(struct isp1301 *isp, u8 reg) -{ - return i2c_smbus_read_byte_data(&isp->client, reg + 0); -} - -static inline int -isp1301_get_u16(struct isp1301 *isp, u8 reg) -{ - return i2c_smbus_read_word_data(&isp->client, reg); -} - -static inline int -isp1301_set_bits(struct isp1301 *isp, u8 reg, u8 bits) -{ - return i2c_smbus_write_byte_data(&isp->client, reg + 0, bits); -} - -static inline int -isp1301_clear_bits(struct isp1301 *isp, u8 reg, u8 bits) -{ - return i2c_smbus_write_byte_data(&isp->client, reg + 1, bits); -} - -/*-------------------------------------------------------------------------*/ - -/* identification */ -#define ISP1301_VENDOR_ID 0x00 /* u16 read */ -#define ISP1301_PRODUCT_ID 0x02 /* u16 read */ -#define ISP1301_BCD_DEVICE 0x14 /* u16 read */ - -#define I2C_VENDOR_ID_PHILIPS 0x04cc -#define I2C_PRODUCT_ID_PHILIPS_1301 0x1301 - -/* operational registers */ -#define ISP1301_MODE_CONTROL_1 0x04 /* u8 read, set, +1 clear */ -# define MC1_SPEED_REG (1 << 0) -# define MC1_SUSPEND_REG (1 << 1) -# define MC1_DAT_SE0 (1 << 2) -# define MC1_TRANSPARENT (1 << 3) -# define MC1_BDIS_ACON_EN (1 << 4) -# define MC1_OE_INT_EN (1 << 5) -# define MC1_UART_EN (1 << 6) -# define MC1_MASK 0x7f -#define ISP1301_MODE_CONTROL_2 0x12 /* u8 read, set, +1 clear */ -# define MC2_GLOBAL_PWR_DN (1 << 0) -# define MC2_SPD_SUSP_CTRL (1 << 1) -# define MC2_BI_DI (1 << 2) -# define MC2_TRANSP_BDIR0 (1 << 3) -# define MC2_TRANSP_BDIR1 (1 << 4) -# define MC2_AUDIO_EN (1 << 5) -# define MC2_PSW_EN (1 << 6) -# define MC2_EN2V7 (1 << 7) -#define ISP1301_OTG_CONTROL_1 0x06 /* u8 read, set, +1 clear */ -# define OTG1_DP_PULLUP (1 << 0) -# define OTG1_DM_PULLUP (1 << 1) -# define OTG1_DP_PULLDOWN (1 << 2) -# define OTG1_DM_PULLDOWN (1 << 3) -# define OTG1_ID_PULLDOWN (1 << 4) -# define OTG1_VBUS_DRV (1 << 5) -# define OTG1_VBUS_DISCHRG (1 << 6) -# define OTG1_VBUS_CHRG (1 << 7) -#define ISP1301_OTG_STATUS 0x10 /* u8 readonly */ -# define OTG_B_SESS_END (1 << 6) -# define OTG_B_SESS_VLD (1 << 7) - -#define ISP1301_INTERRUPT_SOURCE 0x08 /* u8 read */ -#define ISP1301_INTERRUPT_LATCH 0x0A /* u8 read, set, +1 clear */ - -#define ISP1301_INTERRUPT_FALLING 0x0C /* u8 read, set, +1 clear */ -#define ISP1301_INTERRUPT_RISING 0x0E /* u8 read, set, +1 clear */ - -/* same bitfields in all interrupt registers */ -# define INTR_VBUS_VLD (1 << 0) -# define INTR_SESS_VLD (1 << 1) -# define INTR_DP_HI (1 << 2) -# define INTR_ID_GND (1 << 3) -# define INTR_DM_HI (1 << 4) -# define INTR_ID_FLOAT (1 << 5) -# define INTR_BDIS_ACON (1 << 6) -# define INTR_CR_INT (1 << 7) - -/*-------------------------------------------------------------------------*/ - -static const char *state_string(enum usb_otg_state state) -{ - switch (state) { - case OTG_STATE_A_IDLE: return "a_idle"; - case OTG_STATE_A_WAIT_VRISE: return "a_wait_vrise"; - case OTG_STATE_A_WAIT_BCON: return "a_wait_bcon"; - case OTG_STATE_A_HOST: return "a_host"; - case OTG_STATE_A_SUSPEND: return "a_suspend"; - case OTG_STATE_A_PERIPHERAL: return "a_peripheral"; - case OTG_STATE_A_WAIT_VFALL: return "a_wait_vfall"; - case OTG_STATE_A_VBUS_ERR: return "a_vbus_err"; - case OTG_STATE_B_IDLE: return "b_idle"; - case OTG_STATE_B_SRP_INIT: return "b_srp_init"; - case OTG_STATE_B_PERIPHERAL: return "b_peripheral"; - case OTG_STATE_B_WAIT_ACON: return "b_wait_acon"; - case OTG_STATE_B_HOST: return "b_host"; - default: return "UNDEFINED"; - } -} - -static inline const char *state_name(struct isp1301 *isp) -{ - return state_string(isp->otg.state); -} - -/*-------------------------------------------------------------------------*/ - -/* NOTE: some of this ISP1301 setup is specific to H2 boards; - * not everything is guarded by board-specific checks, or even using - * omap_usb_config data to deduce MC1_DAT_SE0 and MC2_BI_DI. - * - * ALSO: this currently doesn't use ISP1301 low-power modes - * while OTG is running. - */ - -static void power_down(struct isp1301 *isp) -{ - isp->otg.state = OTG_STATE_UNDEFINED; - - // isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN); - isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND_REG); - - isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_ID_PULLDOWN); - isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0); -} - -static void power_up(struct isp1301 *isp) -{ - // isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN); - isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND_REG); - - /* do this only when cpu is driving transceiver, - * so host won't see a low speed device... - */ - isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0); -} - -#define NO_HOST_SUSPEND - -static int host_suspend(struct isp1301 *isp) -{ -#ifdef NO_HOST_SUSPEND - return 0; -#else - struct device *dev; - - if (!isp->otg.host) - return -ENODEV; - - /* Currently ASSUMES only the OTG port matters; - * other ports could be active... - */ - dev = isp->otg.host->controller; - return dev->driver->suspend(dev, 3, 0); -#endif -} - -static int host_resume(struct isp1301 *isp) -{ -#ifdef NO_HOST_SUSPEND - return 0; -#else - struct device *dev; - - if (!isp->otg.host) - return -ENODEV; - - dev = isp->otg.host->controller; - return dev->driver->resume(dev, 0); -#endif -} - -static int gadget_suspend(struct isp1301 *isp) -{ - isp->otg.gadget->b_hnp_enable = 0; - isp->otg.gadget->a_hnp_support = 0; - isp->otg.gadget->a_alt_hnp_support = 0; - return usb_gadget_vbus_disconnect(isp->otg.gadget); -} - -/*-------------------------------------------------------------------------*/ - -#define TIMER_MINUTES 10 -#define TIMER_JIFFIES (TIMER_MINUTES * 60 * HZ) - -/* Almost all our I2C messaging comes from a work queue's task context. - * NOTE: guaranteeing certain response times might mean we shouldn't - * share keventd's work queue; a realtime task might be safest. - */ -void -isp1301_defer_work(struct isp1301 *isp, int work) -{ - int status; - - if (isp && !test_and_set_bit(work, &isp->todo)) { - (void) get_device(&isp->client.dev); - status = schedule_work(&isp->work); - if (!status && !isp->working) - dev_vdbg(&isp->client.dev, - "work item %d may be lost\n", work); - } -} - -/* called from irq handlers */ -static void a_idle(struct isp1301 *isp, const char *tag) -{ - if (isp->otg.state == OTG_STATE_A_IDLE) - return; - - isp->otg.default_a = 1; - if (isp->otg.host) { - isp->otg.host->is_b_host = 0; - host_suspend(isp); - } - if (isp->otg.gadget) { - isp->otg.gadget->is_a_peripheral = 1; - gadget_suspend(isp); - } - isp->otg.state = OTG_STATE_A_IDLE; - isp->last_otg_ctrl = OTG_CTRL_REG = OTG_CTRL_REG & OTG_XCEIV_OUTPUTS; - pr_debug(" --> %s/%s\n", state_name(isp), tag); -} - -/* called from irq handlers */ -static void b_idle(struct isp1301 *isp, const char *tag) -{ - if (isp->otg.state == OTG_STATE_B_IDLE) - return; - - isp->otg.default_a = 0; - if (isp->otg.host) { - isp->otg.host->is_b_host = 1; - host_suspend(isp); - } - if (isp->otg.gadget) { - isp->otg.gadget->is_a_peripheral = 0; - gadget_suspend(isp); - } - isp->otg.state = OTG_STATE_B_IDLE; - isp->last_otg_ctrl = OTG_CTRL_REG = OTG_CTRL_REG & OTG_XCEIV_OUTPUTS; - pr_debug(" --> %s/%s\n", state_name(isp), tag); -} - -static void -dump_regs(struct isp1301 *isp, const char *label) -{ -#ifdef DEBUG - u8 ctrl = isp1301_get_u8(isp, ISP1301_OTG_CONTROL_1); - u8 status = isp1301_get_u8(isp, ISP1301_OTG_STATUS); - u8 src = isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE); - - pr_debug("otg: %06x, %s %s, otg/%02x stat/%02x.%02x\n", - OTG_CTRL_REG, label, state_name(isp), - ctrl, status, src); - /* mode control and irq enables don't change much */ -#endif -} - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_USB_OTG - -/* - * The OMAP OTG controller handles most of the OTG state transitions. - * - * We translate isp1301 outputs (mostly voltage comparator status) into - * OTG inputs; OTG outputs (mostly pullup/pulldown controls) and HNP state - * flags into isp1301 inputs ... and infer state transitions. - */ - -#ifdef VERBOSE - -static void check_state(struct isp1301 *isp, const char *tag) -{ - enum usb_otg_state state = OTG_STATE_UNDEFINED; - u8 fsm = OTG_TEST_REG & 0x0ff; - unsigned extra = 0; - - switch (fsm) { - - /* default-b */ - case 0x0: - state = OTG_STATE_B_IDLE; - break; - case 0x3: - case 0x7: - extra = 1; - case 0x1: - state = OTG_STATE_B_PERIPHERAL; - break; - case 0x11: - state = OTG_STATE_B_SRP_INIT; - break; - - /* extra dual-role default-b states */ - case 0x12: - case 0x13: - case 0x16: - extra = 1; - case 0x17: - state = OTG_STATE_B_WAIT_ACON; - break; - case 0x34: - state = OTG_STATE_B_HOST; - break; - - /* default-a */ - case 0x36: - state = OTG_STATE_A_IDLE; - break; - case 0x3c: - state = OTG_STATE_A_WAIT_VFALL; - break; - case 0x7d: - state = OTG_STATE_A_VBUS_ERR; - break; - case 0x9e: - case 0x9f: - extra = 1; - case 0x89: - state = OTG_STATE_A_PERIPHERAL; - break; - case 0xb7: - state = OTG_STATE_A_WAIT_VRISE; - break; - case 0xb8: - state = OTG_STATE_A_WAIT_BCON; - break; - case 0xb9: - state = OTG_STATE_A_HOST; - break; - case 0xba: - state = OTG_STATE_A_SUSPEND; - break; - default: - break; - } - if (isp->otg.state == state && !extra) - return; - pr_debug("otg: %s FSM %s/%02x, %s, %06x\n", tag, - state_string(state), fsm, state_name(isp), OTG_CTRL_REG); -} - -#else - -static inline void check_state(struct isp1301 *isp, const char *tag) { } - -#endif - -/* outputs from ISP1301_INTERRUPT_SOURCE */ -static void update_otg1(struct isp1301 *isp, u8 int_src) -{ - u32 otg_ctrl; - - otg_ctrl = OTG_CTRL_REG - & OTG_CTRL_MASK - & ~OTG_XCEIV_INPUTS - & ~(OTG_ID|OTG_ASESSVLD|OTG_VBUSVLD); - if (int_src & INTR_SESS_VLD) - otg_ctrl |= OTG_ASESSVLD; - else if (isp->otg.state == OTG_STATE_A_WAIT_VFALL) { - a_idle(isp, "vfall"); - otg_ctrl &= ~OTG_CTRL_BITS; - } - if (int_src & INTR_VBUS_VLD) - otg_ctrl |= OTG_VBUSVLD; - if (int_src & INTR_ID_GND) { /* default-A */ - if (isp->otg.state == OTG_STATE_B_IDLE - || isp->otg.state == OTG_STATE_UNDEFINED) { - a_idle(isp, "init"); - return; - } - } else { /* default-B */ - otg_ctrl |= OTG_ID; - if (isp->otg.state == OTG_STATE_A_IDLE - || isp->otg.state == OTG_STATE_UNDEFINED) { - b_idle(isp, "init"); - return; - } - } - OTG_CTRL_REG = otg_ctrl; -} - -/* outputs from ISP1301_OTG_STATUS */ -static void update_otg2(struct isp1301 *isp, u8 otg_status) -{ - u32 otg_ctrl; - - otg_ctrl = OTG_CTRL_REG - & OTG_CTRL_MASK - & ~OTG_XCEIV_INPUTS - & ~(OTG_BSESSVLD|OTG_BSESSEND); - if (otg_status & OTG_B_SESS_VLD) - otg_ctrl |= OTG_BSESSVLD; - else if (otg_status & OTG_B_SESS_END) - otg_ctrl |= OTG_BSESSEND; - OTG_CTRL_REG = otg_ctrl; -} - -/* inputs going to ISP1301 */ -static void otg_update_isp(struct isp1301 *isp) -{ - u32 otg_ctrl, otg_change; - u8 set = OTG1_DM_PULLDOWN, clr = OTG1_DM_PULLUP; - - otg_ctrl = OTG_CTRL_REG; - otg_change = otg_ctrl ^ isp->last_otg_ctrl; - isp->last_otg_ctrl = otg_ctrl; - otg_ctrl = otg_ctrl & OTG_XCEIV_INPUTS; - - switch (isp->otg.state) { - case OTG_STATE_B_IDLE: - case OTG_STATE_B_PERIPHERAL: - case OTG_STATE_B_SRP_INIT: - if (!(otg_ctrl & OTG_PULLUP)) { - // if (otg_ctrl & OTG_B_HNPEN) { - if (isp->otg.gadget->b_hnp_enable) { - isp->otg.state = OTG_STATE_B_WAIT_ACON; - pr_debug(" --> b_wait_acon\n"); - } - goto pulldown; - } -pullup: - set |= OTG1_DP_PULLUP; - clr |= OTG1_DP_PULLDOWN; - break; - case OTG_STATE_A_SUSPEND: - case OTG_STATE_A_PERIPHERAL: - if (otg_ctrl & OTG_PULLUP) - goto pullup; - /* FALLTHROUGH */ - // case OTG_STATE_B_WAIT_ACON: - default: -pulldown: - set |= OTG1_DP_PULLDOWN; - clr |= OTG1_DP_PULLUP; - break; - } - -# define toggle(OTG,ISP) do { \ - if (otg_ctrl & OTG) set |= ISP; \ - else clr |= ISP; \ - } while (0) - - if (!(isp->otg.host)) - otg_ctrl &= ~OTG_DRV_VBUS; - - switch (isp->otg.state) { - case OTG_STATE_A_SUSPEND: - if (otg_ctrl & OTG_DRV_VBUS) { - set |= OTG1_VBUS_DRV; - break; - } - /* HNP failed for some reason (A_AIDL_BDIS timeout) */ - notresponding(isp); - - /* FALLTHROUGH */ - case OTG_STATE_A_VBUS_ERR: - isp->otg.state = OTG_STATE_A_WAIT_VFALL; - pr_debug(" --> a_wait_vfall\n"); - /* FALLTHROUGH */ - case OTG_STATE_A_WAIT_VFALL: - /* FIXME usbcore thinks port power is still on ... */ - clr |= OTG1_VBUS_DRV; - break; - case OTG_STATE_A_IDLE: - if (otg_ctrl & OTG_DRV_VBUS) { - isp->otg.state = OTG_STATE_A_WAIT_VRISE; - pr_debug(" --> a_wait_vrise\n"); - } - /* FALLTHROUGH */ - default: - toggle(OTG_DRV_VBUS, OTG1_VBUS_DRV); - } - - toggle(OTG_PU_VBUS, OTG1_VBUS_CHRG); - toggle(OTG_PD_VBUS, OTG1_VBUS_DISCHRG); - -# undef toggle - - isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, set); - isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, clr); - - /* HNP switch to host or peripheral; and SRP */ - if (otg_change & OTG_PULLUP) { - switch (isp->otg.state) { - case OTG_STATE_B_IDLE: - if (clr & OTG1_DP_PULLUP) - break; - isp->otg.state = OTG_STATE_B_PERIPHERAL; - pr_debug(" --> b_peripheral\n"); - break; - case OTG_STATE_A_SUSPEND: - if (clr & OTG1_DP_PULLUP) - break; - isp->otg.state = OTG_STATE_A_PERIPHERAL; - pr_debug(" --> a_peripheral\n"); - break; - default: - break; - } - OTG_CTRL_REG |= OTG_PULLUP; - } - - check_state(isp, __FUNCTION__); - dump_regs(isp, "otg->isp1301"); -} - -static irqreturn_t omap_otg_irq(int irq, void *_isp) -{ - u16 otg_irq = OTG_IRQ_SRC_REG; - u32 otg_ctrl; - int ret = IRQ_NONE; - struct isp1301 *isp = _isp; - - /* update ISP1301 transciever from OTG controller */ - if (otg_irq & OPRT_CHG) { - OTG_IRQ_SRC_REG = OPRT_CHG; - isp1301_defer_work(isp, WORK_UPDATE_ISP); - ret = IRQ_HANDLED; - - /* SRP to become b_peripheral failed */ - } else if (otg_irq & B_SRP_TMROUT) { - pr_debug("otg: B_SRP_TIMEOUT, %06x\n", OTG_CTRL_REG); - notresponding(isp); - - /* gadget drivers that care should monitor all kinds of - * remote wakeup (SRP, normal) using their own timer - * to give "check cable and A-device" messages. - */ - if (isp->otg.state == OTG_STATE_B_SRP_INIT) - b_idle(isp, "srp_timeout"); - - OTG_IRQ_SRC_REG = B_SRP_TMROUT; - ret = IRQ_HANDLED; - - /* HNP to become b_host failed */ - } else if (otg_irq & B_HNP_FAIL) { - pr_debug("otg: %s B_HNP_FAIL, %06x\n", - state_name(isp), OTG_CTRL_REG); - notresponding(isp); - - otg_ctrl = OTG_CTRL_REG; - otg_ctrl |= OTG_BUSDROP; - otg_ctrl &= OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS; - OTG_CTRL_REG = otg_ctrl; - - /* subset of b_peripheral()... */ - isp->otg.state = OTG_STATE_B_PERIPHERAL; - pr_debug(" --> b_peripheral\n"); - - OTG_IRQ_SRC_REG = B_HNP_FAIL; - ret = IRQ_HANDLED; - - /* detect SRP from B-device ... */ - } else if (otg_irq & A_SRP_DETECT) { - pr_debug("otg: %s SRP_DETECT, %06x\n", - state_name(isp), OTG_CTRL_REG); - - isp1301_defer_work(isp, WORK_UPDATE_OTG); - switch (isp->otg.state) { - case OTG_STATE_A_IDLE: - if (!isp->otg.host) - break; - isp1301_defer_work(isp, WORK_HOST_RESUME); - otg_ctrl = OTG_CTRL_REG; - otg_ctrl |= OTG_A_BUSREQ; - otg_ctrl &= ~(OTG_BUSDROP|OTG_B_BUSREQ) - & ~OTG_XCEIV_INPUTS - & OTG_CTRL_MASK; - OTG_CTRL_REG = otg_ctrl; - break; - default: - break; - } - - OTG_IRQ_SRC_REG = A_SRP_DETECT; - ret = IRQ_HANDLED; - - /* timer expired: T(a_wait_bcon) and maybe T(a_wait_vrise) - * we don't track them separately - */ - } else if (otg_irq & A_REQ_TMROUT) { - otg_ctrl = OTG_CTRL_REG; - pr_info("otg: BCON_TMOUT from %s, %06x\n", - state_name(isp), otg_ctrl); - notresponding(isp); - - otg_ctrl |= OTG_BUSDROP; - otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS; - OTG_CTRL_REG = otg_ctrl; - isp->otg.state = OTG_STATE_A_WAIT_VFALL; - - OTG_IRQ_SRC_REG = A_REQ_TMROUT; - ret = IRQ_HANDLED; - - /* A-supplied voltage fell too low; overcurrent */ - } else if (otg_irq & A_VBUS_ERR) { - otg_ctrl = OTG_CTRL_REG; - printk(KERN_ERR "otg: %s, VBUS_ERR %04x ctrl %06x\n", - state_name(isp), otg_irq, otg_ctrl); - - otg_ctrl |= OTG_BUSDROP; - otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS; - OTG_CTRL_REG = otg_ctrl; - isp->otg.state = OTG_STATE_A_VBUS_ERR; - - OTG_IRQ_SRC_REG = A_VBUS_ERR; - ret = IRQ_HANDLED; - - /* switch driver; the transciever code activates it, - * ungating the udc clock or resuming OHCI. - */ - } else if (otg_irq & DRIVER_SWITCH) { - int kick = 0; - - otg_ctrl = OTG_CTRL_REG; - printk(KERN_NOTICE "otg: %s, SWITCH to %s, ctrl %06x\n", - state_name(isp), - (otg_ctrl & OTG_DRIVER_SEL) - ? "gadget" : "host", - otg_ctrl); - isp1301_defer_work(isp, WORK_UPDATE_ISP); - - /* role is peripheral */ - if (otg_ctrl & OTG_DRIVER_SEL) { - switch (isp->otg.state) { - case OTG_STATE_A_IDLE: - b_idle(isp, __FUNCTION__); - break; - default: - break; - } - isp1301_defer_work(isp, WORK_UPDATE_ISP); - - /* role is host */ - } else { - if (!(otg_ctrl & OTG_ID)) { - otg_ctrl &= OTG_CTRL_MASK & ~OTG_XCEIV_INPUTS; - OTG_CTRL_REG = otg_ctrl | OTG_A_BUSREQ; - } - - if (isp->otg.host) { - switch (isp->otg.state) { - case OTG_STATE_B_WAIT_ACON: - isp->otg.state = OTG_STATE_B_HOST; - pr_debug(" --> b_host\n"); - kick = 1; - break; - case OTG_STATE_A_WAIT_BCON: - isp->otg.state = OTG_STATE_A_HOST; - pr_debug(" --> a_host\n"); - break; - case OTG_STATE_A_PERIPHERAL: - isp->otg.state = OTG_STATE_A_WAIT_BCON; - pr_debug(" --> a_wait_bcon\n"); - break; - default: - break; - } - isp1301_defer_work(isp, WORK_HOST_RESUME); - } - } - - OTG_IRQ_SRC_REG = DRIVER_SWITCH; - ret = IRQ_HANDLED; - - if (kick) - usb_bus_start_enum(isp->otg.host, - isp->otg.host->otg_port); - } - - check_state(isp, __FUNCTION__); - return ret; -} - -static struct platform_device *otg_dev; - -static int otg_init(struct isp1301 *isp) -{ - if (!otg_dev) - return -ENODEV; - - dump_regs(isp, __FUNCTION__); - /* some of these values are board-specific... */ - OTG_SYSCON_2_REG |= OTG_EN - /* for B-device: */ - | SRP_GPDATA /* 9msec Bdev D+ pulse */ - | SRP_GPDVBUS /* discharge after VBUS pulse */ - // | (3 << 24) /* 2msec VBUS pulse */ - /* for A-device: */ - | (0 << 20) /* 200ms nominal A_WAIT_VRISE timer */ - | SRP_DPW /* detect 167+ns SRP pulses */ - | SRP_DATA | SRP_VBUS /* accept both kinds of SRP pulse */ - ; - - update_otg1(isp, isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE)); - update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS)); - - check_state(isp, __FUNCTION__); - pr_debug("otg: %s, %s %06x\n", - state_name(isp), __FUNCTION__, OTG_CTRL_REG); - - OTG_IRQ_EN_REG = DRIVER_SWITCH | OPRT_CHG - | B_SRP_TMROUT | B_HNP_FAIL - | A_VBUS_ERR | A_SRP_DETECT | A_REQ_TMROUT; - OTG_SYSCON_2_REG |= OTG_EN; - - return 0; -} - -static int otg_probe(struct platform_device *dev) -{ - // struct omap_usb_config *config = dev->platform_data; - - otg_dev = dev; - return 0; -} - -static int otg_remove(struct platform_device *dev) -{ - otg_dev = 0; - return 0; -} - -struct platform_driver omap_otg_driver = { - .probe = otg_probe, - .remove = otg_remove, - .driver = { - .owner = THIS_MODULE, - .name = "omap_otg", - }, -}; - -static int otg_bind(struct isp1301 *isp) -{ - int status; - - if (otg_dev) - return -EBUSY; - - status = platform_driver_register(&omap_otg_driver); - if (status < 0) - return status; - - if (otg_dev) - status = request_irq(otg_dev->resource[1].start, omap_otg_irq, - IRQF_DISABLED, DRIVER_NAME, isp); - else - status = -ENODEV; - - if (status < 0) - platform_driver_unregister(&omap_otg_driver); - return status; -} - -static void otg_unbind(struct isp1301 *isp) -{ - if (!otg_dev) - return; - free_irq(otg_dev->resource[1].start, isp); -} - -#else - -/* OTG controller isn't clocked */ - -#endif /* CONFIG_USB_OTG */ - -/*-------------------------------------------------------------------------*/ - -static void b_peripheral(struct isp1301 *isp) -{ - OTG_CTRL_REG = OTG_CTRL_REG & OTG_XCEIV_OUTPUTS; - usb_gadget_vbus_connect(isp->otg.gadget); - -#ifdef CONFIG_USB_OTG - enable_vbus_draw(isp, 8); - otg_update_isp(isp); -#else - enable_vbus_draw(isp, 100); - /* UDC driver just set OTG_BSESSVLD */ - isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLUP); - isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLDOWN); - isp->otg.state = OTG_STATE_B_PERIPHERAL; - pr_debug(" --> b_peripheral\n"); - dump_regs(isp, "2periph"); -#endif -} - -static void isp_update_otg(struct isp1301 *isp, u8 stat) -{ - u8 isp_stat, isp_bstat; - enum usb_otg_state state = isp->otg.state; - - if (stat & INTR_BDIS_ACON) - pr_debug("OTG: BDIS_ACON, %s\n", state_name(isp)); - - /* start certain state transitions right away */ - isp_stat = isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE); - if (isp_stat & INTR_ID_GND) { - if (isp->otg.default_a) { - switch (state) { - case OTG_STATE_B_IDLE: - a_idle(isp, "idle"); - /* FALLTHROUGH */ - case OTG_STATE_A_IDLE: - enable_vbus_source(isp); - /* FALLTHROUGH */ - case OTG_STATE_A_WAIT_VRISE: - /* we skip over OTG_STATE_A_WAIT_BCON, since - * the HC will transition to A_HOST (or - * A_SUSPEND!) without our noticing except - * when HNP is used. - */ - if (isp_stat & INTR_VBUS_VLD) - isp->otg.state = OTG_STATE_A_HOST; - break; - case OTG_STATE_A_WAIT_VFALL: - if (!(isp_stat & INTR_SESS_VLD)) - a_idle(isp, "vfell"); - break; - default: - if (!(isp_stat & INTR_VBUS_VLD)) - isp->otg.state = OTG_STATE_A_VBUS_ERR; - break; - } - isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS); - } else { - switch (state) { - case OTG_STATE_B_PERIPHERAL: - case OTG_STATE_B_HOST: - case OTG_STATE_B_WAIT_ACON: - usb_gadget_vbus_disconnect(isp->otg.gadget); - break; - default: - break; - } - if (state != OTG_STATE_A_IDLE) - a_idle(isp, "id"); - if (isp->otg.host && state == OTG_STATE_A_IDLE) - isp1301_defer_work(isp, WORK_HOST_RESUME); - isp_bstat = 0; - } - } else { - /* if user unplugged mini-A end of cable, - * don't bypass A_WAIT_VFALL. - */ - if (isp->otg.default_a) { - switch (state) { - default: - isp->otg.state = OTG_STATE_A_WAIT_VFALL; - break; - case OTG_STATE_A_WAIT_VFALL: - state = OTG_STATE_A_IDLE; - /* khubd may take a while to notice and - * handle this disconnect, so don't go - * to B_IDLE quite yet. - */ - break; - case OTG_STATE_A_IDLE: - host_suspend(isp); - isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, - MC1_BDIS_ACON_EN); - isp->otg.state = OTG_STATE_B_IDLE; - OTG_CTRL_REG &= OTG_CTRL_REG & OTG_CTRL_MASK - & ~OTG_CTRL_BITS; - break; - case OTG_STATE_B_IDLE: - break; - } - } - isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS); - - switch (isp->otg.state) { - case OTG_STATE_B_PERIPHERAL: - case OTG_STATE_B_WAIT_ACON: - case OTG_STATE_B_HOST: - if (likely(isp_bstat & OTG_B_SESS_VLD)) - break; - enable_vbus_draw(isp, 0); -#ifndef CONFIG_USB_OTG - /* UDC driver will clear OTG_BSESSVLD */ - isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, - OTG1_DP_PULLDOWN); - isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, - OTG1_DP_PULLUP); - dump_regs(isp, __FUNCTION__); -#endif - /* FALLTHROUGH */ - case OTG_STATE_B_SRP_INIT: - b_idle(isp, __FUNCTION__); - OTG_CTRL_REG &= OTG_CTRL_REG & OTG_XCEIV_OUTPUTS; - /* FALLTHROUGH */ - case OTG_STATE_B_IDLE: - if (isp->otg.gadget && (isp_bstat & OTG_B_SESS_VLD)) { -#ifdef CONFIG_USB_OTG - update_otg1(isp, isp_stat); - update_otg2(isp, isp_bstat); -#endif - b_peripheral(isp); - } else if (!(isp_stat & (INTR_VBUS_VLD|INTR_SESS_VLD))) - isp_bstat |= OTG_B_SESS_END; - break; - case OTG_STATE_A_WAIT_VFALL: - break; - default: - pr_debug("otg: unsupported b-device %s\n", - state_name(isp)); - break; - } - } - - if (state != isp->otg.state) - pr_debug(" isp, %s -> %s\n", - state_string(state), state_name(isp)); - -#ifdef CONFIG_USB_OTG - /* update the OTG controller state to match the isp1301; may - * trigger OPRT_CHG irqs for changes going to the isp1301. - */ - update_otg1(isp, isp_stat); - update_otg2(isp, isp_bstat); - check_state(isp, __FUNCTION__); -#endif - - dump_regs(isp, "isp1301->otg"); -} - -/*-------------------------------------------------------------------------*/ - -static u8 isp1301_clear_latch(struct isp1301 *isp) -{ - u8 latch = isp1301_get_u8(isp, ISP1301_INTERRUPT_LATCH); - isp1301_clear_bits(isp, ISP1301_INTERRUPT_LATCH, latch); - return latch; -} - -static void -isp1301_work(struct work_struct *work) -{ - struct isp1301 *isp = container_of(work, struct isp1301, work); - int stop; - - /* implicit lock: we're the only task using this device */ - isp->working = 1; - do { - stop = test_bit(WORK_STOP, &isp->todo); - -#ifdef CONFIG_USB_OTG - /* transfer state from otg engine to isp1301 */ - if (test_and_clear_bit(WORK_UPDATE_ISP, &isp->todo)) { - otg_update_isp(isp); - put_device(&isp->client.dev); - } -#endif - /* transfer state from isp1301 to otg engine */ - if (test_and_clear_bit(WORK_UPDATE_OTG, &isp->todo)) { - u8 stat = isp1301_clear_latch(isp); - - isp_update_otg(isp, stat); - put_device(&isp->client.dev); - } - - if (test_and_clear_bit(WORK_HOST_RESUME, &isp->todo)) { - u32 otg_ctrl; - - /* - * skip A_WAIT_VRISE; hc transitions invisibly - * skip A_WAIT_BCON; same. - */ - switch (isp->otg.state) { - case OTG_STATE_A_WAIT_BCON: - case OTG_STATE_A_WAIT_VRISE: - isp->otg.state = OTG_STATE_A_HOST; - pr_debug(" --> a_host\n"); - otg_ctrl = OTG_CTRL_REG; - otg_ctrl |= OTG_A_BUSREQ; - otg_ctrl &= ~(OTG_BUSDROP|OTG_B_BUSREQ) - & OTG_CTRL_MASK; - OTG_CTRL_REG = otg_ctrl; - break; - case OTG_STATE_B_WAIT_ACON: - isp->otg.state = OTG_STATE_B_HOST; - pr_debug(" --> b_host (acon)\n"); - break; - case OTG_STATE_B_HOST: - case OTG_STATE_B_IDLE: - case OTG_STATE_A_IDLE: - break; - default: - pr_debug(" host resume in %s\n", - state_name(isp)); - } - host_resume(isp); - // mdelay(10); - put_device(&isp->client.dev); - } - - if (test_and_clear_bit(WORK_TIMER, &isp->todo)) { -#ifdef VERBOSE - dump_regs(isp, "timer"); - if (!stop) - mod_timer(&isp->timer, jiffies + TIMER_JIFFIES); -#endif - put_device(&isp->client.dev); - } - - if (isp->todo) - dev_vdbg(&isp->client.dev, - "work done, todo = 0x%lx\n", - isp->todo); - if (stop) { - dev_dbg(&isp->client.dev, "stop\n"); - break; - } - } while (isp->todo); - isp->working = 0; -} - -static irqreturn_t isp1301_irq(int irq, void *isp) -{ - isp1301_defer_work(isp, WORK_UPDATE_OTG); - return IRQ_HANDLED; -} - -static void isp1301_timer(unsigned long _isp) -{ - isp1301_defer_work((void *)_isp, WORK_TIMER); -} - -/*-------------------------------------------------------------------------*/ - -static void isp1301_release(struct device *dev) -{ - struct isp1301 *isp; - - isp = container_of(dev, struct isp1301, client.dev); - - /* ugly -- i2c hijacks our memory hook to wait_for_completion() */ - if (isp->i2c_release) - isp->i2c_release(dev); - kfree (isp); -} - -static struct isp1301 *the_transceiver; - -static int isp1301_detach_client(struct i2c_client *i2c) -{ - struct isp1301 *isp; - - isp = container_of(i2c, struct isp1301, client); - - isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0); - isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0); - free_irq(isp->irq, isp); -#ifdef CONFIG_USB_OTG - otg_unbind(isp); -#endif - if (machine_is_omap_h2()) - omap_free_gpio(2); - - isp->timer.data = 0; - set_bit(WORK_STOP, &isp->todo); - del_timer_sync(&isp->timer); - flush_scheduled_work(); - - put_device(&i2c->dev); - the_transceiver = 0; - - return i2c_detach_client(i2c); -} - -/*-------------------------------------------------------------------------*/ - -/* NOTE: three modes are possible here, only one of which - * will be standards-conformant on any given system: - * - * - OTG mode (dual-role), required if there's a Mini-AB connector - * - HOST mode, for when there's one or more A (host) connectors - * - DEVICE mode, for when there's a B/Mini-B (device) connector - * - * As a rule, you won't have an isp1301 chip unless it's there to - * support the OTG mode. Other modes help testing USB controllers - * in isolation from (full) OTG support, or maybe so later board - * revisions can help to support those feature. - */ - -#ifdef CONFIG_USB_OTG - -static int isp1301_otg_enable(struct isp1301 *isp) -{ - power_up(isp); - otg_init(isp); - - /* NOTE: since we don't change this, this provides - * a few more interrupts than are strictly needed. - */ - isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING, - INTR_VBUS_VLD | INTR_SESS_VLD | INTR_ID_GND); - isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING, - INTR_VBUS_VLD | INTR_SESS_VLD | INTR_ID_GND); - - dev_info(&isp->client.dev, "ready for dual-role USB ...\n"); - - return 0; -} - -#endif - -/* add or disable the host device+driver */ -static int -isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host) -{ - struct isp1301 *isp = container_of(otg, struct isp1301, otg); - - if (!otg || isp != the_transceiver) - return -ENODEV; - - if (!host) { - OTG_IRQ_EN_REG = 0; - power_down(isp); - isp->otg.host = 0; - return 0; - } - -#ifdef CONFIG_USB_OTG - isp->otg.host = host; - dev_dbg(&isp->client.dev, "registered host\n"); - host_suspend(isp); - if (isp->otg.gadget) - return isp1301_otg_enable(isp); - return 0; - -#elif !defined(CONFIG_USB_GADGET_OMAP) - // FIXME update its refcount - isp->otg.host = host; - - power_up(isp); - - if (machine_is_omap_h2()) - isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0); - - dev_info(&isp->client.dev, "A-Host sessions ok\n"); - isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING, - INTR_ID_GND); - isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING, - INTR_ID_GND); - - /* If this has a Mini-AB connector, this mode is highly - * nonstandard ... but can be handy for testing, especially with - * the Mini-A end of an OTG cable. (Or something nonstandard - * like MiniB-to-StandardB, maybe built with a gender mender.) - */ - isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_VBUS_DRV); - - dump_regs(isp, __FUNCTION__); - - return 0; - -#else - dev_dbg(&isp->client.dev, "host sessions not allowed\n"); - return -EINVAL; -#endif - -} - -static int -isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget) -{ - struct isp1301 *isp = container_of(otg, struct isp1301, otg); - - if (!otg || isp != the_transceiver) - return -ENODEV; - - if (!gadget) { - OTG_IRQ_EN_REG = 0; - if (!isp->otg.default_a) - enable_vbus_draw(isp, 0); - usb_gadget_vbus_disconnect(isp->otg.gadget); - isp->otg.gadget = 0; - power_down(isp); - return 0; - } - -#ifdef CONFIG_USB_OTG - isp->otg.gadget = gadget; - dev_dbg(&isp->client.dev, "registered gadget\n"); - /* gadget driver may be suspended until vbus_connect () */ - if (isp->otg.host) - return isp1301_otg_enable(isp); - return 0; - -#elif !defined(CONFIG_USB_OHCI_HCD) && !defined(CONFIG_USB_OHCI_HCD_MODULE) - isp->otg.gadget = gadget; - // FIXME update its refcount - - OTG_CTRL_REG = (OTG_CTRL_REG & OTG_CTRL_MASK - & ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS)) - | OTG_ID; - power_up(isp); - isp->otg.state = OTG_STATE_B_IDLE; - - if (machine_is_omap_h2()) - isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0); - - isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING, - INTR_SESS_VLD); - isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING, - INTR_VBUS_VLD); - dev_info(&isp->client.dev, "B-Peripheral sessions ok\n"); - dump_regs(isp, __FUNCTION__); - - /* If this has a Mini-AB connector, this mode is highly - * nonstandard ... but can be handy for testing, so long - * as you don't plug a Mini-A cable into the jack. - */ - if (isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE) & INTR_VBUS_VLD) - b_peripheral(isp); - - return 0; - -#else - dev_dbg(&isp->client.dev, "peripheral sessions not allowed\n"); - return -EINVAL; -#endif -} - - -/*-------------------------------------------------------------------------*/ - -static int -isp1301_set_power(struct otg_transceiver *dev, unsigned mA) -{ - if (!the_transceiver) - return -ENODEV; - if (dev->state == OTG_STATE_B_PERIPHERAL) - enable_vbus_draw(the_transceiver, mA); - return 0; -} - -static int -isp1301_start_srp(struct otg_transceiver *dev) -{ - struct isp1301 *isp = container_of(dev, struct isp1301, otg); - u32 otg_ctrl; - - if (!dev || isp != the_transceiver - || isp->otg.state != OTG_STATE_B_IDLE) - return -ENODEV; - - otg_ctrl = OTG_CTRL_REG; - if (!(otg_ctrl & OTG_BSESSEND)) - return -EINVAL; - - otg_ctrl |= OTG_B_BUSREQ; - otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_MASK; - OTG_CTRL_REG = otg_ctrl; - isp->otg.state = OTG_STATE_B_SRP_INIT; - - pr_debug("otg: SRP, %s ... %06x\n", state_name(isp), OTG_CTRL_REG); -#ifdef CONFIG_USB_OTG - check_state(isp, __FUNCTION__); -#endif - return 0; -} - -static int -isp1301_start_hnp(struct otg_transceiver *dev) -{ -#ifdef CONFIG_USB_OTG - struct isp1301 *isp = container_of(dev, struct isp1301, otg); - - if (!dev || isp != the_transceiver) - return -ENODEV; - if (isp->otg.default_a && (isp->otg.host == NULL - || !isp->otg.host->b_hnp_enable)) - return -ENOTCONN; - if (!isp->otg.default_a && (isp->otg.gadget == NULL - || !isp->otg.gadget->b_hnp_enable)) - return -ENOTCONN; - - /* We want hardware to manage most HNP protocol timings. - * So do this part as early as possible... - */ - switch (isp->otg.state) { - case OTG_STATE_B_HOST: - isp->otg.state = OTG_STATE_B_PERIPHERAL; - /* caller will suspend next */ - break; - case OTG_STATE_A_HOST: -#if 0 - /* autoconnect mode avoids irq latency bugs */ - isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, - MC1_BDIS_ACON_EN); -#endif - /* caller must suspend then clear A_BUSREQ */ - usb_gadget_vbus_connect(isp->otg.gadget); - OTG_CTRL_REG |= OTG_A_SETB_HNPEN; - - break; - case OTG_STATE_A_PERIPHERAL: - /* initiated by B-Host suspend */ - break; - default: - return -EILSEQ; - } - pr_debug("otg: HNP %s, %06x ...\n", - state_name(isp), OTG_CTRL_REG); - check_state(isp, __FUNCTION__); - return 0; -#else - /* srp-only */ - return -EINVAL; -#endif -} - -/*-------------------------------------------------------------------------*/ - -/* no error returns, they'd just make bus scanning stop */ -static int isp1301_probe(struct i2c_adapter *bus, int address, int kind) -{ - int status; - struct isp1301 *isp; - struct i2c_client *i2c; - - if (the_transceiver) - return 0; - - isp = kzalloc(sizeof *isp, GFP_KERNEL); - if (!isp) - return 0; - - INIT_WORK(&isp->work, isp1301_work); - init_timer(&isp->timer); - isp->timer.function = isp1301_timer; - isp->timer.data = (unsigned long) isp; - - isp->irq = -1; - isp->client.addr = address; - i2c_set_clientdata(&isp->client, isp); - isp->client.adapter = bus; - isp->client.driver = &isp1301_driver; - strlcpy(isp->client.name, DRIVER_NAME, I2C_NAME_SIZE); - i2c = &isp->client; - - /* if this is a true probe, verify the chip ... */ - if (kind < 0) { - status = isp1301_get_u16(isp, ISP1301_VENDOR_ID); - if (status != I2C_VENDOR_ID_PHILIPS) { - dev_dbg(&bus->dev, "addr %d not philips id: %d\n", - address, status); - goto fail1; - } - status = isp1301_get_u16(isp, ISP1301_PRODUCT_ID); - if (status != I2C_PRODUCT_ID_PHILIPS_1301) { - dev_dbg(&bus->dev, "%d not isp1301, %d\n", - address, status); - goto fail1; - } - } - - status = i2c_attach_client(i2c); - if (status < 0) { - dev_dbg(&bus->dev, "can't attach %s to device %d, err %d\n", - DRIVER_NAME, address, status); -fail1: - kfree(isp); - return 0; - } - isp->i2c_release = i2c->dev.release; - i2c->dev.release = isp1301_release; - - /* initial development used chiprev 2.00 */ - status = i2c_smbus_read_word_data(i2c, ISP1301_BCD_DEVICE); - dev_info(&i2c->dev, "chiprev %x.%02x, driver " DRIVER_VERSION "\n", - status >> 8, status & 0xff); - - /* make like power-on reset */ - isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_MASK); - - isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_BI_DI); - isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_2, ~MC2_BI_DI); - - isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, - OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN); - isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, - ~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN)); - - isp1301_clear_bits(isp, ISP1301_INTERRUPT_LATCH, ~0); - isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0); - isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0); - -#ifdef CONFIG_USB_OTG - status = otg_bind(isp); - if (status < 0) { - dev_dbg(&i2c->dev, "can't bind OTG\n"); - goto fail2; - } -#endif - - if (machine_is_omap_h2()) { - /* full speed signaling by default */ - isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, - MC1_SPEED_REG); - isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, - MC2_SPD_SUSP_CTRL); - - /* IRQ wired at M14 */ - omap_cfg_reg(M14_1510_GPIO2); - isp->irq = OMAP_GPIO_IRQ(2); - if (gpio_request(2, "isp1301") == 0) - gpio_direction_input(2); - isp->irq_type = IRQF_TRIGGER_FALLING; - } - - isp->irq_type |= IRQF_SAMPLE_RANDOM; - status = request_irq(isp->irq, isp1301_irq, - isp->irq_type, DRIVER_NAME, isp); - if (status < 0) { - dev_dbg(&i2c->dev, "can't get IRQ %d, err %d\n", - isp->irq, status); -#ifdef CONFIG_USB_OTG -fail2: -#endif - i2c_detach_client(i2c); - goto fail1; - } - - isp->otg.dev = &isp->client.dev; - isp->otg.label = DRIVER_NAME; - - isp->otg.set_host = isp1301_set_host, - isp->otg.set_peripheral = isp1301_set_peripheral, - isp->otg.set_power = isp1301_set_power, - isp->otg.start_srp = isp1301_start_srp, - isp->otg.start_hnp = isp1301_start_hnp, - - enable_vbus_draw(isp, 0); - power_down(isp); - the_transceiver = isp; - -#ifdef CONFIG_USB_OTG - update_otg1(isp, isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE)); - update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS)); -#endif - - dump_regs(isp, __FUNCTION__); - -#ifdef VERBOSE - mod_timer(&isp->timer, jiffies + TIMER_JIFFIES); - dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES); -#endif - - status = otg_set_transceiver(&isp->otg); - if (status < 0) - dev_err(&i2c->dev, "can't register transceiver, %d\n", - status); - - return 0; -} - -static int isp1301_scan_bus(struct i2c_adapter *bus) -{ - if (!i2c_check_functionality(bus, I2C_FUNC_SMBUS_BYTE_DATA - | I2C_FUNC_SMBUS_READ_WORD_DATA)) - return -EINVAL; - return i2c_probe(bus, &addr_data, isp1301_probe); -} - -static struct i2c_driver isp1301_driver = { - .driver = { - .name = "isp1301_omap", - }, - .attach_adapter = isp1301_scan_bus, - .detach_client = isp1301_detach_client, -}; - -/*-------------------------------------------------------------------------*/ - -static int __init isp_init(void) -{ - return i2c_add_driver(&isp1301_driver); -} -module_init(isp_init); - -static void __exit isp_exit(void) -{ - if (the_transceiver) - otg_set_transceiver(0); - i2c_del_driver(&isp1301_driver); -} -module_exit(isp_exit); - diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c deleted file mode 100644 index fb7ea5637ec..00000000000 --- a/drivers/i2c/chips/max6875.c +++ /dev/null @@ -1,273 +0,0 @@ -/* - max6875.c - driver for MAX6874/MAX6875 - - Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com> - - Based on i2c/chips/eeprom.c - - The MAX6875 has a bank of registers and two banks of EEPROM. - Address ranges are defined as follows: - * 0x0000 - 0x0046 = configuration registers - * 0x8000 - 0x8046 = configuration EEPROM - * 0x8100 - 0x82FF = user EEPROM - - This driver makes the user EEPROM available for read. - - The registers & config EEPROM should be accessed via i2c-dev. - - The MAX6875 ignores the lowest address bit, so each chip responds to - two addresses - 0x50/0x51 and 0x52/0x53. - - Note that the MAX6875 uses i2c_smbus_write_byte_data() to set the read - address, so this driver is destructive if loaded for the wrong EEPROM chip. - - 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; version 2 of the License. -*/ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/i2c.h> -#include <linux/mutex.h> - -/* Do not scan - the MAX6875 access method will write to some EEPROM chips */ -static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; - -/* Insmod parameters */ -I2C_CLIENT_INSMOD_1(max6875); - -/* The MAX6875 can only read/write 16 bytes at a time */ -#define SLICE_SIZE 16 -#define SLICE_BITS 4 - -/* USER EEPROM is at addresses 0x8100 - 0x82FF */ -#define USER_EEPROM_BASE 0x8100 -#define USER_EEPROM_SIZE 0x0200 -#define USER_EEPROM_SLICES 32 - -/* MAX6875 commands */ -#define MAX6875_CMD_BLK_READ 0x84 - -/* Each client has this additional data */ -struct max6875_data { - struct i2c_client client; - struct mutex update_lock; - - u32 valid; - u8 data[USER_EEPROM_SIZE]; - unsigned long last_updated[USER_EEPROM_SLICES]; -}; - -static int max6875_attach_adapter(struct i2c_adapter *adapter); -static int max6875_detect(struct i2c_adapter *adapter, int address, int kind); -static int max6875_detach_client(struct i2c_client *client); - -/* This is the driver that will be inserted */ -static struct i2c_driver max6875_driver = { - .driver = { - .name = "max6875", - }, - .attach_adapter = max6875_attach_adapter, - .detach_client = max6875_detach_client, -}; - -static void max6875_update_slice(struct i2c_client *client, int slice) -{ - struct max6875_data *data = i2c_get_clientdata(client); - int i, j, addr; - u8 *buf; - - if (slice >= USER_EEPROM_SLICES) - return; - - mutex_lock(&data->update_lock); - - buf = &data->data[slice << SLICE_BITS]; - - if (!(data->valid & (1 << slice)) || - time_after(jiffies, data->last_updated[slice])) { - - dev_dbg(&client->dev, "Starting update of slice %u\n", slice); - - data->valid &= ~(1 << slice); - - addr = USER_EEPROM_BASE + (slice << SLICE_BITS); - - /* select the eeprom address */ - if (i2c_smbus_write_byte_data(client, addr >> 8, addr & 0xFF)) { - dev_err(&client->dev, "address set failed\n"); - goto exit_up; - } - - if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { - if (i2c_smbus_read_i2c_block_data(client, - MAX6875_CMD_BLK_READ, - SLICE_SIZE, - buf) != SLICE_SIZE) { - goto exit_up; - } - } else { - for (i = 0; i < SLICE_SIZE; i++) { - j = i2c_smbus_read_byte(client); - if (j < 0) { - goto exit_up; - } - buf[i] = j; - } - } - data->last_updated[slice] = jiffies; - data->valid |= (1 << slice); - } -exit_up: - mutex_unlock(&data->update_lock); -} - -static ssize_t max6875_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - struct i2c_client *client = kobj_to_i2c_client(kobj); - struct max6875_data *data = i2c_get_clientdata(client); - int slice, max_slice; - - if (off > USER_EEPROM_SIZE) - return 0; - - if (off + count > USER_EEPROM_SIZE) - count = USER_EEPROM_SIZE - off; - - /* refresh slices which contain requested bytes */ - max_slice = (off + count - 1) >> SLICE_BITS; - for (slice = (off >> SLICE_BITS); slice <= max_slice; slice++) - max6875_update_slice(client, slice); - - memcpy(buf, &data->data[off], count); - - return count; -} - -static struct bin_attribute user_eeprom_attr = { - .attr = { - .name = "eeprom", - .mode = S_IRUGO, - }, - .size = USER_EEPROM_SIZE, - .read = max6875_read, -}; - -static int max6875_attach_adapter(struct i2c_adapter *adapter) -{ - return i2c_probe(adapter, &addr_data, max6875_detect); -} - -/* This function is called by i2c_probe */ -static int max6875_detect(struct i2c_adapter *adapter, int address, int kind) -{ - struct i2c_client *real_client; - struct i2c_client *fake_client; - struct max6875_data *data; - int err = 0; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA - | I2C_FUNC_SMBUS_READ_BYTE)) - return 0; - - /* Only check even addresses */ - if (address & 1) - return 0; - - if (!(data = kzalloc(sizeof(struct max6875_data), GFP_KERNEL))) - return -ENOMEM; - - /* A fake client is created on the odd address */ - if (!(fake_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { - err = -ENOMEM; - goto exit_kfree1; - } - - /* Init real i2c_client */ - real_client = &data->client; - i2c_set_clientdata(real_client, data); - real_client->addr = address; - real_client->adapter = adapter; - real_client->driver = &max6875_driver; - real_client->flags = 0; - strlcpy(real_client->name, "max6875", I2C_NAME_SIZE); - mutex_init(&data->update_lock); - - /* Init fake client data */ - i2c_set_clientdata(fake_client, NULL); - fake_client->addr = address | 1; - fake_client->adapter = adapter; - fake_client->driver = &max6875_driver; - fake_client->flags = 0; - strlcpy(fake_client->name, "max6875 subclient", I2C_NAME_SIZE); - - /* Prevent 24RF08 corruption (in case of user error) */ - i2c_smbus_write_quick(real_client, 0); - - if ((err = i2c_attach_client(real_client)) != 0) - goto exit_kfree2; - - if ((err = i2c_attach_client(fake_client)) != 0) - goto exit_detach1; - - err = sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr); - if (err) - goto exit_detach2; - - return 0; - -exit_detach2: - i2c_detach_client(fake_client); -exit_detach1: - i2c_detach_client(real_client); -exit_kfree2: - kfree(fake_client); -exit_kfree1: - kfree(data); - return err; -} - -/* Will be called for both the real client and the fake client */ -static int max6875_detach_client(struct i2c_client *client) -{ - int err; - struct max6875_data *data = i2c_get_clientdata(client); - - /* data is NULL for the fake client */ - if (data) - sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr); - - err = i2c_detach_client(client); - if (err) - return err; - - if (data) /* real client */ - kfree(data); - else /* fake client */ - kfree(client); - return 0; -} - -static int __init max6875_init(void) -{ - return i2c_add_driver(&max6875_driver); -} - -static void __exit max6875_exit(void) -{ - i2c_del_driver(&max6875_driver); -} - - -MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>"); -MODULE_DESCRIPTION("MAX6875 driver"); -MODULE_LICENSE("GPL"); - -module_init(max6875_init); -module_exit(max6875_exit); diff --git a/drivers/i2c/chips/menelaus.c b/drivers/i2c/chips/menelaus.c deleted file mode 100644 index 2dea0123a95..00000000000 --- a/drivers/i2c/chips/menelaus.c +++ /dev/null @@ -1,1278 +0,0 @@ -/* - * Copyright (C) 2004 Texas Instruments, Inc. - * - * Some parts based tps65010.c: - * Copyright (C) 2004 Texas Instruments and - * Copyright (C) 2004-2005 David Brownell - * - * Some parts based on tlv320aic24.c: - * Copyright (C) by Kai Svahn <kai.svahn@nokia.com> - * - * Changes for interrupt handling and clean-up by - * Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com> - * Cleanup and generalized support for voltage setting by - * Juha Yrjola - * Added support for controlling VCORE and regulator sleep states, - * Amit Kucheria <amit.kucheria@nokia.com> - * Copyright (C) 2005, 2006 Nokia Corporation - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/module.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/sched.h> -#include <linux/mutex.h> -#include <linux/workqueue.h> -#include <linux/delay.h> -#include <linux/rtc.h> -#include <linux/bcd.h> - -#include <asm/mach-types.h> -#include <asm/mach/irq.h> - -#include <asm/arch/gpio.h> -#include <asm/arch/menelaus.h> - -#define DRIVER_NAME "menelaus" - -#define MENELAUS_I2C_ADDRESS 0x72 - -#define MENELAUS_REV 0x01 -#define MENELAUS_VCORE_CTRL1 0x02 -#define MENELAUS_VCORE_CTRL2 0x03 -#define MENELAUS_VCORE_CTRL3 0x04 -#define MENELAUS_VCORE_CTRL4 0x05 -#define MENELAUS_VCORE_CTRL5 0x06 -#define MENELAUS_DCDC_CTRL1 0x07 -#define MENELAUS_DCDC_CTRL2 0x08 -#define MENELAUS_DCDC_CTRL3 0x09 -#define MENELAUS_LDO_CTRL1 0x0A -#define MENELAUS_LDO_CTRL2 0x0B -#define MENELAUS_LDO_CTRL3 0x0C -#define MENELAUS_LDO_CTRL4 0x0D -#define MENELAUS_LDO_CTRL5 0x0E -#define MENELAUS_LDO_CTRL6 0x0F -#define MENELAUS_LDO_CTRL7 0x10 -#define MENELAUS_LDO_CTRL8 0x11 -#define MENELAUS_SLEEP_CTRL1 0x12 -#define MENELAUS_SLEEP_CTRL2 0x13 -#define MENELAUS_DEVICE_OFF 0x14 -#define MENELAUS_OSC_CTRL 0x15 -#define MENELAUS_DETECT_CTRL 0x16 -#define MENELAUS_INT_MASK1 0x17 -#define MENELAUS_INT_MASK2 0x18 -#define MENELAUS_INT_STATUS1 0x19 -#define MENELAUS_INT_STATUS2 0x1A -#define MENELAUS_INT_ACK1 0x1B -#define MENELAUS_INT_ACK2 0x1C -#define MENELAUS_GPIO_CTRL 0x1D -#define MENELAUS_GPIO_IN 0x1E -#define MENELAUS_GPIO_OUT 0x1F -#define MENELAUS_BBSMS 0x20 -#define MENELAUS_RTC_CTRL 0x21 -#define MENELAUS_RTC_UPDATE 0x22 -#define MENELAUS_RTC_SEC 0x23 -#define MENELAUS_RTC_MIN 0x24 -#define MENELAUS_RTC_HR 0x25 -#define MENELAUS_RTC_DAY 0x26 -#define MENELAUS_RTC_MON 0x27 -#define MENELAUS_RTC_YR 0x28 -#define MENELAUS_RTC_WKDAY 0x29 -#define MENELAUS_RTC_AL_SEC 0x2A -#define MENELAUS_RTC_AL_MIN 0x2B -#define MENELAUS_RTC_AL_HR 0x2C -#define MENELAUS_RTC_AL_DAY 0x2D -#define MENELAUS_RTC_AL_MON 0x2E -#define MENELAUS_RTC_AL_YR 0x2F -#define MENELAUS_RTC_COMP_MSB 0x30 -#define MENELAUS_RTC_COMP_LSB 0x31 -#define MENELAUS_S1_PULL_EN 0x32 -#define MENELAUS_S1_PULL_DIR 0x33 -#define MENELAUS_S2_PULL_EN 0x34 -#define MENELAUS_S2_PULL_DIR 0x35 -#define MENELAUS_MCT_CTRL1 0x36 -#define MENELAUS_MCT_CTRL2 0x37 -#define MENELAUS_MCT_CTRL3 0x38 -#define MENELAUS_MCT_PIN_ST 0x39 -#define MENELAUS_DEBOUNCE1 0x3A - -#define IH_MENELAUS_IRQS 12 -#define MENELAUS_MMC_S1CD_IRQ 0 /* MMC slot 1 card change */ -#define MENELAUS_MMC_S2CD_IRQ 1 /* MMC slot 2 card change */ -#define MENELAUS_MMC_S1D1_IRQ 2 /* MMC DAT1 low in slot 1 */ -#define MENELAUS_MMC_S2D1_IRQ 3 /* MMC DAT1 low in slot 2 */ -#define MENELAUS_LOWBAT_IRQ 4 /* Low battery */ -#define MENELAUS_HOTDIE_IRQ 5 /* Hot die detect */ -#define MENELAUS_UVLO_IRQ 6 /* UVLO detect */ -#define MENELAUS_TSHUT_IRQ 7 /* Thermal shutdown */ -#define MENELAUS_RTCTMR_IRQ 8 /* RTC timer */ -#define MENELAUS_RTCALM_IRQ 9 /* RTC alarm */ -#define MENELAUS_RTCERR_IRQ 10 /* RTC error */ -#define MENELAUS_PSHBTN_IRQ 11 /* Push button */ -#define MENELAUS_RESERVED12_IRQ 12 /* Reserved */ -#define MENELAUS_RESERVED13_IRQ 13 /* Reserved */ -#define MENELAUS_RESERVED14_IRQ 14 /* Reserved */ -#define MENELAUS_RESERVED15_IRQ 15 /* Reserved */ - -static void menelaus_work(struct work_struct *_menelaus); - -struct menelaus_chip { - struct mutex lock; - struct i2c_client *client; - struct work_struct work; -#ifdef CONFIG_RTC_DRV_TWL92330 - struct rtc_device *rtc; - u8 rtc_control; - unsigned uie:1; -#endif - unsigned vcore_hw_mode:1; - u8 mask1, mask2; - void (*handlers[16])(struct menelaus_chip *); - void (*mmc_callback)(void *data, u8 mask); - void *mmc_callback_data; -}; - -static struct menelaus_chip *the_menelaus; - -static int menelaus_write_reg(int reg, u8 value) -{ - int val = i2c_smbus_write_byte_data(the_menelaus->client, reg, value); - - if (val < 0) { - pr_err(DRIVER_NAME ": write error"); - return val; - } - - return 0; -} - -static int menelaus_read_reg(int reg) -{ - int val = i2c_smbus_read_byte_data(the_menelaus->client, reg); - - if (val < 0) - pr_err(DRIVER_NAME ": read error"); - - return val; -} - -static int menelaus_enable_irq(int irq) -{ - if (irq > 7) { - irq -= 8; - the_menelaus->mask2 &= ~(1 << irq); - return menelaus_write_reg(MENELAUS_INT_MASK2, - the_menelaus->mask2); - } else { - the_menelaus->mask1 &= ~(1 << irq); - return menelaus_write_reg(MENELAUS_INT_MASK1, - the_menelaus->mask1); - } -} - -static int menelaus_disable_irq(int irq) -{ - if (irq > 7) { - irq -= 8; - the_menelaus->mask2 |= (1 << irq); - return menelaus_write_reg(MENELAUS_INT_MASK2, - the_menelaus->mask2); - } else { - the_menelaus->mask1 |= (1 << irq); - return menelaus_write_reg(MENELAUS_INT_MASK1, - the_menelaus->mask1); - } -} - -static int menelaus_ack_irq(int irq) -{ - if (irq > 7) - return menelaus_write_reg(MENELAUS_INT_ACK2, 1 << (irq - 8)); - else - return menelaus_write_reg(MENELAUS_INT_ACK1, 1 << irq); -} - -/* Adds a handler for an interrupt. Does not run in interrupt context */ -static int menelaus_add_irq_work(int irq, - void (*handler)(struct menelaus_chip *)) -{ - int ret = 0; - - mutex_lock(&the_menelaus->lock); - the_menelaus->handlers[irq] = handler; - ret = menelaus_enable_irq(irq); - mutex_unlock(&the_menelaus->lock); - - return ret; -} - -/* Removes handler for an interrupt */ -static int menelaus_remove_irq_work(int irq) -{ - int ret = 0; - - mutex_lock(&the_menelaus->lock); - ret = menelaus_disable_irq(irq); - the_menelaus->handlers[irq] = NULL; - mutex_unlock(&the_menelaus->lock); - - return ret; -} - -/* - * Gets scheduled when a card detect interrupt happens. Note that in some cases - * this line is wired to card cover switch rather than the card detect switch - * in each slot. In this case the cards are not seen by menelaus. - * FIXME: Add handling for D1 too - */ -static void menelaus_mmc_cd_work(struct menelaus_chip *menelaus_hw) -{ - int reg; - unsigned char card_mask = 0; - - reg = menelaus_read_reg(MENELAUS_MCT_PIN_ST); - if (reg < 0) - return; - - if (!(reg & 0x1)) - card_mask |= (1 << 0); - - if (!(reg & 0x2)) - card_mask |= (1 << 1); - - if (menelaus_hw->mmc_callback) - menelaus_hw->mmc_callback(menelaus_hw->mmc_callback_data, - card_mask); -} - -/* - * Toggles the MMC slots between open-drain and push-pull mode. - */ -int menelaus_set_mmc_opendrain(int slot, int enable) -{ - int ret, val; - - if (slot != 1 && slot != 2) - return -EINVAL; - mutex_lock(&the_menelaus->lock); - ret = menelaus_read_reg(MENELAUS_MCT_CTRL1); - if (ret < 0) { - mutex_unlock(&the_menelaus->lock); - return ret; - } - val = ret; - if (slot == 1) { - if (enable) - val |= 1 << 2; - else - val &= ~(1 << 2); - } else { - if (enable) - val |= 1 << 3; - else - val &= ~(1 << 3); - } - ret = menelaus_write_reg(MENELAUS_MCT_CTRL1, val); - mutex_unlock(&the_menelaus->lock); - - return ret; -} -EXPORT_SYMBOL(menelaus_set_mmc_opendrain); - -int menelaus_set_slot_sel(int enable) -{ - int ret; - - mutex_lock(&the_menelaus->lock); - ret = menelaus_read_reg(MENELAUS_GPIO_CTRL); - if (ret < 0) - goto out; - ret |= 0x02; - if (enable) - ret |= 1 << 5; - else - ret &= ~(1 << 5); - ret = menelaus_write_reg(MENELAUS_GPIO_CTRL, ret); -out: - mutex_unlock(&the_menelaus->lock); - return ret; -} -EXPORT_SYMBOL(menelaus_set_slot_sel); - -int menelaus_set_mmc_slot(int slot, int enable, int power, int cd_en) -{ - int ret, val; - - if (slot != 1 && slot != 2) - return -EINVAL; - if (power >= 3) - return -EINVAL; - - mutex_lock(&the_menelaus->lock); - - ret = menelaus_read_reg(MENELAUS_MCT_CTRL2); - if (ret < 0) - goto out; - val = ret; - if (slot == 1) { - if (cd_en) - val |= (1 << 4) | (1 << 6); - else - val &= ~((1 << 4) | (1 << 6)); - } else { - if (cd_en) - val |= (1 << 5) | (1 << 7); - else - val &= ~((1 << 5) | (1 << 7)); - } - ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, val); - if (ret < 0) - goto out; - - ret = menelaus_read_reg(MENELAUS_MCT_CTRL3); - if (ret < 0) - goto out; - val = ret; - if (slot == 1) { - if (enable) - val |= 1 << 0; - else - val &= ~(1 << 0); - } else { - int b; - - if (enable) - ret |= 1 << 1; - else - ret &= ~(1 << 1); - b = menelaus_read_reg(MENELAUS_MCT_CTRL2); - b &= ~0x03; - b |= power; - ret = menelaus_write_reg(MENELAUS_MCT_CTRL2, b); - if (ret < 0) - goto out; - } - /* Disable autonomous shutdown */ - val &= ~(0x03 << 2); - ret = menelaus_write_reg(MENELAUS_MCT_CTRL3, val); -out: - mutex_unlock(&the_menelaus->lock); - return ret; -} -EXPORT_SYMBOL(menelaus_set_mmc_slot); - -int menelaus_register_mmc_callback(void (*callback)(void *data, u8 card_mask), - void *data) -{ - int ret = 0; - - the_menelaus->mmc_callback_data = data; - the_menelaus->mmc_callback = callback; - ret = menelaus_add_irq_work(MENELAUS_MMC_S1CD_IRQ, - menelaus_mmc_cd_work); - if (ret < 0) - return ret; - ret = menelaus_add_irq_work(MENELAUS_MMC_S2CD_IRQ, - menelaus_mmc_cd_work); - if (ret < 0) - return ret; - ret = menelaus_add_irq_work(MENELAUS_MMC_S1D1_IRQ, - menelaus_mmc_cd_work); - if (ret < 0) - return ret; - ret = menelaus_add_irq_work(MENELAUS_MMC_S2D1_IRQ, - menelaus_mmc_cd_work); - - return ret; -} -EXPORT_SYMBOL(menelaus_register_mmc_callback); - -void menelaus_unregister_mmc_callback(void) -{ - menelaus_remove_irq_work(MENELAUS_MMC_S1CD_IRQ); - menelaus_remove_irq_work(MENELAUS_MMC_S2CD_IRQ); - menelaus_remove_irq_work(MENELAUS_MMC_S1D1_IRQ); - menelaus_remove_irq_work(MENELAUS_MMC_S2D1_IRQ); - - the_menelaus->mmc_callback = NULL; - the_menelaus->mmc_callback_data = 0; -} -EXPORT_SYMBOL(menelaus_unregister_mmc_callback); - -struct menelaus_vtg { - const char *name; - u8 vtg_reg; - u8 vtg_shift; - u8 vtg_bits; - u8 mode_reg; -}; - -struct menelaus_vtg_value { - u16 vtg; - u16 val; -}; - -static int menelaus_set_voltage(const struct menelaus_vtg *vtg, int mV, - int vtg_val, int mode) -{ - int val, ret; - struct i2c_client *c = the_menelaus->client; - - mutex_lock(&the_menelaus->lock); - if (vtg == 0) - goto set_voltage; - - ret = menelaus_read_reg(vtg->vtg_reg); - if (ret < 0) - goto out; - val = ret & ~(((1 << vtg->vtg_bits) - 1) << vtg->vtg_shift); - val |= vtg_val << vtg->vtg_shift; - - dev_dbg(&c->dev, "Setting voltage '%s'" - "to %d mV (reg 0x%02x, val 0x%02x)\n", - vtg->name, mV, vtg->vtg_reg, val); - - ret = menelaus_write_reg(vtg->vtg_reg, val); - if (ret < 0) - goto out; -set_voltage: - ret = menelaus_write_reg(vtg->mode_reg, mode); -out: - mutex_unlock(&the_menelaus->lock); - if (ret == 0) { - /* Wait for voltage to stabilize */ - msleep(1); - } - return ret; -} - -static int menelaus_get_vtg_value(int vtg, const struct menelaus_vtg_value *tbl, - int n) -{ - int i; - - for (i = 0; i < n; i++, tbl++) - if (tbl->vtg == vtg) - return tbl->val; - return -EINVAL; -} - -/* - * Vcore can be programmed in two ways: - * SW-controlled: Required voltage is programmed into VCORE_CTRL1 - * HW-controlled: Required range (roof-floor) is programmed into VCORE_CTRL3 - * and VCORE_CTRL4 - * - * Call correct 'set' function accordingly - */ - -static const struct menelaus_vtg_value vcore_values[] = { - { 1000, 0 }, - { 1025, 1 }, - { 1050, 2 }, - { 1075, 3 }, - { 1100, 4 }, - { 1125, 5 }, - { 1150, 6 }, - { 1175, 7 }, - { 1200, 8 }, - { 1225, 9 }, - { 1250, 10 }, - { 1275, 11 }, - { 1300, 12 }, - { 1325, 13 }, - { 1350, 14 }, - { 1375, 15 }, - { 1400, 16 }, - { 1425, 17 }, - { 1450, 18 }, -}; - -int menelaus_set_vcore_sw(unsigned int mV) -{ - int val, ret; - struct i2c_client *c = the_menelaus->client; - - val = menelaus_get_vtg_value(mV, vcore_values, - ARRAY_SIZE(vcore_values)); - if (val < 0) - return -EINVAL; - - dev_dbg(&c->dev, "Setting VCORE to %d mV (val 0x%02x)\n", mV, val); - - /* Set SW mode and the voltage in one go. */ - mutex_lock(&the_menelaus->lock); - ret = menelaus_write_reg(MENELAUS_VCORE_CTRL1, val); - if (ret == 0) - the_menelaus->vcore_hw_mode = 0; - mutex_unlock(&the_menelaus->lock); - msleep(1); - - return ret; -} - -int menelaus_set_vcore_hw(unsigned int roof_mV, unsigned int floor_mV) -{ - int fval, rval, val, ret; - struct i2c_client *c = the_menelaus->client; - - rval = menelaus_get_vtg_value(roof_mV, vcore_values, - ARRAY_SIZE(vcore_values)); - if (rval < 0) - return -EINVAL; - fval = menelaus_get_vtg_value(floor_mV, vcore_values, - ARRAY_SIZE(vcore_values)); - if (fval < 0) - return -EINVAL; - - dev_dbg(&c->dev, "Setting VCORE FLOOR to %d mV and ROOF to %d mV\n", - floor_mV, roof_mV); - - mutex_lock(&the_menelaus->lock); - ret = menelaus_write_reg(MENELAUS_VCORE_CTRL3, fval); - if (ret < 0) - goto out; - ret = menelaus_write_reg(MENELAUS_VCORE_CTRL4, rval); - if (ret < 0) - goto out; - if (!the_menelaus->vcore_hw_mode) { - val = menelaus_read_reg(MENELAUS_VCORE_CTRL1); - /* HW mode, turn OFF byte comparator */ - val |= ((1 << 7) | (1 << 5)); - ret = menelaus_write_reg(MENELAUS_VCORE_CTRL1, val); - the_menelaus->vcore_hw_mode = 1; - } - msleep(1); -out: - mutex_unlock(&the_menelaus->lock); - return ret; -} - -static const struct menelaus_vtg vmem_vtg = { - .name = "VMEM", - .vtg_reg = MENELAUS_LDO_CTRL1, - .vtg_shift = 0, - .vtg_bits = 2, - .mode_reg = MENELAUS_LDO_CTRL3, -}; - -static const struct menelaus_vtg_value vmem_values[] = { - { 1500, 0 }, - { 1800, 1 }, - { 1900, 2 }, - { 2500, 3 }, -}; - -int menelaus_set_vmem(unsigned int mV) -{ - int val; - - if (mV == 0) - return menelaus_set_voltage(&vmem_vtg, 0, 0, 0); - - val = menelaus_get_vtg_value(mV, vmem_values, ARRAY_SIZE(vmem_values)); - if (val < 0) - return -EINVAL; - return menelaus_set_voltage(&vmem_vtg, mV, val, 0x02); -} -EXPORT_SYMBOL(menelaus_set_vmem); - -static const struct menelaus_vtg vio_vtg = { - .name = "VIO", - .vtg_reg = MENELAUS_LDO_CTRL1, - .vtg_shift = 2, - .vtg_bits = 2, - .mode_reg = MENELAUS_LDO_CTRL4, -}; - -static const struct menelaus_vtg_value vio_values[] = { - { 1500, 0 }, - { 1800, 1 }, - { 2500, 2 }, - { 2800, 3 }, -}; - -int menelaus_set_vio(unsigned int mV) -{ - int val; - - if (mV == 0) - return menelaus_set_voltage(&vio_vtg, 0, 0, 0); - - val = menelaus_get_vtg_value(mV, vio_values, ARRAY_SIZE(vio_values)); - if (val < 0) - return -EINVAL; - return menelaus_set_voltage(&vio_vtg, mV, val, 0x02); -} -EXPORT_SYMBOL(menelaus_set_vio); - -static const struct menelaus_vtg_value vdcdc_values[] = { - { 1500, 0 }, - { 1800, 1 }, - { 2000, 2 }, - { 2200, 3 }, - { 2400, 4 }, - { 2800, 5 }, - { 3000, 6 }, - { 3300, 7 }, -}; - -static const struct menelaus_vtg vdcdc2_vtg = { - .name = "VDCDC2", - .vtg_reg = MENELAUS_DCDC_CTRL1, - .vtg_shift = 0, - .vtg_bits = 3, - .mode_reg = MENELAUS_DCDC_CTRL2, -}; - -static const struct menelaus_vtg vdcdc3_vtg = { - .name = "VDCDC3", - .vtg_reg = MENELAUS_DCDC_CTRL1, - .vtg_shift = 3, - .vtg_bits = 3, - .mode_reg = MENELAUS_DCDC_CTRL3, -}; - -int menelaus_set_vdcdc(int dcdc, unsigned int mV) -{ - const struct menelaus_vtg *vtg; - int val; - - if (dcdc != 2 && dcdc != 3) - return -EINVAL; - if (dcdc == 2) - vtg = &vdcdc2_vtg; - else - vtg = &vdcdc3_vtg; - - if (mV == 0) - return menelaus_set_voltage(vtg, 0, 0, 0); - - val = menelaus_get_vtg_value(mV, vdcdc_values, - ARRAY_SIZE(vdcdc_values)); - if (val < 0) - return -EINVAL; - return menelaus_set_voltage(vtg, mV, val, 0x03); -} - -static const struct menelaus_vtg_value vmmc_values[] = { - { 1850, 0 }, - { 2800, 1 }, - { 3000, 2 }, - { 3100, 3 }, -}; - -static const struct menelaus_vtg vmmc_vtg = { - .name = "VMMC", - .vtg_reg = MENELAUS_LDO_CTRL1, - .vtg_shift = 6, - .vtg_bits = 2, - .mode_reg = MENELAUS_LDO_CTRL7, -}; - -int menelaus_set_vmmc(unsigned int mV) -{ - int val; - - if (mV == 0) - return menelaus_set_voltage(&vmmc_vtg, 0, 0, 0); - - val = menelaus_get_vtg_value(mV, vmmc_values, ARRAY_SIZE(vmmc_values)); - if (val < 0) - return -EINVAL; - return menelaus_set_voltage(&vmmc_vtg, mV, val, 0x02); -} -EXPORT_SYMBOL(menelaus_set_vmmc); - - -static const struct menelaus_vtg_value vaux_values[] = { - { 1500, 0 }, - { 1800, 1 }, - { 2500, 2 }, - { 2800, 3 }, -}; - -static const struct menelaus_vtg vaux_vtg = { - .name = "VAUX", - .vtg_reg = MENELAUS_LDO_CTRL1, - .vtg_shift = 4, - .vtg_bits = 2, - .mode_reg = MENELAUS_LDO_CTRL6, -}; - -int menelaus_set_vaux(unsigned int mV) -{ - int val; - - if (mV == 0) - return menelaus_set_voltage(&vaux_vtg, 0, 0, 0); - - val = menelaus_get_vtg_value(mV, vaux_values, ARRAY_SIZE(vaux_values)); - if (val < 0) - return -EINVAL; - return menelaus_set_voltage(&vaux_vtg, mV, val, 0x02); -} -EXPORT_SYMBOL(menelaus_set_vaux); - -int menelaus_get_slot_pin_states(void) -{ - return menelaus_read_reg(MENELAUS_MCT_PIN_ST); -} -EXPORT_SYMBOL(menelaus_get_slot_pin_states); - -int menelaus_set_regulator_sleep(int enable, u32 val) -{ - int t, ret; - struct i2c_client *c = the_menelaus->client; - - mutex_lock(&the_menelaus->lock); - ret = menelaus_write_reg(MENELAUS_SLEEP_CTRL2, val); - if (ret < 0) - goto out; - - dev_dbg(&c->dev, "regulator sleep configuration: %02x\n", val); - - ret = menelaus_read_reg(MENELAUS_GPIO_CTRL); - if (ret < 0) - goto out; - t = ((1 << 6) | 0x04); - if (enable) - ret |= t; - else - ret &= ~t; - ret = menelaus_write_reg(MENELAUS_GPIO_CTRL, ret); -out: - mutex_unlock(&the_menelaus->lock); - return ret; -} - -/*-----------------------------------------------------------------------*/ - -/* Handles Menelaus interrupts. Does not run in interrupt context */ -static void menelaus_work(struct work_struct *_menelaus) -{ - struct menelaus_chip *menelaus = - container_of(_menelaus, struct menelaus_chip, work); - void (*handler)(struct menelaus_chip *menelaus); - - while (1) { - unsigned isr; - - isr = (menelaus_read_reg(MENELAUS_INT_STATUS2) - & ~menelaus->mask2) << 8; - isr |= menelaus_read_reg(MENELAUS_INT_STATUS1) - & ~menelaus->mask1; - if (!isr) - break; - - while (isr) { - int irq = fls(isr) - 1; - isr &= ~(1 << irq); - - mutex_lock(&menelaus->lock); - menelaus_disable_irq(irq); - menelaus_ack_irq(irq); - handler = menelaus->handlers[irq]; - if (handler) - handler(menelaus); - menelaus_enable_irq(irq); - mutex_unlock(&menelaus->lock); - } - } - enable_irq(menelaus->client->irq); -} - -/* - * We cannot use I2C in interrupt context, so we just schedule work. - */ -static irqreturn_t menelaus_irq(int irq, void *_menelaus) -{ - struct menelaus_chip *menelaus = _menelaus; - - disable_irq_nosync(irq); - (void)schedule_work(&menelaus->work); - - return IRQ_HANDLED; -} - -/*-----------------------------------------------------------------------*/ - -/* - * The RTC needs to be set once, then it runs on backup battery power. - * It supports alarms, including system wake alarms (from some modes); - * and 1/second IRQs if requested. - */ -#ifdef CONFIG_RTC_DRV_TWL92330 - -#define RTC_CTRL_RTC_EN (1 << 0) -#define RTC_CTRL_AL_EN (1 << 1) -#define RTC_CTRL_MODE12 (1 << 2) -#define RTC_CTRL_EVERY_MASK (3 << 3) -#define RTC_CTRL_EVERY_SEC (0 << 3) -#define RTC_CTRL_EVERY_MIN (1 << 3) -#define RTC_CTRL_EVERY_HR (2 << 3) -#define RTC_CTRL_EVERY_DAY (3 << 3) - -#define RTC_UPDATE_EVERY 0x08 - -#define RTC_HR_PM (1 << 7) - -static void menelaus_to_time(char *regs, struct rtc_time *t) -{ - t->tm_sec = BCD2BIN(regs[0]); - t->tm_min = BCD2BIN(regs[1]); - if (the_menelaus->rtc_control & RTC_CTRL_MODE12) { - t->tm_hour = BCD2BIN(regs[2] & 0x1f) - 1; - if (regs[2] & RTC_HR_PM) - t->tm_hour += 12; - } else - t->tm_hour = BCD2BIN(regs[2] & 0x3f); - t->tm_mday = BCD2BIN(regs[3]); - t->tm_mon = BCD2BIN(regs[4]) - 1; - t->tm_year = BCD2BIN(regs[5]) + 100; -} - -static int time_to_menelaus(struct rtc_time *t, int regnum) -{ - int hour, status; - - status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_sec)); - if (status < 0) - goto fail; - - status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_min)); - if (status < 0) - goto fail; - - if (the_menelaus->rtc_control & RTC_CTRL_MODE12) { - hour = t->tm_hour + 1; - if (hour > 12) - hour = RTC_HR_PM | BIN2BCD(hour - 12); - else - hour = BIN2BCD(hour); - } else - hour = BIN2BCD(t->tm_hour); - status = menelaus_write_reg(regnum++, hour); - if (status < 0) - goto fail; - - status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_mday)); - if (status < 0) - goto fail; - - status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_mon + 1)); - if (status < 0) - goto fail; - - status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_year - 100)); - if (status < 0) - goto fail; - - return 0; -fail: - dev_err(&the_menelaus->client->dev, "rtc write reg %02x, err %d\n", - --regnum, status); - return status; -} - -static int menelaus_read_time(struct device *dev, struct rtc_time *t) -{ - struct i2c_msg msg[2]; - char regs[7]; - int status; - - /* block read date and time registers */ - regs[0] = MENELAUS_RTC_SEC; - - msg[0].addr = MENELAUS_I2C_ADDRESS; - msg[0].flags = 0; - msg[0].len = 1; - msg[0].buf = regs; - - msg[1].addr = MENELAUS_I2C_ADDRESS; - msg[1].flags = I2C_M_RD; - msg[1].len = sizeof(regs); - msg[1].buf = regs; - - status = i2c_transfer(the_menelaus->client->adapter, msg, 2); - if (status != 2) { - dev_err(dev, "%s error %d\n", "read", status); - return -EIO; - } - - menelaus_to_time(regs, t); - t->tm_wday = BCD2BIN(regs[6]); - - return 0; -} - -static int menelaus_set_time(struct device *dev, struct rtc_time *t) -{ - int status; - - /* write date and time registers */ - status = time_to_menelaus(t, MENELAUS_RTC_SEC); - if (status < 0) - return status; - status = menelaus_write_reg(MENELAUS_RTC_WKDAY, BIN2BCD(t->tm_wday)); - if (status < 0) { - dev_err(&the_menelaus->client->dev, "rtc write reg %02x " - "err %d\n", MENELAUS_RTC_WKDAY, status); - return status; - } - - /* now commit the write */ - status = menelaus_write_reg(MENELAUS_RTC_UPDATE, RTC_UPDATE_EVERY); - if (status < 0) - dev_err(&the_menelaus->client->dev, "rtc commit time, err %d\n", - status); - - return 0; -} - -static int menelaus_read_alarm(struct device *dev, struct rtc_wkalrm *w) -{ - struct i2c_msg msg[2]; - char regs[6]; - int status; - - /* block read alarm registers */ - regs[0] = MENELAUS_RTC_AL_SEC; - - msg[0].addr = MENELAUS_I2C_ADDRESS; - msg[0].flags = 0; - msg[0].len = 1; - msg[0].buf = regs; - - msg[1].addr = MENELAUS_I2C_ADDRESS; - msg[1].flags = I2C_M_RD; - msg[1].len = sizeof(regs); - msg[1].buf = regs; - - status = i2c_transfer(the_menelaus->client->adapter, msg, 2); - if (status != 2) { - dev_err(dev, "%s error %d\n", "alarm read", status); - return -EIO; - } - - menelaus_to_time(regs, &w->time); - - w->enabled = !!(the_menelaus->rtc_control & RTC_CTRL_AL_EN); - - /* NOTE we *could* check if actually pending... */ - w->pending = 0; - - return 0; -} - -static int menelaus_set_alarm(struct device *dev, struct rtc_wkalrm *w) -{ - int status; - - if (the_menelaus->client->irq <= 0 && w->enabled) - return -ENODEV; - - /* clear previous alarm enable */ - if (the_menelaus->rtc_control & RTC_CTRL_AL_EN) { - the_menelaus->rtc_control &= ~RTC_CTRL_AL_EN; - status = menelaus_write_reg(MENELAUS_RTC_CTRL, - the_menelaus->rtc_control); - if (status < 0) - return status; - } - - /* write alarm registers */ - status = time_to_menelaus(&w->time, MENELAUS_RTC_AL_SEC); - if (status < 0) - return status; - - /* enable alarm if requested */ - if (w->enabled) { - the_menelaus->rtc_control |= RTC_CTRL_AL_EN; - status = menelaus_write_reg(MENELAUS_RTC_CTRL, - the_menelaus->rtc_control); - } - - return status; -} - -#ifdef CONFIG_RTC_INTF_DEV - -static void menelaus_rtc_update_work(struct menelaus_chip *m) -{ - /* report 1/sec update */ - local_irq_disable(); - rtc_update_irq(m->rtc, 1, RTC_IRQF | RTC_UF); - local_irq_enable(); -} - -static int menelaus_ioctl(struct device *dev, unsigned cmd, unsigned long arg) -{ - int status; - - if (the_menelaus->client->irq <= 0) - return -ENOIOCTLCMD; - - switch (cmd) { - /* alarm IRQ */ - case RTC_AIE_ON: - if (the_menelaus->rtc_control & RTC_CTRL_AL_EN) - return 0; - the_menelaus->rtc_control |= RTC_CTRL_AL_EN; - break; - case RTC_AIE_OFF: - if (!(the_menelaus->rtc_control & RTC_CTRL_AL_EN)) - return 0; - the_menelaus->rtc_control &= ~RTC_CTRL_AL_EN; - break; - /* 1/second "update" IRQ */ - case RTC_UIE_ON: - if (the_menelaus->uie) - return 0; - status = menelaus_remove_irq_work(MENELAUS_RTCTMR_IRQ); - status = menelaus_add_irq_work(MENELAUS_RTCTMR_IRQ, - menelaus_rtc_update_work); - if (status == 0) - the_menelaus->uie = 1; - return status; - case RTC_UIE_OFF: - if (!the_menelaus->uie) - return 0; - status = menelaus_remove_irq_work(MENELAUS_RTCTMR_IRQ); - if (status == 0) - the_menelaus->uie = 0; - return status; - default: - return -ENOIOCTLCMD; - } - return menelaus_write_reg(MENELAUS_RTC_CTRL, the_menelaus->rtc_control); -} - -#else -#define menelaus_ioctl NULL -#endif - -/* REVISIT no compensation register support ... */ - -static const struct rtc_class_ops menelaus_rtc_ops = { - .ioctl = menelaus_ioctl, - .read_time = menelaus_read_time, - .set_time = menelaus_set_time, - .read_alarm = menelaus_read_alarm, - .set_alarm = menelaus_set_alarm, -}; - -static void menelaus_rtc_alarm_work(struct menelaus_chip *m) -{ - /* report alarm */ - local_irq_disable(); - rtc_update_irq(m->rtc, 1, RTC_IRQF | RTC_AF); - local_irq_enable(); - - /* then disable it; alarms are oneshot */ - the_menelaus->rtc_control &= ~RTC_CTRL_AL_EN; - menelaus_write_reg(MENELAUS_RTC_CTRL, the_menelaus->rtc_control); -} - -static inline void menelaus_rtc_init(struct menelaus_chip *m) -{ - int alarm = (m->client->irq > 0); - - /* assume 32KDETEN pin is pulled high */ - if (!(menelaus_read_reg(MENELAUS_OSC_CTRL) & 0x80)) { - dev_dbg(&m->client->dev, "no 32k oscillator\n"); - return; - } - - /* support RTC alarm; it can issue wakeups */ - if (alarm) { - if (menelaus_add_irq_work(MENELAUS_RTCALM_IRQ, - menelaus_rtc_alarm_work) < 0) { - dev_err(&m->client->dev, "can't handle RTC alarm\n"); - return; - } - device_init_wakeup(&m->client->dev, 1); - } - - /* be sure RTC is enabled; allow 1/sec irqs; leave 12hr mode alone */ - m->rtc_control = menelaus_read_reg(MENELAUS_RTC_CTRL); - if (!(m->rtc_control & RTC_CTRL_RTC_EN) - || (m->rtc_control & RTC_CTRL_AL_EN) - || (m->rtc_control & RTC_CTRL_EVERY_MASK)) { - if (!(m->rtc_control & RTC_CTRL_RTC_EN)) { - dev_warn(&m->client->dev, "rtc clock needs setting\n"); - m->rtc_control |= RTC_CTRL_RTC_EN; - } - m->rtc_control &= ~RTC_CTRL_EVERY_MASK; - m->rtc_control &= ~RTC_CTRL_AL_EN; - menelaus_write_reg(MENELAUS_RTC_CTRL, m->rtc_control); - } - - m->rtc = rtc_device_register(DRIVER_NAME, - &m->client->dev, - &menelaus_rtc_ops, THIS_MODULE); - if (IS_ERR(m->rtc)) { - if (alarm) { - menelaus_remove_irq_work(MENELAUS_RTCALM_IRQ); - device_init_wakeup(&m->client->dev, 0); - } - dev_err(&m->client->dev, "can't register RTC: %d\n", - (int) PTR_ERR(m->rtc)); - the_menelaus->rtc = NULL; - } -} - -#else - -static inline void menelaus_rtc_init(struct menelaus_chip *m) -{ - /* nothing */ -} - -#endif - -/*-----------------------------------------------------------------------*/ - -static struct i2c_driver menelaus_i2c_driver; - -static int menelaus_probe(struct i2c_client *client) -{ - struct menelaus_chip *menelaus; - int rev = 0, val; - int err = 0; - struct menelaus_platform_data *menelaus_pdata = - client->dev.platform_data; - - if (the_menelaus) { - dev_dbg(&client->dev, "only one %s for now\n", - DRIVER_NAME); - return -ENODEV; - } - - menelaus = kzalloc(sizeof *menelaus, GFP_KERNEL); - if (!menelaus) - return -ENOMEM; - - i2c_set_clientdata(client, menelaus); - - the_menelaus = menelaus; - menelaus->client = client; - - /* If a true probe check the device */ - rev = menelaus_read_reg(MENELAUS_REV); - if (rev < 0) { - pr_err(DRIVER_NAME ": device not found"); - err = -ENODEV; - goto fail1; - } - - /* Ack and disable all Menelaus interrupts */ - menelaus_write_reg(MENELAUS_INT_ACK1, 0xff); - menelaus_write_reg(MENELAUS_INT_ACK2, 0xff); - menelaus_write_reg(MENELAUS_INT_MASK1, 0xff); - menelaus_write_reg(MENELAUS_INT_MASK2, 0xff); - menelaus->mask1 = 0xff; - menelaus->mask2 = 0xff; - - /* Set output buffer strengths */ - menelaus_write_reg(MENELAUS_MCT_CTRL1, 0x73); - - if (client->irq > 0) { - err = request_irq(client->irq, menelaus_irq, IRQF_DISABLED, - DRIVER_NAME, menelaus); - if (err) { - dev_dbg(&client->dev, "can't get IRQ %d, err %d\n", - client->irq, err); - goto fail1; - } - } - - mutex_init(&menelaus->lock); - INIT_WORK(&menelaus->work, menelaus_work); - - pr_info("Menelaus rev %d.%d\n", rev >> 4, rev & 0x0f); - - val = menelaus_read_reg(MENELAUS_VCORE_CTRL1); - if (val < 0) - goto fail2; - if (val & (1 << 7)) - menelaus->vcore_hw_mode = 1; - else - menelaus->vcore_hw_mode = 0; - - if (menelaus_pdata != NULL && menelaus_pdata->late_init != NULL) { - err = menelaus_pdata->late_init(&client->dev); - if (err < 0) - goto fail2; - } - - menelaus_rtc_init(menelaus); - - return 0; -fail2: - free_irq(client->irq, menelaus); - flush_scheduled_work(); -fail1: - kfree(menelaus); - return err; -} - -static int __exit menelaus_remove(struct i2c_client *client) -{ - struct menelaus_chip *menelaus = i2c_get_clientdata(client); - - free_irq(client->irq, menelaus); - kfree(menelaus); - i2c_set_clientdata(client, NULL); - the_menelaus = NULL; - return 0; -} - -static struct i2c_driver menelaus_i2c_driver = { - .driver = { - .name = DRIVER_NAME, - }, - .probe = menelaus_probe, - .remove = __exit_p(menelaus_remove), -}; - -static int __init menelaus_init(void) -{ - int res; - - res = i2c_add_driver(&menelaus_i2c_driver); - if (res < 0) { - pr_err(DRIVER_NAME ": driver registration failed\n"); - return res; - } - - return 0; -} - -static void __exit menelaus_exit(void) -{ - i2c_del_driver(&menelaus_i2c_driver); - - /* FIXME: Shutdown menelaus parts that can be shut down */ -} - -MODULE_AUTHOR("Texas Instruments, Inc. (and others)"); -MODULE_DESCRIPTION("I2C interface for Menelaus."); -MODULE_LICENSE("GPL"); - -module_init(menelaus_init); -module_exit(menelaus_exit); diff --git a/drivers/i2c/chips/pca9539.c b/drivers/i2c/chips/pca9539.c deleted file mode 100644 index f43c4e79b55..00000000000 --- a/drivers/i2c/chips/pca9539.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - pca9539.c - 16-bit I/O port with interrupt and reset - - Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com> - - 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; version 2 of the License. -*/ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/i2c.h> -#include <linux/hwmon-sysfs.h> - -/* Addresses to scan */ -static unsigned short normal_i2c[] = {0x74, 0x75, 0x76, 0x77, I2C_CLIENT_END}; - -/* Insmod parameters */ -I2C_CLIENT_INSMOD_1(pca9539); - -enum pca9539_cmd -{ - PCA9539_INPUT_0 = 0, - PCA9539_INPUT_1 = 1, - PCA9539_OUTPUT_0 = 2, - PCA9539_OUTPUT_1 = 3, - PCA9539_INVERT_0 = 4, - PCA9539_INVERT_1 = 5, - PCA9539_DIRECTION_0 = 6, - PCA9539_DIRECTION_1 = 7, -}; - -static int pca9539_attach_adapter(struct i2c_adapter *adapter); -static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind); -static int pca9539_detach_client(struct i2c_client *client); - -/* This is the driver that will be inserted */ -static struct i2c_driver pca9539_driver = { - .driver = { - .name = "pca9539", - }, - .attach_adapter = pca9539_attach_adapter, - .detach_client = pca9539_detach_client, -}; - -struct pca9539_data { - struct i2c_client client; -}; - -/* following are the sysfs callback functions */ -static ssize_t pca9539_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *psa = to_sensor_dev_attr(attr); - struct i2c_client *client = to_i2c_client(dev); - return sprintf(buf, "%d\n", i2c_smbus_read_byte_data(client, - psa->index)); -} - -static ssize_t pca9539_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *psa = to_sensor_dev_attr(attr); - struct i2c_client *client = to_i2c_client(dev); - unsigned long val = simple_strtoul(buf, NULL, 0); - if (val > 0xff) - return -EINVAL; - i2c_smbus_write_byte_data(client, psa->index, val); - return count; -} - -/* Define the device attributes */ - -#define PCA9539_ENTRY_RO(name, cmd_idx) \ - static SENSOR_DEVICE_ATTR(name, S_IRUGO, pca9539_show, NULL, cmd_idx) - -#define PCA9539_ENTRY_RW(name, cmd_idx) \ - static SENSOR_DEVICE_ATTR(name, S_IRUGO | S_IWUSR, pca9539_show, \ - pca9539_store, cmd_idx) - -PCA9539_ENTRY_RO(input0, PCA9539_INPUT_0); -PCA9539_ENTRY_RO(input1, PCA9539_INPUT_1); -PCA9539_ENTRY_RW(output0, PCA9539_OUTPUT_0); -PCA9539_ENTRY_RW(output1, PCA9539_OUTPUT_1); -PCA9539_ENTRY_RW(invert0, PCA9539_INVERT_0); -PCA9539_ENTRY_RW(invert1, PCA9539_INVERT_1); -PCA9539_ENTRY_RW(direction0, PCA9539_DIRECTION_0); -PCA9539_ENTRY_RW(direction1, PCA9539_DIRECTION_1); - -static struct attribute *pca9539_attributes[] = { - &sensor_dev_attr_input0.dev_attr.attr, - &sensor_dev_attr_input1.dev_attr.attr, - &sensor_dev_attr_output0.dev_attr.attr, - &sensor_dev_attr_output1.dev_attr.attr, - &sensor_dev_attr_invert0.dev_attr.attr, - &sensor_dev_attr_invert1.dev_attr.attr, - &sensor_dev_attr_direction0.dev_attr.attr, - &sensor_dev_attr_direction1.dev_attr.attr, - NULL -}; - -static struct attribute_group pca9539_defattr_group = { - .attrs = pca9539_attributes, -}; - -static int pca9539_attach_adapter(struct i2c_adapter *adapter) -{ - return i2c_probe(adapter, &addr_data, pca9539_detect); -} - -/* This function is called by i2c_probe */ -static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind) -{ - struct i2c_client *new_client; - struct pca9539_data *data; - int err = 0; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - goto exit; - - /* OK. For now, we presume we have a valid client. We now create the - client structure, even though we cannot fill it completely yet. */ - if (!(data = kzalloc(sizeof(struct pca9539_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &pca9539_driver; - new_client->flags = 0; - - if (kind < 0) { - /* Detection: the pca9539 only has 8 registers (0-7). - A read of 7 should succeed, but a read of 8 should fail. */ - if ((i2c_smbus_read_byte_data(new_client, 7) < 0) || - (i2c_smbus_read_byte_data(new_client, 8) >= 0)) - goto exit_kfree; - } - - strlcpy(new_client->name, "pca9539", I2C_NAME_SIZE); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto exit_kfree; - - /* Register sysfs hooks */ - err = sysfs_create_group(&new_client->dev.kobj, - &pca9539_defattr_group); - if (err) - goto exit_detach; - - return 0; - -exit_detach: - i2c_detach_client(new_client); -exit_kfree: - kfree(data); -exit: - return err; -} - -static int pca9539_detach_client(struct i2c_client *client) -{ - int err; - - sysfs_remove_group(&client->dev.kobj, &pca9539_defattr_group); - - if ((err = i2c_detach_client(client))) - return err; - - kfree(i2c_get_clientdata(client)); - return 0; -} - -static int __init pca9539_init(void) -{ - return i2c_add_driver(&pca9539_driver); -} - -static void __exit pca9539_exit(void) -{ - i2c_del_driver(&pca9539_driver); -} - -MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>"); -MODULE_DESCRIPTION("PCA9539 driver"); -MODULE_LICENSE("GPL"); - -module_init(pca9539_init); -module_exit(pca9539_exit); - diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c deleted file mode 100644 index e5b31329b56..00000000000 --- a/drivers/i2c/chips/pcf8574.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - pcf8574.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 2000 Frodo Looijaard <frodol@dds.nl>, - Philip Edelbrock <phil@netroedge.com>, - Dan Eaton <dan.eaton@rocketlogix.com> - Ported to Linux 2.6 by Aurelien Jarno <aurel32@debian.org> with - the help of Jean Delvare <khali@linux-fr.org> - - 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. -*/ - -/* A few notes about the PCF8574: - -* The PCF8574 is an 8-bit I/O expander for the I2C bus produced by - Philips Semiconductors. It is designed to provide a byte I2C - interface to up to 8 separate devices. - -* The PCF8574 appears as a very simple SMBus device which can be - read from or written to with SMBUS byte read/write accesses. - - --Dan - -*/ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/i2c.h> - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - I2C_CLIENT_END -}; - -/* Insmod parameters */ -I2C_CLIENT_INSMOD_2(pcf8574, pcf8574a); - -/* Each client has this additional data */ -struct pcf8574_data { - struct i2c_client client; - - int write; /* Remember last written value */ -}; - -static int pcf8574_attach_adapter(struct i2c_adapter *adapter); -static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind); -static int pcf8574_detach_client(struct i2c_client *client); -static void pcf8574_init_client(struct i2c_client *client); - -/* This is the driver that will be inserted */ -static struct i2c_driver pcf8574_driver = { - .driver = { - .name = "pcf8574", - }, - .attach_adapter = pcf8574_attach_adapter, - .detach_client = pcf8574_detach_client, -}; - -/* following are the sysfs callback functions */ -static ssize_t show_read(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - return sprintf(buf, "%u\n", i2c_smbus_read_byte(client)); -} - -static DEVICE_ATTR(read, S_IRUGO, show_read, NULL); - -static ssize_t show_write(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct pcf8574_data *data = i2c_get_clientdata(to_i2c_client(dev)); - - if (data->write < 0) - return data->write; - - return sprintf(buf, "%d\n", data->write); -} - -static ssize_t set_write(struct device *dev, struct device_attribute *attr, const char *buf, - size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct pcf8574_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - - if (val > 0xff) - return -EINVAL; - - data->write = val; - i2c_smbus_write_byte(client, data->write); - return count; -} - -static DEVICE_ATTR(write, S_IWUSR | S_IRUGO, show_write, set_write); - -static struct attribute *pcf8574_attributes[] = { - &dev_attr_read.attr, - &dev_attr_write.attr, - NULL -}; - -static const struct attribute_group pcf8574_attr_group = { - .attrs = pcf8574_attributes, -}; - -/* - * Real code - */ - -static int pcf8574_attach_adapter(struct i2c_adapter *adapter) -{ - return i2c_probe(adapter, &addr_data, pcf8574_detect); -} - -/* This function is called by i2c_probe */ -static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind) -{ - struct i2c_client *new_client; - struct pcf8574_data *data; - int err = 0; - const char *client_name = ""; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) - goto exit; - - /* OK. For now, we presume we have a valid client. We now create the - client structure, even though we cannot fill it completely yet. */ - if (!(data = kzalloc(sizeof(struct pcf8574_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &pcf8574_driver; - new_client->flags = 0; - - /* Now, we would do the remaining detection. But the PCF8574 is plainly - impossible to detect! Stupid chip. */ - - /* Determine the chip type */ - if (kind <= 0) { - if (address >= 0x38 && address <= 0x3f) - kind = pcf8574a; - else - kind = pcf8574; - } - - if (kind == pcf8574a) - client_name = "pcf8574a"; - else - client_name = "pcf8574"; - - /* Fill in the remaining client fields and put it into the global list */ - strlcpy(new_client->name, client_name, I2C_NAME_SIZE); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto exit_free; - - /* Initialize the PCF8574 chip */ - pcf8574_init_client(new_client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&new_client->dev.kobj, &pcf8574_attr_group); - if (err) - goto exit_detach; - return 0; - - exit_detach: - i2c_detach_client(new_client); - exit_free: - kfree(data); - exit: - return err; -} - -static int pcf8574_detach_client(struct i2c_client *client) -{ - int err; - - sysfs_remove_group(&client->dev.kobj, &pcf8574_attr_group); - - if ((err = i2c_detach_client(client))) - return err; - - kfree(i2c_get_clientdata(client)); - return 0; -} - -/* Called when we have found a new PCF8574. */ -static void pcf8574_init_client(struct i2c_client *client) -{ - struct pcf8574_data *data = i2c_get_clientdata(client); - data->write = -EAGAIN; -} - -static int __init pcf8574_init(void) -{ - return i2c_add_driver(&pcf8574_driver); -} - -static void __exit pcf8574_exit(void) -{ - i2c_del_driver(&pcf8574_driver); -} - - -MODULE_AUTHOR - ("Frodo Looijaard <frodol@dds.nl>, " - "Philip Edelbrock <phil@netroedge.com>, " - "Dan Eaton <dan.eaton@rocketlogix.com> " - "and Aurelien Jarno <aurelien@aurel32.net>"); -MODULE_DESCRIPTION("PCF8574 driver"); -MODULE_LICENSE("GPL"); - -module_init(pcf8574_init); -module_exit(pcf8574_exit); diff --git a/drivers/i2c/chips/pcf8575.c b/drivers/i2c/chips/pcf8575.c deleted file mode 100644 index 3ea08ac0bfa..00000000000 --- a/drivers/i2c/chips/pcf8575.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - pcf8575.c - - About the PCF8575 chip: the PCF8575 is a 16-bit I/O expander for the I2C bus - produced by a.o. Philips Semiconductors. - - Copyright (C) 2006 Michael Hennerich, Analog Devices Inc. - <hennerich@blackfin.uclinux.org> - Based on pcf8574.c. - - Copyright (c) 2007 Bart Van Assche <bart.vanassche@gmail.com>. - Ported this driver from ucLinux to the mainstream Linux kernel. - - 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 <linux/module.h> -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/slab.h> /* kzalloc() */ -#include <linux/sysfs.h> /* sysfs_create_group() */ - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - I2C_CLIENT_END -}; - -/* Insmod parameters */ -I2C_CLIENT_INSMOD; - - -/* Each client has this additional data */ -struct pcf8575_data { - struct i2c_client client; - int write; /* last written value, or error code */ -}; - -static int pcf8575_attach_adapter(struct i2c_adapter *adapter); -static int pcf8575_detect(struct i2c_adapter *adapter, int address, int kind); -static int pcf8575_detach_client(struct i2c_client *client); - -/* This is the driver that will be inserted */ -static struct i2c_driver pcf8575_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "pcf8575", - }, - .attach_adapter = pcf8575_attach_adapter, - .detach_client = pcf8575_detach_client, -}; - -/* following are the sysfs callback functions */ -static ssize_t show_read(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - u16 val; - u8 iopin_state[2]; - - i2c_master_recv(client, iopin_state, 2); - - val = iopin_state[0]; - val |= iopin_state[1] << 8; - - return sprintf(buf, "%u\n", val); -} - -static DEVICE_ATTR(read, S_IRUGO, show_read, NULL); - -static ssize_t show_write(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct pcf8575_data *data = dev_get_drvdata(dev); - if (data->write < 0) - return data->write; - return sprintf(buf, "%d\n", data->write); -} - -static ssize_t set_write(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct pcf8575_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - u8 iopin_state[2]; - - if (val > 0xffff) - return -EINVAL; - - data->write = val; - - iopin_state[0] = val & 0xFF; - iopin_state[1] = val >> 8; - - i2c_master_send(client, iopin_state, 2); - - return count; -} - -static DEVICE_ATTR(write, S_IWUSR | S_IRUGO, show_write, set_write); - -static struct attribute *pcf8575_attributes[] = { - &dev_attr_read.attr, - &dev_attr_write.attr, - NULL -}; - -static const struct attribute_group pcf8575_attr_group = { - .attrs = pcf8575_attributes, -}; - -/* - * Real code - */ - -static int pcf8575_attach_adapter(struct i2c_adapter *adapter) -{ - return i2c_probe(adapter, &addr_data, pcf8575_detect); -} - -/* This function is called by i2c_probe */ -static int pcf8575_detect(struct i2c_adapter *adapter, int address, int kind) -{ - struct i2c_client *client; - struct pcf8575_data *data; - int err = 0; - - if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) - goto exit; - - /* OK. For now, we presume we have a valid client. We now create the - client structure, even though we cannot fill it completely yet. */ - data = kzalloc(sizeof(struct pcf8575_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - client = &data->client; - i2c_set_clientdata(client, data); - client->addr = address; - client->adapter = adapter; - client->driver = &pcf8575_driver; - strlcpy(client->name, "pcf8575", I2C_NAME_SIZE); - data->write = -EAGAIN; - - /* This is the place to detect whether the chip at the specified - address really is a PCF8575 chip. However, there is no method known - to detect whether an I2C chip is a PCF8575 or any other I2C chip. */ - - /* Tell the I2C layer a new client has arrived */ - err = i2c_attach_client(client); - if (err) - goto exit_free; - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &pcf8575_attr_group); - if (err) - goto exit_detach; - - return 0; - -exit_detach: - i2c_detach_client(client); -exit_free: - kfree(data); -exit: - return err; -} - -static int pcf8575_detach_client(struct i2c_client *client) -{ - int err; - - sysfs_remove_group(&client->dev.kobj, &pcf8575_attr_group); - - err = i2c_detach_client(client); - if (err) - return err; - - kfree(i2c_get_clientdata(client)); - return 0; -} - -static int __init pcf8575_init(void) -{ - return i2c_add_driver(&pcf8575_driver); -} - -static void __exit pcf8575_exit(void) -{ - i2c_del_driver(&pcf8575_driver); -} - -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>, " - "Bart Van Assche <bart.vanassche@gmail.com>"); -MODULE_DESCRIPTION("pcf8575 driver"); -MODULE_LICENSE("GPL"); - -module_init(pcf8575_init); -module_exit(pcf8575_exit); diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c deleted file mode 100644 index 66c7c3bb942..00000000000 --- a/drivers/i2c/chips/pcf8591.c +++ /dev/null @@ -1,342 +0,0 @@ -/* - pcf8591.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (C) 2001-2004 Aurelien Jarno <aurelien@aurel32.net> - Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with - the help of Jean Delvare <khali@linux-fr.org> - - 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 <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/i2c.h> -#include <linux/mutex.h> - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, - 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; - -/* Insmod parameters */ -I2C_CLIENT_INSMOD_1(pcf8591); - -static int input_mode; -module_param(input_mode, int, 0); -MODULE_PARM_DESC(input_mode, - "Analog input mode:\n" - " 0 = four single ended inputs\n" - " 1 = three differential inputs\n" - " 2 = single ended and differential mixed\n" - " 3 = two differential inputs\n"); - -/* The PCF8591 control byte - 7 6 5 4 3 2 1 0 - | 0 |AOEF| AIP | 0 |AINC| AICH | */ - -/* Analog Output Enable Flag (analog output active if 1) */ -#define PCF8591_CONTROL_AOEF 0x40 - -/* Analog Input Programming - 0x00 = four single ended inputs - 0x10 = three differential inputs - 0x20 = single ended and differential mixed - 0x30 = two differential inputs */ -#define PCF8591_CONTROL_AIP_MASK 0x30 - -/* Autoincrement Flag (switch on if 1) */ -#define PCF8591_CONTROL_AINC 0x04 - -/* Channel selection - 0x00 = channel 0 - 0x01 = channel 1 - 0x02 = channel 2 - 0x03 = channel 3 */ -#define PCF8591_CONTROL_AICH_MASK 0x03 - -/* Initial values */ -#define PCF8591_INIT_CONTROL ((input_mode << 4) | PCF8591_CONTROL_AOEF) -#define PCF8591_INIT_AOUT 0 /* DAC out = 0 */ - -/* Conversions */ -#define REG_TO_SIGNED(reg) (((reg) & 0x80)?((reg) - 256):(reg)) - -struct pcf8591_data { - struct i2c_client client; - struct mutex update_lock; - - u8 control; - u8 aout; -}; - -static int pcf8591_attach_adapter(struct i2c_adapter *adapter); -static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind); -static int pcf8591_detach_client(struct i2c_client *client); -static void pcf8591_init_client(struct i2c_client *client); -static int pcf8591_read_channel(struct device *dev, int channel); - -/* This is the driver that will be inserted */ -static struct i2c_driver pcf8591_driver = { - .driver = { - .name = "pcf8591", - }, - .attach_adapter = pcf8591_attach_adapter, - .detach_client = pcf8591_detach_client, -}; - -/* following are the sysfs callback functions */ -#define show_in_channel(channel) \ -static ssize_t show_in##channel##_input(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return sprintf(buf, "%d\n", pcf8591_read_channel(dev, channel));\ -} \ -static DEVICE_ATTR(in##channel##_input, S_IRUGO, \ - show_in##channel##_input, NULL); - -show_in_channel(0); -show_in_channel(1); -show_in_channel(2); -show_in_channel(3); - -static ssize_t show_out0_ouput(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct pcf8591_data *data = i2c_get_clientdata(to_i2c_client(dev)); - return sprintf(buf, "%d\n", data->aout * 10); -} - -static ssize_t set_out0_output(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - unsigned int value; - struct i2c_client *client = to_i2c_client(dev); - struct pcf8591_data *data = i2c_get_clientdata(client); - if ((value = (simple_strtoul(buf, NULL, 10) + 5) / 10) <= 255) { - data->aout = value; - i2c_smbus_write_byte_data(client, data->control, data->aout); - return count; - } - return -EINVAL; -} - -static DEVICE_ATTR(out0_output, S_IWUSR | S_IRUGO, - show_out0_ouput, set_out0_output); - -static ssize_t show_out0_enable(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct pcf8591_data *data = i2c_get_clientdata(to_i2c_client(dev)); - return sprintf(buf, "%u\n", !(!(data->control & PCF8591_CONTROL_AOEF))); -} - -static ssize_t set_out0_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct pcf8591_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - - mutex_lock(&data->update_lock); - if (val) - data->control |= PCF8591_CONTROL_AOEF; - else - data->control &= ~PCF8591_CONTROL_AOEF; - i2c_smbus_write_byte(client, data->control); - mutex_unlock(&data->update_lock); - return count; -} - -static DEVICE_ATTR(out0_enable, S_IWUSR | S_IRUGO, - show_out0_enable, set_out0_enable); - -static struct attribute *pcf8591_attributes[] = { - &dev_attr_out0_enable.attr, - &dev_attr_out0_output.attr, - &dev_attr_in0_input.attr, - &dev_attr_in1_input.attr, - NULL -}; - -static const struct attribute_group pcf8591_attr_group = { - .attrs = pcf8591_attributes, -}; - -static struct attribute *pcf8591_attributes_opt[] = { - &dev_attr_in2_input.attr, - &dev_attr_in3_input.attr, - NULL -}; - -static const struct attribute_group pcf8591_attr_group_opt = { - .attrs = pcf8591_attributes_opt, -}; - -/* - * Real code - */ -static int pcf8591_attach_adapter(struct i2c_adapter *adapter) -{ - return i2c_probe(adapter, &addr_data, pcf8591_detect); -} - -/* This function is called by i2c_probe */ -static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind) -{ - struct i2c_client *new_client; - struct pcf8591_data *data; - int err = 0; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE - | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) - goto exit; - - /* OK. For now, we presume we have a valid client. We now create the - client structure, even though we cannot fill it completely yet. */ - if (!(data = kzalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) { - err = -ENOMEM; - goto exit; - } - - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &pcf8591_driver; - new_client->flags = 0; - - /* Now, we would do the remaining detection. But the PCF8591 is plainly - impossible to detect! Stupid chip. */ - - /* Determine the chip type - only one kind supported! */ - if (kind <= 0) - kind = pcf8591; - - /* Fill in the remaining client fields and put it into the global - list */ - strlcpy(new_client->name, "pcf8591", I2C_NAME_SIZE); - mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto exit_kfree; - - /* Initialize the PCF8591 chip */ - pcf8591_init_client(new_client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&new_client->dev.kobj, &pcf8591_attr_group); - if (err) - goto exit_detach; - - /* Register input2 if not in "two differential inputs" mode */ - if (input_mode != 3) { - if ((err = device_create_file(&new_client->dev, - &dev_attr_in2_input))) - goto exit_sysfs_remove; - } - - /* Register input3 only in "four single ended inputs" mode */ - if (input_mode == 0) { - if ((err = device_create_file(&new_client->dev, - &dev_attr_in3_input))) - goto exit_sysfs_remove; - } - - return 0; - -exit_sysfs_remove: - sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group_opt); - sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group); -exit_detach: - i2c_detach_client(new_client); -exit_kfree: - kfree(data); -exit: - return err; -} - -static int pcf8591_detach_client(struct i2c_client *client) -{ - int err; - - sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt); - sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group); - - if ((err = i2c_detach_client(client))) - return err; - - kfree(i2c_get_clientdata(client)); - return 0; -} - -/* Called when we have found a new PCF8591. */ -static void pcf8591_init_client(struct i2c_client *client) -{ - struct pcf8591_data *data = i2c_get_clientdata(client); - data->control = PCF8591_INIT_CONTROL; - data->aout = PCF8591_INIT_AOUT; - - i2c_smbus_write_byte_data(client, data->control, data->aout); - - /* The first byte transmitted contains the conversion code of the - previous read cycle. FLUSH IT! */ - i2c_smbus_read_byte(client); -} - -static int pcf8591_read_channel(struct device *dev, int channel) -{ - u8 value; - struct i2c_client *client = to_i2c_client(dev); - struct pcf8591_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if ((data->control & PCF8591_CONTROL_AICH_MASK) != channel) { - data->control = (data->control & ~PCF8591_CONTROL_AICH_MASK) - | channel; - i2c_smbus_write_byte(client, data->control); - - /* The first byte transmitted contains the conversion code of - the previous read cycle. FLUSH IT! */ - i2c_smbus_read_byte(client); - } - value = i2c_smbus_read_byte(client); - - mutex_unlock(&data->update_lock); - - if ((channel == 2 && input_mode == 2) || - (channel != 3 && (input_mode == 1 || input_mode == 3))) - return (10 * REG_TO_SIGNED(value)); - else - return (10 * value); -} - -static int __init pcf8591_init(void) -{ - if (input_mode < 0 || input_mode > 3) { - printk(KERN_WARNING "pcf8591: invalid input_mode (%d)\n", - input_mode); - input_mode = 0; - } - return i2c_add_driver(&pcf8591_driver); -} - -static void __exit pcf8591_exit(void) -{ - i2c_del_driver(&pcf8591_driver); -} - -MODULE_AUTHOR("Aurelien Jarno <aurelien@aurel32.net>"); -MODULE_DESCRIPTION("PCF8591 driver"); -MODULE_LICENSE("GPL"); - -module_init(pcf8591_init); -module_exit(pcf8591_exit); diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c deleted file mode 100644 index 4154a910885..00000000000 --- a/drivers/i2c/chips/tps65010.c +++ /dev/null @@ -1,969 +0,0 @@ -/* - * tps65010 - driver for tps6501x power management chips - * - * Copyright (C) 2004 Texas Instruments - * Copyright (C) 2004-2005 David Brownell - * - * 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 <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/i2c.h> -#include <linux/delay.h> -#include <linux/workqueue.h> -#include <linux/debugfs.h> -#include <linux/seq_file.h> -#include <linux/mutex.h> - -#include <linux/i2c/tps65010.h> - -/*-------------------------------------------------------------------------*/ - -#define DRIVER_VERSION "2 May 2005" -#define DRIVER_NAME (tps65010_driver.driver.name) - -MODULE_DESCRIPTION("TPS6501x Power Management Driver"); -MODULE_LICENSE("GPL"); - -static struct i2c_driver tps65010_driver; - -/*-------------------------------------------------------------------------*/ - -/* This driver handles a family of multipurpose chips, which incorporate - * voltage regulators, lithium ion/polymer battery charging, GPIOs, LEDs, - * and other features often needed in portable devices like cell phones - * or digital cameras. - * - * The tps65011 and tps65013 have different voltage settings compared - * to tps65010 and tps65012. The tps65013 has a NO_CHG status/irq. - * All except tps65010 have "wait" mode, possibly defaulted so that - * battery-insert != device-on. - * - * We could distinguish between some models by checking VDCDC1.UVLO or - * other registers, unless they've been changed already after powerup - * as part of board setup by a bootloader. - */ -enum tps_model { - TPS_UNKNOWN = 0, - TPS65010, - TPS65011, - TPS65012, - TPS65013, -}; - -struct tps65010 { - struct i2c_client *client; - struct mutex lock; - struct delayed_work work; - struct dentry *file; - unsigned charging:1; - unsigned por:1; - unsigned model:8; - u16 vbus; - unsigned long flags; -#define FLAG_VBUS_CHANGED 0 -#define FLAG_IRQ_ENABLE 1 - - /* copies of last register state */ - u8 chgstatus, regstatus, chgconf; - u8 nmask1, nmask2; - - /* not currently tracking GPIO state */ -}; - -#define POWER_POLL_DELAY msecs_to_jiffies(5000) - -/*-------------------------------------------------------------------------*/ - -#if defined(DEBUG) || defined(CONFIG_DEBUG_FS) - -static void dbg_chgstat(char *buf, size_t len, u8 chgstatus) -{ - snprintf(buf, len, "%02x%s%s%s%s%s%s%s%s\n", - chgstatus, - (chgstatus & TPS_CHG_USB) ? " USB" : "", - (chgstatus & TPS_CHG_AC) ? " AC" : "", - (chgstatus & TPS_CHG_THERM) ? " therm" : "", - (chgstatus & TPS_CHG_TERM) ? " done" : - ((chgstatus & (TPS_CHG_USB|TPS_CHG_AC)) - ? " (charging)" : ""), - (chgstatus & TPS_CHG_TAPER_TMO) ? " taper_tmo" : "", - (chgstatus & TPS_CHG_CHG_TMO) ? " charge_tmo" : "", - (chgstatus & TPS_CHG_PRECHG_TMO) ? " prechg_tmo" : "", - (chgstatus & TPS_CHG_TEMP_ERR) ? " temp_err" : ""); -} - -static void dbg_regstat(char *buf, size_t len, u8 regstatus) -{ - snprintf(buf, len, "%02x %s%s%s%s%s%s%s%s\n", - regstatus, - (regstatus & TPS_REG_ONOFF) ? "off" : "(on)", - (regstatus & TPS_REG_COVER) ? " uncover" : "", - (regstatus & TPS_REG_UVLO) ? " UVLO" : "", - (regstatus & TPS_REG_NO_CHG) ? " NO_CHG" : "", - (regstatus & TPS_REG_PG_LD02) ? " ld02_bad" : "", - (regstatus & TPS_REG_PG_LD01) ? " ld01_bad" : "", - (regstatus & TPS_REG_PG_MAIN) ? " main_bad" : "", - (regstatus & TPS_REG_PG_CORE) ? " core_bad" : ""); -} - -static void dbg_chgconf(int por, char *buf, size_t len, u8 chgconfig) -{ - const char *hibit; - - if (por) - hibit = (chgconfig & TPS_CHARGE_POR) - ? "POR=69ms" : "POR=1sec"; - else - hibit = (chgconfig & TPS65013_AUA) ? "AUA" : ""; - - snprintf(buf, len, "%02x %s%s%s AC=%d%% USB=%dmA %sCharge\n", - chgconfig, hibit, - (chgconfig & TPS_CHARGE_RESET) ? " reset" : "", - (chgconfig & TPS_CHARGE_FAST) ? " fast" : "", - ({int p; switch ((chgconfig >> 3) & 3) { - case 3: p = 100; break; - case 2: p = 75; break; - case 1: p = 50; break; - default: p = 25; break; - }; p; }), - (chgconfig & TPS_VBUS_CHARGING) - ? ((chgconfig & TPS_VBUS_500MA) ? 500 : 100) - : 0, - (chgconfig & TPS_CHARGE_ENABLE) ? "" : "No"); -} - -#endif - -#ifdef DEBUG - -static void show_chgstatus(const char *label, u8 chgstatus) -{ - char buf [100]; - - dbg_chgstat(buf, sizeof buf, chgstatus); - pr_debug("%s: %s %s", DRIVER_NAME, label, buf); -} - -static void show_regstatus(const char *label, u8 regstatus) -{ - char buf [100]; - - dbg_regstat(buf, sizeof buf, regstatus); - pr_debug("%s: %s %s", DRIVER_NAME, label, buf); -} - -static void show_chgconfig(int por, const char *label, u8 chgconfig) -{ - char buf [100]; - - dbg_chgconf(por, buf, sizeof buf, chgconfig); - pr_debug("%s: %s %s", DRIVER_NAME, label, buf); -} - -#else - -static inline void show_chgstatus(const char *label, u8 chgstatus) { } -static inline void show_regstatus(const char *label, u8 chgstatus) { } -static inline void show_chgconfig(int por, const char *label, u8 chgconfig) { } - -#endif - -#ifdef CONFIG_DEBUG_FS - -static int dbg_show(struct seq_file *s, void *_) -{ - struct tps65010 *tps = s->private; - u8 value, v2; - unsigned i; - char buf[100]; - const char *chip; - - switch (tps->model) { - case TPS65010: chip = "tps65010"; break; - case TPS65011: chip = "tps65011"; break; - case TPS65012: chip = "tps65012"; break; - case TPS65013: chip = "tps65013"; break; - default: chip = NULL; break; - } - seq_printf(s, "driver %s\nversion %s\nchip %s\n\n", - DRIVER_NAME, DRIVER_VERSION, chip); - - mutex_lock(&tps->lock); - - /* FIXME how can we tell whether a battery is present? - * likely involves a charge gauging chip (like BQ26501). - */ - - seq_printf(s, "%scharging\n\n", tps->charging ? "" : "(not) "); - - - /* registers for monitoring battery charging and status; note - * that reading chgstat and regstat may ack IRQs... - */ - value = i2c_smbus_read_byte_data(tps->client, TPS_CHGCONFIG); - dbg_chgconf(tps->por, buf, sizeof buf, value); - seq_printf(s, "chgconfig %s", buf); - - value = i2c_smbus_read_byte_data(tps->client, TPS_CHGSTATUS); - dbg_chgstat(buf, sizeof buf, value); - seq_printf(s, "chgstat %s", buf); - value = i2c_smbus_read_byte_data(tps->client, TPS_MASK1); - dbg_chgstat(buf, sizeof buf, value); - seq_printf(s, "mask1 %s", buf); - /* ignore ackint1 */ - - value = i2c_smbus_read_byte_data(tps->client, TPS_REGSTATUS); - dbg_regstat(buf, sizeof buf, value); - seq_printf(s, "regstat %s", buf); - value = i2c_smbus_read_byte_data(tps->client, TPS_MASK2); - dbg_regstat(buf, sizeof buf, value); - seq_printf(s, "mask2 %s\n", buf); - /* ignore ackint2 */ - - (void) schedule_delayed_work(&tps->work, POWER_POLL_DELAY); - - - /* VMAIN voltage, enable lowpower, etc */ - value = i2c_smbus_read_byte_data(tps->client, TPS_VDCDC1); - seq_printf(s, "vdcdc1 %02x\n", value); - - /* VCORE voltage, vibrator on/off */ - value = i2c_smbus_read_byte_data(tps->client, TPS_VDCDC2); - seq_printf(s, "vdcdc2 %02x\n", value); - - /* both LD0s, and their lowpower behavior */ - value = i2c_smbus_read_byte_data(tps->client, TPS_VREGS1); - seq_printf(s, "vregs1 %02x\n\n", value); - - - /* LEDs and GPIOs */ - value = i2c_smbus_read_byte_data(tps->client, TPS_LED1_ON); - v2 = i2c_smbus_read_byte_data(tps->client, TPS_LED1_PER); - seq_printf(s, "led1 %s, on=%02x, per=%02x, %d/%d msec\n", - (value & 0x80) - ? ((v2 & 0x80) ? "on" : "off") - : ((v2 & 0x80) ? "blink" : "(nPG)"), - value, v2, - (value & 0x7f) * 10, (v2 & 0x7f) * 100); - - value = i2c_smbus_read_byte_data(tps->client, TPS_LED2_ON); - v2 = i2c_smbus_read_byte_data(tps->client, TPS_LED2_PER); - seq_printf(s, "led2 %s, on=%02x, per=%02x, %d/%d msec\n", - (value & 0x80) - ? ((v2 & 0x80) ? "on" : "off") - : ((v2 & 0x80) ? "blink" : "off"), - value, v2, - (value & 0x7f) * 10, (v2 & 0x7f) * 100); - - value = i2c_smbus_read_byte_data(tps->client, TPS_DEFGPIO); - v2 = i2c_smbus_read_byte_data(tps->client, TPS_MASK3); - seq_printf(s, "defgpio %02x mask3 %02x\n", value, v2); - - for (i = 0; i < 4; i++) { - if (value & (1 << (4 + i))) - seq_printf(s, " gpio%d-out %s\n", i + 1, - (value & (1 << i)) ? "low" : "hi "); - else - seq_printf(s, " gpio%d-in %s %s %s\n", i + 1, - (value & (1 << i)) ? "hi " : "low", - (v2 & (1 << i)) ? "no-irq" : "irq", - (v2 & (1 << (4 + i))) ? "rising" : "falling"); - } - - mutex_unlock(&tps->lock); - return 0; -} - -static int dbg_tps_open(struct inode *inode, struct file *file) -{ - return single_open(file, dbg_show, inode->i_private); -} - -static const struct file_operations debug_fops = { - .open = dbg_tps_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -#define DEBUG_FOPS &debug_fops - -#else -#define DEBUG_FOPS NULL -#endif - -/*-------------------------------------------------------------------------*/ - -/* handle IRQS in a task context, so we can use I2C calls */ -static void tps65010_interrupt(struct tps65010 *tps) -{ - u8 tmp = 0, mask, poll; - - /* IRQs won't trigger for certain events, but we can get - * others by polling (normally, with external power applied). - */ - poll = 0; - - /* regstatus irqs */ - if (tps->nmask2) { - tmp = i2c_smbus_read_byte_data(tps->client, TPS_REGSTATUS); - mask = tmp ^ tps->regstatus; - tps->regstatus = tmp; - mask &= tps->nmask2; - } else - mask = 0; - if (mask) { - tps->regstatus = tmp; - /* may need to shut something down ... */ - - /* "off" usually means deep sleep */ - if (tmp & TPS_REG_ONOFF) { - pr_info("%s: power off button\n", DRIVER_NAME); -#if 0 - /* REVISIT: this might need its own workqueue - * plus tweaks including deadlock avoidance ... - * also needs to get error handling and probably - * an #ifdef CONFIG_HIBERNATION - */ - hibernate(); -#endif - poll = 1; - } - } - - /* chgstatus irqs */ - if (tps->nmask1) { - tmp = i2c_smbus_read_byte_data(tps->client, TPS_CHGSTATUS); - mask = tmp ^ tps->chgstatus; - tps->chgstatus = tmp; - mask &= tps->nmask1; - } else - mask = 0; - if (mask) { - unsigned charging = 0; - - show_chgstatus("chg/irq", tmp); - if (tmp & (TPS_CHG_USB|TPS_CHG_AC)) - show_chgconfig(tps->por, "conf", tps->chgconf); - - /* Unless it was turned off or disabled, we charge any - * battery whenever there's power available for it - * and the charger hasn't been disabled. - */ - if (!(tps->chgstatus & ~(TPS_CHG_USB|TPS_CHG_AC)) - && (tps->chgstatus & (TPS_CHG_USB|TPS_CHG_AC)) - && (tps->chgconf & TPS_CHARGE_ENABLE) - ) { - if (tps->chgstatus & TPS_CHG_USB) { - /* VBUS options are readonly until reconnect */ - if (mask & TPS_CHG_USB) - set_bit(FLAG_VBUS_CHANGED, &tps->flags); - charging = 1; - } else if (tps->chgstatus & TPS_CHG_AC) - charging = 1; - } - if (charging != tps->charging) { - tps->charging = charging; - pr_info("%s: battery %scharging\n", - DRIVER_NAME, charging ? "" : - ((tps->chgstatus & (TPS_CHG_USB|TPS_CHG_AC)) - ? "NOT " : "dis")); - } - } - - /* always poll to detect (a) power removal, without tps65013 - * NO_CHG IRQ; or (b) restart of charging after stop. - */ - if ((tps->model != TPS65013 || !tps->charging) - && (tps->chgstatus & (TPS_CHG_USB|TPS_CHG_AC))) - poll = 1; - if (poll) - (void) schedule_delayed_work(&tps->work, POWER_POLL_DELAY); - - /* also potentially gpio-in rise or fall */ -} - -/* handle IRQs and polling using keventd for now */ -static void tps65010_work(struct work_struct *work) -{ - struct tps65010 *tps; - - tps = container_of(work, struct tps65010, work.work); - mutex_lock(&tps->lock); - - tps65010_interrupt(tps); - - if (test_and_clear_bit(FLAG_VBUS_CHANGED, &tps->flags)) { - int status; - u8 chgconfig, tmp; - - chgconfig = i2c_smbus_read_byte_data(tps->client, - TPS_CHGCONFIG); - chgconfig &= ~(TPS_VBUS_500MA | TPS_VBUS_CHARGING); - if (tps->vbus == 500) - chgconfig |= TPS_VBUS_500MA | TPS_VBUS_CHARGING; - else if (tps->vbus >= 100) - chgconfig |= TPS_VBUS_CHARGING; - - status = i2c_smbus_write_byte_data(tps->client, - TPS_CHGCONFIG, chgconfig); - - /* vbus update fails unless VBUS is connected! */ - tmp = i2c_smbus_read_byte_data(tps->client, TPS_CHGCONFIG); - tps->chgconf = tmp; - show_chgconfig(tps->por, "update vbus", tmp); - } - - if (test_and_clear_bit(FLAG_IRQ_ENABLE, &tps->flags)) - enable_irq(tps->client->irq); - - mutex_unlock(&tps->lock); -} - -static irqreturn_t tps65010_irq(int irq, void *_tps) -{ - struct tps65010 *tps = _tps; - - disable_irq_nosync(irq); - set_bit(FLAG_IRQ_ENABLE, &tps->flags); - (void) schedule_work(&tps->work.work); - return IRQ_HANDLED; -} - -/*-------------------------------------------------------------------------*/ - -static struct tps65010 *the_tps; - -static int __exit tps65010_remove(struct i2c_client *client) -{ - struct tps65010 *tps = i2c_get_clientdata(client); - - if (client->irq > 0) - free_irq(client->irq, tps); - cancel_delayed_work(&tps->work); - flush_scheduled_work(); - debugfs_remove(tps->file); - kfree(tps); - the_tps = NULL; - return 0; -} - -static int tps65010_probe(struct i2c_client *client) -{ - struct tps65010 *tps; - int status; - - if (the_tps) { - dev_dbg(&client->dev, "only one tps6501x chip allowed\n"); - return -ENODEV; - } - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -EINVAL; - - tps = kzalloc(sizeof *tps, GFP_KERNEL); - if (!tps) - return -ENOMEM; - - mutex_init(&tps->lock); - INIT_DELAYED_WORK(&tps->work, tps65010_work); - tps->client = client; - - if (strcmp(client->name, "tps65010") == 0) - tps->model = TPS65010; - else if (strcmp(client->name, "tps65011") == 0) - tps->model = TPS65011; - else if (strcmp(client->name, "tps65012") == 0) - tps->model = TPS65012; - else if (strcmp(client->name, "tps65013") == 0) - tps->model = TPS65013; - else { - dev_warn(&client->dev, "unknown chip '%s'\n", client->name); - status = -ENODEV; - goto fail1; - } - - /* the IRQ is active low, but many gpio lines can't support that - * so this driver uses falling-edge triggers instead. - */ - if (client->irq > 0) { - status = request_irq(client->irq, tps65010_irq, - IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_FALLING, - DRIVER_NAME, tps); - if (status < 0) { - dev_dbg(&client->dev, "can't get IRQ %d, err %d\n", - client->irq, status); - goto fail1; - } - /* annoying race here, ideally we'd have an option - * to claim the irq now and enable it later. - * FIXME genirq IRQF_NOAUTOEN now solves that ... - */ - disable_irq(client->irq); - set_bit(FLAG_IRQ_ENABLE, &tps->flags); - } else - dev_warn(&client->dev, "IRQ not configured!\n"); - - - switch (tps->model) { - case TPS65010: - case TPS65012: - tps->por = 1; - break; - case TPS_UNKNOWN: - printk(KERN_WARNING "%s: unknown TPS chip\n", DRIVER_NAME); - break; - /* else CHGCONFIG.POR is replaced by AUA, enabling a WAIT mode */ - } - tps->chgconf = i2c_smbus_read_byte_data(client, TPS_CHGCONFIG); - show_chgconfig(tps->por, "conf/init", tps->chgconf); - - show_chgstatus("chg/init", - i2c_smbus_read_byte_data(client, TPS_CHGSTATUS)); - show_regstatus("reg/init", - i2c_smbus_read_byte_data(client, TPS_REGSTATUS)); - - pr_debug("%s: vdcdc1 0x%02x, vdcdc2 %02x, vregs1 %02x\n", DRIVER_NAME, - i2c_smbus_read_byte_data(client, TPS_VDCDC1), - i2c_smbus_read_byte_data(client, TPS_VDCDC2), - i2c_smbus_read_byte_data(client, TPS_VREGS1)); - pr_debug("%s: defgpio 0x%02x, mask3 0x%02x\n", DRIVER_NAME, - i2c_smbus_read_byte_data(client, TPS_DEFGPIO), - i2c_smbus_read_byte_data(client, TPS_MASK3)); - - the_tps = tps; - -#if defined(CONFIG_USB_GADGET) && !defined(CONFIG_USB_OTG) - /* USB hosts can't draw VBUS. OTG devices could, later - * when OTG infrastructure enables it. USB peripherals - * could be relying on VBUS while booting, though. - */ - tps->vbus = 100; -#endif - - /* unmask the "interesting" irqs, then poll once to - * kickstart monitoring, initialize shadowed status - * registers, and maybe disable VBUS draw. - */ - tps->nmask1 = ~0; - (void) i2c_smbus_write_byte_data(client, TPS_MASK1, ~tps->nmask1); - - tps->nmask2 = TPS_REG_ONOFF; - if (tps->model == TPS65013) - tps->nmask2 |= TPS_REG_NO_CHG; - (void) i2c_smbus_write_byte_data(client, TPS_MASK2, ~tps->nmask2); - - (void) i2c_smbus_write_byte_data(client, TPS_MASK3, 0x0f - | i2c_smbus_read_byte_data(client, TPS_MASK3)); - - tps65010_work(&tps->work.work); - - tps->file = debugfs_create_file(DRIVER_NAME, S_IRUGO, NULL, - tps, DEBUG_FOPS); - return 0; -fail1: - kfree(tps); - return status; -} - -static struct i2c_driver tps65010_driver = { - .driver = { - .name = "tps65010", - }, - .probe = tps65010_probe, - .remove = __exit_p(tps65010_remove), -}; - -/*-------------------------------------------------------------------------*/ - -/* Draw from VBUS: - * 0 mA -- DON'T DRAW (might supply power instead) - * 100 mA -- usb unit load (slowest charge rate) - * 500 mA -- usb high power (fast battery charge) - */ -int tps65010_set_vbus_draw(unsigned mA) -{ - unsigned long flags; - - if (!the_tps) - return -ENODEV; - - /* assumes non-SMP */ - local_irq_save(flags); - if (mA >= 500) - mA = 500; - else if (mA >= 100) - mA = 100; - else - mA = 0; - the_tps->vbus = mA; - if ((the_tps->chgstatus & TPS_CHG_USB) - && test_and_set_bit( - FLAG_VBUS_CHANGED, &the_tps->flags)) { - /* gadget drivers call this in_irq() */ - (void) schedule_work(&the_tps->work.work); - } - local_irq_restore(flags); - - return 0; -} -EXPORT_SYMBOL(tps65010_set_vbus_draw); - -/*-------------------------------------------------------------------------*/ -/* tps65010_set_gpio_out_value parameter: - * gpio: GPIO1, GPIO2, GPIO3 or GPIO4 - * value: LOW or HIGH - */ -int tps65010_set_gpio_out_value(unsigned gpio, unsigned value) -{ - int status; - unsigned defgpio; - - if (!the_tps) - return -ENODEV; - if ((gpio < GPIO1) || (gpio > GPIO4)) - return -EINVAL; - - mutex_lock(&the_tps->lock); - - defgpio = i2c_smbus_read_byte_data(the_tps->client, TPS_DEFGPIO); - - /* Configure GPIO for output */ - defgpio |= 1 << (gpio + 3); - - /* Writing 1 forces a logic 0 on that GPIO and vice versa */ - switch (value) { - case LOW: - defgpio |= 1 << (gpio - 1); /* set GPIO low by writing 1 */ - break; - /* case HIGH: */ - default: - defgpio &= ~(1 << (gpio - 1)); /* set GPIO high by writing 0 */ - break; - } - - status = i2c_smbus_write_byte_data(the_tps->client, - TPS_DEFGPIO, defgpio); - - pr_debug("%s: gpio%dout = %s, defgpio 0x%02x\n", DRIVER_NAME, - gpio, value ? "high" : "low", - i2c_smbus_read_byte_data(the_tps->client, TPS_DEFGPIO)); - - mutex_unlock(&the_tps->lock); - return status; -} -EXPORT_SYMBOL(tps65010_set_gpio_out_value); - -/*-------------------------------------------------------------------------*/ -/* tps65010_set_led parameter: - * led: LED1 or LED2 - * mode: ON, OFF or BLINK - */ -int tps65010_set_led(unsigned led, unsigned mode) -{ - int status; - unsigned led_on, led_per, offs; - - if (!the_tps) - return -ENODEV; - - if (led == LED1) - offs = 0; - else { - offs = 2; - led = LED2; - } - - mutex_lock(&the_tps->lock); - - pr_debug("%s: led%i_on 0x%02x\n", DRIVER_NAME, led, - i2c_smbus_read_byte_data(the_tps->client, - TPS_LED1_ON + offs)); - - pr_debug("%s: led%i_per 0x%02x\n", DRIVER_NAME, led, - i2c_smbus_read_byte_data(the_tps->client, - TPS_LED1_PER + offs)); - - switch (mode) { - case OFF: - led_on = 1 << 7; - led_per = 0 << 7; - break; - case ON: - led_on = 1 << 7; - led_per = 1 << 7; - break; - case BLINK: - led_on = 0x30 | (0 << 7); - led_per = 0x08 | (1 << 7); - break; - default: - printk(KERN_ERR "%s: Wrong mode parameter for set_led()\n", - DRIVER_NAME); - mutex_unlock(&the_tps->lock); - return -EINVAL; - } - - status = i2c_smbus_write_byte_data(the_tps->client, - TPS_LED1_ON + offs, led_on); - - if (status != 0) { - printk(KERN_ERR "%s: Failed to write led%i_on register\n", - DRIVER_NAME, led); - mutex_unlock(&the_tps->lock); - return status; - } - - pr_debug("%s: led%i_on 0x%02x\n", DRIVER_NAME, led, - i2c_smbus_read_byte_data(the_tps->client, TPS_LED1_ON + offs)); - - status = i2c_smbus_write_byte_data(the_tps->client, - TPS_LED1_PER + offs, led_per); - - if (status != 0) { - printk(KERN_ERR "%s: Failed to write led%i_per register\n", - DRIVER_NAME, led); - mutex_unlock(&the_tps->lock); - return status; - } - - pr_debug("%s: led%i_per 0x%02x\n", DRIVER_NAME, led, - i2c_smbus_read_byte_data(the_tps->client, - TPS_LED1_PER + offs)); - - mutex_unlock(&the_tps->lock); - - return status; -} -EXPORT_SYMBOL(tps65010_set_led); - -/*-------------------------------------------------------------------------*/ -/* tps65010_set_vib parameter: - * value: ON or OFF - */ -int tps65010_set_vib(unsigned value) -{ - int status; - unsigned vdcdc2; - - if (!the_tps) - return -ENODEV; - - mutex_lock(&the_tps->lock); - - vdcdc2 = i2c_smbus_read_byte_data(the_tps->client, TPS_VDCDC2); - vdcdc2 &= ~(1 << 1); - if (value) - vdcdc2 |= (1 << 1); - status = i2c_smbus_write_byte_data(the_tps->client, - TPS_VDCDC2, vdcdc2); - - pr_debug("%s: vibrator %s\n", DRIVER_NAME, value ? "on" : "off"); - - mutex_unlock(&the_tps->lock); - return status; -} -EXPORT_SYMBOL(tps65010_set_vib); - -/*-------------------------------------------------------------------------*/ -/* tps65010_set_low_pwr parameter: - * mode: ON or OFF - */ -int tps65010_set_low_pwr(unsigned mode) -{ - int status; - unsigned vdcdc1; - - if (!the_tps) - return -ENODEV; - - mutex_lock(&the_tps->lock); - - pr_debug("%s: %s low_pwr, vdcdc1 0x%02x\n", DRIVER_NAME, - mode ? "enable" : "disable", - i2c_smbus_read_byte_data(the_tps->client, TPS_VDCDC1)); - - vdcdc1 = i2c_smbus_read_byte_data(the_tps->client, TPS_VDCDC1); - - switch (mode) { - case OFF: - vdcdc1 &= ~TPS_ENABLE_LP; /* disable ENABLE_LP bit */ - break; - /* case ON: */ - default: - vdcdc1 |= TPS_ENABLE_LP; /* enable ENABLE_LP bit */ - break; - } - - status = i2c_smbus_write_byte_data(the_tps->client, - TPS_VDCDC1, vdcdc1); - - if (status != 0) - printk(KERN_ERR "%s: Failed to write vdcdc1 register\n", - DRIVER_NAME); - else - pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME, - i2c_smbus_read_byte_data(the_tps->client, TPS_VDCDC1)); - - mutex_unlock(&the_tps->lock); - - return status; -} -EXPORT_SYMBOL(tps65010_set_low_pwr); - -/*-------------------------------------------------------------------------*/ -/* tps65010_config_vregs1 parameter: - * value to be written to VREGS1 register - * Note: The complete register is written, set all bits you need - */ -int tps65010_config_vregs1(unsigned value) -{ - int status; - - if (!the_tps) - return -ENODEV; - - mutex_lock(&the_tps->lock); - - pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME, - i2c_smbus_read_byte_data(the_tps->client, TPS_VREGS1)); - - status = i2c_smbus_write_byte_data(the_tps->client, - TPS_VREGS1, value); - - if (status != 0) - printk(KERN_ERR "%s: Failed to write vregs1 register\n", - DRIVER_NAME); - else - pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME, - i2c_smbus_read_byte_data(the_tps->client, TPS_VREGS1)); - - mutex_unlock(&the_tps->lock); - - return status; -} -EXPORT_SYMBOL(tps65010_config_vregs1); - -/*-------------------------------------------------------------------------*/ -/* tps65013_set_low_pwr parameter: - * mode: ON or OFF - */ - -/* FIXME: Assumes AC or USB power is present. Setting AUA bit is not - required if power supply is through a battery */ - -int tps65013_set_low_pwr(unsigned mode) -{ - int status; - unsigned vdcdc1, chgconfig; - - if (!the_tps || the_tps->por) - return -ENODEV; - - mutex_lock(&the_tps->lock); - - pr_debug("%s: %s low_pwr, chgconfig 0x%02x vdcdc1 0x%02x\n", - DRIVER_NAME, - mode ? "enable" : "disable", - i2c_smbus_read_byte_data(the_tps->client, TPS_CHGCONFIG), - i2c_smbus_read_byte_data(the_tps->client, TPS_VDCDC1)); - - chgconfig = i2c_smbus_read_byte_data(the_tps->client, TPS_CHGCONFIG); - vdcdc1 = i2c_smbus_read_byte_data(the_tps->client, TPS_VDCDC1); - - switch (mode) { - case OFF: - chgconfig &= ~TPS65013_AUA; /* disable AUA bit */ - vdcdc1 &= ~TPS_ENABLE_LP; /* disable ENABLE_LP bit */ - break; - /* case ON: */ - default: - chgconfig |= TPS65013_AUA; /* enable AUA bit */ - vdcdc1 |= TPS_ENABLE_LP; /* enable ENABLE_LP bit */ - break; - } - - status = i2c_smbus_write_byte_data(the_tps->client, - TPS_CHGCONFIG, chgconfig); - if (status != 0) { - printk(KERN_ERR "%s: Failed to write chconfig register\n", - DRIVER_NAME); - mutex_unlock(&the_tps->lock); - return status; - } - - chgconfig = i2c_smbus_read_byte_data(the_tps->client, TPS_CHGCONFIG); - the_tps->chgconf = chgconfig; - show_chgconfig(0, "chgconf", chgconfig); - - status = i2c_smbus_write_byte_data(the_tps->client, - TPS_VDCDC1, vdcdc1); - - if (status != 0) - printk(KERN_ERR "%s: Failed to write vdcdc1 register\n", - DRIVER_NAME); - else - pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME, - i2c_smbus_read_byte_data(the_tps->client, TPS_VDCDC1)); - - mutex_unlock(&the_tps->lock); - - return status; -} -EXPORT_SYMBOL(tps65013_set_low_pwr); - -/*-------------------------------------------------------------------------*/ - -static int __init tps_init(void) -{ - u32 tries = 3; - int status = -ENODEV; - - printk(KERN_INFO "%s: version %s\n", DRIVER_NAME, DRIVER_VERSION); - - /* some boards have startup glitches */ - while (tries--) { - status = i2c_add_driver(&tps65010_driver); - if (the_tps) - break; - i2c_del_driver(&tps65010_driver); - if (!tries) { - printk(KERN_ERR "%s: no chip?\n", DRIVER_NAME); - return -ENODEV; - } - pr_debug("%s: re-probe ...\n", DRIVER_NAME); - msleep(10); - } - - return status; -} -/* NOTE: this MUST be initialized before the other parts of the system - * that rely on it ... but after the i2c bus on which this relies. - * That is, much earlier than on PC-type systems, which don't often use - * I2C as a core system bus. - */ -subsys_initcall(tps_init); - -static void __exit tps_exit(void) -{ - i2c_del_driver(&tps65010_driver); -} -module_exit(tps_exit); - diff --git a/drivers/i2c/chips/tsl2550.c b/drivers/i2c/chips/tsl2550.c deleted file mode 100644 index a10fd2791a6..00000000000 --- a/drivers/i2c/chips/tsl2550.c +++ /dev/null @@ -1,481 +0,0 @@ -/* - * tsl2550.c - Linux kernel modules for ambient light sensor - * - * Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it> - * Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it> - * - * 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 <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/i2c.h> -#include <linux/mutex.h> -#include <linux/delay.h> - -#define TSL2550_DRV_NAME "tsl2550" -#define DRIVER_VERSION "1.1.1" - -/* - * Defines - */ - -#define TSL2550_POWER_DOWN 0x00 -#define TSL2550_POWER_UP 0x03 -#define TSL2550_STANDARD_RANGE 0x18 -#define TSL2550_EXTENDED_RANGE 0x1d -#define TSL2550_READ_ADC0 0x43 -#define TSL2550_READ_ADC1 0x83 - -/* - * Structs - */ - -struct tsl2550_data { - struct i2c_client *client; - struct mutex update_lock; - - unsigned int power_state : 1; - unsigned int operating_mode : 1; -}; - -/* - * Global data - */ - -static const u8 TSL2550_MODE_RANGE[2] = { - TSL2550_STANDARD_RANGE, TSL2550_EXTENDED_RANGE, -}; - -/* - * Management functions - */ - -static int tsl2550_set_operating_mode(struct i2c_client *client, int mode) -{ - struct tsl2550_data *data = i2c_get_clientdata(client); - - int ret = i2c_smbus_write_byte(client, TSL2550_MODE_RANGE[mode]); - - data->operating_mode = mode; - - return ret; -} - -static int tsl2550_set_power_state(struct i2c_client *client, int state) -{ - struct tsl2550_data *data = i2c_get_clientdata(client); - int ret; - - if (state == 0) - ret = i2c_smbus_write_byte(client, TSL2550_POWER_DOWN); - else { - ret = i2c_smbus_write_byte(client, TSL2550_POWER_UP); - - /* On power up we should reset operating mode also... */ - tsl2550_set_operating_mode(client, data->operating_mode); - } - - data->power_state = state; - - return ret; -} - -static int tsl2550_get_adc_value(struct i2c_client *client, u8 cmd) -{ - unsigned long end; - int loop = 0, ret = 0; - - /* - * Read ADC channel waiting at most 400ms (see data sheet for further - * info). - * To avoid long busy wait we spin for few milliseconds then - * start sleeping. - */ - end = jiffies + msecs_to_jiffies(400); - while (time_before(jiffies, end)) { - i2c_smbus_write_byte(client, cmd); - - if (loop++ < 5) - mdelay(1); - else - msleep(1); - - ret = i2c_smbus_read_byte(client); - if (ret < 0) - return ret; - else if (ret & 0x0080) - break; - } - if (!(ret & 0x80)) - return -EIO; - return ret & 0x7f; /* remove the "valid" bit */ -} - -/* - * LUX calculation - */ - -#define TSL2550_MAX_LUX 1846 - -static const u8 ratio_lut[] = { - 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100, 100, 100, 100, 100, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 98, 98, 98, 98, 98, - 98, 98, 97, 97, 97, 97, 97, 96, - 96, 96, 96, 95, 95, 95, 94, 94, - 93, 93, 93, 92, 92, 91, 91, 90, - 89, 89, 88, 87, 87, 86, 85, 84, - 83, 82, 81, 80, 79, 78, 77, 75, - 74, 73, 71, 69, 68, 66, 64, 62, - 60, 58, 56, 54, 52, 49, 47, 44, - 42, 41, 40, 40, 39, 39, 38, 38, - 37, 37, 37, 36, 36, 36, 35, 35, - 35, 35, 34, 34, 34, 34, 33, 33, - 33, 33, 32, 32, 32, 32, 32, 31, - 31, 31, 31, 31, 30, 30, 30, 30, - 30, -}; - -static const u16 count_lut[] = { - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 18, 20, 22, 24, 26, 28, 30, - 32, 34, 36, 38, 40, 42, 44, 46, - 49, 53, 57, 61, 65, 69, 73, 77, - 81, 85, 89, 93, 97, 101, 105, 109, - 115, 123, 131, 139, 147, 155, 163, 171, - 179, 187, 195, 203, 211, 219, 227, 235, - 247, 263, 279, 295, 311, 327, 343, 359, - 375, 391, 407, 423, 439, 455, 471, 487, - 511, 543, 575, 607, 639, 671, 703, 735, - 767, 799, 831, 863, 895, 927, 959, 991, - 1039, 1103, 1167, 1231, 1295, 1359, 1423, 1487, - 1551, 1615, 1679, 1743, 1807, 1871, 1935, 1999, - 2095, 2223, 2351, 2479, 2607, 2735, 2863, 2991, - 3119, 3247, 3375, 3503, 3631, 3759, 3887, 4015, -}; - -/* - * This function is described into Taos TSL2550 Designer's Notebook - * pages 2, 3. - */ -static int tsl2550_calculate_lux(u8 ch0, u8 ch1) -{ - unsigned int lux; - - /* Look up count from channel values */ - u16 c0 = count_lut[ch0]; - u16 c1 = count_lut[ch1]; - - /* - * Calculate ratio. - * Note: the "128" is a scaling factor - */ - u8 r = 128; - - /* Avoid division by 0 and count 1 cannot be greater than count 0 */ - if (c0 && (c1 <= c0)) - r = c1 * 128 / c0; - else - return -1; - - /* Calculate LUX */ - lux = ((c0 - c1) * ratio_lut[r]) / 256; - - /* LUX range check */ - return lux > TSL2550_MAX_LUX ? TSL2550_MAX_LUX : lux; -} - -/* - * SysFS support - */ - -static ssize_t tsl2550_show_power_state(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev)); - - return sprintf(buf, "%u\n", data->power_state); -} - -static ssize_t tsl2550_store_power_state(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct tsl2550_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - int ret; - - if (val < 0 || val > 1) - return -EINVAL; - - mutex_lock(&data->update_lock); - ret = tsl2550_set_power_state(client, val); - mutex_unlock(&data->update_lock); - - if (ret < 0) - return ret; - - return count; -} - -static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO, - tsl2550_show_power_state, tsl2550_store_power_state); - -static ssize_t tsl2550_show_operating_mode(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev)); - - return sprintf(buf, "%u\n", data->operating_mode); -} - -static ssize_t tsl2550_store_operating_mode(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct tsl2550_data *data = i2c_get_clientdata(client); - unsigned long val = simple_strtoul(buf, NULL, 10); - int ret; - - if (val < 0 || val > 1) - return -EINVAL; - - if (data->power_state == 0) - return -EBUSY; - - mutex_lock(&data->update_lock); - ret = tsl2550_set_operating_mode(client, val); - mutex_unlock(&data->update_lock); - - if (ret < 0) - return ret; - - return count; -} - -static DEVICE_ATTR(operating_mode, S_IWUSR | S_IRUGO, - tsl2550_show_operating_mode, tsl2550_store_operating_mode); - -static ssize_t __tsl2550_show_lux(struct i2c_client *client, char *buf) -{ - u8 ch0, ch1; - int ret; - - ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC0); - if (ret < 0) - return ret; - ch0 = ret; - - mdelay(1); - - ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC1); - if (ret < 0) - return ret; - ch1 = ret; - - /* Do the job */ - ret = tsl2550_calculate_lux(ch0, ch1); - if (ret < 0) - return ret; - - return sprintf(buf, "%d\n", ret); -} - -static ssize_t tsl2550_show_lux1_input(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct tsl2550_data *data = i2c_get_clientdata(client); - int ret; - - /* No LUX data if not operational */ - if (!data->power_state) - return -EBUSY; - - mutex_lock(&data->update_lock); - ret = __tsl2550_show_lux(client, buf); - mutex_unlock(&data->update_lock); - - return ret; -} - -static DEVICE_ATTR(lux1_input, S_IRUGO, - tsl2550_show_lux1_input, NULL); - -static struct attribute *tsl2550_attributes[] = { - &dev_attr_power_state.attr, - &dev_attr_operating_mode.attr, - &dev_attr_lux1_input.attr, - NULL -}; - -static const struct attribute_group tsl2550_attr_group = { - .attrs = tsl2550_attributes, -}; - -/* - * Initialization function - */ - -static int tsl2550_init_client(struct i2c_client *client) -{ - struct tsl2550_data *data = i2c_get_clientdata(client); - int err; - - /* - * Probe the chip. To do so we try to power up the device and then to - * read back the 0x03 code - */ - err = i2c_smbus_write_byte(client, TSL2550_POWER_UP); - if (err < 0) - return err; - mdelay(1); - if (i2c_smbus_read_byte(client) != TSL2550_POWER_UP) - return -ENODEV; - data->power_state = 1; - - /* Set the default operating mode */ - err = i2c_smbus_write_byte(client, - TSL2550_MODE_RANGE[data->operating_mode]); - if (err < 0) - return err; - - return 0; -} - -/* - * I2C init/probing/exit functions - */ - -static struct i2c_driver tsl2550_driver; -static int __devinit tsl2550_probe(struct i2c_client *client) -{ - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); - struct tsl2550_data *data; - int *opmode, err = 0; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) { - err = -EIO; - goto exit; - } - - data = kzalloc(sizeof(struct tsl2550_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - data->client = client; - i2c_set_clientdata(client, data); - - /* Check platform data */ - opmode = client->dev.platform_data; - if (opmode) { - if (*opmode < 0 || *opmode > 1) { - dev_err(&client->dev, "invalid operating_mode (%d)\n", - *opmode); - err = -EINVAL; - goto exit_kfree; - } - data->operating_mode = *opmode; - } else - data->operating_mode = 0; /* default mode is standard */ - dev_info(&client->dev, "%s operating mode\n", - data->operating_mode ? "extended" : "standard"); - - mutex_init(&data->update_lock); - - /* Initialize the TSL2550 chip */ - err = tsl2550_init_client(client); - if (err) - goto exit_kfree; - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &tsl2550_attr_group); - if (err) - goto exit_kfree; - - dev_info(&client->dev, "support ver. %s enabled\n", DRIVER_VERSION); - - return 0; - -exit_kfree: - kfree(data); -exit: - return err; -} - -static int __devexit tsl2550_remove(struct i2c_client *client) -{ - sysfs_remove_group(&client->dev.kobj, &tsl2550_attr_group); - - /* Power down the device */ - tsl2550_set_power_state(client, 0); - - kfree(i2c_get_clientdata(client)); - - return 0; -} - -#ifdef CONFIG_PM - -static int tsl2550_suspend(struct i2c_client *client, pm_message_t mesg) -{ - return tsl2550_set_power_state(client, 0); -} - -static int tsl2550_resume(struct i2c_client *client) -{ - return tsl2550_set_power_state(client, 1); -} - -#else - -#define tsl2550_suspend NULL -#define tsl2550_resume NULL - -#endif /* CONFIG_PM */ - -static struct i2c_driver tsl2550_driver = { - .driver = { - .name = TSL2550_DRV_NAME, - .owner = THIS_MODULE, - }, - .suspend = tsl2550_suspend, - .resume = tsl2550_resume, - .probe = tsl2550_probe, - .remove = __devexit_p(tsl2550_remove), -}; - -static int __init tsl2550_init(void) -{ - return i2c_add_driver(&tsl2550_driver); -} - -static void __exit tsl2550_exit(void) -{ - i2c_del_driver(&tsl2550_driver); -} - -MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); -MODULE_DESCRIPTION("TSL2550 ambient light sensor driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRIVER_VERSION); - -module_init(tsl2550_init); -module_exit(tsl2550_exit); |
