Commit 883e4d07 authored by qipeng.zha's avatar qipeng.zha Committed by Thierry Reding

pwm: lpss: Update PWM setting for Broxton

For Broxton PWM controller, base unit is defined as 8-bit integer
and 14-bit fraction, so need to update base unit setting to output
wave with right frequency.
Signed-off-by: default avatarQipeng Zha <qipeng.zha@intel.com>
Acked-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: default avatarThierry Reding <thierry.reding@gmail.com>
parent 6ef7d1c4
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/time.h>
#include "pwm-lpss.h" #include "pwm-lpss.h"
...@@ -24,11 +25,8 @@ ...@@ -24,11 +25,8 @@
#define PWM_ENABLE BIT(31) #define PWM_ENABLE BIT(31)
#define PWM_SW_UPDATE BIT(30) #define PWM_SW_UPDATE BIT(30)
#define PWM_BASE_UNIT_SHIFT 8 #define PWM_BASE_UNIT_SHIFT 8
#define PWM_BASE_UNIT_MASK 0x00ffff00
#define PWM_ON_TIME_DIV_MASK 0x000000ff #define PWM_ON_TIME_DIV_MASK 0x000000ff
#define PWM_DIVISION_CORRECTION 0x2 #define PWM_DIVISION_CORRECTION 0x2
#define PWM_LIMIT (0x8000 + PWM_DIVISION_CORRECTION)
#define NSECS_PER_SEC 1000000000UL
/* Size of each PWM register space if multiple */ /* Size of each PWM register space if multiple */
#define PWM_SIZE 0x400 #define PWM_SIZE 0x400
...@@ -36,13 +34,14 @@ ...@@ -36,13 +34,14 @@
struct pwm_lpss_chip { struct pwm_lpss_chip {
struct pwm_chip chip; struct pwm_chip chip;
void __iomem *regs; void __iomem *regs;
unsigned long clk_rate; const struct pwm_lpss_boardinfo *info;
}; };
/* BayTrail */ /* BayTrail */
const struct pwm_lpss_boardinfo pwm_lpss_byt_info = { const struct pwm_lpss_boardinfo pwm_lpss_byt_info = {
.clk_rate = 25000000, .clk_rate = 25000000,
.npwm = 1, .npwm = 1,
.base_unit_bits = 16,
}; };
EXPORT_SYMBOL_GPL(pwm_lpss_byt_info); EXPORT_SYMBOL_GPL(pwm_lpss_byt_info);
...@@ -50,6 +49,7 @@ EXPORT_SYMBOL_GPL(pwm_lpss_byt_info); ...@@ -50,6 +49,7 @@ EXPORT_SYMBOL_GPL(pwm_lpss_byt_info);
const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = { const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = {
.clk_rate = 19200000, .clk_rate = 19200000,
.npwm = 1, .npwm = 1,
.base_unit_bits = 16,
}; };
EXPORT_SYMBOL_GPL(pwm_lpss_bsw_info); EXPORT_SYMBOL_GPL(pwm_lpss_bsw_info);
...@@ -57,6 +57,7 @@ EXPORT_SYMBOL_GPL(pwm_lpss_bsw_info); ...@@ -57,6 +57,7 @@ EXPORT_SYMBOL_GPL(pwm_lpss_bsw_info);
const struct pwm_lpss_boardinfo pwm_lpss_bxt_info = { const struct pwm_lpss_boardinfo pwm_lpss_bxt_info = {
.clk_rate = 19200000, .clk_rate = 19200000,
.npwm = 4, .npwm = 4,
.base_unit_bits = 22,
}; };
EXPORT_SYMBOL_GPL(pwm_lpss_bxt_info); EXPORT_SYMBOL_GPL(pwm_lpss_bxt_info);
...@@ -84,23 +85,25 @@ static int pwm_lpss_config(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -84,23 +85,25 @@ static int pwm_lpss_config(struct pwm_chip *chip, struct pwm_device *pwm,
{ {
struct pwm_lpss_chip *lpwm = to_lpwm(chip); struct pwm_lpss_chip *lpwm = to_lpwm(chip);
u8 on_time_div; u8 on_time_div;
unsigned long c; unsigned long c, base_unit_range;
unsigned long long base_unit, freq = NSECS_PER_SEC; unsigned long long base_unit, freq = NSEC_PER_SEC;
u32 ctrl; u32 ctrl;
do_div(freq, period_ns); do_div(freq, period_ns);
/* The equation is: base_unit = ((freq / c) * 65536) + correction */ /*
base_unit = freq * 65536; * The equation is:
* base_unit = ((freq / c) * base_unit_range) + correction
*/
base_unit_range = BIT(lpwm->info->base_unit_bits);
base_unit = freq * base_unit_range;
c = lpwm->clk_rate; c = lpwm->info->clk_rate;
if (!c) if (!c)
return -EINVAL; return -EINVAL;
do_div(base_unit, c); do_div(base_unit, c);
base_unit += PWM_DIVISION_CORRECTION; base_unit += PWM_DIVISION_CORRECTION;
if (base_unit > PWM_LIMIT)
return -EINVAL;
if (duty_ns <= 0) if (duty_ns <= 0)
duty_ns = 1; duty_ns = 1;
...@@ -109,8 +112,10 @@ static int pwm_lpss_config(struct pwm_chip *chip, struct pwm_device *pwm, ...@@ -109,8 +112,10 @@ static int pwm_lpss_config(struct pwm_chip *chip, struct pwm_device *pwm,
pm_runtime_get_sync(chip->dev); pm_runtime_get_sync(chip->dev);
ctrl = pwm_lpss_read(pwm); ctrl = pwm_lpss_read(pwm);
ctrl &= ~(PWM_BASE_UNIT_MASK | PWM_ON_TIME_DIV_MASK); ctrl &= ~PWM_ON_TIME_DIV_MASK;
ctrl |= (u16) base_unit << PWM_BASE_UNIT_SHIFT; ctrl &= ~((base_unit_range - 1) << PWM_BASE_UNIT_SHIFT);
base_unit &= (base_unit_range - 1);
ctrl |= (u32) base_unit << PWM_BASE_UNIT_SHIFT;
ctrl |= on_time_div; ctrl |= on_time_div;
/* request PWM to update on next cycle */ /* request PWM to update on next cycle */
ctrl |= PWM_SW_UPDATE; ctrl |= PWM_SW_UPDATE;
...@@ -155,7 +160,7 @@ struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r, ...@@ -155,7 +160,7 @@ struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
if (IS_ERR(lpwm->regs)) if (IS_ERR(lpwm->regs))
return ERR_CAST(lpwm->regs); return ERR_CAST(lpwm->regs);
lpwm->clk_rate = info->clk_rate; lpwm->info = info;
lpwm->chip.dev = dev; lpwm->chip.dev = dev;
lpwm->chip.ops = &pwm_lpss_ops; lpwm->chip.ops = &pwm_lpss_ops;
lpwm->chip.base = -1; lpwm->chip.base = -1;
......
...@@ -21,6 +21,7 @@ struct pwm_lpss_chip; ...@@ -21,6 +21,7 @@ struct pwm_lpss_chip;
struct pwm_lpss_boardinfo { struct pwm_lpss_boardinfo {
unsigned long clk_rate; unsigned long clk_rate;
unsigned int npwm; unsigned int npwm;
unsigned long base_unit_bits;
}; };
extern const struct pwm_lpss_boardinfo pwm_lpss_byt_info; extern const struct pwm_lpss_boardinfo pwm_lpss_byt_info;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment