drivers/leds/leds-lp8864.c

Source file repositories/reference/linux-study-clean/drivers/leds/leds-lp8864.c

File Facts

System
Linux kernel
Corpus path
drivers/leds/leds-lp8864.c
Extension
.c
Size
7974 bytes
Lines
297
Domain
Driver Families
Bucket
drivers/leds
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 lp8864_led {
	struct i2c_client *client;
	struct led_classdev led_dev;
	struct regmap *regmap;
	u16 led_status_mask;
};

static int lp8864_fault_check(struct lp8864_led *led)
{
	int ret, i;
	unsigned int val;

	ret = regmap_read(led->regmap, LP8864_SUPPLY_STATUS, &val);
	if (ret)
		goto err;

	/* Odd bits are status bits, even bits are clear bits */
	for (i = 0; i < ARRAY_SIZE(lp8864_supply_status_msg); i++)
		if (val & BIT(i * 2 + 1))
			dev_warn(&led->client->dev, "%s\n", lp8864_supply_status_msg[i]);

	/*
	 * Clear bits have an index preceding the corresponding Status bits;
	 * both have to be written "1" simultaneously to clear the corresponding
	 * Status bit.
	 */
	if (val)
		ret = regmap_write(led->regmap, LP8864_SUPPLY_STATUS, val >> 1 | val);
	if (ret)
		goto err;

	ret = regmap_read(led->regmap, LP8864_BOOST_STATUS, &val);
	if (ret)
		goto err;

	/* Odd bits are status bits, even bits are clear bits */
	for (i = 0; i < ARRAY_SIZE(lp8864_boost_status_msg); i++)
		if (val & BIT(i * 2 + 1))
			dev_warn(&led->client->dev, "%s\n", lp8864_boost_status_msg[i]);

	if (val)
		ret = regmap_write(led->regmap, LP8864_BOOST_STATUS, val >> 1 | val);
	if (ret)
		goto err;

	ret = regmap_read(led->regmap, LP8864_LED_STATUS, &val);
	if (ret)
		goto err;

	/*
	 * Clear already reported faults that maintain their value until device
	 * power-down
	 */
	val &= ~led->led_status_mask;

	for (i = 0; i < ARRAY_SIZE(lp8864_led_status_msg); i++)
		if (lp8864_led_status_msg[i] && val & BIT(i))
			dev_warn(&led->client->dev, "%s\n", lp8864_led_status_msg[i]);

	/*
	 * Mark those which maintain their value until device power-down as
	 * "already reported"
	 */
	led->led_status_mask |= val & ~LP8864_LED_STATUS_WR_MASK;

	/*
	 * Only bits 14, 12, 10 have to be cleared here, but others are RO,
	 * we don't care what we write to them.
	 */
	if (val & LP8864_LED_STATUS_WR_MASK)
		ret = regmap_write(led->regmap, LP8864_LED_STATUS, val >> 1 | val);
	if (ret)
		goto err;

	return 0;

err:
	dev_err(&led->client->dev, "Failed to read/clear faults (%pe)\n", ERR_PTR(ret));

	return ret;
}

static int lp8864_brightness_set(struct led_classdev *led_cdev,
				 enum led_brightness brt_val)
{
	struct lp8864_led *led = container_of(led_cdev, struct lp8864_led, led_dev);
	/* Scale 0..LED_FULL into 16-bit HW brightness */
	unsigned int val = brt_val * 0xffff / LED_FULL;
	int ret;

Annotation

Implementation Notes