[PATCH] input:keyboard: add Cypress button driver for Intel Platform

2015-10-08 Thread Qipeng Zha
This driver is to support Cypress CY8CMBR3XXX family controller,
which is used as button input for Intel platforms.

Signed-off-by: Qipeng Zha <qipeng@intel.com>
---
 drivers/input/keyboard/Kconfig|   7 +
 drivers/input/keyboard/Makefile   |   1 +
 drivers/input/keyboard/cypress-keyboard.c | 278 ++
 3 files changed, 286 insertions(+)
 create mode 100644 drivers/input/keyboard/cypress-keyboard.c

diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index a89ba7c..f39f148 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -686,4 +686,11 @@ config KEYBOARD_CAP11XX
  To compile this driver as a module, choose M here: the
  module will be called cap11xx.
 
+config KEYBOARD_CYPRESS_BUTTON
+   tristate "Cypress Button"
+   depends on I2C
+   help
+ Say Y here to enable support for Cypress button for
+ Intel platforms.
+
 endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 4707678..5a73138 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -60,3 +60,4 @@ obj-$(CONFIG_KEYBOARD_TEGRA)  += tegra-kbc.o
 obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o
 obj-$(CONFIG_KEYBOARD_XTKBD)   += xtkbd.o
 obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o
+obj-$(CONFIG_KEYBOARD_CYPRESS_BUTTON)  += cypress-keyboard.o
diff --git a/drivers/input/keyboard/cypress-keyboard.c 
b/drivers/input/keyboard/cypress-keyboard.c
new file mode 100644
index 000..4a2e7f7
--- /dev/null
+++ b/drivers/input/keyboard/cypress-keyboard.c
@@ -0,0 +1,278 @@
+/*
+ * Cypress button driver
+ *
+ * Copyright (c) 2015, Intel 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* registers */
+#define SENSOR_EN  0x0
+#defineSENSOR_CS0  0
+#defineSENSOR_CS1  1
+#define BUTTON_STAT0xAA
+#defineBUTTON_ACTIVE   1
+
+/* retry I2C transfer in case of autosleep */
+#define I2C_RETRY_TIMES10
+
+struct cy_kb {
+   struct i2c_client *client;
+   struct input_dev *input_dev;
+   struct mutex mutex;
+   unsigned int irq;
+   int gpio;
+   u16 button_status;
+   bool suspended;
+};
+
+static int cy_kb_read(struct cy_kb *data,
+ u16 reg, u16 len, void *buf)
+{
+   int ret;
+   u8 regbuf[1];
+   struct i2c_msg xfer[2];
+   int retry = I2C_RETRY_TIMES;
+
+   regbuf[0] = reg & 0xff;
+
+   xfer[0].addr = data->client->addr;
+   xfer[0].flags = 0;
+   xfer[0].len = sizeof(regbuf);
+   xfer[0].buf = regbuf;
+
+   xfer[1].addr = data->client->addr;
+   xfer[1].flags = I2C_M_RD;
+   xfer[1].len = len;
+   xfer[1].buf = buf;
+
+retry_read:
+   ret = i2c_transfer(data->client->adapter, xfer, ARRAY_SIZE(xfer));
+   if (ret != ARRAY_SIZE(xfer)) {
+   if (retry--) {
+   dev_dbg(>client->dev, "i2c read retry\n");
+   goto retry_read;
+   } else {
+   dev_err(>client->dev, "i2c transfer failed 
(%d)\n",
+   ret);
+   return -EIO;
+   }
+   }
+
+   return 0;
+}
+
+static int cy_kb_write(struct cy_kb *data, u8 reg, u16 val)
+{
+   int ret;
+   u8 *buf;
+   int count;
+   int retry = I2C_RETRY_TIMES;
+
+   count = sizeof(val) + 1;
+   buf = kmalloc(count, GFP_KERNEL);
+   if (!buf)
+   return -ENOMEM;
+
+   buf[0] = reg & 0xff;
+   memcpy([1], , sizeof(val));
+
+retry_write:
+   ret = i2c_master_send(data->client, buf, count);
+   if (ret != count) {
+   if (retry--) {
+   dev_dbg(>client->dev, "i2c write retry\n");
+   goto retry_write;
+   } else {
+   dev_err(>client->dev, "i2c send failed (%d)\n",
+   ret);
+   ret = -EIO;
+   }
+   } else {
+   ret = 0;
+   }
+
+   kfree(buf);
+   return ret;
+}
+
+static irqreturn_t cy_kb_interrupt(int irq, void *dev_id)
+{
+   int ret;
+   u8 buf = 0x0;
+   struct cy_kb *data = dev_id;
+
+   mutex_lock(>mutex);
+
+   ret = cy_kb_read(data, BUTTON_STAT, sizeof(buf), );
+   if (ret) {
+   dev_err(>client->dev, "ca

[PATCH] input:keyboard: add Cypress button driver for Intel Platform

2015-09-21 Thread Qipeng Zha
This driver is to support Cypress CY8CMBR3XXX family controller,
which is used as button input for Intel platforms.

Signed-off-by: Qipeng Zha <qipeng@intel.com>
---
 drivers/input/keyboard/Kconfig|   7 +
 drivers/input/keyboard/Makefile   |   1 +
 drivers/input/keyboard/cypress-keyboard.c | 278 ++
 3 files changed, 286 insertions(+)
 create mode 100644 drivers/input/keyboard/cypress-keyboard.c

diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index a89ba7c..f39f148 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -686,4 +686,11 @@ config KEYBOARD_CAP11XX
  To compile this driver as a module, choose M here: the
  module will be called cap11xx.
 
+config KEYBOARD_CYPRESS_BUTTON
+   tristate "Cypress Button"
+   depends on I2C
+   help
+ Say Y here to enable support for Cypress button for
+ Intel platforms.
+
 endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 4707678..5a73138 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -60,3 +60,4 @@ obj-$(CONFIG_KEYBOARD_TEGRA)  += tegra-kbc.o
 obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o
 obj-$(CONFIG_KEYBOARD_XTKBD)   += xtkbd.o
 obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o
+obj-$(CONFIG_KEYBOARD_CYPRESS_BUTTON)  += cypress-keyboard.o
diff --git a/drivers/input/keyboard/cypress-keyboard.c 
b/drivers/input/keyboard/cypress-keyboard.c
new file mode 100644
index 000..4a2e7f7
--- /dev/null
+++ b/drivers/input/keyboard/cypress-keyboard.c
@@ -0,0 +1,278 @@
+/*
+ * Cypress button driver
+ *
+ * Copyright (c) 2015, Intel 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* registers */
+#define SENSOR_EN  0x0
+#defineSENSOR_CS0  0
+#defineSENSOR_CS1  1
+#define BUTTON_STAT0xAA
+#defineBUTTON_ACTIVE   1
+
+/* retry I2C transfer in case of autosleep */
+#define I2C_RETRY_TIMES10
+
+struct cy_kb {
+   struct i2c_client *client;
+   struct input_dev *input_dev;
+   struct mutex mutex;
+   unsigned int irq;
+   int gpio;
+   u16 button_status;
+   bool suspended;
+};
+
+static int cy_kb_read(struct cy_kb *data,
+ u16 reg, u16 len, void *buf)
+{
+   int ret;
+   u8 regbuf[1];
+   struct i2c_msg xfer[2];
+   int retry = I2C_RETRY_TIMES;
+
+   regbuf[0] = reg & 0xff;
+
+   xfer[0].addr = data->client->addr;
+   xfer[0].flags = 0;
+   xfer[0].len = sizeof(regbuf);
+   xfer[0].buf = regbuf;
+
+   xfer[1].addr = data->client->addr;
+   xfer[1].flags = I2C_M_RD;
+   xfer[1].len = len;
+   xfer[1].buf = buf;
+
+retry_read:
+   ret = i2c_transfer(data->client->adapter, xfer, ARRAY_SIZE(xfer));
+   if (ret != ARRAY_SIZE(xfer)) {
+   if (retry--) {
+   dev_dbg(>client->dev, "i2c read retry\n");
+   goto retry_read;
+   } else {
+   dev_err(>client->dev, "i2c transfer failed 
(%d)\n",
+   ret);
+   return -EIO;
+   }
+   }
+
+   return 0;
+}
+
+static int cy_kb_write(struct cy_kb *data, u8 reg, u16 val)
+{
+   int ret;
+   u8 *buf;
+   int count;
+   int retry = I2C_RETRY_TIMES;
+
+   count = sizeof(val) + 1;
+   buf = kmalloc(count, GFP_KERNEL);
+   if (!buf)
+   return -ENOMEM;
+
+   buf[0] = reg & 0xff;
+   memcpy([1], , sizeof(val));
+
+retry_write:
+   ret = i2c_master_send(data->client, buf, count);
+   if (ret != count) {
+   if (retry--) {
+   dev_dbg(>client->dev, "i2c write retry\n");
+   goto retry_write;
+   } else {
+   dev_err(>client->dev, "i2c send failed (%d)\n",
+   ret);
+   ret = -EIO;
+   }
+   } else {
+   ret = 0;
+   }
+
+   kfree(buf);
+   return ret;
+}
+
+static irqreturn_t cy_kb_interrupt(int irq, void *dev_id)
+{
+   int ret;
+   u8 buf = 0x0;
+   struct cy_kb *data = dev_id;
+
+   mutex_lock(>mutex);
+
+   ret = cy_kb_read(data, BUTTON_STAT, sizeof(buf), );
+   if (ret) {
+   dev_err(>client->dev, "ca

[PATCH] input:gpio-key: set IRQF_NO_SUSPEND for wake capable key

2015-09-17 Thread Qipeng Zha
When wakeup attribute is set, GPIO key is supposed to wake up
the system from system sleep state, So set IRQF_NO_SUSPEND
flag to keep IRQ enabled during suspend.

Signed-off-by: Qi Zheng <qi.zh...@intel.com>
Signed-off-by: Aubrey Li <aubrey...@intel.com>
Signed-off-by: Qipeng Zha <qipeng@intel.com>
---
 drivers/input/keyboard/gpio_keys.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/input/keyboard/gpio_keys.c 
b/drivers/input/keyboard/gpio_keys.c
index ddf4045..9744ad9 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -528,6 +528,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
 */
if (!button->can_disable)
irqflags |= IRQF_SHARED;
+   if (button->wakeup)
+   irqflags |= IRQF_NO_SUSPEND;
 
error = devm_request_any_context_irq(>dev, bdata->irq,
 isr, irqflags, desc, bdata);
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html