doubao_chat/apps/common/iic/iic.c

134 lines
3.2 KiB
C

#include "device/iic.h"
static struct list_head head = LIST_HEAD_INIT(head);
static int iic_open(const char *name, struct device **device, void *arg)
{
struct iic_device *p;
int id = name[3] - '0';
list_for_each_entry(p, &head, entry) {
if (p->id == id) {
*device = &p->dev;
(*device)->private_data = p;
if (!p->open_status) {
if (p->ops->open) {
p->ops->open(p);
}
os_mutex_create(&p->mutex);
p->open_status = 1;
}
return 0;
}
}
return -EINVAL;
}
static int iic_read(struct device *device, void *buf, unsigned int len, u32 addr)
{
struct iic_device *iic = (struct iic_device *)device->private_data;
int ret;
os_mutex_pend(&iic->mutex, 0);
ret = iic->ops->read(iic, buf, len);
os_mutex_post(&iic->mutex);
return ret;
}
static int iic_write(struct device *device, void *buf, unsigned int len, u32 addr)
{
struct iic_device *iic = (struct iic_device *)device->private_data;
int ret;
os_mutex_pend(&iic->mutex, 0);
ret = iic->ops->write(iic, buf, len);
os_mutex_post(&iic->mutex);
return ret;
}
int __attribute__((weak)) iic_ioctl_ex(struct iic_device *iic, int cmd, int arg)
{
return false;
}
static int iic_ioctl(struct device *device, unsigned int cmd, unsigned int arg)
{
int ret = 0;
struct iic_device *iic = (struct iic_device *)device->private_data;
if (iic->ops->ioctl) {
if (cmd == IIC_IOCTL_START) {
if (!(cpu_in_irq() || cpu_irq_disabled())) {
os_mutex_pend(&iic->mutex, 0);
}
}
if (!iic_ioctl_ex(iic, cmd, arg)) {
ret = iic->ops->ioctl(iic, cmd, arg);
}
if (cmd == IIC_IOCTL_STOP) {
if (!(cpu_in_irq() || cpu_irq_disabled())) {
os_mutex_post(&iic->mutex);
}
}
return ret;
}
return 0;
}
static int iic_init(const struct dev_node *node, void *_data)
{
int id;
struct iic_device *iic;
const struct iic_operations *p;
const struct iic_platform_data *data = (const struct iic_platform_data *)_data;
id = node->name[3] - '0';
list_for_each_iic_device_ops(p) {
if (p->type == data->type) {
iic = data->p_iic_device;//(struct iic_device *)malloc(sizeof(*iic));
if (!iic) {
return -ENOMEM;
}
iic->id = id;
iic->hw = &data->data;
iic->ops = p;
iic->open_status = 0;
list_add(&iic->entry, &head);
return 0;
}
}
return -EINVAL;
}
static int iic_close(struct device *device)
{
struct iic_device *iic = (struct iic_device *)device->private_data;
int ret = 0;
os_mutex_pend(&iic->mutex, 0);
if (iic->ops->close) {
ret = iic->ops->close(iic);
}
os_mutex_del(&iic->mutex, OS_DEL_ALWAYS);
iic->open_status = 0;
return ret;
}
const struct device_operations iic_dev_ops = {
.init = iic_init,
.open = iic_open,
.read = iic_read,
.write = iic_write,
.ioctl = iic_ioctl,
.close = iic_close,
};