Commit 03bd570d authored by Lucas Russo's avatar Lucas Russo

sm_io/protocols/*: use "offs"/"size_offs" as the protocol address

Now, we use the offs parameter as the address
to be written by the protocol. This fixes the
protocol semantics, and makes it easier to support
new protocols.
parent d4596cfd
......@@ -29,7 +29,7 @@ typedef enum {
/************************* Our Methods **************************/
/* Creates a new instance of the proto_spi */
smpr_spi_t *smpr_spi_new (uint32_t ss, uint32_t charlen);
smpr_spi_t *smpr_spi_new (uint32_t ss, uint32_t addr_msb);
/* Destroy an instance of the spi */
smpr_err_e smpr_spi_destroy (smpr_spi_t **self_p);
......@@ -38,10 +38,10 @@ smpr_err_e smpr_spi_set_ss (smpr_spi_t *self, uint32_t ss);
/* Get SPI SS parameter */
uint32_t smpr_spi_get_ss (smpr_spi_t *self);
/* Set SPI CHARLEN parameter */
smpr_err_e smpr_spi_set_charlen (smpr_spi_t *self, uint32_t charlen);
/* Get SPI CHARLEN parameter */
uint32_t smpr_spi_get_charlen (smpr_spi_t *self);
/* Get SPI addr_msb parameter */
smpr_err_e smpr_spi_set_addr_msb (smpr_spi_t *self, uint32_t addr_msb);
/* Get SPI addr_msb parameter */
uint32_t smpr_spi_get_addr_msb (smpr_spi_t *self);
/* Get SPI operations */
const smpr_proto_ops_t *smpr_spi_get_ops (smpr_spi_t *self);
......
......@@ -61,14 +61,12 @@ static smpr_err_e _i2c_init (smpr_t *self);
static ssize_t _i2c_check_transfer (smpr_t *self, bool ack_check);
static smpr_err_e _i2c_set_mode (smpr_t *self);
static ssize_t _i2c_read_write_header (smpr_t *self, bool rw);
static ssize_t _i2c_read_generic (smpr_t *self, size_t size_offs, uint64_t offs,
uint8_t *data, size_t size);
static ssize_t _i2c_write_generic (smpr_t *self, size_t size_offs, uint64_t offs,
uint8_t *data, size_t size);
static ssize_t _i2c_read_raw (smpr_t *self, uint8_t *data,
size_t size);
static ssize_t _i2c_write_raw (smpr_t *self, uint8_t *data,
size_t size);
size_t size, uint8_t *data);
static ssize_t _i2c_write_read_generic (smpr_t *self, size_t size_offs, uint64_t offs,
size_t size, uint8_t *data);
static ssize_t _i2c_read_raw (smpr_t *self, size_t size, uint8_t *data);
static ssize_t _i2c_write_raw (smpr_t *self, size_t size, uint8_t *data);
/************ Our methods implementation **********/
......@@ -180,14 +178,14 @@ static ssize_t i2c_read_16 (smpr_t *self, size_t size_offs, uint64_t offs,
{
/* We want to request a read command from some off-FPGA chip. So, we
* always use WRITE_READ mode */
return _i2c_read_generic (self, size_offs, offs, (uint8_t *) data, sizeof(*data));
return _i2c_write_read_generic (self, size_offs, offs, sizeof(*data), (uint8_t *) data);
}
/* Write 16-bit data to I2C device */
static ssize_t i2c_write_16 (smpr_t *self, size_t size_offs, uint64_t offs,
const uint16_t *data)
{
return _i2c_write_generic (self, size_offs, offs, (uint8_t *) data, sizeof(*data));
return _i2c_write_generic (self, size_offs, offs, sizeof(*data), (uint8_t *) data);
}
/* Read 32-bit data from I2C */
......@@ -196,14 +194,14 @@ static ssize_t i2c_read_32 (smpr_t *self, size_t size_offs, uint64_t offs,
{
/* We want to request a read command from some off-FPGA chip. So, we
* always use WRITE_READ mode */
return _i2c_read_generic (self, size_offs, offs, (uint8_t *) data, sizeof(*data));
return _i2c_write_read_generic (self, size_offs, offs, sizeof(*data), (uint8_t *) data);
}
/* Write 32-bit data to I2C device */
static ssize_t i2c_write_32 (smpr_t *self, size_t size_offs, uint64_t offs,
const uint32_t *data)
{
return _i2c_write_generic (self, size_offs, offs, (uint8_t *) data, sizeof(*data));
return _i2c_write_generic (self, size_offs, offs, sizeof(*data), (uint8_t *) data);
}
/* Read 64-bit data from I2C */
......@@ -212,14 +210,14 @@ static ssize_t i2c_read_64 (smpr_t *self, size_t size_offs, uint64_t offs,
{
/* We want to request a read command from some off-FPGA chip. So, we
* always use WRITE_READ mode */
return _i2c_read_generic (self, size_offs, offs, (uint8_t *) data, sizeof(*data));
return _i2c_write_read_generic (self, size_offs, offs, sizeof(*data), (uint8_t *) data);
}
/* Write 64-bit data to I2C device */
static ssize_t i2c_write_64 (smpr_t *self, size_t size_offs, uint64_t offs,
const uint64_t *data)
{
return _i2c_write_generic (self, size_offs, offs, (uint8_t *) data, sizeof(*data));
return _i2c_write_generic (self, size_offs, offs, sizeof(*data), (uint8_t *) data);
}
/* Read data block from I2C device, size in bytes */
......@@ -228,14 +226,14 @@ static ssize_t i2c_read_block (smpr_t *self, size_t size_offs, uint64_t offs,
{
/* We want to request a read command from some off-FPGA chip. So, we
* always use WRITE_READ mode */
return _i2c_read_generic (self, size_offs, offs, (uint8_t *) data, size);
return _i2c_write_read_generic (self, size_offs, offs, size, (uint8_t *) data);
}
/* Write data block from I2C device, size in bytes */
static ssize_t i2c_write_block (smpr_t *self, size_t size_offs, uint64_t offs,
size_t size, const uint32_t *data)
{
return _i2c_write_generic (self, size_offs, offs, (uint8_t *) data, size);
return _i2c_write_generic (self, size_offs, offs, size, (uint8_t *) data);
}
/************ Static functions **********/
......@@ -464,8 +462,7 @@ err_proto_handler:
}
/* Raw write to I2C */
static ssize_t _i2c_write_raw (smpr_t *self, uint8_t *data,
size_t size)
static ssize_t _i2c_write_raw (smpr_t *self, size_t size, uint8_t *data)
{
assert (self);
......@@ -533,8 +530,7 @@ err_proto_handler:
}
/* Raw read from I2C */
static ssize_t _i2c_read_raw (smpr_t *self, uint8_t *data,
size_t size)
static ssize_t _i2c_read_raw (smpr_t *self, size_t size, uint8_t *data)
{
assert (self);
......@@ -602,47 +598,41 @@ err_proto_handler:
return err;
}
#if 0
/* Generic write / read from I2C */
static ssize_t _i2c_write_read_generic (smpr_t *self, uint8_t *data,
size_t size)
static ssize_t _i2c_write_read_generic (smpr_t *self, size_t size_offs, uint64_t offs,
size_t size, uint8_t *data)
{
int err = 0;
smpr_proto_i2c_t *i2c_proto = SMPR_PROTO_I2C(self);
assert (self);
i2c_proto->mode = I2C_MODE_REP_START;
ssize_t err = 0;
smpr_proto_i2c_t *i2c_proto = smpr_get_handler (self);
ASSERT_TEST(i2c_proto != NULL, "Could not get SMPR protocol handler",
err_proto_handler, -1);
/* Get specific parameters */
smpr_i2c_t *smpr_i2c = (smpr_i2c_t *) smpr_get_ops (self);
uint32_t trans_size = size; /* in bytes */
/* Write followed by read always have repeated start mode on */
smpr_i2c_set_rep_start (smpr_i2c, I2C_MODE_REP_START);
ssize_t smpr_err = _i2c_write_raw (self, data, size);
ASSERT_TEST(smpr_err == smpr_i2c->trans_size/SMPR_BYTE_2_BIT /* in bytes*/,
/* Write the address only */
err = _i2c_write_raw (self, size_offs, (uint8_t *) &offs);
ASSERT_TEST(err > 0 && (size_t) err == size_offs /* in bytes*/,
"Could not write data to I2C", err_exit, -1);
smpr_err = _i2c_read_raw (self, data, size);
ASSERT_TEST(smpr_err == size /* in bytes*/,
/* Read the data */
err = _i2c_read_raw (self, size, data);
ASSERT_TEST(err > 0 && (size_t) err == size /* in bytes*/,
"Could not read data to I2C", err_exit, -1);
i2c_proto->mode = I2C_MODE_NORMAL;
err_exit:
/* Restore mode to normal */
smpr_i2c_set_rep_start (smpr_i2c, I2C_MODE_NORMAL);
err_proto_handler:
return err;
}
#endif
static ssize_t _i2c_read_generic (smpr_t *self, size_t size_offs, uint64_t offs,
uint8_t *data, size_t size)
{
assert (self);
(void) size_offs;
(void) offs;
return _i2c_read_raw (self, data, size);
}
static ssize_t _i2c_write_generic (smpr_t *self, size_t size_offs, uint64_t offs,
uint8_t *data, size_t size)
size_t size, uint8_t *data)
{
assert (self);
size_t raw_size = size_offs + size;
......@@ -654,7 +644,15 @@ static ssize_t _i2c_write_generic (smpr_t *self, size_t size_offs, uint64_t offs
memcpy (&raw_data + size_offs, data, size);
}
return _i2c_write_raw (self, raw_data, raw_size);
ssize_t err = _i2c_write_raw (self, raw_size, raw_data);
ASSERT_TEST(err > 0 && (size_t) err == raw_size /* in bytes*/,
"Could not write data to I2C", err_exit, -1);
/* We return only the number of data bytes actually written, not addr+data */
err = size;
err_exit:
return err;
}
static const smpr_proto_ops_t smpr_proto_ops_i2c = {
......
......@@ -56,13 +56,14 @@ struct _smpr_spi_t {
/* Must be located first */
smpr_proto_ops_t proto_ops; /* SPI protocol operations */
uint32_t ss; /* SPI Slave Select */
uint32_t charlen; /* SPI character length:
0 is 128-bit data word, 1 is 1 bit, 2 is 2-bit and so on */
uint32_t addr_msb; /* Copy address to MSB */
};
static smpr_err_e _spi_init (smpr_t *self);
static ssize_t _spi_read_write_generic (smpr_t *self, uint8_t *data,
size_t size, spi_mode_e mode);
static ssize_t _spi_read_write_generic (smpr_t *self, size_t size_offs, uint64_t offs,
size_t size, uint8_t *data, spi_mode_e mode);
static ssize_t _spi_read_write_raw (smpr_t *self, size_t size, uint8_t *data,
spi_mode_e mode);
/************ Our methods implementation **********/
......@@ -172,74 +173,74 @@ err_proto_handler_unset:
}
/* Read 16-bit data from SPI */
static ssize_t spi_read_16 (smpr_t *self, uint64_t offs, uint16_t *data)
static ssize_t spi_read_16 (smpr_t *self, size_t size_offs, uint64_t offs,
uint16_t *data)
{
(void) offs;
/* We want to request a read command from some off-FPGA chip. So, we
* always use WRITE_READ mode */
return _spi_read_write_generic (self, (uint8_t *) data, sizeof(*data),
return _spi_read_write_generic (self, size_offs, offs, sizeof(*data), (uint8_t *) data,
SPI_MODE_WRITE_READ);
}
/* Write 16-bit data to SPI device */
static ssize_t spi_write_16 (smpr_t *self, uint64_t offs, const uint16_t *data)
static ssize_t spi_write_16 (smpr_t *self, size_t size_offs, uint64_t offs,
const uint16_t *data)
{
(void) offs;
return _spi_read_write_generic (self, (uint8_t *) data, sizeof(*data),
return _spi_read_write_generic (self, size_offs, offs, sizeof(*data), (uint8_t *) data,
SPI_MODE_WRITE);
}
/* Read 32-bit data from SPI */
static ssize_t spi_read_32 (smpr_t *self, uint64_t offs, uint32_t *data)
static ssize_t spi_read_32 (smpr_t *self, size_t size_offs, uint64_t offs,
uint32_t *data)
{
(void) offs;
/* We want to request a read command from some off-FPGA chip. So, we
* always use WRITE_READ mode */
return _spi_read_write_generic (self, (uint8_t *) data, sizeof(*data),
return _spi_read_write_generic (self, size_offs, offs, sizeof(*data), (uint8_t *) data,
SPI_MODE_WRITE_READ);
}
/* Write 32-bit data to SPI device */
static ssize_t spi_write_32 (smpr_t *self, uint64_t offs, const uint32_t *data)
static ssize_t spi_write_32 (smpr_t *self, size_t size_offs, uint64_t offs,
const uint32_t *data)
{
(void) offs;
return _spi_read_write_generic (self, (uint8_t *) data, sizeof(*data),
return _spi_read_write_generic (self, size_offs, offs, sizeof(*data), (uint8_t *) data,
SPI_MODE_WRITE);
}
/* Read 64-bit data from SPI */
static ssize_t spi_read_64 (smpr_t *self, uint64_t offs, uint64_t *data)
static ssize_t spi_read_64 (smpr_t *self, size_t size_offs, uint64_t offs,
uint64_t *data)
{
(void) offs;
/* We want to request a read command from some off-FPGA chip. So, we
* always use WRITE_READ mode */
return _spi_read_write_generic (self, (uint8_t *) data, sizeof(*data),
return _spi_read_write_generic (self, size_offs, offs, sizeof(*data), (uint8_t *) data,
SPI_MODE_WRITE_READ);
}
/* Write 64-bit data to SPI device */
static ssize_t spi_write_64 (smpr_t *self, uint64_t offs, const uint64_t *data)
static ssize_t spi_write_64 (smpr_t *self, size_t size_offs, uint64_t offs,
const uint64_t *data)
{
(void) offs;
return _spi_read_write_generic (self, (uint8_t *) data, sizeof(*data),
return _spi_read_write_generic (self, size_offs, offs, sizeof(*data), (uint8_t *) data,
SPI_MODE_WRITE);
}
/* Read data block from SPI device, size in bytes */
static ssize_t spi_read_block (smpr_t *self, uint64_t offs, size_t size, uint32_t *data)
static ssize_t spi_read_block (smpr_t *self, size_t size_offs, uint64_t offs,
size_t size, uint32_t *data)
{
(void) offs;
/* We want to request a read command from some off-FPGA chip. So, we
* always use WRITE_READ mode */
return _spi_read_write_generic (self, (uint8_t *) data, size,
return _spi_read_write_generic (self, size_offs, offs, size, (uint8_t *) data,
SPI_MODE_WRITE_READ);
}
/* Write data block from SPI device, size in bytes */
static ssize_t spi_write_block (smpr_t *self, uint64_t offs, size_t size, const uint32_t *data)
static ssize_t spi_write_block (smpr_t *self, size_t size_offs, uint64_t offs,
size_t size, const uint32_t *data)
{
(void) offs;
return _spi_read_write_generic (self, (uint8_t *) data, size,
return _spi_read_write_generic (self, size_offs, offs, size, (uint8_t *) data,
SPI_MODE_WRITE);
}
......@@ -306,8 +307,8 @@ err_proto_handler:
}
/* Generic read/write to/from SPI */
static ssize_t _spi_read_write_generic (smpr_t *self, uint8_t *data,
size_t size, spi_mode_e mode)
static ssize_t _spi_read_write_raw (smpr_t *self, size_t size, uint8_t *data,
spi_mode_e mode)
{
assert (self);
......@@ -333,7 +334,7 @@ static ssize_t _spi_read_write_generic (smpr_t *self, uint8_t *data,
/* Get specific parameters */
smpr_spi_t *smpr_spi = (smpr_spi_t *) smpr_get_ops (self);
uint32_t ss = smpr_spi_get_ss (smpr_spi);
uint32_t charlen = smpr_spi_get_charlen (smpr_spi);
uint32_t charlen = size*SMPR_BYTE_2_BIT; /* in bits */
/* Configure SS line */
rw_err = SET_PARAM(parent, sm_pr_spi, spi_proto->base, SPI_PROTO, SS, /* field = NULL */,
......@@ -441,9 +442,9 @@ static ssize_t _spi_read_write_generic (smpr_t *self, uint8_t *data,
"[sm_pr:spi] _spi_rw_generic: Reading from RX%u\n", i);
/* As the RXs are just a single register, we write using the SMIO
* functions directly */
num_bytes = smio_thsafe_client_read_32 (parent,
(spi_proto->base | read_base_addr) + SMPR_WB_REG_2_BYTE*i,
(uint32_t *)(data_read + SMPR_WB_REG_2_BYTE*i));
num_bytes = smio_thsafe_client_read_32 (parent,
(spi_proto->base | read_base_addr) + SMPR_WB_REG_2_BYTE*i,
(uint32_t *)(data_read + SMPR_WB_REG_2_BYTE*i));
DBE_DEBUG (DBG_SM_PR | DBG_LVL_TRACE,
"[sm_pr:spi] _spi_rw_generic: Read 0x%08X from RX%u\n",
*((uint32_t *) (data_read + SMPR_WB_REG_2_BYTE*i)), i);
......@@ -461,6 +462,47 @@ err_proto_handler:
return err;
}
static ssize_t _spi_read_write_generic (smpr_t *self, size_t size_offs, uint64_t offs,
size_t size, uint8_t *data, spi_mode_e mode)
{
assert (self);
size_t raw_size = size_offs + size;
uint8_t raw_data [raw_size];
smpr_spi_t *smpr_spi = (smpr_spi_t *) smpr_get_ops (self);
uint32_t addr_msb = smpr_spi_get_addr_msb (smpr_spi);
if (addr_msb) {
/* Copy address (MSB) + data */
if (data != NULL) {
memcpy (&raw_data, data, size);
memcpy (&raw_data + size, &offs, size_offs);
}
/* Only copy address to buffer */
else {
memcpy (&raw_data, &offs, size_offs);
}
}
else {
/* Copy data (MSB) + address */
memcpy (&raw_data, &offs, size_offs);
if (data != NULL) {
memcpy (&raw_data + size_offs, data, size);
}
}
ssize_t err = _spi_read_write_raw (self, raw_size, raw_data, mode);
ASSERT_TEST(err > 0 && (size_t) err == raw_size /* in bytes*/,
"Could not write data to SPI", err_exit, -1);
/* We return only the number of data bytes actually written, not addr+data */
err = size;
err_exit:
return err;
}
static const smpr_proto_ops_t smpr_proto_ops_spi = {
.proto_name = "SPI", /* Protocol name */
.proto_open = spi_open, /* Open device */
......@@ -484,7 +526,7 @@ static const smpr_proto_ops_t smpr_proto_ops_spi = {
/************ Our methods implementation **********/
/* Creates a new instance of the proto_spi */
smpr_spi_t *smpr_spi_new (uint32_t ss, uint32_t charlen)
smpr_spi_t *smpr_spi_new (uint32_t ss, uint32_t addr_msb)
{
smpr_spi_t *self = (smpr_spi_t *) zmalloc (sizeof *self);
ASSERT_ALLOC (self, err_smpr_spi_alloc);
......@@ -493,7 +535,7 @@ smpr_spi_t *smpr_spi_new (uint32_t ss, uint32_t charlen)
self->proto_ops = smpr_proto_ops_spi;
self->ss = ss;
self->charlen = charlen;
self->addr_msb = addr_msb;
return self;
......@@ -530,18 +572,18 @@ uint32_t smpr_spi_get_ss (smpr_spi_t *self)
return self->ss;
}
smpr_err_e smpr_spi_set_charlen (smpr_spi_t *self, uint32_t charlen)
smpr_err_e smpr_spi_set_addr_msb (smpr_spi_t *self, uint32_t addr_msb)
{
assert (self);
self->charlen = charlen;
self->addr_msb = addr_msb;
return SMPR_SUCCESS;
}
uint32_t smpr_spi_get_charlen (smpr_spi_t *self)
uint32_t smpr_spi_get_addr_msb (smpr_spi_t *self)
{
assert (self);
return self->charlen;
return self->addr_msb;
}
const smpr_proto_ops_t *smpr_spi_get_ops (smpr_spi_t *self)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment