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 resource
*mem
;
401 * The maximum LED address must be known in sun50i_a100_ledc_resume() before
402 * class device registration, so parse and validate the subnodes up front.
404 device_for_each_child_node_scoped(dev
, child
) {
407 ret
= fwnode_property_read_u32(child
, "reg", &addr
);
408 if (ret
|| addr
>= LEDC_MAX_LEDS
)
409 return dev_err_probe(dev
, -EINVAL
, "'reg' must be between 0 and %d\n",
412 ret
= fwnode_property_read_u32(child
, "color", &color
);
413 if (ret
|| color
!= LED_COLOR_ID_RGB
)
414 return dev_err_probe(dev
, -EINVAL
, "'color' must be LED_COLOR_ID_RGB\n");
416 max_addr
= max(max_addr
, addr
);
423 priv
= devm_kzalloc(dev
, struct_size(priv
, leds
, num_leds
), GFP_KERNEL
);
428 priv
->max_addr
= max_addr
;
429 priv
->num_leds
= num_leds
;
430 spin_lock_init(&priv
->lock
);
431 dev_set_drvdata(dev
, priv
);
433 ret
= sun50i_a100_ledc_parse_format(dev
, priv
);
437 ret
= sun50i_a100_ledc_parse_timing(dev
, priv
);
441 priv
->base
= devm_platform_get_and_ioremap_resource(pdev
, 0, &mem
);
442 if (IS_ERR(priv
->base
))
443 return PTR_ERR(priv
->base
);
445 priv
->bus_clk
= devm_clk_get(dev
, "bus");
446 if (IS_ERR(priv
->bus_clk
))
447 return PTR_ERR(priv
->bus_clk
);
449 priv
->mod_clk
= devm_clk_get(dev
, "mod");
450 if (IS_ERR(priv
->mod_clk
))
451 return PTR_ERR(priv
->mod_clk
);
453 priv
->reset
= devm_reset_control_get_exclusive(dev
, NULL
);
454 if (IS_ERR(priv
->reset
))
455 return PTR_ERR(priv
->reset
);
457 priv
->dma_chan
= dma_request_chan(dev
, "tx");
458 if (IS_ERR(priv
->dma_chan
)) {
459 if (PTR_ERR(priv
->dma_chan
) != -ENODEV
)
460 return PTR_ERR(priv
->dma_chan
);
462 priv
->dma_chan
= NULL
;
464 priv
->buffer
= devm_kzalloc(dev
, LEDS_TO_BYTES(LEDC_MAX_LEDS
), GFP_KERNEL
);
468 ret
= devm_add_action_or_reset(dev
, sun50i_a100_ledc_dma_cleanup
, priv
);
472 dma_cfg
.dst_addr
= mem
->start
+ LEDC_DATA_REG
;
473 dma_cfg
.dst_addr_width
= DMA_SLAVE_BUSWIDTH_4_BYTES
;
474 dma_cfg
.dst_maxburst
= LEDC_FIFO_DEPTH
/ 2;
476 ret
= dmaengine_slave_config(priv
->dma_chan
, &dma_cfg
);
480 priv
->buffer
= dmam_alloc_attrs(dmaengine_get_dma_device(priv
->dma_chan
),
481 LEDS_TO_BYTES(LEDC_MAX_LEDS
), &priv
->dma_handle
,
482 GFP_KERNEL
, DMA_ATTR_WRITE_COMBINE
);
487 irq
= platform_get_irq(pdev
, 0);
491 ret
= devm_request_irq(dev
, irq
, sun50i_a100_ledc_irq
, 0, dev_name(dev
), priv
);
495 ret
= sun50i_a100_ledc_resume(dev
);
500 device_for_each_child_node_scoped(dev
, child
) {
501 struct led_classdev
*cdev
;
503 /* The node was already validated above. */
504 fwnode_property_read_u32(child
, "reg", &led
->addr
);
506 led
->subled_info
[0].color_index
= LED_COLOR_ID_RED
;
507 led
->subled_info
[0].channel
= 0;
508 led
->subled_info
[1].color_index
= LED_COLOR_ID_GREEN
;
509 led
->subled_info
[1].channel
= 1;
510 led
->subled_info
[2].color_index
= LED_COLOR_ID_BLUE
;
511 led
->subled_info
[2].channel
= 2;
513 led
->mc_cdev
.num_colors
= ARRAY_SIZE(led
->subled_info
);
514 led
->mc_cdev
.subled_info
= led
->subled_info
;
516 cdev
= &led
->mc_cdev
.led_cdev
;
517 cdev
->max_brightness
= U8_MAX
;
518 cdev
->brightness_set
= sun50i_a100_ledc_brightness_set
;
520 init_data
.fwnode
= child
;
522 ret
= led_classdev_multicolor_register_ext(dev
, &led
->mc_cdev
, &init_data
);
524 dev_err_probe(dev
, ret
, "Failed to register multicolor LED %u", led
->addr
);
525 while (led
-- > priv
->leds
)
526 led_classdev_multicolor_unregister(&led
->mc_cdev
);
527 sun50i_a100_ledc_suspend(&pdev
->dev
);
535 dev_info(dev
, "Registered %u LEDs\n", num_leds
);
540 static void sun50i_a100_ledc_remove(struct platform_device
*pdev
)
542 struct sun50i_a100_ledc
*priv
= platform_get_drvdata(pdev
);
544 for (u32 i
= 0; i
< priv
->num_leds
; i
++)
545 led_classdev_multicolor_unregister(&priv
->leds
[i
].mc_cdev
);
546 sun50i_a100_ledc_suspend(&pdev
->dev
);
549 static const struct of_device_id sun50i_a100_ledc_of_match
[] = {
550 { .compatible
= "allwinner,sun50i-a100-ledc" },
553 MODULE_DEVICE_TABLE(of
, sun50i_a100_ledc_of_match
);
555 static DEFINE_SIMPLE_DEV_PM_OPS(sun50i_a100_ledc_pm
,
556 sun50i_a100_ledc_suspend
,
557 sun50i_a100_ledc_resume
);
559 static struct platform_driver sun50i_a100_ledc_driver
= {
560 .probe
= sun50i_a100_ledc_probe
,
561 .remove
= sun50i_a100_ledc_remove
,
562 .shutdown
= sun50i_a100_ledc_remove
,
564 .name
= "sun50i-a100-ledc",
565 .of_match_table
= sun50i_a100_ledc_of_match
,
566 .pm
= pm_ptr(&sun50i_a100_ledc_pm
),
569 module_platform_driver(sun50i_a100_ledc_driver
);
571 MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");
572 MODULE_DESCRIPTION("Allwinner A100 LED controller driver");
573 MODULE_LICENSE("GPL");