Lines Matching +full:timer +full:- +full:pwm

1 // SPDX-License-Identifier: GPL-2.0
3 * DesignWare PWM Controller driver core
5 * Copyright (C) 2018-2020 Intel Corporation
20 #include <linux/pwm.h>
22 #include "pwm-dwc.h"
24 static void __dwc_pwm_set_enable(struct dwc_pwm *dwc, int pwm, int enabled) in __dwc_pwm_set_enable() argument
28 reg = dwc_pwm_readl(dwc, DWC_TIM_CTRL(pwm)); in __dwc_pwm_set_enable()
35 dwc_pwm_writel(dwc, reg, DWC_TIM_CTRL(pwm)); in __dwc_pwm_set_enable()
39 struct pwm_device *pwm, in __dwc_pwm_configure_timer() argument
52 tmp = DIV_ROUND_CLOSEST_ULL(state->duty_cycle, dwc->clk_ns); in __dwc_pwm_configure_timer()
54 return -ERANGE; in __dwc_pwm_configure_timer()
55 low = tmp - 1; in __dwc_pwm_configure_timer()
57 tmp = DIV_ROUND_CLOSEST_ULL(state->period - state->duty_cycle, in __dwc_pwm_configure_timer()
58 dwc->clk_ns); in __dwc_pwm_configure_timer()
60 return -ERANGE; in __dwc_pwm_configure_timer()
61 high = tmp - 1; in __dwc_pwm_configure_timer()
64 * Specification says timer usage flow is to disable timer, then in __dwc_pwm_configure_timer()
66 * into timer after it is enabled - either after a disable or in __dwc_pwm_configure_timer()
70 __dwc_pwm_set_enable(dwc, pwm->hwpwm, false); in __dwc_pwm_configure_timer()
78 dwc_pwm_writel(dwc, low, DWC_TIM_LD_CNT(pwm->hwpwm)); in __dwc_pwm_configure_timer()
79 dwc_pwm_writel(dwc, high, DWC_TIM_LD_CNT2(pwm->hwpwm)); in __dwc_pwm_configure_timer()
82 * Set user-defined mode, timer reloads from Load Count registers in __dwc_pwm_configure_timer()
84 * Set PWM mode, it makes output to toggle and width of low and high in __dwc_pwm_configure_timer()
88 dwc_pwm_writel(dwc, ctrl, DWC_TIM_CTRL(pwm->hwpwm)); in __dwc_pwm_configure_timer()
91 * Enable timer. Output starts from low period. in __dwc_pwm_configure_timer()
93 __dwc_pwm_set_enable(dwc, pwm->hwpwm, state->enabled); in __dwc_pwm_configure_timer()
98 static int dwc_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, in dwc_pwm_apply() argument
103 if (state->polarity != PWM_POLARITY_INVERSED) in dwc_pwm_apply()
104 return -EINVAL; in dwc_pwm_apply()
106 if (state->enabled) { in dwc_pwm_apply()
107 if (!pwm->state.enabled) in dwc_pwm_apply()
109 return __dwc_pwm_configure_timer(dwc, pwm, state); in dwc_pwm_apply()
111 if (pwm->state.enabled) { in dwc_pwm_apply()
112 __dwc_pwm_set_enable(dwc, pwm->hwpwm, false); in dwc_pwm_apply()
120 static int dwc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, in dwc_pwm_get_state() argument
129 ctrl = dwc_pwm_readl(dwc, DWC_TIM_CTRL(pwm->hwpwm)); in dwc_pwm_get_state()
130 ld = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT(pwm->hwpwm)); in dwc_pwm_get_state()
131 ld2 = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT2(pwm->hwpwm)); in dwc_pwm_get_state()
133 state->enabled = !!(ctrl & DWC_TIM_CTRL_EN); in dwc_pwm_get_state()
136 * If we're not in PWM, technically the output is a 50-50 in dwc_pwm_get_state()
137 * based on the timer load-count only. in dwc_pwm_get_state()
140 duty = (ld + 1) * dwc->clk_ns; in dwc_pwm_get_state()
141 period = (ld2 + 1) * dwc->clk_ns; in dwc_pwm_get_state()
144 duty = (ld + 1) * dwc->clk_ns; in dwc_pwm_get_state()
148 state->polarity = PWM_POLARITY_INVERSED; in dwc_pwm_get_state()
149 state->period = period; in dwc_pwm_get_state()
150 state->duty_cycle = duty; in dwc_pwm_get_state()
172 dwc->clk_ns = 10; in dwc_pwm_alloc()
173 chip->ops = &dwc_pwm_ops; in dwc_pwm_alloc()
182 MODULE_DESCRIPTION("DesignWare PWM Controller");