aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-06-15 17:03:57 +0200
committerLoek Le Blansch <loek@pipeframe.xyz>2024-06-15 17:03:57 +0200
commitdc3e1220a3bc60c2f845477b3d5babd3e00e6ea8 (patch)
treebe3280aafe3db7cca6fd661ee61a4f8d093ebfab
parent310a0a145a807706e68200be6cf28f18f6886fd0 (diff)
first attempt i2c driver
-rw-r--r--driver/main.c31
-rw-r--r--driver/main.h20
-rw-r--r--driver/platform.c81
-rw-r--r--driver/platform.h41
-rw-r--r--dts/am335x-boneblack-uboot.dts15
-rw-r--r--readme.md2
6 files changed, 35 insertions, 155 deletions
diff --git a/driver/main.c b/driver/main.c
index 92ff9aa..2097edd 100644
--- a/driver/main.c
+++ b/driver/main.c
@@ -1,13 +1,9 @@
-// #include <linux/cdev.h>
#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
+#include <linux/i2c.h>
#include "main.h"
#include "platform.h"
-// struct cdev *cdev;
struct device *dev;
struct class *class;
dev_t node = 0; // do not register /dev/lork
@@ -30,30 +26,14 @@ static int mod_init(void) {
}
// create platform driver
- err = platform_driver_register(&lork_driver);
+ err = i2c_add_driver(&lork_driver);
if (err) goto free_platform_driver;
- // create driver attribute under /sys/bus/platform/drivers/gpio-extern
- err = driver_create_file(&lork_driver.driver, &drv_attr_int);
- if (err) goto free_drv_attr_int;
-
- // create device attributes under /sys/class
- err = device_create_file(dev, &dev_attr_int);
- if (err) goto free_dev_attr_int;
- err = device_create_file(dev, &dev_attr_str);
- if (err) goto free_dev_attr_str;
-
printk("%s() OK\n", __PRETTY_FUNCTION__);
return 0;
-free_dev_attr_str:
- device_remove_file(dev, &dev_attr_str);
-free_dev_attr_int:
- device_remove_file(dev, &dev_attr_int);
-free_drv_attr_int:
- driver_remove_file(&lork_driver.driver, &drv_attr_int);
free_platform_driver:
- platform_driver_unregister(&lork_driver);
+ i2c_del_driver(&lork_driver);
free_device:
device_destroy(class, node);
free_class:
@@ -63,10 +43,7 @@ free_class:
}
static void mod_exit(void) {
- device_remove_file(dev, &dev_attr_str);
- device_remove_file(dev, &dev_attr_int);
- driver_remove_file(&lork_driver.driver, &drv_attr_int);
- platform_driver_unregister(&lork_driver);
+ i2c_del_driver(&lork_driver);
device_destroy(class, node);
class_destroy(class);
printk("%s()\n", __PRETTY_FUNCTION__);
diff --git a/driver/main.h b/driver/main.h
index a0ef924..666bcc1 100644
--- a/driver/main.h
+++ b/driver/main.h
@@ -5,18 +5,26 @@
#include "platform.h"
-static const struct of_device_id lork_ids[] = {
- { .compatible = "gpio-extern" },
+static const struct of_device_id lork_match[] = {
+ { .compatible = "lork-i2c" },
{},
};
-struct platform_driver lork_driver = {
+static const struct i2c_device_id lork_ids[] = {
+ { "foo", 0 },
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, lork_ids);
+
+struct i2c_driver lork_driver = {
.probe = lork_probe,
.remove = lork_remove,
.driver = {
- .name = "gpio-extern",
+ .name = "lork",
.owner = THIS_MODULE,
- .of_match_table = of_match_ptr(lork_ids),
- }
+ .of_match_table = of_match_ptr(lork_match),
+ },
+ .id_table = lork_ids,
};
diff --git a/driver/platform.c b/driver/platform.c
index b177474..db82d14 100644
--- a/driver/platform.c
+++ b/driver/platform.c
@@ -1,85 +1,14 @@
#include "platform.h"
+#include <linux/platform_device.h>
#include <linux/types.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-// TODO: shouldn't these be used??
-// #include <linux/pinctrl/pinctrl.h>
-// #include <linux/gpio/driver.h>
-
-#include <dt-bindings/gpio/gpio.h>
-
-// NOTE: i believe any nonzero return value for the probe function is
-// recognized as an error because of
-// <https://github.com/torvalds/linux/blob/a5131c3fdf2608f1c15f3809e201cf540eb28489/drivers/base/platform.c#L1004>
-int lork_probe(struct platform_device* dev) {
- // read gpios field from device tree
- uint32_t dt_gpios[3];
- of_property_read_u32_array(dev->dev.of_node, "gpios", dt_gpios, 3);
-
- struct device_node* gpio1 = of_find_node_by_phandle(dt_gpios[0]);
- uint32_t pin = dt_gpios[1];
- uint32_t gpio_mode = dt_gpios[2];
- printk("lork: configure pin %u w/ mode 0x%02x\n", pin, gpio_mode);
-
- // find the multiplexer that controls pin
- size_t len = of_property_count_u32_elems(gpio1, "gpio-ranges");
- struct device_node* am33xx_pinmux = NULL;
- for (size_t i = 0; i < len; i += 4) {
- uint32_t phandle, pin_start, pin_offset, pin_size;
- of_property_read_u32_index(gpio1, "gpio-ranges", i+0, &phandle);
- of_property_read_u32_index(gpio1, "gpio-ranges", i+1, &pin_start);
- of_property_read_u32_index(gpio1, "gpio-ranges", i+2, &pin_offset);
- of_property_read_u32_index(gpio1, "gpio-ranges", i+3, &pin_size);
-
- // get phandle for multiplexer corresponding to configured pin number
- if (pin_start > pin || pin >= pin_start + pin_size) continue;
-
- am33xx_pinmux = of_find_node_by_phandle(phandle);
- printk("0x%02x, %u -> %u + %u\n", phandle, pin_start, pin_offset, pin_size);
- break;
- }
- if (am33xx_pinmux == NULL) return EINVAL;
-
- printk("%s(%s)\n", __PRETTY_FUNCTION__, dev->name);
+int lork_probe(struct i2c_client * client) {
+ printk(KERN_INFO "%s()\n", __PRETTY_FUNCTION__);
return 0;
}
-int lork_remove(struct platform_device* dev) {
- printk("%s(%s)\n", __PRETTY_FUNCTION__, dev->name);
- return 0;
-}
-
-unsigned int val = 0;
-ssize_t drv_attr_int_show(struct device_driver* drv, char* buf) {
- return sprintf(buf, "%u\n", val);
-}
-ssize_t drv_attr_int_store(struct device_driver* drv, const char* buf, size_t count) {
- sscanf(buf, "%u", &val);
- return count;
-}
-
-ssize_t dev_attr_int_show(struct device* dev, struct device_attribute* _attr, char* buf) {
- return sprintf(buf, "%u\n", val);
-}
-ssize_t dev_attr_int_store(struct device* dev, struct device_attribute* _attr, const char* buf, size_t count) {
- sscanf(buf, "%u", &val);
- return count;
-}
-
-char* str = NULL;
-size_t str_len = 0;
-ssize_t dev_attr_str_show(struct device* dev, struct device_attribute* _attr, char* buf) {
- if (str == NULL) return 0;
- strncpy(buf, str, str_len);
- return str_len;
-}
-ssize_t dev_attr_str_store(struct device* dev, struct device_attribute* _attr, const char* buf, size_t count) {
- if (str != NULL) kfree(str);
- str = kmalloc(count, 0);
- str_len = count;
- strncpy(str, buf, str_len);
- return count;
+void lork_remove(struct i2c_client * client) {
+ return;
}
diff --git a/driver/platform.h b/driver/platform.h
index ecac681..1173c3a 100644
--- a/driver/platform.h
+++ b/driver/platform.h
@@ -1,43 +1,8 @@
#pragma once
-#include <linux/types.h>
#include <linux/platform_device.h>
-#include <linux/slab.h>
+#include <linux/i2c.h>
-int lork_probe(struct platform_device*);
-int lork_remove(struct platform_device*);
-
-
-ssize_t drv_attr_int_show(struct device_driver*, char*);
-ssize_t drv_attr_int_store(struct device_driver*, const char*, size_t);
-static const struct driver_attribute drv_attr_int = {
- .attr = {
- .name = "int",
- .mode = 0644,
- },
- .show = drv_attr_int_show,
- .store = drv_attr_int_store,
-};
-
-ssize_t dev_attr_int_show(struct device*, struct device_attribute*, char*);
-ssize_t dev_attr_int_store(struct device*, struct device_attribute*, const char*, size_t);
-static const struct device_attribute dev_attr_int = {
- .attr = {
- .name = "int",
- .mode = 0644,
- },
- .show = dev_attr_int_show,
- .store = dev_attr_int_store,
-};
-
-ssize_t dev_attr_str_show(struct device*, struct device_attribute*, char*);
-ssize_t dev_attr_str_store(struct device*, struct device_attribute*, const char*, size_t);
-static const struct device_attribute dev_attr_str = {
- .attr = {
- .name = "str",
- .mode = 0644,
- },
- .show = dev_attr_str_show,
- .store = dev_attr_str_store,
-};
+int lork_probe(struct i2c_client *);
+void lork_remove(struct i2c_client *);
diff --git a/dts/am335x-boneblack-uboot.dts b/dts/am335x-boneblack-uboot.dts
index 43c1cfe..9cdeada 100644
--- a/dts/am335x-boneblack-uboot.dts
+++ b/dts/am335x-boneblack-uboot.dts
@@ -2177,7 +2177,7 @@
#size-cells = <0x01>;
ranges = <0x00 0x9c000 0x1000>;
- i2c@0 {
+ i2c2: i2c@0 {
compatible = "ti,omap4-i2c";
#address-cells = <0x01>;
#size-cells = <0x00>;
@@ -2241,6 +2241,12 @@
phandle = <0xbb>;
};
};
+
+ // NOTE: this is in i2c2, so I2C2_SCL = P9.19 and I2C2_SDA = P9.20
+ lork {
+ compatible = "lork-i2c"; // load my driver
+ addr = <0x22>; // i2c slave address (see ../arduino/main.cpp)
+ };
};
};
@@ -3892,11 +3898,4 @@
not_available = "/not_available";
vmmcsd_fixed = "/fixedregulator0";
};
-
- // this section is visible at runtime under
- // /sys/firmware/devicetree/base/lork
- lork {
- compatible = "gpio-extern";
- gpios = <&gpio1 18 GPIO_ACTIVE_HIGH>;
- };
};
diff --git a/readme.md b/readme.md
index ca989da..1db60b5 100644
--- a/readme.md
+++ b/readme.md
@@ -15,6 +15,7 @@
- [Driver API][driver-api]
- [AM335x Technical reference manual][ti-am335x-rm]
- [BeagleBone Black system reference manual][bbb-srm]
+- [I2C device driver guide][linux-i2c]
[kbuild-obj-var]: https://docs.kernel.org/kbuild/makefiles.html#loadable-module-goals-obj-m
[kbuild-module-makefile]: https://www.kernel.org/doc/html/latest/kbuild/modules.html#creating-a-kbuild-file-for-an-external-module
@@ -25,6 +26,7 @@
[driver-api]: https://www.kernel.org/doc/html/latest/driver-api/infrastructure.html
[ti-am335x-rm]: https://www.ti.com/lit/ug/spruh73q/spruh73q.pdf
[bbb-srm]: https://cdn-shop.adafruit.com/datasheets/BBB_SRM.pdf
+[linux-i2c]: https://www.kernel.org/doc/html/latest/i2c/writing-clients.html
# tips