drivers/leds/leds-bcm6358.c

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

File Facts

System
Linux kernel
Corpus path
drivers/leds/leds-bcm6358.c
Extension
.c
Size
5246 bytes
Lines
227
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 bcm6358_led {
	struct led_classdev cdev;
	void __iomem *mem;
	spinlock_t *lock;
	unsigned long pin;
	bool active_low;
};

static void bcm6358_led_write(void __iomem *reg, unsigned long data)
{
#ifdef CONFIG_CPU_BIG_ENDIAN
	iowrite32be(data, reg);
#else
	writel(data, reg);
#endif
}

static unsigned long bcm6358_led_read(void __iomem *reg)
{
#ifdef CONFIG_CPU_BIG_ENDIAN
	return ioread32be(reg);
#else
	return readl(reg);
#endif
}

static unsigned long bcm6358_led_busy(void __iomem *mem)
{
	unsigned long val;

	while ((val = bcm6358_led_read(mem + BCM6358_REG_CTRL)) &
		BCM6358_SLED_BUSY)
		udelay(BCM6358_SLED_WAIT);

	return val;
}

static void bcm6358_led_set(struct led_classdev *led_cdev,
			    enum led_brightness value)
{
	struct bcm6358_led *led =
		container_of(led_cdev, struct bcm6358_led, cdev);
	unsigned long flags, val;

	spin_lock_irqsave(led->lock, flags);
	bcm6358_led_busy(led->mem);
	val = bcm6358_led_read(led->mem + BCM6358_REG_MODE);
	if ((led->active_low && value == LED_OFF) ||
	    (!led->active_low && value != LED_OFF))
		val |= BIT(led->pin);
	else
		val &= ~(BIT(led->pin));
	bcm6358_led_write(led->mem + BCM6358_REG_MODE, val);
	spin_unlock_irqrestore(led->lock, flags);
}

static int bcm6358_led(struct device *dev, struct device_node *nc, u32 reg,
		       void __iomem *mem, spinlock_t *lock)
{
	struct led_init_data init_data = {};
	struct bcm6358_led *led;
	enum led_default_state state;
	unsigned long val;
	int rc;

	led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
	if (!led)
		return -ENOMEM;

	led->pin = reg;
	led->mem = mem;
	led->lock = lock;

	if (of_property_read_bool(nc, "active-low"))
		led->active_low = true;

	init_data.fwnode = of_fwnode_handle(nc);

	state = led_init_default_state_get(init_data.fwnode);
	switch (state) {
	case LEDS_DEFSTATE_ON:
		led->cdev.brightness = LED_FULL;
		break;
	case LEDS_DEFSTATE_KEEP:
		val = bcm6358_led_read(led->mem + BCM6358_REG_MODE);
		val &= BIT(led->pin);
		if ((led->active_low && !val) || (!led->active_low && val))
			led->cdev.brightness = LED_FULL;
		else
			led->cdev.brightness = LED_OFF;

Annotation

Implementation Notes