1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Intel Low Power Subsystem PWM controller driver 4 * 5 * Copyright (C) 2014, Intel Corporation 6 * Author: Mika Westerberg <mika.westerberg@linux.intel.com> 7 * Author: Chew Kean Ho <kean.ho.chew@intel.com> 8 * Author: Chang Rebecca Swee Fun <rebecca.swee.fun.chang@intel.com> 9 * Author: Chew Chiau Ee <chiau.ee.chew@intel.com> 10 * Author: Alan Cox <alan@linux.intel.com> 11 */ 12 13#include <linux/bits.h> 14#include <linux/delay.h> 15#include <linux/io.h> 16#include <linux/iopoll.h> 17#include <linux/kernel.h> 18#include <linux/module.h> 19#include <linux/pm_runtime.h> 20#include <linux/time.h> 21 22#define DEFAULT_SYMBOL_NAMESPACE PWM_LPSS 23 24#include "pwm-lpss.h" 25 26#define PWM 0x00000000 27#define PWM_ENABLE BIT(31) 28#define PWM_SW_UPDATE BIT(30) 29#define PWM_BASE_UNIT_SHIFT 8 30#define PWM_ON_TIME_DIV_MASK GENMASK(7, 0) 31 32/* Size of each PWM register space if multiple */ 33#define PWM_SIZE 0x400 34 35/* BayTrail */ 36const struct pwm_lpss_boardinfo pwm_lpss_byt_info = { 37 .clk_rate = 25000000, 38 .npwm = 1, 39 .base_unit_bits = 16, 40}; 41EXPORT_SYMBOL_GPL(pwm_lpss_byt_info); 42 43/* Braswell */ 44const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = { 45 .clk_rate = 19200000, 46 .npwm = 1, 47 .base_unit_bits = 16, 48 .other_devices_aml_touches_pwm_regs = true, 49}; 50EXPORT_SYMBOL_GPL(pwm_lpss_bsw_info); 51 52/* Broxton */ 53const struct pwm_lpss_boardinfo pwm_lpss_bxt_info = { 54 .clk_rate = 19200000, 55 .npwm = 4, 56 .base_unit_bits = 22, 57 .bypass = true, 58}; 59EXPORT_SYMBOL_GPL(pwm_lpss_bxt_info); 60 61/* Tangier */ 62const struct pwm_lpss_boardinfo pwm_lpss_tng_info = { 63 .clk_rate = 19200000, 64 .npwm = 4, 65 .base_unit_bits = 22, 66}; 67EXPORT_SYMBOL_GPL(pwm_lpss_tng_info); 68 69static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip) 70{ 71 return pwmchip_get_drvdata(chip); 72} 73 74static inline u32 pwm_lpss_read(const struct pwm_device *pwm) 75{ 76 struct pwm_lpss_chip *lpwm = to_lpwm(pwm->chip); 77 78 return readl(lpwm->regs + pwm->hwpwm * PWM_SIZE + PWM); 79} 80 81static inline void pwm_lpss_write(const struct pwm_device *pwm, u32 value) 82{ 83 struct pwm_lpss_chip *lpwm = to_lpwm(pwm->chip); 84 85 writel(value, lpwm->regs + pwm->hwpwm * PWM_SIZE + PWM); 86} 87 88static int pwm_lpss_wait_for_update(struct pwm_device *pwm) 89{ 90 struct pwm_lpss_chip *lpwm = to_lpwm(pwm->chip); 91 const void __iomem *addr = lpwm->regs + pwm->hwpwm * PWM_SIZE + PWM; 92 const unsigned int ms = 500 * USEC_PER_MSEC; 93 u32 val; 94 int err; 95 96 /* 97 * PWM Configuration register has SW_UPDATE bit that is set when a new 98 * configuration is written to the register. The bit is automatically 99 * cleared at the start of the next output cycle by the IP block. 100 * 101 * If one writes a new configuration to the register while it still has 102 * the bit enabled, PWM may freeze. That is, while one can still write 103 * to the register, it won't have an effect. Thus, we try to sleep long 104 * enough that the bit gets cleared and make sure the bit is not 105 * enabled while we update the configuration. 106 */ 107 err = readl_poll_timeout(addr, val, !(val & PWM_SW_UPDATE), 40, ms); 108 if (err) 109 dev_err(pwmchip_parent(pwm->chip), "PWM_SW_UPDATE was not cleared\n"); 110 111 return err; 112} 113 114static inline int pwm_lpss_is_updating(struct pwm_device *pwm) 115{ 116 if (pwm_lpss_read(pwm) & PWM_SW_UPDATE) { 117 dev_err(pwmchip_parent(pwm->chip), "PWM_SW_UPDATE is still set, skipping update\n"); 118 return -EBUSY; 119 } 120 121 return 0; 122} 123 124static void pwm_lpss_prepare(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm, 125 int duty_ns, int period_ns) 126{ 127 unsigned long long on_time_div; 128 unsigned long c = lpwm->info->clk_rate, base_unit_range; 129 unsigned long long base_unit, freq = NSEC_PER_SEC; 130 u32 ctrl; 131 132 do_div(freq, period_ns); 133 134 /* 135 * The equation is: 136 * base_unit = round(base_unit_range * freq / c) 137 */ 138 base_unit_range = BIT(lpwm->info->base_unit_bits); 139 freq *= base_unit_range; 140 141 base_unit = DIV_ROUND_CLOSEST_ULL(freq, c); 142 /* base_unit must not be 0 and we also want to avoid overflowing it */ 143 base_unit = clamp_val(base_unit, 1, base_unit_range - 1); 144 145 on_time_div = 255ULL * duty_ns; 146 do_div(on_time_div, period_ns); 147 on_time_div = 255ULL - on_time_div; 148 149 ctrl = pwm_lpss_read(pwm); 150 ctrl &= ~PWM_ON_TIME_DIV_MASK; 151 ctrl &= ~((base_unit_range - 1) << PWM_BASE_UNIT_SHIFT); 152 ctrl |= (u32) base_unit << PWM_BASE_UNIT_SHIFT; 153 ctrl |= on_time_div; 154 155 pwm_lpss_write(pwm, ctrl); 156 pwm_lpss_write(pwm, ctrl | PWM_SW_UPDATE); 157} 158 159static inline void pwm_lpss_cond_enable(struct pwm_device *pwm, bool cond) 160{ 161 if (cond) 162 pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_ENABLE); 163} 164 165static int pwm_lpss_prepare_enable(struct pwm_lpss_chip *lpwm, 166 struct pwm_device *pwm, 167 const struct pwm_state *state) 168{ 169 int ret; 170 171 ret = pwm_lpss_is_updating(pwm); 172 if (ret) 173 return ret; 174 175 pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period); 176 pwm_lpss_cond_enable(pwm, lpwm->info->bypass == false); 177 ret = pwm_lpss_wait_for_update(pwm); 178 if (ret) 179 return ret; 180 181 pwm_lpss_cond_enable(pwm, lpwm->info->bypass == true); 182 return 0; 183} 184 185static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm, 186 const struct pwm_state *state) 187{ 188 struct pwm_lpss_chip *lpwm = to_lpwm(chip); 189 int ret = 0; 190 191 if (state->enabled) { 192 if (!pwm_is_enabled(pwm)) { 193 pm_runtime_get_sync(pwmchip_parent(chip)); 194 ret = pwm_lpss_prepare_enable(lpwm, pwm, state); 195 if (ret) 196 pm_runtime_put(pwmchip_parent(chip)); 197 } else { 198 ret = pwm_lpss_prepare_enable(lpwm, pwm, state); 199 } 200 } else if (pwm_is_enabled(pwm)) { 201 pwm_lpss_write(pwm, pwm_lpss_read(pwm) & ~PWM_ENABLE); 202 pm_runtime_put(pwmchip_parent(chip)); 203 } 204 205 return ret; 206} 207 208static int pwm_lpss_get_state(struct pwm_chip *chip, struct pwm_device *pwm, 209 struct pwm_state *state) 210{ 211 struct pwm_lpss_chip *lpwm = to_lpwm(chip); 212 unsigned long base_unit_range; 213 unsigned long long base_unit, freq, on_time_div; 214 u32 ctrl; 215 216 pm_runtime_get_sync(pwmchip_parent(chip)); 217 218 base_unit_range = BIT(lpwm->info->base_unit_bits); 219 220 ctrl = pwm_lpss_read(pwm); 221 on_time_div = 255 - (ctrl & PWM_ON_TIME_DIV_MASK); 222 base_unit = (ctrl >> PWM_BASE_UNIT_SHIFT) & (base_unit_range - 1); 223 224 freq = base_unit * lpwm->info->clk_rate; 225 do_div(freq, base_unit_range); 226 if (freq == 0) 227 state->period = NSEC_PER_SEC; 228 else 229 state->period = NSEC_PER_SEC / (unsigned long)freq; 230 231 on_time_div *= state->period; 232 do_div(on_time_div, 255); 233 state->duty_cycle = on_time_div; 234 235 state->polarity = PWM_POLARITY_NORMAL; 236 state->enabled = !!(ctrl & PWM_ENABLE); 237 238 pm_runtime_put(pwmchip_parent(chip)); 239 240 return 0; 241} 242 243static const struct pwm_ops pwm_lpss_ops = { 244 .apply = pwm_lpss_apply, 245 .get_state = pwm_lpss_get_state, 246}; 247 248struct pwm_chip *devm_pwm_lpss_probe(struct device *dev, void __iomem *base, 249 const struct pwm_lpss_boardinfo *info) 250{ 251 struct pwm_lpss_chip *lpwm; 252 struct pwm_chip *chip; 253 unsigned long c; 254 int i, ret; 255 u32 ctrl; 256 257 if (WARN_ON(info->npwm > LPSS_MAX_PWMS)) 258 return ERR_PTR(-ENODEV); 259 260 chip = devm_pwmchip_alloc(dev, info->npwm, sizeof(*lpwm)); 261 if (IS_ERR(chip)) 262 return chip; 263 lpwm = to_lpwm(chip); 264 265 lpwm->regs = base; 266 lpwm->info = info; 267 268 c = lpwm->info->clk_rate; 269 if (!c) 270 return ERR_PTR(-EINVAL); 271 272 chip->ops = &pwm_lpss_ops; 273 274 ret = devm_pwmchip_add(dev, chip); 275 if (ret) { 276 dev_err(dev, "failed to add PWM chip: %d\n", ret); 277 return ERR_PTR(ret); 278 } 279 280 for (i = 0; i < lpwm->info->npwm; i++) { 281 ctrl = pwm_lpss_read(&chip->pwms[i]); 282 if (ctrl & PWM_ENABLE) 283 pm_runtime_get(dev); 284 } 285 286 return chip; 287} 288EXPORT_SYMBOL_GPL(devm_pwm_lpss_probe); 289 290MODULE_DESCRIPTION("PWM driver for Intel LPSS"); 291MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); 292MODULE_LICENSE("GPL v2"); 293