1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-16 08:12:53 +08:00
corundum/modules/mqnic/mqnic_i2c.c

157 lines
3.4 KiB
C
Raw Normal View History

// SPDX-License-Identifier: BSD-2-Clause-Views
/*
* Copyright (c) 2019-2023 The Regents of the University of California
*/
#include "mqnic.h"
2021-01-13 20:09:09 -08:00
static void mqnic_i2c_set_scl(void *data, int state)
{
2021-10-08 18:31:53 -07:00
struct mqnic_i2c_bus *bus = data;
if (state)
iowrite32(ioread32(bus->scl_out_reg) | bus->scl_out_mask, bus->scl_out_reg);
else
iowrite32(ioread32(bus->scl_out_reg) & ~bus->scl_out_mask, bus->scl_out_reg);
}
2021-01-13 20:09:09 -08:00
static void mqnic_i2c_set_sda(void *data, int state)
{
2021-10-08 18:31:53 -07:00
struct mqnic_i2c_bus *bus = data;
if (state)
iowrite32(ioread32(bus->sda_out_reg) | bus->sda_out_mask, bus->sda_out_reg);
else
iowrite32(ioread32(bus->sda_out_reg) & ~bus->sda_out_mask, bus->sda_out_reg);
}
2021-01-13 20:09:09 -08:00
static int mqnic_i2c_get_scl(void *data)
{
2021-10-08 18:31:53 -07:00
struct mqnic_i2c_bus *bus = data;
2021-10-08 18:31:53 -07:00
return !!(ioread32(bus->scl_in_reg) & bus->scl_in_mask);
}
2021-01-13 20:09:09 -08:00
static int mqnic_i2c_get_sda(void *data)
{
2021-10-08 18:31:53 -07:00
struct mqnic_i2c_bus *bus = data;
2021-10-08 18:31:53 -07:00
return !!(ioread32(bus->sda_in_reg) & bus->sda_in_mask);
}
2021-12-29 22:31:46 -08:00
struct mqnic_i2c_bus *mqnic_i2c_bus_create(struct mqnic_dev *mqnic, int index)
2020-09-19 17:00:39 -07:00
{
2021-10-08 18:31:53 -07:00
struct mqnic_i2c_bus *bus;
struct i2c_algo_bit_data *algo;
struct i2c_adapter *adapter;
struct mqnic_reg_block *rb;
2021-10-08 18:31:53 -07:00
rb = mqnic_find_reg_block(mqnic->rb_list, MQNIC_RB_I2C_TYPE, MQNIC_RB_I2C_VER, index);
2021-12-29 22:31:46 -08:00
if (!rb)
2021-10-08 18:31:53 -07:00
return NULL;
bus = kzalloc(sizeof(*bus), GFP_KERNEL);
if (!bus)
return NULL;
// set private data
bus->mqnic = mqnic;
2021-12-29 22:31:46 -08:00
bus->scl_in_reg = rb->regs + MQNIC_RB_I2C_REG_CTRL;
bus->scl_out_reg = rb->regs + MQNIC_RB_I2C_REG_CTRL;
bus->sda_in_reg = rb->regs + MQNIC_RB_I2C_REG_CTRL;
bus->sda_out_reg = rb->regs + MQNIC_RB_I2C_REG_CTRL;
2021-10-08 18:31:53 -07:00
bus->scl_in_mask = MQNIC_REG_GPIO_I2C_SCL_IN;
bus->scl_out_mask = MQNIC_REG_GPIO_I2C_SCL_OUT;
bus->sda_in_mask = MQNIC_REG_GPIO_I2C_SDA_IN;
bus->sda_out_mask = MQNIC_REG_GPIO_I2C_SDA_OUT;
// bit-bang algorithm setup
algo = &bus->algo;
algo->udelay = 5;
algo->timeout = usecs_to_jiffies(2000);
2021-10-08 18:31:53 -07:00
algo->setsda = mqnic_i2c_set_sda;
algo->setscl = mqnic_i2c_set_scl;
algo->getsda = mqnic_i2c_get_sda;
algo->getscl = mqnic_i2c_get_scl;
algo->data = bus;
// adapter setup
adapter = &bus->adapter;
adapter->owner = THIS_MODULE;
adapter->algo_data = algo;
adapter->dev.parent = mqnic->dev;
snprintf(adapter->name, sizeof(adapter->name), "%s I2C%d", mqnic->name,
mqnic->i2c_adapter_count);
2021-10-08 18:31:53 -07:00
if (i2c_bit_add_bus(adapter)) {
dev_err(mqnic->dev, "Failed to register I2C adapter");
goto err_free_bus;
}
list_add_tail(&bus->head, &mqnic->i2c_bus);
mqnic->i2c_adapter_count++;
return bus;
err_free_bus:
2021-10-08 18:31:53 -07:00
kfree(bus);
return NULL;
2020-09-19 17:00:39 -07:00
}
2021-12-29 22:31:46 -08:00
struct i2c_adapter *mqnic_i2c_adapter_create(struct mqnic_dev *mqnic, int index)
{
2021-12-29 22:31:46 -08:00
struct mqnic_i2c_bus *bus = mqnic_i2c_bus_create(mqnic, index);
2021-10-08 18:31:53 -07:00
if (!bus)
return NULL;
2021-10-08 18:31:53 -07:00
return &bus->adapter;
}
void mqnic_i2c_bus_release(struct mqnic_i2c_bus *bus)
{
2021-10-08 18:31:53 -07:00
struct mqnic_dev *mqnic;
2021-10-08 18:31:53 -07:00
if (!bus)
return;
2020-09-25 23:14:22 -07:00
2021-10-08 18:31:53 -07:00
mqnic = bus->mqnic;
2020-09-25 23:14:22 -07:00
2021-10-08 18:31:53 -07:00
mqnic->i2c_adapter_count--;
2020-09-25 23:14:22 -07:00
2021-10-08 18:31:53 -07:00
i2c_del_adapter(&bus->adapter);
list_del(&bus->head);
kfree(bus);
}
2020-09-25 23:14:22 -07:00
void mqnic_i2c_adapter_release(struct i2c_adapter *adapter)
{
2021-10-08 18:31:53 -07:00
struct mqnic_i2c_bus *bus;
2021-10-08 18:31:53 -07:00
if (!adapter)
return;
2021-10-08 18:31:53 -07:00
bus = container_of(adapter, struct mqnic_i2c_bus, adapter);
mqnic_i2c_bus_release(bus);
}
int mqnic_i2c_init(struct mqnic_dev *mqnic)
{
2021-10-08 18:31:53 -07:00
INIT_LIST_HEAD(&mqnic->i2c_bus);
2021-10-08 18:31:53 -07:00
return 0;
}
void mqnic_i2c_deinit(struct mqnic_dev *mqnic)
{
2021-10-08 18:31:53 -07:00
struct mqnic_i2c_bus *bus;
while (!list_empty(&mqnic->i2c_bus)) {
bus = list_first_entry(&mqnic->i2c_bus, typeof(*bus), head);
mqnic_i2c_bus_release(bus);
}
}