drivers/leds/leds-sc27xx-bltc.c

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

File Facts

System
Linux kernel
Corpus path
drivers/leds/leds-sc27xx-bltc.c
Extension
.c
Size
9008 bytes
Lines
356
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 sc27xx_led {
	struct fwnode_handle *fwnode;
	struct led_classdev ldev;
	struct sc27xx_led_priv *priv;
	u8 line;
	bool active;
};

struct sc27xx_led_priv {
	struct sc27xx_led leds[SC27XX_LEDS_MAX];
	struct regmap *regmap;
	struct mutex lock;
	u32 base;
};

#define to_sc27xx_led(ldev) \
	container_of(ldev, struct sc27xx_led, ldev)

static int sc27xx_led_init(struct regmap *regmap)
{
	int err;

	err = regmap_update_bits(regmap, SC27XX_MODULE_EN0, SC27XX_BLTC_EN,
				 SC27XX_BLTC_EN);
	if (err)
		return err;

	err = regmap_update_bits(regmap, SC27XX_CLK_EN0, SC27XX_RTC_EN,
				 SC27XX_RTC_EN);
	if (err)
		return err;

	return regmap_update_bits(regmap, SC27XX_RGB_CTRL, SC27XX_RGB_PD, 0);
}

static u32 sc27xx_led_get_offset(struct sc27xx_led *leds)
{
	return leds->priv->base + SC27XX_LEDS_OFFSET * leds->line;
}

static int sc27xx_led_enable(struct sc27xx_led *leds, enum led_brightness value)
{
	u32 base = sc27xx_led_get_offset(leds);
	u32 ctrl_base = leds->priv->base + SC27XX_LEDS_CTRL;
	u8 ctrl_shift = SC27XX_CTRL_SHIFT * leds->line;
	struct regmap *regmap = leds->priv->regmap;
	int err;

	err = regmap_update_bits(regmap, base + SC27XX_LEDS_DUTY,
				 SC27XX_DUTY_MASK,
				 (value << SC27XX_DUTY_SHIFT) |
				 SC27XX_MOD_MASK);
	if (err)
		return err;

	return regmap_update_bits(regmap, ctrl_base,
			(SC27XX_LED_RUN | SC27XX_LED_TYPE) << ctrl_shift,
			(SC27XX_LED_RUN | SC27XX_LED_TYPE) << ctrl_shift);
}

static int sc27xx_led_disable(struct sc27xx_led *leds)
{
	struct regmap *regmap = leds->priv->regmap;
	u32 ctrl_base = leds->priv->base + SC27XX_LEDS_CTRL;
	u8 ctrl_shift = SC27XX_CTRL_SHIFT * leds->line;

	return regmap_update_bits(regmap, ctrl_base,
			(SC27XX_LED_RUN | SC27XX_LED_TYPE) << ctrl_shift, 0);
}

static int sc27xx_led_set(struct led_classdev *ldev, enum led_brightness value)
{
	struct sc27xx_led *leds = to_sc27xx_led(ldev);
	int err;

	mutex_lock(&leds->priv->lock);

	if (value == LED_OFF)
		err = sc27xx_led_disable(leds);
	else
		err = sc27xx_led_enable(leds, value);

	mutex_unlock(&leds->priv->lock);

	return err;
}

static void sc27xx_led_clamp_align_delta_t(u32 *delta_t)
{
	u32 v, offset, t = *delta_t;

Annotation

Implementation Notes