From 20ba3964661840fe1d5ba65b57014f21c63ed9c4 Mon Sep 17 00:00:00 2001 From: Arksine Date: Thu, 9 Jan 2020 19:25:51 -0500 Subject: [PATCH] linux: implement i2c Signed-off-by: Eric Callahan --- src/linux/Kconfig | 1 + src/linux/Makefile | 2 +- src/linux/gpio.h | 9 ++++ src/linux/i2c.c | 101 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 src/linux/i2c.c diff --git a/src/linux/Kconfig b/src/linux/Kconfig index 0ae58516..53fb22fe 100644 --- a/src/linux/Kconfig +++ b/src/linux/Kconfig @@ -9,6 +9,7 @@ config LINUX_SELECT select HAVE_GPIO_ADC select HAVE_GPIO_SPI select HAVE_GPIO_HARD_PWM + select HAVE_GPIO_I2C config BOARD_DIRECTORY string diff --git a/src/linux/Makefile b/src/linux/Makefile index 4ceed5f3..5cc9c69a 100644 --- a/src/linux/Makefile +++ b/src/linux/Makefile @@ -4,7 +4,7 @@ dirs-y += src/linux src/generic src-y += linux/main.c linux/timer.c linux/console.c linux/watchdog.c src-y += linux/pca9685.c linux/spidev.c linux/analog.c linux/hard_pwm.c -src-y += generic/crc16_ccitt.c generic/alloc.c +src-y += linux/i2c.c generic/crc16_ccitt.c generic/alloc.c CFLAGS_klipper.elf += -lutil diff --git a/src/linux/gpio.h b/src/linux/gpio.h index d177581c..32e76bf5 100644 --- a/src/linux/gpio.h +++ b/src/linux/gpio.h @@ -35,4 +35,13 @@ struct gpio_pwm { struct gpio_pwm gpio_pwm_setup(uint8_t pin, uint32_t cycle_time, uint16_t val); void gpio_pwm_write(struct gpio_pwm g, uint16_t val); +struct i2c_config { + int fd; +}; + +struct i2c_config i2c_setup(uint32_t bus, uint32_t rate, uint8_t addr); +void i2c_write(struct i2c_config config, uint8_t write_len, uint8_t *write); +void i2c_read(struct i2c_config config, uint8_t reg_len, uint8_t *reg + , uint8_t read_len, uint8_t *read); + #endif // gpio.h diff --git a/src/linux/i2c.c b/src/linux/i2c.c new file mode 100644 index 00000000..b8e8f253 --- /dev/null +++ b/src/linux/i2c.c @@ -0,0 +1,101 @@ +// Linux i2c implementation +// +// Copyright (C) 2020 Eric Callahan +// +// This file may be distributed under the terms of the GNU GPLv3 license. +#include // open +#include // I2C_SLAVE +#include // snprintf +#include // ioctl +#include // write +#include "gpio.h" // i2c_setup +#include "command.h" // shutdown +#include "internal.h" // report_errno +#include "sched.h" // sched_shutdown + +DECL_ENUMERATION_RANGE("i2c_bus", "i2c.0", 0, 2); + +struct i2c_s { + uint32_t bus; + uint8_t addr; + int fd; +}; + +static struct i2c_s devices[16]; +static int devices_count; + +static int +i2c_open(uint32_t bus, uint8_t addr) +{ + // Find existing device (if already opened) + int i; + for (i=0; i= 0) + close(fd); + shutdown("Unable to open i2c device"); +} + +struct i2c_config +i2c_setup(uint32_t bus, uint32_t rate, uint8_t addr) +{ + // Note: The rate is set by the kernel driver, for a Raspberry Pi this + // is done with the following setting in /boot/config.txt: + // + // dtparam=i2c_baudrate= + + int fd = i2c_open(bus, addr); + return (struct i2c_config){.fd=fd}; +} + +void +i2c_write(struct i2c_config config, uint8_t write_len, uint8_t *data) +{ + int ret = write(config.fd, data, write_len); + if (ret != write_len) { + if (ret < 0) + report_errno("write value i2c", ret); + try_shutdown("Unable write i2c device"); + } +} + +void +i2c_read(struct i2c_config config, uint8_t reg_len, uint8_t *reg + , uint8_t read_len, uint8_t *data) +{ + i2c_write(config, reg_len, reg); + int ret = read(config.fd, data, read_len); + if (ret != read_len) { + if (ret < 0) + report_errno("read value i2c", ret); + try_shutdown("Unable to read i2c device"); + } +}