162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Intel Low Power Subsystem PWM controller driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2014, Intel Corporation 662306a36Sopenharmony_ci * Author: Mika Westerberg <mika.westerberg@linux.intel.com> 762306a36Sopenharmony_ci * Author: Chew Kean Ho <kean.ho.chew@intel.com> 862306a36Sopenharmony_ci * Author: Chang Rebecca Swee Fun <rebecca.swee.fun.chang@intel.com> 962306a36Sopenharmony_ci * Author: Chew Chiau Ee <chiau.ee.chew@intel.com> 1062306a36Sopenharmony_ci * Author: Alan Cox <alan@linux.intel.com> 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/bits.h> 1462306a36Sopenharmony_ci#include <linux/delay.h> 1562306a36Sopenharmony_ci#include <linux/io.h> 1662306a36Sopenharmony_ci#include <linux/iopoll.h> 1762306a36Sopenharmony_ci#include <linux/kernel.h> 1862306a36Sopenharmony_ci#include <linux/module.h> 1962306a36Sopenharmony_ci#include <linux/pm_runtime.h> 2062306a36Sopenharmony_ci#include <linux/time.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#define DEFAULT_SYMBOL_NAMESPACE PWM_LPSS 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include "pwm-lpss.h" 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define PWM 0x00000000 2762306a36Sopenharmony_ci#define PWM_ENABLE BIT(31) 2862306a36Sopenharmony_ci#define PWM_SW_UPDATE BIT(30) 2962306a36Sopenharmony_ci#define PWM_BASE_UNIT_SHIFT 8 3062306a36Sopenharmony_ci#define PWM_ON_TIME_DIV_MASK GENMASK(7, 0) 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* Size of each PWM register space if multiple */ 3362306a36Sopenharmony_ci#define PWM_SIZE 0x400 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/* BayTrail */ 3662306a36Sopenharmony_ciconst struct pwm_lpss_boardinfo pwm_lpss_byt_info = { 3762306a36Sopenharmony_ci .clk_rate = 25000000, 3862306a36Sopenharmony_ci .npwm = 1, 3962306a36Sopenharmony_ci .base_unit_bits = 16, 4062306a36Sopenharmony_ci}; 4162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pwm_lpss_byt_info); 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/* Braswell */ 4462306a36Sopenharmony_ciconst struct pwm_lpss_boardinfo pwm_lpss_bsw_info = { 4562306a36Sopenharmony_ci .clk_rate = 19200000, 4662306a36Sopenharmony_ci .npwm = 1, 4762306a36Sopenharmony_ci .base_unit_bits = 16, 4862306a36Sopenharmony_ci .other_devices_aml_touches_pwm_regs = true, 4962306a36Sopenharmony_ci}; 5062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pwm_lpss_bsw_info); 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci/* Broxton */ 5362306a36Sopenharmony_ciconst struct pwm_lpss_boardinfo pwm_lpss_bxt_info = { 5462306a36Sopenharmony_ci .clk_rate = 19200000, 5562306a36Sopenharmony_ci .npwm = 4, 5662306a36Sopenharmony_ci .base_unit_bits = 22, 5762306a36Sopenharmony_ci .bypass = true, 5862306a36Sopenharmony_ci}; 5962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pwm_lpss_bxt_info); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci/* Tangier */ 6262306a36Sopenharmony_ciconst struct pwm_lpss_boardinfo pwm_lpss_tng_info = { 6362306a36Sopenharmony_ci .clk_rate = 19200000, 6462306a36Sopenharmony_ci .npwm = 4, 6562306a36Sopenharmony_ci .base_unit_bits = 22, 6662306a36Sopenharmony_ci}; 6762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pwm_lpss_tng_info); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci return container_of(chip, struct pwm_lpss_chip, chip); 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic inline u32 pwm_lpss_read(const struct pwm_device *pwm) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci struct pwm_lpss_chip *lpwm = to_lpwm(pwm->chip); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci return readl(lpwm->regs + pwm->hwpwm * PWM_SIZE + PWM); 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistatic inline void pwm_lpss_write(const struct pwm_device *pwm, u32 value) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci struct pwm_lpss_chip *lpwm = to_lpwm(pwm->chip); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci writel(value, lpwm->regs + pwm->hwpwm * PWM_SIZE + PWM); 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic int pwm_lpss_wait_for_update(struct pwm_device *pwm) 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci struct pwm_lpss_chip *lpwm = to_lpwm(pwm->chip); 9162306a36Sopenharmony_ci const void __iomem *addr = lpwm->regs + pwm->hwpwm * PWM_SIZE + PWM; 9262306a36Sopenharmony_ci const unsigned int ms = 500 * USEC_PER_MSEC; 9362306a36Sopenharmony_ci u32 val; 9462306a36Sopenharmony_ci int err; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci /* 9762306a36Sopenharmony_ci * PWM Configuration register has SW_UPDATE bit that is set when a new 9862306a36Sopenharmony_ci * configuration is written to the register. The bit is automatically 9962306a36Sopenharmony_ci * cleared at the start of the next output cycle by the IP block. 10062306a36Sopenharmony_ci * 10162306a36Sopenharmony_ci * If one writes a new configuration to the register while it still has 10262306a36Sopenharmony_ci * the bit enabled, PWM may freeze. That is, while one can still write 10362306a36Sopenharmony_ci * to the register, it won't have an effect. Thus, we try to sleep long 10462306a36Sopenharmony_ci * enough that the bit gets cleared and make sure the bit is not 10562306a36Sopenharmony_ci * enabled while we update the configuration. 10662306a36Sopenharmony_ci */ 10762306a36Sopenharmony_ci err = readl_poll_timeout(addr, val, !(val & PWM_SW_UPDATE), 40, ms); 10862306a36Sopenharmony_ci if (err) 10962306a36Sopenharmony_ci dev_err(pwm->chip->dev, "PWM_SW_UPDATE was not cleared\n"); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci return err; 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_cistatic inline int pwm_lpss_is_updating(struct pwm_device *pwm) 11562306a36Sopenharmony_ci{ 11662306a36Sopenharmony_ci if (pwm_lpss_read(pwm) & PWM_SW_UPDATE) { 11762306a36Sopenharmony_ci dev_err(pwm->chip->dev, "PWM_SW_UPDATE is still set, skipping update\n"); 11862306a36Sopenharmony_ci return -EBUSY; 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci return 0; 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic void pwm_lpss_prepare(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm, 12562306a36Sopenharmony_ci int duty_ns, int period_ns) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci unsigned long long on_time_div; 12862306a36Sopenharmony_ci unsigned long c = lpwm->info->clk_rate, base_unit_range; 12962306a36Sopenharmony_ci unsigned long long base_unit, freq = NSEC_PER_SEC; 13062306a36Sopenharmony_ci u32 ctrl; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci do_div(freq, period_ns); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci /* 13562306a36Sopenharmony_ci * The equation is: 13662306a36Sopenharmony_ci * base_unit = round(base_unit_range * freq / c) 13762306a36Sopenharmony_ci */ 13862306a36Sopenharmony_ci base_unit_range = BIT(lpwm->info->base_unit_bits); 13962306a36Sopenharmony_ci freq *= base_unit_range; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci base_unit = DIV_ROUND_CLOSEST_ULL(freq, c); 14262306a36Sopenharmony_ci /* base_unit must not be 0 and we also want to avoid overflowing it */ 14362306a36Sopenharmony_ci base_unit = clamp_val(base_unit, 1, base_unit_range - 1); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci on_time_div = 255ULL * duty_ns; 14662306a36Sopenharmony_ci do_div(on_time_div, period_ns); 14762306a36Sopenharmony_ci on_time_div = 255ULL - on_time_div; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci ctrl = pwm_lpss_read(pwm); 15062306a36Sopenharmony_ci ctrl &= ~PWM_ON_TIME_DIV_MASK; 15162306a36Sopenharmony_ci ctrl &= ~((base_unit_range - 1) << PWM_BASE_UNIT_SHIFT); 15262306a36Sopenharmony_ci ctrl |= (u32) base_unit << PWM_BASE_UNIT_SHIFT; 15362306a36Sopenharmony_ci ctrl |= on_time_div; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci pwm_lpss_write(pwm, ctrl); 15662306a36Sopenharmony_ci pwm_lpss_write(pwm, ctrl | PWM_SW_UPDATE); 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic inline void pwm_lpss_cond_enable(struct pwm_device *pwm, bool cond) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci if (cond) 16262306a36Sopenharmony_ci pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_ENABLE); 16362306a36Sopenharmony_ci} 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cistatic int pwm_lpss_prepare_enable(struct pwm_lpss_chip *lpwm, 16662306a36Sopenharmony_ci struct pwm_device *pwm, 16762306a36Sopenharmony_ci const struct pwm_state *state) 16862306a36Sopenharmony_ci{ 16962306a36Sopenharmony_ci int ret; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci ret = pwm_lpss_is_updating(pwm); 17262306a36Sopenharmony_ci if (ret) 17362306a36Sopenharmony_ci return ret; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period); 17662306a36Sopenharmony_ci pwm_lpss_cond_enable(pwm, lpwm->info->bypass == false); 17762306a36Sopenharmony_ci ret = pwm_lpss_wait_for_update(pwm); 17862306a36Sopenharmony_ci if (ret) 17962306a36Sopenharmony_ci return ret; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci pwm_lpss_cond_enable(pwm, lpwm->info->bypass == true); 18262306a36Sopenharmony_ci return 0; 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_cistatic int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm, 18662306a36Sopenharmony_ci const struct pwm_state *state) 18762306a36Sopenharmony_ci{ 18862306a36Sopenharmony_ci struct pwm_lpss_chip *lpwm = to_lpwm(chip); 18962306a36Sopenharmony_ci int ret = 0; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci if (state->enabled) { 19262306a36Sopenharmony_ci if (!pwm_is_enabled(pwm)) { 19362306a36Sopenharmony_ci pm_runtime_get_sync(chip->dev); 19462306a36Sopenharmony_ci ret = pwm_lpss_prepare_enable(lpwm, pwm, state); 19562306a36Sopenharmony_ci if (ret) 19662306a36Sopenharmony_ci pm_runtime_put(chip->dev); 19762306a36Sopenharmony_ci } else { 19862306a36Sopenharmony_ci ret = pwm_lpss_prepare_enable(lpwm, pwm, state); 19962306a36Sopenharmony_ci } 20062306a36Sopenharmony_ci } else if (pwm_is_enabled(pwm)) { 20162306a36Sopenharmony_ci pwm_lpss_write(pwm, pwm_lpss_read(pwm) & ~PWM_ENABLE); 20262306a36Sopenharmony_ci pm_runtime_put(chip->dev); 20362306a36Sopenharmony_ci } 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci return ret; 20662306a36Sopenharmony_ci} 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistatic int pwm_lpss_get_state(struct pwm_chip *chip, struct pwm_device *pwm, 20962306a36Sopenharmony_ci struct pwm_state *state) 21062306a36Sopenharmony_ci{ 21162306a36Sopenharmony_ci struct pwm_lpss_chip *lpwm = to_lpwm(chip); 21262306a36Sopenharmony_ci unsigned long base_unit_range; 21362306a36Sopenharmony_ci unsigned long long base_unit, freq, on_time_div; 21462306a36Sopenharmony_ci u32 ctrl; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci pm_runtime_get_sync(chip->dev); 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci base_unit_range = BIT(lpwm->info->base_unit_bits); 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci ctrl = pwm_lpss_read(pwm); 22162306a36Sopenharmony_ci on_time_div = 255 - (ctrl & PWM_ON_TIME_DIV_MASK); 22262306a36Sopenharmony_ci base_unit = (ctrl >> PWM_BASE_UNIT_SHIFT) & (base_unit_range - 1); 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci freq = base_unit * lpwm->info->clk_rate; 22562306a36Sopenharmony_ci do_div(freq, base_unit_range); 22662306a36Sopenharmony_ci if (freq == 0) 22762306a36Sopenharmony_ci state->period = NSEC_PER_SEC; 22862306a36Sopenharmony_ci else 22962306a36Sopenharmony_ci state->period = NSEC_PER_SEC / (unsigned long)freq; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci on_time_div *= state->period; 23262306a36Sopenharmony_ci do_div(on_time_div, 255); 23362306a36Sopenharmony_ci state->duty_cycle = on_time_div; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci state->polarity = PWM_POLARITY_NORMAL; 23662306a36Sopenharmony_ci state->enabled = !!(ctrl & PWM_ENABLE); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci pm_runtime_put(chip->dev); 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci return 0; 24162306a36Sopenharmony_ci} 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_cistatic const struct pwm_ops pwm_lpss_ops = { 24462306a36Sopenharmony_ci .apply = pwm_lpss_apply, 24562306a36Sopenharmony_ci .get_state = pwm_lpss_get_state, 24662306a36Sopenharmony_ci .owner = THIS_MODULE, 24762306a36Sopenharmony_ci}; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_cistruct pwm_lpss_chip *devm_pwm_lpss_probe(struct device *dev, void __iomem *base, 25062306a36Sopenharmony_ci const struct pwm_lpss_boardinfo *info) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci struct pwm_lpss_chip *lpwm; 25362306a36Sopenharmony_ci unsigned long c; 25462306a36Sopenharmony_ci int i, ret; 25562306a36Sopenharmony_ci u32 ctrl; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci if (WARN_ON(info->npwm > LPSS_MAX_PWMS)) 25862306a36Sopenharmony_ci return ERR_PTR(-ENODEV); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci lpwm = devm_kzalloc(dev, sizeof(*lpwm), GFP_KERNEL); 26162306a36Sopenharmony_ci if (!lpwm) 26262306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci lpwm->regs = base; 26562306a36Sopenharmony_ci lpwm->info = info; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci c = lpwm->info->clk_rate; 26862306a36Sopenharmony_ci if (!c) 26962306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci lpwm->chip.dev = dev; 27262306a36Sopenharmony_ci lpwm->chip.ops = &pwm_lpss_ops; 27362306a36Sopenharmony_ci lpwm->chip.npwm = info->npwm; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci ret = devm_pwmchip_add(dev, &lpwm->chip); 27662306a36Sopenharmony_ci if (ret) { 27762306a36Sopenharmony_ci dev_err(dev, "failed to add PWM chip: %d\n", ret); 27862306a36Sopenharmony_ci return ERR_PTR(ret); 27962306a36Sopenharmony_ci } 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci for (i = 0; i < lpwm->info->npwm; i++) { 28262306a36Sopenharmony_ci ctrl = pwm_lpss_read(&lpwm->chip.pwms[i]); 28362306a36Sopenharmony_ci if (ctrl & PWM_ENABLE) 28462306a36Sopenharmony_ci pm_runtime_get(dev); 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci return lpwm; 28862306a36Sopenharmony_ci} 28962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(devm_pwm_lpss_probe); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ciMODULE_DESCRIPTION("PWM driver for Intel LPSS"); 29262306a36Sopenharmony_ciMODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); 29362306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 294