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