drivers/leds/blink/leds-bcm63138.c

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

File Facts

System
Linux kernel
Corpus path
drivers/leds/blink/leds-bcm63138.c
Extension
.c
Size
8382 bytes
Lines
314
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 bcm63138_leds {
	struct device *dev;
	void __iomem *base;
	spinlock_t lock;
};

struct bcm63138_led {
	struct bcm63138_leds *leds;
	struct led_classdev cdev;
	u32 pin;
	bool active_low;
};

/*
 * I/O access
 */

static void bcm63138_leds_write(struct bcm63138_leds *leds, unsigned int reg,
				u32 data)
{
	writel(data, leds->base + reg);
}

static unsigned long bcm63138_leds_read(struct bcm63138_leds *leds,
					unsigned int reg)
{
	return readl(leds->base + reg);
}

static void bcm63138_leds_update_bits(struct bcm63138_leds *leds,
				      unsigned int reg, u32 mask, u32 val)
{
	WARN_ON(val & ~mask);

	bcm63138_leds_write(leds, reg, (bcm63138_leds_read(leds, reg) & ~mask) | (val & mask));
}

/*
 * Helpers
 */

static void bcm63138_leds_set_flash_rate(struct bcm63138_leds *leds,
					 struct bcm63138_led *led,
					 u8 value)
{
	int reg_offset = (led->pin >> fls((BCM63138_LEDS_PER_REG - 1))) * 4;
	int shift = (led->pin & (BCM63138_LEDS_PER_REG - 1)) * BCM63138_LED_BITS;

	bcm63138_leds_update_bits(leds, BCM63138_FLASH_RATE_CTRL1 + reg_offset,
				  BCM63138_LED_MASK << shift, value << shift);
}

static void bcm63138_leds_set_bright(struct bcm63138_leds *leds,
				     struct bcm63138_led *led,
				     u8 value)
{
	int reg_offset = (led->pin >> fls((BCM63138_LEDS_PER_REG - 1))) * 4;
	int shift = (led->pin & (BCM63138_LEDS_PER_REG - 1)) * BCM63138_LED_BITS;

	bcm63138_leds_update_bits(leds, BCM63138_BRIGHT_CTRL1 + reg_offset,
				  BCM63138_LED_MASK << shift, value << shift);
}

static void bcm63138_leds_enable_led(struct bcm63138_leds *leds,
				     struct bcm63138_led *led,
				     enum led_brightness value)
{
	u32 bit = BIT(led->pin);

	bcm63138_leds_update_bits(leds, BCM63138_SW_DATA, bit, value ? bit : 0);
}

/*
 * API callbacks
 */

static void bcm63138_leds_brightness_set(struct led_classdev *led_cdev,
					 enum led_brightness value)
{
	struct bcm63138_led *led = container_of(led_cdev, struct bcm63138_led, cdev);
	struct bcm63138_leds *leds = led->leds;

	guard(spinlock_irqsave)(&leds->lock);

	bcm63138_leds_enable_led(leds, led, value);
	if (!value)
		bcm63138_leds_set_flash_rate(leds, led, 0);
	else
		bcm63138_leds_set_bright(leds, led, value);
}

Annotation

Implementation Notes