drivers/gpio/gpio-ljca.c

Source file repositories/reference/linux-study-clean/drivers/gpio/gpio-ljca.c

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-ljca.c
Extension
.c
Size
13570 bytes
Lines
493
Domain
Driver Families
Bucket
drivers/gpio
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct ljca_gpio_op {
	u8 index;
	u8 value;
} __packed;

struct ljca_gpio_packet {
	u8 num;
	struct ljca_gpio_op item[] __counted_by(num);
} __packed;

struct ljca_gpio_dev {
	struct ljca_client *ljca;
	struct gpio_chip gc;
	struct ljca_gpio_info *gpio_info;
	DECLARE_BITMAP(unmasked_irqs, LJCA_MAX_GPIO_NUM);
	DECLARE_BITMAP(enabled_irqs, LJCA_MAX_GPIO_NUM);
	DECLARE_BITMAP(reenable_irqs, LJCA_MAX_GPIO_NUM);
	DECLARE_BITMAP(output_enabled, LJCA_MAX_GPIO_NUM);
	u8 *connect_mode;
	/* protect irq bus */
	struct mutex irq_lock;
	struct work_struct work;
	/* protect package transfer to hardware */
	struct mutex trans_lock;

	u8 obuf[LJCA_GPIO_BUF_SIZE];
	u8 ibuf[LJCA_GPIO_BUF_SIZE];
};

static int ljca_gpio_config(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id,
			    u8 config)
{
	struct ljca_gpio_packet *packet =
				(struct ljca_gpio_packet *)ljca_gpio->obuf;
	int ret;

	mutex_lock(&ljca_gpio->trans_lock);
	packet->num = 1;
	packet->item[0].index = gpio_id;
	packet->item[0].value = config | ljca_gpio->connect_mode[gpio_id];

	ret = ljca_transfer(ljca_gpio->ljca, LJCA_GPIO_CONFIG, (u8 *)packet,
			    struct_size(packet, item, packet->num), NULL, 0);
	mutex_unlock(&ljca_gpio->trans_lock);

	return ret < 0 ? ret : 0;
}

static int ljca_gpio_read(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id)
{
	struct ljca_gpio_packet *ack_packet =
				(struct ljca_gpio_packet *)ljca_gpio->ibuf;
	struct ljca_gpio_packet *packet =
				(struct ljca_gpio_packet *)ljca_gpio->obuf;
	int ret;

	mutex_lock(&ljca_gpio->trans_lock);
	packet->num = 1;
	packet->item[0].index = gpio_id;
	ret = ljca_transfer(ljca_gpio->ljca, LJCA_GPIO_READ, (u8 *)packet,
			    struct_size(packet, item, packet->num),
			    ljca_gpio->ibuf, LJCA_GPIO_BUF_SIZE);

	if (ret <= 0 || ack_packet->num != packet->num) {
		dev_err(&ljca_gpio->ljca->auxdev.dev,
			"read package error, gpio_id: %u num: %u ret: %d\n",
			gpio_id, ack_packet->num, ret);
		ret = ret < 0 ? ret : -EIO;
	}
	mutex_unlock(&ljca_gpio->trans_lock);

	return ret < 0 ? ret : ack_packet->item[0].value > 0;
}

static int ljca_gpio_write(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id, int value)
{
	struct ljca_gpio_packet *packet =
			(struct ljca_gpio_packet *)ljca_gpio->obuf;
	int ret;

	mutex_lock(&ljca_gpio->trans_lock);
	packet->num = 1;
	packet->item[0].index = gpio_id;
	packet->item[0].value = value & 1;

	ret = ljca_transfer(ljca_gpio->ljca, LJCA_GPIO_WRITE, (u8 *)packet,
			    struct_size(packet, item, packet->num), NULL, 0);
	mutex_unlock(&ljca_gpio->trans_lock);

	return ret < 0 ? ret : 0;

Annotation

Implementation Notes