1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2021-2023 Samuel Holland <samuel@sholland.org>
5 * Partly based on drivers/leds/leds-turris-omnia.c, which is:
6 * Copyright (c) 2020 by Marek BehĂșn <kabel@kernel.org>
9 #include <linux/bitfield.h>
10 #include <linux/clk.h>
11 #include <linux/delay.h>
12 #include <linux/dma-mapping.h>
13 #include <linux/dmaengine.h>
14 #include <linux/interrupt.h>
16 #include <linux/led-class-multicolor.h>
17 #include <linux/leds.h>
18 #include <linux/mod_devicetable.h>
19 #include <linux/module.h>
20 #include <linux/platform_device.h>
22 #include <linux/property.h>
23 #include <linux/reset.h>
24 #include <linux/spinlock.h>
26 #define LEDC_CTRL_REG 0x0000
27 #define LEDC_CTRL_REG_DATA_LENGTH GENMASK(28, 16)
28 #define LEDC_CTRL_REG_RGB_MODE GENMASK(8, 6)
29 #define LEDC_CTRL_REG_LEDC_EN BIT(0)
30 #define LEDC_T01_TIMING_CTRL_REG 0x0004
31 #define LEDC_T01_TIMING_CTRL_REG_T1H GENMASK(26, 21)
32 #define LEDC_T01_TIMING_CTRL_REG_T1L GENMASK(20, 16)
33 #define LEDC_T01_TIMING_CTRL_REG_T0H GENMASK(10, 6)
34 #define LEDC_T01_TIMING_CTRL_REG_T0L GENMASK(5, 0)
35 #define LEDC_RESET_TIMING_CTRL_REG 0x000c
36 #define LEDC_RESET_TIMING_CTRL_REG_TR GENMASK(28, 16)
37 #define LEDC_RESET_TIMING_CTRL_REG_LED_NUM GENMASK(9, 0)
38 #define LEDC_DATA_REG 0x0014
39 #define LEDC_DMA_CTRL_REG 0x0018
40 #define LEDC_DMA_CTRL_REG_DMA_EN BIT(5)
41 #define LEDC_DMA_CTRL_REG_FIFO_TRIG_LEVEL GENMASK(4, 0)
42 #define LEDC_INT_CTRL_REG 0x001c
43 #define LEDC_INT_CTRL_REG_GLOBAL_INT_EN BIT(5)
44 #define LEDC_INT_CTRL_REG_FIFO_CPUREQ_INT_EN BIT(1)
45 #define LEDC_INT_CTRL_REG_TRANS_FINISH_INT_EN BIT(0)
46 #define LEDC_INT_STS_REG 0x0020
47 #define LEDC_INT_STS_REG_FIFO_WLW GENMASK(15, 10)
48 #define LEDC_INT_STS_REG_FIFO_CPUREQ_INT BIT(1)
49 #define LEDC_INT_STS_REG_TRANS_FINISH_INT BIT(0)
51 #define LEDC_FIFO_DEPTH 32U
52 #define LEDC_MAX_LEDS 1024
53 #define LEDC_CHANNELS_PER_LED 3 /* RGB */
55 #define LEDS_TO_BYTES(n) ((n) * sizeof(u32))
57 struct sun50i_a100_ledc_led
{
58 struct led_classdev_mc mc_cdev
;
59 struct mc_subled subled_info
[LEDC_CHANNELS_PER_LED
];
63 #define to_ledc_led(mc) container_of(mc, struct sun50i_a100_ledc_led, mc_cdev)
65 struct sun50i_a100_ledc_timing
{
73 struct sun50i_a100_ledc
{
78 struct reset_control
*reset
;
81 struct dma_chan
*dma_chan
;
82 dma_addr_t dma_handle
;
83 unsigned int pio_length
;
84 unsigned int pio_offset
;
87 unsigned int next_length
;
91 struct sun50i_a100_ledc_timing timing
;
95 struct sun50i_a100_ledc_led leds
[] __counted_by(num_leds
);
98 static int sun50i_a100_ledc_dma_xfer(struct sun50i_a100_ledc
*priv
, unsigned int length
)
100 struct dma_async_tx_descriptor
*desc
;
103 desc
= dmaengine_prep_slave_single(priv
->dma_chan
, priv
->dma_handle
,
104 LEDS_TO_BYTES(length
), DMA_MEM_TO_DEV
, 0);
108 cookie
= dmaengine_submit(desc
);
109 if (dma_submit_error(cookie
))
112 dma_async_issue_pending(priv
->dma_chan
);
117 static void sun50i_a100_ledc_pio_xfer(struct sun50i_a100_ledc
*priv
, unsigned int fifo_used
)
119 unsigned int burst
, length
, offset
;
122 length
= priv
->pio_length
;
123 offset
= priv
->pio_offset
;
124 burst
= min(length
, LEDC_FIFO_DEPTH
- fifo_used
);
126 iowrite32_rep(priv
->base
+ LEDC_DATA_REG
, priv
->buffer
+ offset
, burst
);
128 if (burst
< length
) {
129 priv
->pio_length
= length
- burst
;
130 priv
->pio_offset
= offset
+ burst
;
133 control
= readl(priv
->base
+ LEDC_INT_CTRL_REG
);
134 control
|= LEDC_INT_CTRL_REG_FIFO_CPUREQ_INT_EN
;
135 writel(control
, priv
->base
+ LEDC_INT_CTRL_REG
);
138 /* Disable the request IRQ once all data is written. */
139 control
= readl(priv
->base
+ LEDC_INT_CTRL_REG
);
140 control
&= ~LEDC_INT_CTRL_REG_FIFO_CPUREQ_INT_EN
;
141 writel(control
, priv
->base
+ LEDC_INT_CTRL_REG
);
145 static void sun50i_a100_ledc_start_xfer(struct sun50i_a100_ledc
*priv
, unsigned int length
)
147 bool use_dma
= false;
150 if (priv
->dma_chan
&& length
> LEDC_FIFO_DEPTH
) {
153 ret
= sun50i_a100_ledc_dma_xfer(priv
, length
);
155 dev_warn(priv
->dev
, "Failed to set up DMA (%d), using PIO\n", ret
);
160 /* The DMA trigger level must be at least the burst length. */
161 control
= FIELD_PREP(LEDC_DMA_CTRL_REG_DMA_EN
, use_dma
) |
162 FIELD_PREP_CONST(LEDC_DMA_CTRL_REG_FIFO_TRIG_LEVEL
, LEDC_FIFO_DEPTH
/ 2);
163 writel(control
, priv
->base
+ LEDC_DMA_CTRL_REG
);
165 control
= readl(priv
->base
+ LEDC_CTRL_REG
);
166 control
&= ~LEDC_CTRL_REG_DATA_LENGTH
;
167 control
|= FIELD_PREP(LEDC_CTRL_REG_DATA_LENGTH
, length
) | LEDC_CTRL_REG_LEDC_EN
;
168 writel(control
, priv
->base
+ LEDC_CTRL_REG
);
171 /* The FIFO is empty when starting a new transfer. */
172 unsigned int fifo_used
= 0;
174 priv
->pio_length
= length
;
175 priv
->pio_offset
= 0;
177 sun50i_a100_ledc_pio_xfer(priv
, fifo_used
);
181 static irqreturn_t
sun50i_a100_ledc_irq(int irq
, void *data
)
183 struct sun50i_a100_ledc
*priv
= data
;
186 status
= readl(priv
->base
+ LEDC_INT_STS_REG
);
188 if (status
& LEDC_INT_STS_REG_TRANS_FINISH_INT
) {
189 unsigned int next_length
;
191 spin_lock(&priv
->lock
);
193 /* If another transfer is queued, dequeue and start it. */
194 next_length
= priv
->next_length
;
196 priv
->next_length
= 0;
198 priv
->xfer_active
= false;
200 spin_unlock(&priv
->lock
);
203 sun50i_a100_ledc_start_xfer(priv
, next_length
);
204 } else if (status
& LEDC_INT_STS_REG_FIFO_CPUREQ_INT
) {
205 /* Continue the current transfer. */
206 sun50i_a100_ledc_pio_xfer(priv
, FIELD_GET(LEDC_INT_STS_REG_FIFO_WLW
, status
));
209 /* Clear the W1C status bits. */
210 writel(status
, priv
->base
+ LEDC_INT_STS_REG
);
215 static void sun50i_a100_ledc_brightness_set(struct led_classdev
*cdev
,
216 enum led_brightness brightness
)
218 struct sun50i_a100_ledc
*priv
= dev_get_drvdata(cdev
->dev
->parent
);
219 struct led_classdev_mc
*mc_cdev
= lcdev_to_mccdev(cdev
);
220 struct sun50i_a100_ledc_led
*led
= to_ledc_led(mc_cdev
);
221 unsigned int next_length
;
225 led_mc_calc_color_components(mc_cdev
, brightness
);
227 priv
->buffer
[led
->addr
] = led
->subled_info
[0].brightness
<< 16 |
228 led
->subled_info
[1].brightness
<< 8 |
229 led
->subled_info
[2].brightness
;
231 spin_lock_irqsave(&priv
->lock
, flags
);
233 /* Start, enqueue, or extend an enqueued transfer, as appropriate. */
234 next_length
= max(priv
->next_length
, led
->addr
+ 1);
235 xfer_active
= priv
->xfer_active
;
237 priv
->next_length
= next_length
;
239 priv
->xfer_active
= true;
241 spin_unlock_irqrestore(&priv
->lock
, flags
);
244 sun50i_a100_ledc_start_xfer(priv
, next_length
);
247 static const char *const sun50i_a100_ledc_formats
[] = {
248 "rgb", "rbg", "grb", "gbr", "brg", "bgr",
251 static int sun50i_a100_ledc_parse_format(struct device
*dev
,
252 struct sun50i_a100_ledc
*priv
)
254 const char *format
= "grb";
257 device_property_read_string(dev
, "allwinner,pixel-format", &format
);
259 i
= match_string(sun50i_a100_ledc_formats
, ARRAY_SIZE(sun50i_a100_ledc_formats
), format
);
261 return dev_err_probe(dev
, i
, "Bad pixel format '%s'\n", format
);
267 static void sun50i_a100_ledc_set_format(struct sun50i_a100_ledc
*priv
)
271 control
= readl(priv
->base
+ LEDC_CTRL_REG
);
272 control
&= ~LEDC_CTRL_REG_RGB_MODE
;
273 control
|= FIELD_PREP(LEDC_CTRL_REG_RGB_MODE
, priv
->format
);
274 writel(control
, priv
->base
+ LEDC_CTRL_REG
);
277 static const struct sun50i_a100_ledc_timing sun50i_a100_ledc_default_timing
= {
285 static int sun50i_a100_ledc_parse_timing(struct device
*dev
,
286 struct sun50i_a100_ledc
*priv
)
288 struct sun50i_a100_ledc_timing
*timing
= &priv
->timing
;
290 *timing
= sun50i_a100_ledc_default_timing
;
292 device_property_read_u32(dev
, "allwinner,t0h-ns", &timing
->t0h_ns
);
293 device_property_read_u32(dev
, "allwinner,t0l-ns", &timing
->t0l_ns
);
294 device_property_read_u32(dev
, "allwinner,t1h-ns", &timing
->t1h_ns
);
295 device_property_read_u32(dev
, "allwinner,t1l-ns", &timing
->t1l_ns
);
296 device_property_read_u32(dev
, "allwinner,treset-ns", &timing
->treset_ns
);
301 static void sun50i_a100_ledc_set_timing(struct sun50i_a100_ledc
*priv
)
303 const struct sun50i_a100_ledc_timing
*timing
= &priv
->timing
;
304 unsigned long mod_freq
= clk_get_rate(priv
->mod_clk
);
311 cycle_ns
= NSEC_PER_SEC
/ mod_freq
;
312 control
= FIELD_PREP(LEDC_T01_TIMING_CTRL_REG_T1H
, timing
->t1h_ns
/ cycle_ns
) |
313 FIELD_PREP(LEDC_T01_TIMING_CTRL_REG_T1L
, timing
->t1l_ns
/ cycle_ns
) |
314 FIELD_PREP(LEDC_T01_TIMING_CTRL_REG_T0H
, timing
->t0h_ns
/ cycle_ns
) |
315 FIELD_PREP(LEDC_T01_TIMING_CTRL_REG_T0L
, timing
->t0l_ns
/ cycle_ns
);
316 writel(control
, priv
->base
+ LEDC_T01_TIMING_CTRL_REG
);
318 control
= FIELD_PREP(LEDC_RESET_TIMING_CTRL_REG_TR
, timing
->treset_ns
/ cycle_ns
) |
319 FIELD_PREP(LEDC_RESET_TIMING_CTRL_REG_LED_NUM
, priv
->max_addr
);
320 writel(control
, priv
->base
+ LEDC_RESET_TIMING_CTRL_REG
);
323 static int sun50i_a100_ledc_resume(struct device
*dev
)
325 struct sun50i_a100_ledc
*priv
= dev_get_drvdata(dev
);
328 ret
= reset_control_deassert(priv
->reset
);
332 ret
= clk_prepare_enable(priv
->bus_clk
);
334 goto err_assert_reset
;
336 ret
= clk_prepare_enable(priv
->mod_clk
);
338 goto err_disable_bus_clk
;
340 sun50i_a100_ledc_set_format(priv
);
341 sun50i_a100_ledc_set_timing(priv
);
343 writel(LEDC_INT_CTRL_REG_GLOBAL_INT_EN
| LEDC_INT_CTRL_REG_TRANS_FINISH_INT_EN
,
344 priv
->base
+ LEDC_INT_CTRL_REG
);
349 clk_disable_unprepare(priv
->bus_clk
);
351 reset_control_assert(priv
->reset
);
356 static int sun50i_a100_ledc_suspend(struct device
*dev
)
358 struct sun50i_a100_ledc
*priv
= dev_get_drvdata(dev
);
360 /* Wait for all transfers to complete. */
365 spin_lock_irqsave(&priv
->lock
, flags
);
366 xfer_active
= priv
->xfer_active
;
367 spin_unlock_irqrestore(&priv
->lock
, flags
);
371 usleep_range(1000, 1100);
374 clk_disable_unprepare(priv
->mod_clk
);
375 clk_disable_unprepare(priv
->bus_clk
);
376 reset_control_assert(priv
->reset
);
381 static void sun50i_a100_ledc_dma_cleanup(void *data
)
383 struct sun50i_a100_ledc
*priv
= data
;
385 dma_release_channel(priv
->dma_chan
);
388 static int sun50i_a100_ledc_probe(struct platform_device
*pdev
)
390 struct dma_slave_config dma_cfg
= {};
391 struct led_init_data init_data
= {};
392 struct sun50i_a100_ledc_led
*led
;
393 struct device
*dev
= &pdev
->dev
;
394 struct sun50i_a100_ledc
*priv
;
395 struct fwnode_handle
*child
;
396 struct resource
*mem
;
402 * The maximum LED address must be known in sun50i_a100_ledc_resume() before
403 * class device registration, so parse and validate the subnodes up front.
405 device_for_each_child_node(dev
, child
) {
408 ret
= fwnode_property_read_u32(child
, "reg", &addr
);
409 if (ret
|| addr
>= LEDC_MAX_LEDS
) {
410 fwnode_handle_put(child
);
411 return dev_err_probe(dev
, -EINVAL
, "'reg' must be between 0 and %d\n",
415 ret
= fwnode_property_read_u32(child
, "color", &color
);
416 if (ret
|| color
!= LED_COLOR_ID_RGB
) {
417 fwnode_handle_put(child
);
418 return dev_err_probe(dev
, -EINVAL
, "'color' must be LED_COLOR_ID_RGB\n");
421 max_addr
= max(max_addr
, addr
);
428 priv
= devm_kzalloc(dev
, struct_size(priv
, leds
, num_leds
), GFP_KERNEL
);
433 priv
->max_addr
= max_addr
;
434 priv
->num_leds
= num_leds
;
435 spin_lock_init(&priv
->lock
);
436 dev_set_drvdata(dev
, priv
);
438 ret
= sun50i_a100_ledc_parse_format(dev
, priv
);
442 ret
= sun50i_a100_ledc_parse_timing(dev
, priv
);
446 priv
->base
= devm_platform_get_and_ioremap_resource(pdev
, 0, &mem
);
447 if (IS_ERR(priv
->base
))
448 return PTR_ERR(priv
->base
);
450 priv
->bus_clk
= devm_clk_get(dev
, "bus");
451 if (IS_ERR(priv
->bus_clk
))
452 return PTR_ERR(priv
->bus_clk
);
454 priv
->mod_clk
= devm_clk_get(dev
, "mod");
455 if (IS_ERR(priv
->mod_clk
))
456 return PTR_ERR(priv
->mod_clk
);
458 priv
->reset
= devm_reset_control_get_exclusive(dev
, NULL
);
459 if (IS_ERR(priv
->reset
))
460 return PTR_ERR(priv
->reset
);
462 priv
->dma_chan
= dma_request_chan(dev
, "tx");
463 if (IS_ERR(priv
->dma_chan
)) {
464 if (PTR_ERR(priv
->dma_chan
) != -ENODEV
)
465 return PTR_ERR(priv
->dma_chan
);
467 priv
->dma_chan
= NULL
;
469 priv
->buffer
= devm_kzalloc(dev
, LEDS_TO_BYTES(LEDC_MAX_LEDS
), GFP_KERNEL
);
473 ret
= devm_add_action_or_reset(dev
, sun50i_a100_ledc_dma_cleanup
, priv
);
477 dma_cfg
.dst_addr
= mem
->start
+ LEDC_DATA_REG
;
478 dma_cfg
.dst_addr_width
= DMA_SLAVE_BUSWIDTH_4_BYTES
;
479 dma_cfg
.dst_maxburst
= LEDC_FIFO_DEPTH
/ 2;
481 ret
= dmaengine_slave_config(priv
->dma_chan
, &dma_cfg
);
485 priv
->buffer
= dmam_alloc_attrs(dmaengine_get_dma_device(priv
->dma_chan
),
486 LEDS_TO_BYTES(LEDC_MAX_LEDS
), &priv
->dma_handle
,
487 GFP_KERNEL
, DMA_ATTR_WRITE_COMBINE
);
492 irq
= platform_get_irq(pdev
, 0);
496 ret
= devm_request_irq(dev
, irq
, sun50i_a100_ledc_irq
, 0, dev_name(dev
), priv
);
500 ret
= sun50i_a100_ledc_resume(dev
);
505 device_for_each_child_node(dev
, child
) {
506 struct led_classdev
*cdev
;
508 /* The node was already validated above. */
509 fwnode_property_read_u32(child
, "reg", &led
->addr
);
511 led
->subled_info
[0].color_index
= LED_COLOR_ID_RED
;
512 led
->subled_info
[0].channel
= 0;
513 led
->subled_info
[1].color_index
= LED_COLOR_ID_GREEN
;
514 led
->subled_info
[1].channel
= 1;
515 led
->subled_info
[2].color_index
= LED_COLOR_ID_BLUE
;
516 led
->subled_info
[2].channel
= 2;
518 led
->mc_cdev
.num_colors
= ARRAY_SIZE(led
->subled_info
);
519 led
->mc_cdev
.subled_info
= led
->subled_info
;
521 cdev
= &led
->mc_cdev
.led_cdev
;
522 cdev
->max_brightness
= U8_MAX
;
523 cdev
->brightness_set
= sun50i_a100_ledc_brightness_set
;
525 init_data
.fwnode
= child
;
527 ret
= led_classdev_multicolor_register_ext(dev
, &led
->mc_cdev
, &init_data
);
529 dev_err_probe(dev
, ret
, "Failed to register multicolor LED %u", led
->addr
);
536 dev_info(dev
, "Registered %u LEDs\n", num_leds
);
541 fwnode_handle_put(child
);
542 while (led
-- > priv
->leds
)
543 led_classdev_multicolor_unregister(&led
->mc_cdev
);
544 sun50i_a100_ledc_suspend(&pdev
->dev
);
549 static void sun50i_a100_ledc_remove(struct platform_device
*pdev
)
551 struct sun50i_a100_ledc
*priv
= platform_get_drvdata(pdev
);
553 for (u32 i
= 0; i
< priv
->num_leds
; i
++)
554 led_classdev_multicolor_unregister(&priv
->leds
[i
].mc_cdev
);
555 sun50i_a100_ledc_suspend(&pdev
->dev
);
558 static const struct of_device_id sun50i_a100_ledc_of_match
[] = {
559 { .compatible
= "allwinner,sun50i-a100-ledc" },
562 MODULE_DEVICE_TABLE(of
, sun50i_a100_ledc_of_match
);
564 static DEFINE_SIMPLE_DEV_PM_OPS(sun50i_a100_ledc_pm
,
565 sun50i_a100_ledc_suspend
,
566 sun50i_a100_ledc_resume
);
568 static struct platform_driver sun50i_a100_ledc_driver
= {
569 .probe
= sun50i_a100_ledc_probe
,
570 .remove_new
= sun50i_a100_ledc_remove
,
571 .shutdown
= sun50i_a100_ledc_remove
,
573 .name
= "sun50i-a100-ledc",
574 .of_match_table
= sun50i_a100_ledc_of_match
,
575 .pm
= pm_ptr(&sun50i_a100_ledc_pm
),
578 module_platform_driver(sun50i_a100_ledc_driver
);
580 MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");
581 MODULE_DESCRIPTION("Allwinner A100 LED controller driver");
582 MODULE_LICENSE("GPL");