1212#include <linux/pwm.h>
1313#include <linux/slab.h>
1414
15+ #include <dt-bindings/mfd/cros_ec.h>
16+
1517/**
1618 * struct cros_ec_pwm_device - Driver data for EC PWM
1719 *
1820 * @dev: Device node
1921 * @ec: Pointer to EC device
2022 * @chip: PWM controller chip
23+ * @use_pwm_type: Use PWM types instead of generic channels
2124 */
2225struct cros_ec_pwm_device {
2326 struct device * dev ;
2427 struct cros_ec_device * ec ;
2528 struct pwm_chip chip ;
29+ bool use_pwm_type ;
2630};
2731
2832/**
@@ -58,14 +62,31 @@ static void cros_ec_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
5862 kfree (channel );
5963}
6064
61- static int cros_ec_pwm_set_duty ( struct cros_ec_device * ec , u8 index , u16 duty )
65+ static int cros_ec_dt_type_to_pwm_type ( u8 dt_index , u8 * pwm_type )
6266{
67+ switch (dt_index ) {
68+ case CROS_EC_PWM_DT_KB_LIGHT :
69+ * pwm_type = EC_PWM_TYPE_KB_LIGHT ;
70+ return 0 ;
71+ case CROS_EC_PWM_DT_DISPLAY_LIGHT :
72+ * pwm_type = EC_PWM_TYPE_DISPLAY_LIGHT ;
73+ return 0 ;
74+ default :
75+ return - EINVAL ;
76+ }
77+ }
78+
79+ static int cros_ec_pwm_set_duty (struct cros_ec_pwm_device * ec_pwm , u8 index ,
80+ u16 duty )
81+ {
82+ struct cros_ec_device * ec = ec_pwm -> ec ;
6383 struct {
6484 struct cros_ec_command msg ;
6585 struct ec_params_pwm_set_duty params ;
6686 } __packed buf ;
6787 struct ec_params_pwm_set_duty * params = & buf .params ;
6888 struct cros_ec_command * msg = & buf .msg ;
89+ int ret ;
6990
7091 memset (& buf , 0 , sizeof (buf ));
7192
@@ -75,14 +96,25 @@ static int cros_ec_pwm_set_duty(struct cros_ec_device *ec, u8 index, u16 duty)
7596 msg -> outsize = sizeof (* params );
7697
7798 params -> duty = duty ;
78- params -> pwm_type = EC_PWM_TYPE_GENERIC ;
79- params -> index = index ;
99+
100+ if (ec_pwm -> use_pwm_type ) {
101+ ret = cros_ec_dt_type_to_pwm_type (index , & params -> pwm_type );
102+ if (ret ) {
103+ dev_err (ec -> dev , "Invalid PWM type index: %d\n" , index );
104+ return ret ;
105+ }
106+ params -> index = 0 ;
107+ } else {
108+ params -> pwm_type = EC_PWM_TYPE_GENERIC ;
109+ params -> index = index ;
110+ }
80111
81112 return cros_ec_cmd_xfer_status (ec , msg );
82113}
83114
84- static int cros_ec_pwm_get_duty (struct cros_ec_device * ec , u8 index )
115+ static int cros_ec_pwm_get_duty (struct cros_ec_pwm_device * ec_pwm , u8 index )
85116{
117+ struct cros_ec_device * ec = ec_pwm -> ec ;
86118 struct {
87119 struct cros_ec_command msg ;
88120 union {
@@ -102,8 +134,17 @@ static int cros_ec_pwm_get_duty(struct cros_ec_device *ec, u8 index)
102134 msg -> insize = sizeof (* resp );
103135 msg -> outsize = sizeof (* params );
104136
105- params -> pwm_type = EC_PWM_TYPE_GENERIC ;
106- params -> index = index ;
137+ if (ec_pwm -> use_pwm_type ) {
138+ ret = cros_ec_dt_type_to_pwm_type (index , & params -> pwm_type );
139+ if (ret ) {
140+ dev_err (ec -> dev , "Invalid PWM type index: %d\n" , index );
141+ return ret ;
142+ }
143+ params -> index = 0 ;
144+ } else {
145+ params -> pwm_type = EC_PWM_TYPE_GENERIC ;
146+ params -> index = index ;
147+ }
107148
108149 ret = cros_ec_cmd_xfer_status (ec , msg );
109150 if (ret < 0 )
@@ -133,7 +174,7 @@ static int cros_ec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
133174 */
134175 duty_cycle = state -> enabled ? state -> duty_cycle : 0 ;
135176
136- ret = cros_ec_pwm_set_duty (ec_pwm -> ec , pwm -> hwpwm , duty_cycle );
177+ ret = cros_ec_pwm_set_duty (ec_pwm , pwm -> hwpwm , duty_cycle );
137178 if (ret < 0 )
138179 return ret ;
139180
@@ -149,7 +190,7 @@ static void cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
149190 struct cros_ec_pwm * channel = pwm_get_chip_data (pwm );
150191 int ret ;
151192
152- ret = cros_ec_pwm_get_duty (ec_pwm -> ec , pwm -> hwpwm );
193+ ret = cros_ec_pwm_get_duty (ec_pwm , pwm -> hwpwm );
153194 if (ret < 0 ) {
154195 dev_err (chip -> dev , "error getting initial duty: %d\n" , ret );
155196 return ;
@@ -204,13 +245,13 @@ static const struct pwm_ops cros_ec_pwm_ops = {
204245 * of PWMs it supports directly, so we have to read the pwm duty cycle for
205246 * subsequent channels until we get an error.
206247 */
207- static int cros_ec_num_pwms (struct cros_ec_device * ec )
248+ static int cros_ec_num_pwms (struct cros_ec_pwm_device * ec_pwm )
208249{
209250 int i , ret ;
210251
211252 /* The index field is only 8 bits */
212253 for (i = 0 ; i <= U8_MAX ; i ++ ) {
213- ret = cros_ec_pwm_get_duty (ec , i );
254+ ret = cros_ec_pwm_get_duty (ec_pwm , i );
214255 /*
215256 * We look for SUCCESS, INVALID_COMMAND, or INVALID_PARAM
216257 * responses; everything else is treated as an error.
@@ -236,6 +277,7 @@ static int cros_ec_pwm_probe(struct platform_device *pdev)
236277{
237278 struct cros_ec_device * ec = dev_get_drvdata (pdev -> dev .parent );
238279 struct device * dev = & pdev -> dev ;
280+ struct device_node * np = pdev -> dev .of_node ;
239281 struct cros_ec_pwm_device * ec_pwm ;
240282 struct pwm_chip * chip ;
241283 int ret ;
@@ -251,17 +293,26 @@ static int cros_ec_pwm_probe(struct platform_device *pdev)
251293 chip = & ec_pwm -> chip ;
252294 ec_pwm -> ec = ec ;
253295
296+ if (of_device_is_compatible (np , "google,cros-ec-pwm-type" ))
297+ ec_pwm -> use_pwm_type = true;
298+
254299 /* PWM chip */
255300 chip -> dev = dev ;
256301 chip -> ops = & cros_ec_pwm_ops ;
257302 chip -> of_xlate = cros_ec_pwm_xlate ;
258303 chip -> of_pwm_n_cells = 1 ;
259- ret = cros_ec_num_pwms (ec );
260- if (ret < 0 ) {
261- dev_err (dev , "Couldn't find PWMs: %d\n" , ret );
262- return ret ;
304+
305+ if (ec_pwm -> use_pwm_type ) {
306+ chip -> npwm = CROS_EC_PWM_DT_COUNT ;
307+ } else {
308+ ret = cros_ec_num_pwms (ec_pwm );
309+ if (ret < 0 ) {
310+ dev_err (dev , "Couldn't find PWMs: %d\n" , ret );
311+ return ret ;
312+ }
313+ chip -> npwm = ret ;
263314 }
264- chip -> npwm = ret ;
315+
265316 dev_dbg (dev , "Probed %u PWMs\n" , chip -> npwm );
266317
267318 ret = pwmchip_add (chip );
@@ -288,6 +339,7 @@ static int cros_ec_pwm_remove(struct platform_device *dev)
288339#ifdef CONFIG_OF
289340static const struct of_device_id cros_ec_pwm_of_match [] = {
290341 { .compatible = "google,cros-ec-pwm" },
342+ { .compatible = "google,cros-ec-pwm-type" },
291343 {},
292344};
293345MODULE_DEVICE_TABLE (of , cros_ec_pwm_of_match );
0 commit comments