]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/i2c/chips/twl4030_core.c
I2C: TWL4030: Move twl4030's headers under include/linux/i2c/
[linux-2.6-omap-h63xx.git] / drivers / i2c / chips / twl4030_core.c
index 31340642ce182051b74ff671011ec9e55af9cf10..4f0f4652a1e8a0be6092ff053f0592e87897f3be 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/kthread.h>
 
 #include <linux/i2c.h>
+#include <linux/i2c/twl4030.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/device.h>
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
 
-#include <asm/arch/twl4030.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/mux.h>
 
-/**** Macro Definitions */
+#define DRIVER_NAME                    "twl4030"
+
+/* Macro Definitions */
 #define TWL_CLIENT_STRING              "TWL4030-ID"
 #define TWL_CLIENT_USED                        1
 #define TWL_CLIENT_FREE                        0
@@ -58,9 +60,9 @@
 #define FREE                           0
 #define USED                           1
 
-/** Primary Interrupt Handler on TWL4030 Registers */
+/* Primary Interrupt Handler on TWL4030 Registers */
 
-/**** Register Definitions */
+/* Register Definitions */
 
 #define REG_PIH_ISR_P1                 (0x1)
 #define REG_PIH_ISR_P2                 (0x2)
 #define TWL4030_BASEADD_BACKUP         0x0014
 #define TWL4030_BASEADD_INT            0x002E
 #define TWL4030_BASEADD_PM_MASTER      0x0036
-#define TWL4030_BASEADD_PM_RECIEVER    0x005B
+#define TWL4030_BASEADD_PM_RECEIVER    0x005B
 #define TWL4030_BASEADD_RTC            0x001C
 #define TWL4030_BASEADD_SECURED_REG    0x0000
 
 /* on I2C-1 for 2430SDP */
 #define CONFIG_I2C_TWL4030_ID          1
 
-/**** Helper functions */
+/* Helper functions */
 static int
 twl4030_detect_client(struct i2c_adapter *adapter, unsigned char sid);
 static int twl4030_attach_adapter(struct i2c_adapter *adapter);
@@ -139,9 +141,10 @@ static void do_twl4030_irq(unsigned int irq, irq_desc_t *desc);
 
 static void twl_init_irq(void);
 
-/**** Data Structures */
+/* Data Structures */
 /* To have info on T2 IRQ substem activated or not */
 static unsigned char twl_irq_used = FREE;
+static struct completion irq_event;
 
 /* Structure to define on TWL4030 Slave ID */
 struct twl4030_client {
@@ -185,7 +188,7 @@ static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = {
        { TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_BACKUP },
        { TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_INT },
        { TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_PM_MASTER },
-       { TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_PM_RECIEVER },
+       { TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_PM_RECEIVER },
        { TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_RTC },
        { TWL4030_SLAVENUM_NUM3, TWL4030_BASEADD_SECURED_REG },
 };
@@ -257,16 +260,15 @@ int twl4030_i2c_write(u8 mod_no, u8 * value, u8 reg, u8 num_bytes)
        struct i2c_msg *msg;
 
        if (unlikely(mod_no > TWL4030_MODULE_LAST)) {
-               printk(KERN_ERR "TWL4030: Invalid module Number\n");
+               pr_err("Invalid module Number\n");
                return -EPERM;
        }
        sid = twl4030_map[mod_no].sid;
        client = &(twl4030_modules[sid]);
 
        if (unlikely(client->inuse != TWL_CLIENT_USED)) {
-               printk(KERN_ERR
-                       "TWL4030: I2C Client[%d] is not initialized[%d]\n",
-                       sid, __LINE__);
+               pr_err("I2C Client[%d] is not initialized[%d]\n",
+                      sid, __LINE__);
                return -EPERM;
        }
        down(&(client->xfer_lock));
@@ -307,17 +309,17 @@ int twl4030_i2c_read(u8 mod_no, u8 * value, u8 reg, u8 num_bytes)
        int sid;
        struct twl4030_client *client;
        struct i2c_msg *msg;
+
        if (unlikely(mod_no > TWL4030_MODULE_LAST)) {
-               printk(KERN_ERR "TWL4030: Invalid module Number\n");
+               pr_err("Invalid module Number\n");
                return -EPERM;
        }
        sid = twl4030_map[mod_no].sid;
        client = &(twl4030_modules[sid]);
 
        if (unlikely(client->inuse != TWL_CLIENT_USED)) {
-               printk(KERN_ERR
-                       "TWL4030: I2C Client[%d] is not initialized[%d]\n",
-                       sid, __LINE__);
+               pr_err("I2C Client[%d] is not initialized[%d]\n", sid,
+                      __LINE__);
                return -EPERM;
        }
        down(&(client->xfer_lock));
@@ -325,6 +327,7 @@ int twl4030_i2c_read(u8 mod_no, u8 * value, u8 reg, u8 num_bytes)
        msg = &(client->xfer_msg[0]);
        msg->addr = client->address;
        msg->len = 1;
+       msg->flags = 0; /* Read the register value */
        val = twl4030_map[mod_no].base + reg;
        msg->buf = &val;
        /* [MSG2] fill the data rx buffer */
@@ -353,13 +356,12 @@ int twl4030_i2c_read(u8 mod_no, u8 * value, u8 reg, u8 num_bytes)
  */
 int twl4030_i2c_write_u8(u8 mod_no, u8 value, u8 reg)
 {
-       int ret;
+
        /* 2 bytes offset 1 contains the data offset 0 is used by i2c_write */
        u8 temp_buffer[2] = { 0 };
        /* offset 1 contains the data */
        temp_buffer[1] = value;
-       ret = twl4030_i2c_write(mod_no, temp_buffer, reg, 1);
-       return ret;
+       return twl4030_i2c_write(mod_no, temp_buffer, reg, 1);
 }
 
 /**
@@ -373,12 +375,10 @@ int twl4030_i2c_write_u8(u8 mod_no, u8 value, u8 reg)
  */
 int twl4030_i2c_read_u8(u8 mod_no, u8 * value, u8 reg)
 {
-       int ret = 0;
-       ret = twl4030_i2c_read(mod_no, value, reg, 1);
-       return ret;
+       return twl4030_i2c_read(mod_no, value, reg, 1);
 }
 
-/**** Helper Functions */
+/* Helper Functions */
 
 /*
  * do_twl4030_module_irq() is the desc->handle method for each of the twl4030
@@ -393,7 +393,7 @@ static void do_twl4030_module_irq(unsigned int irq, irq_desc_t *desc)
        /*
         * Earlier this was desc->triggered = 1;
         */
-       desc->status = IRQ_INPROGRESS;
+       desc->status |= IRQ_LEVEL;
 
        /*
         * The desc->handle method would normally call the desc->chip->ack
@@ -453,11 +453,16 @@ static int twl4030_irq_thread(void *data)
        static unsigned i2c_errors;
        const static unsigned max_i2c_errors = 100;
 
+       daemonize("twl4030-irq");
+       current->flags |= PF_NOFREEZE;
+
        while (!kthread_should_stop()) {
                int ret;
                int module_irq;
                u8 pih_isr;
 
+               wait_for_completion_interruptible(&irq_event);
+
                ret = twl4030_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr,
                                          REG_PIH_ISR_P1);
                if (ret) {
@@ -485,16 +490,9 @@ static int twl4030_irq_thread(void *data)
                        }
                }
 
-               local_irq_disable();
-
-               set_current_state(TASK_INTERRUPTIBLE);
                desc->chip->unmask(irq);
-
-               local_irq_enable();
-
-               schedule();
        }
-       set_current_state(TASK_RUNNING);
+
        return 0;
 }
 
@@ -510,12 +508,11 @@ static int twl4030_irq_thread(void *data)
 static void do_twl4030_irq(unsigned int irq, irq_desc_t *desc)
 {
        const unsigned int cpu = smp_processor_id();
-       struct task_struct *thread = (struct task_struct *)desc->chip_data;
 
        /*
         * Earlier this was desc->triggered = 1;
         */
-       desc->status = IRQ_INPROGRESS;
+       desc->status |= IRQ_LEVEL;
 
        /*
         * Acknowledge, clear _AND_ disable the interrupt.
@@ -525,8 +522,7 @@ static void do_twl4030_irq(unsigned int irq, irq_desc_t *desc)
        if (!desc->depth) {
                kstat_cpu(cpu).irqs[irq]++;
 
-               if (thread && thread->state != TASK_RUNNING)
-                       wake_up_process(thread);
+               complete(&irq_event);
        }
 }
 
@@ -535,24 +531,21 @@ static int twl4030_detect_client(struct i2c_adapter *adapter, unsigned char sid)
 {
        int err = 0;
        struct twl4030_client *client;
+
        if (unlikely(sid >= TWL4030_NUM_SLAVES)) {
-               printk(KERN_ERR "TWL4030: sid[%d] >MOD_LAST[%d]\n", sid,
-                               TWL4030_NUM_SLAVES);
+               pr_err("sid[%d] > MOD_LAST[%d]\n", sid, TWL4030_NUM_SLAVES);
                return -EPERM;
        }
 
        /* Check basic functionality */
        if (!(err = i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA |
                                                I2C_FUNC_SMBUS_WRITE_BYTE))) {
-               printk(KERN_WARNING
-                       "TWL4030: SlaveID=%d functionality check failed\n", sid);
+               pr_err("SlaveID=%d functionality check failed\n", sid);
                return err;
        }
        client = &(twl4030_modules[sid]);
        if (unlikely(client->inuse)) {
-               printk(KERN_ERR "TWL4030: Client is already in Use.....\n");
-               printk("%s[ID=0x%x] NOT attached to I2c Adapter %s\n",
-                       client->client_name, client->address, adapter->name);
+               pr_err("Client %s is already in use\n", client->client_name);
                return -EPERM;
        }
 
@@ -564,17 +557,18 @@ static int twl4030_detect_client(struct i2c_adapter *adapter, unsigned char sid)
 
        memcpy(&(client->client.name), client->client_name,
                        sizeof(TWL_CLIENT_STRING) + 1);
-       printk("TWL4030: TRY attach Slave %s on Adapter %s[%d][%x]\n",
-                               client->client_name, adapter->name, err, err);
-       if ((err = i2c_attach_client(&(client->client))))
-               printk(KERN_WARNING
-                       "TWL4030: Couldn't attach Slave %s on Adapter "
-                       "%s[%d][%x]\n",
-                       client->client_name, adapter->name, err, err);
-       else {
+
+       pr_info("TWL4030: TRY attach Slave %s on Adapter %s [%x]\n",
+                               client->client_name, adapter->name, err);
+
+       if ((err = i2c_attach_client(&(client->client)))) {
+               pr_err("Couldn't attach Slave %s on Adapter"
+                      "%s [%x]\n", client->client_name, adapter->name, err);
+       else {
                client->inuse = TWL_CLIENT_USED;
                init_MUTEX(&client->xfer_lock);
        }
+
        return err;
 }
 
@@ -584,6 +578,7 @@ static int twl4030_attach_adapter(struct i2c_adapter *adapter)
        int i;
        int ret = 0;
        static int twl_i2c_adapter = 1;
+
        for (i = 0; i < TWL4030_NUM_SLAVES; i++) {
                /* Check if I need to hook on to this adapter or not */
                if (twl4030_modules[i].adapter_index == twl_i2c_adapter) {
@@ -605,9 +600,7 @@ static int twl4030_attach_adapter(struct i2c_adapter *adapter)
        return 0;
 
 free_client:
-       printk(KERN_ERR
-               "TWL4030: TWL_CLIENT(Idx=%d] REGISTRATION FAILED=%d[0x%x]\n", i,
-                       ret, ret);
+       pr_err("TWL_CLIENT(Idx=%d] registration failed[0x%x]\n",i,ret);
 
        /* ignore current slave..it never got registered */
        i--;
@@ -625,8 +618,7 @@ static int twl4030_detach_client(struct i2c_client *iclient)
 {
        int err;
        if ((err = i2c_detach_client(iclient))) {
-               printk(KERN_ERR
-                               "TWL4030: Client deregistration failed, client not detached.\n");
+               pr_err("Client detach failed\n");
                return err;
        }
        return 0;
@@ -636,11 +628,12 @@ struct task_struct *start_twl4030_irq_thread(int irq)
 {
        struct task_struct *thread;
 
-       thread = kthread_create(twl4030_irq_thread, (void *)irq,
-                               "twl4030 irq %d", irq);
+       init_completion(&irq_event);
+       thread = kthread_run(twl4030_irq_thread, (void *)irq,
+                            "twl4030 irq %d", irq);
        if (!thread)
-               printk(KERN_ERR "%s: could not create twl4030 irq %d thread!\n",
-                       __FUNCTION__, irq);
+               pr_err("%s: could not create twl4030 irq %d thread!\n",
+                      __FUNCTION__, irq);
 
        return thread;
 }
@@ -652,6 +645,7 @@ struct task_struct *start_twl4030_irq_thread(int irq)
 static int protect_pm_master(void)
 {
        int e = 0;
+
        e = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_LOCK,
                        R_PROTECT_KEY);
        return e;
@@ -660,6 +654,7 @@ static int protect_pm_master(void)
 static int unprotect_pm_master(void)
 {
        int e = 0;
+
        e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK1,
                        R_PROTECT_KEY);
        e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK2,
@@ -667,7 +662,7 @@ static int unprotect_pm_master(void)
        return e;
 }
 
-int power_companion_init(void)
+static int power_companion_init(void)
 {
        struct clk *osc;
        u32 rate, ctrl = HFCLK_FREQ_26_MHZ;
@@ -694,9 +689,10 @@ int power_companion_init(void)
 
 static void twl_init_irq(void)
 {
-       int i = 0;
-       int res = 0;
-       int line = 0;
+       int     i = 0;
+       int     res = 0;
+       char    *msg = "Unable to register interrupt subsystem";
+
        /*
         * We end up with interrupts from other modules before
         * they get a chance to handle them...
@@ -704,44 +700,44 @@ static void twl_init_irq(void)
        /* PWR_ISR1 */
        res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x00);
        if (res < 0) {
-               line = __LINE__;
-               goto irq_exit_path;
+               pr_err("%s[%d][%d]\n", msg, res, __LINE__);
+               return;
        }
 
        /* PWR_ISR2 */
        res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x02);
        if (res < 0) {
-               line = __LINE__;
-               goto irq_exit_path;
+               pr_err("%s[%d][%d]\n", msg, res, __LINE__);
+               return;
        }
 
        /* PWR_IMR1 */
        res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x1);
        if (res < 0) {
-               line = __LINE__;
-               goto irq_exit_path;
+               pr_err("%s[%d][%d]\n", msg, res, __LINE__);
+               return;
        }
 
        /* PWR_IMR2 */
        res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x3);
        if (res < 0) {
-               line = __LINE__;
-               goto irq_exit_path;
+               pr_err("%s[%d][%d]\n", msg, res, __LINE__);
+               return;
        }
 
        /* Clear off any other pending interrupts on power */
        /* PWR_ISR1 */
        res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x00);
        if (res < 0) {
-               line = __LINE__;
-               goto irq_exit_path;
+               pr_err("%s[%d][%d]\n", msg, res, __LINE__);
+               return;
        }
 
        /* PWR_ISR2 */
        res = twl4030_i2c_write_u8(TWL4030_MODULE_INT, 0xFF, 0x02);
        if (res < 0) {
-               line = __LINE__;
-               goto irq_exit_path;
+               pr_err("%s[%d][%d]\n", msg, res, __LINE__);
+               return;
        }
        /* POWER HACK (END) */
        /* Slave address 0x4A */
@@ -749,52 +745,52 @@ static void twl_init_irq(void)
        /* BCIIMR1_1 */
        res = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x3);
        if (res < 0) {
-               line = __LINE__;
-               goto irq_exit_path;
+               pr_err("%s[%d][%d]\n", msg, res, __LINE__);
+               return;
        }
 
        /* BCIIMR1_2 */
        res = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x4);
        if (res < 0) {
-               line = __LINE__;
-               goto irq_exit_path;
+               pr_err("%s[%d][%d]\n", msg, res, __LINE__);
+               return;
        }
 
        /* BCIIMR2_1 */
        res = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x7);
        if (res < 0) {
-               line = __LINE__;
-               goto irq_exit_path;
+               pr_err("%s[%d][%d]\n", msg, res, __LINE__);
+               return;
        }
 
        /* BCIIMR2_2 */
        res = twl4030_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xFF, 0x8);
        if (res < 0) {
-               line = __LINE__;
-               goto irq_exit_path;
+               pr_err("%s[%d][%d]\n", msg, res, __LINE__);
+               return;
        }
 
        /* MAD C */
        /* MADC_IMR1 */
        res = twl4030_i2c_write_u8(TWL4030_MODULE_MADC, 0xFF, 0x62);
        if (res < 0) {
-               line = __LINE__;
-               goto irq_exit_path;
+               pr_err("%s[%d][%d]\n", msg, res, __LINE__);
+               return;
        }
 
        /* MADC_IMR2 */
        res = twl4030_i2c_write_u8(TWL4030_MODULE_MADC, 0xFF, 0x64);
        if (res < 0) {
-               line = __LINE__;
-               goto irq_exit_path;
+               pr_err("%s[%d][%d]\n", msg, res, __LINE__);
+               return;
        }
 
        /* key Pad */
        /* KEYPAD - IMR1 */
        res = twl4030_i2c_write_u8(TWL4030_MODULE_KEYPAD, 0xFF, (0x12));
        if (res < 0) {
-               line = __LINE__;
-               goto irq_exit_path;
+               pr_err("%s[%d][%d]\n", msg, res, __LINE__);
+               return;
        }
        {
                u8 clear;
@@ -806,51 +802,51 @@ static void twl_init_irq(void)
        /* KEYPAD - IMR2 */
        res = twl4030_i2c_write_u8(TWL4030_MODULE_KEYPAD, 0xFF, (0x14));
        if (res < 0) {
-               line = __LINE__;
-               goto irq_exit_path;
+               pr_err("%s[%d][%d]\n", msg, res, __LINE__);
+               return;
        }
 
        /* Slave address 0x49 */
        /* GPIO_IMR1A */
        res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x1C));
        if (res < 0) {
-               line = __LINE__;
-               goto irq_exit_path;
+               pr_err("%s[%d][%d]\n", msg, res, __LINE__);
+               return;
        }
 
        /* GPIO_IMR2A */
        res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x1D));
        if (res < 0) {
-               line = __LINE__;
-               goto irq_exit_path;
+               pr_err("%s[%d][%d]\n", msg, res, __LINE__);
+               return;
        }
 
        /* GPIO_IMR3A */
        res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x1E));
        if (res < 0) {
-               line = __LINE__;
-               goto irq_exit_path;
+               pr_err("%s[%d][%d]\n", msg, res, __LINE__);
+               return;
        }
 
        /* GPIO_IMR1B */
        res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x22));
        if (res < 0) {
-               line = __LINE__;
-               goto irq_exit_path;
+               pr_err("%s[%d][%d]\n", msg, res, __LINE__);
+               return;
        }
 
        /* GPIO_IMR2B */
        res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x23));
        if (res < 0) {
-               line = __LINE__;
-               goto irq_exit_path;
+               pr_err("%s[%d][%d]\n", msg, res, __LINE__);
+               return;
        }
 
        /* GPIO_IMR3B */
        res = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0xFF, (0x24));
        if (res < 0) {
-               line = __LINE__;
-               goto irq_exit_path;
+               pr_err("%s[%d][%d]\n", msg, res, __LINE__);
+               return;
        }
 
        /* install an irq handler for each of the PIH modules */
@@ -867,33 +863,27 @@ static void twl_init_irq(void)
 
        res = power_companion_init();
        if (res < 0) {
-               line = __LINE__;
-               goto irq_exit_path;
+               pr_err("%s[%d][%d]\n", msg, res, __LINE__);
        }
-
-irq_exit_path:
-       if (res)
-               printk(KERN_ERR
-                       "TWL4030: Unable to register interrupt "
-                       "subsystem[%d][%d]\n", res, line);
 }
 
 static int __init twl4030_init(void)
 {
        int res;
-       if ((res = i2c_register_driver(THIS_MODULE, &twl4030_driver))) {
+
+       if ((res = i2c_add_driver(&twl4030_driver))) {
                printk(KERN_ERR "TWL4030: Driver registration failed \n");
                return res;
        }
-       printk(KERN_INFO "TWL4030: Driver registration complete.\n");
-       return res;
+
+       pr_info(KERN_INFO "TWL4030: Driver registration complete.\n");
+
+       return 0;
 }
 
 static void __exit twl4030_exit(void)
 {
-       if (i2c_del_driver(&twl4030_driver))
-               printk(KERN_ERR
-                       "TWL4030: Driver remove failed, module not removed\n");
+       i2c_del_driver(&twl4030_driver);
        twl_irq_used = FREE;
 }