[5e3096db] | 1 | /** |
---|
| 2 | * @file |
---|
[6dc5c03f] | 3 | * |
---|
[5e3096db] | 4 | * @ingroup arm_beagle |
---|
[6dc5c03f] | 5 | * |
---|
[5e3096db] | 6 | * @brief Support for PWM for the BeagleBone Black. |
---|
| 7 | */ |
---|
[6dc5c03f] | 8 | |
---|
[5e3096db] | 9 | /** |
---|
[55bde66] | 10 | * Copyright (c) 2016 Punit Vara <punitvara@gmail.com> |
---|
[6dc5c03f] | 11 | * |
---|
[5e3096db] | 12 | * The license and distribution terms for this file may be |
---|
| 13 | * found in the file LICENSE in this distribution or at |
---|
| 14 | * http://www.rtems.org/license/LICENSE. |
---|
[6dc5c03f] | 15 | */ |
---|
| 16 | |
---|
[5e3096db] | 17 | /** This file is based on |
---|
| 18 | * https://github.com/VegetableAvenger/BBBIOlib/blob/master/BBBio_lib/BBBiolib_PWMSS.c |
---|
| 19 | */ |
---|
[6dc5c03f] | 20 | |
---|
[5e3096db] | 21 | #include <libcpu/am335x.h> |
---|
| 22 | #include <stdio.h> |
---|
| 23 | #include <bsp/gpio.h> |
---|
| 24 | #include <bsp/bbb-gpio.h> |
---|
| 25 | #include <bsp.h> |
---|
| 26 | #include <bsp/bbb-pwm.h> |
---|
[55bde66] | 27 | #include <bsp/beagleboneblack.h> |
---|
[5e3096db] | 28 | |
---|
| 29 | /* Currently these definitions are for BeagleBone Black board only |
---|
| 30 | * Later on Beagle-xM board support can be added in this code. |
---|
| 31 | * After support gets added if condition should be removed |
---|
[6dc5c03f] | 32 | */ |
---|
[5e3096db] | 33 | #if IS_AM335X |
---|
[6dc5c03f] | 34 | |
---|
[5e3096db] | 35 | /* |
---|
[55bde66] | 36 | * @brief This function selects EPWM module to be enabled |
---|
[5e3096db] | 37 | * |
---|
| 38 | * @param pwm_id It is the instance number of EPWM of pwm sub system. |
---|
| 39 | * |
---|
| 40 | * @return Base Address of respective pwm instant. |
---|
| 41 | */ |
---|
[55bde66] | 42 | static uint32_t select_pwm(BBB_PWMSS pwm_id) |
---|
[5e3096db] | 43 | { |
---|
[55bde66] | 44 | uint32_t baseAddr=0; |
---|
| 45 | |
---|
| 46 | if (pwm_id == BBB_PWMSS0) { |
---|
| 47 | baseAddr = AM335X_EPWM_0_REGS; |
---|
| 48 | } else if (pwm_id == BBB_PWMSS1) { |
---|
| 49 | baseAddr = AM335X_EPWM_1_REGS; |
---|
| 50 | } else if (pwm_id == BBB_PWMSS2) { |
---|
| 51 | baseAddr = AM335X_EPWM_2_REGS; |
---|
| 52 | } else { |
---|
| 53 | baseAddr = 0; |
---|
| 54 | } |
---|
| 55 | return baseAddr; |
---|
[6dc5c03f] | 56 | } |
---|
| 57 | |
---|
[55bde66] | 58 | /* |
---|
| 59 | * @brief This function selects PWM Sub system to be enabled |
---|
| 60 | * |
---|
| 61 | * @param pwmss_id The instance number of ePWMSS whose system clocks |
---|
| 62 | * have to be configured. |
---|
| 63 | * |
---|
| 64 | * @return Base Address of respective pwmss instant. |
---|
| 65 | */ |
---|
| 66 | static uint32_t select_pwmss(BBB_PWMSS pwmss_id) |
---|
[6dc5c03f] | 67 | { |
---|
[55bde66] | 68 | uint32_t baseAddr=0; |
---|
| 69 | |
---|
| 70 | if (pwmss_id == BBB_PWMSS0) { |
---|
| 71 | baseAddr = AM335X_PWMSS0_MMAP_ADDR; |
---|
| 72 | } else if (pwmss_id == BBB_PWMSS1) { |
---|
| 73 | baseAddr = AM335X_PWMSS1_MMAP_ADDR; |
---|
| 74 | } else if (pwmss_id == BBB_PWMSS2) { |
---|
| 75 | baseAddr = AM335X_PWMSS2_MMAP_ADDR; |
---|
| 76 | } else { |
---|
| 77 | baseAddr = 0; |
---|
| 78 | } |
---|
| 79 | return baseAddr; |
---|
[6dc5c03f] | 80 | } |
---|
[55bde66] | 81 | |
---|
| 82 | bool beagle_pwm_pinmux_setup(bbb_pwm_pin_t pin_no, BBB_PWMSS pwm_id) |
---|
| 83 | { |
---|
| 84 | bool is_valid = true; |
---|
| 85 | |
---|
| 86 | if(pwm_id == BBB_PWMSS0) { |
---|
| 87 | if (pin_no == BBB_P9_21_0B) { |
---|
| 88 | REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_D0) = BBB_MUXMODE(BBB_P9_21_MUX_PWM); |
---|
| 89 | } else if (pin_no == BBB_P9_22_0A) { |
---|
| 90 | REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_SCLK) = BBB_MUXMODE(BBB_P9_22_MUX_PWM); |
---|
| 91 | } else if (pin_no == BBB_P9_29_0B) { |
---|
| 92 | REG(AM335X_PADCONF_BASE + AM335X_CONF_MCASP0_FSX) = BBB_MUXMODE(BBB_P9_29_MUX_PWM); |
---|
| 93 | } else if (pin_no == BBB_P9_31_0A) { |
---|
| 94 | REG(AM335X_PADCONF_BASE + AM335X_CONF_MCASP0_ACLKX) = BBB_MUXMODE(BBB_P9_31_MUX_PWM); |
---|
| 95 | } else { |
---|
| 96 | is_valid = false; |
---|
| 97 | } |
---|
| 98 | |
---|
| 99 | } else if (pwm_id == BBB_PWMSS1) { |
---|
| 100 | if (pin_no == BBB_P8_34_1B) { |
---|
| 101 | REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_LCD_DATA(11)) = BBB_MUXMODE(BBB_P8_34_MUX_PWM); |
---|
| 102 | } else if (pin_no == BBB_P8_36_1A) { |
---|
| 103 | REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_LCD_DATA(10)) = BBB_MUXMODE(BBB_P8_36_MUX_PWM); |
---|
| 104 | } else if (pin_no == BBB_P9_14_1A) { |
---|
| 105 | REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_GPMC_AD(2)) = BBB_MUXMODE(BBB_P9_14_MUX_PWM); |
---|
| 106 | } else if (pin_no == BBB_P9_16_1B) { |
---|
| 107 | REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_GPMC_AD(3)) = BBB_MUXMODE(BBB_P9_16_MUX_PWM); |
---|
| 108 | } else { |
---|
| 109 | is_valid = false; |
---|
| 110 | } |
---|
| 111 | } else if (pwm_id == BBB_PWMSS2) { |
---|
| 112 | if (pin_no == BBB_P8_13_2B) { |
---|
| 113 | REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_GPMC_AD(9)) = BBB_MUXMODE(BBB_P8_13_MUX_PWM); |
---|
| 114 | } else if (pin_no == BBB_P8_19_2A) { |
---|
| 115 | REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_GPMC_AD(8)) = BBB_MUXMODE(BBB_P8_19_MUX_PWM); |
---|
| 116 | } else if (pin_no == BBB_P8_45_2A) { |
---|
| 117 | REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_LCD_DATA(0)) = BBB_MUXMODE(BBB_P8_45_MUX_PWM); |
---|
| 118 | } else if (pin_no == BBB_P8_46_2B) { |
---|
| 119 | REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_LCD_DATA(1)) = BBB_MUXMODE(BBB_P8_46_MUX_PWM); |
---|
| 120 | } else { |
---|
| 121 | is_valid = false; |
---|
| 122 | } |
---|
| 123 | } else { |
---|
| 124 | is_valid = false; |
---|
| 125 | } |
---|
| 126 | return is_valid; |
---|
[6dc5c03f] | 127 | } |
---|
| 128 | |
---|
[5e3096db] | 129 | /** |
---|
| 130 | * @brief This function Enables TBCLK(Time Base Clock) for specific |
---|
| 131 | * EPWM instance of pwmsubsystem. |
---|
[6dc5c03f] | 132 | * |
---|
[5e3096db] | 133 | * @param instance It is the instance number of EPWM of pwmsubsystem. |
---|
[6dc5c03f] | 134 | * |
---|
[5e3096db] | 135 | * @return true if successful |
---|
[55bde66] | 136 | * false if unsuccessful |
---|
[5e3096db] | 137 | **/ |
---|
[55bde66] | 138 | static bool pwmss_tbclk_enable(BBB_PWMSS instance) |
---|
[6dc5c03f] | 139 | { |
---|
[55bde66] | 140 | uint32_t enable_bit; |
---|
| 141 | bool is_valid = true; |
---|
[5e3096db] | 142 | |
---|
[55bde66] | 143 | if (instance == BBB_PWMSS0) { |
---|
| 144 | enable_bit = AM335X_PWMSS_CTRL_PWMSS0_TBCLKEN; |
---|
| 145 | } else if (instance == BBB_PWMSS1) { |
---|
[5e3096db] | 146 | enable_bit = AM335X_PWMSS_CTRL_PWMSS1_TBCLKEN; |
---|
[55bde66] | 147 | } else if (instance == BBB_PWMSS2) { |
---|
[5e3096db] | 148 | enable_bit = AM335X_PWMSS_CTRL_PWMSS2_TBCLKEN; |
---|
[55bde66] | 149 | } else { |
---|
[5e3096db] | 150 | is_valid = false; |
---|
| 151 | } |
---|
| 152 | |
---|
| 153 | if (is_valid) |
---|
| 154 | { |
---|
[55bde66] | 155 | REG(AM335X_PADCONF_BASE + AM335X_PWMSS_CTRL) |= enable_bit; |
---|
[5e3096db] | 156 | } |
---|
| 157 | |
---|
| 158 | return is_valid; |
---|
| 159 | } |
---|
| 160 | |
---|
| 161 | /** |
---|
| 162 | * @brief This functions enables clock for EHRPWM module in PWMSS subsystem. |
---|
[6dc5c03f] | 163 | * |
---|
[5e3096db] | 164 | * @param pwm_id It is the instance number of EPWM of pwm sub system. |
---|
[6dc5c03f] | 165 | * |
---|
[55bde66] | 166 | * @return true if successful |
---|
| 167 | * false if unsuccessful |
---|
[6dc5c03f] | 168 | * |
---|
[5e3096db] | 169 | **/ |
---|
[55bde66] | 170 | static bool pwm_clock_enable(BBB_PWMSS pwm_id) |
---|
| 171 | { |
---|
| 172 | const bool id_is_valid = pwm_id < BBB_PWMSS_COUNT; |
---|
| 173 | bool status = true; |
---|
| 174 | |
---|
| 175 | if (id_is_valid) { |
---|
| 176 | const uint32_t baseAddr = select_pwmss(pwm_id); |
---|
| 177 | REG(baseAddr + AM335X_PWMSS_CLKCONFIG) |= AM335X_PWMSS_CLK_EN_ACK; |
---|
| 178 | } else { |
---|
| 179 | status = false; |
---|
| 180 | } |
---|
| 181 | return status; |
---|
[5e3096db] | 182 | } |
---|
| 183 | |
---|
| 184 | /** |
---|
| 185 | * @brief This function configures the L3 and L4_PER system clocks. |
---|
| 186 | * It also configures the system clocks for the specified ePWMSS |
---|
| 187 | * instance. |
---|
[6dc5c03f] | 188 | * |
---|
[5e3096db] | 189 | * @param pwmss_id The instance number of ePWMSS whose system clocks |
---|
| 190 | * have to be configured. |
---|
[6dc5c03f] | 191 | * |
---|
[5e3096db] | 192 | * 'pwmss_id' can take one of the following values: |
---|
| 193 | * (0 <= pwmss_id <= 2) |
---|
[6dc5c03f] | 194 | * |
---|
[55bde66] | 195 | * @return True if successful |
---|
| 196 | * False if Unsuccessful |
---|
[5e3096db] | 197 | */ |
---|
[55bde66] | 198 | static bool pwmss_module_clk_config(BBB_PWMSS pwmss_id) |
---|
[6dc5c03f] | 199 | { |
---|
[55bde66] | 200 | bool is_valid = true; |
---|
| 201 | |
---|
| 202 | if(pwmss_id == BBB_PWMSS0) { |
---|
| 203 | const uint32_t is_functional = AM335X_CM_PER_EPWMSS0_CLKCTRL_IDLEST_FUNC << |
---|
| 204 | AM335X_CM_PER_EPWMSS0_CLKCTRL_IDLEST_SHIFT; |
---|
| 205 | const uint32_t clkctrl = AM335X_CM_PER_ADDR + AM335X_CM_PER_EPWMSS0_CLKCTRL; |
---|
| 206 | const uint32_t idle_bits = AM335X_CM_PER_EPWMSS0_CLKCTRL_IDLEST; |
---|
| 207 | const uint32_t is_enable = AM335X_CM_PER_EPWMSS0_CLKCTRL_MODULEMODE_ENABLE; |
---|
| 208 | const uint32_t module_mode = AM335X_CM_PER_EPWMSS0_CLKCTRL_MODULEMODE; |
---|
| 209 | |
---|
| 210 | REG(clkctrl) |= is_enable; |
---|
| 211 | while((REG(clkctrl) & module_mode) != is_enable); |
---|
| 212 | while((REG(clkctrl) & idle_bits) != is_functional); |
---|
| 213 | } |
---|
| 214 | else if(pwmss_id == BBB_PWMSS1) { |
---|
| 215 | const uint32_t is_functional = AM335X_CM_PER_EPWMSS1_CLKCTRL_IDLEST_FUNC << |
---|
| 216 | AM335X_CM_PER_EPWMSS1_CLKCTRL_IDLEST_SHIFT; |
---|
| 217 | const uint32_t clkctrl = AM335X_CM_PER_ADDR + AM335X_CM_PER_EPWMSS1_CLKCTRL; |
---|
| 218 | const uint32_t idle_bits = AM335X_CM_PER_EPWMSS1_CLKCTRL_IDLEST; |
---|
| 219 | const uint32_t is_enable = AM335X_CM_PER_EPWMSS1_CLKCTRL_MODULEMODE_ENABLE; |
---|
| 220 | const uint32_t module_mode = AM335X_CM_PER_EPWMSS1_CLKCTRL_MODULEMODE; |
---|
[5e3096db] | 221 | |
---|
[55bde66] | 222 | REG(clkctrl) |= is_enable; |
---|
| 223 | while((REG(clkctrl) & module_mode) != is_enable); |
---|
| 224 | while((REG(clkctrl) & idle_bits) != is_functional); |
---|
| 225 | } else if(pwmss_id == BBB_PWMSS2) { |
---|
| 226 | const uint32_t is_functional = AM335X_CM_PER_EPWMSS2_CLKCTRL_IDLEST_FUNC << |
---|
| 227 | AM335X_CM_PER_EPWMSS2_CLKCTRL_IDLEST_SHIFT; |
---|
| 228 | const uint32_t clkctrl = AM335X_CM_PER_ADDR + AM335X_CM_PER_EPWMSS2_CLKCTRL; |
---|
| 229 | const uint32_t idle_bits = AM335X_CM_PER_EPWMSS2_CLKCTRL_IDLEST; |
---|
| 230 | const uint32_t is_enable = AM335X_CM_PER_EPWMSS2_CLKCTRL_MODULEMODE_ENABLE; |
---|
| 231 | const uint32_t module_mode = AM335X_CM_PER_EPWMSS2_CLKCTRL_MODULEMODE; |
---|
[5e3096db] | 232 | |
---|
[55bde66] | 233 | REG(clkctrl) |= is_enable; |
---|
| 234 | while((REG(clkctrl) & module_mode) != is_enable); |
---|
| 235 | while((REG(clkctrl) & idle_bits) != is_functional); |
---|
| 236 | } else |
---|
| 237 | is_valid = false; |
---|
| 238 | return is_valid; |
---|
[5e3096db] | 239 | } |
---|
[6dc5c03f] | 240 | |
---|
[55bde66] | 241 | bool beagle_pwm_init(BBB_PWMSS pwmss_id) |
---|
[5e3096db] | 242 | { |
---|
[55bde66] | 243 | const bool id_is_valid = pwmss_id < BBB_PWMSS_COUNT; |
---|
[5e3096db] | 244 | bool status = true; |
---|
[55bde66] | 245 | |
---|
| 246 | if(id_is_valid) { |
---|
| 247 | pwmss_module_clk_config(pwmss_id); |
---|
| 248 | pwm_clock_enable(pwmss_id); |
---|
| 249 | pwmss_tbclk_enable(pwmss_id); |
---|
| 250 | } else { |
---|
| 251 | status =false; |
---|
[5e3096db] | 252 | } |
---|
| 253 | return status; |
---|
| 254 | } |
---|
[6dc5c03f] | 255 | |
---|
[55bde66] | 256 | int beagle_pwm_configure(BBB_PWMSS pwm_id, float pwm_freq, float duty_a, float duty_b) |
---|
| 257 | { |
---|
[5e3096db] | 258 | uint32_t baseAddr; |
---|
| 259 | int status = 1; |
---|
[55bde66] | 260 | float cycle = 0.0f,divisor = 0; |
---|
| 261 | unsigned int i,j; |
---|
[5e3096db] | 262 | const float CLKDIV_div[] = {1.0,2.0,4.0,8.0,16.0,32.0,64.0,128.0}; |
---|
| 263 | const float HSPCLKDIV_div[] = {1.0, 2.0, 4.0, 6.0, 8.0, 10.0,12.0, 14.0}; |
---|
[55bde66] | 264 | int NearCLKDIV =7,NearHSPCLKDIV =7,NearTBPRD =0; |
---|
| 265 | |
---|
| 266 | if (pwm_freq <= BBB_PWM_FREQ_THRESHOLD) { |
---|
| 267 | status =0; |
---|
| 268 | } |
---|
| 269 | |
---|
| 270 | if (duty_a < 0.0f || duty_a > 100.0f || duty_b < 0.0f || duty_b > 100.0f) { |
---|
| 271 | status = 0; |
---|
| 272 | } |
---|
| 273 | duty_a /= 100.0f; |
---|
| 274 | duty_b /= 100.0f; |
---|
| 275 | |
---|
[5e3096db] | 276 | /** 10^9 /Hz compute time per cycle (ns) */ |
---|
[55bde66] | 277 | cycle = 1000000000.0f / pwm_freq; |
---|
[5e3096db] | 278 | |
---|
| 279 | /** am335x provide (128* 14) divider and per TBPRD means 10ns when divider |
---|
| 280 | * and max TBPRD is 65535 so max cycle is 128 * 8 * 14 * 65535 * 10ns */ |
---|
[55bde66] | 281 | divisor = (cycle / 655350.0f); |
---|
| 282 | if (divisor > (128 * 14)) { |
---|
| 283 | return 0; |
---|
[5e3096db] | 284 | } |
---|
| 285 | else { |
---|
[55bde66] | 286 | for (i=0;i<8;i++) { |
---|
| 287 | for(j=0 ; j<8; j++) { |
---|
| 288 | if((CLKDIV_div[i] * HSPCLKDIV_div[j]) < (CLKDIV_div[NearCLKDIV] |
---|
| 289 | * HSPCLKDIV_div[NearHSPCLKDIV]) && (CLKDIV_div[i] * HSPCLKDIV_div[j] > divisor)) { |
---|
| 290 | NearCLKDIV = i; |
---|
| 291 | NearHSPCLKDIV = j; |
---|
| 292 | } |
---|
| 293 | } |
---|
| 294 | } |
---|
| 295 | |
---|
| 296 | baseAddr = select_pwm(pwm_id); |
---|
| 297 | |
---|
[5e3096db] | 298 | REG16(baseAddr + AM335X_EPWM_TBCTL) &= ~(AM335X_TBCTL_CLKDIV_MASK | AM335X_TBCTL_HSPCLKDIV_MASK); |
---|
[55bde66] | 299 | const uint16_t clkdiv_clear = (REG16(baseAddr + AM335X_EPWM_TBCTL) & |
---|
| 300 | (~AM335X_EPWM_TBCTL_CLKDIV)); |
---|
| 301 | const uint16_t clkdiv_write = ((NearCLKDIV |
---|
[5e3096db] | 302 | << AM335X_EPWM_TBCTL_CLKDIV_SHIFT) & AM335X_EPWM_TBCTL_CLKDIV); |
---|
[55bde66] | 303 | REG16(baseAddr + AM335X_EPWM_TBCTL) = clkdiv_clear | clkdiv_write; |
---|
| 304 | const uint16_t hspclkdiv_clear = (REG16(baseAddr + AM335X_EPWM_TBCTL) & |
---|
| 305 | (~AM335X_EPWM_TBCTL_HSPCLKDIV)); |
---|
| 306 | const uint16_t hspclkdiv_write = ((NearHSPCLKDIV << |
---|
[5e3096db] | 307 | AM335X_EPWM_TBCTL_HSPCLKDIV_SHIFT) & AM335X_EPWM_TBCTL_HSPCLKDIV); |
---|
[55bde66] | 308 | REG16(baseAddr + AM335X_EPWM_TBCTL) = hspclkdiv_clear | hspclkdiv_write; |
---|
| 309 | NearTBPRD = (cycle / (10.0 * CLKDIV_div[NearCLKDIV] * HSPCLKDIV_div[NearHSPCLKDIV])); |
---|
| 310 | const uint16_t shadow_mask = (REG16(baseAddr + AM335X_EPWM_TBCTL) & |
---|
| 311 | (~AM335X_EPWM_PRD_LOAD_SHADOW_MASK)); |
---|
| 312 | const uint16_t shadow_disable = (((bool)AM335X_EPWM_SHADOW_WRITE_DISABLE << |
---|
[5e3096db] | 313 | AM335X_EPWM_TBCTL_PRDLD_SHIFT) & AM335X_EPWM_PRD_LOAD_SHADOW_MASK); |
---|
[55bde66] | 314 | REG16(baseAddr + AM335X_EPWM_TBCTL) = shadow_mask | shadow_disable; |
---|
| 315 | const uint16_t counter_mask = (REG16(baseAddr + AM335X_EPWM_TBCTL) & |
---|
| 316 | (~AM335X_EPWM_COUNTER_MODE_MASK)); |
---|
| 317 | const uint16_t counter_shift = (((unsigned int)AM335X_EPWM_COUNT_UP << |
---|
[5e3096db] | 318 | AM335X_TBCTL_CTRMODE_SHIFT) & AM335X_EPWM_COUNTER_MODE_MASK); |
---|
[55bde66] | 319 | REG16(baseAddr + AM335X_EPWM_TBCTL) = counter_mask | counter_shift; |
---|
[5e3096db] | 320 | /*setting clock divider and freeze time base*/ |
---|
[55bde66] | 321 | REG16(baseAddr + AM335X_EPWM_CMPB) = (unsigned short)((float)(NearTBPRD) * duty_b); |
---|
| 322 | REG16(baseAddr + AM335X_EPWM_CMPA) = (unsigned short)((float)(NearTBPRD) * duty_a); |
---|
[5e3096db] | 323 | REG16(baseAddr + AM335X_EPWM_TBPRD) = (unsigned short)NearTBPRD; |
---|
| 324 | REG16(baseAddr + AM335X_EPWM_TBCNT) = 0; |
---|
| 325 | } |
---|
| 326 | return status; |
---|
[6dc5c03f] | 327 | } |
---|
| 328 | |
---|
[55bde66] | 329 | bool beagle_pwm_enable(BBB_PWMSS pwmid) |
---|
[6dc5c03f] | 330 | { |
---|
[55bde66] | 331 | const bool id_is_valid = pwmid < BBB_PWMSS_COUNT; |
---|
[5e3096db] | 332 | bool status = true; |
---|
[55bde66] | 333 | |
---|
| 334 | if (id_is_valid) { |
---|
| 335 | const uint32_t baseAddr = select_pwm(pwmid); |
---|
| 336 | /* Initially set EPWMxA o/p high , when increasing counter = CMPA toggle o/p of EPWMxA */ |
---|
| 337 | REG16(baseAddr + AM335X_EPWM_AQCTLA) = AM335X_EPWM_AQCTLA_ZRO_XAHIGH | (AM335X_EPWM_AQCTLA_CAU_EPWMXATOGGLE << AM335X_EPWM_AQCTLA_CAU_SHIFT); |
---|
| 338 | /* Initially set EPWMxB o/p high , when increasing counter = CMPA toggle o/p of EPWMxB */ |
---|
| 339 | REG16(baseAddr + AM335X_EPWM_AQCTLB) = AM335X_EPWM_AQCTLB_ZRO_XBHIGH | (AM335X_EPWM_AQCTLB_CBU_EPWMXBTOGGLE << AM335X_EPWM_AQCTLB_CBU_SHIFT); |
---|
| 340 | REG16(baseAddr + AM335X_EPWM_TBCNT) = 0; |
---|
| 341 | /* Set counter mode : Up-count mode */ |
---|
| 342 | REG16(baseAddr + AM335X_EPWM_TBCTL) |= AM335X_TBCTL_FREERUN | AM335X_TBCTL_CTRMODE_UP; |
---|
| 343 | } else { |
---|
| 344 | status =false; |
---|
[5e3096db] | 345 | } |
---|
[55bde66] | 346 | return status; |
---|
[6dc5c03f] | 347 | } |
---|
| 348 | |
---|
[55bde66] | 349 | bool beagle_pwm_disable(BBB_PWMSS pwmid) |
---|
[6dc5c03f] | 350 | { |
---|
[55bde66] | 351 | const bool id_is_valid = pwmid < BBB_PWMSS_COUNT; |
---|
[5e3096db] | 352 | bool status = true; |
---|
[55bde66] | 353 | |
---|
| 354 | if (id_is_valid) { |
---|
| 355 | const uint32_t baseAddr = select_pwm(pwmid); |
---|
| 356 | REG16(baseAddr + AM335X_EPWM_TBCTL) = AM335X_EPWM_TBCTL_CTRMODE_STOPFREEZE; |
---|
| 357 | REG16(baseAddr + AM335X_EPWM_AQCTLA) = AM335X_EPWM_AQCTLA_ZRO_XALOW | (AM335X_EPWM_AQCTLA_CAU_EPWMXATOGGLE << AM335X_EPWM_AQCTLA_CAU_SHIFT); |
---|
| 358 | REG16(baseAddr + AM335X_EPWM_AQCTLB) = AM335X_EPWM_AQCTLA_ZRO_XBLOW | (AM335X_EPWM_AQCTLB_CBU_EPWMXBTOGGLE << AM335X_EPWM_AQCTLB_CBU_SHIFT); |
---|
| 359 | REG16(baseAddr + AM335X_EPWM_TBCNT) = 0; |
---|
| 360 | } else { |
---|
| 361 | status = false; |
---|
[5e3096db] | 362 | } |
---|
[55bde66] | 363 | return status; |
---|
| 364 | } |
---|
| 365 | |
---|
| 366 | /** |
---|
| 367 | * @brief This functions determines whether time base clock is enabled for EPWMSS |
---|
| 368 | * |
---|
| 369 | * @param pwmss_id The instance number of ePWMSS whose time base clock need to |
---|
| 370 | * be checked |
---|
| 371 | * |
---|
| 372 | * @return returns 4 for PWMSS_ID = 2 |
---|
| 373 | * returns 2 for PWMSS_ID = 1 |
---|
| 374 | * returns 1 for PWMSS_ID = 0 |
---|
| 375 | **/ |
---|
| 376 | static int pwmss_tb_clock_check(unsigned int pwmss_id) |
---|
| 377 | { |
---|
| 378 | unsigned int reg_value; |
---|
| 379 | |
---|
| 380 | /*control module check*/ |
---|
| 381 | reg_value = REG(AM335X_CONTROL_MODULE + AM335X_PWMSS_CTRL); |
---|
| 382 | return (reg_value & (1 << pwmss_id)); |
---|
| 383 | } |
---|
| 384 | |
---|
| 385 | /** |
---|
| 386 | * @brief This functions determines whether clock for EPWMSS is enabled or not. |
---|
| 387 | * |
---|
| 388 | * @param It is the Memory address of the PWMSS instance used. |
---|
| 389 | * |
---|
| 390 | * @return |
---|
| 391 | * |
---|
| 392 | **/ |
---|
| 393 | static unsigned int pwmss_clock_en_status(unsigned int pwmid) |
---|
| 394 | { |
---|
| 395 | unsigned int status; |
---|
| 396 | const uint32_t baseAddr = select_pwmss(pwmid); |
---|
| 397 | |
---|
| 398 | status = REG(baseAddr + AM335X_PWMSS_CLKSTATUS); |
---|
| 399 | status = status >> 8 & 0x1; |
---|
| 400 | return status; |
---|
| 401 | } |
---|
| 402 | |
---|
| 403 | bool beagle_pwmss_is_running(unsigned int pwmss_id) |
---|
| 404 | { |
---|
| 405 | const bool id_is_valid = pwmss_id < BBB_PWMSS_COUNT; |
---|
| 406 | bool status=true; |
---|
| 407 | |
---|
| 408 | if (id_is_valid) { |
---|
| 409 | status = pwmss_clock_en_status(pwmss_id); |
---|
| 410 | if(status){ |
---|
| 411 | status = pwmss_tb_clock_check(pwmss_id); |
---|
| 412 | } else { |
---|
| 413 | status = false; |
---|
| 414 | } |
---|
| 415 | } else { |
---|
| 416 | status = false; |
---|
[5e3096db] | 417 | } |
---|
[55bde66] | 418 | return status; |
---|
[6dc5c03f] | 419 | } |
---|
| 420 | |
---|
[5e3096db] | 421 | #endif |
---|
[6dc5c03f] | 422 | |
---|
[5e3096db] | 423 | /* For support of BeagleboardxM */ |
---|
| 424 | #if IS_DM3730 |
---|
[6dc5c03f] | 425 | |
---|
[5e3096db] | 426 | /* Currently this section is just to satisfy |
---|
| 427 | * GPIO API and to make the build successful. |
---|
| 428 | * Later on support can be added here. |
---|
| 429 | */ |
---|
[55bde66] | 430 | bool beagle_pwm_init(BBB_PWMSS pwmss_id) |
---|
[5e3096db] | 431 | { |
---|
[55bde66] | 432 | return false; |
---|
[5e3096db] | 433 | } |
---|
[55bde66] | 434 | bool beagle_pwm_disable(BBB_PWMSS pwmid) |
---|
[5e3096db] | 435 | { |
---|
[55bde66] | 436 | return false; |
---|
[5e3096db] | 437 | } |
---|
[55bde66] | 438 | bool beagle_pwm_enable(BBB_PWMSS pwmid) |
---|
[5e3096db] | 439 | { |
---|
[55bde66] | 440 | return false; |
---|
[5e3096db] | 441 | } |
---|
[55bde66] | 442 | int beagle_pwm_configure(BBB_PWMSS pwm_id, float pwm_freq, float duty_a, float duty_b) |
---|
[5e3096db] | 443 | { |
---|
[55bde66] | 444 | return -1; |
---|
[5e3096db] | 445 | } |
---|
[55bde66] | 446 | bool beagle_pwm_pinmux_setup(bbb_pwm_pin_t pin_no, BBB_PWMSS pwm_id) |
---|
[5e3096db] | 447 | { |
---|
[55bde66] | 448 | return false; |
---|
[5e3096db] | 449 | } |
---|
[55bde66] | 450 | bool beagle_pwmss_is_running(unsigned int pwmss_id) |
---|
[5e3096db] | 451 | { |
---|
| 452 | return false; |
---|
| 453 | } |
---|
| 454 | #endif |
---|