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