xref: /openbmc/u-boot/drivers/pwm/pwm-imx-util.c (revision fabbeb33)
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 */
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 
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