drivers/leds/leds-mlxreg.c

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

File Facts

System
Linux kernel
Corpus path
drivers/leds/leds-mlxreg.c
Extension
.c
Size
8809 bytes
Lines
294
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 mlxreg_led_data {
	struct mlxreg_core_data *data;
	struct led_classdev led_cdev;
	u8 base_color;
	void *data_parent;
	char led_cdev_name[MLXREG_CORE_LABEL_MAX_SIZE];
};

#define cdev_to_priv(c) container_of(c, struct mlxreg_led_data, led_cdev)

/**
 * struct mlxreg_led_priv_data - platform private data:
 *
 * @pdev: platform device;
 * @pdata: platform data;
 * @access_lock: mutex for attribute IO access;
 */
struct mlxreg_led_priv_data {
	struct platform_device *pdev;
	struct mlxreg_core_platform_data *pdata;
	struct mutex access_lock; /* protect IO operations */
};

static int
mlxreg_led_store_hw(struct mlxreg_led_data *led_data, u8 vset)
{
	struct mlxreg_led_priv_data *priv = led_data->data_parent;
	struct mlxreg_core_platform_data *led_pdata = priv->pdata;
	struct mlxreg_core_data *data = led_data->data;
	u32 regval;
	u32 nib;
	int ret;

	/*
	 * Each LED is controlled through low or high nibble of the relevant
	 * register byte. Register offset is specified by off parameter.
	 * Parameter vset provides color code: 0x0 for off, 0x5 for solid red,
	 * 0x6 for 3Hz blink red, 0xd for solid green, 0xe for 3Hz blink
	 * green.
	 * Parameter mask specifies which nibble is used for specific LED: mask
	 * 0xf0 - lower nibble is to be used (bits from 0 to 3), mask 0x0f -
	 * higher nibble (bits from 4 to 7).
	 */
	mutex_lock(&priv->access_lock);

	ret = regmap_read(led_pdata->regmap, data->reg, &regval);
	if (ret)
		goto access_error;

	nib = (ror32(data->mask, data->bit) == 0xf0) ? rol32(vset, data->bit) :
	      rol32(vset, data->bit + 4);
	regval = (regval & data->mask) | nib;

	ret = regmap_write(led_pdata->regmap, data->reg, regval);

access_error:
	mutex_unlock(&priv->access_lock);

	return ret;
}

static enum led_brightness
mlxreg_led_get_hw(struct mlxreg_led_data *led_data)
{
	struct mlxreg_led_priv_data *priv = led_data->data_parent;
	struct mlxreg_core_platform_data *led_pdata = priv->pdata;
	struct mlxreg_core_data *data = led_data->data;
	u32 regval;
	int err;

	/*
	 * Each LED is controlled through low or high nibble of the relevant
	 * register byte. Register offset is specified by off parameter.
	 * Parameter vset provides color code: 0x0 for off, 0x5 for solid red,
	 * 0x6 for 3Hz blink red, 0xd for solid green, 0xe for 3Hz blink
	 * green.
	 * Parameter mask specifies which nibble is used for specific LED: mask
	 * 0xf0 - lower nibble is to be used (bits from 0 to 3), mask 0x0f -
	 * higher nibble (bits from 4 to 7).
	 */
	err = regmap_read(led_pdata->regmap, data->reg, &regval);
	if (err < 0) {
		dev_warn(led_data->led_cdev.dev, "Failed to get current brightness, error: %d\n",
			 err);
		/* Assume the LED is OFF */
		return LED_OFF;
	}

	regval = regval & ~data->mask;
	regval = (ror32(data->mask, data->bit) == 0xf0) ? ror32(regval,

Annotation

Implementation Notes