drivers/gpu/drm/loongson/lsdc_i2c.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/loongson/lsdc_i2c.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/loongson/lsdc_i2c.c
Extension
.c
Size
4301 bytes
Lines
180
Domain
Driver Families
Bucket
drivers/gpu
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

// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2023 Loongson Technology Corporation Limited
 */

#include <drm/drm_managed.h>
#include <drm/drm_print.h>

#include "lsdc_drv.h"
#include "lsdc_output.h"

/*
 * __lsdc_gpio_i2c_set - set the state of a gpio pin indicated by mask
 * @mask: gpio pin mask
 * @state: "0" for low, "1" for high
 */
static void __lsdc_gpio_i2c_set(struct lsdc_i2c * const li2c, int mask, int state)
{
	struct lsdc_device *ldev = to_lsdc(li2c->ddev);
	unsigned long flags;
	u8 val;

	spin_lock_irqsave(&ldev->reglock, flags);

	if (state) {
		/*
		 * Setting this pin as input directly, write 1 for input.
		 * The external pull-up resistor will pull the level up
		 */
		val = readb(li2c->dir_reg);
		val |= mask;
		writeb(val, li2c->dir_reg);
	} else {
		/* First set this pin as output, write 0 for output */
		val = readb(li2c->dir_reg);
		val &= ~mask;
		writeb(val, li2c->dir_reg);

		/* Then, make this pin output 0 */
		val = readb(li2c->dat_reg);
		val &= ~mask;
		writeb(val, li2c->dat_reg);
	}

	spin_unlock_irqrestore(&ldev->reglock, flags);
}

/*
 * __lsdc_gpio_i2c_get - read value back from the gpio pin indicated by mask
 * @mask: gpio pin mask
 * return "0" for low, "1" for high
 */
static int __lsdc_gpio_i2c_get(struct lsdc_i2c * const li2c, int mask)
{
	struct lsdc_device *ldev = to_lsdc(li2c->ddev);
	unsigned long flags;
	u8 val;

	spin_lock_irqsave(&ldev->reglock, flags);

	/* First set this pin as input */
	val = readb(li2c->dir_reg);
	val |= mask;
	writeb(val, li2c->dir_reg);

	/* Then get level state from this pin */
	val = readb(li2c->dat_reg);

	spin_unlock_irqrestore(&ldev->reglock, flags);

	return (val & mask) ? 1 : 0;
}

static void lsdc_gpio_i2c_set_sda(void *i2c, int state)
{
	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
	/* set state on the li2c->sda pin */
	return __lsdc_gpio_i2c_set(li2c, li2c->sda, state);
}

static void lsdc_gpio_i2c_set_scl(void *i2c, int state)
{
	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;
	/* set state on the li2c->scl pin */
	return __lsdc_gpio_i2c_set(li2c, li2c->scl, state);
}

static int lsdc_gpio_i2c_get_sda(void *i2c)
{
	struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c;

Annotation

Implementation Notes