Add I2C driver

This commit is contained in:
crides 2022-11-25 17:24:58 -06:00
parent 2e0050fa8f
commit 56a1d796af
6 changed files with 57 additions and 61 deletions

View file

@ -1,6 +1,5 @@
#define DT_DRV_COMPAT cirque_pinnacle #define DT_DRV_COMPAT cirque_pinnacle
#include <drivers/spi.h>
#include <init.h> #include <init.h>
#include <drivers/sensor.h> #include <drivers/sensor.h>
#include <zmk/sensors.h> #include <zmk/sensors.h>
@ -10,9 +9,11 @@
LOG_MODULE_REGISTER(pinnacle, CONFIG_SENSOR_LOG_LEVEL); LOG_MODULE_REGISTER(pinnacle, CONFIG_SENSOR_LOG_LEVEL);
static int pinnacle_seq_read(const struct device *dev, const uint8_t start, uint8_t *buf, const uint8_t len) { static int pinnacle_seq_read(const struct device *dev, const uint8_t addr, uint8_t *buf, const uint8_t len) {
const struct pinnacle_config *config = dev->config;
#if DT_INST_ON_BUS(0, spi)
uint8_t tx_buffer[len + 3], rx_dummy[3]; uint8_t tx_buffer[len + 3], rx_dummy[3];
tx_buffer[0] = PINNACLE_READ | start; tx_buffer[0] = PINNACLE_READ | addr;
memset(&tx_buffer[1], PINNACLE_AUTOINC, len + 1); memset(&tx_buffer[1], PINNACLE_AUTOINC, len + 1);
tx_buffer[len + 2] = PINNACLE_DUMMY; tx_buffer[len + 2] = PINNACLE_DUMMY;
@ -38,12 +39,15 @@ static int pinnacle_seq_read(const struct device *dev, const uint8_t start, uint
.buffers = rx_buf, .buffers = rx_buf,
.count = 2, .count = 2,
}; };
const struct pinnacle_data *data = dev->data; return spi_transceive_dt(&config->bus, &tx, &rx);
const struct pinnacle_config *config = dev->config; #elif DT_INST_ON_BUS(0, i2c)
return spi_transceive(data->spi, &config->spi_config, &tx, &rx); return i2c_burst_read_dt(&config->bus, PINNACLE_READ | addr, buf, len);
#endif
} }
static int pinnacle_write(const struct device *dev, const uint8_t addr, const uint8_t val) { static int pinnacle_write(const struct device *dev, const uint8_t addr, const uint8_t val) {
const struct pinnacle_config *config = dev->config;
#if DT_INST_ON_BUS(0, spi)
uint8_t tx_buffer[2] = { PINNACLE_WRITE | addr, val }; uint8_t tx_buffer[2] = { PINNACLE_WRITE | addr, val };
uint8_t rx_buffer[2]; uint8_t rx_buffer[2];
@ -65,9 +69,7 @@ static int pinnacle_write(const struct device *dev, const uint8_t addr, const ui
.buffers = rx_buf, .buffers = rx_buf,
.count = 1, .count = 1,
}; };
const struct pinnacle_data *data = dev->data; const int ret = spi_transceive_dt(&config->bus, &tx, &rx);
const struct pinnacle_config *config = dev->config;
const int ret = spi_transceive(data->spi, &config->spi_config, &tx, &rx);
if (rx_buffer[1] != 0xFB) { if (rx_buffer[1] != 0xFB) {
LOG_ERR("bad ret val"); LOG_ERR("bad ret val");
return -EIO; return -EIO;
@ -76,6 +78,9 @@ static int pinnacle_write(const struct device *dev, const uint8_t addr, const ui
LOG_ERR("spi ret: %d", ret); LOG_ERR("spi ret: %d", ret);
} }
return ret; return ret;
#elif DT_INST_ON_BUS(0, i2c)
return i2c_reg_write_byte_dt(&config->bus, PINNACLE_WRITE | addr, val);
#endif
} }
static int pinnacle_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) { static int pinnacle_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) {
@ -117,7 +122,7 @@ static int pinnacle_sample_fetch(const struct device *dev, enum sensor_channel c
#ifdef CONFIG_PINNACLE_TRIGGER #ifdef CONFIG_PINNACLE_TRIGGER
static void set_int(const struct device *dev, const bool en) { static void set_int(const struct device *dev, const bool en) {
const struct pinnacle_config *config = dev->config; const struct pinnacle_config *config = dev->config;
int ret = gpio_pin_interrupt_configure(config->dr_port, config->dr_pin, en ? GPIO_INT_LEVEL_ACTIVE : GPIO_INT_DISABLE); int ret = gpio_pin_interrupt_configure_dt(&config->dr, en ? GPIO_INT_LEVEL_ACTIVE : GPIO_INT_DISABLE);
if (ret < 0) { if (ret < 0) {
LOG_ERR("can't set interrupt"); LOG_ERR("can't set interrupt");
} }
@ -178,7 +183,6 @@ static void pinnacle_gpio_cb(const struct device *port, struct gpio_callback *cb
static int pinnacle_init(const struct device *dev) { static int pinnacle_init(const struct device *dev) {
struct pinnacle_data *data = dev->data; struct pinnacle_data *data = dev->data;
const struct pinnacle_config *config = dev->config; const struct pinnacle_config *config = dev->config;
data->spi = DEVICE_DT_GET(SPI_BUS);
pinnacle_write(dev, PINNACLE_STATUS1, 0); // Clear CC pinnacle_write(dev, PINNACLE_STATUS1, 0); // Clear CC
pinnacle_write(dev, PINNACLE_Z_IDLE, 0); // No Z-Idle packets pinnacle_write(dev, PINNACLE_Z_IDLE, 0); // No Z-Idle packets
@ -201,9 +205,9 @@ static int pinnacle_init(const struct device *dev) {
#ifdef CONFIG_PINNACLE_TRIGGER #ifdef CONFIG_PINNACLE_TRIGGER
data->dev = dev; data->dev = dev;
gpio_pin_configure(config->dr_port, config->dr_pin, GPIO_INPUT | config->dr_flags); gpio_pin_configure_dt(&config->dr, GPIO_INPUT);
gpio_init_callback(&data->gpio_cb, pinnacle_gpio_cb, BIT(config->dr_pin)); gpio_init_callback(&data->gpio_cb, pinnacle_gpio_cb, BIT(config->dr.pin));
int ret = gpio_add_callback(config->dr_port, &data->gpio_cb); int ret = gpio_add_callback(config->dr.port, &data->gpio_cb);
if (ret < 0) { if (ret < 0) {
LOG_ERR("Failed to set DR callback: %d", ret); LOG_ERR("Failed to set DR callback: %d", ret);
return -EIO; return -EIO;
@ -220,6 +224,7 @@ static int pinnacle_init(const struct device *dev) {
#endif #endif
pinnacle_write(dev, PINNACLE_FEED_CFG1, feed_cfg1); pinnacle_write(dev, PINNACLE_FEED_CFG1, feed_cfg1);
#endif #endif
LOG_WRN("inited");
return 0; return 0;
} }
@ -234,26 +239,17 @@ static const struct sensor_driver_api pinnacle_driver_api = {
static struct pinnacle_data pinnacle_data; static struct pinnacle_data pinnacle_data;
static const struct pinnacle_config pinnacle_config = { static const struct pinnacle_config pinnacle_config = {
.spi_cs = { #if DT_INST_ON_BUS(0, i2c)
.gpio_dev = DEVICE_DT_GET(DT_GPIO_CTLR_BY_IDX(SPI_BUS, cs_gpios, SPI_REG)), .bus = I2C_DT_SPEC_INST_GET(0),
.gpio_pin = DT_GPIO_PIN_BY_IDX(SPI_BUS, cs_gpios, SPI_REG), #elif DT_INST_ON_BUS(0, spi)
.delay = 0, .bus = SPI_DT_SPEC_INST_GET(0, SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_TRANSFER_MSB, 0),
.gpio_dt_flags = DT_GPIO_FLAGS_BY_IDX(SPI_BUS, cs_gpios, SPI_REG), #endif
},
.spi_config = {
.cs = &pinnacle_config.spi_cs,
.frequency = DT_INST_PROP(0, spi_max_frequency),
.slave = DT_INST_REG_ADDR(0),
.operation = (SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_TRANSFER_MSB),
},
.invert_x = DT_INST_PROP(0, invert_x), .invert_x = DT_INST_PROP(0, invert_x),
.invert_y = DT_INST_PROP(0, invert_y), .invert_y = DT_INST_PROP(0, invert_y),
.sleep_en = DT_INST_PROP(0, sleep), .sleep_en = DT_INST_PROP(0, sleep),
.no_taps = DT_INST_PROP(0, no_taps), .no_taps = DT_INST_PROP(0, no_taps),
#ifdef CONFIG_PINNACLE_TRIGGER #ifdef CONFIG_PINNACLE_TRIGGER
.dr_port = DEVICE_DT_GET(DT_GPIO_CTLR(DT_DRV_INST(0), dr_gpios)), .dr = GPIO_DT_SPEC_GET(DT_DRV_INST(0), dr_gpios),
.dr_pin = DT_INST_GPIO_PIN(0, dr_gpios),
.dr_flags = DT_INST_GPIO_FLAGS(0, dr_gpios),
#endif #endif
}; };

View file

@ -1,6 +1,8 @@
#pragma once #pragma once
#include <device.h> #include <device.h>
#include <drivers/spi.h>
#include <drivers/i2c.h>
#define PINNACLE_READ 0xA0 #define PINNACLE_READ 0xA0
#define PINNACLE_WRITE 0x80 #define PINNACLE_WRITE 0x80
@ -50,7 +52,6 @@
#define PINNACLE_PACKET0_Y_SIGN BIT(5) // Y delta sign #define PINNACLE_PACKET0_Y_SIGN BIT(5) // Y delta sign
struct pinnacle_data { struct pinnacle_data {
const struct device *spi;
int16_t dx, dy; int16_t dx, dy;
int8_t wheel; int8_t wheel;
uint8_t btn; uint8_t btn;
@ -70,11 +71,13 @@ struct pinnacle_data {
}; };
struct pinnacle_config { struct pinnacle_config {
struct spi_cs_control spi_cs; #if DT_INST_ON_BUS(0, i2c)
struct spi_config spi_config; const struct i2c_dt_spec bus;
#elif DT_INST_ON_BUS(0, spi)
const struct spi_dt_spec bus;
#endif
bool invert_x, invert_y, sleep_en, no_taps; bool invert_x, invert_y, sleep_en, no_taps;
#ifdef CONFIG_PINNACLE_TRIGGER #ifdef CONFIG_PINNACLE_TRIGGER
const struct device *dr_port; const struct gpio_dt_spec dr;
uint8_t dr_pin, dr_flags;
#endif #endif
}; };

View file

@ -0,0 +1,12 @@
properties:
dr-gpios:
type: phandle-array
description: Data ready pin for the trackpad
invert-x:
type: boolean
invert-y:
type: boolean
sleep:
type: boolean
no-taps:
type: boolean

View file

@ -0,0 +1,6 @@
description: |
Sensor driver for the Cirque Pinnacle trackpad ASICs, using the I2C interface
compatible: "cirque,pinnacle"
include: ["i2c-device.yaml", "cirque,pinnacle-common.yaml"]

View file

@ -0,0 +1,6 @@
description: |
Sensor driver for the Cirque Pinnacle trackpad ASICs, using the SPI interface
compatible: "cirque,pinnacle"
include: ["spi-device.yaml", "cirque,pinnacle-common.yaml"]

View file

@ -1,27 +0,0 @@
description: |
Sensor driver for the Cirque Pinnacle trackpad ASICs
compatible: "cirque,pinnacle"
include: spi-device.yaml
on-bus: spi
properties:
spi-max-frequency:
type: int
required: true
description: |
Maximum SPI clock speed supported by the device, in Hz.
dr-gpios:
type: phandle-array
required: true
description: Data ready pin for the trackpad
invert-x:
type: boolean
invert-y:
type: boolean
sleep:
type: boolean
no-taps:
type: boolean