Linux Input/HID development
 help / color / mirror / Atom feed
* [PATCH v3] Input: Add driver for Microchip's CAP1106
From: Daniel Mack @ 2014-07-11 22:49 UTC (permalink / raw)
  To: dtor; +Cc: linux-input, broonie, dh.herrmann, devicetree, Daniel Mack

This patch adds a driver for Microchips CAP1106, an I2C driven, 6-channel
capacitive touch sensor.

For now, only the capacitive buttons are supported, and no specific
settings that can be tweaked for individual channels, except for the
device-wide sensitivity gain. The defaults seem to work just fine out of
the box, so I'll leave configurable parameters for someone who's in need
of them and who can actually measure the impact. All registers are
prepared, however. Many of them are just not used for now.

The implementation does not make any attempt to be compatible to platform
data driven boards, but fully depends on CONFIG_OF.

Power management functions are also left for volounteers with the ability
to actually test them.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
v2:                                                                              
 * Fix potential deadlocks pointed out by David.

v3:
 * Use devm_request_threaded_irq() and get rid of the work struct.
 * Drop ->open() and ->close() as it isn't actually needed for an
   interrupt-driven device. This way, we can also get rid of the
   locking entirely.

 .../devicetree/bindings/input/cap1106.txt          |  63 ++++
 drivers/input/keyboard/Kconfig                     |  10 +
 drivers/input/keyboard/Makefile                    |   1 +
 drivers/input/keyboard/cap1106.c                   | 322 +++++++++++++++++++++
 4 files changed, 396 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/input/cap1106.txt
 create mode 100644 drivers/input/keyboard/cap1106.c

diff --git a/Documentation/devicetree/bindings/input/cap1106.txt b/Documentation/devicetree/bindings/input/cap1106.txt
new file mode 100644
index 0000000..57f5af3
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/cap1106.txt
@@ -0,0 +1,63 @@
+Device tree bindings for Microchip CAP1106, 6 channel capacitive touch sensor
+
+The node for this driver must be a child of a I2C controller node, as the
+device communication via I2C only.
+
+Required properties:
+
+	compatible:		Must be "microchip,cap1106"
+	reg:			The I2C slave address of the device.
+				Only 0x28 is valid.
+	interrupt:		Node describing the interrupt line the device's
+				ALERT#/CM_IRQ# pin is connected to.
+
+Optional properties:
+
+	autorepeat:		Enables the Linux input system's autorepeat
+				feature on the input device.
+	microchip,sensor-gain:	Defines the gain of the sensor circuitry. This
+				effectively controls the sensitivity, as a
+				smaller delta capacitance is required to
+				generate the same delta count values.
+				Valid values are 1, 2, 4, and 8.
+				By default, a gain of 1 is set.
+
+To define details of each individual button channel, six subnodes can be
+specified. Inside each of those, the following property is valid:
+
+	linux,keycode:	Specify the numeric identifier of the keycode to be
+			generated when this channel is activated. If this
+			property is omitted, KEY_A, KEY_B, etc are used as
+			defaults.
+
+Example:
+
+i2c_controller {
+	cap1106@28 {
+		compatible = "microchip,cap1106";
+		interrupt-parent = <&gpio1>;
+		interrupts = <0 0>;
+		reg = <0x28>;
+		autorepeat;
+		microchip,sensor-gain = <2>;
+
+		up {
+			linux,keycode = <103>; /* KEY_UP */
+		};
+		right {
+			linux,keycode = <106>; /* KEY_RIGHT */
+		};
+		down {
+			linux,keycode = <108>; /* KEY_DOWN */
+		};
+		left {
+			linux,keycode = <105>; /* KEY_LEFT */
+		};
+		pagedown {
+			linux,keycode = <109>; /* KEY_PAGEDOWN */
+		};
+		pageup {
+			linux,keycode = <104>; /* KEY_PAGEUP */
+		};
+	};
+}
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index f7e79b4..a3958c6 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -665,4 +665,14 @@ config KEYBOARD_CROS_EC
 	  To compile this driver as a module, choose M here: the
 	  module will be called cros_ec_keyb.
 
+config KEYBOARD_CAP1106
+	tristate "Microchip CAP1106 touch sensor"
+	depends on OF && I2C
+	select REGMAP_I2C
+	help
+	  Say Y here to enable the CAP1106 touch sensor driver.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cap1106.
+
 endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 7504ae1..0a33456 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_KEYBOARD_AMIGA)		+= amikbd.o
 obj-$(CONFIG_KEYBOARD_ATARI)		+= atakbd.o
 obj-$(CONFIG_KEYBOARD_ATKBD)		+= atkbd.o
 obj-$(CONFIG_KEYBOARD_BFIN)		+= bf54x-keys.o
+obj-$(CONFIG_KEYBOARD_CAP1106)		+= cap1106.o
 obj-$(CONFIG_KEYBOARD_CLPS711X)		+= clps711x-keypad.o
 obj-$(CONFIG_KEYBOARD_CROS_EC)		+= cros_ec_keyb.o
 obj-$(CONFIG_KEYBOARD_DAVINCI)		+= davinci_keyscan.o
diff --git a/drivers/input/keyboard/cap1106.c b/drivers/input/keyboard/cap1106.c
new file mode 100644
index 0000000..14142af
--- /dev/null
+++ b/drivers/input/keyboard/cap1106.c
@@ -0,0 +1,322 @@
+/*
+ * Input driver for Microchip CAP1106, 6 channel capacitive touch sensor
+ *
+ * http://www.microchip.com/wwwproducts/Devices.aspx?product=CAP1106
+ *
+ * (c) 2014 Daniel Mack <linux@zonque.org>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/of_irq.h>
+#include <linux/regmap.h>
+#include <linux/i2c.h>
+#include <linux/gpio/consumer.h>
+
+#define CAP1106_REG_MAIN_CONTROL	0x00
+#define CAP1106_REG_MAIN_CONTROL_GAIN_SHIFT	(6)
+#define CAP1106_REG_MAIN_CONTROL_GAIN_MASK	(0xc0)
+#define CAP1106_REG_GENERAL_STATUS	0x02
+#define CAP1106_REG_SENSOR_INPUT	0x03
+#define CAP1106_REG_NOISE_FLAG_STATUS	0x0a
+#define CAP1106_REG_SENOR_DELTA(X)	(0x10 + (X))
+#define CAP1106_REG_SENSITIVITY_CONTROL	0x1f
+#define CAP1106_REG_CONFIG		0x20
+#define CAP1106_REG_SENSOR_ENABLE	0x21
+#define CAP1106_REG_SENSOR_CONFIG	0x22
+#define CAP1106_REG_SENSOR_CONFIG2	0x23
+#define CAP1106_REG_SAMPLING_CONFIG	0x24
+#define CAP1106_REG_CALIBRATION		0x25
+#define CAP1106_REG_INT_ENABLE		0x26
+#define CAP1106_REG_REPEAT_RATE		0x28
+#define CAP1106_REG_MT_CONFIG		0x2a
+#define CAP1106_REG_MT_PATTERN_CONFIG	0x2b
+#define CAP1106_REG_MT_PATTERN		0x2d
+#define CAP1106_REG_RECALIB_CONFIG	0x2f
+#define CAP1106_REG_SENSOR_THRESH(X)	(0x30 + (X))
+#define CAP1106_REG_SENSOR_NOISE_THRESH	0x38
+#define CAP1106_REG_STANDBY_CHANNEL	0x40
+#define CAP1106_REG_STANDBY_CONFIG	0x41
+#define CAP1106_REG_STANDBY_SENSITIVITY	0x42
+#define CAP1106_REG_STANDBY_THRESH	0x43
+#define CAP1106_REG_CONFIG2		0x44
+#define CAP1106_REG_SENSOR_BASE_CNT(X)	(0x50 + (X))
+#define CAP1106_REG_SENSOR_CALIB	(0xb1 + (X))
+#define CAP1106_REG_SENSOR_CALIB_LSB1	0xb9
+#define CAP1106_REG_SENSOR_CALIB_LSB2	0xba
+#define CAP1106_REG_PRODUCT_ID		0xfd
+#define CAP1106_REG_MANUFACTURER_ID	0xfe
+#define CAP1106_REG_REVISION		0xff
+
+#define CAP1106_NUM_CHN 6
+#define CAP1106_PRODUCT_ID	0x55
+#define CAP1106_MANUFACTURER_ID	0x5d
+
+struct cap1106_priv {
+	struct regmap *regmap;
+	struct input_dev *idev;
+
+	/* config */
+	unsigned int keycodes[CAP1106_NUM_CHN];
+};
+
+static const struct reg_default cap1106_reg_defaults[] = {
+	{ CAP1106_REG_MAIN_CONTROL,		0x00 },
+	{ CAP1106_REG_GENERAL_STATUS,		0x00 },
+	{ CAP1106_REG_SENSOR_INPUT,		0x00 },
+	{ CAP1106_REG_NOISE_FLAG_STATUS,	0x00 },
+	{ CAP1106_REG_SENSITIVITY_CONTROL,	0x2f },
+	{ CAP1106_REG_CONFIG,			0x20 },
+	{ CAP1106_REG_SENSOR_ENABLE,		0x3f },
+	{ CAP1106_REG_SENSOR_CONFIG,		0xa4 },
+	{ CAP1106_REG_SENSOR_CONFIG2,		0x07 },
+	{ CAP1106_REG_SAMPLING_CONFIG,		0x39 },
+	{ CAP1106_REG_CALIBRATION,		0x00 },
+	{ CAP1106_REG_INT_ENABLE,		0x3f },
+	{ CAP1106_REG_REPEAT_RATE,		0x3f },
+	{ CAP1106_REG_MT_CONFIG,		0x80 },
+	{ CAP1106_REG_MT_PATTERN_CONFIG,	0x00 },
+	{ CAP1106_REG_MT_PATTERN,		0x3f },
+	{ CAP1106_REG_RECALIB_CONFIG,		0x8a },
+	{ CAP1106_REG_SENSOR_THRESH(0),		0x40 },
+	{ CAP1106_REG_SENSOR_THRESH(1),		0x40 },
+	{ CAP1106_REG_SENSOR_THRESH(2),		0x40 },
+	{ CAP1106_REG_SENSOR_THRESH(3),		0x40 },
+	{ CAP1106_REG_SENSOR_THRESH(4),		0x40 },
+	{ CAP1106_REG_SENSOR_THRESH(5),		0x40 },
+	{ CAP1106_REG_SENSOR_NOISE_THRESH,	0x01 },
+	{ CAP1106_REG_STANDBY_CHANNEL,		0x00 },
+	{ CAP1106_REG_STANDBY_CONFIG,		0x39 },
+	{ CAP1106_REG_STANDBY_SENSITIVITY,	0x02 },
+	{ CAP1106_REG_STANDBY_THRESH,		0x40 },
+	{ CAP1106_REG_CONFIG2,			0x40 },
+	{ CAP1106_REG_SENSOR_CALIB_LSB1,	0x00 },
+	{ CAP1106_REG_SENSOR_CALIB_LSB2,	0x00 },
+};
+
+static bool cap1106_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case CAP1106_REG_MAIN_CONTROL:
+	case CAP1106_REG_SENSOR_INPUT:
+	case CAP1106_REG_SENOR_DELTA(0):
+	case CAP1106_REG_SENOR_DELTA(1):
+	case CAP1106_REG_SENOR_DELTA(2):
+	case CAP1106_REG_SENOR_DELTA(3):
+	case CAP1106_REG_SENOR_DELTA(4):
+	case CAP1106_REG_SENOR_DELTA(5):
+	case CAP1106_REG_PRODUCT_ID:
+	case CAP1106_REG_MANUFACTURER_ID:
+	case CAP1106_REG_REVISION:
+		return true;
+	}
+
+	return false;
+}
+
+static const struct regmap_config cap1106_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = CAP1106_REG_REVISION,
+	.reg_defaults = cap1106_reg_defaults,
+
+	.num_reg_defaults = ARRAY_SIZE(cap1106_reg_defaults),
+	.cache_type = REGCACHE_RBTREE,
+	.volatile_reg = cap1106_volatile_reg,
+};
+
+static irqreturn_t cap1106_thread_func(int irq_num, void *data)
+{
+	struct cap1106_priv *priv = data;
+	unsigned int status;
+	int ret, i;
+
+	/*
+	 * Deassert interrupt. This needs to be done before reading the status
+	 * registers, which will not carry valid values otherwise.
+	 */
+	ret = regmap_update_bits(priv->regmap, CAP1106_REG_MAIN_CONTROL, 1, 0);
+	if (ret < 0)
+		goto out;
+
+	ret = regmap_read(priv->regmap, CAP1106_REG_SENSOR_INPUT, &status);
+	if (ret < 0)
+		goto out;
+
+	for (i = 0; i < CAP1106_NUM_CHN; i++)
+		input_report_key(priv->idev, priv->keycodes[i],
+				 status & (1 << i));
+
+	input_sync(priv->idev);
+
+out:
+	return IRQ_HANDLED;
+}
+
+static int cap1106_i2c_probe(struct i2c_client *i2c_client,
+			     const struct i2c_device_id *id)
+{
+	struct device *dev = &i2c_client->dev;
+	struct device_node *child, *node;
+	struct cap1106_priv *priv;
+	unsigned int val, rev;
+	int i, ret, irq;
+	u8 gain = 0;
+	u32 tmp32;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->regmap = devm_regmap_init_i2c(i2c_client, &cap1106_regmap_config);
+	if (IS_ERR(priv->regmap))
+		return PTR_ERR(priv->regmap);
+
+	ret = regmap_read(priv->regmap, CAP1106_REG_PRODUCT_ID, &val);
+	if (ret < 0)
+		return ret;
+
+	if (val != CAP1106_PRODUCT_ID) {
+		dev_err(dev, "Product ID: Got 0x%02x, expected 0x%02x\n",
+			val, CAP1106_PRODUCT_ID);
+		return -ENODEV;
+	}
+
+	ret = regmap_read(priv->regmap, CAP1106_REG_MANUFACTURER_ID, &val);
+	if (ret < 0)
+		return ret;
+
+	if (val != CAP1106_MANUFACTURER_ID) {
+		dev_err(dev, "Manufacturer ID: Got 0x%02x, expected 0x%02x\n",
+			val, CAP1106_MANUFACTURER_ID);
+		return -ENODEV;
+	}
+
+	ret = regmap_read(priv->regmap, CAP1106_REG_REVISION, &rev);
+	if (ret < 0)
+		return ret;
+
+	dev_info(dev, "CAP1106 detected, revision 0x%02x\n", rev);
+	i2c_set_clientdata(i2c_client, priv);
+	node = dev->of_node;
+
+	if (!of_property_read_u32(node, "microchip,sensor-gain", &tmp32)) {
+		if (is_power_of_2(tmp32) && tmp32 <= 8)
+			gain = ilog2(tmp32);
+		else
+			dev_err(dev, "Invalid sensor-gain value %d\n", tmp32);
+	}
+
+	ret = regmap_update_bits(priv->regmap, CAP1106_REG_MAIN_CONTROL,
+				 CAP1106_REG_MAIN_CONTROL_GAIN_MASK,
+				 gain << CAP1106_REG_MAIN_CONTROL_GAIN_SHIFT);
+	if (ret < 0)
+		return ret;
+
+	/* disable autorepeat. The Linux input system has its own handling. */
+	ret = regmap_write(priv->regmap, CAP1106_REG_REPEAT_RATE, 0);
+	if (ret < 0)
+		return ret;
+
+	/* set the defaults */
+	for (i = 0; i < CAP1106_NUM_CHN; i++)
+		priv->keycodes[i] = KEY_A + i;
+
+	i = 0;
+	for_each_child_of_node(node, child) {
+		if (i == CAP1106_NUM_CHN) {
+			dev_err(dev, "Too many button nodes.\n");
+			return -EINVAL;
+		}
+
+		if (!of_property_read_u32(child, "linux,keycode", &tmp32))
+			priv->keycodes[i] = tmp32;
+
+		i++;
+	}
+
+	priv->idev = devm_input_allocate_device(dev);
+	if (!priv->idev)
+		return -ENOMEM;
+
+	priv->idev->name = "CAP1106 capacitive touch sensor";
+	priv->idev->id.bustype = BUS_I2C;
+	priv->idev->evbit[0] = BIT_MASK(EV_KEY);
+
+	if (of_get_property(node, "autorepeat", NULL))
+		__set_bit(EV_REP, priv->idev->evbit);
+
+	for (i = 0; i < CAP1106_NUM_CHN; i++) {
+		unsigned int code = priv->keycodes[i];
+		priv->idev->keybit[BIT_WORD(code)] |= BIT_MASK(code);
+	}
+
+	priv->idev->id.vendor = CAP1106_MANUFACTURER_ID;
+	priv->idev->id.product = CAP1106_PRODUCT_ID;
+	priv->idev->id.version = rev;
+
+	input_set_drvdata(priv->idev, priv);
+
+	ret = input_register_device(priv->idev);
+	if (ret < 0)
+		return ret;
+
+	irq = irq_of_parse_and_map(node, 0);
+	if (!irq) {
+		dev_err(dev, "Unable to parse or map IRQ\n");
+		return -ENXIO;
+	}
+
+	ret = devm_request_threaded_irq(dev, irq, NULL, cap1106_thread_func,
+					IRQF_ONESHOT, dev_name(dev), priv);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int cap1106_i2c_remove(struct i2c_client *i2c_client)
+{
+	struct cap1106_priv *priv = i2c_get_clientdata(i2c_client);
+
+	input_unregister_device(priv->idev);
+
+	return 0;
+}
+
+static const struct of_device_id cap1106_dt_ids[] = {
+	{ .compatible = "microchip,cap1106", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, cap1106_dt_ids);
+
+static const struct i2c_device_id cap1106_i2c_ids[] = {
+	{ "cap1106", 0 },
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, cap1106_i2c_ids);
+
+static struct i2c_driver cap1106_i2c_driver = {
+	.driver = {
+		.name	= "cap1106",
+		.owner	= THIS_MODULE,
+		.of_match_table = cap1106_dt_ids,
+	},
+	.id_table	= cap1106_i2c_ids,
+	.probe		= cap1106_i2c_probe,
+	.remove		= cap1106_i2c_remove,
+};
+
+module_i2c_driver(cap1106_i2c_driver);
+
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DESCRIPTION("Microchip CAP1106 driver");
+MODULE_AUTHOR("Daniel Mack <linux@zonque.org>");
+MODULE_LICENSE("GPL v2");
-- 
1.9.3


^ permalink raw reply related

* [PATCH] HID: i2c-hid: call the hid driver's suspend and resume callbacks
From: Andrew Duggan @ 2014-07-11 23:34 UTC (permalink / raw)
  To: linux-input, linux-kernel
  Cc: Andrew Duggan, Jiri Kosina, Benjamin Tissoires, Vincent Huang

Currently, the i2c-hid driver does not call the suspend, resume, and
reset_resume callbacks in the hid_driver struct when those events occur.
This means that HID drivers for i2c-hid devices will not be able to execute
commands which may be needed during suspend or resume. One example is when a
touchpad using the hid-multitouch driver gets reset by i2c-hid coming out of
resume. Since the reset_resume callback never gets called the device is never
put back into the correct input mode. This patch calls the suspend and resume
callbacks and tries to duplicate the functionality of the usb-hid driver.

Signed-off-by: Andrew Duggan <aduggan@synaptics.com>
Signed-off-by: Vincent Huang <vincent.huang@tw.synaptics.com>
---
Hi Benjamin,

This is the patch which Vincent and I came up with to fix the behavior which we were seeing with touchpads not being operational after resuming. We only use the reset_resume callback since i2c_hid_resume is always doing a hardware reset and it doesn't seem like there is a condition in which the standard resume callback would be appropriate. Also, is a full hardware reset always needed when resuming?

 drivers/hid/i2c-hid/i2c-hid.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index 21aafc8..747d544 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -1054,21 +1054,29 @@ static int i2c_hid_remove(struct i2c_client *client)
 static int i2c_hid_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+	struct hid_device *hid = ihid->hid;
+	int ret = 0;
 
 	disable_irq(client->irq);
 	if (device_may_wakeup(&client->dev))
 		enable_irq_wake(client->irq);
 
+	if (hid->driver && hid->driver->suspend)
+		ret = hid->driver->suspend(hid, PMSG_SUSPEND);
+
 	/* Save some power */
 	i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
 
-	return 0;
+	return ret;
 }
 
 static int i2c_hid_resume(struct device *dev)
 {
 	int ret;
 	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_hid *ihid = i2c_get_clientdata(client);
+	struct hid_device *hid = ihid->hid;
 
 	enable_irq(client->irq);
 	ret = i2c_hid_hwreset(client);
@@ -1078,6 +1086,11 @@ static int i2c_hid_resume(struct device *dev)
 	if (device_may_wakeup(&client->dev))
 		disable_irq_wake(client->irq);
 
+	if (hid->driver && hid->driver->reset_resume) {
+		ret = hid->driver->reset_resume(hid);
+		return ret;
+	}
+
 	return 0;
 }
 #endif
-- 
1.9.1


^ permalink raw reply related

* [PATCH] input: driver for touchscreen on iPaq h3xxx
From: Linus Walleij @ 2014-07-12  9:31 UTC (permalink / raw)
  To: Dmitry Torokhov, linux-input
  Cc: Dmitry Artamonow, Alessandro GARDICH, Linus Walleij

From: Dmitry Artamonow <mad_soft@inbox.ru>

This adds a driver for the touchscreen connected to the
Atmel microcontroller on the iPAQ h3xxx series.

Based on a driver from handhelds.org 2.6.21 kernel, written
by Alessandro GARDICH.

Signed-off-by: Alessandro GARDICH <gremlin@gremlin.it>
Signed-off-by: Dmitry Artamonow <mad_soft@inbox.ru>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/input/touchscreen/Kconfig         |   8 ++
 drivers/input/touchscreen/Makefile        |   1 +
 drivers/input/touchscreen/ipaq-micro-ts.c | 137 ++++++++++++++++++++++++++++++
 3 files changed, 146 insertions(+)
 create mode 100644 drivers/input/touchscreen/ipaq-micro-ts.c

diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index a23a94bb4bcb..26d0953c7094 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -471,6 +471,14 @@ config TOUCHSCREEN_HP7XX
 	  To compile this driver as a module, choose M here: the
 	  module will be called jornada720_ts.
 
+config TOUCHSCREEN_IPAQ_MICRO
+	tristate "HP iPAQ Atmel Micro ASIC touchscreen"
+	depends on MFD_IPAQ_MICRO
+	help
+	  This enables support for the touchscreen attached to
+	  the Atmel Micro peripheral controller on iPAQ h3100/h3600/h3700
+
+
 config TOUCHSCREEN_HTCPEN
 	tristate "HTC Shift X9500 touchscreen"
 	depends on ISA
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 126479d8c29a..4be94fce41af 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_TOUCHSCREEN_MTOUCH)	+= mtouch.o
 obj-$(CONFIG_TOUCHSCREEN_MK712)		+= mk712.o
 obj-$(CONFIG_TOUCHSCREEN_HP600)		+= hp680_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_HP7XX)		+= jornada720_ts.o
+obj-$(CONFIG_TOUCHSCREEN_IPAQ_MICRO)	+= ipaq-micro-ts.o
 obj-$(CONFIG_TOUCHSCREEN_HTCPEN)	+= htcpen.o
 obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE)	+= usbtouchscreen.o
 obj-$(CONFIG_TOUCHSCREEN_PCAP)		+= pcap_ts.o
diff --git a/drivers/input/touchscreen/ipaq-micro-ts.c b/drivers/input/touchscreen/ipaq-micro-ts.c
new file mode 100644
index 000000000000..9c5e1b62d192
--- /dev/null
+++ b/drivers/input/touchscreen/ipaq-micro-ts.c
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ *
+ * h3600 atmel micro companion support, touchscreen subdevice
+ * Author : Alessandro Gardich <gremlin@gremlin.it>
+ * Author : Linus Walleij <linus.walleij@linaro.org>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/mfd/ipaq-micro.h>
+
+struct touchscreen_data {
+	struct input_dev *input;
+	struct ipaq_micro *micro;
+};
+
+static void micro_ts_receive(void *data, int len, unsigned char *msg)
+{
+	struct touchscreen_data *ts = data;
+
+	if (len == 4) {
+		input_report_abs(ts->input, ABS_X, (msg[2]<<8)+msg[3]);
+		input_report_abs(ts->input, ABS_Y, (msg[0]<<8)+msg[1]);
+		input_report_abs(ts->input, ABS_PRESSURE, 1);
+		input_report_key(ts->input, BTN_TOUCH, 0);
+	}
+	if (len == 0) {
+		input_report_abs(ts->input, ABS_X, 0);
+		input_report_abs(ts->input, ABS_Y, 0);
+		input_report_abs(ts->input, ABS_PRESSURE, 0);
+		input_report_key(ts->input, BTN_TOUCH, 1);
+	}
+	input_sync(ts->input);
+}
+
+
+static int micro_ts_probe(struct platform_device *pdev)
+{
+	struct touchscreen_data *ts;
+	int ret;
+
+	ts = devm_kzalloc(&pdev->dev, sizeof(*ts), GFP_KERNEL);
+	if (!ts)
+		return -ENOMEM;
+	ts->micro = dev_get_drvdata(pdev->dev.parent);
+
+	platform_set_drvdata(pdev, ts);
+
+	ts->input = input_allocate_device();
+
+	ts->input->evbit[0] = BIT(EV_ABS);
+	ts->input->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
+	input_set_abs_params(ts->input, ABS_X, 0, 1023, 0, 0);
+	input_set_abs_params(ts->input, ABS_Y, 0, 1023, 0, 0);
+	input_set_abs_params(ts->input, ABS_PRESSURE, 0x0, 0x1, 0, 0);
+
+	ts->input->name = "ipaq micro ts";
+	/* ts->input->private = ts; */
+
+	ret = input_register_device(ts->input);
+	if (ret) {
+		dev_err(&pdev->dev, "error registering touch input\n");
+		return ret;
+	}
+
+	spin_lock(&ts->micro->lock);
+	ts->micro->ts = micro_ts_receive;
+	ts->micro->ts_data = ts;
+	spin_unlock(&ts->micro->lock);
+
+	dev_info(&pdev->dev, "iPAQ micro touchscreen\n");
+	return 0;
+}
+
+static int micro_ts_remove(struct platform_device *pdev)
+{
+	struct touchscreen_data *ts = platform_get_drvdata(pdev);
+
+	spin_lock(&ts->micro->lock);
+	ts->micro->ts = NULL;
+	ts->micro->ts_data = NULL;
+	spin_unlock(&ts->micro->lock);
+	input_unregister_device(ts->input);
+
+	return 0;
+}
+
+static int micro_ts_suspend(struct device *dev)
+{
+	struct touchscreen_data *ts = dev_get_drvdata(dev);
+
+	spin_lock(&ts->micro->lock);
+	ts->micro->ts = NULL;
+	ts->micro->ts_data = NULL;
+	spin_unlock(&ts->micro->lock);
+	return 0;
+}
+
+static int micro_ts_resume(struct device *dev)
+{
+	struct touchscreen_data *ts = dev_get_drvdata(dev);
+
+	spin_lock(&ts->micro->lock);
+	ts->micro->ts = micro_ts_receive;
+	ts->micro->ts_data = ts;
+	spin_unlock(&ts->micro->lock);
+	return 0;
+}
+
+static const struct dev_pm_ops micro_ts_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(micro_ts_suspend, micro_ts_resume)
+};
+
+struct platform_driver micro_ts_device_driver = {
+	.driver  = {
+		.name    = "ipaq-micro-ts",
+		.pm	= &micro_ts_dev_pm_ops,
+	},
+	.probe   = micro_ts_probe,
+	.remove  = micro_ts_remove,
+};
+module_platform_driver(micro_ts_device_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("driver for iPAQ Atmel micro touchscreen");
+MODULE_ALIAS("platform:ipaq-micro-ts");
-- 
1.9.3


^ permalink raw reply related

* Synaptics touchpad - lost sync
From: Nicole Faerber @ 2014-07-12 14:37 UTC (permalink / raw)
  To: linux-input; +Cc: nicole.faerber, Hans de Goede

Hello all!

I am experiencing an issue on a new Thinkpad Yoga S1 which implements a
touchpad with integrated buttons - I assume this is called a button-pad?
And as with all Thinkpads it also has a trackpoint (the red knob) as
well as a touchscreen and a graphics tablet integrated into the display
(AFAIK Wacom).

All pointing devices work properly for pointing - I can move the mouse
cursor smoothly without any glitch, also using the touchpad. The
touchscreen and the Wacom also work for "clicking".

But as soon as I press one of the buttons on the touchpad I get a
strange behavior. Either the cursor randomly jumps and causes random
button presses and then freezes for some seconds or it just freezes. In
kernel dmesg I see the following when this happens:

[   38.880242] psmouse serio1: TouchPad at isa0060/serio1/input0 lost
sync at byte 1
[   38.881295] psmouse serio1: TouchPad at isa0060/serio1/input0 lost
sync at byte 1
[   38.882452] psmouse serio1: TouchPad at isa0060/serio1/input0 lost
sync at byte 1
[   38.883558] psmouse serio1: TouchPad at isa0060/serio1/input0 lost
sync at byte 1
[   38.884662] psmouse serio1: TouchPad at isa0060/serio1/input0 lost
sync at byte 1
[   38.884673] psmouse serio1: issuing reconnect request

Soon after the reconnect request it starts working again, i.e. I can
move the cursor again but if I press a button on the touchpad it starts
to fail again.

In dmesg I also see this output after boot:

[    2.106803] psmouse serio1: synaptics: Touchpad model: 1, fw: 8.1,
id: 0x1e2b1, caps: 0xd001a3/0x940300/0x127c00, board id: 2911, fw id:
1514409
[    2.106813] psmouse serio1: synaptics: serio: Synaptics pass-through
port at isa0060/serio1/input0
[    6.584970] psmouse serio2: alps: Unknown ALPS touchpad: E7=10 00 64,
EC=10 00 64
[    8.532572] psmouse serio2: trackpoint: IBM TrackPoint firmware:
0x0e, buttons: 3/3


Do I have a not yet supported touchpad here? Or does my hardware have a
defect?

The main issue I have now is that I just bought this Thinkpad and I need
to know if this is a software or a hardware issue. If it is software it
can surely be fixed and I can wait for that to happen (or even try to
help doing it). But if it is hardware I need to return the machine ASAP
- which would be the worst case.


If you have an idea what I might do to either fix that or help to debug
I would be very happy if you would let me know.

Many thanks!

PS: Please keep me in CC when replying since I am not subscribed to the
linux-input list.

Cheers
  nicole

-- 
kernel concepts GmbH
Sieghuetter Hauptweg 48
D-57072 Siegen
http://www.kernelconcepts.de

^ permalink raw reply

* Re: [PATCH] input: driver for touchscreen on iPaq h3xxx
From: Dmitry Torokhov @ 2014-07-13  2:59 UTC (permalink / raw)
  To: Linus Walleij; +Cc: linux-input, Dmitry Artamonow, Alessandro GARDICH
In-Reply-To: <1405157481-10348-1-git-send-email-linus.walleij@linaro.org>

Hi Linus, Dmitry,

On Sat, Jul 12, 2014 at 11:31:21AM +0200, Linus Walleij wrote:
> From: Dmitry Artamonow <mad_soft@inbox.ru>

So is this Dmitry's or Alessandro's work?

> 
> This adds a driver for the touchscreen connected to the
> Atmel microcontroller on the iPAQ h3xxx series.
> 
> Based on a driver from handhelds.org 2.6.21 kernel, written
> by Alessandro GARDICH.
> 
> Signed-off-by: Alessandro GARDICH <gremlin@gremlin.it>
> Signed-off-by: Dmitry Artamonow <mad_soft@inbox.ru>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
>  drivers/input/touchscreen/Kconfig         |   8 ++
>  drivers/input/touchscreen/Makefile        |   1 +
>  drivers/input/touchscreen/ipaq-micro-ts.c | 137 ++++++++++++++++++++++++++++++
>  3 files changed, 146 insertions(+)
>  create mode 100644 drivers/input/touchscreen/ipaq-micro-ts.c
> 
> diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
> index a23a94bb4bcb..26d0953c7094 100644
> --- a/drivers/input/touchscreen/Kconfig
> +++ b/drivers/input/touchscreen/Kconfig
> @@ -471,6 +471,14 @@ config TOUCHSCREEN_HP7XX
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called jornada720_ts.
>  
> +config TOUCHSCREEN_IPAQ_MICRO
> +	tristate "HP iPAQ Atmel Micro ASIC touchscreen"
> +	depends on MFD_IPAQ_MICRO
> +	help
> +	  This enables support for the touchscreen attached to
> +	  the Atmel Micro peripheral controller on iPAQ h3100/h3600/h3700
> +

To compile this driver as a module ...

> +
>  config TOUCHSCREEN_HTCPEN
>  	tristate "HTC Shift X9500 touchscreen"
>  	depends on ISA
> diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
> index 126479d8c29a..4be94fce41af 100644
> --- a/drivers/input/touchscreen/Makefile
> +++ b/drivers/input/touchscreen/Makefile
> @@ -46,6 +46,7 @@ obj-$(CONFIG_TOUCHSCREEN_MTOUCH)	+= mtouch.o
>  obj-$(CONFIG_TOUCHSCREEN_MK712)		+= mk712.o
>  obj-$(CONFIG_TOUCHSCREEN_HP600)		+= hp680_ts_input.o
>  obj-$(CONFIG_TOUCHSCREEN_HP7XX)		+= jornada720_ts.o
> +obj-$(CONFIG_TOUCHSCREEN_IPAQ_MICRO)	+= ipaq-micro-ts.o
>  obj-$(CONFIG_TOUCHSCREEN_HTCPEN)	+= htcpen.o
>  obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE)	+= usbtouchscreen.o
>  obj-$(CONFIG_TOUCHSCREEN_PCAP)		+= pcap_ts.o
> diff --git a/drivers/input/touchscreen/ipaq-micro-ts.c b/drivers/input/touchscreen/ipaq-micro-ts.c
> new file mode 100644
> index 000000000000..9c5e1b62d192
> --- /dev/null
> +++ b/drivers/input/touchscreen/ipaq-micro-ts.c
> @@ -0,0 +1,137 @@
> +/*
> + * 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.
> + *
> + * h3600 atmel micro companion support, touchscreen subdevice
> + * Author : Alessandro Gardich <gremlin@gremlin.it>
> + * Author : Linus Walleij <linus.walleij@linaro.org>
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/pm.h>
> +#include <linux/delay.h>
> +#include <linux/device.h>
> +#include <linux/input.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/mfd/ipaq-micro.h>

Has this been merged already?

> +
> +struct touchscreen_data {
> +	struct input_dev *input;
> +	struct ipaq_micro *micro;
> +};
> +
> +static void micro_ts_receive(void *data, int len, unsigned char *msg)
> +{
> +	struct touchscreen_data *ts = data;
> +
> +	if (len == 4) {
> +		input_report_abs(ts->input, ABS_X, (msg[2]<<8)+msg[3]);

be16_to_cpup()?

> +		input_report_abs(ts->input, ABS_Y, (msg[0]<<8)+msg[1]);
> +		input_report_abs(ts->input, ABS_PRESSURE, 1);

Please no fake pressure events, update your tslib instead.

> +		input_report_key(ts->input, BTN_TOUCH, 0);

This seems completely backwards.

> +	}
> +	if (len == 0) {
> +		input_report_abs(ts->input, ABS_X, 0);
> +		input_report_abs(ts->input, ABS_Y, 0);
> +		input_report_abs(ts->input, ABS_PRESSURE, 0);
> +		input_report_key(ts->input, BTN_TOUCH, 1);
> +	}
> +	input_sync(ts->input);
> +}
> +
> +
> +static int micro_ts_probe(struct platform_device *pdev)
> +{
> +	struct touchscreen_data *ts;
> +	int ret;
> +
> +	ts = devm_kzalloc(&pdev->dev, sizeof(*ts), GFP_KERNEL);
> +	if (!ts)
> +		return -ENOMEM;
> +	ts->micro = dev_get_drvdata(pdev->dev.parent);
> +
> +	platform_set_drvdata(pdev, ts);
> +
> +	ts->input = input_allocate_device();

Error handling please; also consider using devm_input_allocate_device().

> +
> +	ts->input->evbit[0] = BIT(EV_ABS);
> +	ts->input->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
> +	input_set_abs_params(ts->input, ABS_X, 0, 1023, 0, 0);
> +	input_set_abs_params(ts->input, ABS_Y, 0, 1023, 0, 0);
> +	input_set_abs_params(ts->input, ABS_PRESSURE, 0x0, 0x1, 0, 0);
> +

You are missing setting BTN_TOUCH in capabilities so events you are
trying to send in micro_ts_receive will not go anywhere.

> +	ts->input->name = "ipaq micro ts";
> +	/* ts->input->private = ts; */

Huh?

> +
> +	ret = input_register_device(ts->input);
> +	if (ret) {
> +		dev_err(&pdev->dev, "error registering touch input\n");
> +		return ret;
> +	}
> +
> +	spin_lock(&ts->micro->lock);
> +	ts->micro->ts = micro_ts_receive;
> +	ts->micro->ts_data = ts;
> +	spin_unlock(&ts->micro->lock);
> +
> +	dev_info(&pdev->dev, "iPAQ micro touchscreen\n");
> +	return 0;
> +}
> +
> +static int micro_ts_remove(struct platform_device *pdev)
> +{
> +	struct touchscreen_data *ts = platform_get_drvdata(pdev);
> +
> +	spin_lock(&ts->micro->lock);
> +	ts->micro->ts = NULL;
> +	ts->micro->ts_data = NULL;
> +	spin_unlock(&ts->micro->lock);
> +	input_unregister_device(ts->input);
> +
> +	return 0;
> +}
> +
> +static int micro_ts_suspend(struct device *dev)
> +{
> +	struct touchscreen_data *ts = dev_get_drvdata(dev);
> +
> +	spin_lock(&ts->micro->lock);
> +	ts->micro->ts = NULL;
> +	ts->micro->ts_data = NULL;
> +	spin_unlock(&ts->micro->lock);

What is the point here?

> +	return 0;
> +}
> +
> +static int micro_ts_resume(struct device *dev)
> +{
> +	struct touchscreen_data *ts = dev_get_drvdata(dev);
> +
> +	spin_lock(&ts->micro->lock);
> +	ts->micro->ts = micro_ts_receive;
> +	ts->micro->ts_data = ts;
> +	spin_unlock(&ts->micro->lock);
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops micro_ts_dev_pm_ops = {
> +	SET_SYSTEM_SLEE`P_PM_OPS(micro_ts_suspend, micro_ts_resume)
> +};
> +
> +struct platform_driver micro_ts_device_driver = {
> +	.driver  = {
> +		.name    = "ipaq-micro-ts",
> +		.pm	= &micro_ts_dev_pm_ops,
> +	},
> +	.probe   = micro_ts_probe,
> +	.remove  = micro_ts_remove,
> +};
> +module_platform_driver(micro_ts_device_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("driver for iPAQ Atmel micro touchscreen");
> +MODULE_ALIAS("platform:ipaq-micro-ts");
> -- 
> 1.9.3
> 

Thanks.

-- 
Dmitry

^ permalink raw reply

* [PATCH] drivers: Let several drivers depends on HAS_IOMEM for 'devm_ioremap_resource'
From: Chen Gang @ 2014-07-13  3:07 UTC (permalink / raw)
  To: gregkh
  Cc: linux-iio, benh, teg, thierry.reding, Lennox Wu, marex,
	Liqin Chen, lars, richard, linux-input, linux-pwm, devel,
	linux-watchdog, msalter, dmitry.torokhov,
	linux-kernel@vger.kernel.org, knaack.h, schwidefsky,
	Mischa.Jonker, jic23

Several drivers need 'devm_ioremap_resource' which need HAS_IOMEM enabled.
So let them depend on HAS_IOMEM.

The related error (with allmodconfig under score):

    MODPOST 1365 modules
  ERROR: "devm_ioremap_resource" [drivers/watchdog/tegra_wdt.ko] undefined!
  ERROR: "devm_ioremap_resource" [drivers/watchdog/of_xilinx_wdt.ko] undefined!
  ERROR: "devm_ioremap_resource" [drivers/staging/iio/adc/mxs-lradc.ko] undefined!
  ERROR: "devm_ioremap_resource" [drivers/pwm/pwm-clps711x.ko] undefined!
  ERROR: "devm_ioremap_resource" [drivers/input/serio/olpc_apsp.ko] undefined!
  ERROR: "devm_ioremap_resource" [drivers/input/serio/arc_ps2.ko] undefined!


Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
---
 drivers/input/serio/Kconfig     | 3 ++-
 drivers/pwm/Kconfig             | 2 +-
 drivers/staging/iio/adc/Kconfig | 2 +-
 drivers/watchdog/Kconfig        | 3 ++-
 4 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index bc2d474..449d45f 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -244,6 +244,7 @@ config SERIO_PS2MULT
 
 config SERIO_ARC_PS2
 	tristate "ARC PS/2 support"
+	depends on HAS_IOMEM
 	help
 	  Say Y here if you have an ARC FPGA platform with a PS/2
 	  controller in it.
@@ -263,7 +264,7 @@ config SERIO_APBPS2
 
 config SERIO_OLPC_APSP
 	tristate "OLPC AP-SP input support"
-	depends on OLPC || COMPILE_TEST
+	depends on (OLPC || COMPILE_TEST) && HAS_IOMEM
 	help
 	  Say Y here if you want support for the keyboard and touchpad included
 	  in the OLPC XO-1.75 and XO-4 laptops.
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 4ad7b89..2faf5ce 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -82,7 +82,7 @@ config PWM_BFIN
 
 config PWM_CLPS711X
 	tristate "CLPS711X PWM support"
-	depends on ARCH_CLPS711X || COMPILE_TEST
+	depends on (ARCH_CLPS711X || COMPILE_TEST) && HAS_IOMEM
 	help
 	  Generic PWM framework driver for Cirrus Logic CLPS711X.
 
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index b87e382..4e927d2 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -94,7 +94,7 @@ config LPC32XX_ADC
 
 config MXS_LRADC
 	tristate "Freescale i.MX23/i.MX28 LRADC"
-	depends on ARCH_MXS || COMPILE_TEST
+	depends on (ARCH_MXS || COMPILE_TEST) && HAS_IOMEM
 	depends on INPUT
 	select STMP_DEVICE
 	select IIO_BUFFER
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 76dd541..0e4abb2 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -113,6 +113,7 @@ config WM8350_WATCHDOG
 
 config XILINX_WATCHDOG
 	tristate "Xilinx Watchdog timer"
+	depends on HAS_IOMEM
 	select WATCHDOG_CORE
 	help
 	  Watchdog driver for the xps_timebase_wdt ip core.
@@ -434,7 +435,7 @@ config SIRFSOC_WATCHDOG
 
 config TEGRA_WATCHDOG
 	tristate "Tegra watchdog"
-	depends on ARCH_TEGRA || COMPILE_TEST
+	depends on (ARCH_TEGRA || COMPILE_TEST) && HAS_IOMEM
 	select WATCHDOG_CORE
 	help
 	  Say Y here to include support for the watchdog timer
-- 
1.7.11.7

^ permalink raw reply related

* Re: [PATCH] drivers: Let several drivers depends on HAS_IOMEM for 'devm_ioremap_resource'
From: Chen Gang @ 2014-07-13  3:14 UTC (permalink / raw)
  To: gregkh
  Cc: linux-kernel@vger.kernel.org, dmitry.torokhov, thierry.reding,
	jic23, wim, benh, kys, schwidefsky, teg, Mischa.Jonker, msalter,
	lars, richard, knaack.h, marex, rdunlap, linux-input, linux-pwm,
	linux-iio, devel, linux-watchdog, Liqin Chen, Lennox Wu,
	David Rientjes, Guenter Roeck
In-Reply-To: <53C1F7DE.3060102@gmail.com>


After this last patch, score architecture can pass allmodconfig. :-)

And also find a compiler issue, I will try to fix it, but shall not notify
kernel mailing list, again. The related issue is below (it seems a kernel
issue, but in fact, it is a compiler's issue):

    CC [M]  drivers/staging/lustre/lustre/ptlrpc/sec.o
  drivers/staging/lustre/lustre/ptlrpc/sec.c: In function 'sptlrpc_cli_ctx_expire':
  drivers/staging/lustre/lustre/ptlrpc/sec.c:309:13: error: 'struct ptlrpc_ctx_ops' has no member named '__die'
    ctx->cc_ops->die(ctx, 0);
               ^
  drivers/staging/lustre/lustre/ptlrpc/sec.c: In function 'ctx_refresh_timeout':
  drivers/staging/lustre/lustre/ptlrpc/sec.c:594:26: error: 'struct ptlrpc_ctx_ops' has no member named '__die'
     req->rq_cli_ctx->cc_ops->die(req->rq_cli_ctx, 0);
                            ^
  make[5]: *** [drivers/staging/lustre/lustre/ptlrpc/sec.o] Error 1
  make[4]: *** [drivers/staging/lustre/lustre/ptlrpc] Error 2
  make[3]: *** [drivers/staging/lustre/lustre] Error 2
  make[2]: *** [drivers/staging/lustre] Error 2
  make[1]: *** [drivers/staging] Error 2
  make: *** [drivers] Error 2

Thanks.

On 07/13/2014 11:07 AM, Chen Gang wrote:
> Several drivers need 'devm_ioremap_resource' which need HAS_IOMEM enabled.
> So let them depend on HAS_IOMEM.
> 
> The related error (with allmodconfig under score):
> 
>     MODPOST 1365 modules
>   ERROR: "devm_ioremap_resource" [drivers/watchdog/tegra_wdt.ko] undefined!
>   ERROR: "devm_ioremap_resource" [drivers/watchdog/of_xilinx_wdt.ko] undefined!
>   ERROR: "devm_ioremap_resource" [drivers/staging/iio/adc/mxs-lradc.ko] undefined!
>   ERROR: "devm_ioremap_resource" [drivers/pwm/pwm-clps711x.ko] undefined!
>   ERROR: "devm_ioremap_resource" [drivers/input/serio/olpc_apsp.ko] undefined!
>   ERROR: "devm_ioremap_resource" [drivers/input/serio/arc_ps2.ko] undefined!
> 
> 
> Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
> ---
>  drivers/input/serio/Kconfig     | 3 ++-
>  drivers/pwm/Kconfig             | 2 +-
>  drivers/staging/iio/adc/Kconfig | 2 +-
>  drivers/watchdog/Kconfig        | 3 ++-
>  4 files changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
> index bc2d474..449d45f 100644
> --- a/drivers/input/serio/Kconfig
> +++ b/drivers/input/serio/Kconfig
> @@ -244,6 +244,7 @@ config SERIO_PS2MULT
>  
>  config SERIO_ARC_PS2
>  	tristate "ARC PS/2 support"
> +	depends on HAS_IOMEM
>  	help
>  	  Say Y here if you have an ARC FPGA platform with a PS/2
>  	  controller in it.
> @@ -263,7 +264,7 @@ config SERIO_APBPS2
>  
>  config SERIO_OLPC_APSP
>  	tristate "OLPC AP-SP input support"
> -	depends on OLPC || COMPILE_TEST
> +	depends on (OLPC || COMPILE_TEST) && HAS_IOMEM
>  	help
>  	  Say Y here if you want support for the keyboard and touchpad included
>  	  in the OLPC XO-1.75 and XO-4 laptops.
> diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
> index 4ad7b89..2faf5ce 100644
> --- a/drivers/pwm/Kconfig
> +++ b/drivers/pwm/Kconfig
> @@ -82,7 +82,7 @@ config PWM_BFIN
>  
>  config PWM_CLPS711X
>  	tristate "CLPS711X PWM support"
> -	depends on ARCH_CLPS711X || COMPILE_TEST
> +	depends on (ARCH_CLPS711X || COMPILE_TEST) && HAS_IOMEM
>  	help
>  	  Generic PWM framework driver for Cirrus Logic CLPS711X.
>  
> diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
> index b87e382..4e927d2 100644
> --- a/drivers/staging/iio/adc/Kconfig
> +++ b/drivers/staging/iio/adc/Kconfig
> @@ -94,7 +94,7 @@ config LPC32XX_ADC
>  
>  config MXS_LRADC
>  	tristate "Freescale i.MX23/i.MX28 LRADC"
> -	depends on ARCH_MXS || COMPILE_TEST
> +	depends on (ARCH_MXS || COMPILE_TEST) && HAS_IOMEM
>  	depends on INPUT
>  	select STMP_DEVICE
>  	select IIO_BUFFER
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index 76dd541..0e4abb2 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -113,6 +113,7 @@ config WM8350_WATCHDOG
>  
>  config XILINX_WATCHDOG
>  	tristate "Xilinx Watchdog timer"
> +	depends on HAS_IOMEM
>  	select WATCHDOG_CORE
>  	help
>  	  Watchdog driver for the xps_timebase_wdt ip core.
> @@ -434,7 +435,7 @@ config SIRFSOC_WATCHDOG
>  
>  config TEGRA_WATCHDOG
>  	tristate "Tegra watchdog"
> -	depends on ARCH_TEGRA || COMPILE_TEST
> +	depends on (ARCH_TEGRA || COMPILE_TEST) && HAS_IOMEM
>  	select WATCHDOG_CORE
>  	help
>  	  Say Y here to include support for the watchdog timer
> 


-- 
Chen Gang

Open share and attitude like air water and life which God blessed

^ permalink raw reply

* Re: [PATCH] drivers: Let several drivers depends on HAS_IOMEM for 'devm_ioremap_resource'
From: Marek Vasut @ 2014-07-13  3:45 UTC (permalink / raw)
  To: Chen Gang
  Cc: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	thierry.reding-Re5JQEeQqe8AvxtiuMwx3w,
	jic23-DgEjT+Ai2ygdnm+yROfE0A, wim-IQzOog9fTRqzQB+pC5nmwQ,
	benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, kys-0li6OtcxBFHby3iVrkZq2A,
	schwidefsky-tA70FqPdS9bQT0dZR+AlfA, teg-B22kvLQNl6c,
	Mischa.Jonker-HKixBCOQz3hWk0Htik3J/w,
	msalter-H+wXaHxf7aLQT0dZR+AlfA, lars-Qo5EllUWu/uELgA04lAiVw,
	richard-/L3Ra7n9ekc, knaack.h-Mmb7MZpHnFY,
	rdunlap-wEGCiKHe2LqWVfeAwA7xHQ,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-pwm-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devel-gWbeCf7V1WCQmaza687I9mD2FQJk+8+b,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA, Liqin Chen, Lennox Wu
In-Reply-To: <53C1F7DE.3060102-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

On Sunday, July 13, 2014 at 05:07:10 AM, Chen Gang wrote:
> Several drivers need 'devm_ioremap_resource' which need HAS_IOMEM enabled.
> So let them depend on HAS_IOMEM.
> 
> The related error (with allmodconfig under score):
> 
>     MODPOST 1365 modules
>   ERROR: "devm_ioremap_resource" [drivers/watchdog/tegra_wdt.ko] undefined!
>   ERROR: "devm_ioremap_resource" [drivers/watchdog/of_xilinx_wdt.ko]
> undefined! ERROR: "devm_ioremap_resource"
> [drivers/staging/iio/adc/mxs-lradc.ko] undefined! ERROR:
> "devm_ioremap_resource" [drivers/pwm/pwm-clps711x.ko] undefined! ERROR:
> "devm_ioremap_resource" [drivers/input/serio/olpc_apsp.ko] undefined!
> ERROR: "devm_ioremap_resource" [drivers/input/serio/arc_ps2.ko] undefined!

This stuff should go through different trees, so I'd suggest to split this into 
multiple patches. Thanks for catching this stuff !

Best regards,
Marek Vasut

^ permalink raw reply

* [PATCH v4 2/4] Make all base functions switch depending on product ID
From: Jamie Lentin @ 2014-07-13  7:24 UTC (permalink / raw)
  To: Jiri Kosina, Antonio Ospite, Hans de Goede
  Cc: linux-input, linux-kernel, Jamie Lentin
In-Reply-To: <1405236262-8070-1-git-send-email-jm@lentin.co.uk>

Signed-off-by: Jamie Lentin <jm@lentin.co.uk>
---
 drivers/hid/hid-lenovo.c | 45 ++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 38 insertions(+), 7 deletions(-)

diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
index 0320b96..d11e337 100644
--- a/drivers/hid/hid-lenovo.c
+++ b/drivers/hid/hid-lenovo.c
@@ -1,5 +1,6 @@
 /*
- *  HID driver for Lenovo ThinkPad USB Keyboard with TrackPoint
+ *  HID driver for Lenovo:
+ *  - ThinkPad USB Keyboard with TrackPoint (tpkbd)
  *
  *  Copyright (c) 2012 Bernhard Seibold
  */
@@ -47,6 +48,19 @@ static int lenovo_input_mapping_tpkbd(struct hid_device *hdev,
 	return 0;
 }
 
+static int lenovo_input_mapping(struct hid_device *hdev,
+		struct hid_input *hi, struct hid_field *field,
+		struct hid_usage *usage, unsigned long **bit, int *max)
+{
+	switch (hdev->product) {
+	case USB_DEVICE_ID_LENOVO_TPKBD:
+		return lenovo_input_mapping_tpkbd(hdev, hi, field,
+							usage, bit, max);
+	}
+
+	return 0;
+}
+
 #undef map_key_clear
 
 static int lenovo_features_set_tpkbd(struct hid_device *hdev)
@@ -337,6 +351,16 @@ static int lenovo_probe_tpkbd(struct hid_device *hdev)
 	char *name_mute, *name_micmute;
 	int i;
 
+	/*
+	 * If this is the pointer half of the keyboard, input_mapping should
+	 * have set drvdata to 1. Otherwise, it's the keyboard which needs
+	 * nothing special doing to it.
+	 */
+	if (!hid_get_drvdata(hdev))
+		return 0;
+
+	hid_set_drvdata(hdev, NULL);
+
 	/* Validate required reports. */
 	for (i = 0; i < 4; i++) {
 		if (!hid_validate_values(hdev, HID_FEATURE_REPORT, 4, i, 1))
@@ -409,12 +433,13 @@ static int lenovo_probe(struct hid_device *hdev,
 		goto err;
 	}
 
-	if (hid_get_drvdata(hdev)) {
-		hid_set_drvdata(hdev, NULL);
+	switch (hdev->product) {
+	case USB_DEVICE_ID_LENOVO_TPKBD:
 		ret = lenovo_probe_tpkbd(hdev);
-		if (ret)
-			goto err_hid;
+		break;
 	}
+	if (ret)
+		goto err_hid;
 
 	return 0;
 err_hid:
@@ -430,6 +455,9 @@ static void lenovo_remove_tpkbd(struct hid_device *hdev)
 	sysfs_remove_group(&hdev->dev.kobj,
 			&lenovo_attr_group_tpkbd);
 
+	if (data_pointer == NULL)
+		return;
+
 	led_classdev_unregister(&data_pointer->led_micmute);
 	led_classdev_unregister(&data_pointer->led_mute);
 
@@ -438,8 +466,11 @@ static void lenovo_remove_tpkbd(struct hid_device *hdev)
 
 static void lenovo_remove(struct hid_device *hdev)
 {
-	if (hid_get_drvdata(hdev))
+	switch (hdev->product) {
+	case USB_DEVICE_ID_LENOVO_TPKBD:
 		lenovo_remove_tpkbd(hdev);
+		break;
+	}
 
 	hid_hw_stop(hdev);
 }
@@ -454,7 +485,7 @@ MODULE_DEVICE_TABLE(hid, lenovo_devices);
 static struct hid_driver lenovo_driver = {
 	.name = "lenovo",
 	.id_table = lenovo_devices,
-	.input_mapping = lenovo_input_mapping_tpkbd,
+	.input_mapping = lenovo_input_mapping,
 	.probe = lenovo_probe,
 	.remove = lenovo_remove,
 };
-- 
2.0.0


^ permalink raw reply related

* [PATCH v4 3/4] Style fixes
From: Jamie Lentin @ 2014-07-13  7:24 UTC (permalink / raw)
  To: Jiri Kosina, Antonio Ospite, Hans de Goede
  Cc: linux-input, linux-kernel, Jamie Lentin
In-Reply-To: <1405236262-8070-1-git-send-email-jm@lentin.co.uk>

Signed-off-by: Jamie Lentin <jm@lentin.co.uk>
---
 drivers/hid/hid-lenovo.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
index d11e337..a1a693c 100644
--- a/drivers/hid/hid-lenovo.c
+++ b/drivers/hid/hid-lenovo.c
@@ -349,7 +349,7 @@ static int lenovo_probe_tpkbd(struct hid_device *hdev)
 	struct lenovo_drvdata_tpkbd *data_pointer;
 	size_t name_sz = strlen(dev_name(dev)) + 16;
 	char *name_mute, *name_micmute;
-	int i;
+	int i, ret;
 
 	/*
 	 * If this is the pointer half of the keyboard, input_mapping should
@@ -369,10 +369,9 @@ static int lenovo_probe_tpkbd(struct hid_device *hdev)
 	if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 3, 0, 2))
 		return -ENODEV;
 
-	if (sysfs_create_group(&hdev->dev.kobj,
-				&lenovo_attr_group_tpkbd)) {
+	ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_tpkbd);
+	if (ret)
 		hid_warn(hdev, "Could not create sysfs group\n");
-	}
 
 	data_pointer = devm_kzalloc(&hdev->dev,
 				    sizeof(struct lenovo_drvdata_tpkbd),
-- 
2.0.0


^ permalink raw reply related

* [PATCH v4 0/4] Add support for Lenovo Compact Keyboard
From: Jamie Lentin @ 2014-07-13  7:24 UTC (permalink / raw)
  To: Jiri Kosina, Antonio Ospite, Hans de Goede
  Cc: linux-input, linux-kernel, Jamie Lentin

This patchset follows on from my previous attempts to add support for
these keyboards from Lenovo.

Changes since v3: https://lkml.org/lkml/2014/6/15/159
* Break up first patch [Antonio Ospite]
* Rename ABI docs too [Jiri Kosina]
* Spelling and Grammar, style fixes [Antonio Ospite]
* Driver should just be called 'lenovo' [Antonio Ospite]
* Remove useless id from probe functions [Antonio Ospite]
* Use KEY_SCALE to match Thinkpad ??40 models [Hans de Goede]
* Add ABI documentation for fn_lock setting [Jiri Kosina]
* Use a bool for fn_lock instead of uint [Antonio Ospite]
* hid_output_raw_report has been replaced with hid_hw_raw_request [Antonio Ospite]

Changes since v2: https://lkml.org/lkml/2014/6/10/730
* Rename hid-lenovo-tpkbd to hid-lenovo, to make it obvious this is
  for any Lenovo-manufactured device [Antonio Ospite, Jiri Kosina]
* Style fixes: function calls in conditions, combine checks for 
  both USB & BT keyboards [Antonio Ospite]

Changes since v1: https://lkml.org/lkml/2014/3/25/535
* Merge driver into hid-lenovo-tpkbd.c instead of creating our own
  driver for the hardware [Jiri Kosina]
* Remove key mappings which are now supported by standard
* Use KEY_FILE for Fn-F12 (opens My Computer on Windows)
* Support the USB variant as well as Bluetooth
* Expose the Fn Lock setting as a sysfs attribute instead of trying to
  build a mechanism to toggle into the kernel

Applies against v3.16-rc4, tested with Bluetooth and USB variants of the
Compact Keyboard with Trackpoint.

Cheers,

Jamie Lentin (4):
  Rename hid-lenovo-tpkbd to hid-lenovo
  Make all base functions switch depending on product ID
  Style fixes
  Add support for Compact (Bluetooth|USB) keyboard with Trackpoint

 ...er-hid-lenovo-tpkbd => sysfs-driver-hid-lenovo} |  12 +
 drivers/hid/Kconfig                                |  16 +-
 drivers/hid/Makefile                               |   2 +-
 drivers/hid/hid-core.c                             |   4 +-
 drivers/hid/hid-ids.h                              |   2 +
 drivers/hid/hid-lenovo-tpkbd.c                     | 462 --------------
 drivers/hid/hid-lenovo.c                           | 696 +++++++++++++++++++++
 include/linux/hid.h                                |   1 +
 8 files changed, 724 insertions(+), 471 deletions(-)
 rename Documentation/ABI/testing/{sysfs-driver-hid-lenovo-tpkbd => sysfs-driver-hid-lenovo} (75%)
 delete mode 100644 drivers/hid/hid-lenovo-tpkbd.c
 create mode 100644 drivers/hid/hid-lenovo.c

-- 
2.0.0


^ permalink raw reply

* [PATCH v4 4/4] Add support for Compact (Bluetooth|USB) keyboard with Trackpoint
From: Jamie Lentin @ 2014-07-13  7:24 UTC (permalink / raw)
  To: Jiri Kosina, Antonio Ospite, Hans de Goede
  Cc: linux-input, linux-kernel, Jamie Lentin
In-Reply-To: <1405236262-8070-1-git-send-email-jm@lentin.co.uk>

Signed-off-by: Jamie Lentin <jm@lentin.co.uk>
---
 Documentation/ABI/testing/sysfs-driver-hid-lenovo |  12 ++
 drivers/hid/Kconfig                               |   2 +
 drivers/hid/hid-core.c                            |   2 +
 drivers/hid/hid-ids.h                             |   2 +
 drivers/hid/hid-lenovo.c                          | 203 ++++++++++++++++++++++
 include/linux/hid.h                               |   1 +
 6 files changed, 222 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-hid-lenovo b/Documentation/ABI/testing/sysfs-driver-hid-lenovo
index 57b92cb..53a0725 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-lenovo
+++ b/Documentation/ABI/testing/sysfs-driver-hid-lenovo
@@ -4,18 +4,21 @@ Contact:	linux-input@vger.kernel.org
 Description:	This controls if mouse clicks should be generated if the trackpoint is quickly pressed. How fast this press has to be
 		is being controlled by press_speed.
 		Values are 0 or 1.
+		Applies to Thinkpad USB Keyboard with TrackPoint.
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/dragging
 Date:		July 2011
 Contact:	linux-input@vger.kernel.org
 Description:	If this setting is enabled, it is possible to do dragging by pressing the trackpoint. This requires press_to_select to be enabled.
 		Values are 0 or 1.
+		Applies to Thinkpad USB Keyboard with TrackPoint.
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/release_to_select
 Date:		July 2011
 Contact:	linux-input@vger.kernel.org
 Description:	For details regarding this setting please refer to http://www.pc.ibm.com/ww/healthycomputing/trkpntb.html
 		Values are 0 or 1.
+		Applies to Thinkpad USB Keyboard with TrackPoint.
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/select_right
 Date:		July 2011
@@ -23,16 +26,25 @@ Contact:	linux-input@vger.kernel.org
 Description:	This setting controls if the mouse click events generated by pressing the trackpoint (if press_to_select is enabled) generate
 		a left or right mouse button click.
 		Values are 0 or 1.
+		Applies to Thinkpad USB Keyboard with TrackPoint.
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/sensitivity
 Date:		July 2011
 Contact:	linux-input@vger.kernel.org
 Description:	This file contains the trackpoint sensitivity.
 		Values are decimal integers from 1 (lowest sensitivity) to 255 (highest sensitivity).
+		Applies to Thinkpad USB Keyboard with TrackPoint.
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/press_speed
 Date:		July 2011
 Contact:	linux-input@vger.kernel.org
 Description:	This setting controls how fast the trackpoint needs to be pressed to generate a mouse click if press_to_select is enabled.
 		Values are decimal integers from 1 (slowest) to 255 (fastest).
+		Applies to Thinkpad USB Keyboard with TrackPoint.
 
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/fn_lock
+Date:		July 2014
+Contact:	linux-input@vger.kernel.org
+Description:	This setting controls whether Fn Lock is enabled on the keyboard (i.e. if F1 is Mute or F1)
+		Values are 0 or 1
+		Applies to ThinkPad Compact (USB|Bluetooth) Keyboard with TrackPoint.
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 9b7acfc..1e19292 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -343,6 +343,8 @@ config HID_LENOVO
 	Thinkpad standalone keyboards, e.g:
 	- ThinkPad USB Keyboard with TrackPoint (supports extra LEDs and trackpoint
 	  configuration)
+	- ThinkPad Compact Bluetooth Keyboard with TrackPoint (supports Fn keys)
+	- ThinkPad Compact USB Keyboard with TrackPoint (supports Fn keys)
 
 config HID_LOGITECH
 	tristate "Logitech devices" if EXPERT
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 55841bd..81b3bb6 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1798,6 +1798,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) },
 #if IS_ENABLED(CONFIG_HID_LENOVO)
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) },
 #endif
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 6d00bb9..d2e2a96 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -560,6 +560,8 @@
 
 #define USB_VENDOR_ID_LENOVO		0x17ef
 #define USB_DEVICE_ID_LENOVO_TPKBD	0x6009
+#define USB_DEVICE_ID_LENOVO_CUSBKBD	0x6047
+#define USB_DEVICE_ID_LENOVO_CBTKBD	0x6048
 
 #define USB_VENDOR_ID_LG		0x1fd2
 #define USB_DEVICE_ID_LG_MULTITOUCH	0x0064
diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
index a1a693c..46c5db0 100644
--- a/drivers/hid/hid-lenovo.c
+++ b/drivers/hid/hid-lenovo.c
@@ -1,8 +1,11 @@
 /*
  *  HID driver for Lenovo:
  *  - ThinkPad USB Keyboard with TrackPoint (tpkbd)
+ *  - ThinkPad Compact Bluetooth Keyboard with TrackPoint (cptkbd)
+ *  - ThinkPad Compact USB Keyboard with TrackPoint (cptkbd)
  *
  *  Copyright (c) 2012 Bernhard Seibold
+ *  Copyright (c) 2014 Jamie Lentin <jm@lentin.co.uk>
  */
 
 /*
@@ -33,6 +36,10 @@ struct lenovo_drvdata_tpkbd {
 	int press_speed;
 };
 
+struct lenovo_drvdata_cptkbd {
+	bool fn_lock;
+};
+
 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
 
 static int lenovo_input_mapping_tpkbd(struct hid_device *hdev,
@@ -48,6 +55,49 @@ static int lenovo_input_mapping_tpkbd(struct hid_device *hdev,
 	return 0;
 }
 
+static int lenovo_input_mapping_cptkbd(struct hid_device *hdev,
+		struct hid_input *hi, struct hid_field *field,
+		struct hid_usage *usage, unsigned long **bit, int *max)
+{
+	/* HID_UP_LNVENDOR = USB, HID_UP_MSVENDOR = BT */
+	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR ||
+	    (usage->hid & HID_USAGE_PAGE) == HID_UP_LNVENDOR) {
+		set_bit(EV_REP, hi->input->evbit);
+		switch (usage->hid & HID_USAGE) {
+		case 0x00f1: /* Fn-F4: Mic mute */
+			map_key_clear(KEY_MICMUTE);
+			return 1;
+		case 0x00f2: /* Fn-F5: Brightness down */
+			map_key_clear(KEY_BRIGHTNESSDOWN);
+			return 1;
+		case 0x00f3: /* Fn-F6: Brightness up */
+			map_key_clear(KEY_BRIGHTNESSUP);
+			return 1;
+		case 0x00f4: /* Fn-F7: External display (projector) */
+			map_key_clear(KEY_SWITCHVIDEOMODE);
+			return 1;
+		case 0x00f5: /* Fn-F8: Wireless */
+			map_key_clear(KEY_WLAN);
+			return 1;
+		case 0x00f6: /* Fn-F9: Control panel */
+			map_key_clear(KEY_CONFIG);
+			return 1;
+		case 0x00f8: /* Fn-F11: View open applications (3 boxes) */
+			map_key_clear(KEY_SCALE);
+			return 1;
+		case 0x00fa: /* Fn-Esc: Fn-lock toggle */
+			map_key_clear(KEY_FN_ESC);
+			return 1;
+		case 0x00fb: /* Fn-F12: Open My computer (6 boxes) USB-only */
+			/* NB: This mapping is invented in raw_event below */
+			map_key_clear(KEY_FILE);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
 static int lenovo_input_mapping(struct hid_device *hdev,
 		struct hid_input *hi, struct hid_field *field,
 		struct hid_usage *usage, unsigned long **bit, int *max)
@@ -56,6 +106,10 @@ static int lenovo_input_mapping(struct hid_device *hdev,
 	case USB_DEVICE_ID_LENOVO_TPKBD:
 		return lenovo_input_mapping_tpkbd(hdev, hi, field,
 							usage, bit, max);
+	case USB_DEVICE_ID_LENOVO_CUSBKBD:
+	case USB_DEVICE_ID_LENOVO_CBTKBD:
+		return lenovo_input_mapping_cptkbd(hdev, hi, field,
+							usage, bit, max);
 	}
 
 	return 0;
@@ -63,6 +117,100 @@ static int lenovo_input_mapping(struct hid_device *hdev,
 
 #undef map_key_clear
 
+/* Send a config command to the keyboard */
+static int lenovo_send_cmd_cptkbd(struct hid_device *hdev,
+			unsigned char byte2, unsigned char byte3)
+{
+	int ret;
+	unsigned char buf[] = {0x18, byte2, byte3};
+
+	switch (hdev->product) {
+	case USB_DEVICE_ID_LENOVO_CUSBKBD:
+		ret = hid_hw_raw_request(hdev, 0x13, buf, sizeof(buf),
+					HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+		break;
+	case USB_DEVICE_ID_LENOVO_CBTKBD:
+		ret = hid_hw_output_report(hdev, buf, sizeof(buf));
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret < 0 ? ret : 0; /* BT returns 0, USB returns sizeof(buf) */
+}
+
+static void lenovo_features_set_cptkbd(struct hid_device *hdev)
+{
+	struct lenovo_drvdata_cptkbd *tpcsc = hid_get_drvdata(hdev);
+
+	if (lenovo_send_cmd_cptkbd(hdev, 0x05, tpcsc->fn_lock ? 0x01 : 0x00))
+		hid_err(hdev, "Fn-lock setting failed\n");
+}
+
+static ssize_t attr_fn_lock_show_cptkbd(struct device *dev,
+		struct device_attribute *attr,
+		char *buf)
+{
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct lenovo_drvdata_cptkbd *tpcsc = hid_get_drvdata(hdev);
+
+	return snprintf(buf, PAGE_SIZE, "%u\n", tpcsc->fn_lock);
+}
+
+static ssize_t attr_fn_lock_store_cptkbd(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t count)
+{
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct lenovo_drvdata_cptkbd *tpcsc = hid_get_drvdata(hdev);
+	int value;
+
+	if (kstrtoint(buf, 10, &value))
+		return -EINVAL;
+	if (value < 0 || value > 1)
+		return -EINVAL;
+
+	tpcsc->fn_lock = !!value;
+	lenovo_features_set_cptkbd(hdev);
+
+	return count;
+}
+
+static struct device_attribute dev_attr_fn_lock_cptkbd =
+	__ATTR(fn_lock, S_IWUSR | S_IRUGO,
+			attr_fn_lock_show_cptkbd,
+			attr_fn_lock_store_cptkbd);
+
+static struct attribute *lenovo_attributes_cptkbd[] = {
+	&dev_attr_fn_lock_cptkbd.attr,
+	NULL
+};
+
+static const struct attribute_group lenovo_attr_group_cptkbd = {
+	.attrs = lenovo_attributes_cptkbd,
+};
+
+static int lenovo_raw_event(struct hid_device *hdev,
+			struct hid_report *report, u8 *data, int size)
+{
+	/*
+	 * Compact USB keyboard's Fn-F12 report holds down many other keys, and
+	 * its own key is outside the usage page range. Remove extra
+	 * keypresses and remap to inside usage page.
+	 */
+	if (unlikely(hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD
+			&& size == 3
+			&& data[0] == 0x15
+			&& data[1] == 0x94
+			&& data[2] == 0x01)) {
+		data[1] = 0x0;
+		data[2] = 0x4;
+	}
+
+	return 0;
+}
+
 static int lenovo_features_set_tpkbd(struct hid_device *hdev)
 {
 	struct hid_report *report;
@@ -415,6 +563,44 @@ static int lenovo_probe_tpkbd(struct hid_device *hdev)
 	return 0;
 }
 
+static int lenovo_probe_cptkbd(struct hid_device *hdev)
+{
+	int ret;
+	struct lenovo_drvdata_cptkbd *tpcsc;
+
+	tpcsc = devm_kzalloc(&hdev->dev, sizeof(*tpcsc), GFP_KERNEL);
+	if (tpcsc == NULL) {
+		hid_err(hdev, "can't alloc keyboard descriptor\n");
+		return -ENOMEM;
+	}
+	hid_set_drvdata(hdev, tpcsc);
+
+	/* All the custom action happens on the mouse device for USB */
+	if (hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD
+			&& hdev->type != HID_TYPE_USBMOUSE) {
+		hid_dbg(hdev, "Ignoring keyboard half of device\n");
+		return 0;
+	}
+
+	/*
+	 * Tell the keyboard a driver understands it, and turn F7, F9, F11 into
+	 * regular keys
+	 */
+	ret = lenovo_send_cmd_cptkbd(hdev, 0x01, 0x03);
+	if (ret)
+		hid_warn(hdev, "Failed to switch F7/9/11 into regular keys\n");
+
+	/* Turn Fn-Lock on by default */
+	tpcsc->fn_lock = 1;
+	lenovo_features_set_cptkbd(hdev);
+
+	if (sysfs_create_group(&hdev->dev.kobj,
+				&lenovo_attr_group_cptkbd))
+		hid_warn(hdev, "Could not create sysfs group\n");
+
+	return 0;
+}
+
 static int lenovo_probe(struct hid_device *hdev,
 		const struct hid_device_id *id)
 {
@@ -436,6 +622,10 @@ static int lenovo_probe(struct hid_device *hdev,
 	case USB_DEVICE_ID_LENOVO_TPKBD:
 		ret = lenovo_probe_tpkbd(hdev);
 		break;
+	case USB_DEVICE_ID_LENOVO_CUSBKBD:
+	case USB_DEVICE_ID_LENOVO_CBTKBD:
+		ret = lenovo_probe_cptkbd(hdev);
+		break;
 	}
 	if (ret)
 		goto err_hid;
@@ -463,12 +653,22 @@ static void lenovo_remove_tpkbd(struct hid_device *hdev)
 	hid_set_drvdata(hdev, NULL);
 }
 
+static void lenovo_remove_cptkbd(struct hid_device *hdev)
+{
+	sysfs_remove_group(&hdev->dev.kobj,
+			&lenovo_attr_group_cptkbd);
+}
+
 static void lenovo_remove(struct hid_device *hdev)
 {
 	switch (hdev->product) {
 	case USB_DEVICE_ID_LENOVO_TPKBD:
 		lenovo_remove_tpkbd(hdev);
 		break;
+	case USB_DEVICE_ID_LENOVO_CUSBKBD:
+	case USB_DEVICE_ID_LENOVO_CBTKBD:
+		lenovo_remove_cptkbd(hdev);
+		break;
 	}
 
 	hid_hw_stop(hdev);
@@ -476,6 +676,8 @@ static void lenovo_remove(struct hid_device *hdev)
 
 static const struct hid_device_id lenovo_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) },
 	{ }
 };
 
@@ -487,6 +689,7 @@ static struct hid_driver lenovo_driver = {
 	.input_mapping = lenovo_input_mapping,
 	.probe = lenovo_probe,
 	.remove = lenovo_remove,
+	.raw_event = lenovo_raw_event,
 };
 module_hid_driver(lenovo_driver);
 
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 77632cf..fca74f1 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -167,6 +167,7 @@ struct hid_item {
 #define HID_UP_MSVENDOR		0xff000000
 #define HID_UP_CUSTOM		0x00ff0000
 #define HID_UP_LOGIVENDOR	0xffbc0000
+#define HID_UP_LNVENDOR		0xffa00000
 #define HID_UP_SENSOR		0x00200000
 
 #define HID_USAGE		0x0000ffff
-- 
2.0.0


^ permalink raw reply related

* [PATCH v4 1/4] Rename hid-lenovo-tpkbd to hid-lenovo
From: Jamie Lentin @ 2014-07-13  7:24 UTC (permalink / raw)
  To: Jiri Kosina, Antonio Ospite, Hans de Goede
  Cc: linux-input, linux-kernel, Jamie Lentin
In-Reply-To: <1405236262-8070-1-git-send-email-jm@lentin.co.uk>

Rename module and all functions within so we can add support for other
keyboards in the same file. Rename the _tp postfix to _tpkbd, to
signify functions relevant to the TP USB keyboard.

Signed-off-by: Jamie Lentin <jm@lentin.co.uk>
---
 ...er-hid-lenovo-tpkbd => sysfs-driver-hid-lenovo} |   0
 drivers/hid/Kconfig                                |  14 +-
 drivers/hid/Makefile                               |   2 +-
 drivers/hid/hid-core.c                             |   2 +-
 drivers/hid/{hid-lenovo-tpkbd.c => hid-lenovo.c}   | 185 +++++++++++----------
 5 files changed, 102 insertions(+), 101 deletions(-)
 rename Documentation/ABI/testing/{sysfs-driver-hid-lenovo-tpkbd => sysfs-driver-hid-lenovo} (100%)
 rename drivers/hid/{hid-lenovo-tpkbd.c => hid-lenovo.c} (64%)

diff --git a/Documentation/ABI/testing/sysfs-driver-hid-lenovo-tpkbd b/Documentation/ABI/testing/sysfs-driver-hid-lenovo
similarity index 100%
rename from Documentation/ABI/testing/sysfs-driver-hid-lenovo-tpkbd
rename to Documentation/ABI/testing/sysfs-driver-hid-lenovo
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 800c8b6..9b7acfc 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -331,18 +331,18 @@ config HID_LCPOWER
 	---help---
 	Support for LC-Power RC1000MCE RF remote control.
 
-config HID_LENOVO_TPKBD
-	tristate "Lenovo ThinkPad USB Keyboard with TrackPoint"
+config HID_LENOVO
+	tristate "Lenovo / Thinkpad devices"
 	depends on HID
 	select NEW_LEDS
 	select LEDS_CLASS
 	---help---
-	Support for the Lenovo ThinkPad USB Keyboard with TrackPoint.
+	Support for Lenovo devices that are not fully compliant with HID standard.
 
-	Say Y here if you have a Lenovo ThinkPad USB Keyboard with TrackPoint
-	and would like to use device-specific features like changing the
-	sensitivity of the trackpoint, using the microphone mute button or
-	controlling the mute and microphone mute LEDs.
+	Say Y if you want support for the non-compliant features of the Lenovo
+	Thinkpad standalone keyboards, e.g:
+	- ThinkPad USB Keyboard with TrackPoint (supports extra LEDs and trackpoint
+	  configuration)
 
 config HID_LOGITECH
 	tristate "Logitech devices" if EXPERT
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index a6fa6ba..5e96be3 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -59,7 +59,7 @@ obj-$(CONFIG_HID_KENSINGTON)	+= hid-kensington.o
 obj-$(CONFIG_HID_KEYTOUCH)	+= hid-keytouch.o
 obj-$(CONFIG_HID_KYE)		+= hid-kye.o
 obj-$(CONFIG_HID_LCPOWER)       += hid-lcpower.o
-obj-$(CONFIG_HID_LENOVO_TPKBD)	+= hid-lenovo-tpkbd.o
+obj-$(CONFIG_HID_LENOVO)	+= hid-lenovo.o
 obj-$(CONFIG_HID_LOGITECH)	+= hid-logitech.o
 obj-$(CONFIG_HID_LOGITECH_DJ)	+= hid-logitech-dj.o
 obj-$(CONFIG_HID_MAGICMOUSE)    += hid-magicmouse.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 8ed66fd..55841bd 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1796,7 +1796,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) },
-#if IS_ENABLED(CONFIG_HID_LENOVO_TPKBD)
+#if IS_ENABLED(CONFIG_HID_LENOVO)
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
 #endif
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo.c
similarity index 64%
rename from drivers/hid/hid-lenovo-tpkbd.c
rename to drivers/hid/hid-lenovo.c
index 2d25b6c..0320b96 100644
--- a/drivers/hid/hid-lenovo-tpkbd.c
+++ b/drivers/hid/hid-lenovo.c
@@ -20,8 +20,7 @@
 
 #include "hid-ids.h"
 
-/* This is only used for the trackpoint part of the driver, hence _tp */
-struct tpkbd_data_pointer {
+struct lenovo_drvdata_tpkbd {
 	int led_state;
 	struct led_classdev led_mute;
 	struct led_classdev led_micmute;
@@ -35,7 +34,7 @@ struct tpkbd_data_pointer {
 
 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
 
-static int tpkbd_input_mapping(struct hid_device *hdev,
+static int lenovo_input_mapping_tpkbd(struct hid_device *hdev,
 		struct hid_input *hi, struct hid_field *field,
 		struct hid_usage *usage, unsigned long **bit, int *max)
 {
@@ -50,10 +49,10 @@ static int tpkbd_input_mapping(struct hid_device *hdev,
 
 #undef map_key_clear
 
-static int tpkbd_features_set(struct hid_device *hdev)
+static int lenovo_features_set_tpkbd(struct hid_device *hdev)
 {
 	struct hid_report *report;
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
 
 	report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4];
 
@@ -69,23 +68,23 @@ static int tpkbd_features_set(struct hid_device *hdev)
 	return 0;
 }
 
-static ssize_t pointer_press_to_select_show(struct device *dev,
+static ssize_t attr_press_to_select_show_tpkbd(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
 
 	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select);
 }
 
-static ssize_t pointer_press_to_select_store(struct device *dev,
+static ssize_t attr_press_to_select_store_tpkbd(struct device *dev,
 		struct device_attribute *attr,
 		const char *buf,
 		size_t count)
 {
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
 	int value;
 
 	if (kstrtoint(buf, 10, &value))
@@ -94,28 +93,28 @@ static ssize_t pointer_press_to_select_store(struct device *dev,
 		return -EINVAL;
 
 	data_pointer->press_to_select = value;
-	tpkbd_features_set(hdev);
+	lenovo_features_set_tpkbd(hdev);
 
 	return count;
 }
 
-static ssize_t pointer_dragging_show(struct device *dev,
+static ssize_t attr_dragging_show_tpkbd(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
 
 	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging);
 }
 
-static ssize_t pointer_dragging_store(struct device *dev,
+static ssize_t attr_dragging_store_tpkbd(struct device *dev,
 		struct device_attribute *attr,
 		const char *buf,
 		size_t count)
 {
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
 	int value;
 
 	if (kstrtoint(buf, 10, &value))
@@ -124,28 +123,28 @@ static ssize_t pointer_dragging_store(struct device *dev,
 		return -EINVAL;
 
 	data_pointer->dragging = value;
-	tpkbd_features_set(hdev);
+	lenovo_features_set_tpkbd(hdev);
 
 	return count;
 }
 
-static ssize_t pointer_release_to_select_show(struct device *dev,
+static ssize_t attr_release_to_select_show_tpkbd(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
 
 	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select);
 }
 
-static ssize_t pointer_release_to_select_store(struct device *dev,
+static ssize_t attr_release_to_select_store_tpkbd(struct device *dev,
 		struct device_attribute *attr,
 		const char *buf,
 		size_t count)
 {
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
 	int value;
 
 	if (kstrtoint(buf, 10, &value))
@@ -154,28 +153,28 @@ static ssize_t pointer_release_to_select_store(struct device *dev,
 		return -EINVAL;
 
 	data_pointer->release_to_select = value;
-	tpkbd_features_set(hdev);
+	lenovo_features_set_tpkbd(hdev);
 
 	return count;
 }
 
-static ssize_t pointer_select_right_show(struct device *dev,
+static ssize_t attr_select_right_show_tpkbd(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
 
 	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right);
 }
 
-static ssize_t pointer_select_right_store(struct device *dev,
+static ssize_t attr_select_right_store_tpkbd(struct device *dev,
 		struct device_attribute *attr,
 		const char *buf,
 		size_t count)
 {
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
 	int value;
 
 	if (kstrtoint(buf, 10, &value))
@@ -184,119 +183,119 @@ static ssize_t pointer_select_right_store(struct device *dev,
 		return -EINVAL;
 
 	data_pointer->select_right = value;
-	tpkbd_features_set(hdev);
+	lenovo_features_set_tpkbd(hdev);
 
 	return count;
 }
 
-static ssize_t pointer_sensitivity_show(struct device *dev,
+static ssize_t attr_sensitivity_show_tpkbd(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
 
 	return snprintf(buf, PAGE_SIZE, "%u\n",
 		data_pointer->sensitivity);
 }
 
-static ssize_t pointer_sensitivity_store(struct device *dev,
+static ssize_t attr_sensitivity_store_tpkbd(struct device *dev,
 		struct device_attribute *attr,
 		const char *buf,
 		size_t count)
 {
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
 	int value;
 
 	if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
 		return -EINVAL;
 
 	data_pointer->sensitivity = value;
-	tpkbd_features_set(hdev);
+	lenovo_features_set_tpkbd(hdev);
 
 	return count;
 }
 
-static ssize_t pointer_press_speed_show(struct device *dev,
+static ssize_t attr_press_speed_show_tpkbd(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
 
 	return snprintf(buf, PAGE_SIZE, "%u\n",
 		data_pointer->press_speed);
 }
 
-static ssize_t pointer_press_speed_store(struct device *dev,
+static ssize_t attr_press_speed_store_tpkbd(struct device *dev,
 		struct device_attribute *attr,
 		const char *buf,
 		size_t count)
 {
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
 	int value;
 
 	if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
 		return -EINVAL;
 
 	data_pointer->press_speed = value;
-	tpkbd_features_set(hdev);
+	lenovo_features_set_tpkbd(hdev);
 
 	return count;
 }
 
-static struct device_attribute dev_attr_pointer_press_to_select =
+static struct device_attribute dev_attr_press_to_select_tpkbd =
 	__ATTR(press_to_select, S_IWUSR | S_IRUGO,
-			pointer_press_to_select_show,
-			pointer_press_to_select_store);
+			attr_press_to_select_show_tpkbd,
+			attr_press_to_select_store_tpkbd);
 
-static struct device_attribute dev_attr_pointer_dragging =
+static struct device_attribute dev_attr_dragging_tpkbd =
 	__ATTR(dragging, S_IWUSR | S_IRUGO,
-			pointer_dragging_show,
-			pointer_dragging_store);
+			attr_dragging_show_tpkbd,
+			attr_dragging_store_tpkbd);
 
-static struct device_attribute dev_attr_pointer_release_to_select =
+static struct device_attribute dev_attr_release_to_select_tpkbd =
 	__ATTR(release_to_select, S_IWUSR | S_IRUGO,
-			pointer_release_to_select_show,
-			pointer_release_to_select_store);
+			attr_release_to_select_show_tpkbd,
+			attr_release_to_select_store_tpkbd);
 
-static struct device_attribute dev_attr_pointer_select_right =
+static struct device_attribute dev_attr_select_right_tpkbd =
 	__ATTR(select_right, S_IWUSR | S_IRUGO,
-			pointer_select_right_show,
-			pointer_select_right_store);
+			attr_select_right_show_tpkbd,
+			attr_select_right_store_tpkbd);
 
-static struct device_attribute dev_attr_pointer_sensitivity =
+static struct device_attribute dev_attr_sensitivity_tpkbd =
 	__ATTR(sensitivity, S_IWUSR | S_IRUGO,
-			pointer_sensitivity_show,
-			pointer_sensitivity_store);
+			attr_sensitivity_show_tpkbd,
+			attr_sensitivity_store_tpkbd);
 
-static struct device_attribute dev_attr_pointer_press_speed =
+static struct device_attribute dev_attr_press_speed_tpkbd =
 	__ATTR(press_speed, S_IWUSR | S_IRUGO,
-			pointer_press_speed_show,
-			pointer_press_speed_store);
-
-static struct attribute *tpkbd_attributes_pointer[] = {
-	&dev_attr_pointer_press_to_select.attr,
-	&dev_attr_pointer_dragging.attr,
-	&dev_attr_pointer_release_to_select.attr,
-	&dev_attr_pointer_select_right.attr,
-	&dev_attr_pointer_sensitivity.attr,
-	&dev_attr_pointer_press_speed.attr,
+			attr_press_speed_show_tpkbd,
+			attr_press_speed_store_tpkbd);
+
+static struct attribute *lenovo_attributes_tpkbd[] = {
+	&dev_attr_press_to_select_tpkbd.attr,
+	&dev_attr_dragging_tpkbd.attr,
+	&dev_attr_release_to_select_tpkbd.attr,
+	&dev_attr_select_right_tpkbd.attr,
+	&dev_attr_sensitivity_tpkbd.attr,
+	&dev_attr_press_speed_tpkbd.attr,
 	NULL
 };
 
-static const struct attribute_group tpkbd_attr_group_pointer = {
-	.attrs = tpkbd_attributes_pointer,
+static const struct attribute_group lenovo_attr_group_tpkbd = {
+	.attrs = lenovo_attributes_tpkbd,
 };
 
-static enum led_brightness tpkbd_led_brightness_get(
+static enum led_brightness lenovo_led_brightness_get_tpkbd(
 			struct led_classdev *led_cdev)
 {
 	struct device *dev = led_cdev->dev->parent;
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
 	int led_nr = 0;
 
 	if (led_cdev == &data_pointer->led_micmute)
@@ -307,12 +306,12 @@ static enum led_brightness tpkbd_led_brightness_get(
 				: LED_OFF;
 }
 
-static void tpkbd_led_brightness_set(struct led_classdev *led_cdev,
+static void lenovo_led_brightness_set_tpkbd(struct led_classdev *led_cdev,
 			enum led_brightness value)
 {
 	struct device *dev = led_cdev->dev->parent;
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
 	struct hid_report *report;
 	int led_nr = 0;
 
@@ -330,10 +329,10 @@ static void tpkbd_led_brightness_set(struct led_classdev *led_cdev,
 	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
 }
 
-static int tpkbd_probe_tp(struct hid_device *hdev)
+static int lenovo_probe_tpkbd(struct hid_device *hdev)
 {
 	struct device *dev = &hdev->dev;
-	struct tpkbd_data_pointer *data_pointer;
+	struct lenovo_drvdata_tpkbd *data_pointer;
 	size_t name_sz = strlen(dev_name(dev)) + 16;
 	char *name_mute, *name_micmute;
 	int i;
@@ -347,12 +346,12 @@ static int tpkbd_probe_tp(struct hid_device *hdev)
 		return -ENODEV;
 
 	if (sysfs_create_group(&hdev->dev.kobj,
-				&tpkbd_attr_group_pointer)) {
+				&lenovo_attr_group_tpkbd)) {
 		hid_warn(hdev, "Could not create sysfs group\n");
 	}
 
 	data_pointer = devm_kzalloc(&hdev->dev,
-				    sizeof(struct tpkbd_data_pointer),
+				    sizeof(struct lenovo_drvdata_tpkbd),
 				    GFP_KERNEL);
 	if (data_pointer == NULL) {
 		hid_err(hdev, "Could not allocate memory for driver data\n");
@@ -375,23 +374,25 @@ static int tpkbd_probe_tp(struct hid_device *hdev)
 	hid_set_drvdata(hdev, data_pointer);
 
 	data_pointer->led_mute.name = name_mute;
-	data_pointer->led_mute.brightness_get = tpkbd_led_brightness_get;
-	data_pointer->led_mute.brightness_set = tpkbd_led_brightness_set;
+	data_pointer->led_mute.brightness_get = lenovo_led_brightness_get_tpkbd;
+	data_pointer->led_mute.brightness_set = lenovo_led_brightness_set_tpkbd;
 	data_pointer->led_mute.dev = dev;
 	led_classdev_register(dev, &data_pointer->led_mute);
 
 	data_pointer->led_micmute.name = name_micmute;
-	data_pointer->led_micmute.brightness_get = tpkbd_led_brightness_get;
-	data_pointer->led_micmute.brightness_set = tpkbd_led_brightness_set;
+	data_pointer->led_micmute.brightness_get =
+		lenovo_led_brightness_get_tpkbd;
+	data_pointer->led_micmute.brightness_set =
+		lenovo_led_brightness_set_tpkbd;
 	data_pointer->led_micmute.dev = dev;
 	led_classdev_register(dev, &data_pointer->led_micmute);
 
-	tpkbd_features_set(hdev);
+	lenovo_features_set_tpkbd(hdev);
 
 	return 0;
 }
 
-static int tpkbd_probe(struct hid_device *hdev,
+static int lenovo_probe(struct hid_device *hdev,
 		const struct hid_device_id *id)
 {
 	int ret;
@@ -410,7 +411,7 @@ static int tpkbd_probe(struct hid_device *hdev,
 
 	if (hid_get_drvdata(hdev)) {
 		hid_set_drvdata(hdev, NULL);
-		ret = tpkbd_probe_tp(hdev);
+		ret = lenovo_probe_tpkbd(hdev);
 		if (ret)
 			goto err_hid;
 	}
@@ -422,12 +423,12 @@ err:
 	return ret;
 }
 
-static void tpkbd_remove_tp(struct hid_device *hdev)
+static void lenovo_remove_tpkbd(struct hid_device *hdev)
 {
-	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
+	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
 
 	sysfs_remove_group(&hdev->dev.kobj,
-			&tpkbd_attr_group_pointer);
+			&lenovo_attr_group_tpkbd);
 
 	led_classdev_unregister(&data_pointer->led_micmute);
 	led_classdev_unregister(&data_pointer->led_mute);
@@ -435,28 +436,28 @@ static void tpkbd_remove_tp(struct hid_device *hdev)
 	hid_set_drvdata(hdev, NULL);
 }
 
-static void tpkbd_remove(struct hid_device *hdev)
+static void lenovo_remove(struct hid_device *hdev)
 {
 	if (hid_get_drvdata(hdev))
-		tpkbd_remove_tp(hdev);
+		lenovo_remove_tpkbd(hdev);
 
 	hid_hw_stop(hdev);
 }
 
-static const struct hid_device_id tpkbd_devices[] = {
+static const struct hid_device_id lenovo_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
 	{ }
 };
 
-MODULE_DEVICE_TABLE(hid, tpkbd_devices);
+MODULE_DEVICE_TABLE(hid, lenovo_devices);
 
-static struct hid_driver tpkbd_driver = {
-	.name = "lenovo_tpkbd",
-	.id_table = tpkbd_devices,
-	.input_mapping = tpkbd_input_mapping,
-	.probe = tpkbd_probe,
-	.remove = tpkbd_remove,
+static struct hid_driver lenovo_driver = {
+	.name = "lenovo",
+	.id_table = lenovo_devices,
+	.input_mapping = lenovo_input_mapping_tpkbd,
+	.probe = lenovo_probe,
+	.remove = lenovo_remove,
 };
-module_hid_driver(tpkbd_driver);
+module_hid_driver(lenovo_driver);
 
 MODULE_LICENSE("GPL");
-- 
2.0.0


^ permalink raw reply related

* Re: [PATCH] drivers: Let several drivers depends on HAS_IOMEM for 'devm_ioremap_resource'
From: Lennox Wu @ 2014-07-13  9:27 UTC (permalink / raw)
  To: Marek Vasut
  Cc: linux-iio, Benjamin Herrenschmidt, teg, thierry.reding, Chen Gang,
	devel, Liqin Chen, lars, Richard Weinberger, linux-input,
	linux-pwm, linux-watchdog, msalter, Greg Kroah-Hartman,
	dmitry.torokhov, linux-kernel@vger.kernel.org, knaack.h,
	Martin Schwidefsky, Mischa.Jonker, jic23
In-Reply-To: <201407130545.23004.marex@denx.de>

As I said before, some configurations don't make sense.
I don't think all of the patches are necessary.

Best,
Lennox

2014-07-13 11:45 GMT+08:00 Marek Vasut <marex@denx.de>:
> On Sunday, July 13, 2014 at 05:07:10 AM, Chen Gang wrote:
>> Several drivers need 'devm_ioremap_resource' which need HAS_IOMEM enabled.
>> So let them depend on HAS_IOMEM.
>>
>> The related error (with allmodconfig under score):
>>
>>     MODPOST 1365 modules
>>   ERROR: "devm_ioremap_resource" [drivers/watchdog/tegra_wdt.ko] undefined!
>>   ERROR: "devm_ioremap_resource" [drivers/watchdog/of_xilinx_wdt.ko]
>> undefined! ERROR: "devm_ioremap_resource"
>> [drivers/staging/iio/adc/mxs-lradc.ko] undefined! ERROR:
>> "devm_ioremap_resource" [drivers/pwm/pwm-clps711x.ko] undefined! ERROR:
>> "devm_ioremap_resource" [drivers/input/serio/olpc_apsp.ko] undefined!
>> ERROR: "devm_ioremap_resource" [drivers/input/serio/arc_ps2.ko] undefined!
>
> This stuff should go through different trees, so I'd suggest to split this into
> multiple patches. Thanks for catching this stuff !
>
> Best regards,
> Marek Vasut

^ permalink raw reply

* Re: [PATCH] drivers: Let several drivers depends on HAS_IOMEM for 'devm_ioremap_resource'
From: Richard Weinberger @ 2014-07-13  9:45 UTC (permalink / raw)
  To: Lennox Wu, Marek Vasut
  Cc: linux-iio, Benjamin Herrenschmidt, teg, thierry.reding, Chen Gang,
	devel, Liqin Chen, lars, linux-input, linux-pwm, linux-watchdog,
	msalter, Greg Kroah-Hartman, dmitry.torokhov,
	linux-kernel@vger.kernel.org, knaack.h, Martin Schwidefsky,
	Mischa.Jonker, jic23
In-Reply-To: <CAF0htA60juBVkPo2HQKMDGcEr-wRzRVL_6JgHAa+7WVE_E8M0Q@mail.gmail.com>

Am 13.07.2014 11:27, schrieb Lennox Wu:
> As I said before, some configurations don't make sense.

If such a configuration can be achieved using allmod/yesconfig it has to be fixed.
Chen's fixes seem reasonable as not all architectures support iomem.

Thanks,
//richard

^ permalink raw reply

* Re: [PATCH] drivers: Let several drivers depends on HAS_IOMEM for 'devm_ioremap_resource'
From: Chen Gang @ 2014-07-13 10:06 UTC (permalink / raw)
  To: Richard Weinberger
  Cc: linux-iio, Benjamin Herrenschmidt, teg, thierry.reding, Lennox Wu,
	Marek Vasut, Liqin Chen, lars, msalter, linux-pwm, devel,
	linux-watchdog, linux-input, Greg Kroah-Hartman, dmitry.torokhov,
	linux-kernel@vger.kernel.org, knaack.h, Martin Schwidefsky,
	Mischa.Jonker, jic23
In-Reply-To: <53C25551.1050909@nod.at>

On 07/13/2014 05:45 PM, Richard Weinberger wrote:
> Am 13.07.2014 11:27, schrieb Lennox Wu:
>> As I said before, some configurations don't make sense.
> 
> If such a configuration can be achieved using allmod/yesconfig it has to be fixed.
> Chen's fixes seem reasonable as not all architectures support iomem.
>

OK, thanks. And I shall split them into several patches, although we can
understand that score may not need them.


Thanks.
-- 
Chen Gang

Open share and attitude like air water and life which God blessed

^ permalink raw reply

* [PATCH] drivers/input/serio/Kconfig: Let SERIO_ARC_PS2 and SERIO_OLPC_APSP depend on HAS_IOMEM
From: Chen Gang @ 2014-07-13 12:00 UTC (permalink / raw)
  To: dmitry.torokhov
  Cc: Benjamin Herrenschmidt, kys, Martin Schwidefsky, teg,
	Mischa.Jonker, msalter, linux-input, linux-kernel@vger.kernel.org,
	Liqin Chen, Richard Weinberger, Lennox Wu

SERIO_ARC_PS2 and SERIO_OLPC_APSP need HAS_IOMEM, so let them depend on
HAS_IOMEM. The related error (with allmodconfig under score):

    MODPOST 1365 modules
  ERROR: "devm_ioremap_resource" [drivers/input/serio/olpc_apsp.ko] undefined!
  ERROR: "devm_ioremap_resource" [drivers/input/serio/arc_ps2.ko] undefined!


Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
---
 drivers/input/serio/Kconfig | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index bc2d474..449d45f 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -244,6 +244,7 @@ config SERIO_PS2MULT
 
 config SERIO_ARC_PS2
 	tristate "ARC PS/2 support"
+	depends on HAS_IOMEM
 	help
 	  Say Y here if you have an ARC FPGA platform with a PS/2
 	  controller in it.
@@ -263,7 +264,7 @@ config SERIO_APBPS2
 
 config SERIO_OLPC_APSP
 	tristate "OLPC AP-SP input support"
-	depends on OLPC || COMPILE_TEST
+	depends on (OLPC || COMPILE_TEST) && HAS_IOMEM
 	help
 	  Say Y here if you want support for the keyboard and touchpad included
 	  in the OLPC XO-1.75 and XO-4 laptops.
-- 
1.7.11.7

^ permalink raw reply related

* Re: [PATCH] drivers: Let several drivers depends on HAS_IOMEM for 'devm_ioremap_resource'
From: Lars-Peter Clausen @ 2014-07-13 13:26 UTC (permalink / raw)
  To: Richard Weinberger
  Cc: Lennox Wu, Marek Vasut, Chen Gang, Greg Kroah-Hartman,
	linux-kernel@vger.kernel.org, dmitry.torokhov, thierry.reding,
	jic23, wim, Benjamin Herrenschmidt, kys, Martin Schwidefsky, teg,
	Mischa.Jonker, msalter, knaack.h, rdunlap, linux-input, linux-pwm,
	linux-iio, devel, linux-watchdog, Liqin Chen
In-Reply-To: <53C25551.1050909@nod.at>

On 07/13/2014 11:45 AM, Richard Weinberger wrote:
> Am 13.07.2014 11:27, schrieb Lennox Wu:
>> As I said before, some configurations don't make sense.
>
> If such a configuration can be achieved using allmod/yesconfig it has to be fixed.
> Chen's fixes seem reasonable as not all architectures support iomem.

Maybe we should stub out ioremap() and friends when COMPILE_TEST is enabled to 
avoid these linker errors. That's in my opinion better than turning most of the 
'depends on COMPILE_TEST' into 'depends on COMPILE_TEST && HAS_IOMEM'. The 
issue comes up quite a lot and it is often overlooked when adding a driver that 
can be build when COMPILE_TEST is enabled.

- Lars


^ permalink raw reply

* Re: [PATCH] drivers: Let several drivers depends on HAS_IOMEM for 'devm_ioremap_resource'
From: Richard Weinberger @ 2014-07-13 13:40 UTC (permalink / raw)
  To: Lars-Peter Clausen
  Cc: Lennox Wu, Marek Vasut, Chen Gang, Greg Kroah-Hartman,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	thierry.reding-Re5JQEeQqe8AvxtiuMwx3w,
	jic23-DgEjT+Ai2ygdnm+yROfE0A, wim-IQzOog9fTRqzQB+pC5nmwQ,
	Benjamin Herrenschmidt, kys-0li6OtcxBFHby3iVrkZq2A,
	Martin Schwidefsky, teg-B22kvLQNl6c,
	Mischa.Jonker-HKixBCOQz3hWk0Htik3J/w,
	msalter-H+wXaHxf7aLQT0dZR+AlfA, knaack.h-Mmb7MZpHnFY,
	rdunlap-wEGCiKHe2LqWVfeAwA7xHQ,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-pwm-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devel-gWbeCf7V1WCQmaza687I9mD2FQJk+8+b,
	linux-watchdog-u79uwXL29TY76Z2rM5mHXA, Liqin Chen
In-Reply-To: <53C288F0.3070001-Qo5EllUWu/uELgA04lAiVw@public.gmane.org>

Am 13.07.2014 15:26, schrieb Lars-Peter Clausen:
> On 07/13/2014 11:45 AM, Richard Weinberger wrote:
>> Am 13.07.2014 11:27, schrieb Lennox Wu:
>>> As I said before, some configurations don't make sense.
>>
>> If such a configuration can be achieved using allmod/yesconfig it has to be fixed.
>> Chen's fixes seem reasonable as not all architectures support iomem.
> 
> Maybe we should stub out ioremap() and friends when COMPILE_TEST is enabled to avoid these linker errors. That's in my opinion better than turning most of the 'depends on
> COMPILE_TEST' into 'depends on COMPILE_TEST && HAS_IOMEM'. The issue comes up quite a lot and it is often overlooked when adding a driver that can be build when COMPILE_TEST is
> enabled.

And what should this stub do?
Except calling BUG()...

Thanks,
//richard

^ permalink raw reply

* Re: [PATCH] drivers: Let several drivers depends on HAS_IOMEM for 'devm_ioremap_resource'
From: Lars-Peter Clausen @ 2014-07-13 13:56 UTC (permalink / raw)
  To: Richard Weinberger
  Cc: Lennox Wu, Marek Vasut, Chen Gang, Greg Kroah-Hartman,
	linux-kernel@vger.kernel.org, dmitry.torokhov, thierry.reding,
	jic23, wim, Benjamin Herrenschmidt, kys, Martin Schwidefsky, teg,
	Mischa.Jonker, msalter, knaack.h, rdunlap, linux-input, linux-pwm,
	linux-iio, devel, linux-watchdog, Liqin Chen
In-Reply-To: <53C28C4A.70907@nod.at>

On 07/13/2014 03:40 PM, Richard Weinberger wrote:
> Am 13.07.2014 15:26, schrieb Lars-Peter Clausen:
>> On 07/13/2014 11:45 AM, Richard Weinberger wrote:
>>> Am 13.07.2014 11:27, schrieb Lennox Wu:
>>>> As I said before, some configurations don't make sense.
>>>
>>> If such a configuration can be achieved using allmod/yesconfig it has to be fixed.
>>> Chen's fixes seem reasonable as not all architectures support iomem.
>>
>> Maybe we should stub out ioremap() and friends when COMPILE_TEST is enabled to avoid these linker errors. That's in my opinion better than turning most of the 'depends on
>> COMPILE_TEST' into 'depends on COMPILE_TEST && HAS_IOMEM'. The issue comes up quite a lot and it is often overlooked when adding a driver that can be build when COMPILE_TEST is
>> enabled.
>
> And what should this stub do?
> Except calling BUG()...

return NULL;

It's for compile testing, it's not meant to work at runtime.

- Lars


^ permalink raw reply

* Re: [PATCH] drivers: Let several drivers depends on HAS_IOMEM for 'devm_ioremap_resource'
From: Richard Weinberger @ 2014-07-13 14:03 UTC (permalink / raw)
  To: Lars-Peter Clausen
  Cc: Lennox Wu, Marek Vasut, Chen Gang, Greg Kroah-Hartman,
	linux-kernel@vger.kernel.org, dmitry.torokhov, thierry.reding,
	jic23, wim, Benjamin Herrenschmidt, kys, Martin Schwidefsky, teg,
	Mischa.Jonker, msalter, knaack.h, rdunlap, linux-input, linux-pwm,
	linux-iio, devel, linux-watchdog, Liqin Chen
In-Reply-To: <53C29015.5070607@metafoo.de>

Am 13.07.2014 15:56, schrieb Lars-Peter Clausen:
> On 07/13/2014 03:40 PM, Richard Weinberger wrote:
>> Am 13.07.2014 15:26, schrieb Lars-Peter Clausen:
>>> On 07/13/2014 11:45 AM, Richard Weinberger wrote:
>>>> Am 13.07.2014 11:27, schrieb Lennox Wu:
>>>>> As I said before, some configurations don't make sense.
>>>>
>>>> If such a configuration can be achieved using allmod/yesconfig it has to be fixed.
>>>> Chen's fixes seem reasonable as not all architectures support iomem.
>>>
>>> Maybe we should stub out ioremap() and friends when COMPILE_TEST is enabled to avoid these linker errors. That's in my opinion better than turning most of the 'depends on
>>> COMPILE_TEST' into 'depends on COMPILE_TEST && HAS_IOMEM'. The issue comes up quite a lot and it is often overlooked when adding a driver that can be build when COMPILE_TEST is
>>> enabled.
>>
>> And what should this stub do?
>> Except calling BUG()...
> 
> return NULL;
> 
> It's for compile testing, it's not meant to work at runtime.

Hm, I really don't like the idea of having a non-working kernel.
IMHO either it should build _and_ run and nothing else.
Greg, what do you think?

Thanks,
//richard

^ permalink raw reply

* Re: [PATCH] drivers: Let several drivers depends on HAS_IOMEM for 'devm_ioremap_resource'
From: Lars-Peter Clausen @ 2014-07-13 14:25 UTC (permalink / raw)
  To: Richard Weinberger
  Cc: dmitry.torokhov, linux-iio, Benjamin Herrenschmidt, teg,
	thierry.reding, Lennox Wu, Chen Gang, Marek Vasut, Liqin Chen,
	msalter, linux-pwm, devel, linux-watchdog, linux-input,
	Greg Kroah-Hartman, linux-kernel@vger.kernel.org, knaack.h,
	Martin Schwidefsky, Mischa.Jonker, jic23
In-Reply-To: <53C291C8.6050303@nod.at>

On 07/13/2014 04:03 PM, Richard Weinberger wrote:
> Am 13.07.2014 15:56, schrieb Lars-Peter Clausen:
>> On 07/13/2014 03:40 PM, Richard Weinberger wrote:
>>> Am 13.07.2014 15:26, schrieb Lars-Peter Clausen:
>>>> On 07/13/2014 11:45 AM, Richard Weinberger wrote:
>>>>> Am 13.07.2014 11:27, schrieb Lennox Wu:
>>>>>> As I said before, some configurations don't make sense.
>>>>>
>>>>> If such a configuration can be achieved using allmod/yesconfig it has to be fixed.
>>>>> Chen's fixes seem reasonable as not all architectures support iomem.
>>>>
>>>> Maybe we should stub out ioremap() and friends when COMPILE_TEST is enabled to avoid these linker errors. That's in my opinion better than turning most of the 'depends on
>>>> COMPILE_TEST' into 'depends on COMPILE_TEST && HAS_IOMEM'. The issue comes up quite a lot and it is often overlooked when adding a driver that can be build when COMPILE_TEST is
>>>> enabled.
>>>
>>> And what should this stub do?
>>> Except calling BUG()...
>>
>> return NULL;
>>
>> It's for compile testing, it's not meant to work at runtime.
>
> Hm, I really don't like the idea of having a non-working kernel.
> IMHO either it should build _and_ run and nothing else.
> Greg, what do you think?

The kernel will still be working fine and you can run it on a system. The 
drivers which use ioremap() or similar are probably not instantiated on a 
system that does not provide HAS_IOMEM. But even if it was the driver should 
handle ioremap() returning NULL gracefully and abort the driver probe. That 
said you'll probably not run a kernel that was built with COMPILE_TEST on your 
real hardware since it contains so many drivers that are completely useless on 
your hardware. The idea of COMPILE_TEST is to have as much compile test 
exposure as possible to the code that is enabled by COMPILE_TEST. Stubbing out 
ioremap() and friends when HAS_IOMEM is not set and COMPILE_TEST is set makes 
it easier to get there.

- Lars

^ permalink raw reply

* Re: [PATCH] drivers: Let several drivers depends on HAS_IOMEM for 'devm_ioremap_resource'
From: Chen Gang @ 2014-07-13 14:28 UTC (permalink / raw)
  To: gregkh
  Cc: linux-iio, benh, teg, thierry.reding, Lennox Wu, marex,
	Liqin Chen, lars, richard, linux-input, Guenter Roeck, linux-pwm,
	devel, linux-watchdog, msalter, dmitry.torokhov,
	linux-kernel@vger.kernel.org, knaack.h, schwidefsky,
	David Rientjes, Mischa.Jonker, jic23
In-Reply-To: <53C1F98D.9030603@gmail.com>

On 07/13/2014 11:14 AM, Chen Gang wrote:
[...]
> And also find a compiler issue, I will try to fix it, but shall not notify
> kernel mailing list, again. The related issue is below (it seems a kernel
> issue, but in fact, it is a compiler's issue):
> 
>     CC [M]  drivers/staging/lustre/lustre/ptlrpc/sec.o
>   drivers/staging/lustre/lustre/ptlrpc/sec.c: In function 'sptlrpc_cli_ctx_expire':
>   drivers/staging/lustre/lustre/ptlrpc/sec.c:309:13: error: 'struct ptlrpc_ctx_ops' has no member named '__die'
>     ctx->cc_ops->die(ctx, 0);
>                ^
>   drivers/staging/lustre/lustre/ptlrpc/sec.c: In function 'ctx_refresh_timeout':
>   drivers/staging/lustre/lustre/ptlrpc/sec.c:594:26: error: 'struct ptlrpc_ctx_ops' has no member named '__die'
>      req->rq_cli_ctx->cc_ops->die(req->rq_cli_ctx, 0);
>                             ^
>   make[5]: *** [drivers/staging/lustre/lustre/ptlrpc/sec.o] Error 1
>   make[4]: *** [drivers/staging/lustre/lustre/ptlrpc] Error 2
>   make[3]: *** [drivers/staging/lustre/lustre] Error 2
>   make[2]: *** [drivers/staging/lustre] Error 2
>   make[1]: *** [drivers/staging] Error 2
>   make: *** [drivers] Error 2
> 

Oh, sorry, after check related details, this is still a kernel issue,
'die' is a macro which defined by most of architectures, so can not
use this common name as a declaration in any other area.

I shall send related patch for it.

Thanks.
-- 
Chen Gang

Open share and attitude like air water and life which God blessed

^ permalink raw reply

* Re: [PATCH] drivers: Let several drivers depends on HAS_IOMEM for 'devm_ioremap_resource'
From: Chen Gang @ 2014-07-13 15:02 UTC (permalink / raw)
  To: Lars-Peter Clausen
  Cc: dmitry.torokhov, linux-iio, Benjamin Herrenschmidt, teg,
	thierry.reding, Lennox Wu, Marek Vasut, Liqin Chen,
	Richard Weinberger, msalter, linux-pwm, devel, linux-watchdog,
	linux-input, Greg Kroah-Hartman, linux-kernel@vger.kernel.org,
	knaack.h, Martin Schwidefsky, Mischa.Jonker, jic23
In-Reply-To: <53C296C2.30304@metafoo.de>

On 07/13/2014 10:25 PM, Lars-Peter Clausen wrote:
> On 07/13/2014 04:03 PM, Richard Weinberger wrote:
>> Am 13.07.2014 15:56, schrieb Lars-Peter Clausen:
>>> On 07/13/2014 03:40 PM, Richard Weinberger wrote:
>>>> Am 13.07.2014 15:26, schrieb Lars-Peter Clausen:
>>>>> On 07/13/2014 11:45 AM, Richard Weinberger wrote:
>>>>>> Am 13.07.2014 11:27, schrieb Lennox Wu:
>>>>>>> As I said before, some configurations don't make sense.
>>>>>>
>>>>>> If such a configuration can be achieved using allmod/yesconfig it has to be fixed.
>>>>>> Chen's fixes seem reasonable as not all architectures support iomem.
>>>>>
>>>>> Maybe we should stub out ioremap() and friends when COMPILE_TEST is enabled to avoid these linker errors. That's in my opinion better than turning most of the 'depends on
>>>>> COMPILE_TEST' into 'depends on COMPILE_TEST && HAS_IOMEM'. The issue comes up quite a lot and it is often overlooked when adding a driver that can be build when COMPILE_TEST is
>>>>> enabled.
>>>>
>>>> And what should this stub do?
>>>> Except calling BUG()...
>>>
>>> return NULL;
>>>
>>> It's for compile testing, it's not meant to work at runtime.
>>
>> Hm, I really don't like the idea of having a non-working kernel.
>> IMHO either it should build _and_ run and nothing else.
>> Greg, what do you think?
> 
> The kernel will still be working fine and you can run it on a system. The drivers which use ioremap() or similar are probably not instantiated on a system that does not provide HAS_IOMEM. But even if it was the driver should handle ioremap() returning NULL gracefully and abort the driver probe. That said you'll probably not run a kernel that was built with COMPILE_TEST on your real hardware since it contains so many drivers that are completely useless on your hardware. The idea of COMPILE_TEST is to have as much compile test exposure as possible to the code that is enabled by COMPILE_TEST. Stubbing out ioremap() and friends when HAS_IOMEM is not set and COMPILE_TEST is set makes it easier to get there.
> 

For me, welcome Greg's idea or suggestion for it.

And also if the reply contents are wrapped (e.g. within 80 or less), that
will generate a better display under other members' email clients.


Thanks
-- 
Chen Gang

Open share and attitude like air water and life which God blessed

^ permalink raw reply

* [PATCH] Input: ambakmi - Use managed interfaces
From: Himangi Saraogi @ 2014-07-13 17:30 UTC (permalink / raw)
  To: Russell King, Dmitry Torokhov, linux-input, linux-kernel; +Cc: julia.lawall

This patch introduces the use of managed interfaces like devm_clk_get,
devm_kalloc etc. devm_ioremap_resource is used instead of
amba_request_regions and devm_ioremap. It also does away with the functions
to free the allocated memory in probe and remove functions. Also, some
labels in the probe function are removed.

Signed-off-by: Himangi Saraogi <himangi774@gmail.com>
Acked-by: Julia Lawall <julia.lawall@lip6.fr>
---
 drivers/input/serio/ambakmi.c | 44 ++++++++++---------------------------------
 1 file changed, 10 insertions(+), 34 deletions(-)

diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c
index 8b748d9..405a175 100644
--- a/drivers/input/serio/ambakmi.c
+++ b/drivers/input/serio/ambakmi.c
@@ -23,6 +23,7 @@
 #include <linux/clk.h>
 
 #include <asm/io.h>
+#include <linux/io.h>
 #include <asm/irq.h>
 
 #define KMI_BASE	(kmi->base)
@@ -112,19 +113,10 @@ static int amba_kmi_probe(struct amba_device *dev,
 {
 	struct amba_kmi_port *kmi;
 	struct serio *io;
-	int ret;
-
-	ret = amba_request_regions(dev, NULL);
-	if (ret)
-		return ret;
-
-	kmi = kzalloc(sizeof(struct amba_kmi_port), GFP_KERNEL);
-	io = kzalloc(sizeof(struct serio), GFP_KERNEL);
-	if (!kmi || !io) {
-		ret = -ENOMEM;
-		goto out;
-	}
 
+	io = devm_kzalloc(&dev->dev, sizeof(struct serio), GFP_KERNEL);
+	if (!io)
+		return -ENOMEM;
 
 	io->id.type	= SERIO_8042;
 	io->write	= amba_kmi_write;
@@ -135,32 +127,20 @@ static int amba_kmi_probe(struct amba_device *dev,
 	io->port_data	= kmi;
 	io->dev.parent	= &dev->dev;
 
+	kmi->base	= devm_ioremap_resource(&dev->dev, &dev->res);
+	if (IS_ERR(kmi->base))
+		return PTR_ERR(kmi->base);
 	kmi->io		= io;
-	kmi->base	= ioremap(dev->res.start, resource_size(&dev->res));
-	if (!kmi->base) {
-		ret = -ENOMEM;
-		goto out;
-	}
 
-	kmi->clk = clk_get(&dev->dev, "KMIREFCLK");
-	if (IS_ERR(kmi->clk)) {
-		ret = PTR_ERR(kmi->clk);
-		goto unmap;
-	}
+	kmi->clk = devm_clk_get(&dev->dev, "KMIREFCLK");
+	if (IS_ERR(kmi->clk))
+		return PTR_ERR(kmi->clk);
 
 	kmi->irq = dev->irq[0];
 	amba_set_drvdata(dev, kmi);
 
 	serio_register_port(kmi->io);
 	return 0;
-
- unmap:
-	iounmap(kmi->base);
- out:
-	kfree(kmi);
-	kfree(io);
-	amba_release_regions(dev);
-	return ret;
 }
 
 static int amba_kmi_remove(struct amba_device *dev)
@@ -168,10 +148,6 @@ static int amba_kmi_remove(struct amba_device *dev)
 	struct amba_kmi_port *kmi = amba_get_drvdata(dev);
 
 	serio_unregister_port(kmi->io);
-	clk_put(kmi->clk);
-	iounmap(kmi->base);
-	kfree(kmi);
-	amba_release_regions(dev);
 	return 0;
 }
 
-- 
1.9.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox