From dc3e1220a3bc60c2f845477b3d5babd3e00e6ea8 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sat, 15 Jun 2024 17:03:57 +0200 Subject: first attempt i2c driver --- driver/main.c | 31 +++------------- driver/main.h | 20 +++++++---- driver/platform.c | 81 +++--------------------------------------- driver/platform.h | 41 ++------------------- dts/am335x-boneblack-uboot.dts | 15 ++++---- readme.md | 2 ++ 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 #include -#include -#include -#include +#include #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 #include -#include -#include -// TODO: shouldn't these be used?? -// #include -// #include - -#include - -// NOTE: i believe any nonzero return value for the probe function is -// recognized as an error because of -// -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 #include -#include +#include -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 -- cgit v1.2.3