drivers/leds/leds-sun50i-a100.c
Source file repositories/reference/linux-study-clean/drivers/leds/leds-sun50i-a100.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/leds/leds-sun50i-a100.c- Extension
.c- Size
- 15742 bytes
- Lines
- 574
- 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.
- 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.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/bitfield.hlinux/clk.hlinux/delay.hlinux/dma-mapping.hlinux/dmaengine.hlinux/interrupt.hlinux/io.hlinux/led-class-multicolor.hlinux/leds.hlinux/mod_devicetable.hlinux/module.hlinux/platform_device.hlinux/pm.hlinux/property.hlinux/reset.hlinux/spinlock.h
Detected Declarations
struct sun50i_a100_ledc_ledstruct sun50i_a100_ledc_timingstruct sun50i_a100_ledcfunction sun50i_a100_ledc_dma_xferfunction sun50i_a100_ledc_pio_xferfunction sun50i_a100_ledc_start_xferfunction sun50i_a100_ledc_irqfunction sun50i_a100_ledc_brightness_setfunction sun50i_a100_ledc_parse_formatfunction sun50i_a100_ledc_set_formatfunction sun50i_a100_ledc_parse_timingfunction sun50i_a100_ledc_set_timingfunction sun50i_a100_ledc_resumefunction sun50i_a100_ledc_suspendfunction sun50i_a100_ledc_dma_cleanupfunction sun50i_a100_ledc_probefunction sun50i_a100_ledc_resumefunction sun50i_a100_ledc_remove
Annotated Snippet
struct sun50i_a100_ledc_led {
struct led_classdev_mc mc_cdev;
struct mc_subled subled_info[LEDC_CHANNELS_PER_LED];
u32 addr;
};
#define to_ledc_led(mc) container_of(mc, struct sun50i_a100_ledc_led, mc_cdev)
struct sun50i_a100_ledc_timing {
u32 t0h_ns;
u32 t0l_ns;
u32 t1h_ns;
u32 t1l_ns;
u32 treset_ns;
};
struct sun50i_a100_ledc {
struct device *dev;
void __iomem *base;
struct clk *bus_clk;
struct clk *mod_clk;
struct reset_control *reset;
u32 *buffer;
struct dma_chan *dma_chan;
dma_addr_t dma_handle;
unsigned int pio_length;
unsigned int pio_offset;
spinlock_t lock;
unsigned int next_length;
bool xfer_active;
u32 format;
struct sun50i_a100_ledc_timing timing;
u32 max_addr;
u32 num_leds;
struct sun50i_a100_ledc_led leds[] __counted_by(num_leds);
};
static int sun50i_a100_ledc_dma_xfer(struct sun50i_a100_ledc *priv, unsigned int length)
{
struct dma_async_tx_descriptor *desc;
dma_cookie_t cookie;
desc = dmaengine_prep_slave_single(priv->dma_chan, priv->dma_handle,
LEDS_TO_BYTES(length), DMA_MEM_TO_DEV, 0);
if (!desc)
return -ENOMEM;
cookie = dmaengine_submit(desc);
if (dma_submit_error(cookie))
return -EIO;
dma_async_issue_pending(priv->dma_chan);
return 0;
}
static void sun50i_a100_ledc_pio_xfer(struct sun50i_a100_ledc *priv, unsigned int fifo_used)
{
unsigned int burst, length, offset;
u32 control;
length = priv->pio_length;
offset = priv->pio_offset;
burst = min(length, LEDC_FIFO_DEPTH - fifo_used);
iowrite32_rep(priv->base + LEDC_DATA_REG, priv->buffer + offset, burst);
if (burst < length) {
priv->pio_length = length - burst;
priv->pio_offset = offset + burst;
if (!offset) {
control = readl(priv->base + LEDC_INT_CTRL_REG);
control |= LEDC_INT_CTRL_REG_FIFO_CPUREQ_INT_EN;
writel(control, priv->base + LEDC_INT_CTRL_REG);
}
} else {
/* Disable the request IRQ once all data is written. */
control = readl(priv->base + LEDC_INT_CTRL_REG);
control &= ~LEDC_INT_CTRL_REG_FIFO_CPUREQ_INT_EN;
writel(control, priv->base + LEDC_INT_CTRL_REG);
}
}
static void sun50i_a100_ledc_start_xfer(struct sun50i_a100_ledc *priv, unsigned int length)
{
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/clk.h`, `linux/delay.h`, `linux/dma-mapping.h`, `linux/dmaengine.h`, `linux/interrupt.h`, `linux/io.h`, `linux/led-class-multicolor.h`.
- Detected declarations: `struct sun50i_a100_ledc_led`, `struct sun50i_a100_ledc_timing`, `struct sun50i_a100_ledc`, `function sun50i_a100_ledc_dma_xfer`, `function sun50i_a100_ledc_pio_xfer`, `function sun50i_a100_ledc_start_xfer`, `function sun50i_a100_ledc_irq`, `function sun50i_a100_ledc_brightness_set`, `function sun50i_a100_ledc_parse_format`, `function sun50i_a100_ledc_set_format`.
- Atlas domain: Driver Families / drivers/leds.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.