blob: 823a9d2d6bfaeb5c7c0d319815dc5f6b015dfe0b [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Heiko Schocher2b387762014-07-18 06:07:19 +02002/*
3 * (C) Copyright 2014
4 * Heiko Schocher, DENX Software Engineering, hs@denx.de.
5 *
Robert P. J. Day1f8378a2016-09-13 08:35:18 -04006 * Basic support for the pwm module on imx6.
Heiko Schocher2b387762014-07-18 06:07:19 +02007 *
8 * Based on linux:drivers/pwm/pwm-imx.c
9 * from
10 * Sascha Hauer <s.hauer@pengutronix.de>
Heiko Schocher2b387762014-07-18 06:07:19 +020011 */
12
13#include <common.h>
14#include <div64.h>
15#include <asm/arch/imx-regs.h>
16
Christoph Fritzd1942f52016-11-22 12:01:28 +010017/* pwm_id from 0..7 */
Heiko Schocher2b387762014-07-18 06:07:19 +020018struct 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;
Heiko Schocher2b387762014-07-18 06:07:19 +020023 case 1:
24 return (struct pwm_regs *)PWM2_BASE_ADDR;
Martyn Welcha87af132017-11-08 15:35:11 +000025#ifdef CONFIG_MX6
Heiko Schocher2b387762014-07-18 06:07:19 +020026 case 2:
27 return (struct pwm_regs *)PWM3_BASE_ADDR;
Heiko Schocher2b387762014-07-18 06:07:19 +020028 case 3:
29 return (struct pwm_regs *)PWM4_BASE_ADDR;
Martyn Welcha87af132017-11-08 15:35:11 +000030#endif
Christoph Fritzd1942f52016-11-22 12:01:28 +010031#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
Heiko Schocher2b387762014-07-18 06:07:19 +020041 default:
42 printf("unknown pwm_id: %d\n", pwm_id);
43 break;
44 }
45 return NULL;
46}
47
48int 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;
Brecht Neyrinck33d2d152015-05-06 09:57:48 +020066 c = *period_c * (unsigned long long)duty_ns;
Heiko Schocher2b387762014-07-18 06:07:19 +020067 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}