1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * (C) Copyright 2014
4 * Heiko Schocher, DENX Software Engineering, hs@denx.de.
5 *
6 * Basic support for the pwm module on imx6.
7 *
8 * Based on linux:drivers/pwm/pwm-imx.c
9 * from
10 * Sascha Hauer <s.hauer@pengutronix.de>
11 */
12
13 #include <common.h>
14 #include <div64.h>
15 #include <asm/arch/imx-regs.h>
16
17 /* pwm_id from 0..7 */
pwm_id_to_reg(int pwm_id)18 struct pwm_regs *pwm_id_to_reg(int pwm_id)
19 {
20 switch (pwm_id) {
21 case 0:
22 return (struct pwm_regs *)PWM1_BASE_ADDR;
23 case 1:
24 return (struct pwm_regs *)PWM2_BASE_ADDR;
25 #ifdef CONFIG_MX6
26 case 2:
27 return (struct pwm_regs *)PWM3_BASE_ADDR;
28 case 3:
29 return (struct pwm_regs *)PWM4_BASE_ADDR;
30 #endif
31 #ifdef CONFIG_MX6SX
32 case 4:
33 return (struct pwm_regs *)PWM5_BASE_ADDR;
34 case 5:
35 return (struct pwm_regs *)PWM6_BASE_ADDR;
36 case 6:
37 return (struct pwm_regs *)PWM7_BASE_ADDR;
38 case 7:
39 return (struct pwm_regs *)PWM8_BASE_ADDR;
40 #endif
41 default:
42 printf("unknown pwm_id: %d\n", pwm_id);
43 break;
44 }
45 return NULL;
46 }
47
pwm_imx_get_parms(int period_ns,int duty_ns,unsigned long * period_c,unsigned long * duty_c,unsigned long * prescale)48 int pwm_imx_get_parms(int period_ns, int duty_ns, unsigned long *period_c,
49 unsigned long *duty_c, unsigned long *prescale)
50 {
51 unsigned long long c;
52
53 /*
54 * we have not yet a clock framework for imx6, so add the clock
55 * value here as a define. Replace it when we have the clock
56 * framework.
57 */
58 c = CONFIG_IMX6_PWM_PER_CLK;
59 c = c * period_ns;
60 do_div(c, 1000000000);
61 *period_c = c;
62
63 *prescale = *period_c / 0x10000 + 1;
64
65 *period_c /= *prescale;
66 c = *period_c * (unsigned long long)duty_ns;
67 do_div(c, period_ns);
68 *duty_c = c;
69
70 /*
71 * according to imx pwm RM, the real period value should be
72 * PERIOD value in PWMPR plus 2.
73 */
74 if (*period_c > 2)
75 *period_c -= 2;
76 else
77 *period_c = 0;
78
79 return 0;
80 }
81