Skip to content

Commit

Permalink
pwm: lpss: Update PWM setting for Broxton
Browse files Browse the repository at this point in the history
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: Qipeng Zha <[email protected]>
Acked-by: Mika Westerberg <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
  • Loading branch information
qipengzha authored and thierryreding committed Dec 16, 2015
1 parent 6ef7d1c commit 883e4d0
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 14 deletions.
33 changes: 19 additions & 14 deletions drivers/pwm/pwm-lpss.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,46 +17,47 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/time.h>

#include "pwm-lpss.h"

#define PWM 0x00000000
#define PWM_ENABLE BIT(31)
#define PWM_SW_UPDATE BIT(30)
#define PWM_BASE_UNIT_SHIFT 8
#define PWM_BASE_UNIT_MASK 0x00ffff00
#define PWM_ON_TIME_DIV_MASK 0x000000ff
#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 */
#define PWM_SIZE 0x400

struct pwm_lpss_chip {
struct pwm_chip chip;
void __iomem *regs;
unsigned long clk_rate;
const struct pwm_lpss_boardinfo *info;
};

/* BayTrail */
const struct pwm_lpss_boardinfo pwm_lpss_byt_info = {
.clk_rate = 25000000,
.npwm = 1,
.base_unit_bits = 16,
};
EXPORT_SYMBOL_GPL(pwm_lpss_byt_info);

/* Braswell */
const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = {
.clk_rate = 19200000,
.npwm = 1,
.base_unit_bits = 16,
};
EXPORT_SYMBOL_GPL(pwm_lpss_bsw_info);

/* Broxton */
const struct pwm_lpss_boardinfo pwm_lpss_bxt_info = {
.clk_rate = 19200000,
.npwm = 4,
.base_unit_bits = 22,
};
EXPORT_SYMBOL_GPL(pwm_lpss_bxt_info);

Expand Down Expand Up @@ -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);
u8 on_time_div;
unsigned long c;
unsigned long long base_unit, freq = NSECS_PER_SEC;
unsigned long c, base_unit_range;
unsigned long long base_unit, freq = NSEC_PER_SEC;
u32 ctrl;

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)
return -EINVAL;

do_div(base_unit, c);
base_unit += PWM_DIVISION_CORRECTION;
if (base_unit > PWM_LIMIT)
return -EINVAL;

if (duty_ns <= 0)
duty_ns = 1;
Expand All @@ -109,8 +112,10 @@ static int pwm_lpss_config(struct pwm_chip *chip, struct pwm_device *pwm,
pm_runtime_get_sync(chip->dev);

ctrl = pwm_lpss_read(pwm);
ctrl &= ~(PWM_BASE_UNIT_MASK | PWM_ON_TIME_DIV_MASK);
ctrl |= (u16) base_unit << PWM_BASE_UNIT_SHIFT;
ctrl &= ~PWM_ON_TIME_DIV_MASK;
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;
/* request PWM to update on next cycle */
ctrl |= PWM_SW_UPDATE;
Expand Down Expand Up @@ -155,7 +160,7 @@ struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
if (IS_ERR(lpwm->regs))
return ERR_CAST(lpwm->regs);

lpwm->clk_rate = info->clk_rate;
lpwm->info = info;
lpwm->chip.dev = dev;
lpwm->chip.ops = &pwm_lpss_ops;
lpwm->chip.base = -1;
Expand Down
1 change: 1 addition & 0 deletions drivers/pwm/pwm-lpss.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ struct pwm_lpss_chip;
struct pwm_lpss_boardinfo {
unsigned long clk_rate;
unsigned int npwm;
unsigned long base_unit_bits;
};

extern const struct pwm_lpss_boardinfo pwm_lpss_byt_info;
Expand Down

0 comments on commit 883e4d0

Please sign in to comment.