nuttx/boards/arm/cxd56xx/drivers/sensors/bh1721fvc_scu.c
Alin Jerpelea 077ef70b0c cxd56xx improvements (#48)
* arch: cxd56xx: Add size limitation for I2C SCU xfer

This is a fw restriction, unroll loop because it can be transfer
up to 16 bytes.

* arch: cxd56xx: Fix lack of leave_critical_section

add the missing leave_critical_section

* arch: cxd56xx: Remove unnecessary file

this header is duplicate and we can remove it

* arch: cxd56xx: Cosmetic change

remove space after function

* arch: cxd56xx: update topreg registers

the topreg registers are updated to match the cxd5602 HW

* arch: cxd56xx: Add voltage setting for low battery notification

Add voltage setting for low battery notification

* arch: cxd56xx: Improve perfomance of SD card

Improve a problem that the clock of SD Host Controller is lower than the
expected value in SDR25 transfer mode.

* arch: cxd56xx: Cosmetic changes

cleanup to comply with coding standard

* boards: cxd56xx: Cosmetic changes

updates to comply with coding standard

* boards: cxd56xx: Fix SD card cannot mount issue

SD card cannot mount when connecting and disconnecting three times
or more due to wrong state of parameter 'initialized'.

This change enables to skip swtching initialized state when mount
failed.
2020-01-07 11:21:58 -03:00

395 lines
12 KiB
C

/****************************************************************************
* boards/arm/cxd56xx/drivers/sensors/bh1721fvc_scu.c
*
* Copyright 2018 Sony Semiconductor Solutions Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of Sony Semiconductor Solutions Corporation nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdlib.h>
#include <stdio.h>
#include <fixedmath.h>
#include <errno.h>
#include <debug.h>
#include <semaphore.h>
#include <arch/types.h>
#include <nuttx/kmalloc.h>
#include <nuttx/fs/fs.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/sensors/bh1721fvc.h>
#include <nuttx/irq.h>
#include <arch/chip/scu.h>
#if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_BH1721FVC_SCU)
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define BH1721FVC_ADDR 0x23 /* I2C Slave Address */
#define BH1721FVC_BYTESPERSAMPLE 2
#define BH1721FVC_ELEMENTSIZE 0
/* BH1721FVC Opecode */
#define BH1721FVC_POWERDOWN 0x00
#define BH1721FVC_POWERON 0x01
#define BH1721FVC_AUTORESOLUTION 0x10
#ifndef itemsof
# define itemsof(array) (sizeof(array)/sizeof(array[0]))
#endif
/****************************************************************************
* Private Type Definitions
****************************************************************************/
/**
* @brief Structure for bh1721fvc device
*/
struct bh1721fvc_dev_s
{
FAR struct i2c_master_s *i2c; /* I2C interface */
uint8_t addr; /* I2C address */
int port; /* I2C port */
struct seq_s *seq; /* Sequencer instance */
int minor; /* Minor device number */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/* Character driver methods */
static int bh1721fvc_open(FAR struct file *filep);
static int bh1721fvc_close(FAR struct file *filep);
static ssize_t bh1721fvc_read(FAR struct file *filep, FAR char *buffer,
size_t buflen);
static ssize_t bh1721fvc_write(FAR struct file *filep, FAR const char *buffer,
size_t buflen);
static int bh1721fvc_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
/****************************************************************************
* Private Data
****************************************************************************/
static const struct file_operations g_bh1721fvcfops =
{
bh1721fvc_open, /* open */
bh1721fvc_close, /* close */
bh1721fvc_read, /* read */
bh1721fvc_write, /* write */
0, /* seek */
bh1721fvc_ioctl, /* ioctl */
#ifndef CONFIG_DISABLE_POLL
0, /* poll */
#endif
0 /* unlink */
};
/* Take ambient light data. */
static const uint16_t g_bh1721fvcinst[] =
{
SCU_INST_RECV(BH1721FVC_BYTESPERSAMPLE) | SCU_INST_LAST,
};
/* Reference count */
static int g_refcnt = 0;
/* Sequencer instance */
static struct seq_s *g_seq = NULL;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: bh1721fvc_writeopecode
*
* Description:
* Write to BH1721FVC opecode
*
****************************************************************************/
static void bh1721fvc_writeopecode(FAR struct bh1721fvc_dev_s *priv,
uint8_t opecode)
{
uint16_t inst = SCU_INST_SEND(opecode) | SCU_INST_LAST;
/* Send opecode */
scu_i2ctransfer(priv->port, priv->addr, &inst, 1, NULL, 0);
}
/****************************************************************************
* Name: bh1721fvc_seqinit
*
* Description:
* Initialize SCU sequencer.
*
****************************************************************************/
static int bh1721fvc_seqinit(FAR struct bh1721fvc_dev_s *priv)
{
DEBUGASSERT(g_seq == NULL);
/* Open sequencer */
g_seq = seq_open(SEQ_TYPE_NORMAL, SCU_BUS_I2C0);
if (!g_seq)
{
return -ENOENT;
}
priv->seq = g_seq;
seq_setaddress(priv->seq, priv->addr);
/* Set instruction and sample data information to sequencer */
seq_setinstruction(priv->seq, g_bh1721fvcinst, itemsof(g_bh1721fvcinst));
seq_setsample(priv->seq, BH1721FVC_BYTESPERSAMPLE, 0, BH1721FVC_ELEMENTSIZE,
false);
return OK;
}
/****************************************************************************
* Name: bh1721fvc_open
*
* Description:
* This function is called whenever the BH1721FVC device is opened.
*
****************************************************************************/
static int bh1721fvc_open(FAR struct file *filep)
{
FAR struct inode *inode = filep->f_inode;
FAR struct bh1721fvc_dev_s *priv = inode->i_private;
if (g_refcnt == 0)
{
int ret;
ret = bh1721fvc_seqinit(priv);
if (ret < 0)
{
return ret;
}
bh1721fvc_writeopecode(priv, BH1721FVC_POWERON);
bh1721fvc_writeopecode(priv, BH1721FVC_AUTORESOLUTION);
}
g_refcnt++;
return OK;
}
/****************************************************************************
* Name: bh1721fvc_close
*
* Description:
* This routine is called when the BH1721FVC device is closed.
*
****************************************************************************/
static int bh1721fvc_close(FAR struct file *filep)
{
FAR struct inode *inode = filep->f_inode;
FAR struct bh1721fvc_dev_s *priv = inode->i_private;
g_refcnt--;
seq_ioctl(priv->seq, priv->minor, SCUIOC_STOP, 0);
if (g_refcnt == 0)
{
bh1721fvc_writeopecode(priv, BH1721FVC_POWERDOWN);
seq_close(g_seq);
g_seq = NULL;
}
else
{
seq_ioctl(priv->seq, priv->minor, SCUIOC_FREEFIFO, 0);
}
return OK;
}
/****************************************************************************
* Name: bh1721fvc_read
****************************************************************************/
static ssize_t bh1721fvc_read(FAR struct file *filep, FAR char *buffer,
size_t len)
{
FAR struct inode *inode = filep->f_inode;
FAR struct bh1721fvc_dev_s *priv = inode->i_private;
len = len / BH1721FVC_BYTESPERSAMPLE * BH1721FVC_BYTESPERSAMPLE;
len = seq_read(priv->seq, priv->minor, buffer, len);
return len;
}
/****************************************************************************
* Name: bh1721fvc_write
****************************************************************************/
static ssize_t bh1721fvc_write(FAR struct file *filep, FAR const char *buffer,
size_t buflen)
{
return -ENOSYS;
}
/****************************************************************************
* Name: bh1721fvc_ioctl
****************************************************************************/
static int bh1721fvc_ioctl(FAR struct file *filep, int cmd,
unsigned long arg)
{
FAR struct inode *inode = filep->f_inode;
FAR struct bh1721fvc_dev_s *priv = inode->i_private;
int ret = OK;
switch (cmd)
{
default:
{
if (_SCUIOCVALID(cmd))
{
/* Redirect SCU commands */
ret = seq_ioctl(priv->seq, priv->minor, cmd, arg);
}
else
{
snerr("Unrecognized cmd: %d\n", cmd);
ret = - ENOTTY;
}
}
break;
}
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: bh1721fvc_init
*
* Description:
* Initialize the BH1721FVC device
*
* Input Parameters:
* i2c - An instance of the I2C interface to use to communicate with
* BH1721FVC
* port - I2C port (0 or 1)
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
int bh1721fvc_init(FAR struct i2c_master_s *i2c, int port)
{
return OK;
}
/****************************************************************************
* Name: bh1721fvc_register
*
* Description:
* Register the BH1721FVC ambient light sensor character device as 'devpath'
*
* Input Parameters:
* devpath - The full path to the driver to register. E.g., "/dev/light0"
* minor - minor device number
* i2c - An instance of the I2C interface to use to communicate with
* BH1721FVC
* port - I2C port (0 or 1)
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
*
****************************************************************************/
int bh1721fvc_register(FAR const char *devpath, int minor,
FAR struct i2c_master_s *i2c, int port)
{
FAR struct bh1721fvc_dev_s *priv;
char path[16];
int ret;
/* Initialize the BH1721FVC device structure */
priv = (FAR struct bh1721fvc_dev_s *)
kmm_malloc(sizeof(struct bh1721fvc_dev_s));
if (!priv)
{
snerr("Failed to allocate instance\n");
return -ENOMEM;
}
priv->i2c = i2c;
priv->addr = BH1721FVC_ADDR;
priv->port = port;
priv->seq = NULL;
priv->minor = minor;
/* Register the character driver */
snprintf(path, sizeof(path), "%s%d", devpath, minor);
ret = register_driver(path, &g_bh1721fvcfops, 0666, priv);
if (ret < 0)
{
snerr("Failed to register driver: %d\n", ret);
kmm_free(priv);
}
return ret;
}
#endif /* CONFIG_I2C && CONFIG_SENSORS_BH1721FVC_SCU */