Merge "NFC: Implement multiple NFC clock source and patch version"
diff --git a/Documentation/devicetree/bindings/nfc/nfc-nci.txt b/Documentation/devicetree/bindings/nfc/nfc-nci.txt
index f70d90f..cdd1e68 100644
--- a/Documentation/devicetree/bindings/nfc/nfc-nci.txt
+++ b/Documentation/devicetree/bindings/nfc/nfc-nci.txt
@@ -8,6 +8,8 @@
- reg: NCI i2c slave address.
- qcom,dis-gpio: specific gpio for hardware reset.
- qcom,irq-gpio: specific gpio for read interrupt.
+- qcom,clk-src: nfc clock source ("BBCLK2", "RFCLK3", "GPCLK", ...)
+- qcom,clk-en-gpio: msm gpio clock,used ony if clock source is msm gpio
- interrupt-parent: Should be phandle for the interrupt controller
that services interrupts for this device.
- interrupts: should contain the NFC interrupt. NFC has one read interrupt.
@@ -21,6 +23,8 @@
reg = <0x0e>;
qcom,irq-gpio = <&msmgpio 21 0x00>;
qcom,dis-gpio = <&msmgpio 20 0x00>;
+ qcom,clk-src = "BBCLK2";
+ qcom,clk-en-gpio = <&msmgpio 0 0x00>;
interrupt-parent = <&msmgpio>;
interrupts = <21 0>;
qcom,clk-gpio = <&pm8226_gpios 3 0>;
diff --git a/arch/arm/boot/dts/msm8226-mtp.dtsi b/arch/arm/boot/dts/msm8226-mtp.dtsi
index 318d4fc..5d98271 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-mtp.dtsi
@@ -40,6 +40,8 @@
reg = <0x0e>;
qcom,irq-gpio = <&msmgpio 21 0x00>;
qcom,dis-gpio = <&msmgpio 20 0x00>;
+ qcom,clk-src = "BBCLK2";
+ qcom,clk-en-gpio = <&msmgpio 0 0x00>;
interrupt-parent = <&msmgpio>;
interrupts = <21 0>;
qcom,clk-gpio = <&pm8226_gpios 3 0>;
diff --git a/drivers/nfc/nfc-nci.c b/drivers/nfc/nfc-nci.c
index 87c7c30..67b057c 100644
--- a/drivers/nfc/nfc-nci.c
+++ b/drivers/nfc/nfc-nci.c
@@ -26,12 +26,15 @@
#include <linux/of_device.h>
#include <linux/regulator/consumer.h>
#include "nfc-nci.h"
+#include <mach/gpiomux.h>
struct qca199x_platform_data {
unsigned int irq_gpio;
unsigned int dis_gpio;
unsigned int ven_gpio;
unsigned int reg;
+ const char *clk_src;
+ unsigned int clk_src_gpio;
};
static struct of_device_id msm_match_table[] = {
@@ -397,7 +400,9 @@
gpio_set_value(qca199x_dev->dis_gpio, 1);
usleep(1000);
} else if (arg == 2) {
+ mutex_lock(&qca199x_dev->read_mutex);
r = nfcc_initialise(qca199x_dev->client, 0xE);
+ mutex_unlock(&qca199x_dev->read_mutex);
if (r) {
dev_err(&qca199x_dev->client->dev,
"nfc-nci probe: request nfcc initialise failed\n");
@@ -419,7 +424,6 @@
return r;
}
-
/*
* Inside nfc_ioctl_nfcc_mode
*
@@ -477,6 +481,64 @@
}
/*
+ * Inside nfc_ioctl_nfcc_version
+ *
+ * @brief nfc_ioctl_nfcc_version
+ *
+ *
+ */
+int nfc_ioctl_nfcc_version(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ int r = 0;
+ unsigned short slave_addr = 0xE;
+ unsigned short curr_addr;
+
+ unsigned char raw_chip_version_addr = 0x00;
+ unsigned char raw_chip_rev_id_addr = 0x9C;
+ unsigned char raw_chip_version = 0xFF;
+
+ struct qca199x_dev *qca199x_dev = filp->private_data;
+ struct qca199x_platform_data *platform_data;
+
+ platform_data = qca199x_dev->client->dev.platform_data;
+
+ if (arg == 0) {
+ curr_addr = qca199x_dev->client->addr;
+ qca199x_dev->client->addr = slave_addr;
+ r = nfc_i2c_write(qca199x_dev->client,
+ &raw_chip_version_addr, 1);
+ if (r < 0)
+ goto invalid_wr;
+ usleep(10);
+ r = i2c_master_recv(qca199x_dev->client, &raw_chip_version, 1);
+ /* Restore original NFCC slave I2C address */
+ qca199x_dev->client->addr = curr_addr;
+ }
+ if (arg == 1) {
+ curr_addr = qca199x_dev->client->addr;
+ qca199x_dev->client->addr = slave_addr;
+ r = nfc_i2c_write(qca199x_dev->client,
+ &raw_chip_rev_id_addr, 1);
+ if (r < 0)
+ goto invalid_wr;
+ usleep(10);
+ r = i2c_master_recv(qca199x_dev->client, &raw_chip_version, 1);
+ /* Restore original NFCC slave I2C address */
+ qca199x_dev->client->addr = curr_addr;
+ }
+
+ return raw_chip_version;
+invalid_wr:
+ raw_chip_version = 0xFF;
+ dev_err(&qca199x_dev->client->dev,
+ "\nNFCC_INVALID_CHIP_VERSION = %d\n", raw_chip_version);
+ return raw_chip_version;
+}
+
+
+
+/*
* Inside nfc_ioctl_kernel_logging
*
* @brief nfc_ioctl_kernel_logging
@@ -522,6 +584,9 @@
case NFCC_MODE:
nfc_ioctl_nfcc_mode(pfile, cmd, arg);
break;
+ case NFCC_VERSION:
+ r = nfc_ioctl_nfcc_version(pfile, cmd, arg);
+ break;
case NFC_KERNEL_LOGGING_MODE:
nfc_ioctl_kernel_logging(arg, pfile);
break;
@@ -690,6 +755,14 @@
if ((!gpio_is_valid(pdata->irq_gpio)))
return -EINVAL;
+ r = of_property_read_string(np, "qcom,clk-src", &pdata->clk_src);
+
+ if (!strcmp(pdata->clk_src, "GPCLK"))
+ pdata->clk_src_gpio = of_get_named_gpio(np,
+ "qcom,clk-en-gpio", 0);
+
+ if (r)
+ return -EINVAL;
return r;
}
@@ -698,7 +771,7 @@
{
int r = 0;
int irqn = 0;
- struct clk *nfc_clk;
+ struct clk *nfc_clk = NULL;
struct device_node *node = client->dev.of_node;
struct qca199x_platform_data *platform_data;
struct qca199x_dev *qca199x_dev;
@@ -769,7 +842,7 @@
dev_err(&client->dev,
"NFC: unable to request gpio [%d]\n",
platform_data->dis_gpio);
- goto err_dis_gpio;
+ goto err_free_dev;
}
r = gpio_direction_output(platform_data->dis_gpio, 1);
if (r) {
@@ -785,15 +858,28 @@
gpio_set_value(platform_data->dis_gpio, 1);/* HPD */
msleep(20);
gpio_set_value(platform_data->dis_gpio, 0);/* ULPM */
-
- nfc_clk = clk_get(&client->dev, "ref_clk");
-
- if (nfc_clk == NULL)
- goto err_dis_gpio;
-
+ if (!strcmp(platform_data->clk_src, "BBCLK2")) {
+ nfc_clk = clk_get(&client->dev, "ref_clk");
+ if (nfc_clk == NULL)
+ goto err_dis_gpio;
+ } else if (!strcmp(platform_data->clk_src, "RFCLK3")) {
+ nfc_clk = clk_get(&client->dev, "ref_clk_rf");
+ if (nfc_clk == NULL)
+ goto err_dis_gpio;
+ } else if (!strcmp(platform_data->clk_src, "GPCLK")) {
+ if (gpio_is_valid(platform_data->clk_src_gpio)) {
+ nfc_clk = clk_get(&client->dev, "core_clk");
+ if (nfc_clk == NULL)
+ goto err_dis_gpio;
+ } else {
+ goto err_dis_gpio;
+ }
+ } else {
+ nfc_clk = NULL;
+ }
r = clk_prepare_enable(nfc_clk);
if (r)
- goto err_dis_gpio;
+ goto err_clk;
platform_data->ven_gpio = of_get_named_gpio(node,
"qcom,clk-gpio", 0);
@@ -813,11 +899,9 @@
platform_data->ven_gpio);
goto err_ven_gpio;
}
-
} else {
-
dev_err(&client->dev, "ven gpio not provided\n");
- goto err_dis_gpio;
+ goto err_clk;
}
qca199x_dev->dis_gpio = platform_data->dis_gpio;
qca199x_dev->irq_gpio = platform_data->irq_gpio;
@@ -871,7 +955,18 @@
mutex_destroy(&qca199x_dev->read_mutex);
err_ven_gpio:
gpio_free(platform_data->ven_gpio);
+err_clk:
+ clk_disable_unprepare(nfc_clk);
err_dis_gpio:
+ r = gpio_direction_input(platform_data->dis_gpio);
+ if (r)
+ dev_err(&client->dev, "nfc-nci probe: Unable to set direction\n");
+ if (!strcmp(platform_data->clk_src, "GPCLK")) {
+ r = gpio_direction_input(platform_data->clk_src_gpio);
+ if (r)
+ dev_err(&client->dev, "nfc-nci probe: Unable to set direction\n");
+ gpio_free(platform_data->clk_src_gpio);
+ }
gpio_free(platform_data->dis_gpio);
err_irq:
gpio_free(platform_data->irq_gpio);
diff --git a/drivers/nfc/nfc-nci.h b/drivers/nfc/nfc-nci.h
index c3cabc2..81f2521 100644
--- a/drivers/nfc/nfc-nci.h
+++ b/drivers/nfc/nfc-nci.h
@@ -49,26 +49,27 @@
enum ehandler_mode handle_flavour;
} tdevicemode;
-#define NFC_DRIVER_NAME "nfc-nci"
+#define NFC_DRIVER_NAME "nfc-nci"
#define NFC_I2C_DRIVER_NAME "NCI NFC I2C Interface",
-#define NCI_I2C_SLAVE (0x2C)
-#define NFC_I2C_BUS 3 /* 6, 10, 4, 5 */
-#define NFC_SET_PWR _IOW(0xE9, 0x01, unsigned int)
-#define NFCC_MODE _IOW(0xE9, 0x02, unsigned int)
+#define NCI_I2C_SLAVE (0x2C)
+#define NFC_I2C_BUS 3 /* 6, 10, 4, 5 */
+#define NFC_SET_PWR _IOW(0xE9, 0x01, unsigned int)
+#define NFCC_MODE _IOW(0xE9, 0x02, unsigned int)
#define NFC_KERNEL_LOGGING_MODE _IOW(0xE9, 0x03, unsigned int)
-#define SET_RX_BLOCK _IOW(0xE9, 0x04, unsigned int)
+#define SET_RX_BLOCK _IOW(0xE9, 0x04, unsigned int)
#define SET_EMULATOR_TEST_POINT _IOW(0xE9, 0x05, unsigned int)
+#define NFCC_VERSION _IOW(0xE9, 0x08, unsigned int)
-#define NFC_MAX_I2C_TRANSFER (0x0400)
-#define NFC_MSG_MAX_SIZE (0x21)
+#define NFC_MAX_I2C_TRANSFER (0x0400)
+#define NFC_MSG_MAX_SIZE (0x21)
#define NFC_RX_BUFFER_CNT_START (0x0)
-#define NFC_RX_BUFFER_BLOCK_SIZE (0x120) /* Bytes per Block */
+#define NFC_RX_BUFFER_BLOCK_SIZE (0x120) /* Bytes per Block */
#define NFC_RX_BUFFER_PAGE_SIZE (0x1000) /* Page size Bytes */
#define NFC_RX_BUFFER_PAGES (0x8)
-#define NFC_RX_ORDER_FREE_PAGES (0x3) /* Free 8 Pages */
+#define NFC_RX_ORDER_FREE_PAGES (0x3) /* Free 8 Pages */
/* The total no. of Blocks */
#define NFC_RX_BUFFER_CNT_LIMIT (unsigned short)( \
@@ -86,10 +87,10 @@
/** Power Management Related **/
-#define NFCC_WAKE (0x01)
-#define NFCC_SLEEP (0x00)
+#define NFCC_WAKE (0x01)
+#define NFCC_SLEEP (0x00)
-#define XTAL_CLOCK (0X00)
+#define XTAL_CLOCK (0X00)
#define REFERENCE_CLOCK (0X01)
/* LDO Trim Settings */
@@ -122,8 +123,8 @@
#define LOCALBIASXTAL (0x20)
#define BIAS2X_FORCE (0x10)
#define BIAS2X (0x08)
-#define LBIAS2X (0x04)
-#define SMALLRF (0x02)
+#define LBIAS2X (0x04)
+#define SMALLRF (0x02)
#define SMALLRBIAS (0x01)
/* Select as appropriate */