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