1 #include <hal_gpio.h>
2 #include <hal_dma.h>
3 #include <hal_clk.h>
4 #include <hal_reset.h>
5 #include <hal_cache.h>
6 #include <sunxi_hal_ledc.h>
7
8 #ifdef LEDC_DEBUG
9 #define ledc_info(fmt, args...) printf("%s()%d - "fmt, __func__, __LINE__, ##args)
10 #else
11 #define ledc_info(fmt, args...)
12 #endif
13
14 static unsigned long base_addr = LEDC_BASE;
15 struct sunxi_dma_chan *dma_chan;
16
ledc_clk_init(void)17 static int ledc_clk_init(void)
18 {
19 hal_clk_type_t clk_type = HAL_SUNXI_CCU;
20 hal_clk_id_t mod_clk_id = CLK_LEDC;
21 hal_clk_id_t bus_clk_id = CLK_BUS_LEDC;
22 hal_clk_t mod_clk;
23 hal_clk_t bus_clk;
24
25 hal_reset_type_t reset_type = HAL_SUNXI_RESET;
26 hal_reset_id_t reset_id = RST_BUS_LEDC;
27 struct reset_control *reset;
28
29 reset = hal_reset_control_get(reset_type, reset_id);
30 if (hal_reset_control_deassert(reset))
31 {
32 ledc_info("ledc reset deassert failed!");
33 return -1;
34 }
35 hal_reset_control_put(reset);
36
37 mod_clk = hal_clock_get(clk_type, mod_clk_id);
38 if (hal_clock_enable(mod_clk))
39 {
40 ledc_info("ledc clk enable mclk failed!");
41 return -1;
42 }
43
44 bus_clk = hal_clock_get(clk_type, bus_clk_id);
45 if (hal_clock_enable(bus_clk))
46 {
47 ledc_info("ledc clk enable mclk failed!");
48 return -1;
49 }
50
51
52 return 0;
53 }
54
ledc_pinctrl_init(void)55 static int ledc_pinctrl_init(void)
56 {
57 if (hal_gpio_pinmux_set_function(LEDC_PIN, LEDC_PINMUXSEL))
58 {
59 ledc_info("ledc pin set default function failed!");
60 return -1;
61 }
62
63 return 0;
64 }
ledc_dump_reg(void)65 static void ledc_dump_reg(void)
66 {
67 ledc_info("LEDC_CTRL_REG = %0x\n", hal_readl(base_addr + LEDC_CTRL_REG));
68 ledc_info("LED_T01_TIMING_CTRL_REG = %0x\n", hal_readl(base_addr + LED_T01_TIMING_CTRL_REG));
69 ledc_info("LEDC_DATA_FINISH_CNT_REG = %0x\n", hal_readl(base_addr + LEDC_DATA_FINISH_CNT_REG));
70 ledc_info("LED_RST_TIMING_CTRL_REG = %0x\n", hal_readl(base_addr + LED_RST_TIMING_CTRL_REG));
71 ledc_info("LEDC_WAIT_TIME0_CTRL_REG = %0x\n", hal_readl(base_addr + LEDC_WAIT_TIME0_CTRL_REG));
72 ledc_info("LEDC_DATA_REG = %0x\n", hal_readl(base_addr + LEDC_DATA_REG));
73 ledc_info("LEDC_DMA_CTRL_REG = %0x\n", hal_readl(base_addr + LEDC_DMA_CTRL_REG));
74 ledc_info("LEDC_INTC_REG = %0x\n", hal_readl(base_addr + LEDC_INTC_REG));
75 ledc_info("LEDC_INTS_REG = %0x\n", hal_readl(base_addr + LEDC_INTS_REG));
76 ledc_info("LEDC_WAIT_TIME1_CTRL_REG = %0x\n", hal_readl(base_addr + LEDC_WAIT_TIME1_CTRL_REG));
77 ledc_info("LEDC_FIFO_DATA0_REG = %0x\n", hal_readl(base_addr + LEDC_FIFO_DATA0_REG));
78 }
79
ledc_set_reset_ns(unsigned int reset_ns)80 static void ledc_set_reset_ns(unsigned int reset_ns)
81 {
82 unsigned int n, reg_val;
83 unsigned int mask = 0x1FFF;
84 unsigned int min = LEDC_RESET_TIME_MIN_NS;
85 unsigned int max = LEDC_RESET_TIME_MAX_NS;
86
87 if (reset_ns < min || reset_ns > max) {
88 ledc_info("invalid parameter, reset_ns should be %u-%u!\n", min, max);
89 return;
90 }
91
92 n = (reset_ns - 42) / 42;
93 reg_val = hal_readl(base_addr + LED_RST_TIMING_CTRL_REG);
94 reg_val &= ~(mask << 16);
95 reg_val |= (n << 16);
96 hal_writel(reg_val, base_addr + LED_RST_TIMING_CTRL_REG);
97 }
98
ledc_set_t1h_ns(unsigned int t1h_ns)99 static void ledc_set_t1h_ns(unsigned int t1h_ns)
100 {
101 unsigned int n, reg_val;
102 unsigned int mask = 0x3F;
103 unsigned int shift = 21;
104 unsigned int min = LEDC_T1H_MIN_NS;
105 unsigned int max = LEDC_T1H_MAX_NS;
106
107 if (t1h_ns < min || t1h_ns > max) {
108 ledc_info("invalid parameter, t1h_ns should be %u-%u!\n", min, max);
109 return;
110 }
111
112 n = (t1h_ns - 42) / 42;
113 reg_val = hal_readl(base_addr + LED_T01_TIMING_CTRL_REG);
114 reg_val &= ~(mask << shift);
115 reg_val |= n << shift;
116 hal_writel(reg_val, base_addr + LED_T01_TIMING_CTRL_REG);
117 }
118
ledc_set_t1l_ns(unsigned int t1l_ns)119 static void ledc_set_t1l_ns(unsigned int t1l_ns)
120 {
121 unsigned int n, reg_val;
122 unsigned int mask = 0x1F;
123 unsigned int shift = 16;
124 unsigned int min = LEDC_T1L_MIN_NS;
125 unsigned int max = LEDC_T1L_MAX_NS;
126
127 if (t1l_ns < min || t1l_ns > max) {
128 ledc_info("invalid parameter, t1l_ns should be %u-%u!\n", min, max);
129 return;
130 }
131
132 n = (t1l_ns - 42) / 42;
133 reg_val = hal_readl(base_addr + LED_T01_TIMING_CTRL_REG);
134 reg_val &= ~(mask << shift);
135 reg_val |= n << shift;
136 hal_writel(reg_val, base_addr + LED_T01_TIMING_CTRL_REG);
137 }
138
ledc_set_t0h_ns(unsigned int t0h_ns)139 static void ledc_set_t0h_ns(unsigned int t0h_ns)
140 {
141 unsigned int n, reg_val;
142 unsigned int mask = 0x1F;
143 unsigned int shift = 6;
144 unsigned int min = LEDC_T0H_MIN_NS;
145 unsigned int max = LEDC_T0H_MAX_NS;
146
147 if (t0h_ns < min || t0h_ns > max) {
148 ledc_info("invalid parameter, t0h_ns should be %u-%u!\n", min, max);
149 return;
150 }
151
152 n = (t0h_ns - 42) / 42;
153 reg_val = hal_readl(base_addr + LED_T01_TIMING_CTRL_REG);
154 reg_val &= ~(mask << shift);
155 reg_val |= n << shift;
156 hal_writel(reg_val, base_addr + LED_T01_TIMING_CTRL_REG);
157 }
158
ledc_set_t0l_ns(unsigned int t0l_ns)159 static void ledc_set_t0l_ns(unsigned int t0l_ns)
160 {
161 unsigned int n, reg_val;
162 unsigned int min = LEDC_T0L_MIN_NS;
163 unsigned int max = LEDC_T0L_MAX_NS;
164
165 if (t0l_ns < min || t0l_ns > max) {
166 ledc_info("invalid parameter, t0l_ns should be %u-%u!\n", min, max);
167 return;
168 }
169
170 n = (t0l_ns - 42) / 42;
171 reg_val = hal_readl(base_addr + LED_T01_TIMING_CTRL_REG);
172 reg_val &= ~0x3F;
173 reg_val |= n;
174 hal_writel(reg_val, base_addr + LED_T01_TIMING_CTRL_REG);
175 }
176
ledc_set_wait_time0_ns(unsigned int wait_time0_ns)177 static void ledc_set_wait_time0_ns(unsigned int wait_time0_ns)
178 {
179 unsigned int n, reg_val;
180 unsigned int min = LEDC_WAIT_TIME0_MIN_NS;
181 unsigned int max = LEDC_WAIT_TIME0_MAX_NS;
182
183 if (wait_time0_ns < min || wait_time0_ns > max) {
184 ledc_info("invalid parameter, wait_time0_ns should be %u-%u!\n", min, max);
185 return;
186 }
187
188 n = (wait_time0_ns - 42) / 42;
189 reg_val = (1 << 8) | n;
190 hal_writel(reg_val, base_addr + LEDC_WAIT_TIME0_CTRL_REG);
191 }
192
ledc_set_wait_time1_ns(unsigned long long wait_time1_ns)193 static void ledc_set_wait_time1_ns(unsigned long long wait_time1_ns)
194 {
195 unsigned long long tmp, max = LEDC_WAIT_TIME1_MAX_NS;
196 unsigned int min = LEDC_WAIT_TIME1_MIN_NS;
197 unsigned int n, reg_val;
198
199 if (wait_time1_ns < min || wait_time1_ns > max) {
200 ledc_info("invalid parameter, wait_time1_ns should be %u-%llu!\n", min, max);
201 return;
202 }
203
204 n = wait_time1_ns / 42;
205 //tmp = wait_time1_ns;
206 //n = div_u64(tmp, 42);
207 n -= 1;
208 reg_val = (1 << 31) | n;
209 hal_writel(reg_val, base_addr + LEDC_WAIT_TIME1_CTRL_REG);
210 }
211
ledc_set_wait_data_time_ns(unsigned int wait_data_time_ns)212 static void ledc_set_wait_data_time_ns(unsigned int wait_data_time_ns)
213 {
214 unsigned int mask = 0x1FFF;
215 unsigned int shift = 16;
216 unsigned int reg_val = 0;
217 unsigned int n, min, max;
218
219 min = LEDC_WAIT_DATA_TIME_MIN_NS;
220 max = LEDC_WAIT_DATA_TIME_MAX_NS_IC;
221
222 if (wait_data_time_ns < min || wait_data_time_ns > max) {
223 ledc_info("invalid parameter, wait_data_time_ns should be %u-%u!\n",
224 min, max);
225 return;
226 }
227
228 n = (wait_data_time_ns - 42) / 42;
229 reg_val &= ~(mask << shift);
230 reg_val |= (n << shift);
231 hal_writel(reg_val, base_addr + LEDC_DATA_FINISH_CNT_REG);
232 }
233
ledc_set_length(unsigned int length)234 static void ledc_set_length(unsigned int length)
235 {
236 unsigned int reg_val;
237
238 if (length == 0)
239 return;
240
241 reg_val = hal_readl(base_addr + LEDC_CTRL_REG);
242 reg_val &= ~(0x1FFF << 16);
243 reg_val |= length << 16;
244 hal_writel(reg_val, base_addr + LEDC_CTRL_REG);
245
246 reg_val = hal_readl(base_addr + LED_RST_TIMING_CTRL_REG);
247 reg_val &= ~0x3FF;
248 reg_val |= length - 1;
249 hal_writel(reg_val, base_addr + LED_RST_TIMING_CTRL_REG);
250 }
251
ledc_set_output_mode(const char * str)252 static void ledc_set_output_mode(const char *str)
253 {
254 unsigned int val = 0;
255 unsigned int mask = 0x7;
256 unsigned int shift = 6;
257 unsigned int reg_val ;
258 if (str != NULL) {
259 if (!strncmp(str, "GRB", 3))
260 val = LEDC_OUTPUT_GRB;
261 else if (!strncmp(str, "GBR", 3))
262 val = LEDC_OUTPUT_GBR;
263 else if (!strncmp(str, "RGB", 3))
264 val = LEDC_OUTPUT_RGB;
265 else if (!strncmp(str, "RBG", 3))
266 val = LEDC_OUTPUT_RBG;
267 else if (!strncmp(str, "BGR", 3))
268 val = LEDC_OUTPUT_BGR;
269 else if (!strncmp(str, "BRG", 3))
270 val = LEDC_OUTPUT_BRG;
271 else
272 return;
273 } else {
274 }
275
276 reg_val = hal_readl(base_addr + LEDC_CTRL_REG);
277 reg_val &= ~(mask << shift);
278 reg_val |= val;
279 hal_writel(reg_val, base_addr + LEDC_CTRL_REG);
280 }
281
ledc_disable_irq(unsigned int mask)282 static void ledc_disable_irq(unsigned int mask)
283 {
284 unsigned int reg_val = 0;
285
286 reg_val = hal_readl(base_addr + LEDC_INTC_REG);
287 reg_val &= ~mask;
288 hal_writel(reg_val, base_addr + LEDC_INTC_REG);
289 }
290
ledc_enable_irq(unsigned int mask)291 static void ledc_enable_irq(unsigned int mask)
292 {
293 unsigned int reg_val = 0;
294
295 reg_val = hal_readl(base_addr + LEDC_INTC_REG);
296 reg_val |= mask;
297 hal_writel(reg_val, base_addr + LEDC_INTC_REG);
298 }
299
ledc_set_dma_mode(void)300 static void ledc_set_dma_mode(void)
301 {
302 unsigned int reg_val = 0;
303
304 reg_val |= 1 << 5;
305 hal_writel(reg_val, base_addr + LEDC_DMA_CTRL_REG);
306 }
307
ledc_set_cpu_mode(void)308 static void ledc_set_cpu_mode(void)
309 {
310 unsigned int reg_val = 0;
311
312 reg_val &= ~(1 << 5);
313 hal_writel(reg_val, base_addr + LEDC_DMA_CTRL_REG);
314 }
315
ledc_clear_all_irq(void)316 static void ledc_clear_all_irq(void)
317 {
318 unsigned int reg_val;
319
320 reg_val = hal_readl(base_addr + LEDC_INTS_REG);
321 reg_val |= 0x1F;
322 hal_writel(reg_val, base_addr + LEDC_INTS_REG);
323 }
324
ledc_get_irq_status(void)325 static unsigned int ledc_get_irq_status(void)
326 {
327 return hal_readl(base_addr + LEDC_INTS_REG);
328 }
329
ledc_soft_reset(void)330 static void ledc_soft_reset(void)
331 {
332 unsigned int reg_val;
333
334 reg_val = hal_readl(base_addr + LEDC_CTRL_REG);
335 reg_val |= 1 << 1;
336 hal_writel(reg_val, base_addr + LEDC_CTRL_REG);
337 }
338
ledc_reset_en(void)339 static void ledc_reset_en(void)
340 {
341 unsigned int reg_val;
342
343 reg_val = hal_readl(base_addr + LEDC_CTRL_REG);
344 reg_val |= 1 << 10;
345 hal_writel(reg_val, base_addr + LEDC_CTRL_REG);
346 }
347
ledc_set_data(unsigned int data)348 static void ledc_set_data(unsigned int data)
349 {
350 hal_writel(data, base_addr + LEDC_DATA_REG);
351 }
352
ledc_enable(void)353 static void ledc_enable(void)
354 {
355 unsigned int reg_val;
356
357 reg_val = hal_readl(base_addr + LEDC_CTRL_REG);
358 reg_val |= 1;
359 hal_writel(reg_val, base_addr + LEDC_CTRL_REG);
360 }
361
hal_ledc_set_time(struct ledc_config * ledc)362 static void hal_ledc_set_time(struct ledc_config *ledc)
363 {
364 ledc_set_reset_ns(ledc->reset_ns);
365 ledc_set_t1h_ns(ledc->t1h_ns);
366 ledc_set_t1l_ns(ledc->t1l_ns);
367 ledc_set_t0h_ns(ledc->t0h_ns);
368 ledc_set_t0l_ns(ledc->t0l_ns);
369 ledc_set_wait_time0_ns(ledc->wait_time0_ns);
370 ledc_set_wait_time1_ns(ledc->wait_time1_ns);
371 ledc_set_wait_data_time_ns(ledc->wait_data_time_ns);
372 }
373
hal_ledc_dma_callback(void * para)374 void hal_ledc_dma_callback(void *para)
375 {
376 printf("dma callback\n");
377 }
378
hal_ledc_trans_data(struct ledc_config * ledc)379 void hal_ledc_trans_data(struct ledc_config *ledc)
380 {
381 int i;
382 unsigned long int size;
383 unsigned int mask = 0;
384 struct dma_slave_config slave_config;
385
386 mask = LEDC_TRANS_FINISH_INT_EN | LEDC_WAITDATA_TIMEOUT_INT_EN
387 | LEDC_FIFO_OVERFLOW_INT_EN | LEDC_GLOBAL_INT_EN;
388 if (ledc->length <= SUNXI_LEDC_FIFO_DEPTH) {
389 ledc_info("trans data by CPU mode\n");
390 mask |= LEDC_FIFO_CPUREQ_INT_EN;
391 ledc_reset_en();
392 hal_ledc_set_time(ledc);
393 ledc_set_output_mode(ledc->output_mode);
394 ledc_set_cpu_mode();
395 ledc_set_length(ledc->length);
396 ledc_enable_irq(mask);
397
398 for(i = 0; i < ledc->length; i++)
399 ledc_set_data(ledc->data[i]);
400
401 ledc_enable();
402 } else {
403 ledc_info("trans data by DMA mode\n");
404 mask &= ~LEDC_FIFO_CPUREQ_INT_EN;
405
406 ledc_reset_en();
407 size = ledc->length * 4;
408
409 hal_dcache_clean((unsigned long)ledc->data, sizeof(ledc->data));
410
411 slave_config.direction = DMA_MEM_TO_DEV;
412 slave_config.src_addr = (unsigned long)(ledc->data);
413 slave_config.dst_addr = (uint32_t)(base_addr + LEDC_DATA_REG);
414 slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
415 slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
416 slave_config.src_maxburst = DMA_SLAVE_BURST_16;
417 slave_config.dst_maxburst = DMA_SLAVE_BURST_16;
418 slave_config.slave_id = sunxi_slave_id(DRQDST_LEDC, DRQSRC_SDRAM);
419 hal_dma_slave_config(dma_chan, &slave_config);
420
421 hal_dma_prep_device(dma_chan, slave_config.dst_addr, slave_config.src_addr, size, DMA_MEM_TO_DEV);
422
423 //dma_chan->callback = ledc_dma_callback;
424 hal_dma_start(dma_chan);
425
426 hal_ledc_set_time(ledc);
427 ledc_set_output_mode(ledc->output_mode);
428 ledc_set_length(ledc->length);
429 ledc_set_dma_mode();
430 ledc_enable_irq(mask);
431 ledc_enable();
432 }
433 }
434
hal_ledc_clear_all_irq(void)435 void hal_ledc_clear_all_irq(void)
436 {
437 ledc_clear_all_irq();
438 }
439
hal_ledc_get_irq_status(void)440 unsigned int hal_ledc_get_irq_status(void)
441 {
442 return ledc_get_irq_status();
443 }
444
hal_ledc_reset(void)445 void hal_ledc_reset(void)
446 {
447 ledc_disable_irq(LEDC_TRANS_FINISH_INT_EN | LEDC_WAITDATA_TIMEOUT_INT_EN
448 | LEDC_FIFO_OVERFLOW_INT_EN | LEDC_GLOBAL_INT_EN | LEDC_GLOBAL_INT_EN);
449
450 if (dma_chan)
451 {
452 hal_dma_stop(dma_chan);
453 }
454 ledc_soft_reset();
455 }
456
hal_ledc_deinit(void)457 void hal_ledc_deinit(void)
458 {
459 hal_dma_chan_free(dma_chan);
460 hal_gpio_pinmux_set_function(GPIOE(2), 2);
461 //clk_deinit
462 }
463
hal_ledc_init(void)464 void hal_ledc_init(void)
465 {
466 int i;
467 unsigned int reg_val = 0;
468
469 if (ledc_clk_init())
470 {
471 ledc_info("ledc clk init failed \n");
472 }
473
474 if (ledc_pinctrl_init())
475 {
476 ledc_info("ledc pinctrl init failed \n");
477 }
478
479 hal_dma_chan_request(&dma_chan);
480 }
481
482