1 /* 2 * (C) Copyright 2014 3 * Heiko Schocher, DENX Software Engineering, hs@denx.de. 4 * 5 * Basic support for the pwm module 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..7 */ 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 #ifdef CONFIG_MX6 27 case 2: 28 return (struct pwm_regs *)PWM3_BASE_ADDR; 29 case 3: 30 return (struct pwm_regs *)PWM4_BASE_ADDR; 31 #endif 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 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; 67 c = *period_c * (unsigned long long)duty_ns; 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 } 82