aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm/pwm-lpss.c
diff options
context:
space:
mode:
authorqipeng.zha <qipeng.zha@intel.com>2015-11-17 04:20:15 -0500
committerThierry Reding <thierry.reding@gmail.com>2015-12-16 10:45:38 -0500
commit883e4d070fe125028c0579d8666b820aadf458fb (patch)
treea7d98493046a02b1e9a96c2a5fb5ba29ce880f99 /drivers/pwm/pwm-lpss.c
parent6ef7d1c46f0cbe2b8e9c66d5d95ffa5a612df45d (diff)
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: Qipeng Zha <qipeng.zha@intel.com> Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Diffstat (limited to 'drivers/pwm/pwm-lpss.c')
-rw-r--r--drivers/pwm/pwm-lpss.c33
1 files changed, 19 insertions, 14 deletions
diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c
index 3f61c50964d5..ebf8450a2a09 100644
--- a/drivers/pwm/pwm-lpss.c
+++ b/drivers/pwm/pwm-lpss.c
@@ -17,6 +17,7 @@
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/pm_runtime.h> 19#include <linux/pm_runtime.h>
20#include <linux/time.h>
20 21
21#include "pwm-lpss.h" 22#include "pwm-lpss.h"
22 23
@@ -24,11 +25,8 @@
24#define PWM_ENABLE BIT(31) 25#define PWM_ENABLE BIT(31)
25#define PWM_SW_UPDATE BIT(30) 26#define PWM_SW_UPDATE BIT(30)
26#define PWM_BASE_UNIT_SHIFT 8 27#define PWM_BASE_UNIT_SHIFT 8
27#define PWM_BASE_UNIT_MASK 0x00ffff00
28#define PWM_ON_TIME_DIV_MASK 0x000000ff 28#define PWM_ON_TIME_DIV_MASK 0x000000ff
29#define PWM_DIVISION_CORRECTION 0x2 29#define PWM_DIVISION_CORRECTION 0x2
30#define PWM_LIMIT (0x8000 + PWM_DIVISION_CORRECTION)
31#define NSECS_PER_SEC 1000000000UL
32 30
33/* Size of each PWM register space if multiple */ 31/* Size of each PWM register space if multiple */
34#define PWM_SIZE 0x400 32#define PWM_SIZE 0x400
@@ -36,13 +34,14 @@
36struct pwm_lpss_chip { 34struct pwm_lpss_chip {
37 struct pwm_chip chip; 35 struct pwm_chip chip;
38 void __iomem *regs; 36 void __iomem *regs;
39 unsigned long clk_rate; 37 const struct pwm_lpss_boardinfo *info;
40}; 38};
41 39
42/* BayTrail */ 40/* BayTrail */
43const struct pwm_lpss_boardinfo pwm_lpss_byt_info = { 41const struct pwm_lpss_boardinfo pwm_lpss_byt_info = {
44 .clk_rate = 25000000, 42 .clk_rate = 25000000,
45 .npwm = 1, 43 .npwm = 1,
44 .base_unit_bits = 16,
46}; 45};
47EXPORT_SYMBOL_GPL(pwm_lpss_byt_info); 46EXPORT_SYMBOL_GPL(pwm_lpss_byt_info);
48 47
@@ -50,6 +49,7 @@ EXPORT_SYMBOL_GPL(pwm_lpss_byt_info);
50const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = { 49const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = {
51 .clk_rate = 19200000, 50 .clk_rate = 19200000,
52 .npwm = 1, 51 .npwm = 1,
52 .base_unit_bits = 16,
53}; 53};
54EXPORT_SYMBOL_GPL(pwm_lpss_bsw_info); 54EXPORT_SYMBOL_GPL(pwm_lpss_bsw_info);
55 55
@@ -57,6 +57,7 @@ EXPORT_SYMBOL_GPL(pwm_lpss_bsw_info);
57const struct pwm_lpss_boardinfo pwm_lpss_bxt_info = { 57const struct pwm_lpss_boardinfo pwm_lpss_bxt_info = {
58 .clk_rate = 19200000, 58 .clk_rate = 19200000,
59 .npwm = 4, 59 .npwm = 4,
60 .base_unit_bits = 22,
60}; 61};
61EXPORT_SYMBOL_GPL(pwm_lpss_bxt_info); 62EXPORT_SYMBOL_GPL(pwm_lpss_bxt_info);
62 63
@@ -84,23 +85,25 @@ static int pwm_lpss_config(struct pwm_chip *chip, struct pwm_device *pwm,
84{ 85{
85 struct pwm_lpss_chip *lpwm = to_lpwm(chip); 86 struct pwm_lpss_chip *lpwm = to_lpwm(chip);
86 u8 on_time_div; 87 u8 on_time_div;
87 unsigned long c; 88 unsigned long c, base_unit_range;
88 unsigned long long base_unit, freq = NSECS_PER_SEC; 89 unsigned long long base_unit, freq = NSEC_PER_SEC;
89 u32 ctrl; 90 u32 ctrl;
90 91
91 do_div(freq, period_ns); 92 do_div(freq, period_ns);
92 93
93 /* The equation is: base_unit = ((freq / c) * 65536) + correction */ 94 /*
94 base_unit = freq * 65536; 95 * The equation is:
96 * base_unit = ((freq / c) * base_unit_range) + correction
97 */
98 base_unit_range = BIT(lpwm->info->base_unit_bits);
99 base_unit = freq * base_unit_range;
95 100
96 c = lpwm->clk_rate; 101 c = lpwm->info->clk_rate;
97 if (!c) 102 if (!c)
98 return -EINVAL; 103 return -EINVAL;
99 104
100 do_div(base_unit, c); 105 do_div(base_unit, c);
101 base_unit += PWM_DIVISION_CORRECTION; 106 base_unit += PWM_DIVISION_CORRECTION;
102 if (base_unit > PWM_LIMIT)
103 return -EINVAL;
104 107
105 if (duty_ns <= 0) 108 if (duty_ns <= 0)
106 duty_ns = 1; 109 duty_ns = 1;
@@ -109,8 +112,10 @@ static int pwm_lpss_config(struct pwm_chip *chip, struct pwm_device *pwm,
109 pm_runtime_get_sync(chip->dev); 112 pm_runtime_get_sync(chip->dev);
110 113
111 ctrl = pwm_lpss_read(pwm); 114 ctrl = pwm_lpss_read(pwm);
112 ctrl &= ~(PWM_BASE_UNIT_MASK | PWM_ON_TIME_DIV_MASK); 115 ctrl &= ~PWM_ON_TIME_DIV_MASK;
113 ctrl |= (u16) base_unit << PWM_BASE_UNIT_SHIFT; 116 ctrl &= ~((base_unit_range - 1) << PWM_BASE_UNIT_SHIFT);
117 base_unit &= (base_unit_range - 1);
118 ctrl |= (u32) base_unit << PWM_BASE_UNIT_SHIFT;
114 ctrl |= on_time_div; 119 ctrl |= on_time_div;
115 /* request PWM to update on next cycle */ 120 /* request PWM to update on next cycle */
116 ctrl |= PWM_SW_UPDATE; 121 ctrl |= PWM_SW_UPDATE;
@@ -155,7 +160,7 @@ struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
155 if (IS_ERR(lpwm->regs)) 160 if (IS_ERR(lpwm->regs))
156 return ERR_CAST(lpwm->regs); 161 return ERR_CAST(lpwm->regs);
157 162
158 lpwm->clk_rate = info->clk_rate; 163 lpwm->info = info;
159 lpwm->chip.dev = dev; 164 lpwm->chip.dev = dev;
160 lpwm->chip.ops = &pwm_lpss_ops; 165 lpwm->chip.ops = &pwm_lpss_ops;
161 lpwm->chip.base = -1; 166 lpwm->chip.base = -1;