1 /* 2 * (C) Copyright 2014 3 * Heiko Schocher, DENX Software Engineering, hs@denx.de. 4 * 5 * Basic support for the pwm modul on imx6. 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 18 /* pwm_id from 0..3 */ 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; 24 break; 25 case 1: 26 return (struct pwm_regs *)PWM2_BASE_ADDR; 27 break; 28 case 2: 29 return (struct pwm_regs *)PWM3_BASE_ADDR; 30 break; 31 case 3: 32 return (struct pwm_regs *)PWM4_BASE_ADDR; 33 break; 34 default: 35 printf("unknown pwm_id: %d\n", pwm_id); 36 break; 37 } 38 return NULL; 39 } 40 41 int pwm_imx_get_parms(int period_ns, int duty_ns, unsigned long *period_c, 42 unsigned long *duty_c, unsigned long *prescale) 43 { 44 unsigned long long c; 45 46 /* 47 * we have not yet a clock framework for imx6, so add the clock 48 * value here as a define. Replace it when we have the clock 49 * framework. 50 */ 51 c = CONFIG_IMX6_PWM_PER_CLK; 52 c = c * period_ns; 53 do_div(c, 1000000000); 54 *period_c = c; 55 56 *prescale = *period_c / 0x10000 + 1; 57 58 *period_c /= *prescale; 59 c = (unsigned long long)(*period_c * duty_ns); 60 do_div(c, period_ns); 61 *duty_c = c; 62 63 /* 64 * according to imx pwm RM, the real period value should be 65 * PERIOD value in PWMPR plus 2. 66 */ 67 if (*period_c > 2) 68 *period_c -= 2; 69 else 70 *period_c = 0; 71 72 return 0; 73 } 74