nuttx/drivers: add regmap subsystems support.

regmap: add i2c and spi bus support.

Signed-off-by: likun17 <likun17@xiaomi.com>
This commit is contained in:
likun17 2023-07-19 20:17:15 +08:00 committed by Xiang Xiao
parent 7c4349fa9c
commit f99b1a41a3
12 changed files with 1414 additions and 0 deletions

35
Kconfig
View File

@ -1682,6 +1682,41 @@ config DEBUG_RC_INFO
endif # DEBUG_RC
config DEBUG_REGMAP
bool "REGMAP Debug Features"
default n
depends on REGMAP
---help---
Enable REGMAP debug features.
Support for this debug option is architecture-specific and may not
be available for some MCUs.
if DEBUG_REGMAP
config DEBUG_REGMAP_ERROR
bool "Regmap Error Output"
default n
depends on DEBUG_ERROR
---help---
Enable regmap subsystems error output to SYSLOG.
config DEBUG_REGMAP_WARN
bool "Regmap Warnings Output"
default n
depends on DEBUG_WARN
---help---
Enable regmap subsystems warning output to SYSLOG.
config DEBUG_REGMAP_INFO
bool "Regmap Informational Output"
default n
depends on DEBUG_INFO
---help---
Enable regmap subsystems informational output to SYSLOG.
endif # DEBUG_REGMAP
config DEBUG_RMT
bool "RMT Debug Features"
default n

View File

@ -35,6 +35,7 @@ source "drivers/net/Kconfig"
source "drivers/note/Kconfig"
source "drivers/pipes/Kconfig"
source "drivers/power/Kconfig"
source "drivers/regmap/Kconfig"
source "drivers/rptun/Kconfig"
source "drivers/sensors/Kconfig"
source "drivers/serial/Kconfig"

View File

@ -54,6 +54,7 @@ include net/Make.defs
include note/Make.defs
include pipes/Make.defs
include power/Make.defs
include regmap/Make.defs
include rptun/Make.defs
include sensors/Make.defs
include serial/Make.defs

11
drivers/regmap/Kconfig Normal file
View File

@ -0,0 +1,11 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
menuconfig REGMAP
bool "Regmap Subsystems Support"
default n
---help---
This selection enables building of the regmap subsystems.
See include/nuttx/regmap/regmap.h for further regmpap subsystems information.

39
drivers/regmap/Make.defs Normal file
View File

@ -0,0 +1,39 @@
############################################################################
# drivers/regmap/Make.defs
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
############################################################################
# Include regmap subsystems build surrport
ifeq ($(CONFIG_REGMAP),y)
CSRCS += regmap.c
ifeq ($(CONFIG_I2C),y)
CSRCS += regmap_i2c.c
endif
ifeq ($(CONFIG_SPI),y)
CSRCS += regmap_spi.c
endif
DEPPATH += --dep-path regmap
VPATH += :regmap
CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)drivers$(DELIM)regmap
endif # CONFIG_REGMAP

151
drivers/regmap/README.md Normal file
View File

@ -0,0 +1,151 @@
drivers/regmap README
========================
This is the README.txt file for the drivers/regmap/ directory.
Contents
========
- Regmap Header files
1. include/nuttx/regmap/regmap.h
2. struct lcd_dev_s
3. regmap_init
4. regmap_init_spi
5. regmap_init_i2c
6. regmap_exit
7. regmap_write
8. regmap_bulk_write
9. regmap_read
10. regmap_bulk_read
Regmap Header files
================
**include/nuttx/regmap/regmap.h**
The structures and APIS used in regimap are in this header file.
**struct regmap_bus_s;**
Each bus must implement an instance of struct regmap_bus_s. That structure defines a call table with the following methods:
- Single byte reading of the register (8bits)
typedef CODE int (*reg_read_t)(FAR struct regmap_bus_s *bus,
unsigned int reg,
FAR void *val);
- Single byte writing of the register (8bits)
typedef CODE int (*reg_write_t)(FAR struct regmap_bus_s *bus,
unsigned int reg,
unsigned int val);
- Bulk register data reading.
typedef CODE int (*read_t)(FAR struct regmap_bus_s *bus,
FAR const void *reg_buf, unsigned int reg_size,
FAR void *val_buf, unsigned int val_size);
- Bulk register data writing.
typedef CODE int (*write_t)(FAR struct regmap_bus_s *bus,
FAR const void *data,
unsigned int count);
- Initialize the internal configuration of regmap. The first parameter must be the handle of the bus, and the second parameter is the configuration parameter of the bus. Finally, these two parameters will be transparent to the corresponding bus. If you want to implement the bus interface by yourself, you need to realize the corresponding bus initialization function, refer to regimap_i2c.c and regmap_spi.c.
FAR struct regmap_s *regmap_init(FAR struct regmap_bus_s *bus,
FAR const struct regmap_config_s *config);
- Regmap init i2c bus.
FAR struct regmap_s *regmap_init_i2c(FAR struct i2c_master_s *i2c,
FAR struct i2c_config_s *i2c_config,
FAR const struct regmap_config_s *config);
- regmap init spi bus.
FAR struct regmap_s *regmap_init_spi(FAR struct spi_dev_s *spi, uint32_t freq,
uint32_t devid, enum spi_mode_e mode,
FAR const struct regmap_config_s *config);
- Exit and destroy regmap
void regmap_exit(FAR struct regmap_s *map);
- Regmap write() bulk_write() read() bulk_read(), called after initializing the regmap bus device. the first parameter is regmap_s pointer.
int regmap_write(FAR struct regmap_s *map, unsigned int reg,
unsigned int val);
int regmap_bulk_write(FAR struct regmap_s *map, unsigned int reg,
FAR const void *val, unsigned int val_count);
int regmap_read(FAR struct regmap_s *map, unsigned int reg,
FAR void *val);
int regmap_bulk_read(FAR struct regmap_s *map, unsigned int reg,
FAR void *val, unsigned int val_count);
Examples:
=======================
BMI160 sensor as an example:
- Head file
~~~
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/sensors/bmi160.h>
#include <nuttx/regmap/regmap.h>
#include <stdlib.h>
~~~
- Define the regmap_s handle in the driver's life cycle
~~~
struct bmi160_dev_s
{
#ifdef CONFIG_SENSORS_BMI160_I2C
FAR struct regmap_s * regmap; /* Regmap interface */
#else /* CONFIG_SENSORS_BMI160_SPI */
FAR struct spi_dev_s *spi; /* SPI interface */
#endif
};
~~~
- Initialize regmap
~~~
int bmi160_i2c_regmap_init(FAR struct bmi160_dev_s *priv,
FAR struct i2c_master_s *i2c)
{
struct regmap_config_s config;
struct i2c_config_s dev_config;
config.reg_bits = 8;
config.val_bits = 8;
config.disable_locking = true;
dev_config.frequency = BMI160_I2C_FREQ;
dev_config.address = BMI160_I2C_ADDR;
dev_config.addrlen = 7;
priv->regmap = regmap_init_i2c(i2c, &dev_config, &config);
if (priv->regmap == NULL)
{
snerr("bmi160 Initialize regmap configuration failed!");
return -ENXIO;
}
return OK;
}
~~~
- Use
~~~
int ret;
ret = regmap_read(priv->regmap, regaddr, &regval);
if (ret < 0)
{
snerr("regmap read address[%2X] failed: %d!\n", regaddr, ret);
}
ret = regmap_write(priv->regmap, regaddr, regval);
if (ret < 0)
{
snerr("regmap write address[%2X] failed: %d!\n", regaddr, ret);
}
ret = regmap_bulk_read(priv->regmap, regaddr, regval, len);
if (ret < 0)
{
snerr("regmap read bulk address[%2X] failed: %d!\n", regaddr, ret);
}
~~~

87
drivers/regmap/internal.h Normal file
View File

@ -0,0 +1,87 @@
/****************************************************************************
* drivers/regmap/internal.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __DRIVERS_REGMAP_INTERNAL_H
#define __DRIVERS_REGMAP_INTERNAL_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/regmap/regmap.h>
#include <nuttx/mutex.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
typedef CODE void (*regmap_lock_t)(FAR void *);
typedef CODE void (*regmap_unlock_t)(FAR void *);
/* Configuration for the register map of a device.
* This structure is only used inside regmap.
*/
struct regmap_s
{
regmap_lock_t lock;
regmap_unlock_t unlock;
bool disable_locking;
/* Number of bits in a register address, from regmap_config_s. */
int reg_bytes;
/* Number of bits in a register value, from regmap_config_s. */
int val_bytes;
/* Device bus interface, used internally. */
FAR struct regmap_bus_s *bus;
/* Regmap bus control handle.
* reg_read_t/reg_write_t single-byte register reading.
* read_t/write_t block data reading.
* Note:The transmitted data must be in a data format supported by the bus.
*/
reg_read_t reg_read;
reg_write_t reg_write;
read_t read;
write_t write;
/* The register address stride. Valid register addresses are a multiple
* of this value. If set to 0, a value of 1 will be used.
*/
int reg_stride;
/* Prevent fragmentation */
mutex_t mutex[0];
};
#endif /* __DRIVERS_REGMAP_INTERNAL_H */

382
drivers/regmap/regmap.c Normal file
View File

@ -0,0 +1,382 @@
/****************************************************************************
* drivers/regmap/regmap.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/regmap/regmap.h>
#include <nuttx/lib/math32.h>
#include <nuttx/kmalloc.h>
#include <debug.h>
#include "internal.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define REGMAP_ALIGNED(n, a) (((uint32_t)(n) & ((a) - 1)) == 0)
#define REGMAP_DIVUP(n,d) (((n) + (d) - 1) / (d))
#define REGMAP_DEFAULT_BIT 8
/****************************************************************************
* Private Functions
****************************************************************************/
static void regmap_lock_unlock_none(FAR void *context)
{
}
static void regmap_lock_mutex(FAR void *context)
{
FAR struct regmap_s *map = context;
nxmutex_lock(&map->mutex[0]);
}
static void regmap_unlock_mutex(FAR void *context)
{
FAR struct regmap_s *map = context;
nxmutex_unlock(&map->mutex[0]);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: regmap_init
*
* Description:
* Initialize the internal configuration of regmap. The first parameter
* must be the handle of the bus, and the second parameter is the
* configuration parameter of the bus. Finally, these two parameters will
* be transparent to the corresponding bus.
*
* Input Parameters:
* dev - device handle.
* bus - device configuration.
* config - regmap configuration.
*
* Returned Value:
* Description of the value returned by this function (if any),
* including an enumeration of all possible error values.
*
* Assumptions/Limitations:
* None.
*
****************************************************************************/
FAR struct regmap_s *regmap_init(FAR struct regmap_bus_s *bus,
FAR const struct regmap_config_s *config)
{
FAR struct regmap_s *map;
if (config == NULL || bus == NULL)
{
return NULL;
}
if (config->disable_locking)
{
map = kmm_zalloc(sizeof(*map));
if (map == NULL)
{
return NULL;
}
map->lock = regmap_lock_unlock_none;
map->unlock = regmap_lock_unlock_none;
}
else
{
map = kmm_zalloc(sizeof(*map) + sizeof(mutex_t));
if (map == NULL)
{
return NULL;
}
nxmutex_init(&map->mutex[0]);
map->lock = regmap_lock_mutex;
map->unlock = regmap_unlock_mutex;
}
if (config->reg_stride != 0)
{
map->reg_stride = config->reg_stride;
}
else
{
map->reg_stride = 1;
}
map->reg_bytes = REGMAP_DIVUP(config->reg_bits, REGMAP_DEFAULT_BIT);
map->val_bytes = REGMAP_DIVUP(config->val_bits, REGMAP_DEFAULT_BIT);
map->bus = bus;
map->reg_read = bus->reg_read;
map->reg_write = bus->reg_write;
map->read = bus->read;
map->write = bus->write;
return map;
}
/****************************************************************************
* Name: regmap_write
*
* Description:
* Regmap write, called after initializing the regmap bus device.
* the first parameter is regmap pointer.
*
* Input Parameters:
* map - regmap handler, from regmap bus init function return.
* reg - register address to be write.
* val - write data.
*
* Returned Value:
* Description of the value returned by this function (if any),
* including an enumeration of all possible error values.
*
* Assumptions/Limitations:
* None.
*
****************************************************************************/
int regmap_write(FAR struct regmap_s *map, unsigned int reg,
unsigned int val)
{
int ret;
DEBUGASSERT(REGMAP_ALIGNED(reg, map->reg_stride));
map->lock(map);
ret = map->reg_write(map->bus, reg, val);
map->unlock(map);
return ret;
}
/****************************************************************************
* Name: regmap_bulk_write
*
* Description:
* Regmap bulk write, called after initializing the regmap bus device.
* the first parameter is regmap pointer.
*
* Input Parameters:
* map - regmap handler, from regmap bus init function return.
* reg - register address to be write.
* val - write data buffer.
* val_count - write data buffer size.
*
* Returned Value:
* Description of the value returned by this function (if any),
* including an enumeration of all possible error values.
*
* Assumptions/Limitations:
* None.
*
****************************************************************************/
int regmap_bulk_write(FAR struct regmap_s *map, unsigned int reg,
FAR const void *val, unsigned int val_count)
{
size_t val_bytes = map->val_bytes;
int ret = -ENOSYS;
unsigned int ival;
FAR uint8_t *ptr;
int i;
DEBUGASSERT(REGMAP_ALIGNED(reg, map->reg_stride));
map->lock(map);
if (map->write != NULL)
{
ret = map->write(map->bus, val, val_bytes * val_count);
goto out;
}
for (i = 0; i < val_count; i++)
{
ptr = (FAR uint8_t *)val + (i * val_bytes);
switch (val_bytes)
{
case 1:
ival = *(FAR uint8_t *)ptr;
break;
case 2:
ival = *(FAR uint16_t *)ptr;
break;
case 4:
ival = *(FAR uint32_t *)ptr;
break;
default:
ret = -EINVAL;
goto out;
}
ret = map->reg_write(map->bus, reg + (i * map->reg_stride), ival);
if (ret < 0)
{
break;
}
}
out:
map->unlock(map);
return ret;
}
/****************************************************************************
* Name: regmap_read
*
* Description:
* Regmap read, called after initializing the regmap bus device.
* the first parameter is regmap pointer.
*
* Input Parameters:
* map - regmap handler, from regmap bus init function return.
* reg - register address to be read.
* val - read data buffer.
*
* Returned Value:
* Description of the value returned by this function (if any),
* including an enumeration of all possible error values.
*
* Assumptions/Limitations:
* None.
*
****************************************************************************/
int regmap_read(FAR struct regmap_s *map, unsigned int reg, FAR void *val)
{
int ret;
DEBUGASSERT(REGMAP_ALIGNED(reg, map->reg_stride));
map->lock(map);
ret = map->reg_read(map->bus, reg, val);
map->unlock(map);
return ret;
}
/****************************************************************************
* Name: regmap_bulk_read
*
* Description:
* Regmap bulk read, called after initializing the regmap bus device.
* the first parameter is regmap pointer.
*
* Input Parameters:
* map - regmap handler, from regmap bus init function return.
* reg - register address to be read.
* val - read data buffer.
* val_count - read data buffer size.
*
* Returned Value:
* Description of the value returned by this function (if any),
* including an enumeration of all possible error values.
*
* Assumptions/Limitations:
* None.
*
****************************************************************************/
int regmap_bulk_read(FAR struct regmap_s *map, unsigned int reg,
FAR void *val, unsigned int val_count)
{
FAR uint32_t *u32 = val;
FAR uint16_t *u16 = val;
FAR uint8_t *u8 = val;
unsigned int ival;
int ret = -ENOSYS;
int i;
DEBUGASSERT(REGMAP_ALIGNED(reg, map->reg_stride));
map->lock(map);
if (map->read != NULL)
{
ret = map->read(map->bus, &reg, map->reg_bytes, val, val_count);
}
else
{
for (i = 0; i < val_count; i++)
{
ret = map->reg_read(map->bus, reg + (i * map->reg_stride), &ival);
if (ret < 0)
{
break;
}
switch (map->val_bytes)
{
case 4:
u32[i] = ival;
break;
case 2:
u16[i] = ival;
break;
case 1:
u8[i] = ival;
break;
default:
map->unlock(map);
return -EINVAL;
}
}
}
map->unlock(map);
return ret;
}
/****************************************************************************
* Name: regmap_exit
*
* Description:
* Free a previously allocated register map
*
* Input Parameters:
* map - regmap handler, from regmap bus init function return.
*
* Assumptions/Limitations:
* None.
****************************************************************************/
void regmap_exit(FAR struct regmap_s *map)
{
if (!map->disable_locking)
{
nxmutex_destroy(&map->mutex[0]);
}
kmm_free(map->bus);
kmm_free(map);
}

170
drivers/regmap/regmap_i2c.c Normal file
View File

@ -0,0 +1,170 @@
/****************************************************************************
* drivers/regmap/regmap_i2c.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/regmap/regmap.h>
#include <nuttx/kmalloc.h>
#include <debug.h>
#include "internal.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/* Regmap i2c bus configuration. */
struct regmap_bus_i2c_s
{
struct regmap_bus_s base;
struct i2c_config_s config;
FAR struct i2c_master_s *i2c;
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/* regmap handle functions */
static int regmap_i2c_reg_read(FAR struct regmap_bus_s *bus,
unsigned int regaddr, FAR void *value);
static int regmap_i2c_reg_write(FAR struct regmap_bus_s *bus,
unsigned int regaddr, unsigned int value);
static int regmap_i2c_write(FAR struct regmap_bus_s *bus,
FAR const void *data, unsigned int count);
static int regmap_i2c_read(FAR struct regmap_bus_s *bus,
FAR const void *reg, unsigned int reg_size,
FAR void *val, unsigned int val_size);
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
static int regmap_i2c_write(FAR struct regmap_bus_s *bus,
FAR const void *data, unsigned int count)
{
FAR struct regmap_bus_i2c_s *dev = (FAR struct regmap_bus_i2c_s *)bus;
return i2c_write(dev->i2c, &dev->config, data, count);
}
static int regmap_i2c_read(FAR struct regmap_bus_s *bus,
FAR const void *reg, unsigned int reg_size,
FAR void *val, unsigned int val_size)
{
FAR struct regmap_bus_i2c_s *dev = (FAR struct regmap_bus_i2c_s *)bus;
return i2c_writeread(dev->i2c, &dev->config, reg, reg_size, val,
val_size);
}
static int regmap_i2c_reg_write(FAR struct regmap_bus_s *bus,
unsigned int regaddr, unsigned int value)
{
uint8_t txbuffer[2];
txbuffer[0] = regaddr;
txbuffer[1] = value;
return regmap_i2c_write(bus, txbuffer, 2);
}
static int regmap_i2c_reg_read(FAR struct regmap_bus_s *bus,
unsigned int regaddr, FAR void *value)
{
uint8_t tmp = regaddr;
return regmap_i2c_read(bus, &tmp, 1, value, 1);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: regmap_init_i2c
*
* Description:
* Regmap init i2c bus.
*
* Input Parameters:
* i2c - An instance of the I2C interface to use to communicate.
* i2c_config - i2c device configuration.
* config - regmap configuration.
*
* Returned Value:
* Description of the value returned by this function (if any),
* including an enumeration of all possible error values.
*
* Assumptions/Limitations:
* None.
*
****************************************************************************/
FAR struct regmap_s *
regmap_init_i2c(FAR struct i2c_master_s *i2c,
FAR struct i2c_config_s *i2c_config,
FAR const struct regmap_config_s *config)
{
FAR struct regmap_bus_i2c_s *dev;
FAR struct regmap_s *regmap;
dev = kmm_zalloc(sizeof(struct regmap_bus_i2c_s));
if (dev == NULL)
{
return NULL;
}
dev->base.reg_write = regmap_i2c_reg_write;
dev->base.reg_read = regmap_i2c_reg_read;
dev->base.write = regmap_i2c_write;
dev->base.read = regmap_i2c_read;
dev->config.frequency = i2c_config->frequency;
dev->config.address = i2c_config->address;
dev->config.addrlen = i2c_config->addrlen;
dev->i2c = i2c;
regmap = regmap_init(&dev->base, config);
if (regmap == NULL)
{
kmm_free(dev);
}
return regmap;
}

207
drivers/regmap/regmap_spi.c Normal file
View File

@ -0,0 +1,207 @@
/****************************************************************************
* drivers/regmap/regmap_spi.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/spi/spi_transfer.h>
#include <nuttx/regmap/regmap.h>
#include <nuttx/kmalloc.h>
#include <nuttx/spi/spi.h>
#include <debug.h>
#include "internal.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/* Regmap spi bus configuration. */
struct regmap_bus_spi_s
{
struct regmap_bus_s base;
FAR struct spi_dev_s *spi; /* SPI bus handler. */
struct spi_sequence_s seq; /* Sequence of SPI transactions. */
struct spi_trans_s trans; /* SPI transaction. */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/* Regmap handle functions. */
static int regmap_spi_write(FAR struct regmap_bus_s *bus,
FAR const void *data, unsigned int count);
static int regmap_spi_read(FAR struct regmap_bus_s *bus,
FAR const void *reg, unsigned int reg_size,
FAR void *val, unsigned int val_size);
static int regmap_spi_reg_write(FAR struct regmap_bus_s *bus,
unsigned int regaddr, unsigned int value);
static int regmap_spi_reg_read(FAR struct regmap_bus_s *bus,
unsigned int regaddr, FAR void *value);
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
static int regmap_spi_write(FAR struct regmap_bus_s *bus,
FAR const void *data, unsigned int count)
{
FAR struct regmap_bus_spi_s *dev = (FAR struct regmap_bus_spi_s *)bus;
int ret;
/* Get the attributes of this transactione.
* e.g.:
* data[dev] = {reg_addr, reg_val1, reg_val2, ...}
* if write ok return count, otherwise return negative.
*/
dev->trans.nwords = count;
dev->trans.txbuffer = data;
dev->trans.rxbuffer = NULL;
/* Perform the transfer */
ret = spi_transfer(dev->spi, &dev->seq);
/* Calculate trans length. */
return ret >= 0 ? count : ret;
}
static int regmap_spi_read(FAR struct regmap_bus_s *bus,
FAR const void *reg, unsigned int reg_size,
FAR void *val, unsigned int val_size)
{
FAR struct regmap_bus_spi_s *dev = (FAR struct regmap_bus_spi_s *)bus;
int ret;
/* Get the reference to the spi_transfer_s structure. */
dev->trans.nwords = reg_size + val_size;
dev->trans.txbuffer = reg;
dev->trans.rxbuffer = val;
/* Perform the transfer. */
ret = spi_transfer(dev->spi, &dev->seq);
/* Calculate trans length. */
return ret >= 0 ? val_size : ret;
}
static int regmap_spi_reg_write(FAR struct regmap_bus_s *bus,
unsigned int regaddr, unsigned int value)
{
uint8_t txbuffer[2];
txbuffer[0] = regaddr;
txbuffer[1] = value;
return regmap_spi_write(bus, txbuffer, 2);
}
static int regmap_spi_reg_read(FAR struct regmap_bus_s *bus,
unsigned int regaddr, FAR void *value)
{
uint8_t tmp = regaddr;
return regmap_spi_read(bus, &tmp, 1, value, 1);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: regmap_init_spi
*
* Description:
* Regmap init spi bus.
*
* Input Parameters:
* spi - An instance of the SPI interface to use to communicate.
* freq - SPI frequency (Hz).
* nbits - Number of bits.
* dev_id - See enum spi_devtype_e.
* mode - See enum spi_mode_e.
* config - regmap configuration.
*
* Returned Value:
* Description of the value returned by this function (if any),
* including an enumeration of all possible error values.
*
* Assumptions/Limitations:
* None.
*
****************************************************************************/
FAR struct regmap_s *
regmap_init_spi(FAR struct spi_dev_s *spi, uint32_t freq,
uint32_t devid, enum spi_mode_e mode,
FAR const struct regmap_config_s *config)
{
FAR struct regmap_bus_spi_s *dev;
FAR struct regmap_s *regmap;
dev = kmm_zalloc(sizeof(struct regmap_bus_spi_s));
if (dev == NULL)
{
return NULL;
}
dev->base.reg_write = regmap_spi_reg_write;
dev->base.reg_read = regmap_spi_reg_read;
dev->base.write = regmap_spi_write;
dev->base.read = regmap_spi_read;
dev->trans.deselect = true; /* De-select after transfer. */
dev->seq.dev = devid; /* SPI controler hard cs index. */
dev->seq.mode = mode; /* See enum spi_mode_e. */
dev->seq.nbits = 8; /* Number of bits, Only supports 8bit. */
dev->seq.ntrans = 1; /* Number of transactions. */
dev->seq.frequency = freq; /* SPI frequency (Hz). */
dev->seq.trans = &dev->trans; /* Init spi_sequence_s trans. */
dev->spi = spi;
regmap = regmap_init(&dev->base, config);
if (regmap == NULL)
{
kmm_free(dev);
}
return regmap;
}

View File

@ -650,6 +650,24 @@
# define rcinfo _none
#endif
#ifdef CONFIG_DEBUG_REGMAP_ERROR
# define regmaperr _err
#else
# define regmaperr _none
#endif
#ifdef CONFIG_DEBUG_REGMAP_WARN
# define regmapwarn _warn
#else
# define regmapwarn _none
#endif
#ifdef CONFIG_DEBUG_REGMAP_INFO
# define regmapinfo _info
#else
# define regmapinfo _none
#endif
#ifdef CONFIG_DEBUG_RMT_ERROR
# define rmterr _err
#else

View File

@ -0,0 +1,312 @@
/****************************************************************************
* include/nuttx/regmap/regmap.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_REGMAP_REGMAP_H
#define __INCLUDE_NUTTX_REGMAP_REGMAP_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/compiler.h>
#include <stdbool.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
struct regmap_bus_s;
/* Single byte register read/write. */
typedef CODE int (*reg_read_t)(FAR struct regmap_bus_s *bus,
unsigned int reg,
FAR void *val);
typedef CODE int (*reg_write_t)(FAR struct regmap_bus_s *bus,
unsigned int reg,
unsigned int val);
/* Bulk read/write */
typedef CODE int (*read_t)(FAR struct regmap_bus_s *bus,
FAR const void *reg_buf, unsigned int reg_size,
FAR void *val_buf, unsigned int val_size);
typedef CODE int (*write_t)(FAR struct regmap_bus_s *bus,
FAR const void *data,
unsigned int count);
/* Description of a hardware bus for the register map infrastructure. */
struct regmap_bus_s
{
reg_read_t reg_read;
reg_write_t reg_write;
read_t read;
write_t write;
};
/* Configuration for the register map of a device.
* reg_bits and val_bits must be set.
*/
struct regmap_config_s
{
/* Number of bits in a register address, mandatory. */
int reg_bits;
/* The register address stride. Valid register addresses are a multiple
* of this value. If set to 0, a value of 1 will be used.
*/
int reg_stride;
/* Number of bits in a register value, mandatory. */
int val_bits;
/* This regmap is either protected by external means or is guaranteed
* not to be accessed from multiple threads. Don't use any locking
* mechanisms.
*/
bool disable_locking;
};
struct regmap_s;
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Name: regmap_init
*
* Description:
* Initialize the internal configuration of regmap. The first parameter
* must be the handle of the bus, and the second parameter is the
* configuration parameter of the bus. Finally, these two parameters will
* be transparent to the corresponding bus.
*
* Input Parameters:
* dev - device handle.
* bus - device configuration.
* config - regmap configuration.
*
* Returned Value:
* Description of the value returned by this function (if any),
* including an enumeration of all possible error values.
*
* Assumptions/Limitations:
* none.
*
****************************************************************************/
FAR struct regmap_s *regmap_init(FAR struct regmap_bus_s *bus,
FAR const struct regmap_config_s *config);
/****************************************************************************
* Name: regmap_init_i2c
*
* Description:
* Regmap init i2c bus.
*
* Input Parameters:
* i2c - An instance of the I2C interface to use to communicate.
* i2c_config - i2c device configuration.
* config - regmap configuration.
*
* Returned Value:
* Description of the value returned by this function (if any),
* including an enumeration of all possible error values.
*
* Assumptions/Limitations:
* None.
*
****************************************************************************/
#ifdef CONFIG_I2C
struct i2c_master_s;
struct i2c_config_s;
FAR struct regmap_s *
regmap_init_i2c(FAR struct i2c_master_s *i2c,
FAR struct i2c_config_s *i2c_config,
FAR const struct regmap_config_s *config);
#endif /* CONFIG_I2C */
/****************************************************************************
* Name: regmap_init_spi
*
* Description:
* regmap init spi bus.
*
* Input Parameters:
* spi - An instance of the SPI interface to use to communicate.
* freq - SPI frequency (Hz)
* nbits - Number of bits
* dev_id - See enum spi_devtype_e
* mode - See enum spi_mode_e
* config - regmap configuration.
*
* Returned Value:
* Description of the value returned by this function (if any),
* including an enumeration of all possible error values.
*
* Assumptions/Limitations:
* none.
*
****************************************************************************/
#ifdef CONFIG_SPI
struct spi_dev_s;
FAR struct regmap_s *
regmap_init_spi(FAR struct spi_dev_s *spi, uint32_t freq,
uint32_t devid, enum spi_mode_e mode,
FAR const struct regmap_config_s *config);
#endif /* CONFIG_SPI */
/****************************************************************************
* Name: regmap_exit
*
* Description:
* Regmap exit function.
*
****************************************************************************/
void regmap_exit(FAR struct regmap_s *map);
/****************************************************************************
* Name: regmap_write
*
* Description:
* Regmap write, called after initializing the regmap bus device.
* the first parameter is regmap pointer.
*
* Input Parameters:
* map - regmap handler, from regmap bus init function return.
* reg - register address to be write.
* val - write data.
*
* Returned Value:
* Description of the value returned by this function (if any),
* including an enumeration of all possible error values.
*
* Assumptions/Limitations:
* None.
*
****************************************************************************/
int regmap_write(FAR struct regmap_s *map, unsigned int reg,
unsigned int val);
/****************************************************************************
* Name: regmap_bulk_write
*
* Description:
* Regmap bulk write, called after initializing the regmap bus device.
* the first parameter is regmap pointer.
*
* Input Parameters:
* map - regmap handler, from regmap bus init function return.
* reg - register address to be write.
* val - write data buffer.
* val_count - write data buffer size.
*
* Returned Value:
* Description of the value returned by this function (if any),
* including an enumeration of all possible error values.
*
* Assumptions/Limitations:
* None.
*
****************************************************************************/
int regmap_bulk_write(FAR struct regmap_s *map, unsigned int reg,
FAR const void *val, unsigned int val_count);
/****************************************************************************
* Name: regmap_read
*
* Description:
* Regmap read, called after initializing the regmap bus device.
* the first parameter is regmap pointer.
*
* Input Parameters:
* map - regmap handler, from regmap bus init function return.
* reg - register address to be read.
* val - read data buffer.
*
* Returned Value:
* Description of the value returned by this function (if any),
* including an enumeration of all possible error values.
*
* Assumptions/Limitations:
* None.
*
****************************************************************************/
int regmap_read(FAR struct regmap_s *map, unsigned int reg,
FAR void *val);
/****************************************************************************
* Name: regmap_bulk_read
*
* Description:
* Regmap bulk read, called after initializing the regmap bus device.
* the first parameter is regmap pointer.
*
* Input Parameters:
* map - regmap handler, from regmap bus init function return.
* reg - register address to be read.
* val - read data buffer.
* val_count - read data buffer size.
*
* Returned Value:
* Description of the value returned by this function (if any),
* including an enumeration of all possible error values.
*
* Assumptions/Limitations:
* None.
*
****************************************************************************/
int regmap_bulk_read(FAR struct regmap_s *map, unsigned int reg,
FAR void *val, unsigned int val_count);
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __INCLUDE_NUTTX_REGMAP_REGMAP_H */