]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - drivers/misc/a2220.c
misc: ti-st: Adding IORESOURCE_IRQ_OPTIONAL case
[linux-2.6.git] / drivers / misc / a2220.c
index 6928b1078b2f4192aa21f9c28d2e23d52f442502..46d3f27ffd88276c8ac27ccc8b385b4fe1e7759d 100644 (file)
@@ -2,6 +2,8 @@
  *
  * Copyright (C) 2009 HTC Corporation.
  *
+ * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
+ *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
  * may be copied, distributed, and modified under those terms.
@@ -201,7 +203,10 @@ static ssize_t a2220_hw_reset(struct a2220img *img)
 
        while (retry--) {
                /* Reset A2220 chip */
-               gpio_set_value(pdata->gpio_a2220_reset, 0);
+               if (pdata->gpio_a2220_reset)
+                       gpio_set_value(pdata->gpio_a2220_reset, 0);
+               else
+                       gpio_set_value(VP_RESET, 1);
 
                /* Enable A2220 clock */
                if (control_a2220_clk)
@@ -209,7 +214,10 @@ static ssize_t a2220_hw_reset(struct a2220img *img)
                mdelay(1);
 
                /* Take out of reset */
-               gpio_set_value(pdata->gpio_a2220_reset, 1);
+               if (pdata->gpio_a2220_reset)
+                       gpio_set_value(pdata->gpio_a2220_reset, 1);
+               else
+                       gpio_set_value(VP_RESET, 0);
 
                msleep(50);     /* Delay before send I2C command */
 
@@ -297,13 +305,10 @@ static int hpt_longCmd_execute(unsigned char *i2c_cmds, int size)
 }
 #endif
 
-static ssize_t a2220_bootup_init(struct a2220img *pImg)
+static int a2220_set_boot_mode(void)
 {
-       struct a2220img *vp = pImg;
-       int rc, pass = 0;
-       int remaining;
+       int rc;
        int retry = RETRY_CNT;
-       unsigned char *index;
        char buf[2];
 
        mdelay(100);
@@ -327,19 +332,38 @@ static ssize_t a2220_bootup_init(struct a2220img *pImg)
                buf[1] = A2220_msg_BOOT & 0xff;
                rc = a2220_i2c_write(buf, 2);
                if (rc < 0) {
-                       printk(KERN_ERR "%s: set boot mode error (%d retries left)\n",
+                       printk(KERN_ERR "%s: write error (%d retries left)\n",
                               __func__, retry);
-                       continue;
+                       if (retry > 0)
+                               continue;
+                       else
+                               return rc;
                }
 
                mdelay(1);
                rc = a2220_i2c_read(buf, 1);
 
                if (rc < 0) {
-                       printk(KERN_ERR "%s: boot mode ack error (%d retries left)\n",
+                       printk(KERN_ERR "%s: ack error (%d retries left)\n",
                               __func__, retry);
                        continue;
                }
+       }
+
+       return rc;
+}
+
+static ssize_t a2220_bootup_init(struct a2220img *pImg)
+{
+       struct a2220img *vp = pImg;
+       int rc = 0, pass = 0;
+       int remaining;
+       int retry = RETRY_CNT;
+       unsigned char *index;
+
+       mdelay(10);
+
+       while (retry--) {
                remaining = vp->img_size / 32;
                index = vp->buf;
                pr_info("%s: starting to load image (%d passes)...\n",
@@ -377,11 +401,11 @@ static ssize_t a2220_bootup_init(struct a2220img *pImg)
        if (rc < 0)
                printk(KERN_ERR "%s: suspend error\n", __func__);
 
-       rc = execute_cmdmsg(A100_msg_PortA_C_PASS);
+       rc = execute_cmdmsg(A100_msg_PortD_C_PASS);
        if (rc < 0)
                printk(KERN_ERR "%s: suspend error\n", __func__);
 
-       rc = execute_cmdmsg(A100_msg_PortA_C_PASS);
+       rc = execute_cmdmsg(A100_msg_PortB_A_PASS);
        if (rc < 0)
                printk(KERN_ERR "%s: suspend error\n", __func__);
 
@@ -1051,6 +1075,10 @@ EXPORT_SYMBOL(a2220_ioctl2);
 int a2220_port_path_change(unsigned int msg)
 {
        switch (msg) {
+       case A100_msg_PortC_D_PASS:
+       case A100_msg_PortD_C_PASS:
+       case A100_msg_PortB_A_PASS:
+       case A100_msg_PortA_B_PASS:
        case A100_msg_PortC_A_PASS:
        case A100_msg_PortA_C_PASS:
                break;
@@ -1058,8 +1086,8 @@ int a2220_port_path_change(unsigned int msg)
                printk(KERN_ERR "Not support [0x%X] for port change\n", msg);
                return -EINVAL;
        }
-       /*Default Set to Slave Mode configuration
-       (PORTA -> PORTC in pass through) */
+       /* Default set to PORTD -> PORTC and
+          PORTB -> PORTA in pass through) */
        /* return execute_cmdmsg(msg); */
        return 0;
 }
@@ -1088,13 +1116,13 @@ static int a2220_probe(struct i2c_client *client,
        extern3_clk = clk_get_sys("extern3", NULL);
        if (IS_ERR(extern3_clk)) {
                printk(KERN_ERR "%s: Can't retrieve extern3\n", __func__);
-               goto err_alloc_data_failed;
+               goto err_clk_get_failed;
        }
 
        ret = clk_enable(extern3_clk);
        if (ret) {
                printk(KERN_ERR "Can't enable clk extern3");
-               goto err_alloc_data_failed;
+               goto err_clk_enable_failed;
        }
 
        control_a2220_clk = 1;
@@ -1251,18 +1279,20 @@ static int a2220_probe(struct i2c_client *client,
                }
        }
 
-       rc = gpio_request(pdata->gpio_a2220_reset, "a2220");
-       if (rc < 0) {
-               printk(KERN_ERR "%s: gpio request reset pin failed\n",
+       if (pdata->gpio_a2220_reset) {
+               rc = gpio_request(pdata->gpio_a2220_reset, "a2220");
+               if (rc < 0) {
+                       printk(KERN_ERR "%s: gpio request reset pin failed\n",
                        __func__);
-               goto err_free_gpio;
-       }
+                       goto err_free_gpio;
+               }
 
-       rc = gpio_direction_output(pdata->gpio_a2220_reset, 1);
-       if (rc < 0) {
-               printk(KERN_ERR "%s: request reset gpio direction failed\n",
+               rc = gpio_direction_output(pdata->gpio_a2220_reset, 1);
+               if (rc < 0) {
+                       printk(KERN_ERR "%s: request reset gpio direction failed\n",
                        __func__);
-               goto err_free_gpio_all;
+                       goto err_free_gpio_all;
+               }
        }
 
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
@@ -1295,7 +1325,8 @@ static int a2220_probe(struct i2c_client *client,
 #endif
        }
 
-       gpio_set_value(pdata->gpio_a2220_reset, 1);
+       if (pdata->gpio_a2220_reset)
+               gpio_set_value(pdata->gpio_a2220_reset, 1);
 
        if (pdata->gpio_a2220_audience_chip_sel)
                gpio_set_value(pdata->gpio_a2220_audience_chip_sel, 1);
@@ -1306,13 +1337,21 @@ static int a2220_probe(struct i2c_client *client,
                goto err_free_gpio_all;
        }
 
+       /* send boot msg */
+       rc = a2220_set_boot_mode();
+       if (rc < 0) {
+               printk(KERN_ERR "%s: failed %d\n", __func__, rc);
+               goto err_free_gpio_all;
+       }
+
        /* A2220 firmware download start .. */
        a2220_ioctl2(A2220_BOOTUP_INIT, 0);
 
        return 0;
 
  err_free_gpio_all:
-       gpio_free(pdata->gpio_a2220_reset);
+       if (pdata->gpio_a2220_reset)
+               gpio_free(pdata->gpio_a2220_reset);
  err_free_gpio:
        if (pdata->gpio_a2220_wakeup) {
 #ifdef CONFIG_USA_MODEL_SGH_T989
@@ -1335,9 +1374,13 @@ static int a2220_probe(struct i2c_client *client,
        if (pdata->gpio_a2220_micsel)
                gpio_free(pdata->gpio_a2220_micsel);
  err_free_gpio_clk:
-       if (control_a2220_clk)
+       if (pdata->gpio_a2220_clk)
                gpio_free(pdata->gpio_a2220_clk);
  err_alloc_data_failed:
+       clk_disable(extern3_clk);
+ err_clk_enable_failed:
+       clk_put(extern3_clk);
+ err_clk_get_failed:
 
        return rc;
 }