1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_pwm.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.ipwm"
18 #endif
19 
20 /*******************************************************************************
21  * Prototypes
22  ******************************************************************************/
23 /*!
24  * @brief Get the instance from the base address
25  *
26  * @param base PWM peripheral base address
27  *
28  * @return The PWM module instance
29  */
30 static uint32_t PWM_GetInstance(PWM_Type *base);
31 
32 /*******************************************************************************
33  * Variables
34  ******************************************************************************/
35 /*! @brief Pointers to PWM bases for each instance. */
36 static PWM_Type *const s_pwmBases[] = PWM_BASE_PTRS;
37 
38 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
39 /* Array of PWM clock name. */
40 static const clock_ip_name_t s_pwmClock[] = PWM_CLOCKS;
41 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
42 
43 /*******************************************************************************
44  * Code
45  ******************************************************************************/
PWM_GetInstance(PWM_Type * base)46 static uint32_t PWM_GetInstance(PWM_Type *base)
47 {
48     uint32_t instance;
49     uint32_t pwmArrayCount = (sizeof(s_pwmBases) / sizeof(s_pwmBases[0]));
50 
51     /* Find the instance index from base address mappings. */
52     for (instance = 0; instance < pwmArrayCount; instance++)
53     {
54         if (s_pwmBases[instance] == base)
55         {
56             break;
57         }
58     }
59 
60     assert(instance < pwmArrayCount);
61 
62     return instance;
63 }
64 
65 /*!
66  * brief Ungates the PWM clock and configures the peripheral for basic operation.
67  *
68  * note This API should be called at the beginning of the application using the PWM driver.
69  *
70  * param base      PWM peripheral base address
71  * param config    Pointer to user's PWM config structure.
72  *
73  * return kStatus_Success means success; else failed.
74  */
PWM_Init(PWM_Type * base,const pwm_config_t * config)75 status_t PWM_Init(PWM_Type *base, const pwm_config_t *config)
76 {
77     assert(config);
78 
79 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
80     /* Ungate PWM clock */
81     CLOCK_EnableClock(s_pwmClock[PWM_GetInstance(base)]);
82 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
83 
84     /* Setup the PWM operation */
85     base->PWMCR = (PWM_PWMCR_REPEAT(config->sampleRepeat) | PWM_PWMCR_PRESCALER(config->prescale) |
86                    PWM_PWMCR_CLKSRC(config->clockSource) | PWM_PWMCR_POUTC(config->outputConfig) |
87                    PWM_PWMCR_HCTR(config->halfWordSwap) | PWM_PWMCR_BCTR(config->byteSwap) |
88                    PWM_PWMCR_STOPEN(config->enableStopMode) | PWM_PWMCR_DBGEN(config->enableDebugMode) |
89                    PWM_PWMCR_WAITEN(config->enableWaitMode) | PWM_PWMCR_DOZEN(config->enableDozeMode) |
90                    PWM_PWMCR_FWM(config->fifoWater));
91 
92     return kStatus_Success;
93 }
94 
95 /*!
96  * brief Gate the PWM submodule clock
97  *
98  * param base      PWM peripheral base address
99  */
PWM_Deinit(PWM_Type * base)100 void PWM_Deinit(PWM_Type *base)
101 {
102     /* Set clock source to none to disable counter */
103     base->PWMCR &= ~(PWM_PWMCR_CLKSRC_MASK);
104 
105 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
106     /* Gate the PWM clock */
107     CLOCK_DisableClock(s_pwmClock[PWM_GetInstance(base)]);
108 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
109 }
110 
111 /*!
112  * brief  Fill in the PWM config struct with the default settings
113  *
114  * The default values are:
115  * code
116  *   config->enableStopMode = false;
117  *   config->enableDozeMode = false;
118  *   config->enableWaitMode = false;
119  *   config->enableDozeMode = false;
120  *   config->clockSource = kPWM_LowFrequencyClock;
121  *   config->prescale = 0U;
122  *   config->outputConfig = kPWM_SetAtRolloverAndClearAtcomparison;
123  *   config->fifoWater = kPWM_FIFOWaterMark_2;
124  *   config->sampleRepeat = kPWM_EachSampleOnce;
125  *   config->byteSwap = kPWM_ByteNoSwap;
126  *   config->halfWordSwap = kPWM_HalfWordNoSwap;
127  * endcode
128  * param config Pointer to user's PWM config structure.
129  */
PWM_GetDefaultConfig(pwm_config_t * config)130 void PWM_GetDefaultConfig(pwm_config_t *config)
131 {
132     assert(config);
133 
134     /* Initializes the configure structure to zero. */
135     (void)memset(config, 0, sizeof(*config));
136 
137     /* Stop mode disabled */
138     config->enableStopMode = false;
139     /* Doze mode disabled */
140     config->enableDozeMode = false;
141     /* Wait mode disabled */
142     config->enableWaitMode = false;
143     /* Debug mode disabled */
144     config->enableDebugMode = false;
145     /* Choose low frequency clock to control counter operation */
146     config->clockSource = kPWM_LowFrequencyClock;
147     /* PWM clock devide by (config->prescale + 1) */
148     config->prescale = 0U;
149     /* Output pin is set at rollover and cleared at comparison */
150     config->outputConfig = kPWM_SetAtRolloverAndClearAtcomparison;
151     /* FIFO empty flag is set when there are more than or equal to 2 empty slots in FIFO */
152     config->fifoWater = kPWM_FIFOWaterMark_2;
153     /* Use each sample once */
154     config->sampleRepeat = kPWM_EachSampleOnce;
155     /* byte ordering remains the same */
156     config->byteSwap = kPWM_ByteNoSwap;
157     /* Half word swapping does not take place */
158     config->halfWordSwap = kPWM_HalfWordNoSwap;
159 }
160