Skip to content
Closed
3 changes: 3 additions & 0 deletions common/yocto-imx93-frdm-labs-vars.tex
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
\def\labbooktitle{Yocto Project and OpenEmbedded Training}
\def\labbooksubtitle{imx93-frdm variant}
\def\labboard{imx93-frdm}
2 changes: 2 additions & 0 deletions common/yocto-imx93-frdm-title.tex
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
\def \trainingurl{https://bootlin.com/training/yocto}
\def \trainingtitle{Yocto Project and OpenEmbedded system development}
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
From d39c48a071eb30802429a9ecd405734fdd67f2c5 Mon Sep 17 00:00:00 2001
From: Antoine Picard <antoine.picard@bootlin.com>
Date: Mon, 11 Aug 2025 15:04:00 +0200
Subject: [PATCH 1/2] Add nunchuk driver

Signed-off-by: Antoine Picard <antoine.picard@bootlin.com>
---
drivers/input/joystick/Kconfig | 13 ++
drivers/input/joystick/Makefile | 1 +
drivers/input/joystick/wiichuck.c | 204 ++++++++++++++++++++++++++++++
3 files changed, 218 insertions(+)
create mode 100644 drivers/input/joystick/wiichuck.c

diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
index ac6925ce8366..e155f724b789 100644
--- a/drivers/input/joystick/Kconfig
+++ b/drivers/input/joystick/Kconfig
@@ -207,6 +207,19 @@ config JOYSTICK_TWIDJOY
To compile this driver as a module, choose M here: the
module will be called twidjoy.

+config JOYSTICK_WIICHUCK
+ tristate "Nintendo Wiimote Extension connector on i2c bus"
+ depends on I2C
+ select INPUT_POLLDEV
+ help
+ Say Y here if you have a Nintendo Wiimote extension connector
+ attached directly to an i2c bus, like the Sparcfun Wiichuck adapter
+ board. This driver supports both the Nunchuk and the Classic
+ Controller extensions.
+
+ To compile this driver as a module, choose M here: the
+ modules will be called wiichuck.
+
config JOYSTICK_ZHENHUA
tristate "5-byte Zhenhua RC transmitter"
select SERIO
diff --git a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile
index 3937535f0098..7dee2e46303d 100644
--- a/drivers/input/joystick/Makefile
+++ b/drivers/input/joystick/Makefile
@@ -38,5 +38,6 @@ obj-$(CONFIG_JOYSTICK_TURBOGRAFX) += turbografx.o
obj-$(CONFIG_JOYSTICK_TWIDJOY) += twidjoy.o
obj-$(CONFIG_JOYSTICK_WARRIOR) += warrior.o
obj-$(CONFIG_JOYSTICK_WALKERA0701) += walkera0701.o
+obj-$(CONFIG_JOYSTICK_WIICHUCK) += wiichuck.o
obj-$(CONFIG_JOYSTICK_XPAD) += xpad.o
obj-$(CONFIG_JOYSTICK_ZHENHUA) += zhenhua.o
diff --git a/drivers/input/joystick/wiichuck.c b/drivers/input/joystick/wiichuck.c
new file mode 100644
index 000000000000..9ba1c5b82a9b
--- /dev/null
+++ b/drivers/input/joystick/wiichuck.c
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Available on SOLUTION_URL */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/version.h>
+
+/* Per device structure */
+struct nunchuk_dev {
+ struct i2c_client *i2c_client;
+};
+
+static int nunchuk_read_registers(struct i2c_client *client, u8 *recv)
+{
+ u8 buf[1];
+ int ret;
+
+ /* Ask the device to get ready for a read */
+ usleep_range(10000, 20000);
+
+ buf[0] = 0x00;
+ ret = i2c_master_send(client, buf, 1);
+ if (ret < 0) {
+ dev_err(&client->dev, "i2c send failed (%d)\n", ret);
+ return ret;
+ }
+
+ usleep_range(10000, 20000);
+
+ /* Now read registers */
+ ret = i2c_master_recv(client, recv, 6);
+ if (ret < 0) {
+ dev_err(&client->dev, "i2c recv failed (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void nunchuk_poll(struct input_dev *input)
+{
+ u8 recv[6];
+ int zpressed, cpressed, bx, by;
+
+ /* Retrieve the physical i2c device */
+ struct nunchuk_dev *nunchuk = input_get_drvdata(input);
+ struct i2c_client *client = nunchuk->i2c_client;
+
+ /* Get the state of the device registers */
+ if (nunchuk_read_registers(client, recv) < 0)
+ return;
+
+ zpressed = (recv[5] & BIT(0)) ? 0 : 1;
+ cpressed = (recv[5] & BIT(1)) ? 0 : 1;
+ bx = recv[0];
+ by = recv[1];
+
+ /* Send events to the INPUT subsystem */
+ input_report_key(input, BTN_Z, zpressed);
+ input_report_key(input, BTN_C, cpressed);
+
+ input_report_abs(input, ABS_X, bx);
+ input_report_abs(input, ABS_Y, by);
+
+ input_sync(input);
+}
+
+static int nunchuk_probe(struct i2c_client *client)
+{
+ struct nunchuk_dev *nunchuk;
+ struct input_dev *input;
+ u8 buf[2];
+ int ret;
+
+ /* Allocate per device structure */
+ nunchuk = devm_kzalloc(&client->dev, sizeof(*nunchuk), GFP_KERNEL);
+ if (!nunchuk)
+ /* No message necessary here, already issued by allocation functions */
+ return -ENOMEM;
+
+ /* Initialize device */
+ buf[0] = 0xf0;
+ buf[1] = 0x55;
+
+ ret = i2c_master_send(client, buf, 2);
+ if (ret < 0) {
+ dev_err(&client->dev, "i2c send failed (%d)\n", ret);
+ return ret;
+ }
+
+ udelay(1000);
+
+ buf[0] = 0xfb;
+ buf[1] = 0x00;
+
+ ret = i2c_master_send(client, buf, 2);
+ if (ret < 0) {
+ dev_err(&client->dev, "i2c send failed (%d)\n", ret);
+ return ret;
+ }
+
+ /* Allocate input device */
+ input = devm_input_allocate_device(&client->dev);
+ if (!input)
+ return -ENOMEM;
+
+ /*
+ * Implement pointers from logical to physical. Here, no need for
+ * physical to logical pointers as unregistering and freeing the
+ * polled_input device will be automatic.
+ */
+ nunchuk->i2c_client = client;
+ input_set_drvdata(input, nunchuk);
+
+ /* Configure input device */
+ input->name = "Wii Nunchuk";
+ input->id.bustype = BUS_I2C;
+
+ set_bit(EV_KEY, input->evbit);
+ set_bit(BTN_C, input->keybit);
+ set_bit(BTN_Z, input->keybit);
+
+ set_bit(EV_ABS, input->evbit);
+ set_bit(ABS_X, input->absbit);
+ set_bit(ABS_Y, input->absbit);
+ input_set_abs_params(input, ABS_X, 30, 220, 4, 8);
+ input_set_abs_params(input, ABS_Y, 40, 200, 4, 8);
+
+ /* Classic buttons */
+ set_bit(BTN_TL, input->keybit);
+ set_bit(BTN_SELECT, input->keybit);
+ set_bit(BTN_MODE, input->keybit);
+ set_bit(BTN_START, input->keybit);
+ set_bit(BTN_TR, input->keybit);
+ set_bit(BTN_TL2, input->keybit);
+ set_bit(BTN_B, input->keybit);
+ set_bit(BTN_Y, input->keybit);
+ set_bit(BTN_A, input->keybit);
+ set_bit(BTN_X, input->keybit);
+ set_bit(BTN_TR2, input->keybit);
+
+ /* Register and configure polling function */
+ ret = input_setup_polling(input, nunchuk_poll);
+ if (ret) {
+ dev_err(&client->dev, "Failed to set polling function (%d)\n",
+ ret);
+ return ret;
+ }
+
+ input_set_poll_interval(input, 50);
+
+ /* Register the input device when everything is ready */
+ ret = input_register_device(input);
+ if (ret) {
+ dev_err(&client->dev, "Cannot register input device (%d)\n",
+ ret);
+ return ret;
+ }
+
+
+ pr_info("Nunchuk device probed successfully\n");
+ return 0;
+}
+
+#if KERNEL_VERSION(5, 16, 0) <= LINUX_VERSION_CODE
+static void nunchuk_remove(struct i2c_client *client)
+#else
+static int nunchuk_remove(struct i2c_client *client)
+#endif
+{
+ /*
+ * Nothing to do here, as the polled_input device is automatically
+ * unregistered and freed thanks to the use of
+ * devm_input_allocate_device.
+ */
+
+ pr_info("Nunchuk device removed successfully\n");
+ #if KERNEL_VERSION(5, 16, 0) > LINUX_VERSION_CODE
+ return 0;
+ #endif
+}
+
+/* Specification of supported Device Tree devices */
+static const struct of_device_id nunchuk_dt_match[] = {
+ { .compatible = "nintendo,nunchuk" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, nunchuk_dt_match);
+
+/* Driver declaration */
+static struct i2c_driver nunchuk_driver = {
+ .driver = {
+ .name = "nunchuk",
+ .of_match_table = nunchuk_dt_match,
+ },
+ .probe = nunchuk_probe,
+ .remove = nunchuk_remove,
+};
+module_i2c_driver(nunchuk_driver);
+
+MODULE_LICENSE("GPL");
\ No newline at end of file
--
2.43.0

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
From 14992179c3b01d073dd19d9e59658264595bf269 Mon Sep 17 00:00:00 2001
From: Antoine Picard <antoine.picard@bootlin.com>
Date: Mon, 11 Aug 2025 15:16:13 +0200
Subject: [PATCH 2/2] Add description of nunchuck on i2c

Signed-off-by: Antoine Picard <antoine.picard@bootlin.com>
---
arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts
index d219e244d53b..db415ed223c6 100644
--- a/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts
+++ b/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts
@@ -353,12 +353,17 @@ &lpm {
&lpi2c1 {
#address-cells = <1>;
#size-cells = <0>;
- clock-frequency = <400000>;
+ clock-frequency = <100000>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&pinctrl_lpi2c1>;
pinctrl-1 = <&pinctrl_lpi2c1>;
status = "okay";

+ nunchuk: joystick@52 {
+ compatible = "nintendo,nunchuk";
+ reg = <0x52>;
+ };
+
lvds_bridge: lvds-to-hdmi-bridge@4c {
compatible = "ite,it6263";
reg = <0x4c>;
--
2.43.0

Loading