Add I2C driver
This commit is contained in:
parent
2e0050fa8f
commit
56a1d796af
6 changed files with 57 additions and 61 deletions
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
|
@ -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"]
|
|
@ -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"]
|
|
@ -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
|
|
Loading…
Add table
Reference in a new issue