forked from Imagelibrary/rtems
Use the following variant which was already used by most source files: #ifdef HAVE_CONFIG_H #include "config.h" #endif
133 lines
2.7 KiB
C
133 lines
2.7 KiB
C
/*
|
|
* Copyright (c) 2016-2017 Chris Johns <chrisj@rtems.org>
|
|
* All rights reserved.
|
|
*
|
|
* The license and distribution terms for this file may be
|
|
* found in the file LICENSE in this distribution or at
|
|
* http://www.rtems.org/license/LICENSE.
|
|
*/
|
|
|
|
/*
|
|
* I2C slave for testing:
|
|
* https://github.com/oetr/FPGA-I2C-Slave
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <dev/i2c/i2c.h>
|
|
#include <dev/i2c/fpga-i2c-slave.h>
|
|
|
|
typedef struct {
|
|
i2c_dev base;
|
|
uint16_t address;
|
|
size_t size;
|
|
} fpga_i2c_slave;
|
|
|
|
static ssize_t
|
|
fpga_i2c_slave_read(i2c_dev* base, void* buf, size_t n, off_t offset)
|
|
{
|
|
fpga_i2c_slave* dev = (fpga_i2c_slave*) base;
|
|
off_t avail = dev->size - offset;
|
|
uint8_t* in = buf;
|
|
size_t todo;
|
|
|
|
if (avail <= 0) {
|
|
return 0;
|
|
}
|
|
|
|
if (n > avail) {
|
|
n = (size_t) avail;
|
|
}
|
|
|
|
todo = n;
|
|
|
|
while (todo > 0) {
|
|
/*
|
|
* Limit the transfer size so that it can be stored in 8-bits. This may
|
|
* help some bus controllers.
|
|
*/
|
|
uint16_t cur = (uint16_t) (todo < 255 ? todo : 255);
|
|
i2c_msg msgs = {
|
|
.addr = dev->base.address,
|
|
.flags = I2C_M_RD,
|
|
.buf = in,
|
|
.len = cur
|
|
};
|
|
int err;
|
|
err = i2c_bus_transfer(dev->base.bus, &msgs, 1);
|
|
if (err != 0) {
|
|
return err;
|
|
}
|
|
todo -= cur;
|
|
in += cur;
|
|
}
|
|
|
|
return (ssize_t) n;
|
|
}
|
|
|
|
static ssize_t
|
|
fpga_i2c_slave_write(i2c_dev* base, const void* buf, size_t n, off_t offset)
|
|
{
|
|
fpga_i2c_slave* dev = (fpga_i2c_slave*) base;
|
|
off_t avail = dev->size - offset;
|
|
const uint8_t* out = buf;
|
|
size_t todo;
|
|
|
|
if (avail <= 0) {
|
|
return 0;
|
|
}
|
|
|
|
if (n > avail) {
|
|
n = (size_t) avail;
|
|
}
|
|
|
|
todo = n;
|
|
|
|
while (todo > 0) {
|
|
/*
|
|
* Limit the transfer size so that it can be stored in 8-bits. This may
|
|
* help some bus controllers.
|
|
*/
|
|
uint16_t cur = (uint16_t) (todo < 255 ? todo : 255);
|
|
i2c_msg msgs = {
|
|
.addr = dev->base.address,
|
|
.flags = 0,
|
|
.buf = RTEMS_DECONST(uint8_t*, out),
|
|
.len = cur
|
|
};
|
|
int err;
|
|
err = i2c_bus_transfer(dev->base.bus, &msgs, 1);
|
|
if (err != 0) {
|
|
return err;
|
|
}
|
|
todo -= cur;
|
|
out += cur;
|
|
}
|
|
|
|
return (ssize_t) n;
|
|
}
|
|
|
|
int
|
|
i2c_dev_register_fpga_i2c_slave(const char* bus_path,
|
|
const char* dev_path,
|
|
uint16_t address,
|
|
size_t size)
|
|
|
|
{
|
|
fpga_i2c_slave* dev;
|
|
|
|
dev = (fpga_i2c_slave*)
|
|
i2c_dev_alloc_and_init(sizeof(*dev), bus_path, address);
|
|
if (dev == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
dev->base.read = fpga_i2c_slave_read;
|
|
dev->base.write = fpga_i2c_slave_write;
|
|
dev->size = size;
|
|
|
|
return i2c_dev_register(&dev->base, dev_path);
|
|
}
|