1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2015 Intel Corporation. All rights reserved.
5 * Author: Shobhit Kumar <shobhit.kumar@intel.com>
8 #include <linux/platform_device.h>
9 #include <linux/regmap.h>
10 #include <linux/mfd/intel_soc_pmic.h>
11 #include <linux/pwm.h>
13 #define PWM0_CLK_DIV 0x4B
14 #define PWM_OUTPUT_ENABLE BIT(7)
15 #define PWM_DIV_CLK_0 0x00 /* DIVIDECLK = BASECLK */
16 #define PWM_DIV_CLK_100 0x63 /* DIVIDECLK = BASECLK/100 */
17 #define PWM_DIV_CLK_128 0x7F /* DIVIDECLK = BASECLK/128 */
19 #define PWM0_DUTY_CYCLE 0x4E
20 #define BACKLIGHT_EN 0x51
22 #define PWM_MAX_LEVEL 0xFF
24 #define PWM_BASE_CLK_MHZ 6 /* 6 MHz */
25 #define PWM_MAX_PERIOD_NS 5461334 /* 183 Hz */
28 * struct crystalcove_pwm - Crystal Cove PWM controller
29 * @chip: the abstract pwm_chip structure.
30 * @regmap: the regmap from the parent device.
32 struct crystalcove_pwm
{
34 struct regmap
*regmap
;
37 static inline struct crystalcove_pwm
*to_crc_pwm(struct pwm_chip
*pc
)
39 return container_of(pc
, struct crystalcove_pwm
, chip
);
42 static int crc_pwm_calc_clk_div(int period_ns
)
46 clk_div
= PWM_BASE_CLK_MHZ
* period_ns
/ (256 * NSEC_PER_USEC
);
47 /* clk_div 1 - 128, maps to register values 0-127 */
54 static int crc_pwm_apply(struct pwm_chip
*chip
, struct pwm_device
*pwm
,
55 const struct pwm_state
*state
)
57 struct crystalcove_pwm
*crc_pwm
= to_crc_pwm(chip
);
58 struct device
*dev
= crc_pwm
->chip
.dev
;
61 if (state
->period
> PWM_MAX_PERIOD_NS
) {
62 dev_err(dev
, "un-supported period_ns\n");
66 if (state
->polarity
!= PWM_POLARITY_NORMAL
)
69 if (pwm_is_enabled(pwm
) && !state
->enabled
) {
70 err
= regmap_write(crc_pwm
->regmap
, BACKLIGHT_EN
, 0);
72 dev_err(dev
, "Error writing BACKLIGHT_EN %d\n", err
);
77 if (pwm_get_duty_cycle(pwm
) != state
->duty_cycle
||
78 pwm_get_period(pwm
) != state
->period
) {
79 u64 level
= state
->duty_cycle
* PWM_MAX_LEVEL
;
81 do_div(level
, state
->period
);
83 err
= regmap_write(crc_pwm
->regmap
, PWM0_DUTY_CYCLE
, level
);
85 dev_err(dev
, "Error writing PWM0_DUTY_CYCLE %d\n", err
);
90 if (pwm_is_enabled(pwm
) && state
->enabled
&&
91 pwm_get_period(pwm
) != state
->period
) {
92 /* changing the clk divisor, clear PWM_OUTPUT_ENABLE first */
93 err
= regmap_write(crc_pwm
->regmap
, PWM0_CLK_DIV
, 0);
95 dev_err(dev
, "Error writing PWM0_CLK_DIV %d\n", err
);
100 if (pwm_get_period(pwm
) != state
->period
||
101 pwm_is_enabled(pwm
) != state
->enabled
) {
102 int clk_div
= crc_pwm_calc_clk_div(state
->period
);
103 int pwm_output_enable
= state
->enabled
? PWM_OUTPUT_ENABLE
: 0;
105 err
= regmap_write(crc_pwm
->regmap
, PWM0_CLK_DIV
,
106 clk_div
| pwm_output_enable
);
108 dev_err(dev
, "Error writing PWM0_CLK_DIV %d\n", err
);
113 if (!pwm_is_enabled(pwm
) && state
->enabled
) {
114 err
= regmap_write(crc_pwm
->regmap
, BACKLIGHT_EN
, 1);
116 dev_err(dev
, "Error writing BACKLIGHT_EN %d\n", err
);
124 static void crc_pwm_get_state(struct pwm_chip
*chip
, struct pwm_device
*pwm
,
125 struct pwm_state
*state
)
127 struct crystalcove_pwm
*crc_pwm
= to_crc_pwm(chip
);
128 struct device
*dev
= crc_pwm
->chip
.dev
;
129 unsigned int clk_div
, clk_div_reg
, duty_cycle_reg
;
132 error
= regmap_read(crc_pwm
->regmap
, PWM0_CLK_DIV
, &clk_div_reg
);
134 dev_err(dev
, "Error reading PWM0_CLK_DIV %d\n", error
);
138 error
= regmap_read(crc_pwm
->regmap
, PWM0_DUTY_CYCLE
, &duty_cycle_reg
);
140 dev_err(dev
, "Error reading PWM0_DUTY_CYCLE %d\n", error
);
144 clk_div
= (clk_div_reg
& ~PWM_OUTPUT_ENABLE
) + 1;
147 DIV_ROUND_UP(clk_div
* NSEC_PER_USEC
* 256, PWM_BASE_CLK_MHZ
);
149 DIV_ROUND_UP_ULL(duty_cycle_reg
* state
->period
, PWM_MAX_LEVEL
);
150 state
->polarity
= PWM_POLARITY_NORMAL
;
151 state
->enabled
= !!(clk_div_reg
& PWM_OUTPUT_ENABLE
);
154 static const struct pwm_ops crc_pwm_ops
= {
155 .apply
= crc_pwm_apply
,
156 .get_state
= crc_pwm_get_state
,
159 static int crystalcove_pwm_probe(struct platform_device
*pdev
)
161 struct crystalcove_pwm
*pwm
;
162 struct device
*dev
= pdev
->dev
.parent
;
163 struct intel_soc_pmic
*pmic
= dev_get_drvdata(dev
);
165 pwm
= devm_kzalloc(&pdev
->dev
, sizeof(*pwm
), GFP_KERNEL
);
169 pwm
->chip
.dev
= &pdev
->dev
;
170 pwm
->chip
.ops
= &crc_pwm_ops
;
174 /* get the PMIC regmap */
175 pwm
->regmap
= pmic
->regmap
;
177 platform_set_drvdata(pdev
, pwm
);
179 return pwmchip_add(&pwm
->chip
);
182 static int crystalcove_pwm_remove(struct platform_device
*pdev
)
184 struct crystalcove_pwm
*pwm
= platform_get_drvdata(pdev
);
186 return pwmchip_remove(&pwm
->chip
);
189 static struct platform_driver crystalcove_pwm_driver
= {
190 .probe
= crystalcove_pwm_probe
,
191 .remove
= crystalcove_pwm_remove
,
193 .name
= "crystal_cove_pwm",
197 builtin_platform_driver(crystalcove_pwm_driver
);