1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * (C) Copyright 2014 4 * Heiko Schocher, DENX Software Engineering, hs@denx.de. 5 * 6 * Basic support for the pwm module on imx6. 7 * 8 * Based on linux:drivers/pwm/pwm-imx.c 9 * from 10 * Sascha Hauer <s.hauer@pengutronix.de> 11 */ 12 13 #include <common.h> 14 #include <div64.h> 15 #include <asm/arch/imx-regs.h> 16 17 /* pwm_id from 0..7 */ 18 struct 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; 23 case 1: 24 return (struct pwm_regs *)PWM2_BASE_ADDR; 25 #ifdef CONFIG_MX6 26 case 2: 27 return (struct pwm_regs *)PWM3_BASE_ADDR; 28 case 3: 29 return (struct pwm_regs *)PWM4_BASE_ADDR; 30 #endif 31 #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 41 default: 42 printf("unknown pwm_id: %d\n", pwm_id); 43 break; 44 } 45 return NULL; 46 } 47 48 int 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; 66 c = *period_c * (unsigned long long)duty_ns; 67 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 } 81