[RFC PATCH 2/3] drivers/mfd: rpisense: Raspberry Pi senseHAT joystick driver
From: Joel Savitz
Date: Fri Aug 06 2021 - 20:28:06 EST
This patch implements support for the joystick, including a threaded
IRQ routine.
Signed-off-by: Charles Mirabile <cmirabil@xxxxxxxxxx>
Signed-off-by: Mwesigwa Guma <mguma@xxxxxxxxxx>
Signed-off-by: Joel Savitz <jsavitz@xxxxxxxxxx>
---
drivers/mfd/Makefile | 1 +
drivers/mfd/rpisense-js.c | 132 ++++++++++++++++++++++++++++++++++++++
2 files changed, 133 insertions(+)
create mode 100644 drivers/mfd/rpisense-js.c
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 76f9a9221241..71356153ccdc 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -264,6 +264,7 @@ obj-$(CONFIG_MFD_ROHM_BD957XMUF) += rohm-bd9576.o
obj-$(CONFIG_MFD_STMFX) += stmfx.o
obj-$(CONFIG_MFD_KHADAS_MCU) += khadas-mcu.o
obj-$(CONFIG_MFD_RPISENSE) += rpisense-core.o
+obj-$(CONFIG_MFD_RPISENSE) += rpisense-js.o
obj-$(CONFIG_MFD_ACER_A500_EC) += acer-ec-a500.o
obj-$(CONFIG_MFD_QCOM_PM8008) += qcom-pm8008.o
diff --git a/drivers/mfd/rpisense-js.c b/drivers/mfd/rpisense-js.c
new file mode 100644
index 000000000000..c6c97bff118c
--- /dev/null
+++ b/drivers/mfd/rpisense-js.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Raspberry Pi Sense HAT joystick driver
+ * http://raspberrypi.org
+ *
+ * Copyright (C) 2015 Raspberry Pi
+ * Copyright (C) 2021 Charles Mirabile, Mwesigwa Guma, Joel Savitz
+ *
+ * Original Author: Serge Schneider
+ * Revised for upstream Linux by: Charles Mirabile, Mwesigwa Guma, Joel Savitz
+ */
+
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/gpio/consumer.h>
+#include <linux/platform_device.h>
+
+#include <linux/mfd/rpisense.h>
+
+static unsigned char keymap[] = {KEY_DOWN, KEY_RIGHT, KEY_UP, KEY_ENTER, KEY_LEFT,};
+
+static irqreturn_t rpisense_js_report(int n, void *cookie)
+{
+ int i;
+ static s32 prev_keys;
+ struct rpisense *rpisense = cookie;
+ struct rpisense_js *rpisense_js = &rpisense->joystick;
+ s32 keys = rpisense_get_joystick_state(rpisense);
+ s32 changes = keys ^ prev_keys;
+
+ prev_keys = keys;
+ for (i = 0; i < ARRAY_SIZE(keymap); ++i) {
+ if (changes & (1<<i)) {
+ input_report_key(rpisense_js->keys_dev,
+ keymap[i], keys & (1<<i));
+ }
+ }
+ input_sync(rpisense_js->keys_dev);
+ return IRQ_HANDLED;
+}
+
+static int rpisense_js_probe(struct platform_device *pdev)
+{
+ int ret;
+ int i;
+ struct rpisense *rpisense = dev_get_drvdata(&pdev->dev);
+ struct rpisense_js *rpisense_js = &rpisense->joystick;
+
+ rpisense_js->keys_desc = devm_gpiod_get(&rpisense->i2c_client->dev,
+ "keys-int", GPIOD_IN);
+ if (IS_ERR(rpisense_js->keys_desc)) {
+ dev_warn(&pdev->dev, "Failed to get keys-int descriptor.\n");
+ return PTR_ERR(rpisense_js->keys_desc);
+ }
+
+
+ rpisense_js->keys_dev = devm_input_allocate_device(&pdev->dev);
+ if (rpisense_js->keys_dev == NULL) {
+ dev_err(&pdev->dev, "Could not allocate input device.\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(keymap); i++) {
+ set_bit(keymap[i],
+ rpisense_js->keys_dev->keybit);
+ }
+
+ rpisense_js->keys_dev->name = "Raspberry Pi Sense HAT Joystick";
+ rpisense_js->keys_dev->phys = "rpi-sense-joy/input0";
+ rpisense_js->keys_dev->id.bustype = BUS_I2C;
+ rpisense_js->keys_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
+ rpisense_js->keys_dev->keycode = keymap;
+ rpisense_js->keys_dev->keycodesize = sizeof(unsigned char);
+ rpisense_js->keys_dev->keycodemax = ARRAY_SIZE(keymap);
+
+ ret = input_register_device(rpisense_js->keys_dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not register input device.\n");
+ return ret;
+ }
+
+ ret = gpiod_direction_input(rpisense_js->keys_desc);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not set keys-int direction.\n");
+ return ret;
+ }
+
+ rpisense_js->keys_irq = gpiod_to_irq(rpisense_js->keys_desc);
+ if (rpisense_js->keys_irq < 0) {
+ dev_err(&pdev->dev, "Could not determine keys-int IRQ.\n");
+ return rpisense_js->keys_irq;
+ }
+
+ ret = devm_request_threaded_irq(&pdev->dev, rpisense_js->keys_irq,
+ NULL, rpisense_js_report, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ "keys", rpisense);
+
+ if (ret) {
+ dev_err(&pdev->dev, "IRQ request failed.\n");
+ return ret;
+ }
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id rpisense_js_id[] = {
+ { .compatible = "rpi,rpi-sense-js" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, rpisense_js_id);
+#endif
+
+static struct platform_device_id rpisense_js_device_id[] = {
+ { .name = "rpi-sense-js" },
+ { },
+};
+MODULE_DEVICE_TABLE(platform, rpisense_js_device_id);
+
+static struct platform_driver rpisense_js_driver = {
+ .probe = rpisense_js_probe,
+ .driver = {
+ .name = "rpi-sense-js",
+ },
+};
+
+module_platform_driver(rpisense_js_driver);
+
+MODULE_DESCRIPTION("Raspberry Pi Sense HAT joystick driver");
+MODULE_AUTHOR("Serge Schneider <serge@xxxxxxxxxxxxxxx>");
+MODULE_LICENSE("GPL");
--
2.27.0