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